]> git.sesse.net Git - kdenlive/blobdiff - src/colortools.cpp
Integrate with the required MLT hooks for getting Movit to work.
[kdenlive] / src / colortools.cpp
index cc49e9ef451bbd6dbcb27e63d2a1f73a0a8b784b..7f513a701e2dd5ae211bdcae2ca098753878c87a 100644 (file)
 
 #include <math.h>
 #include "colortools.h"
+#include <QColor>
+
+//#define DEBUG_CT
+#ifdef DEBUG_CT
+#include <QDebug>
+#endif
 
 ColorTools::ColorTools()
 {
@@ -17,14 +23,16 @@ ColorTools::ColorTools()
 
 
 
-QImage ColorTools::yuvColorWheel(const QSize &size, unsigned char Y, float scaling, bool modifiedVersion, bool circleOnly)
+QImage ColorTools::yuvColorWheel(const QSize &size, const unsigned char &Y, const float &scaling, const bool &modifiedVersion, const bool &circleOnly)
 {
     QImage wheel(size, QImage::Format_ARGB32);
     if (size.width() == 0 || size.height() == 0) {
         qCritical("ERROR: Size of the color wheel must not be 0!");
         return wheel;
     }
-    wheel.fill(qRgba(0,0,0,0));
+    if (circleOnly) {
+        wheel.fill(qRgba(0,0,0,0));
+    }
 
     double dr, dg, db, du, dv, dmax;
     double ru, rv, rr;
@@ -86,6 +94,280 @@ QImage ColorTools::yuvColorWheel(const QSize &size, unsigned char Y, float scali
         }
     }
 
-    emit signalWheelCalculationFinished();
+    emit signalYuvWheelCalculationFinished();
     return wheel;
 }
