~ubuntu-branches/ubuntu/intrepid/digikam/intrepid

« back to all changes in this revision

Viewing changes to digikam/libs/dimg/filters/dimgimagefilters.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-07-17 20:25:39 UTC
  • mfrom: (1.3.2 upstream) (37 hardy)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20080717202539-1bw3w3nrsso7yj4z
* New upstream release
  - digiKam 0.9.4 Release Plan (KDE3) ~ 13 July 08 (Closes: #490144)
* DEB_CONFIGURE_EXTRA_FLAGS := --without-included-sqlite3
* Debhelper compatibility level V7
* Install pixmaps in debian/*.install
* Add debian/digikam.lintian-overrides

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        : 2005-24-01
 
7
 * Description : misc image filters
 
8
 * 
 
9
 * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
 
10
 *
 
11
 * Original Equalise and StretchContrast Algorithms copyright 2002
 
12
 * by Daniel M. Duley <mosfet@kde.org> from KImageEffect API.
 
13
 *
 
14
 * Original Normalize Image algorithm copyrighted 1997 by 
 
15
 * Adam D. Moss <adam@foxbox.org> from Gimp 2.0 implementation.
 
16
 *
 
17
 * Original channel mixer algorithm copyrighted 2002 by 
 
18
 * Martin Guldahl <mguldahl at xmission dot com> from Gimp 2.2 
 
19
 * 
 
20
 * This program is free software; you can redistribute it
 
21
 * and/or modify it under the terms of the GNU General
 
22
 * Public License as published by the Free Software Foundation;
 
23
 * either version 2, or (at your option)
 
24
 * any later version.
 
25
 * 
 
26
 * This program is distributed in the hope that it will be useful,
 
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
29
 * GNU General Public License for more details.
 
30
 * 
 
31
 * ============================================================ */
 
32
 
 
33
// C++ includes.
 
34
 
 
35
#include <cstring>
 
36
#include <cstdlib>
 
37
 
 
38
// Local includes.
 
39
 
 
40
#include "imagehistogram.h"
 
41
#include "imagelevels.h"
 
42
#include "dcolor.h"
 
43
#include "ddebug.h"
 
44
#include "dimggaussianblur.h"
 
45
#include "dimgsharpen.h"
 
46
#include "dimgimagefilters.h"
 
47
 
 
48
namespace Digikam
 
49
{
 
50
 
 
51
/** Performs an histogram equalisation of the image.
 
52
    this method adjusts the brightness of colors across the
 
53
    active image so that the histogram for the value channel
 
54
    is as nearly as possible flat, that is, so that each possible
 
55
    brightness value appears at about the same number of pixels
 
56
    as each other value. Sometimes Equalize works wonderfully at
 
57
    enhancing the contrasts in an image. Other times it gives
 
58
    garbage. It is a very powerful operation, which can either work
 
59
    miracles on an image or destroy it.*/
 
60
void DImgImageFilters::equalizeImage(uchar *data, int w, int h, bool sixteenBit)
 
61
{
 
62
    if (!data || !w || !h)
 
63
    {
 
64
       DWarning() << ("DImgImageFilters::equalizeImage: no image data available!") << endl;
 
65
       return;
 
66
    }
 
67
       
 
68
    struct double_packet  high, low, intensity;
 
69
    struct double_packet *map;
 
70
    struct int_packet    *equalize_map;
 
71
    register long         i;               
 
72
    
 
73
    // Create an histogram of the current image.     
 
74
    ImageHistogram *histogram = new ImageHistogram(data, w, h, sixteenBit);
 
75
    
 
76
    // Memory allocation.
 
77
    map          = new double_packet[histogram->getHistogramSegment()];
 
78
    equalize_map = new int_packet[histogram->getHistogramSegment()];
 
79
    
 
80
    if( !histogram || !map || !equalize_map )
 
81
    {
 
82
       if(histogram)
 
83
           delete histogram;
 
84
       
 
85
       if(map)
 
86
           delete [] map;
 
87
       
 
88
       if(equalize_map)
 
89
           delete [] equalize_map;
 
90
        
 
91
       DWarning() << ("DImgImageFilters::equalizeImage: Unable to allocate memory!") << endl;
 
92
       return;
 
93
    }
 
94
    
 
95
    // Integrate the histogram to get the equalization map.
 
96
     
 
97
    memset(&intensity, 0, sizeof(struct double_packet));
 
98
    memset(&high,      0, sizeof(struct double_packet));            
 
99
    memset(&low,       0, sizeof(struct double_packet));
 
100
    
 
101
    for(i = 0 ; i < histogram->getHistogramSegment() ; i++)
 
102
    {
 
103
       intensity.red   += histogram->getValue(ImageHistogram::RedChannel, i);
 
104
       intensity.green += histogram->getValue(ImageHistogram::GreenChannel, i);
 
105
       intensity.blue  += histogram->getValue(ImageHistogram::BlueChannel, i);
 
106
       intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, i);
 
107
       map[i]          = intensity;
 
108
    }
 
109
 
 
110
    // Stretch the histogram.
 
111
    
 
112
    low  = map[0];
 
113
    high = map[histogram->getHistogramSegment()-1];
 
114
    memset(equalize_map, 0, histogram->getHistogramSegment()*sizeof(int_packet));
 
115
    
 
116
    for(i = 0 ; i < histogram->getHistogramSegment() ; i++)
 
117
    {
 
118
       if(high.red != low.red)
 
119
          equalize_map[i].red = (uint)(((256*histogram->getHistogramSegment() -1) *
 
120
                                (map[i].red-low.red))/(high.red-low.red));
 
121
       
 
122
       if(high.green != low.green)
 
123
          equalize_map[i].green = (uint)(((256*histogram->getHistogramSegment() -1) *
 
124
                                  (map[i].green-low.green))/(high.green-low.green));
 
125
       
 
126
       if(high.blue != low.blue)
 
127
          equalize_map[i].blue = (uint)(((256*histogram->getHistogramSegment() -1) *
 
128
                                 (map[i].blue-low.blue))/(high.blue-low.blue));
 
129
       
 
130
       if(high.alpha != low.alpha)
 
131
          equalize_map[i].alpha = (uint)(((256*histogram->getHistogramSegment() -1) *
 
132
                                  (map[i].alpha-low.alpha))/(high.alpha-low.alpha));
 
133
    }
 
134
    
 
135
    delete histogram;
 
136
    delete [] map;
 
137
    
 
138
    // Apply results to image.
 
139
 
 
140
    if (!sixteenBit)        // 8 bits image.
 
141
    {
 
142
        uchar red, green, blue, alpha;
 
143
        uchar *ptr = data;
 
144
        
 
145
        for (i = 0 ; i < w*h ; i++)
 
146
        {
 
147
            blue  = ptr[0];
 
148
            green = ptr[1];
 
149
            red   = ptr[2];
 
150
            alpha = ptr[3];
 
151
        
 
152
            if(low.red != high.red)
 
153
                red = (equalize_map[red].red)/257;
 
154
                        
 
155
            if(low.green != high.green)
 
156
                green = (equalize_map[green].green)/257;
 
157
                    
 
158
            if(low.blue != high.blue)
 
159
                blue = (equalize_map[blue].blue)/257;
 
160
                    
 
161
            if(low.alpha != high.alpha)
 
162
                alpha = (equalize_map[alpha].alpha)/257;
 
163
                            
 
164
            ptr[0] = blue;
 
165
            ptr[1] = green;
 
166
            ptr[2] = red;
 
167
            ptr[3] = alpha;
 
168
            ptr += 4;
 
169
        }
 
170
    }
 
171
    else               // 16 bits image.
 
172
    {
 
173
        unsigned short red, green, blue, alpha;
 
174
        unsigned short *ptr = (unsigned short *)data;
 
175
        
 
176
        for (i = 0 ; i < w*h ; i++)
 
177
        {
 
178
            blue  = ptr[0];
 
179
            green = ptr[1];
 
180
            red   = ptr[2];
 
181
            alpha = ptr[3];
 
182
        
 
183
            if(low.red != high.red)
 
184
                red = (equalize_map[red].red)/257;
 
185
                        
 
186
            if(low.green != high.green)
 
187
                green = (equalize_map[green].green)/257;
 
188
                    
 
189
            if(low.blue != high.blue)
 
190
                blue = (equalize_map[blue].blue)/257;
 
191
                    
 
192
            if(low.alpha != high.alpha)
 
193
                alpha = (equalize_map[alpha].alpha)/257;
 
194
                            
 
195
            ptr[0] = blue;
 
196
            ptr[1] = green;
 
197
            ptr[2] = red;
 
198
            ptr[3] = alpha;
 
199
            ptr += 4;
 
200
        }
 
201
    }
 
202
    
 
203
    delete [] equalize_map;
 
204
}
 
205
 
 
206
/** Performs histogram normalization of the image. The algorithm normalizes
 
207
    the pixel values from an image for to span the full range
 
208
    of color values. This is a contrast enhancement technique.*/
 
209
void DImgImageFilters::stretchContrastImage(uchar *data, int w, int h, bool sixteenBit)
 
210
{
 
211
    if (!data || !w || !h)
 
212
    {
 
213
       DWarning() << ("DImgImageFilters::stretchContrastImage: no image data available!") << endl;
 
214
       return;
 
215
    }
 
216
 
 
217
    struct double_packet  high, low, intensity;
 
218
    struct int_packet    *normalize_map;
 
219
    long long             number_pixels;
 
220
    register long         i;
 
221
    unsigned long         threshold_intensity;
 
222
        
 
223
    // Create an histogram of the current image.     
 
224
    ImageHistogram *histogram = new ImageHistogram(data, w, h, sixteenBit);
 
225
    
 
226
    // Memory allocation.
 
227
    normalize_map = new int_packet[histogram->getHistogramSegment()];
 
228
    
 
229
    if( !histogram || !normalize_map )
 
230
    {
 
231
       if(histogram)
 
232
           delete histogram;
 
233
       
 
234
       if(normalize_map)
 
235
           delete [] normalize_map;
 
236
        
 
237
       DWarning() << ("DImgImageFilters::stretchContrastImage: Unable to allocate memory!") << endl;
 
238
       return;
 
239
    }
 
240
 
 
241
    // Find the histogram boundaries by locating the 0.1 percent levels.
 
242
    
 
243
    number_pixels = (long long)(w*h);
 
244
    threshold_intensity = number_pixels / 1000;
 
245
 
 
246
    memset(&high, 0, sizeof(struct double_packet));            
 
247
    memset(&low,  0, sizeof(struct double_packet));
 
248
        
 
249
    // Red. 
 
250
    
 
251
    memset(&intensity, 0, sizeof(struct double_packet));
 
252
    
 
253
    for(high.red = histogram->getHistogramSegment()-1 ; high.red != 0 ; high.red--)
 
254
    {
 
255
       intensity.red += histogram->getValue(ImageHistogram::RedChannel, (int)high.red);
 
256
       
 
257
       if( intensity.red > threshold_intensity )
 
258
          break;
 
259
    }
 
260
    
 
261
    if( low.red == high.red )
 
262
    {
 
263
       threshold_intensity = 0;
 
264
       memset(&intensity, 0, sizeof(struct double_packet));
 
265
        
 
266
       for(low.red = 0 ; low.red < histogram->getHistogramSegment()-1 ; low.red++)
 
267
       {
 
268
          intensity.red += histogram->getValue(ImageHistogram::RedChannel, (int)low.red);
 
269
          
 
270
          if( intensity.red > threshold_intensity )
 
271
              break;
 
272
       }
 
273
       
 
274
       memset(&intensity, 0, sizeof(struct double_packet));
 
275
       
 
276
       for(high.red = histogram->getHistogramSegment()-1 ; high.red != 0 ; high.red--)
 
277
       {
 
278
          intensity.red += histogram->getValue(ImageHistogram::RedChannel, (int)high.red);
 
279
          
 
280
          if( intensity.red > threshold_intensity )
 
281
             break;
 
282
       }
 
283
    }
 
284
 
 
285
    // Green.
 
286
    
 
287
    memset(&intensity, 0, sizeof(struct double_packet));
 
288
    
 
289
    for(high.green = histogram->getHistogramSegment()-1 ; high.green != 0 ; high.green--)
 
290
    {
 
291
       intensity.green += histogram->getValue(ImageHistogram::GreenChannel, (int)high.green);
 
292
       
 
293
       if( intensity.green > threshold_intensity )
 
294
          break;
 
295
    }
 
296
    
 
297
    if( low.green == high.green )
 
298
    {
 
299
       threshold_intensity = 0;
 
300
       memset(&intensity, 0, sizeof(struct double_packet));
 
301
       
 
302
       for(low.green = 0 ; low.green < histogram->getHistogramSegment()-1 ; low.green++)
 
303
       {
 
304
          intensity.green += histogram->getValue(ImageHistogram::GreenChannel, (int)low.green);
 
305
          
 
306
          if( intensity.green > threshold_intensity )
 
307
             break;
 
308
       }
 
309
       
 
310
       memset(&intensity, 0, sizeof(struct double_packet));
 
311
       
 
312
       for(high.green = histogram->getHistogramSegment()-1 ; high.green != 0 ; high.green--)
 
313
       {
 
314
          intensity.green += histogram->getValue(ImageHistogram::GreenChannel, (int)high.green);
 
315
          
 
316
          if( intensity.green > threshold_intensity )
 
317
             break;
 
318
       }
 
319
    }
 
320
 
 
321
    // Blue.
 
322
    
 
323
    memset(&intensity, 0, sizeof(struct double_packet));
 
324
    
 
325
    for(high.blue = histogram->getHistogramSegment()-1 ; high.blue != 0 ; high.blue--)
 
326
    {
 
327
       intensity.blue += histogram->getValue(ImageHistogram::BlueChannel, (int)high.blue);
 
328
       
 
329
       if( intensity.blue > threshold_intensity )
 
330
          break;
 
331
    }
 
332
       
 
333
    if( low.blue == high.blue )
 
334
    {
 
335
       threshold_intensity = 0;
 
336
       memset(&intensity, 0, sizeof(struct double_packet));
 
337
        
 
338
       for(low.blue = 0 ; low.blue < histogram->getHistogramSegment()-1 ; low.blue++)
 
339
       {
 
340
          intensity.blue += histogram->getValue(ImageHistogram::BlueChannel, (int)low.blue);
 
341
          
 
342
          if( intensity.blue > threshold_intensity )
 
343
              break;
 
344
       }
 
345
       
 
346
       memset(&intensity, 0, sizeof(struct double_packet));
 
347
       
 
348
       for(high.blue = histogram->getHistogramSegment()-1 ; high.blue != 0 ; high.blue--)
 
349
       {
 
350
          intensity.blue += histogram->getValue(ImageHistogram::BlueChannel, (int)high.blue);
 
351
          
 
352
          if( intensity.blue > threshold_intensity )
 
353
             break;
 
354
       }
 
355
    }
 
356
 
 
357
    // Alpha.
 
358
    
 
359
    memset(&intensity, 0, sizeof(struct double_packet));
 
360
    
 
361
    for(high.alpha = histogram->getHistogramSegment()-1 ; high.alpha != 0 ; high.alpha--)
 
362
    {
 
363
       intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, (int)high.alpha);
 
364
       
 
365
       if( intensity.alpha > threshold_intensity )
 
366
          break;
 
367
    }
 
368
       
 
369
    if( low.alpha == high.alpha )
 
370
    {
 
371
       threshold_intensity = 0;
 
372
       memset(&intensity, 0, sizeof(struct double_packet));
 
373
       
 
374
       for(low.alpha = 0 ; low.alpha < histogram->getHistogramSegment()-1 ; low.alpha++)
 
375
       {
 
376
          intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, (int)low.alpha);
 
377
          
 
378
          if( intensity.alpha > threshold_intensity )
 
379
             break;
 
380
       }
 
381
       
 
382
       memset(&intensity, 0, sizeof(struct double_packet));
 
383
       
 
384
       for(high.alpha = histogram->getHistogramSegment()-1 ; high.alpha != 0 ; high.alpha--)
 
385
       {
 
386
          intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, (int)high.alpha);
 
387
          
 
388
          if( intensity.alpha > threshold_intensity )
 
389
             break;
 
390
       }
 
