From da15d2d5c0eaba62cba2388ee242c9bfbaafd9af Mon Sep 17 00:00:00 2001 From: David Lamhauge Date: Fri, 1 Mar 2024 15:36:03 +0100 Subject: [PATCH] Added dof values to layer, pencildef and added to cameraprop-dialog --- app/ui/camerapropertiesdialog.ui | 127 ++++++++++++++++++++++++- core_lib/core_lib.pro | 1 + core_lib/src/structure/camera.h | 14 +++ core_lib/src/structure/layer.cpp | 8 ++ core_lib/src/structure/layer.h | 14 +++ core_lib/src/structure/layerbitmap.cpp | 5 + core_lib/src/structure/layerbitmap.h | 2 + core_lib/src/util/blurutils.h | 124 ++++++++++++++++++++++++ core_lib/src/util/pencildef.h | 2 + 9 files changed, 294 insertions(+), 3 deletions(-) create mode 100644 core_lib/src/util/blurutils.h diff --git a/app/ui/camerapropertiesdialog.ui b/app/ui/camerapropertiesdialog.ui index 44793f17eb..1489ad02fa 100644 --- a/app/ui/camerapropertiesdialog.ui +++ b/app/ui/camerapropertiesdialog.ui @@ -6,8 +6,8 @@ 0 0 - 246 - 105 + 253 + 269 @@ -15,7 +15,7 @@ - + @@ -59,6 +59,127 @@ + + + + Camera Settings + + + + + + + + Aperture + + + + + + + 4 + + + + 2 + + + + + 2,8 + + + + + 4 + + + + + 5,6 + + + + + 8 + + + + + 11 + + + + + 16 + + + + + 22 + + + + + + + + + + + + Distance + + + + + + + m. + + + + + + 1 + + + 50000 + + + 10 + + + + + + + + + + + Reset settings + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index d1725c8973..d7c928a868 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -86,6 +86,7 @@ HEADERS += \ src/tool/strokemanager.h \ src/tool/stroketool.h \ src/util/blitrect.h \ + src/util/blurutils.h \ src/util/cameraeasingtype.h \ src/util/camerafieldoption.h \ src/util/colordictionary.h \ diff --git a/core_lib/src/structure/camera.h b/core_lib/src/structure/camera.h index 92ce4243c3..801fb5e68e 100644 --- a/core_lib/src/structure/camera.h +++ b/core_lib/src/structure/camera.h @@ -58,7 +58,21 @@ class Camera : public KeyFrame void setPathControlPointMoved(bool pathMoved); bool pathControlPointMoved() const { return mPathControlPointMoved; } + void setDistance(qreal dist) { mDistance = dist; } + qreal getDistance() { return mDistance; } + void setAperture(qreal aperture) { mAperture = aperture; } + qreal getAperture() { return mAperture; } + +signals: + + void settingsChanged(qreal mDistance, qreal mAperture); + private: + + // values used for depth of field + qreal mDistance = 10.0f; // standard distance setting on camera + qreal mAperture = 8.0f; // standard aperture setting on camera + QTransform mView; QPointF mTranslate; qreal mRotate = 0.; diff --git a/core_lib/src/structure/layer.cpp b/core_lib/src/structure/layer.cpp index f272e59120..81d4997ff9 100644 --- a/core_lib/src/structure/layer.cpp +++ b/core_lib/src/structure/layer.cpp @@ -22,6 +22,7 @@ GNU General Public License for more details. #include #include #include "keyframe.h" +#include "blurutils.h" // Used to sort the selected frames list bool sortAsc(int left, int right) @@ -676,6 +677,13 @@ bool Layer::isPaintable() const return (type() == BITMAP || type() == VECTOR); } +void Layer::updateFarNearDistance(qreal distance, qreal aperture) +{ + qreal hyperFocalDist = getHyperfocalDistance(50, aperture); + mNearDistance = getDistanceNear(hyperFocalDist, distance, 50); + mFarDistance = getDistanceFar(hyperFocalDist, distance, 50); +} + bool Layer::keyExistsWhichCovers(int frameNumber) { return getKeyFrameWhichCovers(frameNumber) != nullptr; diff --git a/core_lib/src/structure/layer.h b/core_lib/src/structure/layer.h index 0e82e2b1db..a018bb84b5 100644 --- a/core_lib/src/structure/layer.h +++ b/core_lib/src/structure/layer.h @@ -164,6 +164,15 @@ class Layer : public QObject /** Clear the list of dirty keyframes */ void clearDirtyFrames() { mDirtyFrames.clear(); } + // for depth of field + void setDistance(qreal dist) { mDistance = dist; } + qreal getDistance() { return mDistance; } + void setNearDistance(qreal dist) { mNearDistance = dist; } + qreal getNearDistance() { return mNearDistance; } + void setFarDistance(qreal dist) { mFarDistance = dist; } + qreal getFarDistance() { return mFarDistance; } + void updateFarNearDistance(qreal near, qreal far); + protected: virtual KeyFrame* createKeyFrame(int position) = 0; bool loadKey(KeyFrame*); @@ -176,6 +185,11 @@ class Layer : public QObject bool mVisible = true; QString mName; + // vars for depth of field + qreal mDistance = 10.0f; // standard distance from camera to layer + qreal mNearDistance = 10.0f; // nearest distance, where the object will be i "acceptable" focus + qreal mFarDistance = 10.0f; // farthest distance, where the object will be i "acceptable" focus + std::map> mKeyFrames; // We need to keep track of selected frames ordered by last selected diff --git a/core_lib/src/structure/layerbitmap.cpp b/core_lib/src/structure/layerbitmap.cpp index d5eb0cc620..71155bf7da 100644 --- a/core_lib/src/structure/layerbitmap.cpp +++ b/core_lib/src/structure/layerbitmap.cpp @@ -58,6 +58,11 @@ QRect LayerBitmap::getFrameBounds(int frame) return image->bounds(); } +void LayerBitmap::updateDistanceNearFar() +{ + +} + void LayerBitmap::loadImageAtFrame(QString path, QPoint topLeft, int frameNumber, qreal opacity) { BitmapImage* pKeyFrame = new BitmapImage(topLeft, path); diff --git a/core_lib/src/structure/layerbitmap.h b/core_lib/src/structure/layerbitmap.h index 8ae10fe1ad..a28f29d0e5 100644 --- a/core_lib/src/structure/layerbitmap.h +++ b/core_lib/src/structure/layerbitmap.h @@ -40,6 +40,8 @@ class LayerBitmap : public Layer void repositionFrame(QPoint point, int frame); QRect getFrameBounds(int frame); + void updateDistanceNearFar(); + protected: Status saveKeyFrameFile(KeyFrame*, QString strPath) override; KeyFrame* createKeyFrame(int position) override; diff --git a/core_lib/src/util/blurutils.h b/core_lib/src/util/blurutils.h new file mode 100644 index 0000000000..8daa323e2f --- /dev/null +++ b/core_lib/src/util/blurutils.h @@ -0,0 +1,124 @@ +#ifndef BLURUTILS_H +#define BLURUTILS_H + +#include +#include +#include +#include + +using namespace std; + +/** Get the nearest distance, where the object will be i "acceptable" focus + * + * \param h is the Hyperfocal distance + * \param s is the focus distance on the camera + * \param fLength in the cameras focal length, can vary from 25-300 mm (standard is 50 mm) + * @return + */ +inline qreal getDistanceNear(qreal h, qreal s, qreal fLength) +{ + return (s*(h-fLength))/(h+s-2*fLength); +} + +/** Get the farthest distance, where the object will be i "acceptable" focus + * + * \param h is the Hyperfocal distance + * \param s is the focus distance on the camera + * \param fLength in the cameras focal length, can vary from 25-300 mm (standard is 50 mm) + * @return + */ +inline qreal getDistanceFar(qreal h, qreal s, qreal fLength) +{ + return (s*(h-fLength))/(h-s); +} + +/** Get hyperfocal distance using coc, focal length and f-number. + * + * Hyperfoacal distance is a distance beyond which, + * all objects can be brought into an "acceptable" focus. + * coc is Circle of confusion (=0.03) + * \param fLength in the cameras focal length, can vary from 30-300 mm (standard is 50 mm) + * \param aperture is aperture and can be 2.8 4 5.6 8 11 and 22 + * \return The cameras hyperfocal distance in mm + */ +inline qreal getHyperfocalDistance(qreal fLength, qreal aperture) +{ + return ((fLength*fLength)/(0.03*aperture)) + fLength; +} + +/** + * @brief boxesForGauss + * @param sigma + * @param n + * @return + */ +inline vector boxesForGauss(float sigma, int n) // standard deviation, number of boxes +{ + auto wIdeal = sqrt((12 * sigma*sigma / n) + 1); // Ideal averaging filter width + int wl = floor(wIdeal); + if (wl % 2 == 0) + wl--; + int wu = wl + 2; + + auto mIdeal = (12 * sigma*sigma - n * wl*wl - 4 * n*wl - 3 * n) / (-4 * wl - 4); + int m = round(mIdeal); + // var sigmaActual = Math.sqrt( (m*wl*wl + (n-m)*wu*wu - n)/12 ); + + vector sizes(n); + for (auto i = 0; i < n; i++) + sizes[i] = i < m ? wl : wu; + return sizes; +} + +inline void boxBlurH_4(vector& scl, vector& tcl, int w, int h, int r) { + float iarr = 1.f / (r + r + 1); + for (auto i = 0; i < h; i++) { + auto ti = i * w, li = ti, ri = ti + r; + auto fv = scl[ti], lv = scl[ti + w - 1]; + auto val = (r + 1)*fv; + for (auto j = 0; j < r; j++) val += scl[ti + j]; + for (auto j = 0; j <= r; j++) { val += scl[ri++] - fv; tcl[ti++] = round(val*iarr); } + for (auto j = r + 1; j < w - r; j++) { val += scl[ri++] - scl[li++]; tcl[ti++] = round(val*iarr); } + for (auto j = w - r; j < w; j++) { val += lv - scl[li++]; tcl[ti++] = round(val*iarr); } + } +} + +inline void boxBlurT_4(vector& scl, vector& tcl, int w, int h, int r) { + float iarr = 1.f / (r + r + 1); + for (auto i = 0; i < w; i++) { + auto ti = i, li = ti, ri = ti + r * w; + auto fv = scl[ti], lv = scl[ti + w * (h - 1)]; + auto val = (r + 1)*fv; + for (auto j = 0; j < r; j++) val += scl[ti + j * w]; + for (auto j = 0; j <= r; j++) { val += scl[ri] - fv; tcl[ti] = round(val*iarr); ri += w; ti += w; } + for (auto j = r + 1; j < h - r; j++) { val += scl[ri] - scl[li]; tcl[ti] = round(val*iarr); li += w; ri += w; ti += w; } + for (auto j = h - r; j < h; j++) { val += lv - scl[li]; tcl[ti] = round(val*iarr); li += w; ti += w; } + } +} + + +inline void boxBlur_4(vector& scl, vector& tcl, int w, int h, int r) { + for (unsigned i = 0; i < scl.size(); i++) tcl[i] = scl[i]; + boxBlurH_4(tcl, scl, w, h, r); + boxBlurT_4(scl, tcl, w, h, r); +} + +/** + * @brief gaussBlur_4 The '4' because it is Algoritm 4 of fast gaussBlur: + * http://blog.ivank.net/fastest-gaussian-blur.html + * @param scl Source channel + * @param tcl Target channel + * @param w Width + * @param h Height + * @param r Radius + */ +inline void gaussBlur_4(vector& scl, vector& tcl, int w, int h, qreal r) +{ + auto bxs = boxesForGauss(r, 3); + qDebug() << "bxs: " << bxs ; + boxBlur_4(scl, tcl, w, h, (bxs[0] - 1) / 2); + boxBlur_4(tcl, scl, w, h, (bxs[1] - 1) / 2); + boxBlur_4(scl, tcl, w, h, (bxs[2] - 1) / 2); +} + +#endif // BLURUTILS_H diff --git a/core_lib/src/util/pencildef.h b/core_lib/src/util/pencildef.h index e1b9b11ace..4b765244c4 100644 --- a/core_lib/src/util/pencildef.h +++ b/core_lib/src/util/pencildef.h @@ -241,6 +241,8 @@ const static float RotationHandleOffset = 50; #define SETTING_FPS "Fps" #define SETTING_FIELD_W "FieldW" #define SETTING_FIELD_H "FieldH" +#define SETTING_APERTURE "Aperture" +#define SETTING_CAM_DISTANCE "CamDistance" #define SETTING_FRAME_SIZE "FrameSize" #define SETTING_TIMELINE_SIZE "TimelineSize" #define SETTING_LABEL_FONT_SIZE "LabelFontSize"