Subversion Repositories Scribus

Rev

Rev 5555 | Rev 5593 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
2004 fschmid 7
#include "scimage.h"
8
#include "scribus.h"
5243 cbradney 9
#include "scribuscore.h"
2074 fschmid 10
#include <qtextstream.h>
2125 cbradney 11
#include <cassert>
2004 fschmid 12
#ifdef HAVE_CMS
13
        #include CMS_INC
14
extern cmsHPROFILE CMSoutputProf;
15
extern cmsHPROFILE CMSprinterProf;
5369 mrdocs 16
extern cmsHTRANSFORM stdTransRGBMonG;
17
extern cmsHTRANSFORM stdTransCMYKMonG;
2004 fschmid 18
extern cmsHTRANSFORM stdProofG;
19
extern cmsHTRANSFORM stdTransImgG;
20
extern cmsHTRANSFORM stdProofImgG;
21
extern bool BlackPoint;
22
extern bool SoftProofing;
23
extern bool Gamut;
24
extern bool CMSuse;
5345 mrdocs 25
extern int IntentColors;
26
extern int IntentImages;
2004 fschmid 27
#endif
4506 cbradney 28
#include "gsutil.h"
3685 fschmid 29
#include "exif.h"
4546 subik 30
#include "commonstrings.h"
2004 fschmid 31
 
32
 
33
typedef struct my_error_mgr
34
{
35
        struct jpeg_error_mgr pub;            /* "public" fields */
36
        jmp_buf setjmp_buffer;  /* for return to caller */
37
}
38
*my_error_ptr;
39
 
40
static void my_error_exit (j_common_ptr cinfo)
41
{
42
        my_error_ptr myerr = (my_error_ptr) cinfo->err;
43
        (*cinfo->err->output_message) (cinfo);
44
        longjmp (myerr->setjmp_buffer, 1);
45
}
46
 
47
static QDataStream & operator>> ( QDataStream & s, ScImage::PSDHeader & header )
48
{
49
        s >> header.signature;
50
        s >> header.version;
51
        for( int i = 0; i < 6; i++ )
52
        {
53
                s >> header.reserved[i];
54
        }
55
        s >> header.channel_count;
56
        s >> header.height;
57
        s >> header.width;
58
        s >> header.depth;
59
        s >> header.color_mode;
60
        return s;
61
}
62
 
4222 craig 63
ScImage::ScImage(const QImage & image) : QImage(image)
2004 fschmid 64
{
2012 fschmid 65
        initialize();
2004 fschmid 66
}
67
 
68
ScImage::ScImage() : QImage()
69
{
2012 fschmid 70
        initialize();
2004 fschmid 71
}
72
 
73
ScImage::ScImage( int width, int height ) : QImage( width, height, 32 )
74
{
2012 fschmid 75
        initialize();
76
}
77
 
78
void ScImage::initialize()
79
{
2004 fschmid 80
        imgInfo.xres = 72;
81
        imgInfo.yres = 72;
82
        imgInfo.colorspace = 0;
83
        imgInfo.valid = false;
84
        imgInfo.isRequest = false;
5567 mrdocs 85
        imgInfo.isEmbedded = false;
2004 fschmid 86
        imgInfo.progressive = false;
3703 fschmid 87
        imgInfo.exifDataValid = false;
2025 fschmid 88
        imgInfo.lowResType = 1;
89
        imgInfo.lowResScale = 1.0;
2004 fschmid 90
        imgInfo.PDSpathData.clear();
91
        imgInfo.RequestProps.clear();
92
        imgInfo.clipPath = "";
93
        imgInfo.usedPath = "";
94
        imgInfo.layerInfo.clear();
3703 fschmid 95
        imgInfo.exifInfo.cameraName = "";
96
        imgInfo.exifInfo.cameraVendor = "";
97
        imgInfo.exifInfo.thumbnail = QImage();
4331 fschmid 98
        imgInfo.BBoxX = 0;
99
        imgInfo.BBoxH = 0;
2004 fschmid 100
}
101
 
4050 cbradney 102
ScImage::~ScImage()
103
{
104
        curveTable.resize(0);
105
}
106
 
2886 fschmid 107
void ScImage::applyEffect(QValueList<imageEffect> effectsList, QMap<QString,ScColor> colors, bool cmyk)
2074 fschmid 108
{
109
        if (effectsList.count() != 0)
110
        {
111
                for (uint a = 0; a < effectsList.count(); ++a)
112
                {
2082 fschmid 113
                        if ((*effectsList.at(a)).effectCode == EF_INVERT)
2074 fschmid 114
                                invert(cmyk);
2082 fschmid 115
                        if ((*effectsList.at(a)).effectCode == EF_GRAYSCALE)
2074 fschmid 116
                                toGrayscale(cmyk);
2082 fschmid 117
                        if ((*effectsList.at(a)).effectCode == EF_COLORIZE)
2074 fschmid 118
                        {
119
                                QString tmpstr = (*effectsList.at(a)).effectParameters;
4546 subik 120
                                QString col = CommonStrings::None;
2074 fschmid 121
                                int shading = 100;
122
                                QTextStream fp(&tmpstr, IO_ReadOnly);
123
                                fp >> col;
124
                                fp >> shading;
125
                                colorize(colors[col], shading, cmyk);
126
                        }
2082 fschmid 127
                        if ((*effectsList.at(a)).effectCode == EF_BRIGHTNESS)
128
                        {
129
                                QString tmpstr = (*effectsList.at(a)).effectParameters;
130
                                int brightnessValue = 0;
131
                                QTextStream fp(&tmpstr, IO_ReadOnly);
132
                                fp >> brightnessValue;
133
                                brightness(brightnessValue, cmyk);
134
                        }
135
                        if ((*effectsList.at(a)).effectCode == EF_CONTRAST)
136
                        {
137
                                QString tmpstr = (*effectsList.at(a)).effectParameters;
138
                                int contrastValue = 0;
139
                                QTextStream fp(&tmpstr, IO_ReadOnly);
140
                                fp >> contrastValue;
141
                                contrast(contrastValue, cmyk);
142
                        }
2092 fschmid 143
                        if ((*effectsList.at(a)).effectCode == EF_SHARPEN)
144
                        {
145
                                QString tmpstr = (*effectsList.at(a)).effectParameters;
146
                                double radius, sigma;
147
                                QTextStream fp(&tmpstr, IO_ReadOnly);
148
                                fp >> radius;
149
                                fp >> sigma;
150
                                sharpen(radius, sigma);
151
                        }
2095 fschmid 152
                        if ((*effectsList.at(a)).effectCode == EF_BLUR)
153
                        {
154
                                QString tmpstr = (*effectsList.at(a)).effectParameters;
155
                                double radius, sigma;
156
                                QTextStream fp(&tmpstr, IO_ReadOnly);
157
                                fp >> radius;
158
                                fp >> sigma;
159
                                blur(radius, sigma);
160
                        }
2096 fschmid 161
                        if ((*effectsList.at(a)).effectCode == EF_SOLARIZE)
162
                        {
163
                                QString tmpstr = (*effectsList.at(a)).effectParameters;
164
                                double sigma;
165
                                QTextStream fp(&tmpstr, IO_ReadOnly);
166
                                fp >> sigma;
167
                                solarize(sigma, cmyk);
168
                        }
2074 fschmid 169
                }
170
        }
171
}
172
 
2095 fschmid 173
void ScImage::liberateMemory(void **memory)
174
{
175
        assert(memory != (void **)NULL);
176
        if(*memory == (void *)NULL)
177
                return;
178
        free(*memory);
179
        *memory=(void *) NULL;
180
}
181
 
2096 fschmid 182
void ScImage::solarize(double factor, bool cmyk)
183
{
184
        curveTable.resize(256);
185
        int fk = qRound(255 / factor);
186
        for (int i = 0; i < 256; ++i)
187
        {
188
                curveTable[i] = QMIN(255, static_cast<int>(i / fk) * fk);
189
        }
190
        applyCurve(cmyk);
191
}
192
 
2095 fschmid 193
void ScImage::blurScanLine(double *kernel, int width, unsigned int *src, unsigned int *dest, int columns)
194
{
195
        register double *p;
196
        unsigned int *q;
197
        register int x;
198
        register long i;
199
        double red, green, blue, alpha;
200
        double scale = 0.0;
201
        if(width > columns)
202
        {
203
                for(x=0; x < columns; ++x)
204
                {
205
                        scale = 0.0;
206
                        red = blue = green = alpha = 0.0;
207
                        p = kernel;
208
                        q = src;
209
                        for(i=0; i < columns; ++i)
210
                        {
211
                                if((i >= (x-width/2)) && (i <= (x+width/2)))
212
                                {
213
                                        red += (*p)*(qRed(*q)*257);
214
                                        green += (*p)*(qGreen(*q)*257);
215
                                        blue += (*p)*(qBlue(*q)*257);
216
                                        alpha += (*p)*(qAlpha(*q)*257);
217
                                }
218
                                if(((i+width/2-x) >= 0) && ((i+width/2-x) < width))
219
                                        scale+=kernel[i+width/2-x];
220
                                p++;
221
                                q++;
222
                        }
223
                        scale = 1.0/scale;
224
                        red = scale*(red+0.5);
225
                        green = scale*(green+0.5);
226
                        blue = scale*(blue+0.5);
227
                        alpha = scale*(alpha+0.5);
228
                        red = red < 0 ? 0 : red > 65535 ? 65535 : red;
229
                        green = green < 0 ? 0 : green > 65535 ? 65535 : green;
230
                        blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
231
                        alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
232
                        dest[x] = qRgba((unsigned char)(red/257UL),
233
                                        (unsigned char)(green/257UL),
234
                                        (unsigned char)(blue/257UL),
235
                                        (unsigned char)(alpha/257UL));
236
                }
237
                return;
238
        }
239
 
240
        for(x=0; x < width/2; ++x)
241
        {
242
                scale = 0.0;
243
                red = blue = green = alpha = 0.0;
244
                p = kernel+width/2-x;
245
                q = src;
246
                for(i=width/2-x; i < width; ++i)
247
                {
248
                        red += (*p)*(qRed(*q)*257);
249
                        green += (*p)*(qGreen(*q)*257);
250
                        blue += (*p)*(qBlue(*q)*257);
251
                        alpha += (*p)*(qAlpha(*q)*257);
252
                        scale += (*p);
253
                        p++;
254
                        q++;
255
                }
256
                scale=1.0/scale;
257
                red = scale*(red+0.5);
258
                green = scale*(green+0.5);
259
                blue = scale*(blue+0.5);
260
                alpha = scale*(alpha+0.5);
261
                red = red < 0 ? 0 : red > 65535 ? 65535 : red;
262
                green = green < 0 ? 0 : green > 65535 ? 65535 : green;
263
                blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
264
                alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
265
                dest[x] = qRgba((unsigned char)(red/257UL),
266
                                (unsigned char)(green/257UL),
267
                                (unsigned char)(blue/257UL),
268
                                (unsigned char)(alpha/257UL));
269
        }
270
        for(; x < columns-width/2; ++x)
271
        {
272
                red = blue = green = alpha = 0.0;
273
                p = kernel;
274
                q = src+(x-width/2);
275
                for (i=0; i < (long) width; ++i)
276
                {
277
                        red += (*p)*(qRed(*q)*257);
278
                        green += (*p)*(qGreen(*q)*257);
279
                        blue += (*p)*(qBlue(*q)*257);
280
                        alpha += (*p)*(qAlpha(*q)*257);
281
                        p++;
282
                        q++;
283
                }
284
                red = scale*(red+0.5);
285
                green = scale*(green+0.5);
286
                blue = scale*(blue+0.5);
287
                alpha = scale*(alpha+0.5);
288
                red = red < 0 ? 0 : red > 65535 ? 65535 : red;
289
                green = green < 0 ? 0 : green > 65535 ? 65535 : green;
290
                blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
291
                alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
292
                dest[x] = qRgba((unsigned char)(red/257UL),
293
                                (unsigned char)(green/257UL),
294
                                (unsigned char)(blue/257UL),
295
                                (unsigned char)(alpha/257UL));
296
        }
297
        for(; x < columns; ++x)
298
        {
299
                red = blue = green = alpha = 0.0;
300
                scale=0;
301
                p = kernel;
302
                q = src+(x-width/2);
303
                for(i=0; i < columns-x+width/2; ++i)
304
                {
305
                        red += (*p)*(qRed(*q)*257);
306
                        green += (*p)*(qGreen(*q)*257);
307
                        blue += (*p)*(qBlue(*q)*257);
308
                        alpha += (*p)*(qAlpha(*q)*257);
309
                        scale += (*p);
310
                        p++;
311
                        q++;
312
                }
313
                scale=1.0/scale;
314
                red = scale*(red+0.5);
315
                green = scale*(green+0.5);
316
                blue = scale*(blue+0.5);
317
                alpha = scale*(alpha+0.5);
318
                red = red < 0 ? 0 : red > 65535 ? 65535 : red;
319
                green = green < 0 ? 0 : green > 65535 ? 65535 : green;
320
                blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
321
                alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
322
                dest[x] = qRgba((unsigned char)(red/257UL),
323
                                (unsigned char)(green/257UL),
324
                                (unsigned char)(blue/257UL),
325
                                (unsigned char)(alpha/257UL));
326
        }
327
}
328
 