391
    }
 
392
    
 
393
    delete histogram;
 
394
 
 
395
    // Stretch the histogram to create the normalized image mapping.
 
396
    
 
397
    memset(normalize_map, 0, histogram->getHistogramSegment()*sizeof(struct int_packet));
 
398
    
 
399
    for(i = 0 ; i <= (long)histogram->getHistogramSegment()-1 ; i++)
 
400
    {
 
401
       if(i < (long) low.red)
 
402
          normalize_map[i].red = 0;
 
403
       else if (i > (long) high.red)
 
404
          normalize_map[i].red = (256*histogram->getHistogramSegment() -1);
 
405
       else if (low.red != high.red)
 
406
          normalize_map[i].red = (int)(((256*histogram->getHistogramSegment() -1)*(i-low.red))/(high.red-low.red));
 
407
 
 
408
       if(i < (long) low.green)
 
409
          normalize_map[i].green = 0;
 
410
       else if (i > (long) high.green)
 
411
          normalize_map[i].green = (256*histogram->getHistogramSegment() -1);
 
412
       else if (low.green != high.green)
 
413
          normalize_map[i].green = (int)(((256*histogram->getHistogramSegment() -1)*(i-low.green))/(high.green-low.green));
 
414
 
 
415
       if(i < (long) low.blue)
 
416
          normalize_map[i].blue = 0;
 
417
       else if (i > (long) high.blue)
 
418
          normalize_map[i].blue = (256*histogram->getHistogramSegment() -1);
 
419
       else if (low.blue != high.blue)
 
420
          normalize_map[i].blue = (int)(((256*histogram->getHistogramSegment() -1)*(i-low.blue))/(high.blue-low.blue));
 
421
 
 
422
       if(i < (long) low.alpha)
 
423
          normalize_map[i].alpha = 0;
 
424
       else if (i > (long) high.alpha)
 
425
          normalize_map[i].alpha = (256*histogram->getHistogramSegment() -1);
 
426
       else if (low.alpha != high.alpha)
 
427
          normalize_map[i].alpha = (int)(((256*histogram->getHistogramSegment() -1)*(i-low.alpha))/(high.alpha-low.alpha));
 
428
    }
 
