X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fcolorcorrection%2Fwaveformgenerator.cpp;h=4c60518de93752b52ba0252f2ca970461e8cb776;hb=9f42f1faa3f2c0e23def9890c9cf644a3e75f9c5;hp=0575a1c500a66f1bf7bc1b3982535676c6f79058;hpb=b540689a832244cfc6f4c5e62f2b01644f5bc437;p=kdenlive diff --git a/src/colorcorrection/waveformgenerator.cpp b/src/colorcorrection/waveformgenerator.cpp index 0575a1c5..4c60518d 100644 --- a/src/colorcorrection/waveformgenerator.cpp +++ b/src/colorcorrection/waveformgenerator.cpp @@ -8,10 +8,12 @@ * (at your option) any later version. * ***************************************************************************/ -#include -#include -#include +#include + +#include #include +#include +#include #include "waveformgenerator.h" @@ -25,28 +27,25 @@ WaveformGenerator::~WaveformGenerator() { } -QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, const QImage &image, const bool &drawAxis, const uint &accelFactor) +QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, const QImage &image, WaveformGenerator::PaintMode paintMode, + bool drawAxis, WaveformGenerator::Rec rec, uint accelFactor) { Q_ASSERT(accelFactor >= 1); - QTime time; - time.start(); + //QTime time; + //time.start(); QImage wave(waveformSize, QImage::Format_ARGB32); - if (waveformSize.width() <= 0 || waveformSize.height() <= 0) { - qCritical("Waveform size should not be 0."); + if (waveformSize.width() <= 0 || waveformSize.height() <= 0 || image.width() <= 0 || image.height() <= 0) { + return QImage(); } else { - qDebug() << "Waveform calculation started."; - // Fill with transparent color wave.fill(qRgba(0,0,0,0)); QRgb *col; - QRgb waveCol; - QPoint wavePoint; double dY, dx, dy; @@ -56,33 +55,84 @@ QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, const QIm const uint ih = image.height(); const uint byteCount = iw*ih; + uint waveValues[waveformSize.width()][waveformSize.height()]; + for (int i = 0; i < waveformSize.width(); ++i) { + for (int j = 0; j < waveformSize.height(); j++) { + waveValues[i][j] = 0; + } + } + + // Number of input pixels that will fall on one scope pixel. + // Must be a float because the acceleration factor can be high, leading to <1 expected px per px. + const float pixelDepth = (float)((byteCount>>2) / accelFactor)/(ww*wh); + const float gain = 255/(8*pixelDepth); + //qDebug() << "Pixel depth: expected " << pixelDepth << "; Gain: using " << gain << " (acceleration: " << accelFactor << "x)"; + + // Subtract 1 from sizes because we start counting from 0. // Not doing it would result in attempts to paint outside of the image. const float hPrediv = (float)(wh-1)/255; const float wPrediv = (float)(ww-1)/(iw-1); const uchar *bits = image.bits(); - const uint stepsize = 4*accelFactor; + const int bpp = image.depth() / 8; - for (uint i = 0, x = 0; i < byteCount; i += stepsize) { + for (uint i = 0, x = 0; i < byteCount; i += bpp) { + + Q_ASSERT(bits < image.bits() + byteCount); col = (QRgb *)bits; - // CIE 601 Luminance + if (rec == WaveformGenerator::Rec_601) { + // CIE 601 Luminance + dY = .299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col); + } else { + // CIE 709 Luminance + dY = .2125*qRed(*col) + .7154*qGreen(*col) + .0721*qBlue(*col); + } // dY is on [0,255] now. - dY = .299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col); dy = dY*hPrediv; dx = x*wPrediv; - wavePoint = QPoint((int)dx, (int)(wh-1 - dy)); - - waveCol = QRgb(wave.pixel(wavePoint)); - wave.setPixel(wavePoint, qRgba(CHOP255(9 + qRed(waveCol)), CHOP255(36 + qGreen(waveCol)), - CHOP255(18 + qBlue(waveCol)), 255)); + waveValues[(int)dx][(int)dy]++; + + bits += bpp; + x += bpp; + if (x > iw) { + x -= iw; + if (accelFactor > 1) { + bits += bpp*iw*(accelFactor-1); + i += bpp*iw*(accelFactor-1); + } + } + } - bits += stepsize; - x += stepsize; - x %= iw; // Modulo image width, to represent the current x position in the image + switch (paintMode) { + case PaintMode_Green: + for (int i = 0; i < waveformSize.width(); ++i) { + for (int j = 0; j < waveformSize.height(); j++) { + // Logarithmic scale. Needs fine tuning by hand, but looks great. + wave.setPixel(i, waveformSize.height()-j-1, qRgba(CHOP255(52*log(0.1*gain*waveValues[i][j])), + CHOP255(52*log(gain*waveValues[i][j])), + CHOP255(52*log(.25*gain*waveValues[i][j])), + CHOP255(64*log(gain*waveValues[i][j])))); + } + } + break; + case PaintMode_Yellow: + for (int i = 0; i < waveformSize.width(); ++i) { + for (int j = 0; j < waveformSize.height(); j++) { + wave.setPixel(i, waveformSize.height()-j-1, qRgba(255,242,0, CHOP255(gain*waveValues[i][j]))); + } + } + break; + default: + for (int i = 0; i < waveformSize.width(); ++i) { + for (int j = 0; j < waveformSize.height(); j++) { + wave.setPixel(i, waveformSize.height()-j-1, qRgba(255,255,255, CHOP255(2*gain*waveValues[i][j]))); + } + } + break; } if (drawAxis) { @@ -90,22 +140,23 @@ QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, const QIm QRgb opx; davinci.setPen(qRgba(150,255,200,32)); davinci.setCompositionMode(QPainter::CompositionMode_Overlay); - for (uint i = 0; i <= 10; i++) { + for (uint i = 0; i <= 10; ++i) { dy = (float)i/10 * (wh-1); for (uint x = 0; x < ww; x++) { opx = wave.pixel(x, dy); wave.setPixel(x,dy, qRgba(CHOP255(150+qRed(opx)), 255, CHOP255(200+qBlue(opx)), CHOP255(32+qAlpha(opx)))); } - //davinci.drawLine(0, dy, ww-1, dy); } } } - uint diff = time.elapsed(); -// qDebug() << "Waveform calculation ended. Time taken: " << diff << " ms. Sending signal now."; - emit signalCalculationFinished(wave, diff); + //uint diff = time.elapsed(); + //emit signalCalculationFinished(wave, diff); return wave; } +#undef CHOP255 + +#include "waveformgenerator.moc"