Subversion Repositories Scribus

Rev

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

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