429
 
 
430
    // Apply result to image.
 
431
 
 
432
    if (!sixteenBit)        // 8 bits image.
 
433
    {
 
434
        uchar red, green, blue, alpha;
 
435
        uchar *ptr = data;
 
436
        
 
437
        for (i = 0 ; i < w*h ; i++)
 
438
        {
 
439
            blue  = ptr[0];
 
440
            green = ptr[1];
 
441
            red   = ptr[2];
 
442
            alpha = ptr[3];
 
443
        
 
444
            if(low.red != high.red)
 
445
                red = (normalize_map[red].red)/257;
 
446
                    
 
447
            if(low.green != high.green)
 
448
                green = (normalize_map[green].green)/257;
 
449
                
 
450
            if(low.blue != high.blue)
 
451
                blue = (normalize_map[blue].blue)/257;
 
452
                
 
453
            if(low.alpha != high.alpha)
 
454
                alpha = (normalize_map[alpha].alpha)/257;
 
455
                                
 
456
            ptr[0] = blue;
 
457
            ptr[1] = green;
 
458
            ptr[2] = red;
 
459
            ptr[3] = alpha;
 
460
            ptr += 4;
 
461
        }
 
462
    }
 
463
    else               // 16 bits image.
 
464
    {
 
465
        unsigned short red, green, blue, alpha;
 
466
        unsigned short *ptr = (unsigned short *)data;
 
467
        
 
468
        for (i = 0 ; i < w*h ; i++)
 
469
        {
 
470
            blue  = ptr[0];
 
471
            green = ptr[1];
 
472
            red   = ptr[2];
 
473
            alpha = ptr[3];
 
474
        
 
475
            if(low.red != high.red)
 
476
                red = (normalize_map[red].red)/257;
 
477
                    
 
478
            if(low.green != high.green)
 
479
                green = (normalize_map[green].green)/257;
 
480
                
 
481
            if(low.blue != high.blue)
 
482
                blue = (normalize_map[blue].blue)/257;
 
483
                
 
484
            if(low.alpha != high.alpha)
 
485
                alpha = (normalize_map[alpha].alpha)/257;
 
486
                            
 
487
            ptr[0] = blue;
 
488
            ptr[1] = green;
 
489
            ptr[2] = red;
 
490
            ptr[3] = alpha;
 
491
            ptr += 4;
 
492
        }
 
493
    }
 