329
int ScImage::getBlurKernel(int width, double sigma, double **kernel)
330
{
331
        double alpha, normalize;
332
        register long i;
333
        int bias;
334
        assert(sigma != 0.0);
335
        if(width == 0)
336
                width = 3;
337
        *kernel=(double *)malloc(width*sizeof(double));
338
        if(*kernel == (double *)NULL)
339
                return(0);
340
        memset(*kernel, 0, width*sizeof(double));
341
        bias = 3*width/2;
342
        for(i=(-bias); i <= bias; i++)
343
        {
344
                alpha=exp(-((double) i*i)/(2.0*3*3*sigma*sigma));
345
                (*kernel)[(i+bias)/3]+=alpha/(2.50662827463100024161235523934010416269302368164062*sigma);
346
        }
347
        normalize=0;
348
        for(i=0; i < width; i++)
349
                normalize+=(*kernel)[i];
350
        for(i=0; i < width; i++)
351
                (*kernel)[i]/=normalize;
352
        return(width);
353
}
354
 
355
void ScImage::blur(double radius, double sigma)
356
{
357
        double *kernel;
358
        QImage dest;
359
        int widthk;
360
        int x, y;
361
        unsigned int *scanline, *temp;
362
        unsigned int *p, *q;
363
        if(sigma == 0.0)
364
                return;
365
        kernel=(double *) NULL;
366
        if(radius > 0)
367
                widthk=getBlurKernel((int) (2*ceil(radius)+1),sigma,&kernel);
368
        else
369
        {
370
                double *last_kernel;
371
                last_kernel=(double *) NULL;
372
                widthk=getBlurKernel(3,sigma,&kernel);
373
                while ((long) (255*kernel[0]) > 0)
374
                {
375
                        if(last_kernel != (double *)NULL)
376
                        {
377
                                liberateMemory((void **) &last_kernel);
378
                        }
379
                        last_kernel=kernel;
380
                        kernel = (double *)NULL;
381
                        widthk = getBlurKernel(widthk+2, sigma, &kernel);
382
                }
383
                if(last_kernel != (double *) NULL)
384
                {
385
                        liberateMemory((void **) &kernel);
386
                        widthk-=2;
387
                        kernel = last_kernel;
388
                }
389
        }
390
        if(widthk < 3)
391
        {
392
                liberateMemory((void **) &kernel);
393
                return;
394
        }
395
        dest.create(width(), height(), 32);
396
        scanline = (unsigned int *)malloc(sizeof(unsigned int)*height());
397
        temp = (unsigned int *)malloc(sizeof(unsigned int)*height());
398
        for(y=0; y < height(); ++y)
399
        {
400
                p = (unsigned int *)scanLine(y);
401
                q = (unsigned int *)dest.scanLine(y);
402
                blurScanLine(kernel, widthk, p, q, width());
403
        }
404
        unsigned int **srcTable = (unsigned int **)jumpTable();
405
        unsigned int **destTable = (unsigned int **)dest.jumpTable();
406
        for(x=0; x < width(); ++x)
407
        {
408
                for(y=0; y < height(); ++y)
409
                {
410
                        scanline[y] = srcTable[y][x];
411
                }
412
                blurScanLine(kernel, widthk, scanline, temp, height());
413
                for(y=0; y < height(); ++y)
414
                {
415
                        destTable[y][x] = temp[y];
416
                }
417
        }
418
        liberateMemory((void **) &scanline);
419
        liberateMemory((void **) &temp);
420
        liberateMemory((void **) &kernel);
421
        for( int yi=0; yi < dest.height(); ++yi )
422
        {
423
                QRgb *s = (QRgb*)(dest.scanLine( yi ));
424
                QRgb *d = (QRgb*)(scanLine( yi ));
425
                for(int xi=0; xi < dest.width(); ++xi )
426
                {
427
                        (*d) = (*s);
428
                        s++;
429
                        d++;
430
                }
431
        }
432
        return;
433
}
434
 
2092 fschmid 435
bool ScImage::convolveImage(QImage *dest, const unsigned int order, const double *kernel)
436
{
437
        long widthk;
438
        double red, green, blue, alpha;
439
        double normalize, *normal_kernel;
440
        register const double *k;
441
        register unsigned int *q;
442
        int x, y, mx, my, sx, sy;
443
        long i;
444
        int mcx, mcy;
445
        widthk = order;
446
        if((widthk % 2) == 0)
447
                return(false);
448
        normal_kernel = (double *)malloc(widthk*widthk*sizeof(double));
449
        if(!normal_kernel)
450
                return(false);
451
        dest->reset();
452
        dest->create(width(), height(), 32);
453
        normalize=0.0;
454
        for(i=0; i < (widthk*widthk); i++)
455
                normalize += kernel[i];
456
        if(fabs(normalize) <= 1.0e-12)
457
                normalize=1.0;
458
        normalize=1.0/normalize;
459
        for(i=0; i < (widthk*widthk); i++)
460
                normal_kernel[i] = normalize*kernel[i];
461
        unsigned int **jumpTablek = (unsigned int **)jumpTable();
462
        for(y=0; y < dest->height(); ++y)
463
        {
464
                sy = y-(widthk/2);
465
                q = (unsigned int *)dest->scanLine(y);
466
                for(x=0; x < dest->width(); ++x)
467
                {
468
                        k = normal_kernel;
469
                        red = green = blue = alpha = 0;
470
                        sy = y-(widthk/2);
471
                        for(mcy=0; mcy < widthk; ++mcy, ++sy)
472
                        {
473
                                my = sy < 0 ? 0 : sy > height()-1 ? height()-1 : sy;
474
                                sx = x+(-widthk/2);
475
                                for(mcx=0; mcx < widthk; ++mcx, ++sx)
476
                                {
477
                                        mx = sx < 0 ? 0 : sx > width()-1 ? width()-1 : sx;
478
                                        red += (*k)*(qRed(jumpTablek[my][mx])*257);
479
                                        green += (*k)*(qGreen(jumpTablek[my][mx])*257);
480
                                        blue += (*k)*(qBlue(jumpTablek[my][mx])*257);
481
                                        alpha += (*k)*(qAlpha(jumpTablek[my][mx])*257);
482
                                        ++k;
483
                                }
484
                        }
485
                        red = red < 0 ? 0 : red > 65535 ? 65535 : red+0.5;
486
                        green = green < 0 ? 0 : green > 65535 ? 65535 : green+0.5;
487
                        blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue+0.5;
488
                        alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha+0.5;
489
                        *q++ = qRgba((unsigned char)(red/257UL),
2095 fschmid 490
                                     (unsigned char)(green/257UL),
491
                                     (unsigned char)(blue/257UL),
492
                                     (unsigned char)(alpha/257UL));
2092 fschmid 493
                }
494
        }
2095 fschmid 495
        free(normal_kernel);
2092 fschmid 496
        return(true);
497
}
498
 
499
int ScImage::getOptimalKernelWidth(double radius, double sigma)
500
{
501
        double normalize, value;
502
        long width;
503
        register long u;
504
        assert(sigma != 0.0);
505
        if(radius > 0.0)
506
                return((int)(2.0*ceil(radius)+1.0));
507
        for(width=5; ;)
508
        {
509
                normalize=0.0;
510
                for(u=(-width/2); u <= (width/2); u++)
511
                        normalize+=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma);
512
                u=width/2;
513
                value=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma)/normalize;
514
                if((long)(65535*value) <= 0)
515
                        break;
516
                width+=2;
517
        }
518
        return((int)width-2);
519
}
520
 
521
void ScImage::sharpen(double radius, double sigma)
522
{
523
        double alpha, normalize, *kernel;
524
        int widthk;
525
        register long i, u, v;
526
        QImage dest;
527
        if(sigma == 0.0)
528
                return;
529
        widthk = getOptimalKernelWidth(radius, sigma);
530
        if(width() < widthk)
531
                return;
532
        kernel = (double *)malloc(widthk*widthk*sizeof(double));
533
        if(!kernel)
534
                return;
535
        i = 0;
536
        normalize=0.0;
537
        for (v=(-widthk/2); v <= (widthk/2); v++)
538
        {
539
                for (u=(-widthk/2); u <= (widthk/2); u++)
540
                {
541
                        alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
542
                        kernel[i]=alpha/(2.0*3.14159265358979323846264338327950288419716939937510*sigma*sigma);
543
                        normalize+=kernel[i];
544
                        i++;
545
                }
546
        }
547
        kernel[i/2]=(-2.0)*normalize;
548
        convolveImage(&dest, widthk, kernel);
2095 fschmid 549
        liberateMemory((void **) &kernel);
2092 fschmid 550
        for( int yi=0; yi < dest.height(); ++yi )
551
        {
552
                QRgb *s = (QRgb*)(dest.scanLine( yi ));
553
                QRgb *d = (QRgb*)(scanLine( yi ));
554
                for(int xi=0; xi < dest.width(); ++xi )
555
                {
556
                        (*d) = (*s);
557
                        s++;
558
                        d++;
559
                }
560
        }
561
        return;
562
}
563
 
