~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to krita/kritacolor/kis_basic_histogram_producers.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-04-20 21:38:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060420213853-j5lxluqvymxt2zny
Tags: 1:1.5.0-0ubuntu2
UbuntuĀ uploadĀ 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
 
3
 *
 
4
 *  This program is free software; you can redistribute it and/or modify
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation; either version 2 of the License, or
 
7
 *  (at your option) any later version.
 
8
 *
 
9
 *  This program is distributed in the hope that it will be useful,
 
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *  GNU General Public License for more details.
 
13
 *
 
14
 *  You should have received a copy of the GNU General Public License
 
15
 *  along with this program; if not, write to the Free Software
 
16
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 */
 
18
 
 
19
#include <qstring.h>
 
20
#include <klocale.h>
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#ifdef HAVE_OPENEXR
 
25
#include <half.h>
 
26
#endif
 
27
 
 
28
#include "kis_global.h"
 
29
#include "kis_basic_histogram_producers.h"
 
30
#include "kis_integer_maths.h"
 
31
#include "kis_channelinfo.h"
 
32
#include "kis_colorspace.h"
 
33
#include "kis_lab_colorspace.h"
 
34
 
 
35
KisLabColorSpace* KisGenericLabHistogramProducer::m_labCs = 0;
 
36
 
 
37
 
 
38
KisBasicHistogramProducer::KisBasicHistogramProducer(const KisID& id, int channels, int nrOfBins, KisColorSpace *cs)
 
39
    : m_channels(channels),
 
40
      m_nrOfBins(nrOfBins),
 
41
      m_colorSpace(cs),
 
42
      m_id(id)
 
43
{
 
44
    m_bins.resize(m_channels);
 
45
    for (int i = 0; i < m_channels; i++)
 
46
        m_bins.at(i).resize(m_nrOfBins);
 
47
    m_outLeft.resize(m_channels);
 
48
    m_outRight.resize(m_channels);
 
49
    m_count = 0;
 
50
    m_from = 0.0;
 
51
    m_width = 1.0;
 
52
}
 
53
 
 
54
void KisBasicHistogramProducer::clear() {
 
55
    m_count = 0;
 
56
    for (int i = 0; i < m_channels; i++) {
 
57
        for (int j = 0; j < m_nrOfBins; j++) {
 
58
            m_bins.at(i).at(j) = 0;
 
59
        }
 
60
        m_outRight.at(i) = 0;
 
61
        m_outLeft.at(i) = 0;
 
62
    }
 
63
}
 
64
 
 
65
void KisBasicHistogramProducer::makeExternalToInternal() {
 
66
    // This function assumes that the pixel is has no 'gaps'. That is to say: if we start
 
67
    // at byte 0, we can get to the end of the pixel by adding consecutive size()s of
 
68
    // the channels
 
69
    QValueVector<KisChannelInfo *> c = channels();
 
70
    uint count = c.count();
 
71
    int currentPos = 0;
 
72
 
 
73
    for (uint i = 0; i < count; i++) {
 
74
        for (uint j = 0; j < count; j++) {
 
75
            if (c.at(j)->pos() == currentPos) {
 
76
                m_external.append(j);
 
77
                break;
 
78
            }
 
79
        }
 
80
        currentPos += c.at(m_external.at(m_external.count() - 1))->size();
 
81
    }
 
82
}
 
83
 
 
84
// ------------ U8 ---------------------
 
85
 
 
86
KisBasicU8HistogramProducer::KisBasicU8HistogramProducer(const KisID& id, KisColorSpace *cs)
 
87
    : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs)
 
88
{
 
89
}
 
90
 
 
91
QString KisBasicU8HistogramProducer::positionToString(double pos) const {
 
92
    return QString("%1").arg(static_cast<Q_UINT8>(pos * UINT8_MAX));
 
93
}
 
94
 
 
95
void KisBasicU8HistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
 
