~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to core/libs/dimg/filters/levels/imagelevels.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer, Rohan Garg, Philip Muškovac, Felix Geyer
  • Date: 2011-09-23 18:18:55 UTC
  • mfrom: (1.2.36 upstream)
  • Revision ID: package-import@ubuntu.com-20110923181855-ifs67wxkugshev9k
Tags: 2:2.1.1-0ubuntu1
[ Rohan Garg ]
* New upstream release (LP: #834190)
  - debian/control
    + Build with libqtwebkit-dev
 - debian/kipi-plugins-common
    + Install libkvkontakte required by kipi-plugins
 - debian/digikam
    + Install panoramagui

[ Philip Muškovac ]
* New upstream release
  - debian/control:
    + Add libcv-dev, libcvaux-dev, libhighgui-dev, libboost-graph1.46-dev,
      libksane-dev, libxml2-dev, libxslt-dev, libqt4-opengl-dev, libqjson-dev,
      libgpod-dev and libqca2-dev to build-deps
    + Add packages for kipi-plugins, libmediawiki, libkface, libkgeomap and
      libkvkontakte
  - debian/rules:
    + Don't build with gphoto2 since it doesn't build with it.
  - Add kubuntu_fix_test_linking.diff to fix linking of the dngconverter test
  - update install files
  - update kubuntu_01_mysqld_executable_name.diff for new cmake layout
    and rename to kubuntu_mysqld_executable_name.diff
* Fix typo in digikam-data description (LP: #804894)
* Fix Vcs links

[ Felix Geyer ]
* Move library data files to the new packages libkface-data, libkgeomap-data
  and libkvkontakte-data.
* Override version of the embedded library packages to 1.0~digikam<version>.
* Exclude the library packages from digikam-dbg to prevent file conflicts in
  the future.
* Call dh_install with --list-missing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ============================================================
 
2
 *
 
3
 * This file is a part of digiKam project
 
4
 * http://www.digikam.org
 
5
 *
 
6
 * Date        : 2004-07-29
 
7
 * Description : image levels manipulation methods.
 
8
 *
 
9
 * Copyright (C) 2004-2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
 
10
 *
 
11
 * Some code parts are inspired from gimp 2.0
 
12
 * app/base/levels.c, gimplut.c, and app/base/gimpleveltool.c
 
13
 * source files.
 
14
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
15
 *
 
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)
 
20
 * any later version.
 
21
 *
 
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.
 
26
 *
 
27
 * ============================================================ */
 
28
 
 
29
/*  Map RGB to intensity  */
 
30
 
 
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)
 
37
 
 
38
#include "imagelevels.h"
 
39
 
 
40
// Qt includes
 
41
 
 
42
#include <QFile>
 
43
 
 
44
// C++ includes
 
45
 
 
46
#include <cstdio>
 
47
#include <cmath>
 
48
#include <cstring>
 
49
#include <cstdlib>
 
50
#include <cerrno>
 
51
 
 
52
// KDE includes
 
53
 
 
54
#include <kdebug.h>
 
55
 
 
56
// Local includes
 
57
 
 
58
#include "imagehistogram.h"
 
59
#include "globals.h"
 
60
 
 
61
namespace Digikam
 