494
    
 
495
    delete [] normalize_map;
 
496
}
 
497
 
 
498
/** This method scales brightness values across the active 
 
499
    image so that the darkest point becomes black, and the 
 
500
    brightest point becomes as bright as possible without
 
501
    altering its hue. This is often a magic fix for
 
502
    images that are dim or washed out.*/
 
503
void DImgImageFilters::normalizeImage(uchar *data, int w, int h, bool sixteenBit)
 
504
{
 
505
    NormalizeParam  param;
 
506
    int             x, i;
 
507
    unsigned short  range;
 
508
 
 
509
    int segments = sixteenBit ? 65536 : 256;
 
510
 
 
511
    // Memory allocation.
 
512
 
 
513
    param.lut = new unsigned short[segments];
 
514
 
 
515
    // Find min. and max. values.
 
516
 
 
517
    param.min = segments-1;
 
518
    param.max = 0;
 
519
 
 
520
    if (!sixteenBit)        // 8 bits image.
 
521
    {
 
522
        uchar red, green, blue;
 
523
        uchar *ptr = data;
 
524
        
 
525
        for (i = 0 ; i < w*h ; i++)
 
526
        {
 
527
            blue  = ptr[0];
 
528
            green = ptr[1];
 
529
            red   = ptr[2];
 
530
        
 
531
            if (red < param.min) param.min = red;
 
532
            if (red > param.max) param.max = red;
 
533
    
 
534
            if (green < param.min) param.min = green;
 
535
            if (green > param.max) param.max = green;
 
536
    
 
537
            if (blue < param.min) param.min = blue;
 
538
            if (blue > param.max) param.max = blue;
 
539
 
 
540
            ptr += 4;
 
541
        }
 
542
    }
 
543
    else               // 16 bits image.
 
544
    {
 
545
        unsigned short red, green, blue;
 
546
        unsigned short *ptr = (unsigned short *)data;
 
547
        
 
548
        for (i = 0 ; i < w*h ; i++)
 
549
        {
 
550
            blue  = ptr[0];
 
551
            green = ptr[1];
 
552
            red   = ptr[2];
 
553
        
 
554
            if (red < param.min) param.min = red;
 
555
            if (red > param.max) param.max = red;
 
556
    
 
557
            if (green < param.min) param.min = green;
 
558
            if (green > param.max) param.max = green;
 
559
    
 
560
            if (blue < param.min) param.min = blue;
 
561
            if (blue > param.max) param.max = blue;
 
562
 
 
563
            ptr += 4;
 
564
        }
 
565
    }
 
566
 
 
567
    // Calculate LUT.
 
568
 
 
569
    range = (unsigned short)(param.max - param.min);
 
570
 
 
571
    if (range != 0)
 
572
    {
 
573
       for (x = (int)param.min ; x <= (int)param.max ; x++)
 
574
          param.lut[x] = (unsigned short)((segments-1) * (x - param.min) / range);
 
575
    }
 
576
    else
 
577
       param.lut[(int)param.min] = (unsigned short)param.min;
 
578
 
 
579
    // Apply LUT to image.
 
580
 
 
581
    if (!sixteenBit)        // 8 bits image.
 
582
    {
 
583
        uchar red, green, blue;
 
584
        uchar *ptr = data;
 
585
        
 
586
        for (i = 0 ; i < w*h ; i++)
 
587
        {
 
588
            blue  = ptr[0];
 
589
            green = ptr[1];
 
590
            red   = ptr[2];
 
591
        
 
592
            ptr[0] = param.lut[blue];
 
593
            ptr[1] = param.lut[green];
 
594
            ptr[2] = param.lut[red];
 
595
 
 
596
            ptr += 4;
 
597
        }
 
598
    }
 
599
    else               // 16 bits image.
 
600
    {
 
601
        unsigned short red, green, blue;
 
602
        unsigned short *ptr = (unsigned short *)data;
 
603
        
 
604
        for (i = 0 ; i < w*h ; i++)
 
605
        {
 
606
            blue  = ptr[0];
 
607
            green = ptr[1];
 
608
            red   = ptr[2];
 
609
        
 
610
            ptr[0] = param.lut[blue];
 
611
            ptr[1] = param.lut[green];
 
612
            ptr[2] = param.lut[red];
 
613
 
 
614
            ptr += 4;
 
615
        }
 
616
    }
 
617
 
 
618
     delete [] param.lut;
 
619
}
 