96
{
 
97
    Q_INT32 pSize = cs->pixelSize();
 
98
 
 
99
    if ( selectionMask ) {
 
100
        while (nPixels > 0) {
 
101
            if ( ! (m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT) ) {
 
102
 
 
103
                for (int i = 0; i < m_channels; i++) {
 
104
                    m_bins.at(i).at(pixels[i])++;
 
105
                }
 
106
                m_count++;
 
107
 
 
108
            }
 
109
 
 
110
            pixels += pSize;
 
111
            selectionMask++;
 
112
            nPixels--;
 
113
        }
 
114
    }
 
115
    else {
 
116
        while (nPixels > 0) {
 
117
            if ( ! (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT) ) {
 
118
 
 
119
                for (int i = 0; i < m_channels; i++) {
 
120
                    m_bins.at(i).at(pixels[i])++;
 
121
                }
 
122
                m_count++;
 
123
 
 
124
            }
 
125
 
 
126
            pixels += pSize;
 
127
            nPixels--;
 
128
        }
 
129
    }
 
130
}
 
131
 
 
132
// ------------ U16 ---------------------
 
133
 
 
134
KisBasicU16HistogramProducer::KisBasicU16HistogramProducer(const KisID& id, KisColorSpace *cs)
 
135
    : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs)
 
136
{
 
137
}
 
138
 
 
139
QString KisBasicU16HistogramProducer::positionToString(double pos) const
 
140
{
 
141
    return QString("%1").arg(static_cast<Q_UINT8>(pos * UINT8_MAX));
 
142
}
 
143
 
 
144
double KisBasicU16HistogramProducer::maximalZoom() const
 
145
{
 
146
    return 1.0 / 255.0;
 
147
}
 
148
 
 
149
void KisBasicU16HistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
 