62
{
 
63
 
 
64
class ImageLevels::ImageLevelsPriv
 
65
{
 
66
 
 
67
public:
 
68
 
 
69
    enum PixelType
 
70
    {
 
71
        RedPixel = 0,
 
72
        GreenPixel,
 
73
        BluePixel,
 
74
        AlphaPixel
 
75
    };
 
76
 
 
77
    struct _Levels
 
78
    {
 
79
        double gamma[5];
 
80
 
 
81
        int    low_input[5];
 
82
        int    high_input[5];
 
83
 
 
84
        int    low_output[5];
 
85
        int    high_output[5];
 
86
    };
 
87
 
 
88
    struct _Lut
 
89
    {
 
90
        unsigned short** luts;
 
91
        int              nchannels;
 
92
    };
 
93
 
 
94
public:
 
95
 
 
96
    ImageLevelsPriv()
 
97
    {
 
98
        levels = 0;
 
99
        lut    = 0;
 
100
        dirty  = false;
 
101
    }
 
102
 
 
103
    // Levels data.
 
104
    struct _Levels* levels;
 
105
 
 
106
    // Lut data.
 
107
    struct _Lut*    lut;
 
108
 
 
109
    bool            sixteenBit;
 
110
    bool            dirty;
 
111
};
 
112
 
 
113
ImageLevels::ImageLevels(bool sixteenBit)
 
114
    : d(new ImageLevelsPriv)
 
115
{
 
116
    d->lut        = new ImageLevelsPriv::_Lut;
 
117
    d->levels     = new ImageLevelsPriv::_Levels;
 
118
    d->sixteenBit = sixteenBit;
 
119
 
 
120
    memset(d->levels, 0, sizeof(struct ImageLevelsPriv::_Levels));
 
121
    d->lut->luts      = NULL;
 
122
    d->lut->nchannels = 0;
 
123
 
 
124
    reset();
 
125
}
 
126
 
 
127
ImageLevels::~ImageLevels()
 
128
{
 
129
    if (d->lut)
 
130
    {
 
131
        if (d->lut->luts)
 
132
        {
 
133
            for (int i = 0 ; i < d->lut->nchannels ; ++i)
 
134
            {
 
135
                delete [] d->lut->luts[i];
 
136
            }
 
137
 
 
138
            delete [] d->lut->luts;
 
139
        }
 
140
 
 
141
        delete d->lut;
 
142
    }
 
143
 
 
144
    if (d->levels)
 
145
    {
 
146
        delete d->levels;
 
147
    }
 
148
 
 
149
    delete d;
 
150
}
 
151
 
 
152
bool ImageLevels::isDirty()
 
153
{
 
154
    return d->dirty;
 
155
}
 
156
 
 
157
bool ImageLevels::isSixteenBits()
 
158
{
 
159
    return d->sixteenBit;
 
160
}
 
161
 
 
162
void ImageLevels::reset()
 
163
{
 
164
    for (int channel = 0 ; channel < 5 ; ++channel)
 
165
    {
 
166
        levelsChannelReset(channel);
 
167
    }
 
168
}
 
169
 
 
170
void ImageLevels::levelsChannelReset(int channel)
 
171
{
 
172
    if (!d->levels)
 
173
    {
 
174
        return;
 
175
    }
 
176
 
 
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;
 
182
    d->dirty = false;
 
183
}
 
184
 
 
185
void ImageLevels::levelsAuto(ImageHistogram* hist)
 
186
{
 
187
    if (!d->levels || !hist)
 
188
    {
 
189
        return;
 
190
    }
 
191
 
 
192
    levelsChannelReset(LuminosityChannel);
 
193
 
 
194
    for (int channel = RedChannel ;
 
195
         channel <= BlueChannel ;
 
196
         ++channel)
 
197
    {
 
198
        levelsChannelAuto(hist, channel);
 
199
    }
 
200
 
 
201
    d->dirty = true;
 
202
}
 
203
 
 
204
void ImageLevels::levelsChannelAuto(ImageHistogram* hist, int channel)
 
205
{
 
206
    int    i;
 
207
    double count, new_count, percentage, next_percentage;
 
208
 
 
209
    if (!d->levels || !hist)
 
210
    {
 
211
        return;
 
212
    }
 
213
 
 
214
    d->levels->gamma[channel]       = 1.0;
 
215
    d->levels->low_output[channel]  = 0;
 
216
    d->levels->high_output[channel] = d->sixteenBit ? 65535 : 255;
 
217
 
 
218
    count = hist->getCount(channel, 0, d->sixteenBit ? 65535 : 255);
 
219
 
 
220
    if (count == 0.0)
 
221
    {
 
222
        d->levels->low_input[channel]  = 0;
 
223
        d->levels->high_input[channel] = 0;
 
224
    }
 
225
    else
 
226
    {
 
227
        //  Set the low input
 
228
 
 
229
        new_count = 0.0;
 
230
 
 
231
        for (i = 0 ; i < (d->sixteenBit ? 65535 : 255) ; ++i)
 
232
        {
 
233
            new_count       += hist->getValue(channel, i);
 
234
            percentage      = new_count / count;
 
235
            next_percentage = (new_count + hist->getValue(channel, i + 1)) / count;
 
236
 
 
237
            if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
 
238
            {
 
239
                d->levels->low_input[channel] = i + 1;
 
240
                break;
 
241
            }
 
242
        }
 
243
 
 
244
        //  Set the high input
 
245
 
 
246
        new_count = 0.0;
 
247
 
 
248
        for (i = (d->sixteenBit ? 65535 : 255) ; i > 0 ; --i)
 
249
        {
 
250
            new_count       += hist->getValue(channel, i);
 
251
            percentage      = new_count / count;
 
252
            next_percentage = (new_count + hist->getValue(channel, i - 1)) / count;
 
253
 
 
254
            if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
 
255
            {
 
256
                d->levels->high_input[channel] = i - 1;
 
257
                break;
 
258
            }
 
259
        }
 
260
    }
 
261
 
 
262
    d->dirty = true;
 
263
}
 
264
 
 
265
int ImageLevels::levelsInputFromColor(int channel, const DColor& color)
 
266
{
 
267
    switch (channel)
 
268
    {
 
269
        case LuminosityChannel:
 
270
            return qMax (qMax (color.red(), color.green()), color.blue());
 
271
 
 
272
        case RedChannel:
 
273
            return color.red();
 
274
 
 
275
        case GreenChannel:
 
276
            return color.green();
 
277
 
 
278
        case BlueChannel:
 
279
            return color.blue();
 
280
    }
 
281
 
 
282
    return 0;  // just to please the compiler.
 
283
}
 
284
 
 
285
void ImageLevels::levelsBlackToneAdjustByColors(int channel, const DColor& color)
 
286
{
 
287
    if (!d->levels)
 
288
    {
 
289
        return;
 
290
    }
 
291
 
 
292
    d->levels->low_input[channel] = levelsInputFromColor(channel, color);
 
293
    d->dirty = true;
 
294
}
 
295
 
 
296
void ImageLevels::levelsWhiteToneAdjustByColors(int channel, const DColor& color)
 
297
{
 
298
    if (!d->levels)
 
299
    {
 
300
        return;
 
301
    }
 
302
 
 
303
    d->levels->high_input[channel] = levelsInputFromColor(channel, color);
 
304
    d->dirty = true;
 
305
}
 
306
 
 
307
void ImageLevels::levelsGrayToneAdjustByColors(int channel, const DColor& color)
 
308
{
 
309
    if (!d->levels)
 
310
    {
 
311
        return;
 
312
    }
 
313
 
 
314
    int            input;
 
315
    int            range;
 
316
    double         inten;
 
317
    double         out_light;
 
318
    unsigned short lightness;
 
319
 
 
320
    // Calculate lightness value.
 
321
 
 
322
    lightness = (unsigned short)LEVELS_RGB_INTENSITY (color.red(), color.green(), color.blue());
 
323
 
 
324
    input     = levelsInputFromColor(channel, color);
 
325
 
 
326
    range     = d->levels->high_input[channel] - d->levels->low_input[channel];
 
327
 
 
328
    if (range <= 0)
 
329
    {
 
330
        return;
 
331
    }
 
332
 
 
333
    input -= d->levels->low_input[channel];
 
334
 
 
335
    if (input < 0)
 
336
    {
 
337
        return;
 
338
    }
 
339
 
 
340
    // Normalize input and lightness.
 
341
 
 
342
    inten     = (double) input / (double) range;
 
343
    out_light = (double) lightness/ (double) range;
 
344
 
 
345
    if (out_light <= 0)
 
346
    {
 
347
        return;
 
348
    }
 
349
 
 
350
    // Map selected color to corresponding lightness.
 
351
 
 
352
    d->levels->gamma[channel] = log (inten) / log (out_light);
 
353
    d->dirty = true;
 
354
}
 
355
 
 
356
void ImageLevels::levelsCalculateTransfers()
 
357
{
 
358
    double inten;
 
359
    int    i, j;
 
360
 
 
361
    if (!d->levels)
 
362
    {
 
363
        return;
 
364
    }
 
365
 
 
366
    // Recalculate the levels arrays.
 
367
 
 
368
    for (j = 0 ; j < 5 ; ++j)
 
369
    {
 
370
        for (i = 0; i <= (d->sixteenBit ? 65535 : 255); ++i)
 
371
        {
 
372
            //  determine input intensity.
 
373
 
 
374
            if (d->levels->high_input[j] != d->levels->low_input[j])
 
375
            {
 
376
                inten = ((double) (i - d->levels->low_input[j]) /
 
377
                         (double) (d->levels->high_input[j] - d->levels->low_input[j]));
 
378
            }
 
379
            else
 
380
            {
 
381
                inten = (double) (i - d->levels->low_input[j]);
 
382
            }
 
383
 
 
384
            inten = CLAMP (inten, 0.0, 1.0);
 
385
 
 
386
            if (d->levels->gamma[j] != 0.0)
 
387
            {
 
388
                inten = pow (inten, (1.0 / d->levels->gamma[j]));
 
389
            }
 
390
        }
 
391
    }
 
392
}
 
393
 
 
394
float ImageLevels::levelsLutFunc(int n_channels, int channel, float value)
 
395
{
 
396
    double inten;
 
397
    int    j;
 
398
 
 
399
    if (!d->levels)
 
400
    {
 
401
        return 0.0;
 
402
    }
 
403
 
 
404
    if (n_channels == 1)
 
405
    {
 
406
        j = 0;
 
407
    }
 
408
    else
 
409
    {
 
410
        j = channel + 1;
 
411
    }
 
412
 
 
413
    inten = value;
 
414
 
 
415
    // For color  images this runs through the loop with j = channel +1
 
416
    // the first time and j = 0 the second time.
 
417
    //
 
418
    // For bw images this runs through the loop with j = 0 the first and
 
419
    // only time.
 
420
 
 
421
    for ( ; j >= 0 ; j -= (channel + 1) )
 
422
    {
 
423
        // Don't apply the overall curve to the alpha channel.
 
424
 
 
425
        if (j == 0 && (n_channels == 2 || n_channels == 4)
 
426
            && channel == n_channels -1)
 
427
        {
 
428
            return inten;
 
429
        }
 
430
 
 
431
        //  Determine input intensity.
 
432
 
 
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]));
 
