00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <qstring.h>
00020 #include <klocale.h>
00021
00022 #include "config.h"
00023
00024 #ifdef HAVE_OPENEXR
00025 #include <half.h>
00026 #endif
00027
00028 #include "kis_global.h"
00029 #include "kis_basic_histogram_producers.h"
00030 #include "kis_integer_maths.h"
00031 #include "kis_channelinfo.h"
00032 #include "kis_colorspace.h"
00033 #include "kis_lab_colorspace.h"
00034
00035 KisLabColorSpace* KisGenericLabHistogramProducer::m_labCs = 0;
00036
00037
00038 KisBasicHistogramProducer::KisBasicHistogramProducer(const KisID& id, int channels, int nrOfBins, KisColorSpace *cs)
00039 : m_channels(channels),
00040 m_nrOfBins(nrOfBins),
00041 m_colorSpace(cs),
00042 m_id(id)
00043 {
00044 m_bins.resize(m_channels);
00045 for (int i = 0; i < m_channels; i++)
00046 m_bins.at(i).resize(m_nrOfBins);
00047 m_outLeft.resize(m_channels);
00048 m_outRight.resize(m_channels);
00049 m_count = 0;
00050 m_from = 0.0;
00051 m_width = 1.0;
00052 }
00053
00054 void KisBasicHistogramProducer::clear() {
00055 m_count = 0;
00056 for (int i = 0; i < m_channels; i++) {
00057 for (int j = 0; j < m_nrOfBins; j++) {
00058 m_bins.at(i).at(j) = 0;
00059 }
00060 m_outRight.at(i) = 0;
00061 m_outLeft.at(i) = 0;
00062 }
00063 }
00064
00065 void KisBasicHistogramProducer::makeExternalToInternal() {
00066
00067
00068
00069 QValueVector<KisChannelInfo *> c = channels();
00070 uint count = c.count();
00071 int currentPos = 0;
00072
00073 for (uint i = 0; i < count; i++) {
00074 for (uint j = 0; j < count; j++) {
00075 if (c.at(j)->pos() == currentPos) {
00076 m_external.append(j);
00077 break;
00078 }
00079 }
00080 currentPos += c.at(m_external.at(m_external.count() - 1))->size();
00081 }
00082 }
00083
00084
00085
00086 KisBasicU8HistogramProducer::KisBasicU8HistogramProducer(const KisID& id, KisColorSpace *cs)
00087 : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs)
00088 {
00089 }
00090
00091 QString KisBasicU8HistogramProducer::positionToString(double pos) const {
00092 return QString("%1").arg(static_cast<Q_UINT8>(pos * UINT8_MAX));
00093 }
00094
00095 void KisBasicU8HistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
00096 {
00097 Q_INT32 pSize = cs->pixelSize();
00098
00099 if ( selectionMask ) {
00100 while (nPixels > 0) {
00101 if ( ! (m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT) ) {
00102
00103 for (int i = 0; i < m_channels; i++) {
00104 m_bins.at(i).at(pixels[i])++;
00105 }
00106 m_count++;
00107
00108 }
00109
00110 pixels += pSize;
00111 selectionMask++;
00112 nPixels--;
00113 }
00114 }
00115 else {
00116 while (nPixels > 0) {
00117 if ( ! (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT) ) {
00118
00119 for (int i = 0; i < m_channels; i++) {
00120 m_bins.at(i).at(pixels[i])++;
00121 }
00122 m_count++;
00123
00124 }
00125
00126 pixels += pSize;
00127 nPixels--;
00128 }
00129 }
00130 }
00131
00132
00133
00134 KisBasicU16HistogramProducer::KisBasicU16HistogramProducer(const KisID& id, KisColorSpace *cs)
00135 : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs)
00136 {
00137 }
00138
00139 QString KisBasicU16HistogramProducer::positionToString(double pos) const
00140 {
00141 return QString("%1").arg(static_cast<Q_UINT8>(pos * UINT8_MAX));
00142 }
00143
00144 double KisBasicU16HistogramProducer::maximalZoom() const
00145 {
00146 return 1.0 / 255.0;
00147 }
00148
00149 void KisBasicU16HistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
00150 {
00151
00152 Q_UINT16 from = static_cast<Q_UINT16>(m_from * UINT16_MAX);
00153 Q_UINT16 width = static_cast<Q_UINT16>(m_width * UINT16_MAX + 0.5);
00154 Q_UINT16 to = from + width;
00155 double factor = 255.0 / width;
00156
00157 Q_INT32 pSize = cs->pixelSize();
00158
00159 if ( selectionMask ) {
00160 Q_UINT16* pixel = reinterpret_cast<Q_UINT16*>(pixels);
00161 while (nPixels > 0) {
00162 if ( ! ((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00163 for (int i = 0; i < m_channels; i++) {
00164 Q_UINT16 value = pixel[i];
00165 if (value > to)
00166 m_outRight.at(i)++;
00167 else if (value < from)
00168 m_outLeft.at(i)++;
00169 else
00170 m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
00171 }
00172 m_count++;
00173 }
00174 pixels += pSize;
00175 selectionMask++;
00176 nPixels--;
00177 }
00178 }
00179 else {
00180 while (nPixels > 0) {
00181 Q_UINT16* pixel = reinterpret_cast<Q_UINT16*>(pixels);
00182
00183 if ( ! (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00184 for (int i = 0; i < m_channels; i++) {
00185 Q_UINT16 value = pixel[i];
00186 if (value > to)
00187 m_outRight.at(i)++;
00188 else if (value < from)
00189 m_outLeft.at(i)++;
00190 else
00191 m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
00192 }
00193 m_count++;
00194 }
00195 pixels += pSize;
00196 nPixels--;
00197
00198 }
00199 }
00200 }
00201
00202
00203 KisBasicF32HistogramProducer::KisBasicF32HistogramProducer(const KisID& id, KisColorSpace *cs)
00204 : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs)
00205 {
00206 }
00207
00208 QString KisBasicF32HistogramProducer::positionToString(double pos) const {
00209 return QString("%1").arg(static_cast<float>(pos));
00210 }
00211
00212 double KisBasicF32HistogramProducer::maximalZoom() const {
00213
00214 return 1.0 / 255.0;
00215 }
00216
00217 void KisBasicF32HistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs) {
00218
00219 float from = static_cast<float>(m_from);
00220 float width = static_cast<float>(m_width);
00221 float to = from + width;
00222 float factor = 255.0 / width;
00223
00224 Q_INT32 pSize = cs->pixelSize();
00225
00226 if ( selectionMask ) {
00227 while (nPixels > 0) {
00228
00229 float* pixel = reinterpret_cast<float*>(pixels);
00230 if ( !((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00231 for (int i = 0; i < m_channels; i++) {
00232 float value = pixel[i];
00233 if (value > to)
00234 m_outRight.at(i)++;
00235 else if (value < from)
00236 m_outLeft.at(i)++;
00237 else
00238 m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
00239 }
00240 m_count++;
00241 }
00242
00243 pixels += pSize;
00244 selectionMask++;
00245 nPixels--;
00246
00247 }
00248 }
00249 else {
00250 while (nPixels > 0) {
00251
00252 float* pixel = reinterpret_cast<float*>(pixels);
00253 if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00254 for (int i = 0; i < m_channels; i++) {
00255 float value = pixel[i];
00256 if (value > to)
00257 m_outRight.at(i)++;
00258 else if (value < from)
00259 m_outLeft.at(i)++;
00260 else
00261 m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
00262 }
00263 m_count++;
00264 }
00265
00266 pixels += pSize;
00267 nPixels--;
00268
00269 }
00270 }
00271 }
00272
00273 #ifdef HAVE_OPENEXR
00274
00275 KisBasicF16HalfHistogramProducer::KisBasicF16HalfHistogramProducer(const KisID& id,
00276 KisColorSpace *cs)
00277 : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs) {
00278 }
00279
00280 QString KisBasicF16HalfHistogramProducer::positionToString(double pos) const {
00281 return QString("%1").arg(static_cast<float>(pos));
00282 }
00283
00284 double KisBasicF16HalfHistogramProducer::maximalZoom() const {
00285
00286 return 1.0 / 255.0;
00287 }
00288
00289 void KisBasicF16HalfHistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs) {
00290
00291 float from = static_cast<float>(m_from);
00292 float width = static_cast<float>(m_width);
00293 float to = from + width;
00294 float factor = 255.0 / width;
00295
00296 Q_INT32 pSize = cs->pixelSize();
00297 if ( selectionMask ) {
00298 while (nPixels > 0) {
00299 half* pixel = reinterpret_cast<half*>(pixels);
00300 if ( !((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00301 for (int i = 0; i < m_channels; i++) {
00302 float value = pixel[i];
00303 if (value > to)
00304 m_outRight.at(i)++;
00305 else if (value < from)
00306 m_outLeft.at(i)++;
00307 else
00308 m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
00309 }
00310 m_count++;
00311 }
00312 pixels += pSize;
00313 selectionMask++;
00314 nPixels--;
00315 }
00316 }
00317 else {
00318 while (nPixels > 0) {
00319 half* pixel = reinterpret_cast<half*>(pixels);
00320 if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00321 for (int i = 0; i < m_channels; i++) {
00322 float value = pixel[i];
00323 if (value > to)
00324 m_outRight.at(i)++;
00325 else if (value < from)
00326 m_outLeft.at(i)++;
00327 else
00328 m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
00329 }
00330 m_count++;
00331 }
00332 pixels += pSize;
00333 nPixels--;
00334 }
00335 }
00336 }
00337 #endif
00338
00339
00340 KisGenericRGBHistogramProducer::KisGenericRGBHistogramProducer()
00341 : KisBasicHistogramProducer(KisID("GENRGBHISTO", i18n("Generic RGB Histogram")),
00342 3, 256, 0) {
00343
00344
00345 m_channelsList.append(new KisChannelInfo(i18n("R"), 0, KisChannelInfo::COLOR, KisChannelInfo::UINT8, 1, QColor(255,0,0)));
00346 m_channelsList.append(new KisChannelInfo(i18n("G"), 1, KisChannelInfo::COLOR, KisChannelInfo::UINT8, 1, QColor(0,255,0)));
00347 m_channelsList.append(new KisChannelInfo(i18n("B"), 2, KisChannelInfo::COLOR, KisChannelInfo::UINT8, 1, QColor(0,0,255)));
00348 }
00349
00350 QValueVector<KisChannelInfo *> KisGenericRGBHistogramProducer::channels() {
00351 return m_channelsList;
00352 }
00353
00354 QString KisGenericRGBHistogramProducer::positionToString(double pos) const {
00355 return QString("%1").arg(static_cast<Q_UINT8>(pos * UINT8_MAX));
00356 }
00357
00358 double KisGenericRGBHistogramProducer::maximalZoom() const {
00359 return 1.0;
00360 }
00361
00362
00363 void KisGenericRGBHistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
00364 {
00365 for (int i = 0; i < m_channels; i++) {
00366 m_outRight.at(i) = 0;
00367 m_outLeft.at(i) = 0;
00368 }
00369
00370 QColor c;
00371 Q_INT32 pSize = cs->pixelSize();
00372 if (selectionMask) {
00373 while (nPixels > 0) {
00374 if ( !((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00375 cs->toQColor(pixels, &c);
00376 m_bins.at(0).at(c.red())++;
00377 m_bins.at(1).at(c.green())++;
00378 m_bins.at(2).at(c.blue())++;
00379
00380 m_count++;
00381 }
00382 pixels += pSize;
00383 selectionMask++;
00384 nPixels--;
00385 }
00386
00387 }
00388 else {
00389 while (nPixels > 0) {
00390
00391 if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00392 cs->toQColor(pixels, &c);
00393 m_bins.at(0).at(c.red())++;
00394 m_bins.at(1).at(c.green())++;
00395 m_bins.at(2).at(c.blue())++;
00396
00397 m_count++;
00398 }
00399 pixels += pSize;
00400 nPixels--;
00401 }
00402 }
00403 }
00404
00405
00406 KisGenericLabHistogramProducer::KisGenericLabHistogramProducer()
00407 : KisBasicHistogramProducer(KisID("GENLABHISTO", i18n("L*a*b* Histogram")), 3, 256, 0) {
00408
00409
00410 m_channelsList.append(new KisChannelInfo(i18n("L*"), 0, KisChannelInfo::COLOR, KisChannelInfo::UINT8));
00411 m_channelsList.append(new KisChannelInfo(i18n("a*"), 1, KisChannelInfo::COLOR, KisChannelInfo::UINT8));
00412 m_channelsList.append(new KisChannelInfo(i18n("b*"), 2, KisChannelInfo::COLOR, KisChannelInfo::UINT8));
00413
00414 if (!m_labCs) {
00415 KisProfile *labProfile = new KisProfile(cmsCreateLabProfile(NULL));
00416 m_labCs = new KisLabColorSpace(0, labProfile);
00417 }
00418 m_colorSpace = m_labCs;
00419 }
00420 KisGenericLabHistogramProducer::~KisGenericLabHistogramProducer()
00421 {
00422 delete m_channelsList[0];
00423 delete m_channelsList[1];
00424 delete m_channelsList[2];
00425 }
00426
00427 QValueVector<KisChannelInfo *> KisGenericLabHistogramProducer::channels() {
00428 return m_channelsList;
00429 }
00430
00431 QString KisGenericLabHistogramProducer::positionToString(double pos) const {
00432 return QString("%1").arg(static_cast<Q_UINT16>(pos * UINT16_MAX));
00433 }
00434
00435 double KisGenericLabHistogramProducer::maximalZoom() const {
00436 return 1.0;
00437 }
00438
00439
00440 void KisGenericLabHistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
00441 {
00442 for (int i = 0; i < m_channels; i++) {
00443 m_outRight.at(i) = 0;
00444 m_outLeft.at(i) = 0;
00445 }
00446
00447 Q_UINT8 dst[8];
00448 Q_INT32 pSize = cs->pixelSize();
00449
00450 if (selectionMask) {
00451 while (nPixels > 0) {
00452 if ( !((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00453
00454
00455
00456
00457 m_count++;
00458 }
00459 pixels += pSize;
00460 selectionMask++;
00461 nPixels--;
00462 }
00463 }
00464 else {
00465 while (nPixels > 0) {
00466 if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00467
00468 cs->convertPixelsTo(pixels, dst, m_colorSpace, 1);
00469 m_bins.at(0).at(m_colorSpace->scaleToU8(dst, 0))++;
00470 m_bins.at(1).at(m_colorSpace->scaleToU8(dst, 1))++;
00471 m_bins.at(2).at(m_colorSpace->scaleToU8(dst, 2))++;
00472
00473 m_count++;
00474 }
00475 pixels += pSize;
00476 nPixels--;
00477 }
00478 }
00479 }
00480