620
 
 
621
/** Performs histogram auto correction of levels.
 
622
    This method maximizes the tonal range in the Red,
 
623
    Green, and Blue channels. It search the image shadow and highlight 
 
624
    limit values and adjust the Red, Green, and Blue channels
 
625
    to a full histogram range.*/
 
626
void DImgImageFilters::autoLevelsCorrectionImage(uchar *data, int w, int h, bool sixteenBit)
 
627
{
 
628
    if (!data || !w || !h)
 
629
    {
 
630
       DWarning() << ("DImgImageFilters::autoLevelsCorrectionImage: no image data available!")
 
631
                   << endl;
 
632
       return;
 
633
    }
 
634
    uchar* desData;
 
635
 
 
636
    // Create the new empty destination image data space.
 
637
    if (sixteenBit)
 
638
       desData = new uchar[w*h*8];
 
639
    else
 
640
       desData = new uchar[w*h*4];
 
641
       
 
642
    // Create an histogram of the current image.     
 
643
    ImageHistogram *histogram = new ImageHistogram(data, w, h, sixteenBit);
 
644
  
 
645
    // Create an empty instance of levels to use.
 
646
    ImageLevels *levels = new ImageLevels(sixteenBit);
 
647
  
 
648
    // Initialize an auto levels correction of the histogram.
 
649
    levels->levelsAuto(histogram);
 
650
 
 
651
    // Calculate the LUT to apply on the image.
 
652
    levels->levelsLutSetup(ImageHistogram::AlphaChannel);
 
653
  
 
654
    // Apply the lut to the image.
 
655
    levels->levelsLutProcess(data, desData, w, h);
 
656
  
 
657
    if (sixteenBit)
 
658
       memcpy (data, desData, w*h*8);
 
659
    else
 
660
       memcpy (data, desData, w*h*4);
 
661
 
 
662
    delete [] desData;
 
663
    delete histogram;
 
664
    delete levels;
 
665
}
 
