1
/* ============================================================
3
* This file is a part of digiKam project
4
* http://www.digikam.org
7
* Description : misc image filters
9
* Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
11
* Original Equalise and StretchContrast Algorithms copyright 2002
12
* by Daniel M. Duley <mosfet@kde.org> from KImageEffect API.
14
* Original Normalize Image algorithm copyrighted 1997 by
15
* Adam D. Moss <adam@foxbox.org> from Gimp 2.0 implementation.
17
* Original channel mixer algorithm copyrighted 2002 by
18
* Martin Guldahl <mguldahl at xmission dot com> from Gimp 2.2
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)
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.
31
* ============================================================ */
40
#include "imagehistogram.h"
41
#include "imagelevels.h"
44
#include "dimggaussianblur.h"
45
#include "dimgsharpen.h"
46
#include "dimgimagefilters.h"
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)
62
if (!data || !w || !h)
64
DWarning() << ("DImgImageFilters::equalizeImage: no image data available!") << endl;
68
struct double_packet high, low, intensity;
69
struct double_packet *map;
70
struct int_packet *equalize_map;
73
// Create an histogram of the current image.
74
ImageHistogram *histogram = new ImageHistogram(data, w, h, sixteenBit);
77
map = new double_packet[histogram->getHistogramSegment()];
78
equalize_map = new int_packet[histogram->getHistogramSegment()];
80
if( !histogram || !map || !equalize_map )
89
delete [] equalize_map;
91
DWarning() << ("DImgImageFilters::equalizeImage: Unable to allocate memory!") << endl;
95
// Integrate the histogram to get the equalization map.
97
memset(&intensity, 0, sizeof(struct double_packet));
98
memset(&high, 0, sizeof(struct double_packet));
99
memset(&low, 0, sizeof(struct double_packet));
101
for(i = 0 ; i < histogram->getHistogramSegment() ; i++)
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);
110
// Stretch the histogram.
113
high = map[histogram->getHistogramSegment()-1];
114
memset(equalize_map, 0, histogram->getHistogramSegment()*sizeof(int_packet));
116
for(i = 0 ; i < histogram->getHistogramSegment() ; i++)
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));
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));
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));
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));
138
// Apply results to image.
140
if (!sixteenBit) // 8 bits image.
142
uchar red, green, blue, alpha;
145
for (i = 0 ; i < w*h ; i++)
152
if(low.red != high.red)
153
red = (equalize_map[red].red)/257;
155
if(low.green != high.green)
156
green = (equalize_map[green].green)/257;
158
if(low.blue != high.blue)
159
blue = (equalize_map[blue].blue)/257;
161
if(low.alpha != high.alpha)
162
alpha = (equalize_map[alpha].alpha)/257;
171
else // 16 bits image.
173
unsigned short red, green, blue, alpha;
174
unsigned short *ptr = (unsigned short *)data;
176
for (i = 0 ; i < w*h ; i++)
183
if(low.red != high.red)
184
red = (equalize_map[red].red)/257;
186
if(low.green != high.green)
187
green = (equalize_map[green].green)/257;
189
if(low.blue != high.blue)
190
blue = (equalize_map[blue].blue)/257;
192
if(low.alpha != high.alpha)
193
alpha = (equalize_map[alpha].alpha)/257;
203
delete [] equalize_map;
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)
211
if (!data || !w || !h)
213
DWarning() << ("DImgImageFilters::stretchContrastImage: no image data available!") << endl;
217
struct double_packet high, low, intensity;
218
struct int_packet *normalize_map;
219
long long number_pixels;
221
unsigned long threshold_intensity;
223
// Create an histogram of the current image.
224
ImageHistogram *histogram = new ImageHistogram(data, w, h, sixteenBit);
226
// Memory allocation.
227
normalize_map = new int_packet[histogram->getHistogramSegment()];
229
if( !histogram || !normalize_map )
235
delete [] normalize_map;
237
DWarning() << ("DImgImageFilters::stretchContrastImage: Unable to allocate memory!") << endl;
241
// Find the histogram boundaries by locating the 0.1 percent levels.
243
number_pixels = (long long)(w*h);
244
threshold_intensity = number_pixels / 1000;
246
memset(&high, 0, sizeof(struct double_packet));
247
memset(&low, 0, sizeof(struct double_packet));
251
memset(&intensity, 0, sizeof(struct double_packet));
253
for(high.red = histogram->getHistogramSegment()-1 ; high.red != 0 ; high.red--)
255
intensity.red += histogram->getValue(ImageHistogram::RedChannel, (int)high.red);
257
if( intensity.red > threshold_intensity )
261
if( low.red == high.red )
263
threshold_intensity = 0;
264
memset(&intensity, 0, sizeof(struct double_packet));
266
for(low.red = 0 ; low.red < histogram->getHistogramSegment()-1 ; low.red++)
268
intensity.red += histogram->getValue(ImageHistogram::RedChannel, (int)low.red);
270
if( intensity.red > threshold_intensity )
274
memset(&intensity, 0, sizeof(struct double_packet));
276
for(high.red = histogram->getHistogramSegment()-1 ; high.red != 0 ; high.red--)
278
intensity.red += histogram->getValue(ImageHistogram::RedChannel, (int)high.red);
280
if( intensity.red > threshold_intensity )
287
memset(&intensity, 0, sizeof(struct double_packet));
289
for(high.green = histogram->getHistogramSegment()-1 ; high.green != 0 ; high.green--)
291
intensity.green += histogram->getValue(ImageHistogram::GreenChannel, (int)high.green);
293
if( intensity.green > threshold_intensity )
297
if( low.green == high.green )
299
threshold_intensity = 0;
300
memset(&intensity, 0, sizeof(struct double_packet));
302
for(low.green = 0 ; low.green < histogram->getHistogramSegment()-1 ; low.green++)
304
intensity.green += histogram->getValue(ImageHistogram::GreenChannel, (int)low.green);
306
if( intensity.green > threshold_intensity )
310
memset(&intensity, 0, sizeof(struct double_packet));
312
for(high.green = histogram->getHistogramSegment()-1 ; high.green != 0 ; high.green--)
314
intensity.green += histogram->getValue(ImageHistogram::GreenChannel, (int)high.green);
316
if( intensity.green > threshold_intensity )
323
memset(&intensity, 0, sizeof(struct double_packet));
325
for(high.blue = histogram->getHistogramSegment()-1 ; high.blue != 0 ; high.blue--)
327
intensity.blue += histogram->getValue(ImageHistogram::BlueChannel, (int)high.blue);
329
if( intensity.blue > threshold_intensity )
333
if( low.blue == high.blue )
335
threshold_intensity = 0;
336
memset(&intensity, 0, sizeof(struct double_packet));
338
for(low.blue = 0 ; low.blue < histogram->getHistogramSegment()-1 ; low.blue++)
340
intensity.blue += histogram->getValue(ImageHistogram::BlueChannel, (int)low.blue);
342
if( intensity.blue > threshold_intensity )
346
memset(&intensity, 0, sizeof(struct double_packet));
348
for(high.blue = histogram->getHistogramSegment()-1 ; high.blue != 0 ; high.blue--)
350
intensity.blue += histogram->getValue(ImageHistogram::BlueChannel, (int)high.blue);
352
if( intensity.blue > threshold_intensity )
359
memset(&intensity, 0, sizeof(struct double_packet));
361
for(high.alpha = histogram->getHistogramSegment()-1 ; high.alpha != 0 ; high.alpha--)
363
intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, (int)high.alpha);
365
if( intensity.alpha > threshold_intensity )
369
if( low.alpha == high.alpha )
371
threshold_intensity = 0;
372
memset(&intensity, 0, sizeof(struct double_packet));
374
for(low.alpha = 0 ; low.alpha < histogram->getHistogramSegment()-1 ; low.alpha++)
376
intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, (int)low.alpha);
378
if( intensity.alpha > threshold_intensity )
382
memset(&intensity, 0, sizeof(struct double_packet));
384
for(high.alpha = histogram->getHistogramSegment()-1 ; high.alpha != 0 ; high.alpha--)
386
intensity.alpha += histogram->getValue(ImageHistogram::AlphaChannel, (int)high.alpha);
388
if( intensity.alpha > threshold_intensity )
395
// Stretch the histogram to create the normalized image mapping.
397
memset(normalize_map, 0, histogram->getHistogramSegment()*sizeof(struct int_packet));
399
for(i = 0 ; i <= (long)histogram->getHistogramSegment()-1 ; i++)
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));
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));
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));
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));
430
// Apply result to image.
432
if (!sixteenBit) // 8 bits image.
434
uchar red, green, blue, alpha;
437
for (i = 0 ; i < w*h ; i++)
444
if(low.red != high.red)
445
red = (normalize_map[red].red)/257;
447
if(low.green != high.green)
448
green = (normalize_map[green].green)/257;
450
if(low.blue != high.blue)
451
blue = (normalize_map[blue].blue)/257;
453
if(low.alpha != high.alpha)
454
alpha = (normalize_map[alpha].alpha)/257;
463
else // 16 bits image.
465
unsigned short red, green, blue, alpha;
466
unsigned short *ptr = (unsigned short *)data;
468
for (i = 0 ; i < w*h ; i++)
475
if(low.red != high.red)
476
red = (normalize_map[red].red)/257;
478
if(low.green != high.green)
479
green = (normalize_map[green].green)/257;
481
if(low.blue != high.blue)
482
blue = (normalize_map[blue].blue)/257;
484
if(low.alpha != high.alpha)
485
alpha = (normalize_map[alpha].alpha)/257;
495
delete [] normalize_map;
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)
505
NormalizeParam param;
507
unsigned short range;
509
int segments = sixteenBit ? 65536 : 256;
511
// Memory allocation.
513
param.lut = new unsigned short[segments];
515
// Find min. and max. values.
517
param.min = segments-1;
520
if (!sixteenBit) // 8 bits image.
522
uchar red, green, blue;
525
for (i = 0 ; i < w*h ; i++)
531
if (red < param.min) param.min = red;
532
if (red > param.max) param.max = red;
534
if (green < param.min) param.min = green;
535
if (green > param.max) param.max = green;
537
if (blue < param.min) param.min = blue;
538
if (blue > param.max) param.max = blue;
543
else // 16 bits image.
545
unsigned short red, green, blue;
546
unsigned short *ptr = (unsigned short *)data;
548
for (i = 0 ; i < w*h ; i++)
554
if (red < param.min) param.min = red;
555
if (red > param.max) param.max = red;
557
if (green < param.min) param.min = green;
558
if (green > param.max) param.max = green;
560
if (blue < param.min) param.min = blue;
561
if (blue > param.max) param.max = blue;
569
range = (unsigned short)(param.max - param.min);
573
for (x = (int)param.min ; x <= (int)param.max ; x++)
574
param.lut[x] = (unsigned short)((segments-1) * (x - param.min) / range);
577
param.lut[(int)param.min] = (unsigned short)param.min;
579
// Apply LUT to image.
581
if (!sixteenBit) // 8 bits image.
583
uchar red, green, blue;
586
for (i = 0 ; i < w*h ; i++)
592
ptr[0] = param.lut[blue];
593
ptr[1] = param.lut[green];
594
ptr[2] = param.lut[red];
599
else // 16 bits image.
601
unsigned short red, green, blue;
602
unsigned short *ptr = (unsigned short *)data;
604
for (i = 0 ; i < w*h ; i++)
610
ptr[0] = param.lut[blue];
611
ptr[1] = param.lut[green];
612
ptr[2] = param.lut[red];
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)
628
if (!data || !w || !h)
630
DWarning() << ("DImgImageFilters::autoLevelsCorrectionImage: no image data available!")
636
// Create the new empty destination image data space.
638
desData = new uchar[w*h*8];
640
desData = new uchar[w*h*4];
642
// Create an histogram of the current image.
643
ImageHistogram *histogram = new ImageHistogram(data, w, h, sixteenBit);
645
// Create an empty instance of levels to use.
646
ImageLevels *levels = new ImageLevels(sixteenBit);
648
// Initialize an auto levels correction of the histogram.
649
levels->levelsAuto(histogram);
651
// Calculate the LUT to apply on the image.
652
levels->levelsLutSetup(ImageHistogram::AlphaChannel);
654
// Apply the lut to the image.
655
levels->levelsLutProcess(data, desData, w, h);
658
memcpy (data, desData, w*h*8);
660
memcpy (data, desData, w*h*4);
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)
671
if (!data || !w || !h)
673
DWarning() << ("DImgImageFilters::invertImage: no image data available!")
678
if (!sixteenBit) // 8 bits image.
682
for (int i = 0 ; i < w*h ; i++)
684
ptr[0] = 255 - ptr[0];
685
ptr[1] = 255 - ptr[1];
686
ptr[2] = 255 - ptr[2];
687
ptr[3] = 255 - ptr[3];
691
else // 16 bits image.
693
unsigned short *ptr = (unsigned short *)data;
695
for (int i = 0 ; i < w*h ; i++)
697
ptr[0] = 65535 - ptr[0];
698
ptr[1] = 65535 - ptr[1];
699
ptr[2] = 65535 - ptr[2];
700
ptr[3] = 65535 - ptr[3];
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)
713
if (!data || !Width || !Height)
715
DWarning() << ("DImgImageFilters::channelMixerImage: no image data available!")
722
double rnorm = CalculateNorm (rrGain, rgGain, rbGain, bPreserveLum);
723
double gnorm = CalculateNorm (grGain, ggGain, gbGain, bPreserveLum);
724
double bnorm = CalculateNorm (brGain, bgGain, bbGain, bPreserveLum);
726
if (!sixteenBit) // 8 bits image.
728
uchar nGray, red, green, blue;
731
for (i = 0 ; i < Width*Height ; i++)
739
nGray = MixPixel (rrGain, rgGain, rbGain,
740
(unsigned short)red, (unsigned short)green, (unsigned short)blue,
742
ptr[0] = ptr[1] = ptr[2] = nGray;
746
ptr[0] = (uchar)MixPixel (brGain, bgGain, bbGain,
747
(unsigned short)red, (unsigned short)green, (unsigned short)blue,
749
ptr[1] = (uchar)MixPixel (grGain, ggGain, gbGain,
750
(unsigned short)red, (unsigned short)green, (unsigned short)blue,
752
ptr[2] = (uchar)MixPixel (rrGain, rgGain, rbGain,
753
(unsigned short)red, (unsigned short)green, (unsigned short)blue,
760
else // 16 bits image.
762
unsigned short nGray, red, green, blue;
763
unsigned short *ptr = (unsigned short *)data;
765
for (i = 0 ; i < Width*Height ; i++)
773
nGray = MixPixel (rrGain, rgGain, rbGain, red, green, blue, sixteenBit, rnorm);
774
ptr[0] = ptr[1] = ptr[2] = nGray;
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);
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)
792
if (!data || !width || !height)
794
DWarning() << ("DImgImageFilters::changeTonality: no image data available!")
801
DColor mask(redMask, greenMask, blueMask, 0, sixteenBit);
802
mask.getHSL(&hue, &sat, &lig);
804
if (!sixteenBit) // 8 bits image.
808
for (int i = 0 ; i < width*height ; i++)
810
// Convert to grayscale using tonal mask
812
lig = ROUND (0.3 * ptr[2] + 0.59 * ptr[1] + 0.11 * ptr[0]);
814
mask.setRGB(hue, sat, lig, sixteenBit);
816
ptr[0] = (uchar)mask.blue();
817
ptr[1] = (uchar)mask.green();
818
ptr[2] = (uchar)mask.red();
822
else // 16 bits image.
824
unsigned short *ptr = (unsigned short *)data;
826
for (int i = 0 ; i < width*height ; i++)
828
// Convert to grayscale using tonal mask
830
lig = ROUND (0.3 * ptr[2] + 0.59 * ptr[1] + 0.11 * ptr[0]);
832
mask.setRGB(hue, sat, lig, sixteenBit);
834
ptr[0] = (unsigned short)mask.blue();
835
ptr[1] = (unsigned short)mask.green();
836
ptr[2] = (unsigned short)mask.red();
842
/** Function to apply the GaussianBlur on an image. This method do not use a
844
void DImgImageFilters::gaussianBlurImage(uchar *data, int width, int height, bool sixteenBit, int radius)
846
if (!data || !width || !height)
848
DWarning() << ("DImgImageFilters::gaussianBlurImage: no image data available!")
853
if (radius > 100) radius = 100;
854
if (radius <= 0) return;
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() );
863
/** Function to apply the sharpen filter on an image. This method do not use a
865
void DImgImageFilters::sharpenImage(uchar *data, int width, int height, bool sixteenBit, int radius)
867
if (!data || !width || !height)
869
DWarning() << ("DImgImageFilters::sharpenImage: no image data available!")
874
if (radius > 100) radius = 100;
875
if (radius <= 0) return;
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() );
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)
890
double lfWeightX[2], lfWeightY[2], lfWeight;
891
double lfTotalR = 0.0, lfTotalG = 0.0, lfTotalB = 0.0, lfTotalA = 0.0;
897
lfWeightY[0] = 1.0 - (lfWeightY[1] = Y - (double)nY);
899
lfWeightY[1] = 1.0 - (lfWeightY[0] = -(Y - (double)nY));
902
lfWeightX[0] = 1.0 - (lfWeightX[1] = X - (double)nX);
904
lfWeightX[1] = 1.0 - (lfWeightX[0] = -(X - (double)nX));
906
for (int loopx = 0; loopx <= 1; loopx++)
908
for (int loopy = 0; loopy <= 1; loopy++)
910
lfWeight = lfWeightX[loopx] * lfWeightY[loopy];
911
j = setPositionAdjusted (Width, Height, nX + loopx, nY + loopy);
913
lfTotalB += ((double)data[j] * lfWeight);
915
lfTotalG += ((double)data[j] * lfWeight);
917
lfTotalR += ((double)data[j] * lfWeight);
919
lfTotalA += ((double)data[j] * lfWeight);
924
*B = CLAMP0255((int)lfTotalB);
925
*G = CLAMP0255((int)lfTotalG);
926
*R = CLAMP0255((int)lfTotalR);
927
*A = CLAMP0255((int)lfTotalA);
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,
937
double lfWeightX[2], lfWeightY[2], lfWeight;
938
double lfTotalR = 0.0, lfTotalG = 0.0, lfTotalB = 0.0, lfTotalA = 0.0;
944
lfWeightY[0] = 1.0 - (lfWeightY[1] = Y - (double)nY);
946
lfWeightY[1] = 1.0 - (lfWeightY[0] = -(Y - (double)nY));
949
lfWeightX[0] = 1.0 - (lfWeightX[1] = X - (double)nX);
951
lfWeightX[1] = 1.0 - (lfWeightX[0] = -(X - (double)nX));
953
for (int loopx = 0; loopx <= 1; loopx++)
955
for (int loopy = 0; loopy <= 1; loopy++)
957
lfWeight = lfWeightX[loopx] * lfWeightY[loopy];
958
j = setPositionAdjusted (Width, Height, nX + loopx, nY + loopy);
960
lfTotalB += ((double)data[j] * lfWeight);
962
lfTotalG += ((double)data[j] * lfWeight);
964
lfTotalR += ((double)data[j] * lfWeight);
966
lfTotalA += ((double)data[j] * lfWeight);
971
*B = CLAMP065535((int)lfTotalB);
972
*G = CLAMP065535((int)lfTotalG);
973
*R = CLAMP065535((int)lfTotalR);
974
*A = CLAMP065535((int)lfTotalA);
977
} // NameSpace Digikam