2082 fschmid 564
void ScImage::contrast(int contrastValue, bool cmyk)
565
{
566
        curveTable.resize(256);
567
        QPoint p1(0,0 - contrastValue);
568
        QPoint p2(256, 256 + contrastValue);
569
        double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
570
        for (int i = 0; i < 256; ++i)
571
        {
572
                curveTable[i] = QMIN(255, QMAX(0, int(i * mc) + p1.y()));
573
        }
574
        applyCurve(cmyk);
575
}
576
 
577
void ScImage::brightness(int brightnessValue, bool cmyk)
578
{
579
        curveTable.resize(256);
580
        QPoint p1(0,0 + brightnessValue);
581
        QPoint p2(256, 256 + brightnessValue);
582
        double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
583
        for (int i = 0; i < 256; ++i)
584
        {
585
                curveTable[i] = QMIN(255, QMAX(0, int(i * mc) + p1.y()));
586
        }
587
        applyCurve(cmyk);
588
}
589
 
590
void ScImage::applyCurve(bool cmyk)
591
{
592
        int h = height();
593
        int w = width();
594
        for( int yi=0; yi < h; ++yi )
595
        {
596
                QRgb * s = (QRgb*)(scanLine( yi ));
597
                for( int xi=0; xi < w; ++xi )
598
                {
599
                        QRgb r=*s;
600
                        int c, m, y, k;
601
                        if (cmyk)
602
                        {
2766 cbradney 603
                                unsigned char *p = (unsigned char *) s;
604
                                unsigned char rc = 255 - QMIN(255, p[0] + p[3]);
605
                                unsigned char gc = 255 - QMIN(255, p[1] + p[3]);
606
                                unsigned char bc = 255 - QMIN(255, p[2] + p[3]);
4419 cbradney 607
                                c = 255 - curveTable[(int)rc];
608
                                m = 255 - curveTable[(int)gc];
609
                                y = 255 - curveTable[(int)bc];
2082 fschmid 610
                                k = QMIN(QMIN(c, m), y);
611
                                *s = qRgba(y - k, m - k, c - k, k );
612
                        }
613
                        else
614
                        {
615
                                c = curveTable[qRed(r)];
616
                                m = curveTable[qGreen(r)];
617
                                y = curveTable[qBlue(r)];
618
                                k = qAlpha(r);
619
                                *s = qRgba(c, m, y, k);
620
                        }
621
                        s++;
622
                }
623
        }
624
}
625
 
2886 fschmid 626
void ScImage::colorize(ScColor color, int shade, bool cmyk)
2053 fschmid 627
{
628
        int h = height();
629
        int w = width();
630
        int cc, cm, cy, ck;
2057 fschmid 631
        int hu, sa, v;
2886 fschmid 632
        ScColor tmp2;
2057 fschmid 633
        QColor tmpR;
2053 fschmid 634
        if (cmyk)
2057 fschmid 635
                color.getShadeColorCMYK(&cc, &cm, &cy, &ck, shade);
2053 fschmid 636
        else
637
        {
638
                ck = 0;
2057 fschmid 639
                color.getShadeColorRGB(&cc, &cm, &cy, shade);
2053 fschmid 640
        }
641
        for( int yi=0; yi < h; ++yi )
642
        {
643
                QRgb * s = (QRgb*)(scanLine( yi ));
644
                for( int xi=0; xi < w; ++xi )
645
                {
646
                        QRgb r=*s;
647
                        if (cmyk)
648
                        {
2057 fschmid 649
                                double k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255) / 255.0;
2053 fschmid 650
                                *s = qRgba(QMIN(qRound(cc*k), 255), QMIN(qRound(cm*k), 255), QMIN(qRound(cy*k), 255), QMIN(qRound(ck*k), 255));
651
                        }
652
                        else
653
                        {
2057 fschmid 654
                                int k = 255 - QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
655
                                int cc2, cm2, cy2;
656
                                tmpR.setRgb(cc, cm, cy);
657
                                tmpR.hsv(&hu, &sa, &v);
658
                                if (cc == cm && cm == cy)
659
                                        tmpR.setHsv(hu, sa, 255 - ((255 - v) * k / 255));
660
                                else
661
                                        tmpR.setHsv(hu, sa * k / 255, v);
662
                                tmpR.getRgb(&cc2, &cm2, &cy2);
2053 fschmid 663
                                int a = qAlpha(r);
2057 fschmid 664
                                *s = qRgba(cc2, cm2, cy2, a);
2053 fschmid 665
                        }
666
                        s++;
667
                }
668
        }
669
}
670
 
2057 fschmid 671
void ScImage::invert(bool cmyk)
672
{
673
        int h = height();
674
        int w = width();
675
        for( int yi=0; yi < h; ++yi )
676
        {
677
                QRgb * s = (QRgb*)(scanLine( yi ));
678
                for( int xi=0; xi < w; ++xi )
679
                {
680
                        if (cmyk)
681
                        {
2766 cbradney 682
                                unsigned char *p = (unsigned char *) s;
2057 fschmid 683
                                unsigned char c, m, y, k;
2766 cbradney 684
                                c = 255 - QMIN(255, p[0] + p[3]);
685
                                m = 255 - QMIN(255, p[1] + p[3]);
686
                                y = 255 - QMIN(255, p[2] + p[3]);
2061 fschmid 687
                                k = QMIN(QMIN(c, m), y);
2766 cbradney 688
                                p[0] = c - k;
689
                                p[1] = m - k;
690
                                p[2] = y - k;
691
                                p[3] = k;
2057 fschmid 692
                        }
693
                        else
2766 cbradney 694
                                *s ^= 0x00ffffff;
2057 fschmid 695
                        s++;
696
                }
697
        }
698
}
699
 
2053 fschmid 700
void ScImage::toGrayscale(bool cmyk)
701
{
702
        int h = height();
703
        int w = width();
704
        for( int yi=0; yi < h; ++yi )
705
        {
706
                QRgb * s = (QRgb*)(scanLine( yi ));
707
                for( int xi=0; xi < w; ++xi )
708
                {
709
                        QRgb r=*s;
710
                        int k;
711
                        if (cmyk)
712
                        {
2056 fschmid 713
                                k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
2053 fschmid 714
                                *s = qRgba(0, 0, 0, k);
715
                        }
716
                        else
717
                        {
718
                                k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
719
                                int a = qAlpha(r);
720
                                *s = qRgba(k, k, k, a);
721
                        }
722
                        s++;
723
                }
724
        }
725
}
726
 
2012 fschmid 727
void ScImage::swapRGBA()
728
{
729
        for (int i = 0; i < height(); ++i)
730
        {
2766 cbradney 731
                unsigned int *ptr = (unsigned int *) scanLine(i);
732
                unsigned char r, b;
2012 fschmid 733
                for (int j = 0; j < width(); ++j)
734
                {
735
                        unsigned char *p = (unsigned char *) ptr;
2766 cbradney 736
                        r = p[0];
737
                        b = p[2];
738
                        p[2] = r;
739
                        p[0] = b;
740
                        ptr++;
2012 fschmid 741
                }
742
        }
743
}
744
 
2025 fschmid 745
void ScImage::createLowRes(double scale)
2012 fschmid 746
{
2025 fschmid 747
        int w = qRound(width() / scale);
748
        int h = qRound(height() / scale);
2012 fschmid 749
        QImage tmp = smoothScale(w, h);
750
        create(w, h, 32);
751
        for( int yi=0; yi < tmp.height(); ++yi )
752
        {
753
                QRgb *s = (QRgb*)(tmp.scanLine( yi ));
754
                QRgb *d = (QRgb*)(scanLine( yi ));
755
                for(int xi=0; xi < tmp.width(); ++xi )
756
                {
757
                        (*d) = (*s);
758
                        s++;
759
                        d++;
760
                }
761
        }
762
}
763
 
2004 fschmid 764
void ScImage::Convert2JPG(QString fn, int Quality, bool isCMYK, bool isGray)
765
{
766
        struct jpeg_compress_struct cinfo;
767
        struct my_error_mgr         jerr;
768
        FILE     *outfile;
769
        JSAMPROW row_pointer[1];
770
        row_pointer[0] = 0;
771
        cinfo.err = jpeg_std_error (&jerr.pub);
772
        jerr.pub.error_exit = my_error_exit;
773
        outfile = NULL;
774
        if (setjmp (jerr.setjmp_buffer))
775
        {
776
                jpeg_destroy_compress (&cinfo);
777
                if (outfile)
778
                        fclose (outfile);
779
                return;
780
        }
781
        jpeg_create_compress (&cinfo);
2643 craig 782
        if ((outfile = fopen (fn.local8Bit(), "wb")) == NULL)
2004 fschmid 783
                return;
784
        jpeg_stdio_dest (&cinfo, outfile);
785
        cinfo.image_width  = width();
786
        cinfo.image_height = height();
787
        if (isCMYK)
788
        {
789
                cinfo.in_color_space = JCS_CMYK;
790
                cinfo.input_components = 4;
791
        }
792
        else
793
        {
794
                if (isGray)
795
                {
796
                        cinfo.in_color_space = JCS_GRAYSCALE;
797
                        cinfo.input_components = 1;
798
                }
799
                else
800
                {
801
                        cinfo.in_color_space = JCS_RGB;
802
                        cinfo.input_components = 3;
803
                }
804
        }
805
        jpeg_set_defaults (&cinfo);
806
        int qual[] = { 95, 85, 75, 50, 25 };  // These are the JPEG Quality settings 100 means best, 0 .. don't discuss
807
        jpeg_set_quality (&cinfo, qual[Quality], true);
2680 cbradney 808
        jpeg_start_compress (&cinfo, true);
2004 fschmid 809
        row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
810
        int w = cinfo.image_width;
811
        while (cinfo.next_scanline < cinfo.image_height)
812
        {
813
                uchar *row = row_pointer[0];
814
                if (isCMYK)
815
                {
816
                        QRgb* rgba = (QRgb*)scanLine(cinfo.next_scanline);
817
                        for (int i=0; i<w; ++i)
818
                        {
3963 fschmid 819
                                *row++ = 255-qRed(*rgba);
820
                                *row++ = 255-qGreen(*rgba);
821
                                *row++ = 255-qBlue(*rgba);
822
                                *row++ = 255-qAlpha(*rgba);
2004 fschmid 823
                                ++rgba;
824
                        }
825
                }
826
                else
827
                {
828
                        if (isGray)
829
                        {
830
                                QRgb* rgba = (QRgb*)scanLine(cinfo.next_scanline);
831
                                for (int i=0; i<w; ++i)
832
                                {
833
                                        *row++ = qRed(*rgba);
834
                                        ++rgba;
835
                                }
836
                        }
837
                        else
838
                        {
839
                                QRgb* rgb = (QRgb*)scanLine(cinfo.next_scanline);
840
                                for (int i=0; i<w; i++)
841
                                {
842
                                        *row++ = qRed(*rgb);
843
                                        *row++ = qGreen(*rgb);
844
                                        *row++ = qBlue(*rgb);
845
                                        ++rgb;
846
                                }
847
                        }
848
                }
849
                jpeg_write_scanlines (&cinfo, row_pointer, 1);
850
        }
851
        jpeg_finish_compress (&cinfo);
852
        fclose (outfile);
853
        jpeg_destroy_compress (&cinfo);
854
        delete [] row_pointer[0];
855
}
856
 