436
        else
 
437
        {
 
438
            inten = (double) ((float)(d->sixteenBit ? 65535 : 255) * inten - d->levels->low_input[j]);
 
439
        }
 
440
 
 
441
        if (d->levels->gamma[j] != 0.0)
 
442
        {
 
443
            if (inten >= 0.0)
 
444
            {
 
445
                inten =  pow ( inten, (1.0 / d->levels->gamma[j]));
 
446
            }
 
447
            else
 
448
            {
 
449
                inten = -pow (-inten, (1.0 / d->levels->gamma[j]));
 
450
            }
 
451
        }
 
452
 
 
453
        //  determine the output intensity.
 
454
 
 
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]);
 
458
 
 
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]));
 
462
 
 
463
        inten /= (float)(d->sixteenBit ? 65535 : 255);
 
464
    }
 
465
 
 
466
    return inten;
 
467
}
 
468
 
 
469
void ImageLevels::levelsLutSetup(int nchannels)
 
470
{
 
471
    int    i;
 
472
    uint   v;
 
473
    double val;
 
474
 
 
475
    if (d->lut->luts)
 
476
    {
 
477
        for (i = 0 ; i < d->lut->nchannels ; ++i)
 
478
        {
 
479
            delete [] d->lut->luts[i];
 
480
        }
 
481
 
 
482
        delete [] d->lut->luts;
 
483
    }
 
484
 
 
485
    d->lut->nchannels = nchannels;
 
486
    d->lut->luts      = new unsigned short*[d->lut->nchannels];
 
487
 
 
488
    for (i = 0 ; i < d->lut->nchannels ; ++i)
 
489
    {
 
490
        d->lut->luts[i] = new unsigned short[(d->sixteenBit ? 65535 : 255) + 1];
 
491
 
 
492
        for (v = 0 ; v <= (uint)(d->sixteenBit ? 65535 : 255) ; ++v)
 
493
        {
 
494
            // to add gamma correction use func(v ^ g) ^ 1/g instead.
 
495
 
 
496
            val = (float)(d->sixteenBit ? 65535 : 255) *
 
497
                  levelsLutFunc( d->lut->nchannels, i, v/(float)(d->sixteenBit ? 65535 : 255)) + 0.5;
 
498
 
 
499
            d->lut->luts[i][v] = (unsigned short)CLAMP(val, 0.0, (d->sixteenBit ? 65535.0 : 255.0));
 
500
        }
 
501
    }
 
502
}
 
