summaryrefslogtreecommitdiff
path: root/libopie2
Unidiff
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opieui/oimageeffect.cpp1
1 files changed, 0 insertions, 1 deletions
diff --git a/libopie2/opieui/oimageeffect.cpp b/libopie2/opieui/oimageeffect.cpp
index 2855da6..01e7c6f 100644
--- a/libopie2/opieui/oimageeffect.cpp
+++ b/libopie2/opieui/oimageeffect.cpp
@@ -1,1572 +1,1571 @@
1/* This file is part of the KDE libraries 1/* This file is part of the KDE libraries
2 Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@kde.org> 2 Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@kde.org>
3 (C) 1998, 1999 Christian Tibirna <ctibirna@total.net> 3 (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
4 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org> 4 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
5 (C) 2000 Josef Weidendorfer <weidendo@in.tum.de> 5 (C) 2000 Josef Weidendorfer <weidendo@in.tum.de>
6 6
7Redistribution and use in source and binary forms, with or without 7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions 8modification, are permitted provided that the following conditions
9are met: 9are met:
10 10
111. Redistributions of source code must retain the above copyright 111. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer. 12 notice, this list of conditions and the following disclaimer.
132. Redistributions in binary form must reproduce the above copyright 132. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the 14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution. 15 documentation and/or other materials provided with the distribution.
16 16
17THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28*/ 28*/
29 29
30// $Id$ 30// $Id$
31 31
32#include <math.h> 32#include <math.h>
33 33
34#include <qimage.h> 34#include <qimage.h>
35#include <stdlib.h> 35#include <stdlib.h>
36#include <iostream>
37 36
38#include "oimageeffect.h" 37#include "oimageeffect.h"
39 38
40#define MaxRGB 255L 39#define MaxRGB 255L
41#define DegreesToRadians(x) ((x)*M_PI/180.0) 40#define DegreesToRadians(x) ((x)*M_PI/180.0)
42 41
43using namespace std; 42using namespace std;
44 43
45inline unsigned int intensityValue(unsigned int color) 44inline unsigned int intensityValue(unsigned int color)
46{ 45{
47 return((unsigned int)((0.299*qRed(color) + 46 return((unsigned int)((0.299*qRed(color) +
48 0.587*qGreen(color) + 47 0.587*qGreen(color) +
49 0.1140000000000001*qBlue(color)))); 48 0.1140000000000001*qBlue(color))));
50} 49}
51 50
52//====================================================================== 51//======================================================================
53// 52//
54// Gradient effects 53// Gradient effects
55// 54//
56//====================================================================== 55//======================================================================
57 56
58QImage OImageEffect::gradient(const QSize &size, const QColor &ca, 57QImage OImageEffect::gradient(const QSize &size, const QColor &ca,
59 const QColor &cb, GradientType eff, int ncols) 58 const QColor &cb, GradientType eff, int ncols)
60{ 59{
61 int rDiff, gDiff, bDiff; 60 int rDiff, gDiff, bDiff;
62 int rca, gca, bca, rcb, gcb, bcb; 61 int rca, gca, bca, rcb, gcb, bcb;
63 62
64 QImage image(size, 32); 63 QImage image(size, 32);
65 64
66 if (size.width() == 0 || size.height() == 0) { 65 if (size.width() == 0 || size.height() == 0) {
67 qDebug( "WARNING: OImageEffect::gradient: invalid image" ); 66 qDebug( "WARNING: OImageEffect::gradient: invalid image" );
68 return image; 67 return image;
69 } 68 }
70 69
71 register int x, y; 70 register int x, y;
72 71
73 rDiff = (rcb = cb.red()) - (rca = ca.red()); 72 rDiff = (rcb = cb.red()) - (rca = ca.red());
74 gDiff = (gcb = cb.green()) - (gca = ca.green()); 73 gDiff = (gcb = cb.green()) - (gca = ca.green());
75 bDiff = (bcb = cb.blue()) - (bca = ca.blue()); 74 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
76 75
77 if( eff == VerticalGradient || eff == HorizontalGradient ){ 76 if( eff == VerticalGradient || eff == HorizontalGradient ){
78 77
79 uint *p; 78 uint *p;
80 uint rgb; 79 uint rgb;
81 80
82 register int rl = rca << 16; 81 register int rl = rca << 16;
83 register int gl = gca << 16; 82 register int gl = gca << 16;
84 register int bl = bca << 16; 83 register int bl = bca << 16;
85 84
86 if( eff == VerticalGradient ) { 85 if( eff == VerticalGradient ) {
87 86
88 int rcdelta = ((1<<16) / size.height()) * rDiff; 87 int rcdelta = ((1<<16) / size.height()) * rDiff;
89 int gcdelta = ((1<<16) / size.height()) * gDiff; 88 int gcdelta = ((1<<16) / size.height()) * gDiff;
90 int bcdelta = ((1<<16) / size.height()) * bDiff; 89 int bcdelta = ((1<<16) / size.height()) * bDiff;
91 90
92 for ( y = 0; y < size.height(); y++ ) { 91 for ( y = 0; y < size.height(); y++ ) {
93 p = (uint *) image.scanLine(y); 92 p = (uint *) image.scanLine(y);
94 93
95 rl += rcdelta; 94 rl += rcdelta;
96 gl += gcdelta; 95 gl += gcdelta;
97 bl += bcdelta; 96 bl += bcdelta;
98 97
99 rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) ); 98 rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) );
100 99
101 for( x = 0; x < size.width(); x++ ) { 100 for( x = 0; x < size.width(); x++ ) {
102 *p = rgb; 101 *p = rgb;
103 p++; 102 p++;
104 } 103 }
105 } 104 }
106 105
107 } 106 }
108 else { // must be HorizontalGradient 107 else { // must be HorizontalGradient
109 108
110 unsigned int *o_src = (unsigned int *)image.scanLine(0); 109 unsigned int *o_src = (unsigned int *)image.scanLine(0);
111 unsigned int *src = o_src; 110 unsigned int *src = o_src;
112 111
113 int rcdelta = ((1<<16) / size.width()) * rDiff; 112 int rcdelta = ((1<<16) / size.width()) * rDiff;
114 int gcdelta = ((1<<16) / size.width()) * gDiff; 113 int gcdelta = ((1<<16) / size.width()) * gDiff;
115 int bcdelta = ((1<<16) / size.width()) * bDiff; 114 int bcdelta = ((1<<16) / size.width()) * bDiff;
116 115
117 for( x = 0; x < size.width(); x++) { 116 for( x = 0; x < size.width(); x++) {
118 117
119 rl += rcdelta; 118 rl += rcdelta;
120 gl += gcdelta; 119 gl += gcdelta;
121 bl += bcdelta; 120 bl += bcdelta;
122 121
123 *src++ = qRgb( (rl>>16), (gl>>16), (bl>>16)); 122 *src++ = qRgb( (rl>>16), (gl>>16), (bl>>16));
124 } 123 }
125 124
126 src = o_src; 125 src = o_src;
127 126
128 // Believe it or not, manually copying in a for loop is faster 127 // Believe it or not, manually copying in a for loop is faster
129 // than calling memcpy for each scanline (on the order of ms...). 128 // than calling memcpy for each scanline (on the order of ms...).
130 // I think this is due to the function call overhead (mosfet). 129 // I think this is due to the function call overhead (mosfet).
131 130
132 for (y = 1; y < size.height(); ++y) { 131 for (y = 1; y < size.height(); ++y) {
133 132
134 p = (unsigned int *)image.scanLine(y); 133 p = (unsigned int *)image.scanLine(y);
135 src = o_src; 134 src = o_src;
136 for(x=0; x < size.width(); ++x) 135 for(x=0; x < size.width(); ++x)
137 *p++ = *src++; 136 *p++ = *src++;
138 } 137 }
139 } 138 }
140 } 139 }
141 140
142 else { 141 else {
143 142
144 float rfd, gfd, bfd; 143 float rfd, gfd, bfd;
145 float rd = rca, gd = gca, bd = bca; 144 float rd = rca, gd = gca, bd = bca;
146 145
147 unsigned char *xtable[3]; 146 unsigned char *xtable[3];
148 unsigned char *ytable[3]; 147 unsigned char *ytable[3];
149 148
150 unsigned int w = size.width(), h = size.height(); 149 unsigned int w = size.width(), h = size.height();
151 xtable[0] = new unsigned char[w]; 150 xtable[0] = new unsigned char[w];
152 xtable[1] = new unsigned char[w]; 151 xtable[1] = new unsigned char[w];
153 xtable[2] = new unsigned char[w]; 152 xtable[2] = new unsigned char[w];
154 ytable[0] = new unsigned char[h]; 153 ytable[0] = new unsigned char[h];
155 ytable[1] = new unsigned char[h]; 154 ytable[1] = new unsigned char[h];
156 ytable[2] = new unsigned char[h]; 155 ytable[2] = new unsigned char[h];
157 w*=2, h*=2; 156 w*=2, h*=2;
158 157
159 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) { 158 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) {
160 // Diagonal dgradient code inspired by BlackBox (mosfet) 159 // Diagonal dgradient code inspired by BlackBox (mosfet)
161 // BlackBox dgradient is (C) Brad Hughes, <bhughes@tcac.net> and 160 // BlackBox dgradient is (C) Brad Hughes, <bhughes@tcac.net> and
162 // Mike Cole <mike@mydot.com>. 161 // Mike Cole <mike@mydot.com>.
163 162
164 rfd = (float)rDiff/w; 163 rfd = (float)rDiff/w;
165 gfd = (float)gDiff/w; 164 gfd = (float)gDiff/w;
166 bfd = (float)bDiff/w; 165 bfd = (float)bDiff/w;
167 166
168 int dir; 167 int dir;
169 for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) { 168 for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) {
170 dir = eff == DiagonalGradient? x : size.width() - x - 1; 169 dir = eff == DiagonalGradient? x : size.width() - x - 1;
171 xtable[0][dir] = (unsigned char) rd; 170 xtable[0][dir] = (unsigned char) rd;
172 xtable[1][dir] = (unsigned char) gd; 171 xtable[1][dir] = (unsigned char) gd;
173 xtable[2][dir] = (unsigned char) bd; 172 xtable[2][dir] = (unsigned char) bd;
174 } 173 }
175 rfd = (float)rDiff/h; 174 rfd = (float)rDiff/h;
176 gfd = (float)gDiff/h; 175 gfd = (float)gDiff/h;
177 bfd = (float)bDiff/h; 176 bfd = (float)bDiff/h;
178 rd = gd = bd = 0; 177 rd = gd = bd = 0;
179 for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) { 178 for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) {
180 ytable[0][y] = (unsigned char) rd; 179 ytable[0][y] = (unsigned char) rd;
181 ytable[1][y] = (unsigned char) gd; 180 ytable[1][y] = (unsigned char) gd;
182 ytable[2][y] = (unsigned char) bd; 181 ytable[2][y] = (unsigned char) bd;
183 } 182 }
184 183
185 for (y = 0; y < size.height(); y++) { 184 for (y = 0; y < size.height(); y++) {
186 unsigned int *scanline = (unsigned int *)image.scanLine(y); 185 unsigned int *scanline = (unsigned int *)image.scanLine(y);
187 for (x = 0; x < size.width(); x++) { 186 for (x = 0; x < size.width(); x++) {
188 scanline[x] = qRgb(xtable[0][x] + ytable[0][y], 187 scanline[x] = qRgb(xtable[0][x] + ytable[0][y],
189 xtable[1][x] + ytable[1][y], 188 xtable[1][x] + ytable[1][y],
190 xtable[2][x] + ytable[2][y]); 189 xtable[2][x] + ytable[2][y]);
191 } 190 }
192 } 191 }
193 } 192 }
194 193
195 else if (eff == RectangleGradient || 194 else if (eff == RectangleGradient ||
196 eff == PyramidGradient || 195 eff == PyramidGradient ||
197 eff == PipeCrossGradient || 196 eff == PipeCrossGradient ||
198 eff == EllipticGradient) 197 eff == EllipticGradient)
199 { 198 {
200 int rSign = rDiff>0? 1: -1; 199 int rSign = rDiff>0? 1: -1;
201 int gSign = gDiff>0? 1: -1; 200 int gSign = gDiff>0? 1: -1;
202 int bSign = bDiff>0? 1: -1; 201 int bSign = bDiff>0? 1: -1;
203 202
204 rfd = (float)rDiff / size.width(); 203 rfd = (float)rDiff / size.width();
205 gfd = (float)gDiff / size.width(); 204 gfd = (float)gDiff / size.width();
206 bfd = (float)bDiff / size.width(); 205 bfd = (float)bDiff / size.width();
207 206
208 rd = (float)rDiff/2; 207 rd = (float)rDiff/2;
209 gd = (float)gDiff/2; 208 gd = (float)gDiff/2;
210 bd = (float)bDiff/2; 209 bd = (float)bDiff/2;
211 210
212 for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd) 211 for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd)
213 { 212 {
214 xtable[0][x] = (unsigned char) abs((int)rd); 213 xtable[0][x] = (unsigned char) abs((int)rd);
215 xtable[1][x] = (unsigned char) abs((int)gd); 214 xtable[1][x] = (unsigned char) abs((int)gd);
216 xtable[2][x] = (unsigned char) abs((int)bd); 215 xtable[2][x] = (unsigned char) abs((int)bd);
217 } 216 }
218 217
219 rfd = (float)rDiff/size.height(); 218 rfd = (float)rDiff/size.height();
220 gfd = (float)gDiff/size.height(); 219 gfd = (float)gDiff/size.height();
221 bfd = (float)bDiff/size.height(); 220 bfd = (float)bDiff/size.height();
222 221
223 rd = (float)rDiff/2; 222 rd = (float)rDiff/2;
224 gd = (float)gDiff/2; 223 gd = (float)gDiff/2;
225 bd = (float)bDiff/2; 224 bd = (float)bDiff/2;
226 225
227 for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd) 226 for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd)
228 { 227 {
229 ytable[0][y] = (unsigned char) abs((int)rd); 228 ytable[0][y] = (unsigned char) abs((int)rd);
230 ytable[1][y] = (unsigned char) abs((int)gd); 229 ytable[1][y] = (unsigned char) abs((int)gd);
231 ytable[2][y] = (unsigned char) abs((int)bd); 230 ytable[2][y] = (unsigned char) abs((int)bd);
232 } 231 }
233 unsigned int rgb; 232 unsigned int rgb;
234 int h = (size.height()+1)>>1; 233 int h = (size.height()+1)>>1;
235 for (y = 0; y < h; y++) { 234 for (y = 0; y < h; y++) {
236 unsigned int *sl1 = (unsigned int *)image.scanLine(y); 235 unsigned int *sl1 = (unsigned int *)image.scanLine(y);
237 unsigned int *sl2 = (unsigned int *)image.scanLine(QMAX(size.height()-y-1, y)); 236 unsigned int *sl2 = (unsigned int *)image.scanLine(QMAX(size.height()-y-1, y));
238 237
239 int w = (size.width()+1)>>1; 238 int w = (size.width()+1)>>1;
240 int x2 = size.width()-1; 239 int x2 = size.width()-1;
241 240
242 for (x = 0; x < w; x++, x2--) { 241 for (x = 0; x < w; x++, x2--) {
243 rgb = 0; 242 rgb = 0;
244 if (eff == PyramidGradient) { 243 if (eff == PyramidGradient) {
245 rgb = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]), 244 rgb = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
246 gcb-gSign*(xtable[1][x]+ytable[1][y]), 245 gcb-gSign*(xtable[1][x]+ytable[1][y]),
247 bcb-bSign*(xtable[2][x]+ytable[2][y])); 246 bcb-bSign*(xtable[2][x]+ytable[2][y]));
248 } 247 }
249 if (eff == RectangleGradient) { 248 if (eff == RectangleGradient) {
250 rgb = qRgb(rcb - rSign * 249 rgb = qRgb(rcb - rSign *
251 QMAX(xtable[0][x], ytable[0][y]) * 2, 250 QMAX(xtable[0][x], ytable[0][y]) * 2,
252 gcb - gSign * 251 gcb - gSign *
253 QMAX(xtable[1][x], ytable[1][y]) * 2, 252 QMAX(xtable[1][x], ytable[1][y]) * 2,
254 bcb - bSign * 253 bcb - bSign *
255 QMAX(xtable[2][x], ytable[2][y]) * 2); 254 QMAX(xtable[2][x], ytable[2][y]) * 2);
256 } 255 }
257 if (eff == PipeCrossGradient) { 256 if (eff == PipeCrossGradient) {
258 rgb = qRgb(rcb - rSign * 257 rgb = qRgb(rcb - rSign *
259 QMIN(xtable[0][x], ytable[0][y]) * 2, 258 QMIN(xtable[0][x], ytable[0][y]) * 2,
260 gcb - gSign * 259 gcb - gSign *
261 QMIN(xtable[1][x], ytable[1][y]) * 2, 260 QMIN(xtable[1][x], ytable[1][y]) * 2,
262 bcb - bSign * 261 bcb - bSign *
263 QMIN(xtable[2][x], ytable[2][y]) * 2); 262 QMIN(xtable[2][x], ytable[2][y]) * 2);
264 } 263 }
265 if (eff == EllipticGradient) { 264 if (eff == EllipticGradient) {
266 rgb = qRgb(rcb - rSign * 265 rgb = qRgb(rcb - rSign *
267 (int)sqrt((xtable[0][x]*xtable[0][x] + 266 (int)sqrt((xtable[0][x]*xtable[0][x] +
268 ytable[0][y]*ytable[0][y])*2.0), 267 ytable[0][y]*ytable[0][y])*2.0),
269 gcb - gSign * 268 gcb - gSign *
270 (int)sqrt((xtable[1][x]*xtable[1][x] + 269 (int)sqrt((xtable[1][x]*xtable[1][x] +
271 ytable[1][y]*ytable[1][y])*2.0), 270 ytable[1][y]*ytable[1][y])*2.0),
272 bcb - bSign * 271 bcb - bSign *
273 (int)sqrt((xtable[2][x]*xtable[2][x] + 272 (int)sqrt((xtable[2][x]*xtable[2][x] +
274 ytable[2][y]*ytable[2][y])*2.0)); 273 ytable[2][y]*ytable[2][y])*2.0));
275 } 274 }
276 275
277 sl1[x] = sl2[x] = rgb; 276 sl1[x] = sl2[x] = rgb;
278 sl1[x2] = sl2[x2] = rgb; 277 sl1[x2] = sl2[x2] = rgb;
279 } 278 }
280 } 279 }
281 } 280 }
282 281
283 delete [] xtable[0]; 282 delete [] xtable[0];
284 delete [] xtable[1]; 283 delete [] xtable[1];
285 delete [] xtable[2]; 284 delete [] xtable[2];
286 delete [] ytable[0]; 285 delete [] ytable[0];
287 delete [] ytable[1]; 286 delete [] ytable[1];
288 delete [] ytable[2]; 287 delete [] ytable[2];
289 } 288 }
290 289
291 // dither if necessary 290 // dither if necessary
292 if (ncols && (QPixmap::defaultDepth() < 15 )) { 291 if (ncols && (QPixmap::defaultDepth() < 15 )) {
293 if ( ncols < 2 || ncols > 256 ) 292 if ( ncols < 2 || ncols > 256 )
294 ncols = 3; 293 ncols = 3;
295 QColor *dPal = new QColor[ncols]; 294 QColor *dPal = new QColor[ncols];
296 for (int i=0; i<ncols; i++) { 295 for (int i=0; i<ncols; i++) {
297 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ), 296 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
298 gca + gDiff * i / ( ncols - 1 ), 297 gca + gDiff * i / ( ncols - 1 ),
299 bca + bDiff * i / ( ncols - 1 ) ); 298 bca + bDiff * i / ( ncols - 1 ) );
300 } 299 }
301 dither(image, dPal, ncols); 300 dither(image, dPal, ncols);
302 delete [] dPal; 301 delete [] dPal;
303 } 302 }
304 303
305 return image; 304 return image;
306} 305}
307 306
308 307
309// ----------------------------------------------------------------------------- 308// -----------------------------------------------------------------------------
310 309
311//CT this was (before Dirk A. Mueller's speedup changes) 310//CT this was (before Dirk A. Mueller's speedup changes)
312// merely the same code as in the above method, but it's supposedly 311// merely the same code as in the above method, but it's supposedly
313// way less performant since it introduces a lot of supplementary tests 312// way less performant since it introduces a lot of supplementary tests
314// and simple math operations for the calculus of the balance. 313// and simple math operations for the calculus of the balance.
315// (surprizingly, it isn't less performant, in the contrary :-) 314// (surprizingly, it isn't less performant, in the contrary :-)
316// Yes, I could have merged them, but then the excellent performance of 315// Yes, I could have merged them, but then the excellent performance of
317// the balanced code would suffer with no other gain than a mere 316// the balanced code would suffer with no other gain than a mere
318// source code and byte code size economy. 317// source code and byte code size economy.
319 318
320QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca, 319QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca,
321 const QColor &cb, GradientType eff, int xfactor, int yfactor, 320 const QColor &cb, GradientType eff, int xfactor, int yfactor,
322 int ncols) 321 int ncols)
323{ 322{
324 int dir; // general parameter used for direction switches 323 int dir; // general parameter used for direction switches
325 324
326 bool _xanti = false , _yanti = false; 325 bool _xanti = false , _yanti = false;
327 326
328 if (xfactor < 0) _xanti = true; // negative on X direction 327 if (xfactor < 0) _xanti = true; // negative on X direction
329 if (yfactor < 0) _yanti = true; // negative on Y direction 328 if (yfactor < 0) _yanti = true; // negative on Y direction
330 329
331 xfactor = abs(xfactor); 330 xfactor = abs(xfactor);
332 yfactor = abs(yfactor); 331 yfactor = abs(yfactor);
333 332
334 if (!xfactor) xfactor = 1; 333 if (!xfactor) xfactor = 1;
335 if (!yfactor) yfactor = 1; 334 if (!yfactor) yfactor = 1;
336 335
337 if (xfactor > 200 ) xfactor = 200; 336 if (xfactor > 200 ) xfactor = 200;
338 if (yfactor > 200 ) yfactor = 200; 337 if (yfactor > 200 ) yfactor = 200;
339 338
340 339
341 // float xbal = xfactor/5000.; 340 // float xbal = xfactor/5000.;
342 // float ybal = yfactor/5000.; 341 // float ybal = yfactor/5000.;
343 float xbal = xfactor/30./size.width(); 342 float xbal = xfactor/30./size.width();
344 float ybal = yfactor/30./size.height(); 343 float ybal = yfactor/30./size.height();
345 float rat; 344 float rat;
346 345
347 int rDiff, gDiff, bDiff; 346 int rDiff, gDiff, bDiff;
348 int rca, gca, bca, rcb, gcb, bcb; 347 int rca, gca, bca, rcb, gcb, bcb;
349 348
350 QImage image(size, 32); 349 QImage image(size, 32);
351 350
352 if (size.width() == 0 || size.height() == 0) { 351 if (size.width() == 0 || size.height() == 0) {
353 qDebug( "WARNING: OImageEffect::unbalancedGradient : invalid image" ); 352 qDebug( "WARNING: OImageEffect::unbalancedGradient : invalid image" );
354 return image; 353 return image;
355 } 354 }
356 355
357 register int x, y; 356 register int x, y;
358 unsigned int *scanline; 357 unsigned int *scanline;
359 358
360 rDiff = (rcb = cb.red()) - (rca = ca.red()); 359 rDiff = (rcb = cb.red()) - (rca = ca.red());
361 gDiff = (gcb = cb.green()) - (gca = ca.green()); 360 gDiff = (gcb = cb.green()) - (gca = ca.green());
362 bDiff = (bcb = cb.blue()) - (bca = ca.blue()); 361 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
363 362
364 if( eff == VerticalGradient || eff == HorizontalGradient){ 363 if( eff == VerticalGradient || eff == HorizontalGradient){
365 QColor cRow; 364 QColor cRow;
366 365
367 uint *p; 366 uint *p;
368 uint rgbRow; 367 uint rgbRow;
369 368
370 if( eff == VerticalGradient) { 369 if( eff == VerticalGradient) {
371 for ( y = 0; y < size.height(); y++ ) { 370 for ( y = 0; y < size.height(); y++ ) {
372 dir = _yanti ? y : size.height() - 1 - y; 371 dir = _yanti ? y : size.height() - 1 - y;
373 p = (uint *) image.scanLine(dir); 372 p = (uint *) image.scanLine(dir);
374 rat = 1 - exp( - (float)y * ybal ); 373 rat = 1 - exp( - (float)y * ybal );
375 374
376 cRow.setRgb( rcb - (int) ( rDiff * rat ), 375 cRow.setRgb( rcb - (int) ( rDiff * rat ),
377 gcb - (int) ( gDiff * rat ), 376 gcb - (int) ( gDiff * rat ),
378 bcb - (int) ( bDiff * rat ) ); 377 bcb - (int) ( bDiff * rat ) );
379 378
380 rgbRow = cRow.rgb(); 379 rgbRow = cRow.rgb();
381 380
382 for( x = 0; x < size.width(); x++ ) { 381 for( x = 0; x < size.width(); x++ ) {
383 *p = rgbRow; 382 *p = rgbRow;
384 p++; 383 p++;
385 } 384 }
386 } 385 }
387 } 386 }
388 else { 387 else {
389 388
390 unsigned int *src = (unsigned int *)image.scanLine(0); 389 unsigned int *src = (unsigned int *)image.scanLine(0);
391 for(x = 0; x < size.width(); x++ ) 390 for(x = 0; x < size.width(); x++ )
392 { 391 {
393 dir = _xanti ? x : size.width() - 1 - x; 392 dir = _xanti ? x : size.width() - 1 - x;
394 rat = 1 - exp( - (float)x * xbal ); 393 rat = 1 - exp( - (float)x * xbal );
395 394
396 src[dir] = qRgb(rcb - (int) ( rDiff * rat ), 395 src[dir] = qRgb(rcb - (int) ( rDiff * rat ),
397 gcb - (int) ( gDiff * rat ), 396 gcb - (int) ( gDiff * rat ),
398 bcb - (int) ( bDiff * rat )); 397 bcb - (int) ( bDiff * rat ));
399 } 398 }
400 399
401 // Believe it or not, manually copying in a for loop is faster 400 // Believe it or not, manually copying in a for loop is faster
402 // than calling memcpy for each scanline (on the order of ms...). 401 // than calling memcpy for each scanline (on the order of ms...).
403 // I think this is due to the function call overhead (mosfet). 402 // I think this is due to the function call overhead (mosfet).
404 403
405 for(y = 1; y < size.height(); ++y) 404 for(y = 1; y < size.height(); ++y)
406 { 405 {
407 scanline = (unsigned int *)image.scanLine(y); 406 scanline = (unsigned int *)image.scanLine(y);
408 for(x=0; x < size.width(); ++x) 407 for(x=0; x < size.width(); ++x)
409 scanline[x] = src[x]; 408 scanline[x] = src[x];
410 } 409 }
411 } 410 }
412 } 411 }
413 412
414 else { 413 else {
415 int w=size.width(), h=size.height(); 414 int w=size.width(), h=size.height();
416 415
417 unsigned char *xtable[3]; 416 unsigned char *xtable[3];
418 unsigned char *ytable[3]; 417 unsigned char *ytable[3];
419 xtable[0] = new unsigned char[w]; 418 xtable[0] = new unsigned char[w];
420 xtable[1] = new unsigned char[w]; 419 xtable[1] = new unsigned char[w];
421 xtable[2] = new unsigned char[w]; 420 xtable[2] = new unsigned char[w];
422 ytable[0] = new unsigned char[h]; 421 ytable[0] = new unsigned char[h];
423 ytable[1] = new unsigned char[h]; 422 ytable[1] = new unsigned char[h];
424 ytable[2] = new unsigned char[h]; 423 ytable[2] = new unsigned char[h];
425 424
426 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) 425 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient)
427 { 426 {
428 for (x = 0; x < w; x++) { 427 for (x = 0; x < w; x++) {
429 dir = _xanti ? x : w - 1 - x; 428 dir = _xanti ? x : w - 1 - x;
430 rat = 1 - exp( - (float)x * xbal ); 429 rat = 1 - exp( - (float)x * xbal );
431 430
432 xtable[0][dir] = (unsigned char) ( rDiff/2 * rat ); 431 xtable[0][dir] = (unsigned char) ( rDiff/2 * rat );
433 xtable[1][dir] = (unsigned char) ( gDiff/2 * rat ); 432 xtable[1][dir] = (unsigned char) ( gDiff/2 * rat );
434 xtable[2][dir] = (unsigned char) ( bDiff/2 * rat ); 433 xtable[2][dir] = (unsigned char) ( bDiff/2 * rat );
435 } 434 }
436 435
437 for (y = 0; y < h; y++) { 436 for (y = 0; y < h; y++) {
438 dir = _yanti ? y : h - 1 - y; 437 dir = _yanti ? y : h - 1 - y;
439 rat = 1 - exp( - (float)y * ybal ); 438 rat = 1 - exp( - (float)y * ybal );
440 439
441 ytable[0][dir] = (unsigned char) ( rDiff/2 * rat ); 440 ytable[0][dir] = (unsigned char) ( rDiff/2 * rat );
442 ytable[1][dir] = (unsigned char) ( gDiff/2 * rat ); 441 ytable[1][dir] = (unsigned char) ( gDiff/2 * rat );
443 ytable[2][dir] = (unsigned char) ( bDiff/2 * rat ); 442 ytable[2][dir] = (unsigned char) ( bDiff/2 * rat );
444 } 443 }
445 444
446 for (y = 0; y < h; y++) { 445 for (y = 0; y < h; y++) {
447 unsigned int *scanline = (unsigned int *)image.scanLine(y); 446 unsigned int *scanline = (unsigned int *)image.scanLine(y);
448 for (x = 0; x < w; x++) { 447 for (x = 0; x < w; x++) {
449 scanline[x] = qRgb(rcb - (xtable[0][x] + ytable[0][y]), 448 scanline[x] = qRgb(rcb - (xtable[0][x] + ytable[0][y]),
450 gcb - (xtable[1][x] + ytable[1][y]), 449 gcb - (xtable[1][x] + ytable[1][y]),
451 bcb - (xtable[2][x] + ytable[2][y])); 450 bcb - (xtable[2][x] + ytable[2][y]));
452 } 451 }
453 } 452 }
454 } 453 }
455 454
456 else if (eff == RectangleGradient || 455 else if (eff == RectangleGradient ||
457 eff == PyramidGradient || 456 eff == PyramidGradient ||
458 eff == PipeCrossGradient || 457 eff == PipeCrossGradient ||
459 eff == EllipticGradient) 458 eff == EllipticGradient)
460 { 459 {
461 int rSign = rDiff>0? 1: -1; 460 int rSign = rDiff>0? 1: -1;
462 int gSign = gDiff>0? 1: -1; 461 int gSign = gDiff>0? 1: -1;
463 int bSign = bDiff>0? 1: -1; 462 int bSign = bDiff>0? 1: -1;
464 463
465 for (x = 0; x < w; x++) 464 for (x = 0; x < w; x++)
466 { 465 {
467 dir = _xanti ? x : w - 1 - x; 466 dir = _xanti ? x : w - 1 - x;
468 rat = 1 - exp( - (float)x * xbal ); 467 rat = 1 - exp( - (float)x * xbal );
469 468
470 xtable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat))); 469 xtable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
471 xtable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat))); 470 xtable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
472 xtable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat))); 471 xtable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
473 } 472 }
474 473
475 for (y = 0; y < h; y++) 474 for (y = 0; y < h; y++)
476 { 475 {
477 dir = _yanti ? y : h - 1 - y; 476 dir = _yanti ? y : h - 1 - y;
478 477
479 rat = 1 - exp( - (float)y * ybal ); 478 rat = 1 - exp( - (float)y * ybal );
480 479
481 ytable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat))); 480 ytable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
482 ytable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat))); 481 ytable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
483 ytable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat))); 482 ytable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
484 } 483 }
485 484
486 for (y = 0; y < h; y++) { 485 for (y = 0; y < h; y++) {
487 unsigned int *scanline = (unsigned int *)image.scanLine(y); 486 unsigned int *scanline = (unsigned int *)image.scanLine(y);
488 for (x = 0; x < w; x++) { 487 for (x = 0; x < w; x++) {
489 if (eff == PyramidGradient) 488 if (eff == PyramidGradient)
490 { 489 {
491 scanline[x] = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]), 490 scanline[x] = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
492 gcb-gSign*(xtable[1][x]+ytable[1][y]), 491 gcb-gSign*(xtable[1][x]+ytable[1][y]),
493 bcb-bSign*(xtable[2][x]+ytable[2][y])); 492 bcb-bSign*(xtable[2][x]+ytable[2][y]));
494 } 493 }
495 if (eff == RectangleGradient) 494 if (eff == RectangleGradient)
496 { 495 {
497 scanline[x] = qRgb(rcb - rSign * 496 scanline[x] = qRgb(rcb - rSign *
498 QMAX(xtable[0][x], ytable[0][y]) * 2, 497 QMAX(xtable[0][x], ytable[0][y]) * 2,
499 gcb - gSign * 498 gcb - gSign *
500 QMAX(xtable[1][x], ytable[1][y]) * 2, 499 QMAX(xtable[1][x], ytable[1][y]) * 2,
501 bcb - bSign * 500 bcb - bSign *
502 QMAX(xtable[2][x], ytable[2][y]) * 2); 501 QMAX(xtable[2][x], ytable[2][y]) * 2);
503 } 502 }
504 if (eff == PipeCrossGradient) 503 if (eff == PipeCrossGradient)
505 { 504 {
506 scanline[x] = qRgb(rcb - rSign * 505 scanline[x] = qRgb(rcb - rSign *
507 QMIN(xtable[0][x], ytable[0][y]) * 2, 506 QMIN(xtable[0][x], ytable[0][y]) * 2,
508 gcb - gSign * 507 gcb - gSign *
509 QMIN(xtable[1][x], ytable[1][y]) * 2, 508 QMIN(xtable[1][x], ytable[1][y]) * 2,
510 bcb - bSign * 509 bcb - bSign *
511 QMIN(xtable[2][x], ytable[2][y]) * 2); 510 QMIN(xtable[2][x], ytable[2][y]) * 2);
512 } 511 }
513 if (eff == EllipticGradient) 512 if (eff == EllipticGradient)
514 { 513 {
515 scanline[x] = qRgb(rcb - rSign * 514 scanline[x] = qRgb(rcb - rSign *
516 (int)sqrt((xtable[0][x]*xtable[0][x] + 515 (int)sqrt((xtable[0][x]*xtable[0][x] +
517 ytable[0][y]*ytable[0][y])*2.0), 516 ytable[0][y]*ytable[0][y])*2.0),
518 gcb - gSign * 517 gcb - gSign *
519 (int)sqrt((xtable[1][x]*xtable[1][x] + 518 (int)sqrt((xtable[1][x]*xtable[1][x] +
520 ytable[1][y]*ytable[1][y])*2.0), 519 ytable[1][y]*ytable[1][y])*2.0),
521 bcb - bSign * 520 bcb - bSign *
522 (int)sqrt((xtable[2][x]*xtable[2][x] + 521 (int)sqrt((xtable[2][x]*xtable[2][x] +
523 ytable[2][y]*ytable[2][y])*2.0)); 522 ytable[2][y]*ytable[2][y])*2.0));
524 } 523 }
525 } 524 }
526 } 525 }
527 } 526 }
528 527
529 if (ncols && (QPixmap::defaultDepth() < 15 )) { 528 if (ncols && (QPixmap::defaultDepth() < 15 )) {
530 if ( ncols < 2 || ncols > 256 ) 529 if ( ncols < 2 || ncols > 256 )
531 ncols = 3; 530 ncols = 3;
532 QColor *dPal = new QColor[ncols]; 531 QColor *dPal = new QColor[ncols];
533 for (int i=0; i<ncols; i++) { 532 for (int i=0; i<ncols; i++) {
534 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ), 533 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
535 gca + gDiff * i / ( ncols - 1 ), 534 gca + gDiff * i / ( ncols - 1 ),
536 bca + bDiff * i / ( ncols - 1 ) ); 535 bca + bDiff * i / ( ncols - 1 ) );
537 } 536 }
538 dither(image, dPal, ncols); 537 dither(image, dPal, ncols);
539 delete [] dPal; 538 delete [] dPal;
540 } 539 }
541 540
542 delete [] xtable[0]; 541 delete [] xtable[0];
543 delete [] xtable[1]; 542 delete [] xtable[1];
544 delete [] xtable[2]; 543 delete [] xtable[2];
545 delete [] ytable[0]; 544 delete [] ytable[0];
546 delete [] ytable[1]; 545 delete [] ytable[1];
547 delete [] ytable[2]; 546 delete [] ytable[2];
548 547
549 } 548 }
550 549
551 return image; 550 return image;
552} 551}
553 552
554 553
555//====================================================================== 554//======================================================================
556// 555//
557// Intensity effects 556// Intensity effects
558// 557//
559//====================================================================== 558//======================================================================
560 559
561 560
562/* This builds a 256 byte unsigned char lookup table with all 561/* This builds a 256 byte unsigned char lookup table with all
563 * the possible percent values prior to applying the effect, then uses 562 * the possible percent values prior to applying the effect, then uses
564 * integer math for the pixels. For any image larger than 9x9 this will be 563 * integer math for the pixels. For any image larger than 9x9 this will be
565 * less expensive than doing a float operation on the 3 color components of 564 * less expensive than doing a float operation on the 3 color components of
566 * each pixel. (mosfet) 565 * each pixel. (mosfet)
567 */ 566 */
568 567
569QImage& OImageEffect::intensity(QImage &image, float percent) 568QImage& OImageEffect::intensity(QImage &image, float percent)
570{ 569{
571 if (image.width() == 0 || image.height() == 0) { 570 if (image.width() == 0 || image.height() == 0) {
572 qDebug( "WARNING: OImageEffect::intensity : invalid image" ); 571 qDebug( "WARNING: OImageEffect::intensity : invalid image" );
573 return image; 572 return image;
574 } 573 }
575 574
576 int segColors = image.depth() > 8 ? 256 : image.numColors(); 575 int segColors = image.depth() > 8 ? 256 : image.numColors();
577 unsigned char *segTbl = new unsigned char[segColors]; 576 unsigned char *segTbl = new unsigned char[segColors];
578 int pixels = image.depth() > 8 ? image.width()*image.height() : 577 int pixels = image.depth() > 8 ? image.width()*image.height() :
579 image.numColors(); 578 image.numColors();
580 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() : 579 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
581 (unsigned int *)image.colorTable(); 580 (unsigned int *)image.colorTable();
582 581
583 bool brighten = (percent >= 0); 582 bool brighten = (percent >= 0);
584 if(percent < 0) 583 if(percent < 0)
585 percent = -percent; 584 percent = -percent;
586 585
587 if(brighten){ // keep overflow check out of loops 586 if(brighten){ // keep overflow check out of loops
588 for(int i=0; i < segColors; ++i){ 587 for(int i=0; i < segColors; ++i){
589 int tmp = (int)(i*percent); 588 int tmp = (int)(i*percent);
590 if(tmp > 255) 589 if(tmp > 255)
591 tmp = 255; 590 tmp = 255;
592 segTbl[i] = tmp; 591 segTbl[i] = tmp;
593 } 592 }
594 } 593 }
595 else{ 594 else{
596 for(int i=0; i < segColors; ++i){ 595 for(int i=0; i < segColors; ++i){
597 int tmp = (int)(i*percent); 596 int tmp = (int)(i*percent);
598 if(tmp < 0) 597 if(tmp < 0)
599 tmp = 0; 598 tmp = 0;
600 segTbl[i] = tmp; 599 segTbl[i] = tmp;
601 } 600 }
602 } 601 }
603 602
604 if(brighten){ // same here 603 if(brighten){ // same here
605 for(int i=0; i < pixels; ++i){ 604 for(int i=0; i < pixels; ++i){
606 int r = qRed(data[i]); 605 int r = qRed(data[i]);
607 int g = qGreen(data[i]); 606 int g = qGreen(data[i]);
608 int b = qBlue(data[i]); 607 int b = qBlue(data[i]);
609 int a = qAlpha(data[i]); 608 int a = qAlpha(data[i]);
610 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r]; 609 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
611 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g]; 610 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
612 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b]; 611 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
613 data[i] = qRgba(r, g, b,a); 612 data[i] = qRgba(r, g, b,a);
614 } 613 }
615 } 614 }
616 else{ 615 else{
617 for(int i=0; i < pixels; ++i){ 616 for(int i=0; i < pixels; ++i){
618 int r = qRed(data[i]); 617 int r = qRed(data[i]);
619 int g = qGreen(data[i]); 618 int g = qGreen(data[i]);
620 int b = qBlue(data[i]); 619 int b = qBlue(data[i]);
621 int a = qAlpha(data[i]); 620 int a = qAlpha(data[i]);
622 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r]; 621 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
623 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g]; 622 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
624 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b]; 623 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
625 data[i] = qRgba(r, g, b, a); 624 data[i] = qRgba(r, g, b, a);
626 } 625 }
627 } 626 }
628 delete [] segTbl; 627 delete [] segTbl;
629 628
630 return image; 629 return image;
631} 630}
632 631
633QImage& OImageEffect::channelIntensity(QImage &image, float percent, 632QImage& OImageEffect::channelIntensity(QImage &image, float percent,
634 RGBComponent channel) 633 RGBComponent channel)
635{ 634{
636 if (image.width() == 0 || image.height() == 0) { 635 if (image.width() == 0 || image.height() == 0) {
637 qDebug( "WARNING: OImageEffect::channelIntensity : invalid image" ); 636 qDebug( "WARNING: OImageEffect::channelIntensity : invalid image" );
638 return image; 637 return image;
639 } 638 }
640 639
641 int segColors = image.depth() > 8 ? 256 : image.numColors(); 640 int segColors = image.depth() > 8 ? 256 : image.numColors();
642 unsigned char *segTbl = new unsigned char[segColors]; 641 unsigned char *segTbl = new unsigned char[segColors];
643 int pixels = image.depth() > 8 ? image.width()*image.height() : 642 int pixels = image.depth() > 8 ? image.width()*image.height() :
644 image.numColors(); 643 image.numColors();
645 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() : 644 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
646 (unsigned int *)image.colorTable(); 645 (unsigned int *)image.colorTable();
647 bool brighten = (percent >= 0); 646 bool brighten = (percent >= 0);
648 if(percent < 0) 647 if(percent < 0)
649 percent = -percent; 648 percent = -percent;
650 649
651 if(brighten){ // keep overflow check out of loops 650 if(brighten){ // keep overflow check out of loops
652 for(int i=0; i < segColors; ++i){ 651 for(int i=0; i < segColors; ++i){
653 int tmp = (int)(i*percent); 652 int tmp = (int)(i*percent);
654 if(tmp > 255) 653 if(tmp > 255)
655 tmp = 255; 654 tmp = 255;
656 segTbl[i] = tmp; 655 segTbl[i] = tmp;
657 } 656 }
658 } 657 }
659 else{ 658 else{
660 for(int i=0; i < segColors; ++i){ 659 for(int i=0; i < segColors; ++i){
661 int tmp = (int)(i*percent); 660 int tmp = (int)(i*percent);
662 if(tmp < 0) 661 if(tmp < 0)
663 tmp = 0; 662 tmp = 0;
664 segTbl[i] = tmp; 663 segTbl[i] = tmp;
665 } 664 }
666 } 665 }
667 666
668 if(brighten){ // same here 667 if(brighten){ // same here
669 if(channel == Red){ // and here ;-) 668 if(channel == Red){ // and here ;-)
670 for(int i=0; i < pixels; ++i){ 669 for(int i=0; i < pixels; ++i){
671 int c = qRed(data[i]); 670 int c = qRed(data[i]);
672 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c]; 671 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
673 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i])); 672 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
674 } 673 }
675 } 674 }
676 if(channel == Green){ 675 if(channel == Green){
677 for(int i=0; i < pixels; ++i){ 676 for(int i=0; i < pixels; ++i){
678 int c = qGreen(data[i]); 677 int c = qGreen(data[i]);
679 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c]; 678 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
680 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i])); 679 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
681 } 680 }
682 } 681 }
683 else{ 682 else{
684 for(int i=0; i < pixels; ++i){ 683 for(int i=0; i < pixels; ++i){
685 int c = qBlue(data[i]); 684 int c = qBlue(data[i]);
686 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c]; 685 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
687 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i])); 686 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
688 } 687 }
689 } 688 }
690 689
691 } 690 }
692 else{ 691 else{
693 if(channel == Red){ 692 if(channel == Red){
694 for(int i=0; i < pixels; ++i){ 693 for(int i=0; i < pixels; ++i){
695 int c = qRed(data[i]); 694 int c = qRed(data[i]);
696 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c]; 695 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
697 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i])); 696 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
698 } 697 }
699 } 698 }
700 if(channel == Green){ 699 if(channel == Green){
701 for(int i=0; i < pixels; ++i){ 700 for(int i=0; i < pixels; ++i){
702 int c = qGreen(data[i]); 701 int c = qGreen(data[i]);
703 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c]; 702 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
704 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i])); 703 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
705 } 704 }
706 } 705 }
707 else{ 706 else{
708 for(int i=0; i < pixels; ++i){ 707 for(int i=0; i < pixels; ++i){
709 int c = qBlue(data[i]); 708 int c = qBlue(data[i]);
710 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c]; 709 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
711 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i])); 710 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
712 } 711 }
713 } 712 }
714 } 713 }
715 delete [] segTbl; 714 delete [] segTbl;
716 715
717 return image; 716 return image;
718} 717}
719 718
720// Modulate an image with an RBG channel of another image 719// Modulate an image with an RBG channel of another image
721// 720//
722QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse, 721QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse,
723 ModulationType type, int factor, RGBComponent channel) 722 ModulationType type, int factor, RGBComponent channel)
724{ 723{
725 if (image.width() == 0 || image.height() == 0 || 724 if (image.width() == 0 || image.height() == 0 ||
726 modImage.width() == 0 || modImage.height() == 0) { 725 modImage.width() == 0 || modImage.height() == 0) {
727 qDebug( "WARNING: OImageEffect::modulate : invalid image" ); 726 qDebug( "WARNING: OImageEffect::modulate : invalid image" );
728 return image; 727 return image;
729 } 728 }
730 729
731 int r, g, b, h, s, v, a; 730 int r, g, b, h, s, v, a;
732 QColor clr; 731 QColor clr;
733 int mod=0; 732 int mod=0;
734 unsigned int x1, x2, y1, y2; 733 unsigned int x1, x2, y1, y2;
735 register int x, y; 734 register int x, y;
736 735
737 // for image, we handle only depth 32 736 // for image, we handle only depth 32
738 if (image.depth()<32) image = image.convertDepth(32); 737 if (image.depth()<32) image = image.convertDepth(32);
739 738
740 // for modImage, we handle depth 8 and 32 739 // for modImage, we handle depth 8 and 32
741 if (modImage.depth()<8) modImage = modImage.convertDepth(8); 740 if (modImage.depth()<8) modImage = modImage.convertDepth(8);
742 741
743 unsigned int *colorTable2 = (modImage.depth()==8) ? 742 unsigned int *colorTable2 = (modImage.depth()==8) ?
744 modImage.colorTable():0; 743 modImage.colorTable():0;
745 unsigned int *data1, *data2; 744 unsigned int *data1, *data2;
746 unsigned char *data2b; 745 unsigned char *data2b;
747 unsigned int color1, color2; 746 unsigned int color1, color2;
748 747
749 x1 = image.width(); y1 = image.height(); 748 x1 = image.width(); y1 = image.height();
750 x2 = modImage.width(); y2 = modImage.height(); 749 x2 = modImage.width(); y2 = modImage.height();
751 750
752 for (y = 0; y < (int)y1; y++) { 751 for (y = 0; y < (int)y1; y++) {
753 data1 = (unsigned int *) image.scanLine(y); 752 data1 = (unsigned int *) image.scanLine(y);
754 data2 = (unsigned int *) modImage.scanLine( y%y2 ); 753 data2 = (unsigned int *) modImage.scanLine( y%y2 );
755 data2b = (unsigned char *) modImage.scanLine( y%y2 ); 754 data2b = (unsigned char *) modImage.scanLine( y%y2 );
756 755
757 x=0; 756 x=0;
758 while(x < (int)x1) { 757 while(x < (int)x1) {
759 color2 = (colorTable2) ? colorTable2[*data2b] : *data2; 758 color2 = (colorTable2) ? colorTable2[*data2b] : *data2;
760 if (reverse) { 759 if (reverse) {
761 color1 = color2; 760 color1 = color2;
762 color2 = *data1; 761 color2 = *data1;
763 } 762 }
764 else 763 else
765 color1 = *data1; 764 color1 = *data1;
766 765
767 if (type == Intensity || type == Contrast) { 766 if (type == Intensity || type == Contrast) {
768 r = qRed(color1); 767 r = qRed(color1);
769 g = qGreen(color1); 768 g = qGreen(color1);
770 b = qBlue(color1); 769 b = qBlue(color1);
771 if (channel != All) { 770 if (channel != All) {
772 mod = (channel == Red) ? qRed(color2) : 771 mod = (channel == Red) ? qRed(color2) :
773 (channel == Green) ? qGreen(color2) : 772 (channel == Green) ? qGreen(color2) :
774 (channel == Blue) ? qBlue(color2) : 773 (channel == Blue) ? qBlue(color2) :
775 (channel == Gray) ? qGray(color2) : 0; 774 (channel == Gray) ? qGray(color2) : 0;
776 mod = mod*factor/50; 775 mod = mod*factor/50;
777 } 776 }
778 777
779 if (type == Intensity) { 778 if (type == Intensity) {
780 if (channel == All) { 779 if (channel == All) {
781 r += r * factor/50 * qRed(color2)/256; 780 r += r * factor/50 * qRed(color2)/256;
782 g += g * factor/50 * qGreen(color2)/256; 781 g += g * factor/50 * qGreen(color2)/256;
783 b += b * factor/50 * qBlue(color2)/256; 782 b += b * factor/50 * qBlue(color2)/256;
784 } 783 }
785 else { 784 else {
786 r += r * mod/256; 785 r += r * mod/256;
787 g += g * mod/256; 786 g += g * mod/256;
788 b += b * mod/256; 787 b += b * mod/256;
789 } 788 }
790 } 789 }
791 else { // Contrast 790 else { // Contrast
792 if (channel == All) { 791 if (channel == All) {
793 r += (r-128) * factor/50 * qRed(color2)/128; 792 r += (r-128) * factor/50 * qRed(color2)/128;
794 g += (g-128) * factor/50 * qGreen(color2)/128; 793 g += (g-128) * factor/50 * qGreen(color2)/128;
795 b += (b-128) * factor/50 * qBlue(color2)/128; 794 b += (b-128) * factor/50 * qBlue(color2)/128;
796 } 795 }
797 else { 796 else {
798 r += (r-128) * mod/128; 797 r += (r-128) * mod/128;
799 g += (g-128) * mod/128; 798 g += (g-128) * mod/128;
800 b += (b-128) * mod/128; 799 b += (b-128) * mod/128;
801 } 800 }
802 } 801 }
803 802
804 if (r<0) r=0; if (r>255) r=255; 803 if (r<0) r=0; if (r>255) r=255;
805 if (g<0) g=0; if (g>255) g=255; 804 if (g<0) g=0; if (g>255) g=255;
806 if (b<0) b=0; if (b>255) b=255; 805 if (b<0) b=0; if (b>255) b=255;
807 a = qAlpha(*data1); 806 a = qAlpha(*data1);
808 *data1 = qRgba(r, g, b, a); 807 *data1 = qRgba(r, g, b, a);
809 } 808 }
810 else if (type == Saturation || type == HueShift) { 809 else if (type == Saturation || type == HueShift) {
811 clr.setRgb(color1); 810 clr.setRgb(color1);
812 clr.hsv(&h, &s, &v); 811 clr.hsv(&h, &s, &v);
813 mod = (channel == Red) ? qRed(color2) : 812 mod = (channel == Red) ? qRed(color2) :
814 (channel == Green) ? qGreen(color2) : 813 (channel == Green) ? qGreen(color2) :
815 (channel == Blue) ? qBlue(color2) : 814 (channel == Blue) ? qBlue(color2) :
816 (channel == Gray) ? qGray(color2) : 0; 815 (channel == Gray) ? qGray(color2) : 0;
817 mod = mod*factor/50; 816 mod = mod*factor/50;
818 817
819 if (type == Saturation) { 818 if (type == Saturation) {
820 s -= s * mod/256; 819 s -= s * mod/256;
821 if (s<0) s=0; if (s>255) s=255; 820 if (s<0) s=0; if (s>255) s=255;
822 } 821 }
823 else { // HueShift 822 else { // HueShift
824 h += mod; 823 h += mod;
825 while(h<0) h+=360; 824 while(h<0) h+=360;
826 h %= 360; 825 h %= 360;
827 } 826 }
828 827
829 clr.setHsv(h, s, v); 828 clr.setHsv(h, s, v);
830 a = qAlpha(*data1); 829 a = qAlpha(*data1);
831 *data1 = clr.rgb() | ((uint)(a & 0xff) << 24); 830 *data1 = clr.rgb() | ((uint)(a & 0xff) << 24);
832 } 831 }
833 data1++; data2++; data2b++; x++; 832 data1++; data2++; data2b++; x++;
834 if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; } 833 if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; }
835 } 834 }
836 } 835 }
837 return image; 836 return image;
838} 837}
839 838
840 839
841 840
842//====================================================================== 841//======================================================================
843// 842//
844// Blend effects 843// Blend effects
845// 844//
846//====================================================================== 845//======================================================================
847 846
848 847
849// Nice and fast direct pixel manipulation 848// Nice and fast direct pixel manipulation
850QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity) 849QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity)
851{ 850{
852 if (dst.width() <= 0 || dst.height() <= 0) 851 if (dst.width() <= 0 || dst.height() <= 0)
853 return dst; 852 return dst;
854 853
855 if (opacity < 0.0 || opacity > 1.0) { 854 if (opacity < 0.0 || opacity > 1.0) {
856 qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1] "); 855 qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1] ");
857 return dst; 856 return dst;
858 } 857 }
859 858
860 int depth = dst.depth(); 859 int depth = dst.depth();
861 if (depth != 32) 860 if (depth != 32)
862 dst = dst.convertDepth(32); 861 dst = dst.convertDepth(32);
863 862
864 int pixels = dst.width() * dst.height(); 863 int pixels = dst.width() * dst.height();
865 int rcol, gcol, bcol; 864 int rcol, gcol, bcol;
866 clr.rgb(&rcol, &gcol, &bcol); 865 clr.rgb(&rcol, &gcol, &bcol);
867 866
868#ifdef WORDS_BIGENDIAN // ARGB (skip alpha) 867#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
869 register unsigned char *data = (unsigned char *)dst.bits() + 1; 868 register unsigned char *data = (unsigned char *)dst.bits() + 1;
870#else // BGRA 869#else // BGRA
871 register unsigned char *data = (unsigned char *)dst.bits(); 870 register unsigned char *data = (unsigned char *)dst.bits();
872#endif 871#endif
873 872
874 for (register int i=0; i<pixels; i++) 873 for (register int i=0; i<pixels; i++)
875 { 874 {
876#ifdef WORDS_BIGENDIAN 875#ifdef WORDS_BIGENDIAN
877 *(data++) += (unsigned char)((rcol - *data) * opacity); 876 *(data++) += (unsigned char)((rcol - *data) * opacity);
878 *(data++) += (unsigned char)((gcol - *data) * opacity); 877 *(data++) += (unsigned char)((gcol - *data) * opacity);
879 *(data++) += (unsigned char)((bcol - *data) * opacity); 878 *(data++) += (unsigned char)((bcol - *data) * opacity);
880#else 879#else
881 *(data++) += (unsigned char)((bcol - *data) * opacity); 880 *(data++) += (unsigned char)((bcol - *data) * opacity);
882 *(data++) += (unsigned char)((gcol - *data) * opacity); 881 *(data++) += (unsigned char)((gcol - *data) * opacity);
883 *(data++) += (unsigned char)((rcol - *data) * opacity); 882 *(data++) += (unsigned char)((rcol - *data) * opacity);
884#endif 883#endif
885 data++; // skip alpha 884 data++; // skip alpha
886 } 885 }
887 return dst; 886 return dst;
888} 887}
889 888
890// Nice and fast direct pixel manipulation 889// Nice and fast direct pixel manipulation
891QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity) 890QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity)
892{ 891{
893 if (src.width() <= 0 || src.height() <= 0) 892 if (src.width() <= 0 || src.height() <= 0)
894 return dst; 893 return dst;
895 if (dst.width() <= 0 || dst.height() <= 0) 894 if (dst.width() <= 0 || dst.height() <= 0)
896 return dst; 895 return dst;
897 896
898 if (src.width() != dst.width() || src.height() != dst.height()) { 897 if (src.width() != dst.width() || src.height() != dst.height()) {
899 qDebug( "WARNING: OImageEffect::blend : src and destination images are not the same size" ); 898 qDebug( "WARNING: OImageEffect::blend : src and destination images are not the same size" );
900 return dst; 899 return dst;
901 } 900 }
902 901
903 if (opacity < 0.0 || opacity > 1.0) { 902 if (opacity < 0.0 || opacity > 1.0) {
904 qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]" ); 903 qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]" );
905 return dst; 904 return dst;
906 } 905 }
907 906
908 if (src.depth() != 32) src = src.convertDepth(32); 907 if (src.depth() != 32) src = src.convertDepth(32);
909 if (dst.depth() != 32) dst = dst.convertDepth(32); 908 if (dst.depth() != 32) dst = dst.convertDepth(32);
910 909
911 int pixels = src.width() * src.height(); 910 int pixels = src.width() * src.height();
912#ifdef WORDS_BIGENDIAN // ARGB (skip alpha) 911#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
913 register unsigned char *data1 = (unsigned char *)dst.bits() + 1; 912 register unsigned char *data1 = (unsigned char *)dst.bits() + 1;
914 register unsigned char *data2 = (unsigned char *)src.bits() + 1; 913 register unsigned char *data2 = (unsigned char *)src.bits() + 1;
915#else // BGRA 914#else // BGRA
916 register unsigned char *data1 = (unsigned char *)dst.bits(); 915 register unsigned char *data1 = (unsigned char *)dst.bits();
917 register unsigned char *data2 = (unsigned char *)src.bits(); 916 register unsigned char *data2 = (unsigned char *)src.bits();
918#endif 917#endif
919 918
920 for (register int i=0; i<pixels; i++) 919 for (register int i=0; i<pixels; i++)
921 { 920 {
922#ifdef WORDS_BIGENDIAN 921#ifdef WORDS_BIGENDIAN
923 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 922 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
924 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 923 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
925 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 924 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
926#else 925#else
927 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 926 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
928 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 927 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
929 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 928 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
930#endif 929#endif
931 data1++; // skip alpha 930 data1++; // skip alpha
932 data2++; 931 data2++;
933 } 932 }
934 933
935 return dst; 934 return dst;
936} 935}
937 936
938 937
939QImage& OImageEffect::blend(QImage &image, float initial_intensity, 938QImage& OImageEffect::blend(QImage &image, float initial_intensity,
940 const QColor &bgnd, GradientType eff, 939 const QColor &bgnd, GradientType eff,
941 bool anti_dir) 940 bool anti_dir)
942{ 941{
943 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) { 942 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
944 qDebug( "WARNING: OImageEffect::blend : invalid image" ); 943 qDebug( "WARNING: OImageEffect::blend : invalid image" );
945 return image; 944 return image;
946 } 945 }
947 946
948 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue(); 947 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
949 int r, g, b; 948 int r, g, b;
950 int ind; 949 int ind;
951 950
952 unsigned int xi, xf, yi, yf; 951 unsigned int xi, xf, yi, yf;
953 unsigned int a; 952 unsigned int a;
954 953
955 // check the boundaries of the initial intesity param 954 // check the boundaries of the initial intesity param
956 float unaffected = 1; 955 float unaffected = 1;
957 if (initial_intensity > 1) initial_intensity = 1; 956 if (initial_intensity > 1) initial_intensity = 1;
958 if (initial_intensity < -1) initial_intensity = -1; 957 if (initial_intensity < -1) initial_intensity = -1;
959 if (initial_intensity < 0) { 958 if (initial_intensity < 0) {
960 unaffected = 1. + initial_intensity; 959 unaffected = 1. + initial_intensity;
961 initial_intensity = 0; 960 initial_intensity = 0;
962 } 961 }
963 962
964 963
965 float intensity = initial_intensity; 964 float intensity = initial_intensity;
966 float var = 1. - initial_intensity; 965 float var = 1. - initial_intensity;
967 966
968 if (anti_dir) { 967 if (anti_dir) {
969 initial_intensity = intensity = 1.; 968 initial_intensity = intensity = 1.;
970 var = -var; 969 var = -var;
971 } 970 }
972 971
973 register int x, y; 972 register int x, y;
974 973
975 unsigned int *data = (unsigned int *)image.bits(); 974 unsigned int *data = (unsigned int *)image.bits();
976 975
977 int image_width = image.width(); //Those can't change 976 int image_width = image.width(); //Those can't change
978 int image_height = image.height(); 977 int image_height = image.height();
979 978
980 979
981 if( eff == VerticalGradient || eff == HorizontalGradient ) { 980 if( eff == VerticalGradient || eff == HorizontalGradient ) {
982 981
983 // set the image domain to apply the effect to 982 // set the image domain to apply the effect to
984 xi = 0, xf = image_width; 983 xi = 0, xf = image_width;
985 yi = 0, yf = image_height; 984 yi = 0, yf = image_height;
986 if (eff == VerticalGradient) { 985 if (eff == VerticalGradient) {
987 if (anti_dir) yf = (int)(image_height * unaffected); 986 if (anti_dir) yf = (int)(image_height * unaffected);
988 else yi = (int)(image_height * (1 - unaffected)); 987 else yi = (int)(image_height * (1 - unaffected));
989 } 988 }
990 else { 989 else {
991 if (anti_dir) xf = (int)(image_width * unaffected); 990 if (anti_dir) xf = (int)(image_width * unaffected);
992 else xi = (int)(image_height * (1 - unaffected)); 991 else xi = (int)(image_height * (1 - unaffected));
993 } 992 }
994 993
995 var /= (eff == VerticalGradient?yf-yi:xf-xi); 994 var /= (eff == VerticalGradient?yf-yi:xf-xi);
996 995
997 int ind_base; 996 int ind_base;
998 for (y = yi; y < (int)yf; y++) { 997 for (y = yi; y < (int)yf; y++) {
999 intensity = eff == VerticalGradient? intensity + var : 998 intensity = eff == VerticalGradient? intensity + var :
1000 initial_intensity; 999 initial_intensity;
1001 ind_base = image_width * y ; 1000 ind_base = image_width * y ;
1002 for (x = xi; x < (int)xf ; x++) { 1001 for (x = xi; x < (int)xf ; x++) {
1003 if (eff == HorizontalGradient) intensity += var; 1002 if (eff == HorizontalGradient) intensity += var;
1004 ind = x + ind_base; 1003 ind = x + ind_base;
1005 r = qRed (data[ind]) + (int)(intensity * 1004 r = qRed (data[ind]) + (int)(intensity *
1006 (r_bgnd - qRed (data[ind]))); 1005 (r_bgnd - qRed (data[ind])));
1007 g = qGreen(data[ind]) + (int)(intensity * 1006 g = qGreen(data[ind]) + (int)(intensity *
1008 (g_bgnd - qGreen(data[ind]))); 1007 (g_bgnd - qGreen(data[ind])));
1009 b = qBlue (data[ind]) + (int)(intensity * 1008 b = qBlue (data[ind]) + (int)(intensity *
1010 (b_bgnd - qBlue (data[ind]))); 1009 (b_bgnd - qBlue (data[ind])));
1011 if (r > 255) r = 255; if (r < 0 ) r = 0; 1010 if (r > 255) r = 255; if (r < 0 ) r = 0;
1012 if (g > 255) g = 255; if (g < 0 ) g = 0; 1011 if (g > 255) g = 255; if (g < 0 ) g = 0;
1013 if (b > 255) b = 255; if (b < 0 ) b = 0; 1012 if (b > 255) b = 255; if (b < 0 ) b = 0;
1014 a = qAlpha(data[ind]); 1013 a = qAlpha(data[ind]);
1015 data[ind] = qRgba(r, g, b, a); 1014 data[ind] = qRgba(r, g, b, a);
1016 } 1015 }
1017 } 1016 }
1018 } 1017 }
1019 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) { 1018 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
1020 float xvar = var / 2 / image_width; // / unaffected; 1019 float xvar = var / 2 / image_width; // / unaffected;
1021 float yvar = var / 2 / image_height; // / unaffected; 1020 float yvar = var / 2 / image_height; // / unaffected;
1022 float tmp; 1021 float tmp;
1023 1022
1024 for (x = 0; x < image_width ; x++) { 1023 for (x = 0; x < image_width ; x++) {
1025 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1); 1024 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
1026 ind = x; 1025 ind = x;
1027 for (y = 0; y < image_height ; y++) { 1026 for (y = 0; y < image_height ; y++) {
1028 intensity = initial_intensity + tmp + yvar * y; 1027 intensity = initial_intensity + tmp + yvar * y;
1029 1028
1030 r = qRed (data[ind]) + (int)(intensity * 1029 r = qRed (data[ind]) + (int)(intensity *
1031 (r_bgnd - qRed (data[ind]))); 1030 (r_bgnd - qRed (data[ind])));
1032 g = qGreen(data[ind]) + (int)(intensity * 1031 g = qGreen(data[ind]) + (int)(intensity *
1033 (g_bgnd - qGreen(data[ind]))); 1032 (g_bgnd - qGreen(data[ind])));
1034 b = qBlue (data[ind]) + (int)(intensity * 1033 b = qBlue (data[ind]) + (int)(intensity *
1035 (b_bgnd - qBlue (data[ind]))); 1034 (b_bgnd - qBlue (data[ind])));
1036 if (r > 255) r = 255; if (r < 0 ) r = 0; 1035 if (r > 255) r = 255; if (r < 0 ) r = 0;
1037 if (g > 255) g = 255; if (g < 0 ) g = 0; 1036 if (g > 255) g = 255; if (g < 0 ) g = 0;
1038 if (b > 255) b = 255; if (b < 0 ) b = 0; 1037 if (b > 255) b = 255; if (b < 0 ) b = 0;
1039 a = qAlpha(data[ind]); 1038 a = qAlpha(data[ind]);
1040 data[ind] = qRgba(r, g, b, a); 1039 data[ind] = qRgba(r, g, b, a);
1041 1040
1042 ind += image_width; 1041 ind += image_width;
1043 } 1042 }
1044 } 1043 }
1045 } 1044 }
1046 1045
1047 else if (eff == RectangleGradient || eff == EllipticGradient) { 1046 else if (eff == RectangleGradient || eff == EllipticGradient) {
1048 float xvar; 1047 float xvar;
1049 float yvar; 1048 float yvar;
1050 1049
1051 for (x = 0; x < image_width / 2 + image_width % 2; x++) { 1050 for (x = 0; x < image_width / 2 + image_width % 2; x++) {
1052 xvar = var / image_width * (image_width - x*2/unaffected-1); 1051 xvar = var / image_width * (image_width - x*2/unaffected-1);
1053 for (y = 0; y < image_height / 2 + image_height % 2; y++) { 1052 for (y = 0; y < image_height / 2 + image_height % 2; y++) {
1054 yvar = var / image_height * (image_height - y*2/unaffected -1); 1053 yvar = var / image_height * (image_height - y*2/unaffected -1);
1055 1054
1056 if (eff == RectangleGradient) 1055 if (eff == RectangleGradient)
1057 intensity = initial_intensity + QMAX(xvar, yvar); 1056 intensity = initial_intensity + QMAX(xvar, yvar);
1058 else 1057 else
1059 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar); 1058 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1060 if (intensity > 1) intensity = 1; 1059 if (intensity > 1) intensity = 1;
1061 if (intensity < 0) intensity = 0; 1060 if (intensity < 0) intensity = 0;
1062 1061
1063 //NW 1062 //NW
1064 ind = x + image_width * y ; 1063 ind = x + image_width * y ;
1065 r = qRed (data[ind]) + (int)(intensity * 1064 r = qRed (data[ind]) + (int)(intensity *
1066 (r_bgnd - qRed (data[ind]))); 1065 (r_bgnd - qRed (data[ind])));
1067 g = qGreen(data[ind]) + (int)(intensity * 1066 g = qGreen(data[ind]) + (int)(intensity *
1068 (g_bgnd - qGreen(data[ind]))); 1067 (g_bgnd - qGreen(data[ind])));
1069 b = qBlue (data[ind]) + (int)(intensity * 1068 b = qBlue (data[ind]) + (int)(intensity *
1070 (b_bgnd - qBlue (data[ind]))); 1069 (b_bgnd - qBlue (data[ind])));
1071 if (r > 255) r = 255; if (r < 0 ) r = 0; 1070 if (r > 255) r = 255; if (r < 0 ) r = 0;
1072 if (g > 255) g = 255; if (g < 0 ) g = 0; 1071 if (g > 255) g = 255; if (g < 0 ) g = 0;
1073 if (b > 255) b = 255; if (b < 0 ) b = 0; 1072 if (b > 255) b = 255; if (b < 0 ) b = 0;
1074 a = qAlpha(data[ind]); 1073 a = qAlpha(data[ind]);
1075 data[ind] = qRgba(r, g, b, a); 1074 data[ind] = qRgba(r, g, b, a);
1076 1075
1077 //NE 1076 //NE
1078 ind = image_width - x - 1 + image_width * y ; 1077 ind = image_width - x - 1 + image_width * y ;
1079 r = qRed (data[ind]) + (int)(intensity * 1078 r = qRed (data[ind]) + (int)(intensity *
1080 (r_bgnd - qRed (data[ind]))); 1079 (r_bgnd - qRed (data[ind])));
1081 g = qGreen(data[ind]) + (int)(intensity * 1080 g = qGreen(data[ind]) + (int)(intensity *
1082 (g_bgnd - qGreen(data[ind]))); 1081 (g_bgnd - qGreen(data[ind])));
1083 b = qBlue (data[ind]) + (int)(intensity * 1082 b = qBlue (data[ind]) + (int)(intensity *
1084 (b_bgnd - qBlue (data[ind]))); 1083 (b_bgnd - qBlue (data[ind])));
1085 if (r > 255) r = 255; if (r < 0 ) r = 0; 1084 if (r > 255) r = 255; if (r < 0 ) r = 0;
1086 if (g > 255) g = 255; if (g < 0 ) g = 0; 1085 if (g > 255) g = 255; if (g < 0 ) g = 0;
1087 if (b > 255) b = 255; if (b < 0 ) b = 0; 1086 if (b > 255) b = 255; if (b < 0 ) b = 0;
1088 a = qAlpha(data[ind]); 1087 a = qAlpha(data[ind]);
1089 data[ind] = qRgba(r, g, b, a); 1088 data[ind] = qRgba(r, g, b, a);
1090 } 1089 }
1091 } 1090 }
1092 1091
1093 //CT loop is doubled because of stupid central row/column issue. 1092 //CT loop is doubled because of stupid central row/column issue.
1094 // other solution? 1093 // other solution?
1095 for (x = 0; x < image_width / 2; x++) { 1094 for (x = 0; x < image_width / 2; x++) {
1096 xvar = var / image_width * (image_width - x*2/unaffected-1); 1095 xvar = var / image_width * (image_width - x*2/unaffected-1);
1097 for (y = 0; y < image_height / 2; y++) { 1096 for (y = 0; y < image_height / 2; y++) {
1098 yvar = var / image_height * (image_height - y*2/unaffected -1); 1097 yvar = var / image_height * (image_height - y*2/unaffected -1);
1099 1098
1100 if (eff == RectangleGradient) 1099 if (eff == RectangleGradient)
1101 intensity = initial_intensity + QMAX(xvar, yvar); 1100 intensity = initial_intensity + QMAX(xvar, yvar);
1102 else 1101 else
1103 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar); 1102 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1104 if (intensity > 1) intensity = 1; 1103 if (intensity > 1) intensity = 1;
1105 if (intensity < 0) intensity = 0; 1104 if (intensity < 0) intensity = 0;
1106 1105
1107 //SW 1106 //SW
1108 ind = x + image_width * (image_height - y -1) ; 1107 ind = x + image_width * (image_height - y -1) ;
1109 r = qRed (data[ind]) + (int)(intensity * 1108 r = qRed (data[ind]) + (int)(intensity *
1110 (r_bgnd - qRed (data[ind]))); 1109 (r_bgnd - qRed (data[ind])));
1111 g = qGreen(data[ind]) + (int)(intensity * 1110 g = qGreen(data[ind]) + (int)(intensity *
1112 (g_bgnd - qGreen(data[ind]))); 1111 (g_bgnd - qGreen(data[ind])));
1113 b = qBlue (data[ind]) + (int)(intensity * 1112 b = qBlue (data[ind]) + (int)(intensity *
1114 (b_bgnd - qBlue (data[ind]))); 1113 (b_bgnd - qBlue (data[ind])));
1115 if (r > 255) r = 255; if (r < 0 ) r = 0; 1114 if (r > 255) r = 255; if (r < 0 ) r = 0;
1116 if (g > 255) g = 255; if (g < 0 ) g = 0; 1115 if (g > 255) g = 255; if (g < 0 ) g = 0;
1117 if (b > 255) b = 255; if (b < 0 ) b = 0; 1116 if (b > 255) b = 255; if (b < 0 ) b = 0;
1118 a = qAlpha(data[ind]); 1117 a = qAlpha(data[ind]);
1119 data[ind] = qRgba(r, g, b, a); 1118 data[ind] = qRgba(r, g, b, a);
1120 1119
1121 //SE 1120 //SE
1122 ind = image_width-x-1 + image_width * (image_height - y - 1) ; 1121 ind = image_width-x-1 + image_width * (image_height - y - 1) ;
1123 r = qRed (data[ind]) + (int)(intensity * 1122 r = qRed (data[ind]) + (int)(intensity *
1124 (r_bgnd - qRed (data[ind]))); 1123 (r_bgnd - qRed (data[ind])));
1125 g = qGreen(data[ind]) + (int)(intensity * 1124 g = qGreen(data[ind]) + (int)(intensity *
1126 (g_bgnd - qGreen(data[ind]))); 1125 (g_bgnd - qGreen(data[ind])));
1127 b = qBlue (data[ind]) + (int)(intensity * 1126 b = qBlue (data[ind]) + (int)(intensity *
1128 (b_bgnd - qBlue (data[ind]))); 1127 (b_bgnd - qBlue (data[ind])));
1129 if (r > 255) r = 255; if (r < 0 ) r = 0; 1128 if (r > 255) r = 255; if (r < 0 ) r = 0;
1130 if (g > 255) g = 255; if (g < 0 ) g = 0; 1129 if (g > 255) g = 255; if (g < 0 ) g = 0;
1131 if (b > 255) b = 255; if (b < 0 ) b = 0; 1130 if (b > 255) b = 255; if (b < 0 ) b = 0;
1132 a = qAlpha(data[ind]); 1131 a = qAlpha(data[ind]);
1133 data[ind] = qRgba(r, g, b, a); 1132 data[ind] = qRgba(r, g, b, a);
1134 } 1133 }
1135 } 1134 }
1136 } 1135 }
1137 else qDebug( "OImageEffect::blend effect not implemented" ); 1136 else qDebug( "OImageEffect::blend effect not implemented" );
1138 return image; 1137 return image;
1139} 1138}
1140 1139
1141// Not very efficient as we create a third big image... 1140// Not very efficient as we create a third big image...
1142// 1141//
1143QImage& OImageEffect::blend(QImage &image1, QImage &image2, 1142QImage& OImageEffect::blend(QImage &image1, QImage &image2,
1144 GradientType gt, int xf, int yf) 1143 GradientType gt, int xf, int yf)
1145{ 1144{
1146 if (image1.width() == 0 || image1.height() == 0 || 1145 if (image1.width() == 0 || image1.height() == 0 ||
1147 image2.width() == 0 || image2.height() == 0) 1146 image2.width() == 0 || image2.height() == 0)
1148 return image1; 1147 return image1;
1149 1148
1150 QImage image3; 1149 QImage image3;
1151 1150
1152 image3 = OImageEffect::unbalancedGradient(image1.size(), 1151 image3 = OImageEffect::unbalancedGradient(image1.size(),
1153 QColor(0,0,0), QColor(255,255,255), 1152 QColor(0,0,0), QColor(255,255,255),
1154 gt, xf, yf, 0); 1153 gt, xf, yf, 0);
1155 1154
1156 return blend(image1,image2,image3, Red); // Channel to use is arbitrary 1155 return blend(image1,image2,image3, Red); // Channel to use is arbitrary
1157} 1156}
1158 1157
1159// Blend image2 into image1, using an RBG channel of blendImage 1158// Blend image2 into image1, using an RBG channel of blendImage
1160// 1159//
1161QImage& OImageEffect::blend(QImage &image1, QImage &image2, 1160QImage& OImageEffect::blend(QImage &image1, QImage &image2,
1162 QImage &blendImage, RGBComponent channel) 1161 QImage &blendImage, RGBComponent channel)
1163{ 1162{
1164 if (image1.width() == 0 || image1.height() == 0 || 1163 if (image1.width() == 0 || image1.height() == 0 ||
1165 image2.width() == 0 || image2.height() == 0 || 1164 image2.width() == 0 || image2.height() == 0 ||
1166 blendImage.width() == 0 || blendImage.height() == 0) { 1165 blendImage.width() == 0 || blendImage.height() == 0) {
1167 qDebug( "OImageEffect::blend effect invalid image" ); 1166 qDebug( "OImageEffect::blend effect invalid image" );
1168 return image1; 1167 return image1;
1169 } 1168 }
1170 1169
1171 int r, g, b; 1170 int r, g, b;
1172 int ind1, ind2, ind3; 1171 int ind1, ind2, ind3;
1173 1172
1174 unsigned int x1, x2, x3, y1, y2, y3; 1173 unsigned int x1, x2, x3, y1, y2, y3;
1175 unsigned int a; 1174 unsigned int a;
1176 1175
1177 register int x, y; 1176 register int x, y;
1178 1177
1179 // for image1 and image2, we only handle depth 32 1178 // for image1 and image2, we only handle depth 32
1180 if (image1.depth()<32) image1 = image1.convertDepth(32); 1179 if (image1.depth()<32) image1 = image1.convertDepth(32);
1181 if (image2.depth()<32) image2 = image2.convertDepth(32); 1180 if (image2.depth()<32) image2 = image2.convertDepth(32);
1182 1181
1183 // for blendImage, we handle depth 8 and 32 1182 // for blendImage, we handle depth 8 and 32
1184 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8); 1183 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
1185 1184
1186 unsigned int *colorTable3 = (blendImage.depth()==8) ? 1185 unsigned int *colorTable3 = (blendImage.depth()==8) ?
1187 blendImage.colorTable():0; 1186 blendImage.colorTable():0;
1188 1187
1189 unsigned int *data1 = (unsigned int *)image1.bits(); 1188 unsigned int *data1 = (unsigned int *)image1.bits();
1190 unsigned int *data2 = (unsigned int *)image2.bits(); 1189 unsigned int *data2 = (unsigned int *)image2.bits();
1191 unsigned int *data3 = (unsigned int *)blendImage.bits(); 1190 unsigned int *data3 = (unsigned int *)blendImage.bits();
1192 unsigned char *data3b = (unsigned char *)blendImage.bits(); 1191 unsigned char *data3b = (unsigned char *)blendImage.bits();
1193 unsigned int color3; 1192 unsigned int color3;
1194 1193
1195 x1 = image1.width(); y1 = image1.height(); 1194 x1 = image1.width(); y1 = image1.height();
1196 x2 = image2.width(); y2 = image2.height(); 1195 x2 = image2.width(); y2 = image2.height();
1197 x3 = blendImage.width(); y3 = blendImage.height(); 1196 x3 = blendImage.width(); y3 = blendImage.height();
1198 1197
1199 for (y = 0; y < (int)y1; y++) { 1198 for (y = 0; y < (int)y1; y++) {
1200 ind1 = x1*y; 1199 ind1 = x1*y;
1201 ind2 = x2*(y%y2); 1200 ind2 = x2*(y%y2);
1202 ind3 = x3*(y%y3); 1201 ind3 = x3*(y%y3);
1203 1202
1204 x=0; 1203 x=0;
1205 while(x < (int)x1) { 1204 while(x < (int)x1) {
1206 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3]; 1205 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
1207 1206
1208 a = (channel == Red) ? qRed(color3) : 1207 a = (channel == Red) ? qRed(color3) :
1209 (channel == Green) ? qGreen(color3) : 1208 (channel == Green) ? qGreen(color3) :
1210 (channel == Blue) ? qBlue(color3) : qGray(color3); 1209 (channel == Blue) ? qBlue(color3) : qGray(color3);
1211 1210
1212 r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256; 1211 r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256;
1213 g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256; 1212 g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256;
1214 b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256; 1213 b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256;
1215 1214
1216 a = qAlpha(data1[ind1]); 1215 a = qAlpha(data1[ind1]);
1217 data1[ind1] = qRgba(r, g, b, a); 1216 data1[ind1] = qRgba(r, g, b, a);
1218 1217
1219 ind1++; ind2++; ind3++; x++; 1218 ind1++; ind2++; ind3++; x++;
1220 if ( (x%x2) ==0) ind2 -= x2; 1219 if ( (x%x2) ==0) ind2 -= x2;
1221 if ( (x%x3) ==0) ind3 -= x3; 1220 if ( (x%x3) ==0) ind3 -= x3;
1222 } 1221 }
1223 } 1222 }
1224 return image1; 1223 return image1;
1225} 1224}
1226 1225
1227 1226
1228//====================================================================== 1227//======================================================================
1229// 1228//
1230// Hash effects 1229// Hash effects
1231// 1230//
1232//====================================================================== 1231//======================================================================
1233 1232
1234unsigned int OImageEffect::lHash(unsigned int c) 1233unsigned int OImageEffect::lHash(unsigned int c)
1235{ 1234{
1236 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c); 1235 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
1237 unsigned char nr, ng, nb; 1236 unsigned char nr, ng, nb;
1238 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr; 1237 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
1239 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng; 1238 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
1240 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb; 1239 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
1241 1240
1242 return qRgba(nr, ng, nb, a); 1241 return qRgba(nr, ng, nb, a);
1243} 1242}
1244 1243
1245 1244
1246// ----------------------------------------------------------------------------- 1245// -----------------------------------------------------------------------------
1247 1246
1248unsigned int OImageEffect::uHash(unsigned int c) 1247unsigned int OImageEffect::uHash(unsigned int c)
1249{ 1248{
1250 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c); 1249 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
1251 unsigned char nr, ng, nb; 1250 unsigned char nr, ng, nb;
1252 nr = r + (r >> 3); nr = nr < r ? ~0 : nr; 1251 nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
1253 ng = g + (g >> 3); ng = ng < g ? ~0 : ng; 1252 ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
1254 nb = b + (b >> 3); nb = nb < b ? ~0 : nb; 1253 nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
1255 1254
1256 return qRgba(nr, ng, nb, a); 1255 return qRgba(nr, ng, nb, a);
1257} 1256}
1258 1257
1259 1258
1260// ----------------------------------------------------------------------------- 1259// -----------------------------------------------------------------------------
1261 1260
1262QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing) 1261QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing)
1263{ 1262{
1264 if (image.width() == 0 || image.height() == 0) { 1263 if (image.width() == 0 || image.height() == 0) {
1265 qDebug( "OImageEffect::hash effect invalid image" ); 1264 qDebug( "OImageEffect::hash effect invalid image" );
1266 return image; 1265 return image;
1267 } 1266 }
1268 1267
1269 register int x, y; 1268 register int x, y;
1270 unsigned int *data = (unsigned int *)image.bits(); 1269 unsigned int *data = (unsigned int *)image.bits();
1271 unsigned int ind; 1270 unsigned int ind;
1272 1271
1273 //CT no need to do it if not enough space 1272 //CT no need to do it if not enough space
1274 if ((lite == NorthLite || 1273 if ((lite == NorthLite ||
1275 lite == SouthLite)&& 1274 lite == SouthLite)&&
1276 (unsigned)image.height() < 2+spacing) return image; 1275 (unsigned)image.height() < 2+spacing) return image;
1277 if ((lite == EastLite || 1276 if ((lite == EastLite ||
1278 lite == WestLite)&& 1277 lite == WestLite)&&
1279 (unsigned)image.height() < 2+spacing) return image; 1278 (unsigned)image.height() < 2+spacing) return image;
1280 1279
1281 if (lite == NorthLite || lite == SouthLite) { 1280 if (lite == NorthLite || lite == SouthLite) {
1282 for (y = 0 ; y < image.height(); y = y + 2 + spacing) { 1281 for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
1283 for (x = 0; x < image.width(); x++) { 1282 for (x = 0; x < image.width(); x++) {
1284 ind = x + image.width() * y; 1283 ind = x + image.width() * y;
1285 data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]); 1284 data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]);
1286 1285
1287 ind = ind + image.width(); 1286 ind = ind + image.width();
1288 data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]); 1287 data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]);
1289 } 1288 }
1290 } 1289 }
1291 } 1290 }
1292 1291
1293 else if (lite == EastLite || lite == WestLite) { 1292 else if (lite == EastLite || lite == WestLite) {
1294 for (y = 0 ; y < image.height(); y++) { 1293 for (y = 0 ; y < image.height(); y++) {
1295 for (x = 0; x < image.width(); x = x + 2 + spacing) { 1294 for (x = 0; x < image.width(); x = x + 2 + spacing) {
1296 ind = x + image.width() * y; 1295 ind = x + image.width() * y;
1297 data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]); 1296 data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]);
1298 1297
1299 ind++; 1298 ind++;
1300 data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]); 1299 data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]);
1301 } 1300 }
1302 } 1301 }
1303 } 1302 }
1304 1303
1305 else if (lite == NWLite || lite == SELite) { 1304 else if (lite == NWLite || lite == SELite) {
1306 for (y = 0 ; y < image.height(); y++) { 1305 for (y = 0 ; y < image.height(); y++) {
1307 for (x = 0; 1306 for (x = 0;
1308 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing); 1307 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
1309 x = x + 2 + spacing) { 1308 x = x + 2 + spacing) {
1310 ind = x + image.width() * y + ((y & 1)? 1 : 0); 1309 ind = x + image.width() * y + ((y & 1)? 1 : 0);
1311 data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]); 1310 data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]);
1312 1311
1313 ind++; 1312 ind++;
1314 data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]); 1313 data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]);
1315 } 1314 }
1316 } 1315 }
1317 } 1316 }
1318 1317
1319 else if (lite == SWLite || lite == NELite) { 1318 else if (lite == SWLite || lite == NELite) {
1320 for (y = 0 ; y < image.height(); y++) { 1319 for (y = 0 ; y < image.height(); y++) {
1321 for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) { 1320 for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) {
1322 ind = x + image.width() * y - ((y & 1)? 1 : 0); 1321 ind = x + image.width() * y - ((y & 1)? 1 : 0);
1323 data[ind] = lite==SWLite?uHash(data[ind]):lHash(data[ind]); 1322 data[ind] = lite==SWLite?uHash(data[ind]):lHash(data[ind]);
1324 1323
1325 ind++; 1324 ind++;
1326 data[ind] = lite==SWLite?lHash(data[ind]):uHash(data[ind]); 1325 data[ind] = lite==SWLite?lHash(data[ind]):uHash(data[ind]);
1327 } 1326 }
1328 } 1327 }
1329 } 1328 }
1330 1329
1331 return image; 1330 return image;
1332} 1331}
1333 1332
1334 1333
1335//====================================================================== 1334//======================================================================
1336// 1335//
1337// Flatten effects 1336// Flatten effects
1338// 1337//
1339//====================================================================== 1338//======================================================================
1340 1339
1341QImage& OImageEffect::flatten(QImage &img, const QColor &ca, 1340QImage& OImageEffect::flatten(QImage &img, const QColor &ca,
1342 const QColor &cb, int ncols) 1341 const QColor &cb, int ncols)
1343{ 1342{
1344 if (img.width() == 0 || img.height() == 0) 1343 if (img.width() == 0 || img.height() == 0)
1345 return img; 1344 return img;
1346 1345
1347 // a bitmap is easy... 1346 // a bitmap is easy...
1348 if (img.depth() == 1) { 1347 if (img.depth() == 1) {
1349 img.setColor(0, ca.rgb()); 1348 img.setColor(0, ca.rgb());
1350 img.setColor(1, cb.rgb()); 1349 img.setColor(1, cb.rgb());
1351 return img; 1350 return img;
1352 } 1351 }
1353 1352
1354 int r1 = ca.red(); int r2 = cb.red(); 1353 int r1 = ca.red(); int r2 = cb.red();
1355 int g1 = ca.green(); int g2 = cb.green(); 1354 int g1 = ca.green(); int g2 = cb.green();
1356 int b1 = ca.blue(); int b2 = cb.blue(); 1355 int b1 = ca.blue(); int b2 = cb.blue();
1357 int min = 0, max = 255; 1356 int min = 0, max = 255;
1358 1357
1359 QRgb col; 1358 QRgb col;
1360 1359
1361 // Get minimum and maximum greylevel. 1360 // Get minimum and maximum greylevel.
1362 if (img.numColors()) { 1361 if (img.numColors()) {
1363 // pseudocolor 1362 // pseudocolor
1364 for (int i = 0; i < img.numColors(); i++) { 1363 for (int i = 0; i < img.numColors(); i++) {
1365 col = img.color(i); 1364 col = img.color(i);
1366 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3; 1365 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1367 min = QMIN(min, mean); 1366 min = QMIN(min, mean);
1368 max = QMAX(max, mean); 1367 max = QMAX(max, mean);
1369 } 1368 }
1370 } else { 1369 } else {
1371 // truecolor 1370 // truecolor
1372 for (int y=0; y < img.height(); y++) 1371 for (int y=0; y < img.height(); y++)
1373 for (int x=0; x < img.width(); x++) { 1372 for (int x=0; x < img.width(); x++) {
1374 col = img.pixel(x, y); 1373 col = img.pixel(x, y);
1375 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3; 1374 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1376 min = QMIN(min, mean); 1375 min = QMIN(min, mean);
1377 max = QMAX(max, mean); 1376 max = QMAX(max, mean);
1378 } 1377 }
1379 } 1378 }
1380 1379
1381 // Conversion factors 1380 // Conversion factors
1382 float sr = ((float) r2 - r1) / (max - min); 1381 float sr = ((float) r2 - r1) / (max - min);
1383 float sg = ((float) g2 - g1) / (max - min); 1382 float sg = ((float) g2 - g1) / (max - min);
1384 float sb = ((float) b2 - b1) / (max - min); 1383 float sb = ((float) b2 - b1) / (max - min);
1385 1384
1386 1385
1387 // Repaint the image 1386 // Repaint the image
1388 if (img.numColors()) { 1387 if (img.numColors()) {
1389 for (int i=0; i < img.numColors(); i++) { 1388 for (int i=0; i < img.numColors(); i++) {
1390 col = img.color(i); 1389 col = img.color(i);
1391 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3; 1390 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1392 int r = (int) (sr * (mean - min) + r1 + 0.5); 1391 int r = (int) (sr * (mean - min) + r1 + 0.5);
1393 int g = (int) (sg * (mean - min) + g1 + 0.5); 1392 int g = (int) (sg * (mean - min) + g1 + 0.5);
1394 int b = (int) (sb * (mean - min) + b1 + 0.5); 1393 int b = (int) (sb * (mean - min) + b1 + 0.5);
1395 img.setColor(i, qRgba(r, g, b, qAlpha(col))); 1394 img.setColor(i, qRgba(r, g, b, qAlpha(col)));
1396 } 1395 }
1397 } else { 1396 } else {
1398 for (int y=0; y < img.height(); y++) 1397 for (int y=0; y < img.height(); y++)
1399 for (int x=0; x < img.width(); x++) { 1398 for (int x=0; x < img.width(); x++) {
1400 col = img.pixel(x, y); 1399 col = img.pixel(x, y);
1401 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3; 1400 int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
1402 int r = (int) (sr * (mean - min) + r1 + 0.5); 1401 int r = (int) (sr * (mean - min) + r1 + 0.5);
1403 int g = (int) (sg * (mean - min) + g1 + 0.5); 1402 int g = (int) (sg * (mean - min) + g1 + 0.5);
1404 int b = (int) (sb * (mean - min) + b1 + 0.5); 1403 int b = (int) (sb * (mean - min) + b1 + 0.5);
1405 img.setPixel(x, y, qRgba(r, g, b, qAlpha(col))); 1404 img.setPixel(x, y, qRgba(r, g, b, qAlpha(col)));
1406 } 1405 }
1407 } 1406 }
1408 1407
1409 1408
1410 // Dither if necessary 1409 // Dither if necessary
1411 if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols))) 1410 if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols)))
1412 return img; 1411 return img;
1413 1412
1414 if (ncols == 1) ncols++; 1413 if (ncols == 1) ncols++;
1415 if (ncols > 256) ncols = 256; 1414 if (ncols > 256) ncols = 256;
1416 1415
1417 QColor *pal = new QColor[ncols]; 1416 QColor *pal = new QColor[ncols];
1418 sr = ((float) r2 - r1) / (ncols - 1); 1417 sr = ((float) r2 - r1) / (ncols - 1);
1419 sg = ((float) g2 - g1) / (ncols - 1); 1418 sg = ((float) g2 - g1) / (ncols - 1);
1420 sb = ((float) b2 - b1) / (ncols - 1); 1419 sb = ((float) b2 - b1) / (ncols - 1);
1421 1420
1422 for (int i=0; i<ncols; i++) 1421 for (int i=0; i<ncols; i++)
1423 pal[i] = QColor(r1 + int(sr*i), g1 + int(sg*i), b1 + int(sb*i)); 1422 pal[i] = QColor(r1 + int(sr*i), g1 + int(sg*i), b1 + int(sb*i));
1424 1423
1425 dither(img, pal, ncols); 1424 dither(img, pal, ncols);
1426 1425
1427 delete[] pal; 1426 delete[] pal;
1428 return img; 1427 return img;
1429} 1428}
1430 1429
1431 1430
1432//====================================================================== 1431//======================================================================
1433// 1432//
1434// Fade effects 1433// Fade effects
1435// 1434//
1436//====================================================================== 1435//======================================================================
1437 1436
1438QImage& OImageEffect::fade(QImage &img, float val, const QColor &color) 1437QImage& OImageEffect::fade(QImage &img, float val, const QColor &color)
1439{ 1438{
1440 if (img.width() == 0 || img.height() == 0) 1439 if (img.width() == 0 || img.height() == 0)
1441 return img; 1440 return img;
1442 1441
1443 // We don't handle bitmaps 1442 // We don't handle bitmaps
1444 if (img.depth() == 1) 1443 if (img.depth() == 1)
1445 return img; 1444 return img;
1446 1445
1447 unsigned char tbl[256]; 1446 unsigned char tbl[256];
1448 for (int i=0; i<256; i++) 1447 for (int i=0; i<256; i++)
1449 tbl[i] = (int) (val * i + 0.5); 1448 tbl[i] = (int) (val * i + 0.5);
1450 1449
1451 int red = color.red(); 1450 int red = color.red();
1452 int green = color.green(); 1451 int green = color.green();
1453 int blue = color.blue(); 1452 int blue = color.blue();
1454 1453
1455 QRgb col; 1454 QRgb col;
1456 int r, g, b, cr, cg, cb; 1455 int r, g, b, cr, cg, cb;
1457 1456
1458 if (img.depth() <= 8) { 1457 if (img.depth() <= 8) {
1459 // pseudo color 1458 // pseudo color
1460 for (int i=0; i<img.numColors(); i++) { 1459 for (int i=0; i<img.numColors(); i++) {
1461 col = img.color(i); 1460 col = img.color(i);
1462 cr = qRed(col); cg = qGreen(col); cb = qBlue(col); 1461 cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
1463 if (cr > red) 1462 if (cr > red)
1464 r = cr - tbl[cr - red]; 1463 r = cr - tbl[cr - red];
1465 else 1464 else
1466 r = cr + tbl[red - cr]; 1465 r = cr + tbl[red - cr];
1467 if (cg > green) 1466 if (cg > green)
1468 g = cg - tbl[cg - green]; 1467 g = cg - tbl[cg - green];
1469 else 1468 else
1470 g = cg + tbl[green - cg]; 1469 g = cg + tbl[green - cg];
1471 if (cb > blue) 1470 if (cb > blue)
1472 b = cb - tbl[cb - blue]; 1471 b = cb - tbl[cb - blue];
1473 else 1472 else
1474 b = cb + tbl[blue - cb]; 1473 b = cb + tbl[blue - cb];
1475 img.setColor(i, qRgba(r, g, b, qAlpha(col))); 1474 img.setColor(i, qRgba(r, g, b, qAlpha(col)));
1476 } 1475 }
1477 1476
1478 } else { 1477 } else {
1479 // truecolor 1478 // truecolor
1480 for (int y=0; y<img.height(); y++) { 1479 for (int y=0; y<img.height(); y++) {
1481 QRgb *data = (QRgb *) img.scanLine(y); 1480 QRgb *data = (QRgb *) img.scanLine(y);
1482 for (int x=0; x<img.width(); x++) { 1481 for (int x=0; x<img.width(); x++) {
1483 col = *data; 1482 col = *data;
1484 cr = qRed(col); cg = qGreen(col); cb = qBlue(col); 1483 cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
1485 if (cr > red) 1484 if (cr > red)
1486 r = cr - tbl[cr - red]; 1485 r = cr - tbl[cr - red];
1487 else 1486 else
1488 r = cr + tbl[red - cr]; 1487 r = cr + tbl[red - cr];
1489 if (cg > green) 1488 if (cg > green)
1490 g = cg - tbl[cg - green]; 1489 g = cg - tbl[cg - green];
1491 else 1490 else
1492 g = cg + tbl[green - cg]; 1491 g = cg + tbl[green - cg];
1493 if (cb > blue) 1492 if (cb > blue)
1494 b = cb - tbl[cb - blue]; 1493 b = cb - tbl[cb - blue];
1495 else 1494 else
1496 b = cb + tbl[blue - cb]; 1495 b = cb + tbl[blue - cb];
1497 *data++ = qRgba(r, g, b, qAlpha(col)); 1496 *data++ = qRgba(r, g, b, qAlpha(col));
1498 } 1497 }
1499 } 1498 }
1500 } 1499 }
1501 1500
1502 return img; 1501 return img;
1503} 1502}
1504 1503
1505//====================================================================== 1504//======================================================================
1506// 1505//
1507// Color effects 1506// Color effects
1508// 1507//
1509//====================================================================== 1508//======================================================================
1510 1509
1511// This code is adapted from code (C) Rik Hemsley <rik@kde.org> 1510// This code is adapted from code (C) Rik Hemsley <rik@kde.org>
1512// 1511//
1513// The formula used (r + b + g) /3 is different from the qGray formula 1512// The formula used (r + b + g) /3 is different from the qGray formula
1514// used by Qt. This is because our formula is much much faster. If, 1513// used by Qt. This is because our formula is much much faster. If,
1515// however, it turns out that this is producing sub-optimal images, 1514// however, it turns out that this is producing sub-optimal images,
1516// then it will have to change (kurt) 1515// then it will have to change (kurt)
1517// 1516//
1518// It does produce lower quality grayscale ;-) Use fast == true for the fast 1517// It does produce lower quality grayscale ;-) Use fast == true for the fast
1519// algorithm, false for the higher quality one (mosfet). 1518// algorithm, false for the higher quality one (mosfet).
1520QImage& OImageEffect::toGray(QImage &img, bool fast) 1519QImage& OImageEffect::toGray(QImage &img, bool fast)
1521{ 1520{
1522 if (img.width() == 0 || img.height() == 0) 1521 if (img.width() == 0 || img.height() == 0)
1523 return img; 1522 return img;
1524 1523
1525 if(fast){ 1524 if(fast){
1526 if (img.depth() == 32) { 1525 if (img.depth() == 32) {
1527 register uchar * r(img.bits()); 1526 register uchar * r(img.bits());
1528 register uchar * g(img.bits() + 1); 1527 register uchar * g(img.bits() + 1);
1529 register uchar * b(img.bits() + 2); 1528 register uchar * b(img.bits() + 2);
1530 1529
1531 uchar * end(img.bits() + img.numBytes()); 1530 uchar * end(img.bits() + img.numBytes());
1532 1531
1533 while (r != end) { 1532 while (r != end) {
1534 1533
1535 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3 1534 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
1536 1535
1537 r += 4; 1536 r += 4;
1538 g += 4; 1537 g += 4;
1539 b += 4; 1538 b += 4;
1540 } 1539 }
1541 } 1540 }
1542 else 1541 else
1543 { 1542 {
1544 for (int i = 0; i < img.numColors(); i++) 1543 for (int i = 0; i < img.numColors(); i++)
1545 { 1544 {
1546 register uint r = qRed(img.color(i)); 1545 register uint r = qRed(img.color(i));
1547 register uint g = qGreen(img.color(i)); 1546 register uint g = qGreen(img.color(i));
1548 register uint b = qBlue(img.color(i)); 1547 register uint b = qBlue(img.color(i));
1549 1548
1550 register uint gray = (((r + g) >> 1) + b) >> 1; 1549 register uint gray = (((r + g) >> 1) + b) >> 1;
1551 img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i)))); 1550 img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i))));
1552 } 1551 }
1553 } 1552 }
1554 } 1553 }
1555 else{ 1554 else{
1556 int pixels = img.depth() > 8 ? img.width()*img.height() : 1555 int pixels = img.depth() > 8 ? img.width()*img.height() :
1557 img.numColors(); 1556 img.numColors();
1558 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() : 1557 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
1559 (unsigned int *)img.colorTable(); 1558 (unsigned int *)img.colorTable();
1560 int val, i; 1559 int val, i;
1561 for(i=0; i < pixels; ++i){ 1560 for(i=0; i < pixels; ++i){
1562 val = qGray(data[i]); 1561 val = qGray(data[i]);
1563 data[i] = qRgba(val, val, val, qAlpha(data[i])); 1562 data[i] = qRgba(val, val, val, qAlpha(data[i]));
1564 } 1563 }
1565 } 1564 }
1566 return img; 1565 return img;
1567} 1566}
1568 1567
1569// CT 29Jan2000 - desaturation algorithms 1568// CT 29Jan2000 - desaturation algorithms
1570QImage& OImageEffect::desaturate(QImage &img, float desat) 1569QImage& OImageEffect::desaturate(QImage &img, float desat)
1571{ 1570{
1572 if (img.width() == 0 || img.height() == 0) 1571 if (img.width() == 0 || img.height() == 0)