5234 fschmid 857
QByteArray ScImage::ImageToArray()
2004 fschmid 858
{
2884 fschmid 859
        int i = 0;
2004 fschmid 860
        int h = height();
861
        int w = width();
2884 fschmid 862
        unsigned char u;
5234 fschmid 863
        QByteArray imgArray(3 * h * w);
2004 fschmid 864
        for( int yi=0; yi < h; ++yi )
865
        {
866
                QRgb * s = (QRgb*)(scanLine( yi ));
867
                for( int xi=0; xi < w; ++xi )
868
                {
869
                        QRgb r=*s++;
2884 fschmid 870
                        u=qRed(r);
5234 fschmid 871
                        imgArray[i++] = u;
2004 fschmid 872
                        u=qGreen(r);
5234 fschmid 873
                        imgArray[i++] = u;
2004 fschmid 874
                        u=qBlue(r);
5234 fschmid 875
                        imgArray[i++] = u;
2004 fschmid 876
                }
877
        }
5234 fschmid 878
        return imgArray;
2004 fschmid 879
}
880
 
5234 fschmid 881
QByteArray ScImage::ImageToGray()
2004 fschmid 882
{
2884 fschmid 883
        int i = 0;
2004 fschmid 884
        int h = height();
885
        int w = width();
5234 fschmid 886
        QByteArray imgArray(h * w);
2004 fschmid 887
        for( int yi=0; yi < h; ++yi )
888
        {
889
                QRgb * s = (QRgb*)(scanLine( yi ));
890
                for( int xi=0; xi < w; ++xi )
891
                {
892
                        QRgb r=*s;
893
                        int k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
894
                        *s = qRgba(k, 0, 0, 0);
5234 fschmid 895
                        imgArray[i++] = k;
2004 fschmid 896
                        s++;
897
                }
898
        }
5234 fschmid 899
        return imgArray;
2004 fschmid 900
}
901
 
5234 fschmid 902
QByteArray ScImage::ImageToCMYK_PDF(bool pre)
2004 fschmid 903
{
2884 fschmid 904
        int i = 0;
2004 fschmid 905
        int h = height();
906
        int w = width();
5234 fschmid 907
        QByteArray imgArray( 4 * h * w );
2004 fschmid 908
        if (pre)
909
        {
910
                for( int yi=0; yi < h; ++yi )
911
                {
912
                        QRgb * s = (QRgb*)(scanLine( yi ));
913
                        for( int xi=0; xi < w; ++xi )
914
                        {
915
                                QRgb r=*s;
916
                                int c = qRed(r);
917
                                int m = qGreen(r);
918
                                int y = qBlue(r);
919
                                int k = qAlpha(r);
5234 fschmid 920
                                imgArray[i++] = static_cast<unsigned char> (c);
921
                                imgArray[i++] = static_cast<unsigned char> (m);
922
                                imgArray[i++] = static_cast<unsigned char> (y);
923
                                imgArray[i++] = static_cast<unsigned char> (k);
2004 fschmid 924
                                s++;
925
                        }
926
                }
927
        }
928
        else
929
        {
930
                for( int yi=0; yi < h; ++yi )
931
                {
932
                        QRgb * s = (QRgb*)(scanLine( yi ));
933
                        for( int xi=0; xi < w; ++xi )
934
                        {
935
                                QRgb r=*s;
936
                                int c = 255 - qRed(r);
937
                                int m = 255 - qGreen(r);
938
                                int y = 255 - qBlue(r);
939
                                int k = QMIN(QMIN(c, m), y);
5234 fschmid 940
                                imgArray[i++] = static_cast<unsigned char> (c - k);
941
                                imgArray[i++] = static_cast<unsigned char> (m - k);
942
                                imgArray[i++] = static_cast<unsigned char> (y - k);
943
                                imgArray[i++] = static_cast<unsigned char> (k);
2004 fschmid 944
                                s++;
945
                        }
946
                }
947
        }
5234 fschmid 948
        return imgArray;
2004 fschmid 949
}
950
 
5234 fschmid 951
QByteArray ScImage::ImageToCMYK_PS(int pl, bool pre)
2004 fschmid 952
{
2884 fschmid 953
        int i = 0;
2004 fschmid 954
        int h = height();
955
        int w = width();
5234 fschmid 956
        QByteArray imgArray;
2884 fschmid 957
        if(pl == -1)
5234 fschmid 958
                imgArray.resize(4 * h * w);
2884 fschmid 959
        else
5234 fschmid 960
                imgArray.resize(h * w);
2004 fschmid 961
        if (pre)
962
        {
963
                for( int yi=0; yi < h; ++yi )
964
                {
965
                        QRgb * s = (QRgb*)(scanLine( yi ));
966
                        for( int xi=0; xi < w; ++xi )
967
                        {
968
                                QRgb r=*s++;
969
                                int c = qRed(r);
970
                                int m = qGreen(r);
971
                                int y = qBlue(r);
972
                                int k = qAlpha(r);
973
                                if (pl == -1)
974
                                {
5234 fschmid 975
                                        imgArray[i++] = static_cast<unsigned char> (c);
976
                                        imgArray[i++] = static_cast<unsigned char> (m);
977
                                        imgArray[i++] = static_cast<unsigned char> (y);
978
                                        imgArray[i++] = static_cast<unsigned char> (k);
2004 fschmid 979
                                }
980
                                else
981
                                {
982
                                        if (pl == -2)
5234 fschmid 983
                                                imgArray[i++] = static_cast<unsigned char> (QMIN(255, qRound(0.3 * c + 0.59 * m + 0.11 * y + k)));
2004 fschmid 984
                                        if (pl == 1)
5234 fschmid 985
                                                imgArray[i++] = static_cast<unsigned char> (c);
2004 fschmid 986
                                        if (pl == 2)
5234 fschmid 987
                                                imgArray[i++] = static_cast<unsigned char> (m);
2004 fschmid 988
                                        if (pl == 3)
5234 fschmid 989
                                                imgArray[i++] = static_cast<unsigned char> (y);
2004 fschmid 990
                                        if (pl == 0)
5234 fschmid 991
                                                imgArray[i++] = static_cast<unsigned char> (k);
2004 fschmid 992
                                }
993
                        }
994
                }
995
        }
996
        else
997
        {
998
                for( int yi=0; yi < h; ++yi )
999
                {
1000
                        QRgb * s = (QRgb*)(scanLine( yi ));
1001
                        for( int xi=0; xi < w; ++xi )
1002
                        {
1003
                                QRgb r=*s++;
1004
                                int c = 255 - qRed(r);
1005
                                int m = 255 - qGreen(r);
1006
                                int y = 255 - qBlue(r);
1007
                                int k = QMIN(QMIN(c, m), y);
1008
                                if (pl == -1)
1009
                                {
5234 fschmid 1010
                                        imgArray[i++] = static_cast<unsigned char> (c - k);
1011
                                        imgArray[i++] = static_cast<unsigned char> (m - k);
1012
                                        imgArray[i++] = static_cast<unsigned char> (y - k);
1013
                                        imgArray[i++] = static_cast<unsigned char> (k);
2004 fschmid 1014
                                }
1015
                                else
1016
                                {
1017
                                        if (pl == -2)
5234 fschmid 1018
                                                imgArray[i++] = static_cast<unsigned char> (QMIN(255, qRound(0.3 * c + 0.59 * m + 0.11 * y + k)));
2004 fschmid 1019
                                        if (pl == 1)
5234 fschmid 1020
                                                imgArray[i++] = static_cast<unsigned char> (c - k);
2004 fschmid 1021
                                        if (pl == 2)
5234 fschmid 1022
                                                imgArray[i++] = static_cast<unsigned char> (m - k);
2004 fschmid 1023
                                        if (pl == 3)
5234 fschmid 1024
                                                imgArray[i++] = static_cast<unsigned char> (y - k);
2004 fschmid 1025
                                        if (pl == 0)
5234 fschmid 1026
                                                imgArray[i++] = static_cast<unsigned char> (k);
2004 fschmid 1027
                                }
1028
                        }
1029
                }
1030
        }
5234 fschmid 1031
        return imgArray;
2004 fschmid 1032
}
1033
 
1034
// Check that the header is a valid PSD.
1035
bool ScImage::IsValid( const PSDHeader & header )
1036
{
1037
        if( header.signature != 0x38425053 )
1038
                return false;
1039
        return true;
1040
}
1041
 
1042
// Check that the header is supported.
1043
bool ScImage::IsSupported( const PSDHeader & header )
1044
{
1045
        if ( header.version != 1 )
1046
                return false;
1047
        if ( header.channel_count > 16 )
1048
                return false;
1049
        if ( header.depth != 8 )
1050
                return false;
3836 fschmid 1051
        if ((header.color_mode == CM_RGB) || (header.color_mode == CM_CMYK)
1052
         || (header.color_mode == CM_GRAYSCALE) || (header.color_mode == CM_INDEXED))
2004 fschmid 1053
                return true;
1054
        return false;
1055
}
1056
 
1057
unsigned char ScImage::INT_MULT ( unsigned char a, unsigned char b )
1058
{
1059
        int c = a * b + 0x80;
1060
        return (unsigned char)(( ( c >> 8 ) + c ) >> 8);
1061
}
1062
 
1063
/*!
1064
 * Convert a color in RGB space to HSV space (Hue, Saturation, Value).
1065
 * \param red the red component (modified in place).
1066
 * \param green the green component (modified in place).
1067
 * \param blue the blue component (modified in place).
1068
 */
1069
void ScImage::RGBTOHSV ( uchar& red, uchar& green, uchar& blue )
1070
{
1071
        int r, g, b;
1072
        double h, s, v;
1073
        int min, max;
1074
        h = 0.;
1075
        r = red;
1076
        g = green;
1077
        b = blue;
1078
        if ( r > g )
1079
        {
1080
                max = QMAX( r, b );
1081
                min = QMIN( g, b );
1082
        }
1083
        else
1084
        {
1085
                max = QMAX( g, b );
1086
                min = QMIN( r, b );
1087
        }
1088
        v = max;
1089
        if ( max != 0 )
1090
                s = ( ( max - min ) * 255 ) / (double)max;
1091
        else
1092
                s = 0;
1093
        if ( s == 0 )
1094
                h = 0;
1095
        else
1096
        {
1097
                int delta = max - min;
1098
                if ( r == max )
1099
                        h = ( g - b ) / (double)delta;
1100
                else if ( g == max )
1101
                        h = 2 + ( b - r ) / (double)delta;
1102
                else if ( b == max )
1103
                        h = 4 + ( r - g ) / (double)delta;
1104
                h *= 42.5;
1105
                if ( h < 0 )
1106
                        h += 255;
1107
                if ( h > 255 )
1108
                        h -= 255;
1109
        }
1110
        red   = (uchar)h;
1111
        green = (uchar)s;
1112
        blue  = (uchar)v;
1113
}
1114
 