503
 
 
504
void ImageLevels::levelsLutProcess(uchar* srcPR, uchar* destPR, int w, int h)
 
505
{
 
506
    unsigned short* lut0 = NULL, *lut1 = NULL, *lut2 = NULL, *lut3 = NULL;
 
507
 
 
508
    int   i;
 
509
 
 
510
    if (d->lut->nchannels > 0)
 
511
    {
 
512
        lut0 = d->lut->luts[0];
 
513
    }
 
514
 
 
515
    if (d->lut->nchannels > 1)
 
516
    {
 
517
        lut1 = d->lut->luts[1];
 
518
    }
 
519
 
 
520
    if (d->lut->nchannels > 2)
 
521
    {
 
522
        lut2 = d->lut->luts[2];
 
523
    }
 
524
 
 
525
    if (d->lut->nchannels > 3)
 
526
    {
 
527
        lut3 = d->lut->luts[3];
 
528
    }
 
529
 
 
530
    if (!d->sixteenBit)        // 8 bits image.
 
531
    {
 
532
        uchar red, green, blue, alpha;
 
533
        uchar* ptr = srcPR;
 
534
        uchar* dst = destPR;
 
535
 
 
536
        for (i = 0 ; i < w*h ; ++i)
 
537
        {
 
538
            blue  = ptr[0];
 
539
            green = ptr[1];
 
540
            red   = ptr[2];
 
541
            alpha = ptr[3];
 
542
 
 
543
            if ( d->lut->nchannels > 0 )
 
544
            {
 
545
                red = lut0[red];
 
546
            }
 
547
 
 
548
            if ( d->lut->nchannels > 1 )
 
549
            {
 
550
                green = lut1[green];
 
551
            }
 
552
 
 
553
            if ( d->lut->nchannels > 2 )
 
554
            {
 
555
                blue = lut2[blue];
 
556
            }
 
557
 
 
558
            if ( d->lut->nchannels > 3 )
 
559
            {
 
560
                alpha = lut3[alpha];
 
561
            }
 
562
 
 
563
            dst[0] = blue;
 
564
            dst[1] = green;
 
565
            dst[2] = red;
 
566
            dst[3] = alpha;
 
567
 
 
568
            ptr += 4;
 
569
            dst += 4;
 
570
        }
 
571
    }
 
572
    else               // 16 bits image.
 
573
    {
 
574
        unsigned short red, green, blue, alpha;
 
575
        unsigned short* ptr = (unsigned short*)srcPR;
 
576
        unsigned short* dst = (unsigned short*)destPR;
 
577
 
 
578
        for (i = 0 ; i < w*h ; ++i)
 
579
        {
 
580
            blue  = ptr[0];
 
581
            green = ptr[1];
 
582
            red   = ptr[2];
 
583
            alpha = ptr[3];
 
584
 
 
585
            if ( d->lut->nchannels > 0 )
 
586
            {
 
587
                red = lut0[red];
 
588
            }
 
589
 
 
590
            if ( d->lut->nchannels > 1 )
 
591
            {
 
592
                green = lut1[green];
 
593
            }
 
594
 
 
595
            if ( d->lut->nchannels > 2 )
 
596
            {
 
597
                blue = lut2[blue];
 
598
            }
 
599
 
 
600
            if ( d->lut->nchannels > 3 )
 
601
            {
 
602
                alpha = lut3[alpha];
 
603
            }
 
604
 
 
605
            dst[0] = blue;
 
606
            dst[1] = green;
 
607
            dst[2] = red;
 
608
            dst[3] = alpha;
 
609
 
 
610
            ptr += 4;
 
611
            dst += 4;
 
612
        }
 
613
    }
 
614
}
 