666
 
 
667
/** Performs image colors inversion. This tool is used for negate image
 
668
    resulting of a positive film scanned.*/
 
669
void DImgImageFilters::invertImage(uchar *data, int w, int h, bool sixteenBit)
 
670
{
 
671
    if (!data || !w || !h)
 
672
    {
 
673
       DWarning() << ("DImgImageFilters::invertImage: no image data available!")
 
674
                   << endl;
 
675
       return;
 
676
    }
 
677
 
 
678
    if (!sixteenBit)        // 8 bits image.
 
679
    {
 
680
        uchar *ptr = data;
 
681
        
 
682
        for (int i = 0 ; i < w*h ; i++)
 
683
        {
 
684
            ptr[0] = 255 - ptr[0];
 
685
            ptr[1] = 255 - ptr[1];
 
686
            ptr[2] = 255 - ptr[2];
 
687
            ptr[3] = 255 - ptr[3];
 
688
            ptr += 4;
 
689
        }
 
690
    }
 
691
    else               // 16 bits image.
 
692
    {
 
693
        unsigned short *ptr = (unsigned short *)data;
 
694
        
 
695
        for (int i = 0 ; i < w*h ; i++)
 
696
        {
 
697
            ptr[0] = 65535 - ptr[0];
 
698
            ptr[1] = 65535 - ptr[1];
 
699
            ptr[2] = 65535 - ptr[2];
 
700
            ptr[3] = 65535 - ptr[3];
 
701
            ptr += 4;
 
702
        }
 
703
    }
 
704
}
 
705
 
 
706
/** Mix RGB channel color from image*/
 
707
void DImgImageFilters::channelMixerImage(uchar *data, int Width, int Height, bool sixteenBit,
 
708
                                         bool bPreserveLum, bool bMonochrome,
 
709
                                         float rrGain, float rgGain, float rbGain,
 
710
                                         float grGain, float ggGain, float gbGain,
 
711
                                         float brGain, float bgGain, float bbGain)
 
712
{
 
713
    if (!data || !Width || !Height)
 
714
    {
 
715
       DWarning() << ("DImgImageFilters::channelMixerImage: no image data available!")
 
716
                  << endl;
 
717
       return;
 
718
    }
 
719
        
 
720
    register int i;
 
721
 
 
722
    double rnorm = CalculateNorm (rrGain, rgGain, rbGain, bPreserveLum);
 
723
    double gnorm = CalculateNorm (grGain, ggGain, gbGain, bPreserveLum);
 
724
    double bnorm = CalculateNorm (brGain, bgGain, bbGain, bPreserveLum);
 
725
 
 
726
    if (!sixteenBit)        // 8 bits image.
 
727
    {
 
728
        uchar  nGray, red, green, blue;
 
729
        uchar *ptr = data;
 
730
 
 
731
        for (i = 0 ; i < Width*Height ; i++)
 
732
        {
 
733
            blue  = ptr[0];
 
734
            green = ptr[1];
 
735
            red   = ptr[2];
 
736
        
 
737
            if (bMonochrome)
 
738
            {
 
739
                nGray = MixPixel (rrGain, rgGain, rbGain, 
 
740
                                  (unsigned short)red, (unsigned short)green, (unsigned short)blue,
 
741
                                  sixteenBit, rnorm);
 
742
                ptr[0] = ptr[1] = ptr[2] = nGray;
 
743
            }
 
744
            else
 
745
            {
 
746
                ptr[0] = (uchar)MixPixel (brGain, bgGain, bbGain, 
 
747
                                          (unsigned short)red, (unsigned short)green, (unsigned short)blue,
 
748
                                          sixteenBit, bnorm);
 
749
                ptr[1] = (uchar)MixPixel (grGain, ggGain, gbGain, 
 
750
                                          (unsigned short)red, (unsigned short)green, (unsigned short)blue,
 
751
                                          sixteenBit, gnorm);
 
752
                ptr[2] = (uchar)MixPixel (rrGain, rgGain, rbGain, 
 
753
                                          (unsigned short)red, (unsigned short)green, (unsigned short)blue,
 
754
                                          sixteenBit, rnorm);
 
755
            }
 
756
                                
 
757
            ptr += 4;
 
758
        }
 
759
    }
 
760
    else               // 16 bits image.
 
761
    {
 
762
        unsigned short  nGray, red, green, blue;
 
763
        unsigned short *ptr = (unsigned short *)data;
 
764
        
 
765
        for (i = 0 ; i < Width*Height ; i++)
 
766
        {
 
767
            blue  = ptr[0];
 
768
            green = ptr[1];
 
769
            red   = ptr[2];
 
770
        
 
771
            if (bMonochrome)
 
772
            {
 
773
                nGray = MixPixel (rrGain, rgGain, rbGain, red, green, blue, sixteenBit, rnorm);
 
774
                ptr[0] = ptr[1] = ptr[2] = nGray;
 
775
            }
 
776
            else
 
777
            {
 
778
                ptr[0] = MixPixel (brGain, bgGain, bbGain, red, green, blue, sixteenBit, bnorm);
 
779
                ptr[1] = MixPixel (grGain, ggGain, gbGain, red, green, blue, sixteenBit, gnorm);
 
780
                ptr[2] = MixPixel (rrGain, rgGain, rbGain, red, green, blue, sixteenBit, rnorm);
 
781
            }
 
782
                            
 
783
            ptr += 4;
 
784
        }
 
785
    }
 
786
}
 