1115
/*!
1116
 * Convert a color in HSV space to RGB space.
1117
 * \param hue the hue component (modified in place).
1118
 * \param saturation the saturation component (modified in place).
1119
 * \param value the value component (modified in place).
1120
 */
1121
void ScImage::HSVTORGB ( uchar& hue, uchar& saturation, uchar& value )
1122
{
1123
        if ( saturation == 0 )
1124
        {
1125
                hue        = value;
1126
                saturation = value;
1127
                value      = value;
1128
        }
1129
        else
1130
        {
1131
                double h = hue * 6. / 255.;
1132
                double s = saturation / 255.;
1133
                double v = value / 255.;
1134
 
1135
                double f = h - (int)h;
1136
                double p = v * ( 1. - s );
1137
                double q = v * ( 1. - ( s * f ) );
1138
                double t = v * ( 1. - ( s * ( 1. - f ) ) );
1139
                // Worth a note here that gcc 2.96 will generate different results
1140
                // depending on optimization mode on i386.
1141
                switch ((int)h)
1142
                {
1143
                case 0:
1144
                        hue        = (uchar)( v * 255 );
1145
                        saturation = (uchar)( t * 255 );
1146
                        value      = (uchar)( p * 255 );
1147
                        break;
1148
                case 1:
1149
                        hue        = (uchar)( q * 255 );
1150
                        saturation = (uchar)( v * 255 );
1151
                        value      = (uchar)( p * 255 );
1152
                        break;
1153
                case 2:
1154
                        hue        = (uchar)( p * 255 );
1155
                        saturation = (uchar)( v * 255 );
1156
                        value      = (uchar)( t * 255 );
1157
                        break;
1158
                case 3:
1159
                        hue        = (uchar)( p * 255 );
1160
                        saturation = (uchar)( q * 255 );
1161
                        value      = (uchar)( v * 255 );
1162
                        break;
1163
                case 4:
1164
                        hue        = (uchar)( t * 255 );
1165
                        saturation = (uchar)( p * 255 );
1166
                        value      = (uchar)( v * 255 );
1167
                        break;
1168
                case 5:
1169
                        hue        = (uchar)( v * 255 );
1170
                        saturation = (uchar)( p * 255 );
1171
                        value      = (uchar)( q * 255 );
1172
                }
1173
        }
1174
}
1175
 
1176
/*!
1177
 * Convert a color in RGB space to HLS space (Hue, Lightness, Saturation).
1178
 * \param red the red component (modified in place).
1179
 * \param green the green component (modified in place).
1180
 * \param blue the blue component (modified in place).
1181
 */
1182
void ScImage::RGBTOHLS ( uchar& red, uchar& green, uchar& blue )
1183
{
1184
        int r = red;
1185
        int g = green;
1186
        int b = blue;
1187
        int min, max;
1188
        if ( r > g )
1189
        {
1190
                max = QMAX( r, b );
1191
                min = QMIN( g, b );
1192
        }
1193
        else
1194
        {
1195
                max = QMAX( g, b );
1196
                min = QMIN( r, b );
1197
        }
1198
        double h;
1199
        double l = ( max + min ) / 2.;
1200
        double s;
1201
        if ( max == min )
1202
        {
1203
                s = 0.;
1204
                h = 0.;
1205
        }
1206
        else
1207
        {
1208
                int delta = max - min;
1209
                if ( l < 128 )
1210
                        s = 255 * (double)delta / (double)( max + min );
1211
                else
1212
                        s = 255 * (double)delta / (double)( 511 - max - min );
1213
                if ( r == max )
1214
                        h = ( g - b ) / (double)delta;
1215
                else if ( g == max )
1216
                        h = 2 + ( b - r ) / (double)delta;
1217
                else
1218
                        h = 4 + ( r - g ) / (double)delta;
1219
                h *= 42.5;
1220
                if ( h < 0 )
1221
                        h += 255;
1222
                else if ( h > 255 )
1223
                        h -= 255;
1224
        }
1225
        red   = (uchar)h;
1226
        green = (uchar)l;
1227
        blue  = (uchar)s;
1228
}
1229
 
1230
/*!
1231
 * Implement the HLS "double hex-cone".
1232
 * \param n1 lightness fraction (?)
1233
 * \param n2 saturation fraction (?)
1234
 * \param hue hue "angle".
1235
 * \return HLS value.
1236
 */
1237
int ScImage::HLSVALUE ( double n1, double n2, double hue )
1238
{
1239
        double value;
1240
        if ( hue > 255 )
1241
                hue -= 255;
1242
        else if ( hue < 0 )
1243
                hue += 255;
1244
        if ( hue < 42.5 )
1245
                value = n1 + ( n2 - n1 ) * ( hue / 42.5 );
1246
        else if ( hue < 127.5 )
1247
                value = n2;
1248
        else if ( hue < 170 )
1249
                value = n1 + ( n2 - n1 ) * ( ( 170 - hue ) / 42.5 );
1250
        else
1251
                value = n1;
1252
        return (int)( value * 255 );
1253
}
1254
 
1255
/*!
1256
 * Convert a color in HLS space to RGB space.
1257
 * \param hue the hue component (modified in place).
1258
 * \param lightness the lightness component (modified in place).
1259
 * \param saturation the saturation component (modified in place).
1260
 */
1261
void ScImage::HLSTORGB ( uchar& hue, uchar& lightness, uchar& saturation )
1262
{
1263
        double h = hue;
1264
        double l = lightness;
1265
        double s = saturation;
1266
        if ( s == 0 )
1267
        {
1268
                hue        = (uchar)l;
1269
                lightness  = (uchar)l;
1270
                saturation = (uchar)l;
1271
        }
1272
        else
1273
        {
1274
                double m1, m2;
1275
                if ( l < 128 )
1276
                        m2 = ( l * ( 255 + s ) ) / 65025.;
1277
                else
1278
                        m2 = ( l + s - ( l * s ) / 255. ) / 255.;
1279
                m1 = ( l / 127.5 ) - m2;
1280
                hue        = HLSVALUE( m1, m2, h + 85 );
1281
                lightness  = HLSVALUE( m1, m2, h );
1282
                saturation = HLSVALUE( m1, m2, h - 85 );
1283
        }
1284
}
1285
 
3802 fschmid 1286
bool ScImage::loadChannel( QDataStream & s, const PSDHeader & header, QValueList<PSDLayer> &layerInfo, uint layer, int channel, int component, QImage &tmpImg)
1287
{
1288
        uint base = s.device()->at();
1289
        uchar cbyte;
1290
        ushort compression;
1291
        s >> compression;
1292
        if( compression > 1 )
1293
                return false;
1294
        if (compression == 0)
1295
        {
1296
                int count = layerInfo[layer].channelLen[channel]-2;
1297
                for (int i = 0; i < tmpImg.height(); i++)
1298
                {
1299
                        uchar *ptr =  tmpImg.scanLine(i);
1300
                        for (int j = 0; j < tmpImg.width(); j++)
1301
                        {
1302
                                s >> cbyte;
1303
                                count--;
1304
                                if (header.color_mode == CM_CMYK)
1305
                                        cbyte = 255 - cbyte;
3814 fschmid 1306
                                if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
1307
                                {
1308
                                        ptr[0] = cbyte;
1309
                                        ptr[1] = cbyte;
1310
                                        ptr[2] = cbyte;
1311
                                }
3836 fschmid 1312
                                else if ((header.color_mode == CM_INDEXED) && (component != 3))
1313
                                {
1314
                                        int ccol = colorTable[cbyte];
4099 fschmid 1315
                                        ptr[2] = qRed(ccol);
3836 fschmid 1316
                                        ptr[1] = qGreen(ccol);
4099 fschmid 1317
                                        ptr[0] = qBlue(ccol);
3836 fschmid 1318
                                }
3814 fschmid 1319
                                else
1320
                                {
1321
                                        if (channel < 4)
1322
                                                ptr[component] = cbyte;
1323
                                }
3802 fschmid 1324
                                if (count == 0)
1325
                                        break;
1326
                                ptr += 4;
1327
                        }
1328
                        if (count == 0)
1329
                                break;
1330
                }
1331
        }
1332
        else
1333
        {
1334
                s.device()->at( s.device()->at() + tmpImg.height() * 2 );
1335
                uint pixel_count = tmpImg.width();
1336
                for (int hh = 0; hh < tmpImg.height(); hh++)
1337
                {
1338
                        uint count = 0;
1339
                        uchar *ptr = tmpImg.scanLine(hh);
1340
                        uchar *ptr2 = ptr+tmpImg.width() * 4;
1341
                        ptr += component;
1342
                        while( count < pixel_count )
1343
                        {
1344
                                uchar c;
1345
                                if(s.atEnd())
1346
                                        return false;
1347
                                s >> c;
1348
                                uint len = c;
1349
                                if( len < 128 )
1350
                                {
1351
                                        // Copy next len+1 bytes literally.
1352
                                        len++;
1353
                                        count += len;
1354
                                        while( len != 0 )
1355
                                        {
1356
                                                s >> cbyte;
1357
                                                if (ptr < ptr2)
1358
                                                {
1359
                                                        if (header.color_mode == CM_CMYK)
1360
                                                                cbyte = 255 - cbyte;
3814 fschmid 1361
                                                        if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
1362
                                                        {
1363
                                                                ptr -= component;
1364
                                                                ptr[0] = cbyte;
1365
                                                                ptr[1] = cbyte;
1366
                                                                ptr[2] = cbyte;
1367
                                                                ptr += component;
1368
                                                        }
3836 fschmid 1369
                                                        else if ((header.color_mode == CM_INDEXED) && (component != 3))
1370
                                                        {
1371
                                                                ptr -= component;
1372
                                                                int ccol = colorTable[cbyte];
4099 fschmid 1373
                                                                ptr[2] = qRed(ccol);
3836 fschmid 1374
                                                                ptr[1] = qGreen(ccol);
4099 fschmid 1375
                                                                ptr[0] = qBlue(ccol);
3836 fschmid 1376
                                                                ptr += component;
1377
                                                        }
3814 fschmid 1378
                                                        else
1379
                                                        {
1380
                                                                *ptr = cbyte;
1381
                                                        }
3802 fschmid 1382
                                                }
1383
                                                ptr += 4;
1384
                                                len--;
1385
                                        }
1386
                                }
1387
                                else if( len > 128 )
1388
                                {
1389
                                        // Next -len+1 bytes in the dest are replicated from next source byte.
1390
                                        // (Interpret len as a negative 8-bit int.)
1391
                                        len ^= 0xFF;
1392
                                        len += 2;
1393
                                        count += len;
1394
                                        uchar val;
1395
                                        s >> val;
1396
                                        if (header.color_mode == CM_CMYK)
1397
                                                val = 255 - val;
1398
                                        while( len != 0 )
1399
                                        {
1400
                                                if (ptr < ptr2)
3814 fschmid 1401
                                                {
1402
                                                        if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
1403
                                                        {
1404
                                                                ptr -= component;
1405
                                                                ptr[0] = val;
1406
                                                                ptr[1] = val;
1407
                                                                ptr[2] = val;
1408
                                                                ptr += component;
1409
                                                        }
3836 fschmid 1410
                                                        else if ((header.color_mode == CM_INDEXED) && (component != 3))
1411
                                                        {
1412
                                                                ptr -= component;
1413
                                                                int ccol = colorTable[val];
4099 fschmid 1414
                                                                ptr[2] = qRed(ccol);
3836 fschmid 1415
                                                                ptr[1] = qGreen(ccol);
4099 fschmid 1416
                                                                ptr[0] = qBlue(ccol);
3836 fschmid 1417
                                                                ptr += component;
1418
                                                        }
3814 fschmid 1419
                                                        else
1420
                                                                *ptr = val;
1421
                                                }
3802 fschmid 1422
                                                ptr += 4;
1423
                                                len--;
1424
                                        }
1425
                                }
1426
                                else if( len == 128 )
1427
                                {
1428
                                        // No-op.
1429
                                }
1430
                        }
1431
                }
1432
        }
1433
        s.device()->at( base+layerInfo[layer].channelLen[channel] );
1434
        return true;
1435
}
1436
 
