1
/* ============================================================
3
* This file is a part of digiKam project
4
* http://www.digikam.org
7
* Description : image levels manipulation methods.
9
* Copyright (C) 2004-2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
11
* Some code parts are inspired from gimp 2.0
12
* app/base/levels.c, gimplut.c, and app/base/gimpleveltool.c
14
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
16
* This program is free software; you can redistribute it
17
* and/or modify it under the terms of the GNU General
18
* Public License as published by the Free Software Foundation;
19
* either version 2, or (at your option)
22
* This program is distributed in the hope that it will be useful,
23
* but WITHOUT ANY WARRANTY; without even the implied warranty of
24
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
* GNU General Public License for more details.
27
* ============================================================ */
29
/* Map RGB to intensity */
31
#define LEVELS_RGB_INTENSITY_RED 0.30
32
#define LEVELS_RGB_INTENSITY_GREEN 0.59
33
#define LEVELS_RGB_INTENSITY_BLUE 0.11
34
#define LEVELS_RGB_INTENSITY(r,g,b) ((r) * LEVELS_RGB_INTENSITY_RED + \
35
(g) * LEVELS_RGB_INTENSITY_GREEN + \
36
(b) * LEVELS_RGB_INTENSITY_BLUE)
38
#include "imagelevels.h"
58
#include "imagehistogram.h"
64
class ImageLevels::ImageLevelsPriv
90
unsigned short** luts;
104
struct _Levels* levels;
113
ImageLevels::ImageLevels(bool sixteenBit)
114
: d(new ImageLevelsPriv)
116
d->lut = new ImageLevelsPriv::_Lut;
117
d->levels = new ImageLevelsPriv::_Levels;
118
d->sixteenBit = sixteenBit;
120
memset(d->levels, 0, sizeof(struct ImageLevelsPriv::_Levels));
122
d->lut->nchannels = 0;
127
ImageLevels::~ImageLevels()
133
for (int i = 0 ; i < d->lut->nchannels ; ++i)
135
delete [] d->lut->luts[i];
138
delete [] d->lut->luts;
152
bool ImageLevels::isDirty()
157
bool ImageLevels::isSixteenBits()
159
return d->sixteenBit;
162
void ImageLevels::reset()
164
for (int channel = 0 ; channel < 5 ; ++channel)
166
levelsChannelReset(channel);
170
void ImageLevels::levelsChannelReset(int channel)
177
d->levels->gamma[channel] = 1.0;
178
d->levels->low_input[channel] = 0;
179
d->levels->high_input[channel] = d->sixteenBit ? 65535 : 255;
180
d->levels->low_output[channel] = 0;
181
d->levels->high_output[channel] = d->sixteenBit ? 65535 : 255;
185
void ImageLevels::levelsAuto(ImageHistogram* hist)
187
if (!d->levels || !hist)
192
levelsChannelReset(LuminosityChannel);
194
for (int channel = RedChannel ;
195
channel <= BlueChannel ;
198
levelsChannelAuto(hist, channel);
204
void ImageLevels::levelsChannelAuto(ImageHistogram* hist, int channel)
207
double count, new_count, percentage, next_percentage;
209
if (!d->levels || !hist)
214
d->levels->gamma[channel] = 1.0;
215
d->levels->low_output[channel] = 0;
216
d->levels->high_output[channel] = d->sixteenBit ? 65535 : 255;
218
count = hist->getCount(channel, 0, d->sixteenBit ? 65535 : 255);
222
d->levels->low_input[channel] = 0;
223
d->levels->high_input[channel] = 0;
231
for (i = 0 ; i < (d->sixteenBit ? 65535 : 255) ; ++i)
233
new_count += hist->getValue(channel, i);
234
percentage = new_count / count;
235
next_percentage = (new_count + hist->getValue(channel, i + 1)) / count;
237
if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
239
d->levels->low_input[channel] = i + 1;
244
// Set the high input
248
for (i = (d->sixteenBit ? 65535 : 255) ; i > 0 ; --i)
250
new_count += hist->getValue(channel, i);
251
percentage = new_count / count;
252
next_percentage = (new_count + hist->getValue(channel, i - 1)) / count;
254
if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
256
d->levels->high_input[channel] = i - 1;
265
int ImageLevels::levelsInputFromColor(int channel, const DColor& color)
269
case LuminosityChannel:
270
return qMax (qMax (color.red(), color.green()), color.blue());
276
return color.green();
282
return 0; // just to please the compiler.
285
void ImageLevels::levelsBlackToneAdjustByColors(int channel, const DColor& color)
292
d->levels->low_input[channel] = levelsInputFromColor(channel, color);
296
void ImageLevels::levelsWhiteToneAdjustByColors(int channel, const DColor& color)
303
d->levels->high_input[channel] = levelsInputFromColor(channel, color);
307
void ImageLevels::levelsGrayToneAdjustByColors(int channel, const DColor& color)
318
unsigned short lightness;
320
// Calculate lightness value.
322
lightness = (unsigned short)LEVELS_RGB_INTENSITY (color.red(), color.green(), color.blue());
324
input = levelsInputFromColor(channel, color);
326
range = d->levels->high_input[channel] - d->levels->low_input[channel];
333
input -= d->levels->low_input[channel];
340
// Normalize input and lightness.
342
inten = (double) input / (double) range;
343
out_light = (double) lightness/ (double) range;
350
// Map selected color to corresponding lightness.
352
d->levels->gamma[channel] = log (inten) / log (out_light);
356
void ImageLevels::levelsCalculateTransfers()
366
// Recalculate the levels arrays.
368
for (j = 0 ; j < 5 ; ++j)
370
for (i = 0; i <= (d->sixteenBit ? 65535 : 255); ++i)
372
// determine input intensity.
374
if (d->levels->high_input[j] != d->levels->low_input[j])
376
inten = ((double) (i - d->levels->low_input[j]) /
377
(double) (d->levels->high_input[j] - d->levels->low_input[j]));
381
inten = (double) (i - d->levels->low_input[j]);
384
inten = CLAMP (inten, 0.0, 1.0);
386
if (d->levels->gamma[j] != 0.0)
388
inten = pow (inten, (1.0 / d->levels->gamma[j]));
394
float ImageLevels::levelsLutFunc(int n_channels, int channel, float value)
415
// For color images this runs through the loop with j = channel +1
416
// the first time and j = 0 the second time.
418
// For bw images this runs through the loop with j = 0 the first and
421
for ( ; j >= 0 ; j -= (channel + 1) )
423
// Don't apply the overall curve to the alpha channel.
425
if (j == 0 && (n_channels == 2 || n_channels == 4)
426
&& channel == n_channels -1)
431
// Determine input intensity.
433
if (d->levels->high_input[j] != d->levels->low_input[j])
434
inten = ((double) ((float)(d->sixteenBit ? 65535 : 255) * inten - d->levels->low_input[j]) /
435
(double) (d->levels->high_input[j] - d->levels->low_input[j]));
438
inten = (double) ((float)(d->sixteenBit ? 65535 : 255) * inten - d->levels->low_input[j]);
441
if (d->levels->gamma[j] != 0.0)
445
inten = pow ( inten, (1.0 / d->levels->gamma[j]));
449
inten = -pow (-inten, (1.0 / d->levels->gamma[j]));
453
// determine the output intensity.
455
if (d->levels->high_output[j] >= d->levels->low_output[j])
456
inten = (double) (inten * (d->levels->high_output[j] -
457
d->levels->low_output[j]) + d->levels->low_output[j]);
459
else if (d->levels->high_output[j] < d->levels->low_output[j])
460
inten = (double) (d->levels->low_output[j] - inten *
461
(d->levels->low_output[j] - d->levels->high_output[j]));
463
inten /= (float)(d->sixteenBit ? 65535 : 255);
469
void ImageLevels::levelsLutSetup(int nchannels)
477
for (i = 0 ; i < d->lut->nchannels ; ++i)
479
delete [] d->lut->luts[i];
482
delete [] d->lut->luts;
485
d->lut->nchannels = nchannels;
486
d->lut->luts = new unsigned short*[d->lut->nchannels];
488
for (i = 0 ; i < d->lut->nchannels ; ++i)
490
d->lut->luts[i] = new unsigned short[(d->sixteenBit ? 65535 : 255) + 1];
492
for (v = 0 ; v <= (uint)(d->sixteenBit ? 65535 : 255) ; ++v)
494
// to add gamma correction use func(v ^ g) ^ 1/g instead.
496
val = (float)(d->sixteenBit ? 65535 : 255) *
497
levelsLutFunc( d->lut->nchannels, i, v/(float)(d->sixteenBit ? 65535 : 255)) + 0.5;
499
d->lut->luts[i][v] = (unsigned short)CLAMP(val, 0.0, (d->sixteenBit ? 65535.0 : 255.0));
504
void ImageLevels::levelsLutProcess(uchar* srcPR, uchar* destPR, int w, int h)
506
unsigned short* lut0 = NULL, *lut1 = NULL, *lut2 = NULL, *lut3 = NULL;
510
if (d->lut->nchannels > 0)
512
lut0 = d->lut->luts[0];
515
if (d->lut->nchannels > 1)
517
lut1 = d->lut->luts[1];
520
if (d->lut->nchannels > 2)
522
lut2 = d->lut->luts[2];
525
if (d->lut->nchannels > 3)
527
lut3 = d->lut->luts[3];
530
if (!d->sixteenBit) // 8 bits image.
532
uchar red, green, blue, alpha;
536
for (i = 0 ; i < w*h ; ++i)
543
if ( d->lut->nchannels > 0 )
548
if ( d->lut->nchannels > 1 )
553
if ( d->lut->nchannels > 2 )
558
if ( d->lut->nchannels > 3 )
572
else // 16 bits image.
574
unsigned short red, green, blue, alpha;
575
unsigned short* ptr = (unsigned short*)srcPR;
576
unsigned short* dst = (unsigned short*)destPR;
578
for (i = 0 ; i < w*h ; ++i)
585
if ( d->lut->nchannels > 0 )
590
if ( d->lut->nchannels > 1 )
595
if ( d->lut->nchannels > 2 )
600
if ( d->lut->nchannels > 3 )
616
void ImageLevels::setLevelGammaValue(int channel, double val)
618
if ( d->levels && channel>=0 && channel<5 )
620
d->levels->gamma[channel] = val;
625
void ImageLevels::setLevelLowInputValue(int channel, int val)
627
if ( d->levels && channel>=0 && channel<5 )
629
d->levels->low_input[channel] = val;
634
void ImageLevels::setLevelHighInputValue(int channel, int val)
636
if ( d->levels && channel>=0 && channel<5 )
638
d->levels->high_input[channel] = val;
643
void ImageLevels::setLevelLowOutputValue(int channel, int val)
645
if ( d->levels && channel>=0 && channel<5 )
647
d->levels->low_output[channel] = val;
652
void ImageLevels::setLevelHighOutputValue(int channel, int val)
654
if ( d->levels && channel>=0 && channel<5 )
656
d->levels->high_output[channel] = val;
661
double ImageLevels::getLevelGammaValue(int channel)
663
if ( d->levels && channel>=0 && channel<5 )
665
return (d->levels->gamma[channel]);
671
int ImageLevels::getLevelLowInputValue(int channel)
673
if ( d->levels && channel>=0 && channel<5 )
675
return (d->levels->low_input[channel]);
681
int ImageLevels::getLevelHighInputValue(int channel)
683
if ( d->levels && channel>=0 && channel<5 )
685
return (d->levels->high_input[channel]);
691
int ImageLevels::getLevelLowOutputValue(int channel)
693
if ( d->levels && channel>=0 && channel<5 )
695
return (d->levels->low_output[channel]);
701
int ImageLevels::getLevelHighOutputValue(int channel)
703
if ( d->levels && channel>=0 && channel<5 )
705
return (d->levels->high_output[channel]);
711
bool ImageLevels::loadLevelsFromGimpLevelsFile(const KUrl& fileUrl)
713
// TODO : support KUrl !
725
file = fopen(QFile::encodeName(fileUrl.toLocalFile()), "r");
732
if (! fgets (buf, sizeof (buf), file))
738
if (strcmp (buf, "# GIMP Levels File\n") != 0)
744
for (i = 0 ; i < 5 ; ++i)
746
fields = fscanf (file, "%d %d %d %d ",
754
kWarning() << "Invalid Gimp levels file!";
759
if (!fgets (buf, 50, file))
761
kWarning() << "Invalid Gimp levels file!";
766
gamma[i] = strtod (buf, &nptr);
768
if (buf == nptr || errno == ERANGE)
770
kWarning() << "Invalid Gimp levels file!";
776
for (i = 0 ; i < 5 ; ++i)
778
setLevelGammaValue(i, gamma[i]);
779
setLevelLowInputValue(i, d->sixteenBit ? low_input[i]*255 : low_input[i]);
780
setLevelHighInputValue(i, d->sixteenBit ? high_input[i]*255 : high_input[i]);
781
setLevelLowOutputValue(i, d->sixteenBit ? low_output[i]*255 : low_output[i]);
782
setLevelHighOutputValue(i, d->sixteenBit ? high_output[i]*255 : high_output[i]);
789
bool ImageLevels::saveLevelsToGimpLevelsFile(const KUrl& fileUrl)
791
// TODO : support KUrl !
796
file = fopen(QFile::encodeName(fileUrl.toLocalFile()), "w");
803
fprintf (file, "# GIMP Levels File\n");
805
for (i = 0 ; i < 5 ; ++i)
808
sprintf (buf, "%f", getLevelGammaValue(i));
810
fprintf (file, "%d %d %d %d %s\n",
811
d->sixteenBit ? getLevelLowInputValue(i)/255 : getLevelLowInputValue(i),
812
d->sixteenBit ? getLevelHighInputValue(i)/255 : getLevelHighInputValue(i),
813
d->sixteenBit ? getLevelLowOutputValue(i)/255 : getLevelLowOutputValue(i),
814
d->sixteenBit ? getLevelHighInputValue(i)/255 : getLevelHighInputValue(i),
824
} // namespace Digikam