787
 
 
788
/** Change color tonality of an image to appling a RGB color mask.*/
 
789
void DImgImageFilters::changeTonality(uchar *data, int width, int height, bool sixteenBit,
 
790
                                      int redMask, int greenMask, int blueMask)
 
791
{
 
792
    if (!data || !width || !height)
 
793
    {
 
794
       DWarning() << ("DImgImageFilters::changeTonality: no image data available!")
 
795
                   << endl;
 
796
       return;
 
797
    }
 
798
 
 
799
    int hue, sat, lig;
 
800
    
 
801
    DColor mask(redMask, greenMask, blueMask, 0, sixteenBit);
 
802
    mask.getHSL(&hue, &sat, &lig);
 
803
 
 
804
    if (!sixteenBit)        // 8 bits image.
 
805
    {
 
806
        uchar *ptr = data;
 
807
        
 
808
        for (int i = 0 ; i < width*height ; i++)
 
809
        {
 
810
            // Convert to grayscale using tonal mask
 
811
                
 
812
            lig = ROUND (0.3 * ptr[2] + 0.59 * ptr[1] + 0.11 * ptr[0]);
 
813
            
 
814
            mask.setRGB(hue, sat, lig, sixteenBit);
 
815
 
 
816
            ptr[0] = (uchar)mask.blue();
 
817
            ptr[1] = (uchar)mask.green();
 
818
            ptr[2] = (uchar)mask.red();
 
819
            ptr += 4;
 
820
        }
 
821
    }
 
822
    else               // 16 bits image.
 
823
    {
 
824
        unsigned short *ptr = (unsigned short *)data;
 
825
        
 
826
        for (int i = 0 ; i < width*height ; i++)
 
827
        {
 
828
            // Convert to grayscale using tonal mask
 
829
                
 
830
            lig = ROUND (0.3 * ptr[2] + 0.59 * ptr[1] + 0.11 * ptr[0]);
 
831
            
 
832
            mask.setRGB(hue, sat, lig, sixteenBit);
 
833
                                
 
834
            ptr[0] = (unsigned short)mask.blue();
 
835
            ptr[1] = (unsigned short)mask.green();
 
836
            ptr[2] = (unsigned short)mask.red();
 
837
            ptr += 4;
 
838
        }
 
839
    }
 
840
}
 
841
 
 
842
/** Function to apply the GaussianBlur on an image. This method do not use a
 
843
    dedicaced thread.*/
 
844
void DImgImageFilters::gaussianBlurImage(uchar *data, int width, int height, bool sixteenBit, int radius)
 
845
{
 
846
    if (!data || !width || !height)
 
847
    {
 
848
       DWarning() << ("DImgImageFilters::gaussianBlurImage: no image data available!")
 
849
                   << endl;
 
850
       return;
 
851
    }
 
852
 
 
853
    if (radius > 100) radius = 100;
 
854
    if (radius <= 0) return;
 
855
 
 
856
    DImg orgImage(width, height, sixteenBit, true, data);
 
857
    DImgGaussianBlur *filter = new DImgGaussianBlur(&orgImage, 0L, radius);
 
858
    DImg imDest = filter->getTargetImage();
 
859
    memcpy( data, imDest.bits(), imDest.numBytes() );
 
860
    delete filter;
 
861
}
 
862
 
 
863
/** Function to apply the sharpen filter on an image. This method do not use a
 
864
    dedicaced thread.*/
 
865
void DImgImageFilters::sharpenImage(uchar *data, int width, int height, bool sixteenBit, int radius)
 