2004 fschmid 1437
bool ScImage::loadLayerChannels( QDataStream & s, const PSDHeader & header, QValueList<PSDLayer> &layerInfo, uint layer, bool* firstLayer)
1438
{
1439
        // Find out if the data is compressed.
1440
        // Known values:
1441
        //   0: no compression
1442
        //   1: RLE compressed
3814 fschmid 1443
        uint base = s.device()->at();
1444
        uint base2 = base;
1445
        uint channel_num = layerInfo[layer].channelLen.count();
3802 fschmid 1446
        QImage tmpImg = QImage();
1447
        QImage mask = QImage();
1448
        if( !tmpImg.create( layerInfo[layer].width, layerInfo[layer].height, 32 ))
3814 fschmid 1449
        {
1450
                for(uint channel = 0; channel < channel_num; channel++)
1451
                {
1452
                        base2 += layerInfo[layer].channelLen[channel];
1453
                }
1454
                s.device()->at( base2 );
3802 fschmid 1455
                return false;
3814 fschmid 1456
        }
5010 fschmid 1457
        tmpImg.fill(qRgba(255, 255, 255, 0));
2004 fschmid 1458
        tmpImg.setAlphaBuffer( true );
1459
        channel_num = QMIN(channel_num, 39);
1460
        uint components[40];
1461
        for(uint channel = 0; channel < channel_num; channel++)
1462
        {
1463
                switch(layerInfo[layer].channelType[channel])
1464
                {
1465
                case 0:
1466
                        components[channel] = 2;
1467
                        break;
1468
                case 1:
1469
                        components[channel] = 1;
1470
                        break;
1471
                case 2:
1472
                        components[channel] = 0;
1473
                        break;
1474
                case 3:
1475
                        components[channel] = 3;
1476
                        break;
1477
                case -1:
1478
                case -2:
1479
                        components[channel] = 3;
1480
                        break;
1481
                }
1482
        }
3802 fschmid 1483
        if (channel_num < 4)
2004 fschmid 1484
        {
3802 fschmid 1485
                for (int i = 0; i < tmpImg.height(); i++)
2004 fschmid 1486
                {
3802 fschmid 1487
                        QRgb * s = (QRgb*)(tmpImg.scanLine( i ));
1488
                        for (int j = 0; j < tmpImg.width(); j++)
2004 fschmid 1489
                        {
3922 fschmid 1490
                                *s++ = qRgba(255, 255, 255, 255);
2004 fschmid 1491
                        }
1492
                }
1493
        }
3802 fschmid 1494
        for(uint channel = 0; channel < channel_num; channel++)
2004 fschmid 1495
        {
3802 fschmid 1496
                if ((layerInfo[layer].channelType[channel] < 0) && (header.color_mode == CM_CMYK))
3764 fschmid 1497
                {
3802 fschmid 1498
                        s.device()->at( base+layerInfo[layer].channelLen[channel] );
1499
                        base = base+layerInfo[layer].channelLen[channel];
1500
                        continue;
3764 fschmid 1501
                }
4268 fschmid 1502
//              if ((layerInfo[layer].channelType[channel] == -2) || (layerInfo[layer].channelType[channel] == -1))
3802 fschmid 1503
                if (layerInfo[layer].channelType[channel] == -2)
2004 fschmid 1504
                {
3802 fschmid 1505
                        if (!mask.create( layerInfo[layer].maskWidth, layerInfo[layer].maskHeight, 32 ))
4268 fschmid 1506
//                      {
1507
//                              if (!mask.create(layerInfo[layer].width, layerInfo[layer].height, 32 ))
1508
                                        break;
1509
//                      }
5010 fschmid 1510
                        mask.fill(qRgba(255, 255, 255, 0));
3802 fschmid 1511
                        mask.setAlphaBuffer( true );
1512
                        if (!loadChannel(s, header, layerInfo, layer, channel, components[channel], mask))
1513
                                break;
2004 fschmid 1514
                }
3802 fschmid 1515
                else
1516
                {
1517
                        if (!loadChannel(s, header, layerInfo, layer, channel, components[channel], tmpImg))
1518
                                break;
1519
                }
2004 fschmid 1520
        }
3799 fschmid 1521
        for(uint channel = 0; channel < channel_num; channel++)
1522
        {
1523
                base2 += layerInfo[layer].channelLen[channel];
1524
        }
1525
        s.device()->at( base2 );
2004 fschmid 1526
        QImage tmpImg2 = tmpImg.copy();
1527
        if (header.color_mode == CM_CMYK)
1528
        {
1529
                for (int i = 0; i < tmpImg.height(); i++)
1530
                {
2766 cbradney 1531
                        unsigned int *ptr = (unsigned int *) tmpImg.scanLine(i);
1532
                        unsigned int *ptr2 = (unsigned int *) tmpImg2.scanLine(i);
2004 fschmid 1533
                        unsigned char r, g, b;
1534
                        for (int j = 0; j < tmpImg.width(); j++)
1535
                        {
2766 cbradney 1536
                                unsigned char *p = (unsigned char *) ptr;
1537
                                unsigned char *p2 = (unsigned char *) ptr2;
1538
                                r = 255 - QMIN(255, p[0] + p[3]);
1539
                                g = 255 - QMIN(255, p[1] + p[3]);
1540
                                b = 255 - QMIN(255, p[2] + p[3]);
1541
                                p2[0] = r;
1542
                                p2[1] = g;
1543
                                p2[2] = b;
1544
                                p2[3] = 255;
2004 fschmid 1545
                                ptr++;
2766 cbradney 1546
                                ptr2++;
2004 fschmid 1547
                        }
1548
                }
1549
        }
1550
        QImage imt;
1551
        double sx = tmpImg.width() / 40.0;
1552
        double sy = tmpImg.height() / 40.0;
1553
        imt = sy < sx ?  tmpImg2.smoothScale(qRound(tmpImg.width() / sx), qRound(tmpImg.height() / sx)) :
2095 fschmid 1554
              tmpImg2.smoothScale(qRound(tmpImg.width() / sy), qRound(tmpImg.height() / sy));
2004 fschmid 1555
        layerInfo[layer].thumb = imt.copy();
1556
        bool visible = !(layerInfo[layer].flags & 2);
1557
        if ((imgInfo.isRequest) && (imgInfo.RequestProps.contains(layer)))
1558
                visible = imgInfo.RequestProps[layer].visible;
1559
        if (visible)
1560
        {
3799 fschmid 1561
                unsigned int startSrcY, startSrcX, startDstY, startDstX;
1562
                if (layerInfo[layer].ypos < 0)
1563
                {
1564
                        startSrcY = abs(layerInfo[layer].ypos);
1565
                        startDstY = 0;
1566
                }
1567
                else
1568
                {
1569
                        startSrcY = 0;
1570
                        startDstY = layerInfo[layer].ypos;
1571
                }
1572
                if (layerInfo[layer].xpos < 0)
1573
                {
1574
                        startSrcX = abs(layerInfo[layer].xpos);
1575
                        startDstX = 0;
1576
                }
1577
                else
1578
                {
1579
                        startSrcX = 0;
1580
                        startDstX = layerInfo[layer].xpos;
1581
                }
3802 fschmid 1582
                unsigned int startSrcYm, startSrcXm, startDstYm, startDstXm;
1583
                if (layerInfo[layer].maskYpos < 0)
1584
                {
1585
                        startSrcYm = abs(layerInfo[layer].maskYpos);
1586
                        startDstYm = 0;
1587
                }
1588
                else
1589
                {
1590
                        startSrcYm = 0;
1591
                        startDstYm = layerInfo[layer].maskYpos;
1592
                }
1593
                if (layerInfo[layer].maskXpos < 0)
1594
                {
1595
                        startSrcXm = abs(layerInfo[layer].maskXpos);
1596
                        startDstXm = 0;
1597
                }
1598
                else
1599
                {
1600
                        startSrcXm = 0;
1601
                        startDstXm = layerInfo[layer].maskXpos;
1602
                }
3922 fschmid 1603
                QString layBlend2 = layerInfo[layer].blend;
1604
                if ((imgInfo.isRequest) && (imgInfo.RequestProps.contains(layer)))
1605
                        layBlend2 = imgInfo.RequestProps[layer].blend;
1606
                if ((layBlend2 == "diss") && (header.color_mode != CM_CMYK))
1607
                {
1608
                        for (int l = 0; l < tmpImg.height(); l++)
1609
                        {
1610
                                srand(random_table[ l  % 4096]);
1611
                                for (int k = 0; k < tmpImg.width(); k++)
1612
                                {
1613
                                        int rand_val = rand() & 0xff;
1614
                                        QRgb pixel = tmpImg.pixel(k, l);
1615
                                        if (rand_val > 128)
1616
                                                tmpImg.setPixel(k, l, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), 0));
1617
                                }
1618
                        }
1619
                }
2004 fschmid 1620
                if (*firstLayer)