615
 
 
616
void ImageLevels::setLevelGammaValue(int channel, double val)
 
617
{
 
618
    if ( d->levels && channel>=0 && channel<5 )
 
619
    {
 
620
        d->levels->gamma[channel] = val;
 
621
        d->dirty = true;
 
622
    }
 
623
}
 
624
 
 
625
void ImageLevels::setLevelLowInputValue(int channel, int val)
 
626
{
 
627
    if ( d->levels && channel>=0 && channel<5 )
 
628
    {
 
629
        d->levels->low_input[channel] = val;
 
630
        d->dirty = true;
 
631
    }
 
632
}
 
633
 
 
634
void ImageLevels::setLevelHighInputValue(int channel, int val)
 
635
{
 
636
    if ( d->levels && channel>=0 && channel<5 )
 
637
    {
 
638
        d->levels->high_input[channel] = val;
 
639
        d->dirty = true;
 
640
    }
 
641
}
 
642
 
 
643
void ImageLevels::setLevelLowOutputValue(int channel, int val)
 
644
{
 
645
    if ( d->levels && channel>=0 && channel<5 )
 
646
    {
 
647
        d->levels->low_output[channel] = val;
 
648
        d->dirty = true;
 
649
    }
 
650
}
 
651
 
 
652
void ImageLevels::setLevelHighOutputValue(int channel, int val)
 