150
{
 
151
    // The view
 
152
    Q_UINT16 from = static_cast<Q_UINT16>(m_from * UINT16_MAX);
 
153
    Q_UINT16 width = static_cast<Q_UINT16>(m_width * UINT16_MAX + 0.5); // We include the end
 
154
    Q_UINT16 to = from + width;
 
155
    double factor = 255.0 / width;
 
156
 
 
157
    Q_INT32 pSize = cs->pixelSize();
 
158
 
 
159
    if ( selectionMask ) {
 
160
        Q_UINT16* pixel = reinterpret_cast<Q_UINT16*>(pixels);
 
161
        while (nPixels > 0) {
 
162
            if ( ! ((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
 
163
                for (int i = 0; i < m_channels; i++) {
 
164
                    Q_UINT16 value = pixel[i];
 
165
                    if (value > to)
 
166
                        m_outRight.at(i)++;
 
167
                    else if (value < from)
 
168
                        m_outLeft.at(i)++;
 
169
                    else
 
170
                        m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
 
171
                }
 
172
                m_count++;
 
173
            }
 
174
            pixels += pSize;
 
175
            selectionMask++;
 
176
            nPixels--;
 
177
        }
 
178
    }
 
179
    else {
 
180
        while (nPixels > 0) {
 
181
            Q_UINT16* pixel = reinterpret_cast<Q_UINT16*>(pixels);
 
182
 
 
183
            if ( ! (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
 
184
                for (int i = 0; i < m_channels; i++) {
 
185
                    Q_UINT16 value = pixel[i];
 
186
                    if (value > to)
 
187
                        m_outRight.at(i)++;
 
188
                    else if (value < from)
 
189
                        m_outLeft.at(i)++;
 
190
                    else
 
191
                        m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
 
192
                }
 
193
                m_count++;
 
194
            }
 
195
            pixels += pSize;
 
196
            nPixels--;
 
197
 
 
198
        }
 
199
    }
 
200
}
 
201
 
 
202
// ------------ Float32 ---------------------
 
203
KisBasicF32HistogramProducer::KisBasicF32HistogramProducer(const KisID& id, KisColorSpace *cs)
 
204
    : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs)
 
205
{
 
206
}
 
207
 
 
208
QString KisBasicF32HistogramProducer::positionToString(double pos) const {
 
209
    return QString("%1").arg(static_cast<float>(pos)); // XXX I doubt this is correct!
 
210
}
 
211
 
 
212
double KisBasicF32HistogramProducer::maximalZoom() const {
 
213
    // 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
 
214
    return 1.0 / 255.0;
 
215
}
 
216
 
 
217
void KisBasicF32HistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs) {
 
218
    // The view
 
219
    float from = static_cast<float>(m_from);
 
220
    float width = static_cast<float>(m_width);
 
221
    float to = from + width;
 
222
    float factor = 255.0 / width;
 
223
 
 
224
    Q_INT32 pSize = cs->pixelSize();
 
225
 
 
226
    if ( selectionMask ) {
 
227
        while (nPixels > 0) {
 
228
 
 
229
            float* pixel = reinterpret_cast<float*>(pixels);
 
230
            if ( !((m_skipUnselected && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
 
231
                for (int i = 0; i < m_channels; i++) {
 
232
                    float value = pixel[i];
 
233
                    if (value > to)
 
234
                        m_outRight.at(i)++;
 
235
                    else if (value < from)
 
236
                        m_outLeft.at(i)++;
 
237
                    else
 
238
                        m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
 
239
                }
 
240
                m_count++;
 
241
            }
 
242
 
 
243
            pixels += pSize;
 
244
            selectionMask++;
 
245
            nPixels--;
 
246
 
 
247
        }
 
248
    }
 
249
    else {
 
250
        while (nPixels > 0) {
 
251
 
 
252
            float* pixel = reinterpret_cast<float*>(pixels);
 
253
            if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
 
254
                for (int i = 0; i < m_channels; i++) {
 
255
                    float value = pixel[i];
 
256
                    if (value > to)
 
257
                        m_outRight.at(i)++;
 
258
                    else if (value < from)
 
259
                        m_outLeft.at(i)++;
 
260
                    else
 
261
                        m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
 
262
                }
 
263
                m_count++;
 
264
            }
 
265
 
 
266
            pixels += pSize;
 
267
            nPixels--;
 
268
 
 
269
        }
 
270
    }
 
271
}
 
272
 
 
273
#ifdef HAVE_OPENEXR
 
274
// ------------ Float16 Half ---------------------
 
275
KisBasicF16HalfHistogramProducer::KisBasicF16HalfHistogramProducer(const KisID& id,
 
276
                                                                   KisColorSpace *cs)
 
277
    : KisBasicHistogramProducer(id, cs->nChannels(), 256, cs) {
 
278
}
 
279
 
 
280
QString KisBasicF16HalfHistogramProducer::positionToString(double pos) const {
 
281
    return QString("%1").arg(static_cast<float>(pos)); // XXX I doubt this is correct!
 
282
}
 
283
 
 
284
double KisBasicF16HalfHistogramProducer::maximalZoom() const {
 
285
    // 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
 
286
    return 1.0 / 255.0;
 
287
}
 
288
 
 
289
void KisBasicF16HalfHistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs) {
 
290
    // The view
 
291
    float from = static_cast<float>(m_from);
 
292
    float width = static_cast<float>(m_width);
 
293
    float to = from + width;
 
294
    float factor = 255.0 / width;
 
295
 
 
296
    Q_INT32 pSize = cs->pixelSize();
 
297
    if ( selectionMask ) {
 
298
        while (nPixels > 0) {
 
299
            half* pixel = reinterpret_cast<half*>(pixels);
 
300
            if ( !((m_skipUnselected  && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
 
301
                for (int i = 0; i < m_channels; i++) {
 
302
                    float value = pixel[i];
 
303
                    if (value > to)
 
304
                        m_outRight.at(i)++;
 
305
                    else if (value < from)
 
306
                        m_outLeft.at(i)++;
 
307
                    else
 
308
                        m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
 
309
                }
 
310
                m_count++;
 
311
            }
 
312
            pixels += pSize;
 
313
            selectionMask++;
 
314
            nPixels--;
 
315
        }
 
316
    }
 
317
    else {
 
318
        while (nPixels > 0) {
 
319
            half* pixel = reinterpret_cast<half*>(pixels);
 
320
            if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
 
321
                for (int i = 0; i < m_channels; i++) {
 
322
                    float value = pixel[i];
 
323
                    if (value > to)
 
324
                        m_outRight.at(i)++;
 
325
                    else if (value < from)
 
326
                        m_outLeft.at(i)++;
 
327
                    else
 
328
                        m_bins.at(i).at(static_cast<Q_UINT8>((value - from) * factor))++;
 
329
                }
 
330
                m_count++;
 
331
            }
 
332
            pixels += pSize;
 
333
            nPixels--;
 
334
        }
 
335
    }
 
336
}
 
337
#endif
 
338
 
 
339
// ------------ Generic RGB ---------------------
 
340
KisGenericRGBHistogramProducer::KisGenericRGBHistogramProducer()
 
341
    : KisBasicHistogramProducer(KisID("GENRGBHISTO", i18n("Generic RGB Histogram")),
 
342
                                3, 256, 0) {
 
343
    /* we set 0 as colorspece, because we are not based on a specific colorspace. This
 
344
       is no problem for the superclass since we override channels() */
 
345
    m_channelsList.append(new KisChannelInfo(i18n("R"), 0, KisChannelInfo::COLOR, KisChannelInfo::UINT8, 1, QColor(255,0,0)));
 
346
    m_channelsList.append(new KisChannelInfo(i18n("G"), 1, KisChannelInfo::COLOR, KisChannelInfo::UINT8, 1, QColor(0,255,0)));
 
347
    m_channelsList.append(new KisChannelInfo(i18n("B"), 2, KisChannelInfo::COLOR, KisChannelInfo::UINT8, 1, QColor(0,0,255)));
 
348
}
 
349
 
 
350
QValueVector<KisChannelInfo *> KisGenericRGBHistogramProducer::channels() {
 
351
    return m_channelsList;
 
352
}
 
353
 
 
354
QString KisGenericRGBHistogramProducer::positionToString(double pos) const {
 
355
    return QString("%1").arg(static_cast<Q_UINT8>(pos * UINT8_MAX));
 
356
}
 
357
 
 
358
double KisGenericRGBHistogramProducer::maximalZoom() const {
 
359
    return 1.0;
 
360
}
 
361
 
 
362
 
 
363
void KisGenericRGBHistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels, KisColorSpace *cs)
 
364
{
 
365
    for (int i = 0; i < m_channels; i++) {
 
366
        m_outRight.at(i) = 0;
 
367
        m_outLeft.at(i) = 0;
 
368
    }
 
369
 
 
370
    QColor c;
 
371
    Q_INT32 pSize = cs->pixelSize();
 
372
    if (selectionMask) {
 
373
        while (nPixels > 0) {
 
374
            if ( !((m_skipUnselected  && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
 
375
                cs->toQColor(pixels, &c);
 
376
                m_bins.at(0).at(c.red())++;
 
377
                m_bins.at(1).at(c.green())++;
 
378
                m_bins.at(2).at(c.blue())++;
 
379
 
 
380
                m_count++;
 
381
            }
 
382
            pixels += pSize;
 
383
            selectionMask++;
 
384
            nPixels--;
 
385
        }
 
386
 
 
387
    }
 
388
    else {
 
389
        while (nPixels > 0) {
 
390
 
 
391
            if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) {
 
392
                cs->toQColor(pixels, &c);
 
393
                m_bins.at(0).at(c.red())++;
 
394
                m_bins.at(1).at(c.green())++;
 
395
                m_bins.at(2).at(c.blue())++;
 
396
 
 
397
                m_count++;
 
398
            }
 
399
            pixels += pSize;
 
400
            nPixels--;
 
401
        }
 
402
    }
 
403
}
 
404
 
 
405
// ------------ Generic L*a*b* ---------------------
 
406
KisGenericLabHistogramProducer::KisGenericLabHistogramProducer()
 
407
    : KisBasicHistogramProducer(KisID("GENLABHISTO", i18n("L*a*b* Histogram")), 3, 256, 0) {
 
408
    /* we set 0 as colorspace, because we are not based on a specific colorspace. This
 
409
       is no problem for the superclass since we override channels() */
 
410
    m_channelsList.append(new KisChannelInfo(i18n("L*"), 0, KisChannelInfo::COLOR, KisChannelInfo::UINT8));
 
411
    m_channelsList.append(new KisChannelInfo(i18n("a*"), 1, KisChannelInfo::COLOR, KisChannelInfo::UINT8));
 
412
    m_channelsList.append(new KisChannelInfo(i18n("b*"), 2, KisChannelInfo::COLOR, KisChannelInfo::UINT8));
 
413
 
 
414
    if (!m_labCs) {
 
415
        KisProfile *labProfile = new KisProfile(cmsCreateLabProfile(NULL));
 
416
        m_labCs = new KisLabColorSpace(0, labProfile);
 
417
    }
 
418
    m_colorSpace = m_labCs;
 
419
}
 
420
KisGenericLabHistogramProducer::~KisGenericLabHistogramProducer()
 
421
{
 
422
    delete m_channelsList[0];
 
423
    delete m_channelsList[1];
 
424
    delete m_channelsList[2];
 
425
}
 
426
 
 
427
QValueVector<KisChannelInfo *> KisGenericLabHistogramProducer::channels() {
 
428
    return m_channelsList;
 
429
}
 
430
 
 
431
QString KisGenericLabHistogramProducer::positionToString(double pos) const {
 
432
    return QString("%1").arg(static_cast<Q_UINT16>(pos * UINT16_MAX));
 
433
}
 
434
 
 
435
double KisGenericLabHistogramProducer::maximalZoom() const {
 
436
    return 1.0;
 
437
}
 
438
 
 
439
 
 
440
void KisGenericLabHistogramProducer::addRegionToBin(Q_UINT8 * pixels, Q_UINT8 * selectionMask, Q_UINT32 nPixels,  KisColorSpace *cs)
 
441
{
 
442
    for (int i = 0; i < m_channels; i++) {
 
443
        m_outRight.at(i) = 0;
 
444
        m_outLeft.at(i) = 0;
 
445
    }
 
446
 
 
447
    Q_UINT8 dst[8];
 
448
    Q_INT32 pSize = cs->pixelSize();
 
449
 
 
450
    if (selectionMask) {
 
451
        while (nPixels > 0) {
 
452
            if ( !((m_skipUnselected  && *selectionMask == 0) || (m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT)) ) {
 
453
/*
 
454
  cs->toQColor(pixels, &c);
 
455
  m_bins.at(0).at(c.red())++;
 
456
*/
 
457
                m_count++;
 
458
            }
 
459
            pixels += pSize;
 
460
            selectionMask++;
 
461
            nPixels--;
 
462
        }
 
463
    }
 
464
    else {
 
465
        while (nPixels > 0) {
 
466
            if ( !(m_skipTransparent && cs->getAlpha(pixels) == OPACITY_TRANSPARENT))  {
 
467
 
 
468
  cs->convertPixelsTo(pixels, dst, m_colorSpace, 1);
 
469
  m_bins.at(0).at(m_colorSpace->scaleToU8(dst, 0))++;
 
470
  m_bins.at(1).at(m_colorSpace->scaleToU8(dst, 1))++;
 
471
  m_bins.at(2).at(m_colorSpace->scaleToU8(dst, 2))++;
 
472
 
 
473
                m_count++;
 
474
            }
 
475
            pixels += pSize;
 
476
            nPixels--;
 
477
        }
 
478
    }
 
479
}
 
480