1621
                {
3799 fschmid 1622
                        for( int yi=static_cast<int>(startSrcY); yi < QMIN(tmpImg.height(), height()); ++yi )
2004 fschmid 1623
                        {
1624
                                QRgb *s = (QRgb*)(tmpImg.scanLine( yi ));
3799 fschmid 1625
                                QRgb *d = (QRgb*)(scanLine( QMIN(static_cast<int>(startDstY), height()-1) ));
1626
                                d += QMIN(static_cast<int>(startDstX), width()-1);
3802 fschmid 1627
                                s += QMIN(static_cast<int>(startSrcX), tmpImg.width()-1);
4268 fschmid 1628
/*                              unsigned int *srcm;
1629
                                if (!mask.isNull())
1630
                                {
1631
                                        srcm = (unsigned int *)mask.scanLine(QMIN(yi, mask.height()-1));
1632
                                        srcm += QMIN(static_cast<int>(startSrcXm), mask.width()-1);
1633
                                } */
3799 fschmid 1634
                                for(int xi=static_cast<int>(startSrcX); xi < QMIN(tmpImg.width(), width()); ++xi )
2004 fschmid 1635
                                {
1636
                                        (*d) = (*s);
4268 fschmid 1637
/*                                      unsigned char *sm = (unsigned char *) srcm;
1638
                                        unsigned char *sc = (unsigned char *) d;
1639
                                        unsigned char *ss = (unsigned char *) s;
1640
                                        if (!mask.isNull())
1641
                                        {
1642
                                                if (header.color_mode == CM_CMYK)
1643
                                                {
1644
                                                        sc[0] = (sc[0] * (255 - sm[3]) + ss[0] * sm[3]) / 255;
1645
                                                        sc[1] = (sc[1] * (255 - sm[3]) + ss[1] * sm[3]) / 255;
1646
                                                        sc[2] = (sc[2] * (255 - sm[3]) + ss[2] * sm[3]) / 255;
1647
                                                        sc[3] = (sc[3] * (255 - sm[3]) + ss[3] * sm[3]) / 255;
1648
                                                }
1649
                                                else
1650
                                                        sc[3] = sm[3];
1651
                                        }
1652
                                        srcm++; */
2004 fschmid 1653
                                        s++;
1654
                                        d++;
1655
                                }
3799 fschmid 1656
                                startDstY++;
2004 fschmid 1657
                        }
1658
                }
1659
                else
1660
                {
3799 fschmid 1661
                        for (int i = static_cast<int>(startSrcY); i < layerInfo[layer].height; i++)
2004 fschmid 1662
                        {
3799 fschmid 1663
                                unsigned int *dst = (unsigned int *)scanLine(QMIN(static_cast<int>(startDstY), height()-1));
1664
                                unsigned int *src = (unsigned int *)tmpImg.scanLine(QMIN(i, tmpImg.height()-1));
1665
                                dst += QMIN(static_cast<int>(startDstX), width()-1);
3802 fschmid 1666
                                src += QMIN(static_cast<int>(startSrcX), tmpImg.width()-1);
4849 cbradney 1667
                                unsigned int *srcm = 0;
3802 fschmid 1668
                                if (!mask.isNull())
1669
                                {
1670
                                        srcm = (unsigned int *)mask.scanLine(QMIN(i, mask.height()-1));
1671
                                        srcm += QMIN(static_cast<int>(startSrcXm), mask.width()-1);
1672
                                }
3799 fschmid 1673
                                startDstY++;
3802 fschmid 1674
                                unsigned char r, g, b, a, src_r, src_g, src_b, src_a, mask_a;
4849 cbradney 1675
                                //<<#3356
1676
                                unsigned int maxDestX = width() - startDstX + startSrcX - 1;
1677
                                for (unsigned int j = startSrcX; j < QMIN(maxDestX, static_cast<unsigned int>(layerInfo[layer].width)); j++)
1678
                                //for (unsigned int j = startSrcX; j < static_cast<unsigned int>(layerInfo[layer].width); j++)
1679
                                //>>#3356
2004 fschmid 1680
                                {
2766 cbradney 1681
                                        unsigned char *d = (unsigned char *) dst;
1682
                                        unsigned char *s = (unsigned char *) src;
3802 fschmid 1683
                                        unsigned char *sm = (unsigned char *) srcm;
2766 cbradney 1684
                                        src_r = s[0];
1685
                                        src_g = s[1];
1686
                                        src_b = s[2];
1687
                                        src_a = s[3];
3802 fschmid 1688
                                        if (!mask.isNull())
1689
                                                mask_a = sm[3];
2004 fschmid 1690
                                        QString layBlend = layerInfo[layer].blend;
1691
                                        if ((imgInfo.isRequest) && (imgInfo.RequestProps.contains(layer)))
1692
                                                layBlend = imgInfo.RequestProps[layer].blend;
1693
                                        if (layBlend == "mul ")
1694
                                        {
1695
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1696
                                                {
1697
                                                        src_r = INT_MULT(src_r, d[0]);
1698
                                                        src_g = INT_MULT(src_g, d[1]);
1699
                                                        src_b = INT_MULT(src_b, d[2]);
2766 cbradney 1700
                                                        src_a = INT_MULT(src_a, d[3]);
3764 fschmid 1701
                                                }
2004 fschmid 1702
                                                else
3764 fschmid 1703
                                                {
1704
                                                        if (d[3] > 0)
1705
                                                        {
1706
                                                                src_r = INT_MULT(src_r, d[0]);
1707
                                                                src_g = INT_MULT(src_g, d[1]);
1708
                                                                src_b = INT_MULT(src_b, d[2]);
1709
                                                        }
1710
                                                }
2004 fschmid 1711
                                        }
1712
                                        else if (layBlend == "scrn")
1713
                                        {
1714
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1715
                                                {
1716
                                                        src_r = 255 - INT_MULT(255 - d[0], 255 - src_r);
1717
                                                        src_g = 255 - INT_MULT(255 - d[1], 255 - src_g);
1718
                                                        src_b = 255 - INT_MULT(255 - d[2], 255 - src_b);
2766 cbradney 1719
                                                        src_a = 255 - INT_MULT(255 - d[3], 255 - src_a);
3764 fschmid 1720
                                                }
2004 fschmid 1721
                                                else
3764 fschmid 1722
                                                {
1723
                                                        if (d[3] > 0)
1724
                                                        {
1725
                                                                src_r = 255 - INT_MULT(255 - d[0], 255 - src_r);
1726
                                                                src_g = 255 - INT_MULT(255 - d[1], 255 - src_g);
1727
                                                                src_b = 255 - INT_MULT(255 - d[2], 255 - src_b);
1728
                                                        }
1729
                                                }
2004 fschmid 1730
                                        }
1731
                                        else if (layBlend == "over")
1732
                                        {
1733
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1734
                                                {
1735
                                                        src_r = INT_MULT(d[0], d[0] + INT_MULT(2 * src_r, 255 - d[0]));
1736
                                                        src_g = INT_MULT(d[1], d[1] + INT_MULT(2 * src_g, 255 - d[1]));
1737
                                                        src_b = INT_MULT(d[2], d[2] + INT_MULT(2 * src_b, 255 - d[2]));
2766 cbradney 1738
                                                        src_a = INT_MULT(d[3], d[3] + INT_MULT(2 * src_a, 255 - d[3]));
3764 fschmid 1739
                                                }
2004 fschmid 1740
                                                else
3764 fschmid 1741
                                                {
1742
                                                        if (d[3] > 0)
1743
                                                        {
1744
                                                                src_r = INT_MULT(d[0], d[0] + INT_MULT(2 * src_r, 255 - d[0]));
1745
                                                                src_g = INT_MULT(d[1], d[1] + INT_MULT(2 * src_g, 255 - d[1]));
1746
                                                                src_b = INT_MULT(d[2], d[2] + INT_MULT(2 * src_b, 255 - d[2]));
1747
                                                        }
1748
                                                }
2004 fschmid 1749
                                        }
1750
                                        else if (layBlend == "diff")
1751
                                        {
1752
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1753
                                                {
1754
                                                        src_r = d[0] > src_r ? d[0] - src_r : src_r - d[0];
1755
                                                        src_g = d[1] > src_g ? d[1] - src_g : src_g - d[1];
1756
                                                        src_b = d[2] > src_b ? d[2] - src_b : src_b - d[2];
2766 cbradney 1757
                                                        src_a = d[3] > src_a ? d[3] - src_a : src_a - d[3];
3764 fschmid 1758
                                                }
2004 fschmid 1759
                                                else
3764 fschmid 1760
                                                {
1761
                                                        if (d[3] > 0)
1762
                                                        {
1763
                                                                src_r = d[0] > src_r ? d[0] - src_r : src_r - d[0];
1764
                                                                src_g = d[1] > src_g ? d[1] - src_g : src_g - d[1];
1765
                                                                src_b = d[2] > src_b ? d[2] - src_b : src_b - d[2];
1766
                                                        }
1767
                                                }
2004 fschmid 1768
                                        }
1769
                                        else if (layBlend == "dark")
1770
                                        {
1771
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1772
                                                {
1773
                                                        src_r = d[0]  < src_r ? d[0]  : src_r;
1774
                                                        src_g = d[1] < src_g ? d[1] : src_g;
1775
                                                        src_b = d[2] < src_b ? d[2] : src_b;
2766 cbradney 1776
                                                        src_a = d[3] < src_a ? d[3] : src_a;
3764 fschmid 1777
                                                }
2004 fschmid 1778
                                                else
3764 fschmid 1779
                                                {
1780
                                                        if (d[3] > 0)
1781
                                                        {
1782
                                                                src_r = d[0]  < src_r ? d[0]  : src_r;
1783
                                                                src_g = d[1] < src_g ? d[1] : src_g;
1784
                                                                src_b = d[2] < src_b ? d[2] : src_b;
1785
                                                        }
1786
                                                }
2004 fschmid 1787
                                        }
3871 fschmid 1788
                                        else if (layBlend == "hLit")
1789
                                        {
1790
                                                if (header.color_mode == CM_CMYK)
1791
                                                {
3872 fschmid 1792
                                                        src_r = src_r < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128);
1793
                                                        src_g = src_g < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128);
1794
                                                        src_b = src_b < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128);
1795
                                                        src_a = src_a < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128);
3871 fschmid 1796
                                                }
1797
                                                else
1798
                                                {
1799
                                                        if (d[3] > 0)
1800
                                                        {
3872 fschmid 1801
                                                                src_r = src_r < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128);
1802
                                                                src_g = src_g < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128);
1803
                                                                src_b = src_b < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128);
3871 fschmid 1804
                                                        }
1805
                                                }
1806
                                        }
3872 fschmid 1807
                                        else if (layBlend == "sLit")