+
+QImage ColorTools::yuvVerticalPlane(const QSize &size, const float &angle, const float &scaling)
+{
+    QImage plane(size, QImage::Format_ARGB32);
+    if (size.width() == 0 || size.height() == 0) {
+        qCritical("ERROR: Size of the color plane must not be 0!");
+        return plane;
+    }
+
+    double dr, dg, db, du, dv, Y;
+    const int w = size.width();
+    const int h = size.height();
+    const double uscaling = scaling*cos(M_PI*angle/180);
+    const double vscaling = scaling*sin(M_PI*angle/180);
+
+    for (int uv = 0; uv < w; uv++) {
+        du = uscaling*((double)2*uv/w - 1);//(double)?
+        dv = vscaling*((double)2*uv/w - 1);
+
+        for (int y = 0; y < h; y++) {
+            Y = (double)255*y/h;
+
+            // See yuv2rgb, yuvColorWheel
+            dr = Y + 290.8*dv;
+            dg = Y - 100.6*du - 148*dv;
+            db = Y + 517.2*du;
+            if (dr < 0) dr = 0;
+            if (dg < 0) dg = 0;
+            if (db < 0) db = 0;
+            if (dr > 255) dr = 255;
+            if (dg > 255) dg = 255;
+            if (db > 255) db = 255;
+
+            plane.setPixel(uv, (h-y-1), qRgba(dr, dg, db, 255));
+
+        }
+    }
+
+
+    return plane;
+
+}
+
+QImage ColorTools::rgbCurvePlane(const QSize &size, const ColorTools::ColorsRGB &color, float scaling, const QRgb &background)
+{
+    Q_ASSERT(scaling > 0 && scaling <= 1);
+
+    QImage plane(size, QImage::Format_ARGB32);
+    if (size.width() == 0 || size.height() == 0) {
+        qCritical("ERROR: Size of the color plane must not be 0!");
+        return plane;
+    }
+
+    const int w = size.width();
+    const int h = size.height();
+
+    double dcol, dval;
+    double dx, dy;
+
+    for (int x = 0; x < w; x++) {
+        dval = (double)255*x/(w-1);
+
+        for (int y = 0; y < h; y++) {
+            dy = (double)y/(h-1);
+            dx = (double)x/(w-1);
+
+            if (1-scaling < 0.0001) {
+                dcol = (double)255*dy;
+            } else {
+                dcol = (double)255 * (dy - (dy-dx)*(1-scaling));
+            }
+
+            if (color == ColorTools::COL_R) {
+                plane.setPixel(x, (h-y-1), qRgb(dcol, dval, dval));
+            } else if (color == ColorTools::COL_G) {
+                plane.setPixel(x, (h-y-1), qRgb(dval, dcol, dval));
+            } else if (color == ColorTools::COL_B){
+                plane.setPixel(x, (h-y-1), qRgb(dval, dval, dcol));
+            } else if (color == ColorTools::COL_A) {
+                plane.setPixel(x, (h-y-1), qRgb(dcol / 255. * qRed(background), dcol / 255. * qGreen(background), dcol / 255. * qBlue(background)));
+            } else {
+                plane.setPixel(x, (h-y-1), qRgb(dcol, dcol, dcol));
+            }
+
+        }
+    }
+    return plane;
+}
+
+QImage ColorTools::yPbPrColorWheel(const QSize &size, const unsigned char &Y, const float &scaling, const bool &circleOnly)
+{
+
+    QImage wheel(size, QImage::Format_ARGB32);
+    if (size.width() == 0 || size.height() == 0) {
+        qCritical("ERROR: Size of the color wheel must not be 0!");
+        return wheel;
+    }
+    if (circleOnly) {
+        wheel.fill(qRgba(0,0,0,0));
+    }
+
+    double dr, dg, db, dpB, dpR;
+    double rB, rR, rr;
+    const int w = size.width();
+    const int h = size.height();
+    const float w2 = (float)w/2;
+    const float h2 = (float)h/2;
+
+    for (int b = 0; b < w; b++) {
+        // Transform pB from {0,...,w} to [-0.5,0.5]
+        dpB = (double) b/(w-1) - .5;
+        dpB = scaling*dpB;
+
+        for (int r = 0; r < h; r++) {
+            dpR = (double) r/(h-1) - .5;
+            dpR = scaling*dpR;
+
+            if (circleOnly) {
+                // see yuvColorWheel
+                rB = b - w2;
+                rR = r - h2;
+                rr = rB*rB/(w2*w2) + rR*rR/(h2*h2);
+                if (rr > 1) {
+                    continue;
+                }
+            }
+
+            // Calculate the RGB values from YPbPr
+            dr = Y + 357.5*dpR;
+            dg = Y - 87.75*dpB - 182.1*dpR;
+            db = Y + 451.86*dpB;
+
+            // Avoid overflows (which would generate intersting patterns).
+            // Note that not all possible (y,u,v) values with u,v \in [-1,1]
+            // have a correct RGB representation, therefore some RGB values
+            // may exceed {0,...,255}.
+            if (dr < 0) dr = 0;
+            if (dg < 0) dg = 0;
+            if (db < 0) db = 0;
+            if (dr > 255) dr = 255;
+            if (dg > 255) dg = 255;
+            if (db > 255) db = 255;
+
+            wheel.setPixel(b, (h-r-1), qRgba(dr, dg, db, 255));
+        }
+    }
+
+    return wheel;
+}
+
+QImage ColorTools::hsvHueShiftPlane(const QSize &size, const uint &S, const uint &V, const int &MIN, const int &MAX)
+{
+    Q_ASSERT(size.width() > 0);
+    Q_ASSERT(size.height() > 0);
+    Q_ASSERT(MAX > MIN);
+
+    QImage plane(size, QImage::Format_ARGB32);
+
+#ifdef DEBUG_CT
+    qDebug() << "Requested: Saturation " << S << ", Value " << V;
+    QColor colTest(-1, 256, 257);
+    qDebug() << "-1 mapped to " << colTest.red() << ", 256 to " << colTest.green() << ", 257 to " << colTest.blue();
+#endif
+
+    QColor col(0, 0, 0);
+
+    const int hueValues = MAX-MIN;
+
+    float hue, huediff;
+    int newhue;
+    for (int x = 0; x < size.width(); x++) {
+        hue = x/(size.width() - 1.0) * 359;
+        for (int y = 0; y < size.height(); y++) {
+            huediff = (1.0f - y/(size.height() - 1.0)) * hueValues + MIN;
+//            qDebug() << "hue: " << hue << ", huediff: " << huediff;
+
+            newhue = hue + huediff + 360; // Avoid negative numbers. Rest (>360) will be mapped correctly.
+
+            col.setHsv(newhue, S, V);
+            plane.setPixel(x, y, col.rgba());
+
+        }
+    }
+
+    return plane;
+
+}
+
+QImage ColorTools::hsvCurvePlane(const QSize &size, const QColor &baseColor,
+                                 const ComponentsHSV &xVariant, const ComponentsHSV &yVariant, const bool &shear, const float offsetY)
+{
+    Q_ASSERT(size.width() > 0);
+    Q_ASSERT(size.height() > 0);
+
+    /*int xMax, yMax;
+
+    switch(xVariant) {
+    case COM_H:
+        xMax = 360;
+        break;
+    case COM_S:
+    case COM_V:
+        xMax = 256;
+        break;
+    }
+
+    switch (yVariant) {
+    case COM_H:
+        yMax = 360;
+        break;
+    case COM_S:
+    case COM_V:
+        yMax = 256;
+        break;
+    }*/
+
+
+    QImage plane(size, QImage::Format_ARGB32);
+
+    QColor col(0, 0, 0);
+
+    float hue, sat, val;
+    hue = baseColor.hueF();
+    sat = baseColor.saturationF();
+    val = baseColor.valueF();
+
+    for (int x = 0; x < size.width(); x++) {
+        switch (xVariant) {
+        case COM_H:
+            hue = x / (size.width()-1.0);
+            break;
+        case COM_S:
+            sat = x / (size.width()-1.0);
+            break;
+        case COM_V:
+            val = x / (size.width()-1.0);
+            break;
+        }
+        for (int y = 0; y < size.height(); y++) {
+            switch (yVariant) {
+            case COM_H:
+                hue = 1.0 - y / (size.height()-1.0);
+                break;
+            case COM_S:
+                sat = 1.0 - y / (size.height()-1.0);
+                break;
+            case COM_V:
+                val = 1.0 - y / (size.height()-1.0);
+                break;
+            }
+
+            col.setHsvF(hue, sat, val);
+
+            if (!shear) {
+                plane.setPixel(x, y, col.rgba());
+            } else {
+                plane.setPixel(x, int(2*size.height() + y - x*size.width()/size.height() - offsetY * size.height()) % size.height(), col.rgba());
+            }
+        }
+    }
+
+    return plane;
+
+}
+
+
+
+
+
+
+
+
+
+#include "colortools.moc"