653
{
 
654
    if ( d->levels && channel>=0 && channel<5 )
 
655
    {
 
656
        d->levels->high_output[channel] = val;
 
657
        d->dirty = true;
 
658
    }
 
659
}
 
660
 
 
661
double ImageLevels::getLevelGammaValue(int channel)
 
662
{
 
663
    if ( d->levels && channel>=0 && channel<5 )
 
664
    {
 
665
        return (d->levels->gamma[channel]);
 
666
    }
 
667
 
 
668
    return 0.0;
 
669
}
 
670
 
 
671
int ImageLevels::getLevelLowInputValue(int channel)
 
672
{
 
673
    if ( d->levels && channel>=0 && channel<5 )
 
674
    {
 
675
        return (d->levels->low_input[channel]);
 
676
    }
 
677
 
 
678
    return 0;
 
679
}
 
680
 
 
681
int ImageLevels::getLevelHighInputValue(int channel)
 
682
{
 
683
    if ( d->levels && channel>=0 && channel<5 )
 
684
    {
 
685
        return (d->levels->high_input[channel]);
 
686
    }
 
687
 
 
688
    return 0;
 
689
}
 
690
 
 
691
int ImageLevels::getLevelLowOutputValue(int channel)
 
692
{
 
693
    if ( d->levels && channel>=0 && channel<5 )
 
694
    {
 
695
        return (d->levels->low_output[channel]);
 
696
    }
 
697
 
 
698
    return 0;
 
699
}
 