1808
                                        {
1809
                                                if (header.color_mode == CM_CMYK)
1810
                                                {
1811
                                                        src_r = src_r * d[0] / 256 + src_r * (255 - ((255-src_r)*(255-d[0]) / 256) - src_r * d[0] / 256) / 256;
1812
                                                        src_g = src_g * d[1] / 256 + src_g * (255 - ((255-src_g)*(255-d[1]) / 256) - src_g * d[1] / 256) / 256;
1813
                                                        src_b = src_b * d[2] / 256 + src_b * (255 - ((255-src_b)*(255-d[2]) / 256) - src_b * d[2] / 256) / 256;
1814
                                                        src_a = src_a * d[3] / 256 + src_a * (255 - ((255-src_a)*(255-d[3]) / 256) - src_a * d[3] / 256) / 256;
1815
                                                }
1816
                                                else
1817
                                                {
1818
                                                        if (d[3] > 0)
1819
                                                        {
1820
                                                                src_r = src_r * d[0] / 256 + src_r * (255 - ((255-src_r)*(255-d[0]) / 256) - src_r * d[0] / 256) / 256;
1821
                                                                src_g = src_g * d[1] / 256 + src_g * (255 - ((255-src_g)*(255-d[1]) / 256) - src_g * d[1] / 256) / 256;
1822
                                                                src_b = src_b * d[2] / 256 + src_b * (255 - ((255-src_b)*(255-d[2]) / 256) - src_b * d[2] / 256) / 256;
1823
                                                        }
1824
                                                }
1825
                                        }
2004 fschmid 1826
                                        else if (layBlend == "lite")
1827
                                        {
1828
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1829
                                                {
1830
                                                        src_r = d[0] < src_r ? src_r : d[0];
1831
                                                        src_g = d[1] < src_g ? src_g : d[1];
1832
                                                        src_b = d[2] < src_b ? src_b : d[2];
2766 cbradney 1833
                                                        src_a = d[3] < src_a ? src_a : d[3];
3764 fschmid 1834
                                                }
2004 fschmid 1835
                                                else
3764 fschmid 1836
                                                {
1837
                                                        if (d[3] > 0)
1838
                                                        {
1839
                                                                src_r = d[0] < src_r ? src_r : d[0];
1840
                                                                src_g = d[1] < src_g ? src_g : d[1];
1841
                                                                src_b = d[2] < src_b ? src_b : d[2];
1842
                                                        }
1843
                                                }
2004 fschmid 1844
                                        }
3898 fschmid 1845
                                        else if (layBlend == "smud")
1846
                                        {
1847
                                                if (header.color_mode == CM_CMYK)
1848
                                                {
1849
                                                        src_r = d[0] + src_r - src_r * d[0] / 128;
1850
                                                        src_g = d[1] + src_g - src_g * d[1] / 128;
1851
                                                        src_b = d[2] + src_b - src_b * d[2] / 128;
1852
                                                        src_a = d[3] + src_a - src_a * d[3] / 128;
1853
                                                }
1854
                                                else
1855
                                                {
1856
                                                        if (d[3] > 0)
1857
                                                        {
1858
                                                                src_r = d[0] + src_r - src_r * d[0] / 128;
1859
                                                                src_g = d[1] + src_g - src_g * d[1] / 128;
1860
                                                                src_b = d[2] + src_b - src_b * d[2] / 128;
1861
                                                        }
1862
                                                }
1863
                                        }
1864
                                        else if (layBlend == "div ")
1865
                                        {
1866
                                                if (header.color_mode == CM_CMYK)
1867
                                                {
1868
                                                        src_r = src_r == 255 ? 255 : ((d[0] * 256) / (255-src_r)) > 255 ? 255 : (d[0] * 256) / (255-src_r);
1869
                                                        src_g = src_g == 255 ? 255 : ((d[1] * 256) / (255-src_g)) > 255 ? 255 : (d[1] * 256) / (255-src_g);
1870
                                                        src_b = src_b == 255 ? 255 : ((d[2] * 256) / (255-src_b)) > 255 ? 255 : (d[2] * 256) / (255-src_b);
1871
                                                        src_a = src_a == 255 ? 255 : ((d[3] * 256) / (255-src_a)) > 255 ? 255 : (d[3] * 256) / (255-src_a);
1872
                                                }
1873
                                                else
1874
                                                {
1875
                                                        if (d[3] > 0)
1876
                                                        {
1877
                                                                src_r = src_r == 255 ? 255 : ((d[0] * 256) / (255-src_r)) > 255 ? 255 : (d[0] * 256) / (255-src_r);
1878
                                                                src_g = src_g == 255 ? 255 : ((d[1] * 256) / (255-src_g)) > 255 ? 255 : (d[1] * 256) / (255-src_g);
1879
                                                                src_b = src_b == 255 ? 255 : ((d[2] * 256) / (255-src_b)) > 255 ? 255 : (d[2] * 256) / (255-src_b);
1880
                                                        }
1881
                                                }
1882
                                        }
1883
                                        else if (layBlend == "idiv")
1884
                                        {
1885
                                                if (header.color_mode == CM_CMYK)
1886
                                                {
1887
                                                        src_r = src_r == 0 ? 0 : (255 - (((255-d[0]) * 256) / src_r)) < 0 ? 0 : 255 - (((255-d[0]) * 256) / src_r);
1888
                                                        src_g = src_g == 0 ? 0 : (255 - (((255-d[1]) * 256) / src_g)) < 0 ? 0 : 255 - (((255-d[1]) * 256) / src_g);
1889
                                                        src_b = src_b == 0 ? 0 : (255 - (((255-d[2]) * 256) / src_b)) < 0 ? 0 : 255 - (((255-d[2]) * 256) / src_b);
1890
                                                        src_a = src_a == 0 ? 0 : (255 - (((255-d[3]) * 256) / src_a)) < 0 ? 0 : 255 - (((255-d[3]) * 256) / src_a);
1891
                                                }
1892
                                                else
1893
                                                {
1894
                                                        if (d[3] > 0)
1895
                                                        {
1896
                                                                src_r = src_r == 0 ? 0 : (255 - (((255-d[0]) * 256) / src_r)) < 0 ? 0 : 255 - (((255-d[0]) * 256) / src_r);
1897
                                                                src_g = src_g == 0 ? 0 : (255 - (((255-d[1]) * 256) / src_g)) < 0 ? 0 : 255 - (((255-d[1]) * 256) / src_g);
1898
                                                                src_b = src_b == 0 ? 0 : (255 - (((255-d[2]) * 256) / src_b)) < 0 ? 0 : 255 - (((255-d[2]) * 256) / src_b);
1899
                                                        }
1900
                                                }
1901
                                        }
2004 fschmid 1902
                                        else if (layBlend == "hue ")
1903
                                        {
1904
                                                if (header.color_mode != CM_CMYK)
1905
                                                {
3764 fschmid 1906
                                                        if (d[3] > 0)
1907
                                                        {
1908
                                                                uchar new_r = d[0];
1909
                                                                uchar new_g = d[1];
1910
                                                                uchar new_b = d[2];
1911
                                                                RGBTOHSV(src_r, src_g, src_b);
1912
                                                                RGBTOHSV(new_r, new_g, new_b);
1913
                                                                new_r = src_r;
1914
                                                                HSVTORGB(new_r, new_g, new_b);
1915
                                                                src_r = new_r;
1916
                                                                src_g = new_g;
1917
                                                                src_b = new_b;
1918
                                                        }
2004 fschmid 1919
                                                }
1920
                                        }
1921
                                        else if (layBlend == "sat ")
1922
                                        {
1923
                                                if (header.color_mode != CM_CMYK)
1924
                                                {
3764 fschmid 1925
                                                        if (d[3] > 0)
1926
                                                        {
1927
                                                                uchar new_r = d[0];
1928
                                                                uchar new_g = d[1];
1929
                                                                uchar new_b = d[2];
1930
                                                                RGBTOHSV(src_r, src_g, src_b);
1931
                                                                RGBTOHSV(new_r, new_g, new_b);
1932
                                                                new_g = src_g;
1933
                                                                HSVTORGB(new_r, new_g, new_b);
1934
                                                                src_r = new_r;
1935
                                                                src_g = new_g;
1936
                                                                src_b = new_b;
1937
                                                        }
2004 fschmid 1938
                                                }
1939
                                        }
1940
                                        else if (layBlend == "lum ")
1941
                                        {
1942
                                                if (header.color_mode != CM_CMYK)
1943
                                                {
3764 fschmid 1944
                                                        if (d[3] > 0)
1945
                                                        {
1946
                                                                uchar new_r = d[0];
1947
                                                                uchar new_g = d[1];
1948
                                                                uchar new_b = d[2];
1949
                                                                RGBTOHSV(src_r, src_g, src_b);
1950
                                                                RGBTOHSV(new_r, new_g, new_b);
1951
                                                                new_b = src_b;
1952
                                                                HSVTORGB(new_r, new_g, new_b);
1953
                                                                src_r = new_r;
1954
                                                                src_g = new_g;
1955
                                                                src_b = new_b;
1956
                                                        }
2004 fschmid 1957
                                                }
1958
                                        }
1959
                                        else if (layBlend == "colr")
1960
                                        {
1961
                                                if (header.color_mode != CM_CMYK)
1962
                                                {
3764 fschmid 1963
                                                        if (d[3] > 0)
1964
                                                        {
1965
                                                                uchar new_r = d[0];
1966
                                                                uchar new_g = d[1];
1967
                                                                uchar new_b = d[2];
1968
                                                                RGBTOHLS(src_r, src_g, src_b);
1969
                                                                RGBTOHLS(new_r, new_g, new_b);
1970
                                                                new_r = src_r;
1971
                                                                new_b = src_b;
1972
                                                                HLSTORGB(new_r, new_g, new_b);
1973
                                                                src_r = new_r;
1974
                                                                src_g = new_g;
1975
                                                                src_b = new_b;
1976
                                                        }
2004 fschmid 1977
                                                }
1978
                                        }
4849 cbradney 1979
 
2004 fschmid 1980
                                        int layOpa = layerInfo[layer].opacity;
1981
                                        if ((imgInfo.isRequest) && (imgInfo.RequestProps.contains(layer)))
1982
                                                layOpa = imgInfo.RequestProps[layer].opacity;
3802 fschmid 1983
                                        if (!mask.isNull())
1984
                                                layOpa = INT_MULT(mask_a, layOpa);
5010 fschmid 1985
                                        if (header.color_mode != CM_CMYK)
1986
                                                src_a = INT_MULT(src_a, layOpa);
3764 fschmid 1987
                                        if (d[3] > 0)
1988
                                        {
1989
                                                r = (d[0] * (255 - layOpa) + src_r * layOpa) / 255;
1990
                                                g = (d[1] * (255 - layOpa) + src_g * layOpa) / 255;
1991
                                                b = (d[2] * (255 - layOpa) + src_b * layOpa) / 255;
5010 fschmid 1992
                                                if (header.color_mode == CM_CMYK)
3764 fschmid 1993
                                                        a = (d[3] * (255 - layOpa) + src_a * layOpa) / 255;
5010 fschmid 1994
                                                else
1995
                                                {
1996
                                                        a = d[3] + INT_MULT(255 - d[3], src_a);
1997
                                                        r = (d[0] * (255 - src_a) + src_r * src_a) / 255;
1998
                                                        g = (d[1] * (255 - src_a) + src_g * src_a) / 255;
1999
                                                        b = (d[2] * (255 - src_a) + src_b * src_a) / 255;
2000
                                                }
3764 fschmid 2001
                                        }
2002
                                        else
2003
                                        {
2004
                                                r = src_r;
2005
                                                g = src_g;
2006
                                                b = src_b;
<