F:/KPlato/koffice/libs/pigment/KoBasicHistogramProducers.cpp

Aller à la documentation de ce fichier.
00001 /*
00002  *  Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU Lesser General Public License as published
00006  *  by the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Lesser General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <QString>
00020 #include <klocale.h>
00021 
00022 #include "config.h"
00023 // #include <config-krita.h>
00024 #ifdef HAVE_OPENEXR
00025 #include <half.h>
00026 #endif
00027 
00028 // #include "Ko_global.h"
00029 #include "KoBasicHistogramProducers.h"
00030 #include "KoIntegerMaths.h"
00031 #include "KoChannelInfo.h"
00032 #include "KoColorSpace.h"
00033 #include "colorspaces/KoLabColorSpace.h"
00034 
00035 // TODO: get ride of this
00036 const quint8 quint8_MAX = UCHAR_MAX;
00037 const quint16 quint16_MAX = 65535;
00038 
00039 const qint32 qint32_MAX = (2147483647);
00040 const qint32 qint32_MIN = (-2147483647-1);
00041 
00042 
00043 KoLabColorSpace* KoGenericLabHistogramProducer::m_labCs = 0;
00044 
00045 
00046 KoBasicHistogramProducer::KoBasicHistogramProducer(const KoID& id, int channels, int nrOfBins, KoColorSpace *cs)
00047     : m_channels(channels),
00048       m_nrOfBins(nrOfBins),
00049       m_colorSpace(cs),
00050       m_id(id)
00051 {
00052     m_bins.resize(m_channels);
00053     for (int i = 0; i < m_channels; i++)
00054         m_bins.at(i).resize(m_nrOfBins);
00055     m_outLeft.resize(m_channels);
00056     m_outRight.resize(m_channels);
00057     m_count = 0;
00058     m_from = 0.0;
00059     m_width = 1.0;
00060 }
00061 
00062 void KoBasicHistogramProducer::clear() {
00063     m_count = 0;
00064     for (int i = 0; i < m_channels; i++) {
00065         for (int j = 0; j < m_nrOfBins; j++) {
00066             m_bins.at(i).at(j) = 0;
00067         }
00068         m_outRight.at(i) = 0;
00069         m_outLeft.at(i) = 0;
00070     }
00071 }
00072 
00073 void KoBasicHistogramProducer::makeExternalToInternal() {
00074     // This function assumes that the pixel is has no 'gaps'. That is to say: if we start
00075     // at byte 0, we can get to the end of the pixel by adding consecutive size()s of
00076     // the channels
00077     Q3ValueVector<KoChannelInfo *> c = channels();
00078     uint count = c.count();
00079     int currentPos = 0;
00080 
00081     for (uint i = 0; i < count; i++) {
00082         for (uint j = 0; j < count; j++) {
00083             if (c.at(j)->pos() == currentPos) {
00084                 m_external.append(j);
00085                 break;
00086             }
00087         }
00088         currentPos += c.at(m_external.at(m_external.count() - 1))->size();
00089     }
00090 }
00091 
00092 // ------------ U8 ---------------------
00093 
00094 KoBasicU8HistogramProducer::KoBasicU8HistogramProducer(const KoID& id, KoColorSpace *cs)
00095     : KoBasicHistogramProducer(id, cs->nChannels(), 256, cs)
00096 {
00097 }
00098 
00099 QString KoBasicU8HistogramProducer::positionToString(double pos) const {
00100     return QString("%1").arg(static_cast<quint8>(pos * UINT8_MAX));
00101 }
00102 
00103 void KoBasicU8HistogramProducer::addRegionToBin(const quint8 * pixels, const quint8 * selectionMask, quint32 nPixels, KoColorSpace *cs)
00104 {
00105     qint32 pSize = cs->pixelSize();
00106 
00107     if ( selectionMask ) {
00108         while (nPixels > 0) {
00109             if ( ! (m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT) ) {
00110 
00111                 for (int i = 0; i < m_channels; i++) {
00112                     m_bins.at(i).at(pixels[i])++;
00113                 }
00114                 m_count++;
00115 
00116             }
00117 
00118             pixels += pSize;
00119             selectionMask++;
00120             nPixels--;
00121         }
00122     }
00123     else {
00124         while (nPixels > 0) {
00125             if ( ! (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT) ) {
00126 
00127                 for (int i = 0; i < m_channels; i++) {
00128                     m_bins.at(i).at(pixels[i])++;
00129                 }
00130                 m_count++;
00131 
00132             }
00133 
00134             pixels += pSize;
00135             nPixels--;
00136         }
00137     }
00138 }
00139 
00140 // ------------ U16 ---------------------
00141 
00142 KoBasicU16HistogramProducer::KoBasicU16HistogramProducer(const KoID& id, KoColorSpace *cs)
00143     : KoBasicHistogramProducer(id, cs->nChannels(), 256, cs)
00144 {
00145 }
00146 
00147 QString KoBasicU16HistogramProducer::positionToString(double pos) const
00148 {
00149     return QString("%1").arg(static_cast<quint8>(pos * UINT8_MAX));
00150 }
00151 
00152 double KoBasicU16HistogramProducer::maximalZoom() const
00153 {
00154     return 1.0 / 255.0;
00155 }
00156 
00157 void KoBasicU16HistogramProducer::addRegionToBin(const quint8 * pixels, const quint8 * selectionMask, quint32 nPixels, KoColorSpace *cs)
00158 {
00159     // The view
00160     quint16 from = static_cast<quint16>(m_from * UINT16_MAX);
00161     quint16 width = static_cast<quint16>(m_width * UINT16_MAX + 0.5); // We include the end
00162     quint16 to = from + width;
00163     double factor = 255.0 / width;
00164 
00165     qint32 pSize = cs->pixelSize();
00166 
00167     if ( selectionMask ) {
00168         const quint16* pixel = reinterpret_cast<const quint16*>(pixels);
00169         while (nPixels > 0) {
00170             if ( ! ((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00171                 for (int i = 0; i < m_channels; i++) {
00172                     quint16 value = pixel[i];
00173                     if (value > to)
00174                         m_outRight.at(i)++;
00175                     else if (value < from)
00176                         m_outLeft.at(i)++;
00177                     else
00178                         m_bins.at(i).at(static_cast<quint8>((value - from) * factor))++;
00179                 }
00180                 m_count++;
00181             }
00182             pixels += pSize;
00183             selectionMask++;
00184             nPixels--;
00185         }
00186     }
00187     else {
00188         while (nPixels > 0) {
00189             const quint16* pixel = reinterpret_cast<const quint16*>(pixels);
00190 
00191             if ( ! (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00192                 for (int i = 0; i < m_channels; i++) {
00193                     quint16 value = pixel[i];
00194                     if (value > to)
00195                         m_outRight.at(i)++;
00196                     else if (value < from)
00197                         m_outLeft.at(i)++;
00198                     else
00199                         m_bins.at(i).at(static_cast<quint8>((value - from) * factor))++;
00200                 }
00201                 m_count++;
00202             }
00203             pixels += pSize;
00204             nPixels--;
00205 
00206         }
00207     }
00208 }
00209 
00210 // ------------ Float32 ---------------------
00211 KoBasicF32HistogramProducer::KoBasicF32HistogramProducer(const KoID& id, KoColorSpace *cs)
00212     : KoBasicHistogramProducer(id, cs->nChannels(), 256, cs)
00213 {
00214 }
00215 
00216 QString KoBasicF32HistogramProducer::positionToString(double pos) const {
00217     return QString("%1").arg(static_cast<float>(pos)); // XXX I doubt this is correct!
00218 }
00219 
00220 double KoBasicF32HistogramProducer::maximalZoom() const {
00221     // XXX What _is_ the maximal zoom here? I don't think there is one with floats, so this seems a fine compromis for the moment
00222     return 1.0 / 255.0;
00223 }
00224 
00225 void KoBasicF32HistogramProducer::addRegionToBin(const quint8 * pixels, const quint8 * selectionMask, quint32 nPixels, KoColorSpace *cs) {
00226     // The view
00227     float from = static_cast<float>(m_from);
00228     float width = static_cast<float>(m_width);
00229     float to = from + width;
00230     float factor = 255.0 / width;
00231 
00232     qint32 pSize = cs->pixelSize();
00233 
00234     if ( selectionMask ) {
00235         while (nPixels > 0) {
00236 
00237             const float* pixel = reinterpret_cast<const float*>(pixels);
00238             if ( !((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00239                 for (int i = 0; i < m_channels; i++) {
00240                     float value = pixel[i];
00241                     if (value > to)
00242                         m_outRight.at(i)++;
00243                     else if (value < from)
00244                         m_outLeft.at(i)++;
00245                     else
00246                         m_bins.at(i).at(static_cast<quint8>((value - from) * factor))++;
00247                 }
00248                 m_count++;
00249             }
00250 
00251             pixels += pSize;
00252             selectionMask++;
00253             nPixels--;
00254 
00255         }
00256     }
00257     else {
00258         while (nPixels > 0) {
00259 
00260             const float* pixel = reinterpret_cast<const float*>(pixels);
00261             if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00262                 for (int i = 0; i < m_channels; i++) {
00263                     float value = pixel[i];
00264                     if (value > to)
00265                         m_outRight.at(i)++;
00266                     else if (value < from)
00267                         m_outLeft.at(i)++;
00268                     else
00269                         m_bins.at(i).at(static_cast<quint8>((value - from) * factor))++;
00270                 }
00271                 m_count++;
00272             }
00273 
00274             pixels += pSize;
00275             nPixels--;
00276 
00277         }
00278     }
00279 }
00280 
00281 #ifdef HAVE_OPENEXR
00282 // ------------ Float16 Half ---------------------
00283 KoBasicF16HalfHistogramProducer::KoBasicF16HalfHistogramProducer(const KoID& id,
00284                                                                    KoColorSpace *cs)
00285     : KoBasicHistogramProducer(id, cs->nChannels(), 256, cs) {
00286 }
00287 
00288 QString KoBasicF16HalfHistogramProducer::positionToString(double pos) const {
00289     return QString("%1").arg(static_cast<float>(pos)); // XXX I doubt this is correct!
00290 }
00291 
00292 double KoBasicF16HalfHistogramProducer::maximalZoom() const {
00293     // XXX What _is_ the maximal zoom here? I don't think there is one with floats, so this seems a fine compromis for the moment
00294     return 1.0 / 255.0;
00295 }
00296 
00297 void KoBasicF16HalfHistogramProducer::addRegionToBin(const quint8 * pixels, const quint8 * selectionMask, quint32 nPixels, KoColorSpace *cs) {
00298     // The view
00299     float from = static_cast<float>(m_from);
00300     float width = static_cast<float>(m_width);
00301     float to = from + width;
00302     float factor = 255.0 / width;
00303 
00304     qint32 pSize = cs->pixelSize();
00305     if ( selectionMask ) {
00306         while (nPixels > 0) {
00307             const half* pixel = reinterpret_cast<const half*>(pixels);
00308             if ( !((m_skipUnselected  && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00309                 for (int i = 0; i < m_channels; i++) {
00310                     float value = pixel[i];
00311                     if (value > to)
00312                         m_outRight.at(i)++;
00313                     else if (value < from)
00314                         m_outLeft.at(i)++;
00315                     else
00316                         m_bins.at(i).at(static_cast<quint8>((value - from) * factor))++;
00317                 }
00318                 m_count++;
00319             }
00320             pixels += pSize;
00321             selectionMask++;
00322             nPixels--;
00323         }
00324     }
00325     else {
00326         while (nPixels > 0) {
00327             const half* pixel = reinterpret_cast<const half*>(pixels);
00328             if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00329                 for (int i = 0; i < m_channels; i++) {
00330                     float value = pixel[i];
00331                     if (value > to)
00332                         m_outRight.at(i)++;
00333                     else if (value < from)
00334                         m_outLeft.at(i)++;
00335                     else
00336                         m_bins.at(i).at(static_cast<quint8>((value - from) * factor))++;
00337                 }
00338                 m_count++;
00339             }
00340             pixels += pSize;
00341             nPixels--;
00342         }
00343     }
00344 }
00345 #endif
00346 
00347 // ------------ Generic RGB ---------------------
00348 KoGenericRGBHistogramProducer::KoGenericRGBHistogramProducer()
00349     : KoBasicHistogramProducer(KoID("GENRGBHISTO", i18n("Generic RGB Histogram")),
00350                                 3, 256, 0) {
00351     /* we set 0 as colorspece, because we are not based on a specific colorspace. This
00352        is no problem for the superclass since we override channels() */
00353     m_channelsList.append(new KoChannelInfo(i18n("R"), 0, KoChannelInfo::COLOR, KoChannelInfo::UINT8, 1, QColor(255,0,0)));
00354     m_channelsList.append(new KoChannelInfo(i18n("G"), 1, KoChannelInfo::COLOR, KoChannelInfo::UINT8, 1, QColor(0,255,0)));
00355     m_channelsList.append(new KoChannelInfo(i18n("B"), 2, KoChannelInfo::COLOR, KoChannelInfo::UINT8, 1, QColor(0,0,255)));
00356 }
00357 
00358 Q3ValueVector<KoChannelInfo *> KoGenericRGBHistogramProducer::channels() {
00359     return m_channelsList;
00360 }
00361 
00362 QString KoGenericRGBHistogramProducer::positionToString(double pos) const {
00363     return QString("%1").arg(static_cast<quint8>(pos * UINT8_MAX));
00364 }
00365 
00366 double KoGenericRGBHistogramProducer::maximalZoom() const {
00367     return 1.0;
00368 }
00369 
00370 
00371 void KoGenericRGBHistogramProducer::addRegionToBin(const quint8 * pixels, const quint8 * selectionMask, quint32 nPixels, KoColorSpace *cs)
00372 {
00373     for (int i = 0; i < m_channels; i++) {
00374         m_outRight.at(i) = 0;
00375         m_outLeft.at(i) = 0;
00376     }
00377 
00378     QColor c;
00379     qint32 pSize = cs->pixelSize();
00380     if (selectionMask) {
00381         while (nPixels > 0) {
00382             if ( !((m_skipUnselected  && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00383                 cs->toQColor(pixels, &c);
00384                 m_bins.at(0).at(c.red())++;
00385                 m_bins.at(1).at(c.green())++;
00386                 m_bins.at(2).at(c.blue())++;
00387 
00388                 m_count++;
00389             }
00390             pixels += pSize;
00391             selectionMask++;
00392             nPixels--;
00393         }
00394 
00395     }
00396     else {
00397         while (nPixels > 0) {
00398 
00399             if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
00400                 cs->toQColor(pixels, &c);
00401                 m_bins.at(0).at(c.red())++;
00402                 m_bins.at(1).at(c.green())++;
00403                 m_bins.at(2).at(c.blue())++;
00404 
00405                 m_count++;
00406             }
00407             pixels += pSize;
00408             nPixels--;
00409         }
00410     }
00411 }
00412 
00413 // ------------ Generic L*a*b* ---------------------
00414 KoGenericLabHistogramProducer::KoGenericLabHistogramProducer()
00415     : KoBasicHistogramProducer(KoID("GENLABHISTO", i18n("L*a*b* Histogram")), 3, 256, 0) {
00416     /* we set 0 as colorspace, because we are not based on a specific colorspace. This
00417        is no problem for the superclass since we override channels() */
00418     m_channelsList.append(new KoChannelInfo(i18n("L*"), 0, KoChannelInfo::COLOR, KoChannelInfo::UINT8));
00419     m_channelsList.append(new KoChannelInfo(i18n("a*"), 1, KoChannelInfo::COLOR, KoChannelInfo::UINT8));
00420     m_channelsList.append(new KoChannelInfo(i18n("b*"), 2, KoChannelInfo::COLOR, KoChannelInfo::UINT8));
00421 
00422     if (!m_labCs) {
00423         KoColorProfile *labProfile = new KoColorProfile(cmsCreateLabProfile(NULL));
00424         m_labCs = new KoLabColorSpace(0, labProfile);
00425     }
00426     m_colorSpace = m_labCs;
00427 }
00428 KoGenericLabHistogramProducer::~KoGenericLabHistogramProducer()
00429 {
00430     delete m_channelsList[0];
00431     delete m_channelsList[1];
00432     delete m_channelsList[2];
00433 }
00434 
00435 Q3ValueVector<KoChannelInfo *> KoGenericLabHistogramProducer::channels() {
00436     return m_channelsList;
00437 }
00438 
00439 QString KoGenericLabHistogramProducer::positionToString(double pos) const {
00440     return QString("%1").arg(static_cast<quint16>(pos * UINT16_MAX));
00441 }
00442 
00443 double KoGenericLabHistogramProducer::maximalZoom() const {
00444     return 1.0;
00445 }
00446 
00447 
00448 void KoGenericLabHistogramProducer::addRegionToBin(const quint8 * pixels, const quint8 * selectionMask, quint32 nPixels,  KoColorSpace *cs)
00449 {
00450     for (int i = 0; i < m_channels; i++) {
00451         m_outRight.at(i) = 0;
00452         m_outLeft.at(i) = 0;
00453     }
00454 
00455     quint8 dst[8];
00456     qint32 pSize = cs->pixelSize();
00457 
00458     if (selectionMask) {
00459         while (nPixels > 0) {
00460             if ( !((m_skipUnselected  && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
00461 /*
00462   cs->toQColor(pixels, &c);
00463   m_bins.at(0).at(c.red())++;
00464 */
00465                 m_count++;
00466             }
00467             pixels += pSize;
00468             selectionMask++;
00469             nPixels--;
00470         }
00471     }
00472     else {
00473         while (nPixels > 0) {
00474             if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT))  {
00475 
00476   cs->convertPixelsTo(pixels, dst, m_colorSpace, 1);
00477   m_bins.at(0).at(m_colorSpace->scaleToU8(dst, 0))++;
00478   m_bins.at(1).at(m_colorSpace->scaleToU8(dst, 1))++;
00479   m_bins.at(2).at(m_colorSpace->scaleToU8(dst, 2))++;
00480 
00481                 m_count++;
00482             }
00483             pixels += pSize;
00484             nPixels--;
00485         }
00486     }
00487 }
00488 

Généré le Wed Nov 22 23:41:13 2006 pour KPlato par  doxygen 1.5.1-p1