1 /***************************************************************************
2 * Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com) *
3 * This file is part of kdenlive. See www.kdenlive.org. *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
16 #include "histogramgenerator.h"
18 HistogramGenerator::HistogramGenerator()
22 QImage HistogramGenerator::calculateHistogram(const QSize ¶deSize, const QImage &image, const int &components,
23 HistogramGenerator::Rec rec, bool unscaled, uint accelFactor) const
25 if (paradeSize.height() <= 0 || paradeSize.width() <= 0 || image.width() <= 0 || image.height() <= 0) {
29 bool drawY = (components & HistogramGenerator::ComponentY) != 0;
30 bool drawR = (components & HistogramGenerator::ComponentR) != 0;
31 bool drawG = (components & HistogramGenerator::ComponentG) != 0;
32 bool drawB = (components & HistogramGenerator::ComponentB) != 0;
33 bool drawSum = (components & HistogramGenerator::ComponentSum) != 0;
35 int r[256], g[256], b[256], y[256], s[766];
36 // Initialize the values to zero
37 std::fill(r, r+256, 0);
38 std::fill(g, g+256, 0);
39 std::fill(b, b+256, 0);
40 std::fill(y, y+256, 0);
41 std::fill(s, s+766, 0);
43 const uint iw = image.bytesPerLine();
44 const uint ih = image.height();
45 const uint ww = paradeSize.width();
46 const uint wh = paradeSize.height();
47 const uint byteCount = iw*ih;
48 const uint stepsize = image.depth() / 8 *accelFactor;
50 const uchar *bits = image.bits();
54 // Read the stats from the input image
55 for (uint i = 0; i < byteCount; i += stepsize) {
62 // Use if branch to avoid expensive multiplication if Y disabled
63 if (rec == HistogramGenerator::Rec_601) {
64 y[(int)floor(.299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col))]++;
66 y[(int)floor(.2125*qRed(*col) + .7154*qGreen(*col) + .0721*qBlue(*col))]++;
70 // Use an if branch here because the sum takes more operations than rgb
80 const int nParts = (drawY ? 1 : 0) + (drawR ? 1 : 0) + (drawG ? 1 : 0) + (drawB ? 1 : 0) + (drawSum ? 1 : 0);
86 const int d = 20; // Distance for text
87 const int partH = (wh-nParts*d)/nParts;
89 int div = byteCount >> 7;
91 scaling = (float)partH/(byteCount >> 7);
94 int wy = 0; // Drawing position
96 QImage histogram(paradeSize, QImage::Format_ARGB32);
97 QPainter davinci(&histogram);
98 davinci.setPen(QColor(220, 220, 220, 255));
99 histogram.fill(qRgba(0, 0, 0, 0));
102 drawComponentFull(&davinci, y, scaling, QRect(0, wy, ww, partH + dist), QColor(220, 220, 210, 255), dist, unscaled, 256);
108 drawComponentFull(&davinci, s, scaling/3, QRect(0, wy, ww, partH + dist), QColor(220, 220, 210, 255), dist, unscaled, 256);
114 drawComponentFull(&davinci, r, scaling, QRect(0, wy, ww, partH + dist), QColor(255, 128, 0, 255), dist, unscaled, 256);
120 drawComponentFull(&davinci, g, scaling, QRect(0, wy, ww, partH + dist), QColor(128, 255, 0, 255), dist, unscaled, 256);
125 drawComponentFull(&davinci, b, scaling, QRect(0, wy, ww, partH + dist), QColor(0, 128, 255, 255), dist, unscaled, 256);
133 QImage HistogramGenerator::drawComponent(const int *y, const QSize &size, const float &scaling, const QColor &color,
134 bool unscaled, uint max) const
136 QImage component(max, size.height(), QImage::Format_ARGB32);
137 component.fill(qRgba(0, 0, 0, 0));
138 Q_ASSERT(scaling != INFINITY);
140 const int partH = size.height();
143 for (uint x = 0; x < max; x++) {
144 // Calculate the height of the curve at position x
145 partY = scaling*y[x];
148 if (partY > partH-1) { partY = partH-1; }
149 partY = partH-1 - partY;
151 for (int k = partH-1; k >= partY; k--) {
152 component.setPixel(x, k, color.rgba());
155 if (unscaled && size.width() >= component.width()) {
158 return component.scaled(size, Qt::IgnoreAspectRatio, Qt::FastTransformation);
162 void HistogramGenerator::drawComponentFull(QPainter *davinci, const int *y, const float &scaling, const QRect &rect,
163 const QColor &color, int textSpace, bool unscaled, uint max) const
165 QImage component = drawComponent(y, rect.size() - QSize(0, textSpace), scaling, color, unscaled, max);
166 davinci->drawImage(rect.topLeft(), component);
169 for (uint x = 0; x < max; x++) {
176 for (int x = max-1; x >= 0; x--) {
183 const int textY = rect.bottom()-textSpace+15;
185 const int cw = component.width();
187 davinci->drawText(0, textY, i18n("min"));
188 davinci->drawText(dist, textY, QString::number(min, 'f', 0));
190 davinci->drawText(cw-dist-30, textY, i18n("max"));
191 davinci->drawText(cw-30, textY, QString::number(maxVal, 'f', 0));