866
{
 
867
    if (!data || !width || !height)
 
868
    {
 
869
       DWarning() << ("DImgImageFilters::sharpenImage: no image data available!")
 
870
                   << endl;
 
871
       return;
 
872
    }
 
873
 
 
874
    if (radius > 100) radius = 100;
 
875
    if (radius <= 0) return;
 
876
 
 
877
    DImg orgImage(width, height, sixteenBit, true, data);
 
878
    DImgSharpen *filter = new DImgSharpen(&orgImage, 0L, radius);
 
879
    DImg imDest = filter->getTargetImage();
 
880
    memcpy( data, imDest.bits(), imDest.numBytes() );
 
881
    delete filter;
 
882
}
 
883
 
 
884
/** Function to perform pixel antialiasing with 8 bits/color/pixel images. This method is used to smooth target
 
885
    image in transformation  method like free rotation or shear tool. */
 
886
void DImgImageFilters::pixelAntiAliasing(uchar *data, int Width, int Height, double X, double Y,
 
887
                                         uchar *A, uchar *R, uchar *G, uchar *B)
 
888
{
 
889
    int nX, nY, j;
 
890
    double lfWeightX[2], lfWeightY[2], lfWeight;
 
891
    double lfTotalR = 0.0, lfTotalG = 0.0, lfTotalB = 0.0, lfTotalA = 0.0;
 
892
 
 
893
    nX = (int)X;
 
894
    nY = (int)Y;
 
895
 
 
896
    if (Y >= 0.0)
 
897
        lfWeightY[0] = 1.0 - (lfWeightY[1] = Y - (double)nY);
 
898
    else
 
899
        lfWeightY[1] = 1.0 - (lfWeightY[0] = -(Y - (double)nY));
 
900
 
 
901
    if (X >= 0.0)
 
902
        lfWeightX[0] = 1.0 - (lfWeightX[1] = X - (double)nX);
 
903
    else
 
904
        lfWeightX[1] = 1.0 - (lfWeightX[0] = -(X - (double)nX));
 
905
 
 
906
    for (int loopx = 0; loopx <= 1; loopx++)
 
907
    {
 
908
        for (int loopy = 0; loopy <= 1; loopy++)
 
909
        {
 
910
            lfWeight = lfWeightX[loopx] * lfWeightY[loopy];
 
911
            j = setPositionAdjusted (Width, Height, nX + loopx, nY + loopy);
 
912
 
 
913
            lfTotalB += ((double)data[j] * lfWeight);
 
914
            j++;
 
915
            lfTotalG += ((double)data[j] * lfWeight);
 
916
            j++;
 
917
            lfTotalR += ((double)data[j] * lfWeight);
 
918
            j++;
 
919
            lfTotalA += ((double)data[j] * lfWeight);
 
920
            j++;
 
921
        }
 
922
    }
 
923
         
 
924
    *B = CLAMP0255((int)lfTotalB);
 
925
    *G = CLAMP0255((int)lfTotalG);
 
926
    *R = CLAMP0255((int)lfTotalR);
 
927
    *A = CLAMP0255((int)lfTotalA);
 
928
}
 
929
 
 
930
/** Function to perform pixel antialiasing with 16 bits/color/pixel images. This method is used to smooth target
 
931
    image in transformation  method like free rotation or shear tool. */
 
932
void DImgImageFilters::pixelAntiAliasing16(unsigned short *data, int Width, int Height, double X, double Y,
 
933
                                           unsigned short *A, unsigned short *R, unsigned short *G,
 
934
                                           unsigned short *B)
 
935
{
 
936
    int nX, nY, j;
 
937
    double lfWeightX[2], lfWeightY[2], lfWeight;
 
938
    double lfTotalR = 0.0, lfTotalG = 0.0, lfTotalB = 0.0, lfTotalA = 0.0;
 
939
 
 
940
    nX = (int)X;
 
941
    nY = (int)Y;
 
942
 
 
943
    if (Y >= 0.0)
 
944
        lfWeightY[0] = 1.0 - (lfWeightY[1] = Y - (double)nY);
 
945
    else
 
946
        lfWeightY[1] = 1.0 - (lfWeightY[0] = -(Y - (double)nY));
 
947
 
 
948
    if (X >= 0.0)
 
949
        lfWeightX[0] = 1.0 - (lfWeightX[1] = X - (double)nX);
 
950
    else
 
951
        lfWeightX[1] = 1.0 - (lfWeightX[0] = -(X - (double)nX));
 
952
 
 
953
    for (int loopx = 0; loopx <= 1; loopx++)
 
954
    {
 
955
        for (int loopy = 0; loopy <= 1; loopy++)
 
956
        {
 
957
            lfWeight = lfWeightX[loopx] * lfWeightY[loopy];
 
958
            j = setPositionAdjusted (Width, Height, nX + loopx, nY + loopy);
 
959
 
 
960
            lfTotalB += ((double)data[j] * lfWeight);
 
961
            j++;
 
962
            lfTotalG += ((double)data[j] * lfWeight);
 
963
            j++;
 
964
            lfTotalR += ((double)data[j] * lfWeight);
 
965
            j++;
 
966
            lfTotalA += ((double)data[j] * lfWeight);
 
967
            j++;
 
968
        }
 
969
    }
 
970
         
 
971
    *B = CLAMP065535((int)lfTotalB);
 
972
    *G = CLAMP065535((int)lfTotalG);
 
973
    *R = CLAMP065535((int)lfTotalR);
 
974
    *A = CLAMP065535((int)lfTotalA);
 
975
}
 
976
 
 
977
}  // NameSpace Digikam