700
 
 
701
int ImageLevels::getLevelHighOutputValue(int channel)
 
702
{
 
703
    if ( d->levels && channel>=0 && channel<5 )
 
704
    {
 
705
        return (d->levels->high_output[channel]);
 
706
    }
 
707
 
 
708
    return 0;
 
709
}
 
710
 
 
711
bool ImageLevels::loadLevelsFromGimpLevelsFile(const KUrl& fileUrl)
 
712
{
 
713
    // TODO : support KUrl !
 
714
 
 
715
    FILE*   file=0;
 
716
    int     low_input[5];
 
717
    int     high_input[5];
 
718
    int     low_output[5];
 
719
    int     high_output[5];
 
720
    double  gamma[5];
 
721
    int     i, fields;
 
722
    char    buf[50];
 
723
    char*   nptr=0;
 
724
 
 
725
    file = fopen(QFile::encodeName(fileUrl.toLocalFile()), "r");
 
726
 
 
727
    if (!file)
 
728
    {
 
729
        return false;
 
730
    }
 
731
 
 
732
    if (! fgets (buf, sizeof (buf), file))
 
733
    {
 
734
        fclose(file);
 
735
        return false;
 
736
    }
 
737
 
 
738
    if (strcmp (buf, "# GIMP Levels File\n") != 0)
 
739
    {
 
740
        fclose(file);
 
741
        return false;
 
742
    }
 
743
 
 
744
    for (i = 0 ; i < 5 ; ++i)
 
745
    {
 
746
        fields = fscanf (file, "%d %d %d %d ",
 
747
                         &low_input[i],
 
748
                         &high_input[i],
 
749
                         &low_output[i],
 
750
                         &high_output[i]);
 
751
 
 
752
        if (fields != 4)
 
753
        {
 
754
            kWarning() <<  "Invalid Gimp levels file!";
 
755
            fclose(file);
 
756
            return false;
 
757
        }
 
758
 
 
759
        if (!fgets (buf, 50, file))
 
760
        {
 
761
            kWarning() <<  "Invalid Gimp levels file!";
 
762
            fclose(file);
 
763
            return false;
 
764
        }
 
765
 
 
766
        gamma[i] = strtod (buf, &nptr);
 
767
 
 
768
        if (buf == nptr || errno == ERANGE)
 
769
        {
 
770
            kWarning() <<  "Invalid Gimp levels file!";
 
771
            fclose(file);
 
772
            return false;
 
773
        }
 
774
    }
 
775
 
 
776
    for (i = 0 ; i < 5 ; ++i)
 
777
    {
 
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]);
 
783
    }
 
784
 
 
785
    fclose(file);
 
786
    return true;
 
787
}
 
788
 
 
789
bool ImageLevels::saveLevelsToGimpLevelsFile(const KUrl& fileUrl)
 
790
{
 
791
    // TODO : support KUrl !
 
792
 
 
793
    FILE* file=0;
 
794
    int   i;
 
795
 
 
796
    file = fopen(QFile::encodeName(fileUrl.toLocalFile()), "w");
 
797
 
 
798
    if (!file)
 
799
    {
 
800
        return false;
 
801
    }
 
802
 
 
803
    fprintf (file, "# GIMP Levels File\n");
 
804
 
 
805
    for (i = 0 ; i < 5 ; ++i)
 
806
    {
 
807
        char buf[256];
 
808
        sprintf (buf, "%f", getLevelGammaValue(i));
 
809
 
 
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),
 
815
                 buf);
 
816
    }
 
817
 
 
818
    fflush(file);
 
819
    fclose(file);
 
820
 
 
821
    return true;
 
822
}
 
823
 
 
824
}  // namespace Digikam