Ejemplo n.º 1
0
void AbstractScopeWidget::paintEvent(QPaintEvent *)
{
    QPainter davinci(this);
    davinci.drawImage(m_scopeRect.topLeft(), m_imgBackground);
    davinci.drawImage(m_scopeRect.topLeft(), m_imgScope);
    davinci.drawImage(m_scopeRect.topLeft(), m_imgHUD);
}
Ejemplo n.º 2
0
int main()
{
    int width = 640, height = 320;
    QImage img(width, height, QImage::Format_ARGB32);

    QPainter davinci(&img);
    davinci.setPen(QColor(40, 80, 255, 20));

    VideoOut_sV video;
    int ret = prepare(&video, "/tmp/ffmpegEncodedFrames.mov", "ffv1", width, height, 1000000, 1, 25);
    if (ret != 0) {
        qDebug() << "Preparing the video failed: " << video.errorMessage << "(" << ret << ")";
        return ret;
    }


    eatSample(&video);
    for (int i = 0; i < 100; i++) {

        img.fill(QColor(100, 100, 100).rgb());
        davinci.drawLine(0, 2*i, width-1, 2*i);
        davinci.fillRect(0, 0, 100, 2*i, QColor(255, 0, 0));

        eatARGB(&video, img.bits());
    }
    finish(&video);
}
Ejemplo n.º 3
0
QImage AudioSpectrum::renderHUD(uint)
{
    QTime start = QTime::currentTime();

    if (m_innerScopeRect.height() > 0 && m_innerScopeRect.width() > 0) { // May be below 0 if widget is too small

        // Minimum distance between two lines
        const uint minDistY = 30;
        const uint minDistX = 40;
        const uint textDistX = 10;
        const uint textDistY = 25;
        const uint topDist = m_innerScopeRect.top() - m_scopeRect.top();
        const uint leftDist = m_innerScopeRect.left() - m_scopeRect.left();
        const uint dbDiff = ceil((float)minDistY/m_innerScopeRect.height() * (m_dBmax-m_dBmin));
        const int mouseX = m_mousePos.x() - m_innerScopeRect.left();
        const int mouseY = m_mousePos.y() - m_innerScopeRect.top();


        QImage hud(m_scopeRect.size(), QImage::Format_ARGB32);
        hud.fill(qRgba(0,0,0,0));

        QPainter davinci(&hud);
        davinci.setPen(AbstractScopeWidget::penLight);

        int y;
        for (int db = -dbDiff; db > m_dBmin; db -= dbDiff) {
            y = topDist + m_innerScopeRect.height() * ((float)db)/(m_dBmin - m_dBmax);
            if (y-topDist > m_innerScopeRect.height()-minDistY+10) {
                // Abort here, there is still a line left for min dB to paint which needs some room.
                break;
            }
            davinci.drawLine(leftDist, y, leftDist + m_innerScopeRect.width()-1, y);
            davinci.drawText(leftDist + m_innerScopeRect.width() + textDistX, y + 6, i18n("%1 dB", m_dBmax + db));
        }
        davinci.drawLine(leftDist, topDist, leftDist + m_innerScopeRect.width()-1, topDist);
        davinci.drawText(leftDist + m_innerScopeRect.width() + textDistX, topDist+6, i18n("%1 dB", m_dBmax));
        davinci.drawLine(leftDist, topDist+m_innerScopeRect.height()-1, leftDist + m_innerScopeRect.width()-1, topDist+m_innerScopeRect.height()-1);
        davinci.drawText(leftDist + m_innerScopeRect.width() + textDistX, topDist+m_innerScopeRect.height()+6, i18n("%1 dB", m_dBmin));

        const uint hzDiff = ceil( ((float)minDistX)/m_innerScopeRect.width() * m_freqMax / 1000 ) * 1000;
        int x = 0;
        const int rightBorder = leftDist + m_innerScopeRect.width()-1;
        y = topDist + m_innerScopeRect.height() + textDistY;
        for (int hz = 0; x <= rightBorder; hz += hzDiff) {
            davinci.setPen(AbstractScopeWidget::penLighter);
            x = leftDist + m_innerScopeRect.width() * ((float)hz)/m_freqMax;

            if (x <= rightBorder) {
                davinci.drawLine(x, topDist, x, topDist + m_innerScopeRect.height()+6);
            }
            if (hz < m_freqMax && x+textDistY < leftDist + m_innerScopeRect.width()) {
                davinci.drawText(x-4, y, QVariant(hz/1000).toString());
            } else {
                x = leftDist + m_innerScopeRect.width();
                davinci.drawLine(x, topDist, x, topDist + m_innerScopeRect.height()+6);
                davinci.drawText(x-10, y, i18n("%1 kHz", QString("%1").arg((double)m_freqMax/1000, 0, 'f', 1)));
            }

            if (hz > 0) {
                // Draw finer lines between the main lines
                davinci.setPen(AbstractScopeWidget::penLightDots);
                for (uint dHz = 3; dHz > 0; dHz--) {
                    x = leftDist + m_innerScopeRect.width() * ((float)hz - dHz * hzDiff/4.0f)/m_freqMax;
                    if (x > rightBorder) {
                        break;
                    }
                    davinci.drawLine(x, topDist, x, topDist + m_innerScopeRect.height()-1);
                }
            }
        }

        if (m_aTrackMouse->isChecked() && m_mouseWithinWidget && mouseX < m_innerScopeRect.width()-1) {
            davinci.setPen(AbstractScopeWidget::penThin);

            x = leftDist + mouseX;

            float db = 0;
            float freq = ((float) mouseX)/(m_innerScopeRect.width()-1) * m_freqMax;
            bool drawDb = false;

            m_lastFFTLock.acquire();
            // We need to test whether the mouse is inside the widget
            // because the position could already have changed in the meantime (-> crash)
            if (m_lastFFT.size() > 0 && mouseX >= 0 && mouseX < m_innerScopeRect.width()) {
                uint right = ((float) m_freqMax)/(m_freq/2) * (m_lastFFT.size() - 1);
                QVector<float> dbMap = FFTTools::interpolatePeakPreserving(m_lastFFT, m_innerScopeRect.width(), 0, right, -120);

                db = dbMap[mouseX];
                y = topDist + m_innerScopeRect.height()-1 - (dbMap[mouseX] - m_dBmin) / (m_dBmax-m_dBmin) * (m_innerScopeRect.height()-1);

                if (y < (int)topDist + m_innerScopeRect.height()-1) {
                    drawDb = true;
                    davinci.drawLine(x, y, leftDist + m_innerScopeRect.width()-1, y);
                }
            } else {
                y = topDist + mouseY;
            }
            m_lastFFTLock.release();

            if (y > (int)topDist + mouseY) {
                y = topDist+ mouseY;
            }
            davinci.drawLine(x, y, x, topDist + m_innerScopeRect.height()-1);

            if (drawDb) {
                QPoint dist(20, -20);
                QRect rect(
                            leftDist + mouseX + dist.x(),
                            topDist + mouseY + dist.y(),
                            100,
                            40
                            );
                if (rect.right() > (int)leftDist + m_innerScopeRect.width()-1) {
                    // Mirror the rectangle at the y axis to keep it inside the widget
                    rect = QRect(
                                rect.topLeft() - QPoint(rect.width() + 2*dist.x(), 0),
                                rect.size());
                }

                QRect textRect(
                            rect.topLeft() + QPoint(12, 4),
                            rect.size()
                            );

                davinci.fillRect(rect, AbstractScopeWidget::penBackground.brush());
                davinci.setPen(AbstractScopeWidget::penLighter);
                davinci.drawRect(rect);
                davinci.drawText(textRect, QString(
                                     i18n("%1 dB", QString("%1").arg(db, 0, 'f', 2))
                                     + '\n'
                                     + i18n("%1 kHz", QString("%1").arg(freq/1000, 0, 'f', 2))));
            }

        }

        emit signalHUDRenderingFinished(start.elapsed(), 1);
        return hud;

    } else {
#ifdef DEBUG_AUDIOSPEC
        qDebug() << "Widget is too small for painting inside. Size of inner scope rect is "
                 << m_innerScopeRect.width() << "x" << m_innerScopeRect.height() <<".";
#endif
        emit signalHUDRenderingFinished(0, 1);
        return QImage();
    }

}
Ejemplo n.º 4
0
QImage AudioSpectrum::renderAudioScope(uint, const QVector<int16_t> audioFrame, const int freq, const int num_channels,
                                       const int num_samples, const int)
{
    if (
            audioFrame.size() > 63
            && m_innerScopeRect.width() > 0 && m_innerScopeRect.height() > 0    // <= 0 if widget is too small (resized by user)
    ) {
        if (!m_customFreq) {
            m_freqMax = freq / 2;
        }

        QTime start = QTime::currentTime();


#ifdef DETECT_OVERMODULATION
        bool overmodulated = false;
        int overmodulateCount = 0;

        for (int i = 0; i < audioFrame.size(); i++) {
            if (
                    audioFrame[i] == std::numeric_limits<int16_t>::max()
                    || audioFrame[i] == std::numeric_limits<int16_t>::min()) {
                overmodulateCount++;
                if (overmodulateCount > 3) {
                    overmodulated = true;
                    break;
                }
            }
        }
        if (overmodulated) {
            colorizeFactor = 1;
        } else {
            if (colorizeFactor > 0) {
                colorizeFactor -= .08;
                if (colorizeFactor < 0) {
                    colorizeFactor = 0;
                }
            }
        }
#endif


        // Determine the window size to use. It should be
        // * not bigger than the number of samples actually available
        // * divisible by 2
        int fftWindow = ui->windowSize->itemData(ui->windowSize->currentIndex()).toInt();
        if (fftWindow > num_samples) {
            fftWindow = num_samples;
        }
        if ((fftWindow & 1) == 1) {
            fftWindow--;
        }

        // Show the window size used, for information
        ui->labelFFTSizeNumber->setText(QVariant(fftWindow).toString());


        // Get the spectral power distribution of the input samples,
        // using the given window size and function
        float freqSpectrum[fftWindow/2];
        FFTTools::WindowType windowType = (FFTTools::WindowType) ui->windowFunction->itemData(ui->windowFunction->currentIndex()).toInt();
        m_fftTools.fftNormalized(audioFrame, 0, num_channels, freqSpectrum, windowType, fftWindow, 0);


        // Store the current FFT window (for the HUD) and run the interpolation
        // for easy pixel-based dB value access
        QVector<float> dbMap;
        m_lastFFTLock.acquire();
        m_lastFFT = QVector<float>(fftWindow/2);
        memcpy(m_lastFFT.data(), &(freqSpectrum[0]), fftWindow/2 * sizeof(float));

        uint right = ((float) m_freqMax)/(m_freq/2) * (m_lastFFT.size() - 1);
        dbMap = FFTTools::interpolatePeakPreserving(m_lastFFT, m_innerScopeRect.width(), 0, right, -180);
        m_lastFFTLock.release();


#ifdef DEBUG_AUDIOSPEC
        QTime drawTime = QTime::currentTime();
#endif

        // Draw the spectrum
        QImage spectrum(m_scopeRect.size(), QImage::Format_ARGB32);
        spectrum.fill(qRgba(0,0,0,0));
        const uint w = m_innerScopeRect.width();
        const uint h = m_innerScopeRect.height();
        const uint leftDist = m_innerScopeRect.left() - m_scopeRect.left();
        const uint topDist = m_innerScopeRect.top() - m_scopeRect.top();
        QColor spectrumColor(AbstractScopeWidget::colDarkWhite);
        int yMax;

#ifdef DETECT_OVERMODULATION
        if (colorizeFactor > 0) {
            QColor col = AbstractScopeWidget::colHighlightDark;
            QColor spec = spectrumColor;
            float f = std::sin(M_PI_2 * colorizeFactor);
            spectrumColor = QColor(
                        (int) (f * col.red() + (1-f) * spec.red()),
                        (int) (f * col.green() + (1-f) * spec.green()),
                        (int) (f * col.blue() + (1-f) * spec.blue()),
                        spec.alpha()
                        );
            // Limit the maximum colorization for non-overmodulated frames to better
            // recognize consecutively overmodulated frames
            if (colorizeFactor > MAX_OVM_COLOR) {
                colorizeFactor = MAX_OVM_COLOR;
            }
        }
#endif

#ifdef AUDIOSPEC_LINES
        QPainter davinci(&spectrum);
        davinci.setPen(QPen(QBrush(spectrumColor.rgba()), 1, Qt::SolidLine));
#endif

        for (uint i = 0; i < w; i++) {
            yMax = (dbMap[i] - m_dBmin) / (m_dBmax-m_dBmin) * (h-1);
            if (yMax < 0) {
                yMax = 0;
            } else if (yMax >= (int)h) {
                yMax = h-1;
            }
#ifdef AUDIOSPEC_LINES
            davinci.drawLine(leftDist + i, topDist + h-1, leftDist + i, topDist + h-1 - yMax);
#else
            for (int y = 0; y < yMax && y < (int)h; y++) {
                spectrum.setPixel(leftDist + i, topDist + h-y-1, spectrumColor.rgba());
            }
#endif
        }

        // Calculate the peak values. Use the new value if it is bigger, otherwise adapt to lower
        // values using the Moving Average formula
        if (m_aShowMax->isChecked()) {
            davinci.setPen(QPen(QBrush(AbstractScopeWidget::colHighlightLight), 2));
            if (m_peaks.size() != fftWindow/2) {
                m_peaks = QVector<float>(m_lastFFT);
            } else {
                for (int i = 0; i < fftWindow/2; i++) {
                    if (m_lastFFT[i] > m_peaks[i]) {
                        m_peaks[i] = m_lastFFT[i];
                    } else {
                        m_peaks[i] = ALPHA_MOVING_AVG * m_lastFFT[i] + (1-ALPHA_MOVING_AVG) * m_peaks[i];
                    }
                }
            }
            int prev = 0;
            m_peakMap = FFTTools::interpolatePeakPreserving(m_peaks, m_innerScopeRect.width(), 0, right, -180);
            for (uint i = 0; i < w; i++) {
                yMax = (m_peakMap[i] - m_dBmin) / (m_dBmax-m_dBmin) * (h-1);
                if (yMax < 0) {
                    yMax = 0;
                } else if (yMax >= (int)h) {
                    yMax = h-1;
                }

                davinci.drawLine(leftDist + i-1, topDist + h-prev-1, leftDist + i, topDist + h-yMax-1);
                spectrum.setPixel(leftDist + i, topDist + h-yMax-1, AbstractScopeWidget::colHighlightLight.rgba());
                prev = yMax;
            }
        }

#ifdef DEBUG_AUDIOSPEC
        m_showTotal++;
        m_timeTotal += drawTime.elapsed();
        qDebug() << widgetName() << " took " << drawTime.elapsed() << " ms for drawing. Average: " << ((float)m_timeTotal/m_showTotal) ;
#endif

        emit signalScopeRenderingFinished(start.elapsed(), 1);


        return spectrum;
    } else {
        emit signalScopeRenderingFinished(0, 1);
        return QImage();
    }
}
Ejemplo n.º 5
0
QImage Waveform::renderHUD(uint)
{
    QImage hud(m_scopeRect.size(), QImage::Format_ARGB32);
    hud.fill(qRgba(0,0,0,0));

    QPainter davinci(&hud);
    davinci.setPen(penLight);

    QMap< QString, QString > values = ProfilesDialog::getSettingsFromFile(KdenliveSettings::current_profile());
//    qDebug() << values.value("width");

    const int rightX = scopeRect().width()-m_textWidth.width()+3;
    const int x = m_mousePos.x() - scopeRect().x();
    const int y = m_mousePos.y() - scopeRect().y();

    if (scopeRect().height() > 0 && m_mouseWithinWidget) {
        int val = 255*(1-(float)y/scopeRect().height());

        if (val >= 0 && val <= 255) {
            // Draw a horizontal line through the current mouse position
            // and show the value of the waveform there
            davinci.drawLine(0, y, scopeRect().size().width()-m_textWidth.width(), y);

            // Make the value stick to the line unless it is at the top/bottom of the scope
            int valY = y+5;
            const int top = 30;
            const int bottom = 20;
            if (valY < top) {
                valY = top;
            } else if (valY > scopeRect().height()-bottom) {
                valY = scopeRect().height()-bottom;
            }
            davinci.drawText(rightX, valY, QVariant(val).toString());
        }

        if (scopeRect().width() > 0) {
            // Draw a vertical line and the x position of the source clip
            bool ok;
            const int profileWidth = values.value("width").toInt(&ok);

            if (ok) {
                const int clipX = (float)x/(scopeRect().width()-m_textWidth.width()-1)*(profileWidth-1);

                if (clipX >= 0 && clipX <= profileWidth) {
                    int valX = x-15;
                    if (valX < 0) { valX = 0; }
                    if (valX > scopeRect().width()-55-m_textWidth.width()) { valX = scopeRect().width()-55-m_textWidth.width(); }

                    davinci.drawLine(x, y, x, scopeRect().height()-m_paddingBottom);
                    davinci.drawText(valX, scopeRect().height()-5, QVariant(clipX).toString() + " px");
                }
            }
        }

    }
    davinci.drawText(rightX, scopeRect().height()-m_paddingBottom, "0");
    davinci.drawText(rightX, 10, "255");

    emit signalHUDRenderingFinished(0, 1);
    return hud;
}
Ejemplo n.º 6
0
QImage HistogramGenerator::calculateHistogram(const QSize &paradeSize, const QImage &image, const int &components,
                                              HistogramGenerator::Rec rec, const bool &unscaled, const uint &accelFactor) const
{
    if (paradeSize.height() <= 0 || paradeSize.width() <= 0 || image.width() <= 0 || image.height() <= 0) {
        return QImage();
    }

    bool drawY = (components & HistogramGenerator::ComponentY) != 0;
    bool drawR = (components & HistogramGenerator::ComponentR) != 0;
    bool drawG = (components & HistogramGenerator::ComponentG) != 0;
    bool drawB = (components & HistogramGenerator::ComponentB) != 0;
    bool drawSum = (components & HistogramGenerator::ComponentSum) != 0;

    int r[256], g[256], b[256], y[256], s[766];
    // Initialize the values to zero
    std::fill(r, r+256, 0);
    std::fill(g, g+256, 0);
    std::fill(b, b+256, 0);
    std::fill(y, y+256, 0);
    std::fill(s, s+766, 0);

    const uint iw = image.bytesPerLine();
    const uint ih = image.height();
    const uint ww = paradeSize.width();
    const uint wh = paradeSize.height();
    const uint byteCount = iw*ih;
    const uint stepsize = 4*accelFactor;

    const uchar *bits = image.bits();
    QRgb *col;


    // Read the stats from the input image
    for (uint i = 0; i < byteCount; i += stepsize) {
        col = (QRgb *)bits;

        r[qRed(*col)]++;
        g[qGreen(*col)]++;
        b[qBlue(*col)]++;
        if (drawY) {
            // Use if branch to avoid expensive multiplication if Y disabled
            if (rec == HistogramGenerator::Rec_601) {
                y[(int)floor(.299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col))]++;
            } else {
                y[(int)floor(.2125*qRed(*col) + .7154*qGreen(*col) + .0721*qBlue(*col))]++;
            }
        }
        if (drawSum) {
            // Use an if branch here because the sum takes more operations than rgb
            s[qRed(*col)]++;
            s[qGreen(*col)]++;
            s[qBlue(*col)]++;
        }

        bits += stepsize;
    }


    const int nParts = (drawY ? 1 : 0) + (drawR ? 1 : 0) + (drawG ? 1 : 0) + (drawB ? 1 : 0) + (drawSum ? 1 : 0);
    if (nParts == 0) {
        // Nothing to draw
        return QImage();
    }

    const int d = 20; // Distance for text
    const int partH = (wh-nParts*d)/nParts;
    const float scaling = (float)partH/(byteCount >> 7);
    const int dist = 40;

    int wy = 0; // Drawing position

    QImage histogram(paradeSize, QImage::Format_ARGB32);
    QPainter davinci(&histogram);
    davinci.setPen(QColor(220, 220, 220, 255));
    histogram.fill(qRgba(0, 0, 0, 0));

    if (drawY) {
        drawComponentFull(&davinci, y, scaling, QRect(0, wy, ww, partH + dist), QColor(220, 220, 210, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    if (drawSum) {
        drawComponentFull(&davinci, s, scaling/3, QRect(0, wy, ww, partH + dist), QColor(220, 220, 210, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    if (drawR) {
        drawComponentFull(&davinci, r, scaling, QRect(0, wy, ww, partH + dist), QColor(255, 128, 0, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    if (drawG) {
        drawComponentFull(&davinci, g, scaling, QRect(0, wy, ww, partH + dist), QColor(128, 255, 0, 255), dist, unscaled, 256);
        wy += partH + d;
    }

    if (drawB) {
        drawComponentFull(&davinci, b, scaling, QRect(0, wy, ww, partH + dist), QColor(0, 128, 255, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    return histogram;
}