Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
10601 mrdocs 7
 
8
#include "cmsettings.h"
13497 jghali 9
#include "scclocale.h"
2004 fschmid 10
#include "scimage.h"
19080 craig 11
 
5917 jghali 12
#include "scpaths.h"
5243 cbradney 13
#include "scribuscore.h"
6412 fschmid 14
#include "scimgdataloader_gimp.h"
13958 jghali 15
#ifdef GMAGICK_FOUND
13957 herm 16
#include "scimgdataloader_gmagick.h"
13958 jghali 17
#endif
5937 jghali 18
#include "scimgdataloader_jpeg.h"
18954 fschmid 19
#include "scimgdataloader_ora.h"
14036 fschmid 20
#include "scimgdataloader_pict.h"
5937 jghali 21
#include "scimgdataloader_ps.h"
22
#include "scimgdataloader_psd.h"
23
#include "scimgdataloader_pdf.h"
15796 fschmid 24
#include "scimgdataloader_pgf.h"
5937 jghali 25
#include "scimgdataloader_qt.h"
26
#include "scimgdataloader_tiff.h"
14087 fschmid 27
#include "scimgdataloader_wpg.h"
15165 jghali 28
#include "scstreamfilter_jpeg.h"
13503 cbradney 29
#include "sctextstream.h"
15165 jghali 30
#include <QFile>
10223 cbradney 31
#include <QMessageBox>
9803 fschmid 32
#include <QList>
9535 fschmid 33
#include <QByteArray>
13990 fschmid 34
#include <QImageReader>
10768 jghali 35
#include <cassert>
36
#include <cmath>
37
#include <cstdlib>
5937 jghali 38
#include <memory>
10768 jghali 39
#include <setjmp.h>
14179 jghali 40
 
10203 cbradney 41
#include "commonstrings.h"
3685 fschmid 42
#include "exif.h"
7478 jghali 43
#include "sccolorengine.h"
14539 jghali 44
#include "scimagecacheproxy.h"
14179 jghali 45
#include "scstreamfilter.h"
10203 cbradney 46
#include "util.h"
47
#include "util_color.h"
10212 cbradney 48
#include "util_formats.h"
14179 jghali 49
#include "util_ghostscript.h"
50
#include "rawimage.h"
12136 fschmid 51
 
5937 jghali 52
using namespace std;
53
 
4222 craig 54
ScImage::ScImage(const QImage & image) : QImage(image)
2004 fschmid 55
{
2012 fschmid 56
        initialize();
2004 fschmid 57
}
58
 
5593 avox 59
 
60
// ScImage will use implicit sharing:
61
ScImage::ScImage(const ScImage & image) : QImage(image.copy())
62
{
63
        initialize();
64
}
65
 
66
 
2004 fschmid 67
ScImage::ScImage() : QImage()
68
{
2012 fschmid 69
        initialize();
2004 fschmid 70
}
71
 
10561 fschmid 72
ScImage::ScImage( int width, int height ) : QImage( width, height, QImage::Format_ARGB32 )
2004 fschmid 73
{
2012 fschmid 74
        initialize();
75
}
76
 
5593 avox 77
const QImage& ScImage::qImage()
78
{
79
        return *this;
80
}
81
 
6063 fschmid 82
QImage* ScImage::qImagePtr()
83
{
84
        return this;
85
}
86
 
10398 cbradney 87
QImage ScImage::scaled(int h, int w, Qt::AspectRatioMode mode, Qt::TransformationMode transformMode) const
5593 avox 88
{
10398 cbradney 89
        return QImage::scaled(h, w, mode, transformMode);
5593 avox 90
}
91
 
92
 
2012 fschmid 93
void ScImage::initialize()
94
{
2004 fschmid 95
        imgInfo.xres = 72;
96
        imgInfo.yres = 72;
11331 jghali 97
        imgInfo.colorspace = ColorSpaceRGB;
2004 fschmid 98
        imgInfo.valid = false;
99
        imgInfo.isRequest = false;
5567 mrdocs 100
        imgInfo.isEmbedded = false;
2004 fschmid 101
        imgInfo.progressive = false;
3703 fschmid 102
        imgInfo.exifDataValid = false;
2025 fschmid 103
        imgInfo.lowResType = 1;
104
        imgInfo.lowResScale = 1.0;
2004 fschmid 105
        imgInfo.PDSpathData.clear();
106
        imgInfo.RequestProps.clear();
107
        imgInfo.clipPath = "";
108
        imgInfo.usedPath = "";
109
        imgInfo.layerInfo.clear();
6085 fschmid 110
        imgInfo.duotoneColors.clear();
3703 fschmid 111
        imgInfo.exifInfo.cameraName = "";
112
        imgInfo.exifInfo.cameraVendor = "";
113
        imgInfo.exifInfo.thumbnail = QImage();
4331 fschmid 114
        imgInfo.BBoxX = 0;
115
        imgInfo.BBoxH = 0;
2004 fschmid 116
}
117
 
4050 cbradney 118
ScImage::~ScImage()
119
{
120
}
121
 
10954 jghali 122
void ScImage::applyEffect(const ScImageEffectList& effectsList, ColorList& colors, bool cmyk)
2074 fschmid 123
{
7478 jghali 124
        ScribusDoc* doc = colors.document();
2074 fschmid 125
        if (effectsList.count() != 0)
126
        {
8545 cbradney 127
                for (int a = 0; a < effectsList.count(); ++a)
2074 fschmid 128
                {
9803 fschmid 129
                        if (effectsList.at(a).effectCode == EF_INVERT)
2074 fschmid 130
                                invert(cmyk);
9803 fschmid 131
                        if (effectsList.at(a).effectCode == EF_GRAYSCALE)
2074 fschmid 132
                                toGrayscale(cmyk);
9803 fschmid 133
                        if (effectsList.at(a).effectCode == EF_COLORIZE)
2074 fschmid 134
                        {
9803 fschmid 135
                                QString tmpstr = effectsList.at(a).effectParameters;
4546 subik 136
                                QString col = CommonStrings::None;
2074 fschmid 137
                                int shading = 100;
13497 jghali 138
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
12130 fschmid 139
                        //      fp >> col;
140
                                col = fp.readLine();
2074 fschmid 141
                                fp >> shading;
7478 jghali 142
                                colorize(doc, colors[col], shading, cmyk);
2074 fschmid 143
                        }
9803 fschmid 144
                        if (effectsList.at(a).effectCode == EF_BRIGHTNESS)
2082 fschmid 145
                        {
9803 fschmid 146
                                QString tmpstr = effectsList.at(a).effectParameters;
2082 fschmid 147
                                int brightnessValue = 0;
13497 jghali 148
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
2082 fschmid 149
                                fp >> brightnessValue;
150
                                brightness(brightnessValue, cmyk);
151
                        }
9803 fschmid 152
                        if (effectsList.at(a).effectCode == EF_CONTRAST)
2082 fschmid 153
                        {
9803 fschmid 154
                                QString tmpstr = effectsList.at(a).effectParameters;
2082 fschmid 155
                                int contrastValue = 0;
13497 jghali 156
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
2082 fschmid 157
                                fp >> contrastValue;
158
                                contrast(contrastValue, cmyk);
159
                        }
9803 fschmid 160
                        if (effectsList.at(a).effectCode == EF_SHARPEN)
2092 fschmid 161
                        {
9803 fschmid 162
                                QString tmpstr = effectsList.at(a).effectParameters;
2092 fschmid 163
                                double radius, sigma;
13497 jghali 164
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
2092 fschmid 165
                                fp >> radius;
166
                                fp >> sigma;
167
                                sharpen(radius, sigma);
168
                        }
9803 fschmid 169
                        if (effectsList.at(a).effectCode == EF_BLUR)
2095 fschmid 170
                        {
9803 fschmid 171
                                QString tmpstr = effectsList.at(a).effectParameters;
2095 fschmid 172
                                double radius, sigma;
13497 jghali 173
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
2095 fschmid 174
                                fp >> radius;
175
                                fp >> sigma;
6011 fschmid 176
                                blur(static_cast<int>(radius));
2095 fschmid 177
                        }
9803 fschmid 178
                        if (effectsList.at(a).effectCode == EF_SOLARIZE)
2096 fschmid 179
                        {
9803 fschmid 180
                                QString tmpstr = effectsList.at(a).effectParameters;
2096 fschmid 181
                                double sigma;
13497 jghali 182
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
2096 fschmid 183
                                fp >> sigma;
184
                                solarize(sigma, cmyk);
185
                        }
9803 fschmid 186
                        if (effectsList.at(a).effectCode == EF_DUOTONE)
6080 fschmid 187
                        {
9803 fschmid 188
                                QString tmpstr = effectsList.at(a).effectParameters;
6080 fschmid 189
                                QString col1 = CommonStrings::None;
190
                                int shading1 = 100;
191
                                QString col2 = CommonStrings::None;
192
                                int shading2 = 100;
13497 jghali 193
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
6080 fschmid 194
                                col1 = fp.readLine();
195
                                col2 = fp.readLine();
196
                                fp >> shading1;
197
                                fp >> shading2;
6129 fschmid 198
                                int numVals;
199
                                double xval, yval;
200
                                FPointArray curve1;
201
                                curve1.resize(0);
202
                                fp >> numVals;
203
                                for (int nv = 0; nv < numVals; nv++)
204
                                {
205
                                        fp >> xval;
206
                                        fp >> yval;
207
                                        curve1.addPoint(xval, yval);
208
                                }
6193 fschmid 209
                                int lin1;
210
                                fp >> lin1;
6129 fschmid 211
                                FPointArray curve2;
212
                                curve2.resize(0);
213
                                fp >> numVals;
214
                                for (int nv = 0; nv < numVals; nv++)
215
                                {
216
                                        fp >> xval;
217
                                        fp >> yval;
218
                                        curve2.addPoint(xval, yval);
219
                                }
6193 fschmid 220
                                int lin2;
221
                                fp >> lin2;
7478 jghali 222
                                duotone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, cmyk);
6080 fschmid 223
                        }
9803 fschmid 224
                        if (effectsList.at(a).effectCode == EF_TRITONE)
6080 fschmid 225
                        {
9803 fschmid 226
                                QString tmpstr = effectsList.at(a).effectParameters;
6080 fschmid 227
                                QString col1 = CommonStrings::None;
228
                                QString col2 = CommonStrings::None;
229
                                QString col3 = CommonStrings::None;
230
                                int shading1 = 100;
231
                                int shading2 = 100;
232
                                int shading3 = 100;
13497 jghali 233
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
6080 fschmid 234
                                col1 = fp.readLine();
235
                                col2 = fp.readLine();
236
                                col3 = fp.readLine();
237
                                fp >> shading1;
238
                                fp >> shading2;
239
                                fp >> shading3;
6129 fschmid 240
                                int numVals;
241
                                double xval, yval;
242
                                FPointArray curve1;
243
                                curve1.resize(0);
244
                                fp >> numVals;
245
                                for (int nv = 0; nv < numVals; nv++)
246
                                {
247
                                        fp >> xval;
248
                                        fp >> yval;
249
                                        curve1.addPoint(xval, yval);
250
                                }
6193 fschmid 251
                                int lin1;
252
                                fp >> lin1;
6129 fschmid 253
                                FPointArray curve2;
254
                                curve2.resize(0);
255
                                fp >> numVals;
256
                                for (int nv = 0; nv < numVals; nv++)
257
                                {
258
                                        fp >> xval;
259
                                        fp >> yval;
260
                                        curve2.addPoint(xval, yval);
261
                                }
6193 fschmid 262
                                int lin2;
263
                                fp >> lin2;
6129 fschmid 264
                                FPointArray curve3;
265
                                curve3.resize(0);
266
                                fp >> numVals;
267
                                for (int nv = 0; nv < numVals; nv++)
268
                                {
269
                                        fp >> xval;
270
                                        fp >> yval;
271
                                        curve3.addPoint(xval, yval);
272
                                }
6193 fschmid 273
                                int lin3;
274
                                fp >> lin3;
7478 jghali 275
                                tritone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, colors[col3], shading3, curve3, lin3, cmyk);
6080 fschmid 276
                        }
9803 fschmid 277
                        if (effectsList.at(a).effectCode == EF_QUADTONE)
6080 fschmid 278
                        {
9803 fschmid 279
                                QString tmpstr = effectsList.at(a).effectParameters;
6080 fschmid 280
                                QString col1 = CommonStrings::None;
281
                                QString col2 = CommonStrings::None;
282
                                QString col3 = CommonStrings::None;
283
                                QString col4 = CommonStrings::None;
284
                                int shading1 = 100;
285
                                int shading2 = 100;
286
                                int shading3 = 100;
287
                                int shading4 = 100;
13497 jghali 288
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
6080 fschmid 289
                                col1 = fp.readLine();
290
                                col2 = fp.readLine();
291
                                col3 = fp.readLine();
292
                                col4 = fp.readLine();
293
                                fp >> shading1;
294
                                fp >> shading2;
295
                                fp >> shading3;
296
                                fp >> shading4;
6129 fschmid 297
                                int numVals;
298
                                double xval, yval;
299
                                FPointArray curve1;
300
                                curve1.resize(0);
301
                                fp >> numVals;
302
                                for (int nv = 0; nv < numVals; nv++)
303
                                {
304
                                        fp >> xval;
305
                                        fp >> yval;
306
                                        curve1.addPoint(xval, yval);
307
                                }
6193 fschmid 308
                                int lin1;
309
                                fp >> lin1;
6129 fschmid 310
                                FPointArray curve2;
311
                                curve2.resize(0);
312
                                fp >> numVals;
313
                                for (int nv = 0; nv < numVals; nv++)
314
                                {
315
                                        fp >> xval;
316
                                        fp >> yval;
317
                                        curve2.addPoint(xval, yval);
318
                                }
6193 fschmid 319
                                int lin2;
320
                                fp >> lin2;
6129 fschmid 321
                                FPointArray curve3;
322
                                curve3.resize(0);
323
                                fp >> numVals;
324
                                for (int nv = 0; nv < numVals; nv++)
325
                                {
326
                                        fp >> xval;
327
                                        fp >> yval;
328
                                        curve3.addPoint(xval, yval);
329
                                }
6193 fschmid 330
                                int lin3;
331
                                fp >> lin3;
6129 fschmid 332
                                FPointArray curve4;
333
                                curve4.resize(0);
334
                                fp >> numVals;
335
                                for (int nv = 0; nv < numVals; nv++)
336
                                {
337
                                        fp >> xval;
338
                                        fp >> yval;
339
                                        curve4.addPoint(xval, yval);
340
                                }
6193 fschmid 341
                                int lin4;
342
                                fp >> lin4;
7478 jghali 343
                                quadtone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, colors[col3], shading3, curve3, lin3, colors[col4], shading4, curve4, lin4, cmyk);
6080 fschmid 344
                        }
9803 fschmid 345
                        if (effectsList.at(a).effectCode == EF_GRADUATE)
6116 fschmid 346
                        {
9803 fschmid 347
                                QString tmpstr = effectsList.at(a).effectParameters;
6116 fschmid 348
                                int numVals;
349
                                double xval, yval;
350
                                FPointArray curve;
351
                                curve.resize(0);
13497 jghali 352
                                ScTextStream fp(&tmpstr, QIODevice::ReadOnly);
6116 fschmid 353
                                fp >> numVals;
354
                                for (int nv = 0; nv < numVals; nv++)
355
                                {
356
                                        fp >> xval;
357
                                        fp >> yval;
358
                                        curve.addPoint(xval, yval);
359
                                }
6193 fschmid 360
                                int lin;
361
                                fp >> lin;
362
                                doGraduate(curve, cmyk, lin);
6116 fschmid 363
                        }
2074 fschmid 364
                }
365
        }
366
}
8002 fschmid 367
/*
2095 fschmid 368
void ScImage::liberateMemory(void **memory)
369
{
370
        assert(memory != (void **)NULL);
371
        if(*memory == (void *)NULL)
372
                return;
373
        free(*memory);
374
        *memory=(void *) NULL;
375
}
8002 fschmid 376
*/
2096 fschmid 377
void ScImage::solarize(double factor, bool cmyk)
378
{
12216 jghali 379
        QVector<int> curveTable(256);
2096 fschmid 380
        int fk = qRound(255 / factor);
381
        for (int i = 0; i < 256; ++i)
382
        {
8562 jghali 383
                curveTable[i] = qMin(255, static_cast<int>(i / fk) * fk);
2096 fschmid 384
        }
12216 jghali 385
        applyCurve(curveTable, cmyk);
2096 fschmid 386
}
2095 fschmid 387
 
6011 fschmid 388
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
389
void ScImage::blur(int radius)
390
{
15459 craig 391
        if (radius < 1) {
392
                return;
393
        }
2095 fschmid 394
 
15459 craig 395
        QRgb *pix = (QRgb*)bits();
396
        int w   = width();
397
        int h   = height();
398
        int wm  = w-1;
399
        int hm  = h-1;
400
        int wh  = w*h;
401
        int div = radius+radius+1;
6011 fschmid 402
 
15459 craig 403
        int *r = new int[wh];
404
        int *g = new int[wh];
405
        int *b = new int[wh];
406
        int *a = new int[wh];
407
        int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
408
        QRgb p;
409
        int *vmin = new int[qMax(w,h)];
6011 fschmid 410
 
15459 craig 411
        int divsum = (div+1)>>1;
412
        divsum *= divsum;
413
        int *dv = new int[256*divsum];
414
        for (i=0; i < 256*divsum; ++i) {
415
                dv[i] = (i/divsum);
416
        }
6011 fschmid 417
 
15459 craig 418
        yw = yi = 0;
6011 fschmid 419
 
15459 craig 420
        int **stack = new int*[div];
421
        for(int i = 0; i < div; ++i) {
422
                stack[i] = new int[4];
423
        }
6011 fschmid 424
 
425
 
15459 craig 426
        int stackpointer;
427
        int stackstart;
428
        int *sir;
429
        int rbs;
430
        int r1 = radius+1;
431
        int routsum, goutsum, boutsum, aoutsum;
432
        int rinsum, ginsum, binsum, ainsum;
6011 fschmid 433
 
15459 craig 434
        for (y = 0; y < h; ++y)
435
        {
436
                rinsum = ginsum = binsum = ainsum
437
                        = routsum = goutsum = boutsum = aoutsum
438
                        = rsum = gsum = bsum = asum = 0;
19596 jghali 439
                for(i = -radius; i <= radius; ++i)
15459 craig 440
                {
441
                        p = pix[yi+qMin(wm,qMax(i,0))];
442
                        sir = stack[i+radius];
443
                        sir[0] = qRed(p);
444
                        sir[1] = qGreen(p);
445
                        sir[2] = qBlue(p);
446
                        sir[3] = qAlpha(p);
6011 fschmid 447
 
15459 craig 448
                        rbs = r1-abs(i);
449
                        rsum += sir[0]*rbs;
450
                        gsum += sir[1]*rbs;
451
                        bsum += sir[2]*rbs;
452
                        asum += sir[3]*rbs;
6011 fschmid 453
 
15459 craig 454
                        if (i > 0)
455
                        {
456
                                rinsum += sir[0];
457
                                ginsum += sir[1];
458
                                binsum += sir[2];
459
                                ainsum += sir[3];
460
                        }
461
                        else
462
                        {
463
                                routsum += sir[0];
464
                                goutsum += sir[1];
465
                                boutsum += sir[2];
466
                                aoutsum += sir[3];
467
                        }
468
                }
469
                stackpointer = radius;
6011 fschmid 470
 
15459 craig 471
                for (x=0; x < w; ++x)
472
                {
6011 fschmid 473
 
15459 craig 474
                        r[yi] = dv[rsum];
475
                        g[yi] = dv[gsum];
476
                        b[yi] = dv[bsum];
477
                        a[yi] = dv[asum];
6011 fschmid 478
 
15459 craig 479
                        rsum -= routsum;
480
                        gsum -= goutsum;
481
                        bsum -= boutsum;
482
                        asum -= aoutsum;
6011 fschmid 483
 
15459 craig 484
                        stackstart = stackpointer-radius+div;
485
                        sir = stack[stackstart%div];
6011 fschmid 486
 
15459 craig 487
                        routsum -= sir[0];
488
                        goutsum -= sir[1];
489
                        boutsum -= sir[2];
490
                        aoutsum -= sir[3];
6011 fschmid 491
 
15459 craig 492
                        if (y == 0)
493
                        {
494
                                vmin[x] = qMin(x+radius+1,wm);
495
                        }
496
                        p = pix[yw+vmin[x]];
6011 fschmid 497
 
15459 craig 498
                        sir[0] = qRed(p);
499
                        sir[1] = qGreen(p);
500
                        sir[2] = qBlue(p);
501
                        sir[3] = qAlpha(p);
6011 fschmid 502
 
15459 craig 503
                        rinsum += sir[0];
504
                        ginsum += sir[1];
505
                        binsum += sir[2];
506
                        ainsum += sir[3];
6011 fschmid 507
 
15459 craig 508
                        rsum += rinsum;
509
                        gsum += ginsum;
510
                        bsum += binsum;
511
                        asum += ainsum;
6011 fschmid 512
 
15459 craig 513
                        stackpointer = (stackpointer+1)%div;
514
                        sir = stack[(stackpointer)%div];
6011 fschmid 515
 
15459 craig 516
                        routsum += sir[0];
517
                        goutsum += sir[1];
518
                        boutsum += sir[2];
519
                        aoutsum += sir[3];
6011 fschmid 520
 
15459 craig 521
                        rinsum -= sir[0];
522
                        ginsum -= sir[1];
523
                        binsum -= sir[2];
524
                        ainsum -= sir[3];
6011 fschmid 525
 
15459 craig 526
                        ++yi;
527
                }
528
                yw += w;
529
        }
530
        for (x=0; x < w; ++x)
531
        {
532
                rinsum = ginsum = binsum = ainsum
533
                        = routsum = goutsum = boutsum = aoutsum
534
                        = rsum = gsum = bsum = asum = 0;
6011 fschmid 535
 
15459 craig 536
                yp =- radius * w;
6011 fschmid 537
 
15459 craig 538
                for(i=-radius; i <= radius; ++i)
539
                {
540
                        yi=qMax(0,yp)+x;
6011 fschmid 541
 
15459 craig 542
                        sir = stack[i+radius];
6011 fschmid 543
 
15459 craig 544
                        sir[0] = r[yi];
545
                        sir[1] = g[yi];
546
                        sir[2] = b[yi];
547
                        sir[3] = a[yi];
6011 fschmid 548
 
15459 craig 549
                        rbs = r1-abs(i);
6011 fschmid 550
 
15459 craig 551
                        rsum += r[yi]*rbs;
552
                        gsum += g[yi]*rbs;
553
                        bsum += b[yi]*rbs;
554
                        asum += a[yi]*rbs;
6011 fschmid 555
 
15459 craig 556
                        if (i > 0)
557
                        {
558
                                rinsum += sir[0];
559
                                ginsum += sir[1];
560
                                binsum += sir[2];
561
                                ainsum += sir[3];
562
                        }
563
                        else
564
                        {
565
                                routsum += sir[0];
566
                                goutsum += sir[1];
567
                                boutsum += sir[2];
568
                                aoutsum += sir[3];
569
                        }
6011 fschmid 570
 
15459 craig 571
                        if (i < hm)
572
                        {
573
                                yp += w;
574
                        }
575
                }
6011 fschmid 576
 
15459 craig 577
                yi = x;
578
                stackpointer = radius;
6011 fschmid 579
 
15459 craig 580
                for (y=0; y < h; ++y)
581
                {
582
                        pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]);
6011 fschmid 583
 
15459 craig 584
                        rsum -= routsum;
585
                        gsum -= goutsum;
586
                        bsum -= boutsum;
587
                        asum -= aoutsum;
6011 fschmid 588
 
15459 craig 589
                        stackstart = stackpointer-radius+div;
590
                        sir = stack[stackstart%div];
6011 fschmid 591
 
15459 craig 592
                        routsum -= sir[0];
593
                        goutsum -= sir[1];
594
                        boutsum -= sir[2];
595
                        aoutsum -= sir[3];
6011 fschmid 596
 
15459 craig 597
                        if (x==0)
598
                        {
599
                                vmin[y] = qMin(y+r1,hm)*w;
600
                        }
601
                        p = x+vmin[y];
6011 fschmid 602
 
15459 craig 603
                        sir[0] = r[p];
604
                        sir[1] = g[p];
605
                        sir[2] = b[p];
606
                        sir[3] = a[p];
6011 fschmid 607
 
15459 craig 608
                        rinsum += sir[0];
609
                        ginsum += sir[1];
610
                        binsum += sir[2];
611
                        ainsum += sir[3];
6011 fschmid 612
 
15459 craig 613
                        rsum += rinsum;
614
                        gsum += ginsum;
615
                        bsum += binsum;
616
                        asum += ainsum;
6011 fschmid 617
 
15459 craig 618
                        stackpointer = (stackpointer+1)%div;
619
                        sir = stack[stackpointer];
620
 
621
                        routsum += sir[0];
622
                        goutsum += sir[1];
623
                        boutsum += sir[2];
624
                        aoutsum += sir[3];
625
 
626
                        rinsum -= sir[0];
627
                        ginsum -= sir[1];
628
                        binsum -= sir[2];
629
                        ainsum -= sir[3];
630
 
631
                        yi += w;
632
                }
633
        }
634
        delete [] r;
635
        delete [] g;
636
        delete [] b;
637
        delete [] a;
638
        delete [] vmin;
639
        delete [] dv;
640
 
641
        for(int i = 0; i < div; ++i)
642
        {
643
                delete [] stack[i];
644
        }
645
        delete [] stack;
6011 fschmid 646
}
6116 fschmid 647
 
2092 fschmid 648
bool ScImage::convolveImage(QImage *dest, const unsigned int order, const double *kernel)
649
{
650
        long widthk;
651
        double red, green, blue, alpha;
652
        double normalize, *normal_kernel;
653
        register const double *k;
654
        register unsigned int *q;
655
        int x, y, mx, my, sx, sy;
656
        long i;
657
        int mcx, mcy;
658
        widthk = order;
659
        if((widthk % 2) == 0)
660
                return(false);
661
        normal_kernel = (double *)malloc(widthk*widthk*sizeof(double));
662
        if(!normal_kernel)
663
                return(false);
10561 fschmid 664
        *dest = QImage(width(), height(), QImage::Format_ARGB32);
2092 fschmid 665
        normalize=0.0;
666
        for(i=0; i < (widthk*widthk); i++)
667
                normalize += kernel[i];
668
        if(fabs(normalize) <= 1.0e-12)
669
                normalize=1.0;
670
        normalize=1.0/normalize;
671
        for(i=0; i < (widthk*widthk); i++)
672
                normal_kernel[i] = normalize*kernel[i];
673
        for(y=0; y < dest->height(); ++y)
674
        {
675
                sy = y-(widthk/2);
676
                q = (unsigned int *)dest->scanLine(y);
677
                for(x=0; x < dest->width(); ++x)
678
                {
679
                        k = normal_kernel;
680
                        red = green = blue = alpha = 0;
681
                        sy = y-(widthk/2);
682
                        for(mcy=0; mcy < widthk; ++mcy, ++sy)
683
                        {
684
                                my = sy < 0 ? 0 : sy > height()-1 ? height()-1 : sy;
685
                                sx = x+(-widthk/2);
686
                                for(mcx=0; mcx < widthk; ++mcx, ++sx)
687
                                {
688
                                        mx = sx < 0 ? 0 : sx > width()-1 ? width()-1 : sx;
12135 fschmid 689
                                        int px = pixel(mx, my);
690
                                        red += (*k)*(qRed(px)*257);
691
                                        green += (*k)*(qGreen(px)*257);
692
                                        blue += (*k)*(qBlue(px)*257);
693
                                        alpha += (*k)*(qAlpha(px)*257);
2092 fschmid 694
                                        ++k;
695
                                }
696
                        }
697
                        red = red < 0 ? 0 : red > 65535 ? 65535 : red+0.5;
698
                        green = green < 0 ? 0 : green > 65535 ? 65535 : green+0.5;
699
                        blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue+0.5;
700
                        alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha+0.5;
701
                        *q++ = qRgba((unsigned char)(red/257UL),
2095 fschmid 702
                                     (unsigned char)(green/257UL),
703
                                     (unsigned char)(blue/257UL),
704
                                     (unsigned char)(alpha/257UL));
2092 fschmid 705
                }
706
        }
2095 fschmid 707
        free(normal_kernel);
2092 fschmid 708
        return(true);
709
}
710
 
711
int ScImage::getOptimalKernelWidth(double radius, double sigma)
712
{
713
        double normalize, value;
714
        long width;
715
        register long u;
716
        assert(sigma != 0.0);
717
        if(radius > 0.0)
718
                return((int)(2.0*ceil(radius)+1.0));
719
        for(width=5; ;)
720
        {
721
                normalize=0.0;
722
                for(u=(-width/2); u <= (width/2); u++)
723
                        normalize+=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma);
724
                u=width/2;
725
                value=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma)/normalize;
726
                if((long)(65535*value) <= 0)
727
                        break;
728
                width+=2;
729
        }
730
        return((int)width-2);
731
}
732
 
733
void ScImage::sharpen(double radius, double sigma)
734
{
735
        double alpha, normalize, *kernel;
736
        int widthk;
737
        register long i, u, v;
738
        QImage dest;
739
        if(sigma == 0.0)
740
                return;
741
        widthk = getOptimalKernelWidth(radius, sigma);
742
        if(width() < widthk)
743
                return;
744
        kernel = (double *)malloc(widthk*widthk*sizeof(double));
745
        if(!kernel)
746
                return;
747
        i = 0;
748
        normalize=0.0;
749
        for (v=(-widthk/2); v <= (widthk/2); v++)
750
        {
751
                for (u=(-widthk/2); u <= (widthk/2); u++)
752
                {
753
                        alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
754
                        kernel[i]=alpha/(2.0*3.14159265358979323846264338327950288419716939937510*sigma*sigma);
755
                        normalize+=kernel[i];
756
                        i++;
757
                }
758
        }
759
        kernel[i/2]=(-2.0)*normalize;
760
        convolveImage(&dest, widthk, kernel);
8002 fschmid 761
        free(kernel);
762
//      liberateMemory((void **) &kernel);
2092 fschmid 763
        for( int yi=0; yi < dest.height(); ++yi )
764
        {
765
                QRgb *s = (QRgb*)(dest.scanLine( yi ));
766
                QRgb *d = (QRgb*)(scanLine( yi ));
767
                for(int xi=0; xi < dest.width(); ++xi )
768
                {
769
                        (*d) = (*s);
770
                        s++;
771
                        d++;
772
                }
773
        }
774
        return;
775
}
776
 
2082 fschmid 777
void ScImage::contrast(int contrastValue, bool cmyk)
778
{
12216 jghali 779
        QVector<int> curveTable(256);
2082 fschmid 780
        QPoint p1(0,0 - contrastValue);
781
        QPoint p2(256, 256 + contrastValue);
782
        double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
783
        for (int i = 0; i < 256; ++i)
784
        {
8562 jghali 785
                curveTable[i] = qMin(255, qMax(0, int(i * mc) + p1.y()));
2082 fschmid 786
        }
12216 jghali 787
        applyCurve(curveTable, cmyk);
2082 fschmid 788
}
789
 
790
void ScImage::brightness(int brightnessValue, bool cmyk)
791
{
12216 jghali 792
        QVector<int> curveTable(256);
2082 fschmid 793
        QPoint p1(0,0 + brightnessValue);
794
        QPoint p2(256, 256 + brightnessValue);
795
        double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
796
        for (int i = 0; i < 256; ++i)
797
        {
8562 jghali 798
                curveTable[i] = qMin(255, qMax(0, int(i * mc) + p1.y()));
2082 fschmid 799
        }
12216 jghali 800
        applyCurve(curveTable, cmyk);
2082 fschmid 801
}
802
 
6193 fschmid 803
void ScImage::doGraduate(FPointArray curve, bool cmyk, bool linear)
6116 fschmid 804
{
12216 jghali 805
        QVector<int> curveTable(256);
6116 fschmid 806
        for (int x = 0 ; x < 256 ; x++)
807
        {
8562 jghali 808
                curveTable[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve, x / 255.0, linear) * 255)));
6116 fschmid 809
        }
12216 jghali 810
        applyCurve(curveTable, cmyk);
6116 fschmid 811
}
812
 
12216 jghali 813
void ScImage::applyCurve(const QVector<int>& curveTable, bool cmyk)
2082 fschmid 814
{
815
        int h = height();
816
        int w = width();
7175 fschmid 817
        QRgb *s;
818
        QRgb r;
819
        int c, m, y, k;
820
        unsigned char *p;
2082 fschmid 821
        for( int yi=0; yi < h; ++yi )
822
        {
7175 fschmid 823
                s = (QRgb*)(scanLine( yi ));
2082 fschmid 824
                for( int xi=0; xi < w; ++xi )
825
                {
7175 fschmid 826
                        r = *s;
2082 fschmid 827
                        if (cmyk)
828
                        {
7175 fschmid 829
                                p = (unsigned char *) s;
12108 jghali 830
                                p[0] = 255 - curveTable[255 - p[0]];
831
                                p[1] = 255 - curveTable[255 - p[1]];
832
                                p[2] = 255 - curveTable[255 - p[2]];
833
                                p[3] = 255 - curveTable[255 - p[3]];
2082 fschmid 834
                        }
835
                        else
836
                        {
837
                                c = curveTable[qRed(r)];
838
                                m = curveTable[qGreen(r)];
839
                                y = curveTable[qBlue(r)];
840
                                k = qAlpha(r);
841
                                *s = qRgba(c, m, y, k);
842
                        }
843
                        s++;
844
                }
845
        }
846
}
847
 
7478 jghali 848
void ScImage::colorize(ScribusDoc* doc, ScColor color, int shade, bool cmyk)
2053 fschmid 849
{
850
        int h = height();
851
        int w = width();
852
        int cc, cm, cy, ck;
2057 fschmid 853
        int hu, sa, v;
2886 fschmid 854
        ScColor tmp2;
2057 fschmid 855
        QColor tmpR;
7175 fschmid 856
        QRgb *s;
857
        QRgb r;
858
        double k;
859
        int cc2, cm2, cy2, k2;
2053 fschmid 860
        if (cmyk)
7478 jghali 861
        {
862
                CMYKColor cmykCol;
863
                ScColorEngine::getShadeColorCMYK(color, doc, cmykCol, shade);
864
                cmykCol.getValues(cc, cm, cy, ck);
865
        }
2053 fschmid 866
        else
867
        {
868
                ck = 0;
7478 jghali 869
                RGBColor rgbCol;
870
                ScColorEngine::getShadeColorRGB(color, doc, rgbCol, shade);
871
                rgbCol.getValues(cc, cm, cy);
2053 fschmid 872
        }
873
        for( int yi=0; yi < h; ++yi )
874
        {
7175 fschmid 875
                s = (QRgb*)(scanLine( yi ));
2053 fschmid 876
                for( int xi=0; xi < w; ++xi )
877
                {
7175 fschmid 878
                        r = *s;
2053 fschmid 879
                        if (cmyk)
880
                        {
8562 jghali 881
                                k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255) / 255.0;
882
                                *s = qRgba(qMin(qRound(cc*k), 255), qMin(qRound(cm*k), 255), qMin(qRound(cy*k), 255), qMin(qRound(ck*k), 255));
2053 fschmid 883
                        }
884
                        else
885
                        {
8562 jghali 886
                                k2 = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
2057 fschmid 887
                                tmpR.setRgb(cc, cm, cy);
10561 fschmid 888
                                tmpR.getHsv(&hu, &sa, &v);
7175 fschmid 889
                                tmpR.setHsv(hu, sa * k2 / 255, 255 - ((255 - v) * k2 / 255));
2057 fschmid 890
                                tmpR.getRgb(&cc2, &cm2, &cy2);
7175 fschmid 891
                                *s = qRgba(cc2, cm2, cy2, qAlpha(r));
2053 fschmid 892
                        }
893
                        s++;
894
                }
895
        }
896
}
897
 
7478 jghali 898
void ScImage::duotone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, bool cmyk)
6080 fschmid 899
{
900
        int h = height();
901
        int w = width();
902
        int c, c1, m, m1, y, y1, k, k1;
903
        int cn, c1n, mn, m1n, yn, y1n, kn, k1n;
904
        uchar cb;
9944 fschmid 905
        QVector<int> curveTable1;
906
        QVector<int> curveTable2;
7478 jghali 907
        CMYKColor cmykCol;
908
        ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
909
        cmykCol.getValues(c, m, y, k);
910
        ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
911
        cmykCol.getValues(c1, m1, y1, k1);
6129 fschmid 912
        curveTable1.resize(256);
913
        for (int x = 0 ; x < 256 ; x++)
914
        {
8562 jghali 915
                curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
6129 fschmid 916
        }
917
        curveTable2.resize(256);
918
        for (int x = 0 ; x < 256 ; x++)
919
        {
8562 jghali 920
                curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
6129 fschmid 921
        }
6080 fschmid 922
        for( int yi=0; yi < h; ++yi )
923
        {
924
                QRgb * s = (QRgb*)(scanLine( yi ));
925
                for( int xi=0; xi < w; ++xi )
926
                {
927
                        QRgb r=*s;
928
                        if (cmyk)
8562 jghali 929
                                cb = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
6080 fschmid 930
                        else
8562 jghali 931
                                cb = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
932
                        cn = qMin((c * curveTable1[(int)cb]) >> 8, 255);
933
                        mn = qMin((m * curveTable1[(int)cb]) >> 8, 255);
934
                        yn = qMin((y * curveTable1[(int)cb]) >> 8, 255);
935
                        kn = qMin((k * curveTable1[(int)cb]) >> 8, 255);
936
                        c1n = qMin((c1 * curveTable1[(int)cb]) >> 8, 255);
937
                        m1n = qMin((m1 * curveTable2[(int)cb]) >> 8, 255);
938
                        y1n = qMin((y1 * curveTable2[(int)cb]) >> 8, 255);
939
                        k1n = qMin((k1 * curveTable2[(int)cb]) >> 8, 255);
940
                        ScColor col = ScColor(qMin(cn+c1n, 255), qMin(mn+m1n, 255), qMin(yn+y1n, 255), qMin(kn+k1n, 255));
6080 fschmid 941
                        if (cmyk)
942
                                col.getCMYK(&cn, &mn, &yn, &kn);
943
                        else
944
                        {
945
                                col.getRawRGBColor(&cn, &mn, &yn);
946
                                kn = qAlpha(r);
947
                        }
948
                        *s = qRgba(cn, mn, yn, kn);
949
                        s++;
950
                }
951
        }
952
}
953
 
7478 jghali 954
void ScImage::tritone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, ScColor color3, int shade3, FPointArray curve3, bool lin3, bool cmyk)
6080 fschmid 955
{
956
        int h = height();
957
        int w = width();
958
        int c, c1, c2, m, m1, m2, y, y1, y2, k, k1, k2;
959
        int cn, c1n, c2n, mn, m1n, m2n, yn, y1n, y2n, kn, k1n, k2n;
960
        uchar cb;
7478 jghali 961
        CMYKColor cmykCol;
9944 fschmid 962
        QVector<int> curveTable1;
963
        QVector<int> curveTable2;
964
        QVector<int> curveTable3;
7478 jghali 965
        ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
966
        cmykCol.getValues(c, m, y, k);
967
        ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
968
        cmykCol.getValues(c1, m1, y1, k1);
969
        ScColorEngine::getShadeColorCMYK(color3, doc, cmykCol, shade3);
970
        cmykCol.getValues(c2, m2, y2, k2);
6129 fschmid 971
        curveTable1.resize(256);
972
        for (int x = 0 ; x < 256 ; x++)
973
        {
8562 jghali 974
                curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
6129 fschmid 975
        }
976
        curveTable2.resize(256);
977
        for (int x = 0 ; x < 256 ; x++)
978
        {
8562 jghali 979
                curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
6129 fschmid 980
        }
981
        curveTable3.resize(256);
982
        for (int x = 0 ; x < 256 ; x++)
983
        {
8562 jghali 984
                curveTable3[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin3) * 255)));
6129 fschmid 985
        }
6080 fschmid 986
        for( int yi=0; yi < h; ++yi )
987
        {
988
                QRgb * s = (QRgb*)(scanLine( yi ));
989
                for( int xi=0; xi < w; ++xi )
990
                {
991
                        QRgb r=*s;
992
                        if (cmyk)
8562 jghali 993
                                cb = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
6080 fschmid 994
                        else
8562 jghali 995
                                cb = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
996
                        cn = qMin((c * curveTable1[(int)cb]) >> 8, 255);
997
                        mn = qMin((m * curveTable1[(int)cb]) >> 8, 255);
998
                        yn = qMin((y * curveTable1[(int)cb]) >> 8, 255);
999
                        kn = qMin((k * curveTable1[(int)cb]) >> 8, 255);
1000
                        c1n = qMin((c1 * curveTable2[(int)cb]) >> 8, 255);
1001
                        m1n = qMin((m1 * curveTable2[(int)cb]) >> 8, 255);
1002
                        y1n = qMin((y1 * curveTable2[(int)cb]) >> 8, 255);
1003
                        k1n = qMin((k1 * curveTable2[(int)cb]) >> 8, 255);
1004
                        c2n = qMin((c2 * curveTable3[(int)cb]) >> 8, 255);
1005
                        m2n = qMin((m2 * curveTable3[(int)cb]) >> 8, 255);
1006
                        y2n = qMin((y2 * curveTable3[(int)cb]) >> 8, 255);
1007
                        k2n = qMin((k2 * curveTable3[(int)cb]) >> 8, 255);
1008
                        ScColor col = ScColor(qMin(cn+c1n+c2n, 255), qMin(mn+m1n+m2n, 255), qMin(yn+y1n+y2n, 255), qMin(kn+k1n+k2n, 255));
6080 fschmid 1009
                        if (cmyk)
1010
                                col.getCMYK(&cn, &mn, &yn, &kn);
1011
                        else
1012
                        {
1013
                                col.getRawRGBColor(&cn, &mn, &yn);
1014
                                kn = qAlpha(r);
1015
                        }
1016
                        *s = qRgba(cn, mn, yn, kn);
1017
                        s++;
1018
                }
1019
        }
1020
}
1021
 
7478 jghali 1022
void ScImage::quadtone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, ScColor color3, int shade3, FPointArray curve3, bool lin3, ScColor color4, int shade4, FPointArray curve4, bool lin4, bool cmyk)
6080 fschmid 1023
{
1024
        int h = height();
1025
        int w = width();
1026
        int c, c1, c2, c3, m, m1, m2, m3, y, y1, y2, y3, k, k1, k2, k3;
1027
        int cn, c1n, c2n, c3n, mn, m1n, m2n, m3n, yn, y1n, y2n, y3n, kn, k1n, k2n, k3n;
1028
        uchar cb;
7478 jghali 1029
        CMYKColor cmykCol;
9944 fschmid 1030
        QVector<int> curveTable1;
1031
        QVector<int> curveTable2;
1032
        QVector<int> curveTable3;
1033
        QVector<int> curveTable4;
7478 jghali 1034
        ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
1035
        cmykCol.getValues(c, m, y, k);
1036
        ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
1037
        cmykCol.getValues(c1, m1, y1, k1);
1038
        ScColorEngine::getShadeColorCMYK(color3, doc, cmykCol, shade3);
1039
        cmykCol.getValues(c2, m2, y2, k2);
1040
        ScColorEngine::getShadeColorCMYK(color4, doc, cmykCol, shade4);
1041
        cmykCol.getValues(c3, m3, y3, k3);
6129 fschmid 1042
        curveTable1.resize(256);
1043
        for (int x = 0 ; x < 256 ; x++)
1044
        {
8562 jghali 1045
                curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
6129 fschmid 1046
        }
1047
        curveTable2.resize(256);
1048
        for (int x = 0 ; x < 256 ; x++)
1049
        {
8562 jghali 1050
                curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
6129 fschmid 1051
        }
1052
        curveTable3.resize(256);
1053
        for (int x = 0 ; x < 256 ; x++)
1054
        {
8562 jghali 1055
                curveTable3[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve3, x / 255.0, lin3) * 255)));
6129 fschmid 1056
        }
1057
        curveTable4.resize(256);
1058
        for (int x = 0 ; x < 256 ; x++)
1059
        {
8562 jghali 1060
                curveTable4[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve4, x / 255.0, lin4) * 255)));
6129 fschmid 1061
        }
6080 fschmid 1062
        for( int yi=0; yi < h; ++yi )
1063
        {
1064
                QRgb * s = (QRgb*)(scanLine( yi ));
1065
                for( int xi=0; xi < w; ++xi )
1066
                {
1067
                        QRgb r=*s;
1068
                        if (cmyk)
8562 jghali 1069
                                cb = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
6080 fschmid 1070
                        else
8562 jghali 1071
                                cb = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
1072
                        cn = qMin((c * curveTable1[(int)cb]) >> 8, 255);
1073
                        mn = qMin((m * curveTable1[(int)cb]) >> 8, 255);
1074
                        yn = qMin((y * curveTable1[(int)cb]) >> 8, 255);
1075
                        kn = qMin((k * curveTable1[(int)cb]) >> 8, 255);
1076
                        c1n = qMin((c1 * curveTable2[(int)cb]) >> 8, 255);
1077
                        m1n = qMin((m1 * curveTable2[(int)cb]) >> 8, 255);
1078
                        y1n = qMin((y1 * curveTable2[(int)cb]) >> 8, 255);
1079
                        k1n = qMin((k1 * curveTable2[(int)cb]) >> 8, 255);
1080
                        c2n = qMin((c2 * curveTable3[(int)cb]) >> 8, 255);
1081
                        m2n = qMin((m2 * curveTable3[(int)cb]) >> 8, 255);
1082
                        y2n = qMin((y2 * curveTable3[(int)cb]) >> 8, 255);
1083
                        k2n = qMin((k2 * curveTable3[(int)cb]) >> 8, 255);
1084
                        c3n = qMin((c3 * curveTable4[(int)cb]) >> 8, 255);
1085
                        m3n = qMin((m3 * curveTable4[(int)cb]) >> 8, 255);
1086
                        y3n = qMin((y3 * curveTable4[(int)cb]) >> 8, 255);
1087
                        k3n = qMin((k3 * curveTable4[(int)cb]) >> 8, 255);
1088
                        ScColor col = ScColor(qMin(cn+c1n+c2n+c3n, 255), qMin(mn+m1n+m2n+m3n, 255), qMin(yn+y1n+y2n+y3n, 255), qMin(kn+k1n+k2n+k3n, 255));
6080 fschmid 1089
                        if (cmyk)
1090
                                col.getCMYK(&cn, &mn, &yn, &kn);
1091
                        else
1092
                        {
1093
                                col.getRawRGBColor(&cn, &mn, &yn);
1094
                                kn = qAlpha(r);
1095
                        }
1096
                        *s = qRgba(cn, mn, yn, kn);
1097
                        s++;
1098
                }
1099
        }
1100
}
1101
 
2057 fschmid 1102
void ScImage::invert(bool cmyk)
1103
{
1104
        int h = height();
1105
        int w = width();
7175 fschmid 1106
        unsigned char *p;
1107
        QRgb * s;
1108
        unsigned char c, m, y, k;
2057 fschmid 1109
        for( int yi=0; yi < h; ++yi )
1110
        {
7175 fschmid 1111
                s = (QRgb*)(scanLine( yi ));
2057 fschmid 1112
                for( int xi=0; xi < w; ++xi )
1113
                {
1114
                        if (cmyk)
1115
                        {
7175 fschmid 1116
                                p = (unsigned char *) s;
8562 jghali 1117
                                c = 255 - qMin(255, p[0] + p[3]);
1118
                                m = 255 - qMin(255, p[1] + p[3]);
1119
                                y = 255 - qMin(255, p[2] + p[3]);
1120
                                k = qMin(qMin(c, m), y);
2766 cbradney 1121
                                p[0] = c - k;
1122
                                p[1] = m - k;
1123
                                p[2] = y - k;
1124
                                p[3] = k;
2057 fschmid 1125
                        }
1126
                        else
2766 cbradney 1127
                                *s ^= 0x00ffffff;
2057 fschmid 1128
                        s++;
1129
                }
1130
        }
1131
}
1132
 
2053 fschmid 1133
void ScImage::toGrayscale(bool cmyk)
1134
{
1135
        int h = height();
1136
        int w = width();
7175 fschmid 1137
        int k;
1138
        QRgb * s;
1139
        QRgb r;
2053 fschmid 1140
        for( int yi=0; yi < h; ++yi )
1141
        {
7175 fschmid 1142
                s = (QRgb*)(scanLine( yi ));
2053 fschmid 1143
                for( int xi=0; xi < w; ++xi )
1144
                {
7175 fschmid 1145
                        r = *s;
2053 fschmid 1146
                        if (cmyk)
1147
                        {
8562 jghali 1148
                                k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
2053 fschmid 1149
                                *s = qRgba(0, 0, 0, k);
1150
                        }
1151
                        else
1152
                        {
8562 jghali 1153
                                k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
7175 fschmid 1154
                                *s = qRgba(k, k, k, qAlpha(r));
2053 fschmid 1155
                        }
1156
                        s++;
1157
                }
1158
        }
1159
}
1160
 
2012 fschmid 1161
void ScImage::swapRGBA()
1162
{
7175 fschmid 1163
        unsigned int *ptr;
1164
        unsigned char *p;
1165
        unsigned char r, b;
2012 fschmid 1166
        for (int i = 0; i < height(); ++i)
1167
        {
7175 fschmid 1168
                ptr = (unsigned int *) scanLine(i);
2012 fschmid 1169
                for (int j = 0; j < width(); ++j)
1170
                {
7175 fschmid 1171
                        p = (unsigned char *) ptr;
2766 cbradney 1172
                        r = p[0];
1173
                        b = p[2];
1174
                        p[2] = r;
1175
                        p[0] = b;
1176
                        ptr++;
2012 fschmid 1177
                }
1178
        }
1179
}
1180
 
14539 jghali 1181
bool ScImage::createLowRes(double scale)
2012 fschmid 1182
{
2025 fschmid 1183
        int w = qRound(width() / scale);
1184
        int h = qRound(height() / scale);
14539 jghali 1185
        if (w >= width() && h >= height())  // don't do unnecessary scaling
1186
                return false;
10561 fschmid 1187
        QImage tmp = scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
11610 jghali 1188
        if (tmp.format() != QImage::Format_ARGB32)
1189
                tmp = tmp.convertToFormat(QImage::Format_ARGB32);
1190
        QImage::operator=(tmp);
14539 jghali 1191
        return true;
2012 fschmid 1192
}
1193
 
14467 jghali 1194
bool ScImage::convert2JPG(QString fn, int Quality, bool isCMYK, bool isGray)
2004 fschmid 1195
{
15165 jghali 1196
        bool success = false;
1197
        QFile file(fn);
1198
        if (file.open(QIODevice::WriteOnly))
2004 fschmid 1199
        {
15165 jghali 1200
                ScJpegEncodeFilter::Color imgColor = ScJpegEncodeFilter::GRAY;
2004 fschmid 1201
                if (isCMYK)
15165 jghali 1202
                        imgColor = ScJpegEncodeFilter::CMYK;
1203
                else if (!isGray)
1204
                        imgColor = ScJpegEncodeFilter::RGB;
1205
                int qual[] = { 95, 85, 75, 50, 25 };  // These are the JPEG Quality settings 100 means best, 0 .. don't discuss
1206
                QDataStream dataStream(&file);
1207
                ScJpegEncodeFilter jpegFilter(&dataStream, width(), height(), imgColor);
1208
                jpegFilter.setQuality(qual[Quality]);
1209
                if (jpegFilter.openFilter())
2004 fschmid 1210
                {
15165 jghali 1211
                        if (isCMYK)
1212
                                success = writeCMYKDataToFilter(&jpegFilter);
1213
                        else if (isGray)
1214
                                success = writeGrayDataToFilter(&jpegFilter, true);
2004 fschmid 1215
                        else
15165 jghali 1216
                                success = writeRGBDataToFilter(&jpegFilter);
1217
                        success &= jpegFilter.closeFilter();
2004 fschmid 1218
                }
15165 jghali 1219
                file.close();
2004 fschmid 1220
        }
15165 jghali 1221
        return success;
2004 fschmid 1222
}
1223
 
5234 fschmid 1224
QByteArray ScImage::ImageToArray()
2004 fschmid 1225
{
2884 fschmid 1226
        int i = 0;
2004 fschmid 1227
        int h = height();
1228
        int w = width();
2884 fschmid 1229
        unsigned char u;
7175 fschmid 1230
        QRgb *s;
1231
        QRgb r;
10561 fschmid 1232
        QByteArray imgArray(3 * h * w, ' ');
11060 jghali 1233
        if (imgArray.isNull())
1234
                return imgArray;
2004 fschmid 1235
        for( int yi=0; yi < h; ++yi )
1236
        {
7175 fschmid 1237
                s = (QRgb*)(scanLine( yi ));
2004 fschmid 1238
                for( int xi=0; xi < w; ++xi )
1239
                {
7175 fschmid 1240
                        r = *s++;
2884 fschmid 1241
                        u=qRed(r);
5234 fschmid 1242
                        imgArray[i++] = u;
2004 fschmid 1243
                        u=qGreen(r);
5234 fschmid 1244
                        imgArray[i++] = u;
2004 fschmid 1245
                        u=qBlue(r);
5234 fschmid 1246
                        imgArray[i++] = u;
2004 fschmid 1247
                }
1248
        }
5234 fschmid 1249
        return imgArray;
2004 fschmid 1250
}
1251
 
11597 jghali 1252
void ScImage::convertToGray(void)
2004 fschmid 1253
{
12135 fschmid 1254
        int k;
2004 fschmid 1255
        int h = height();
1256
        int w = width();
11597 jghali 1257
        QRgb *s, r;
11568 jghali 1258
        for( int yi=0; yi < h; ++yi )
2004 fschmid 1259
        {
11568 jghali 1260
                s = (QRgb*)(scanLine( yi ));
1261
                for( int xi=0; xi < w; ++xi )
2004 fschmid 1262
                {
11597 jghali 1263
                        r = *s;
1264
                        k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
1265
                        *s++ = qRgba(k, 0, 0, 0);
1266
                }
1267
        }
1268
}
1269
 
1270
bool ScImage::writeRGBDataToFilter(ScStreamFilter* filter)
1271
{
1272
        QRgb r, *s;
1273
        QByteArray buffer;
1274
        bool success = true;
1275
        int  h = height();
1276
        int  w = width();
1277
        int  pending = 0;
1278
        int  scanLineSize = (3 * w);
1279
        int  bufferSize   = qMax(scanLineSize, (65536 - 65536 % scanLineSize));
1280
        buffer.resize(bufferSize + 16);
1281
        if (buffer.isNull()) // Memory allocation failure
1282
                return false;
1283
        for( int yi=0; yi < h; ++yi )
1284
        {
1285
                s = (QRgb*)(scanLine( yi ));
1286
                for( int xi=0; xi < w; ++xi )
1287
                {
11568 jghali 1288
                        r = *s++;
11597 jghali 1289
                        buffer[pending++] = static_cast<unsigned char>(qRed(r));
1290
                        buffer[pending++] = static_cast<unsigned char>(qGreen(r));
1291
                        buffer[pending++] = static_cast<unsigned char>(qBlue(r));
2004 fschmid 1292
                }
11597 jghali 1293
                if (pending >= bufferSize)
1294
                {
1295
                        success &= filter->writeData(buffer.constData(), pending);
1296
                        pending = 0;
1297
                }
2004 fschmid 1298
        }
11597 jghali 1299
        if (pending)
1300
                success &= filter->writeData(buffer.constData(), pending);
1301
        return success;
11568 jghali 1302
}
1303
 
12732 fschmid 1304
bool ScImage::writeGrayDataToFilter(ScStreamFilter* filter, bool precal)
11597 jghali 1305
{
1306
        QRgb r, *s;
1307
        QByteArray buffer;
1308
        bool success = true;
1309
        int  h = height();
1310
        int  w = width();
1311
        int  pending = 0, k;
1312
        int  scanLineSize = w;
1313
        int  bufferSize   = qMax(scanLineSize, (65536 - 65536 % scanLineSize));
1314
        buffer.resize(bufferSize + 16);
1315
        if (buffer.isNull()) // Memory allocation failure
1316
                return false;
1317
        for( int yi=0; yi < h; ++yi )
1318
        {
1319
                s = (QRgb*)(scanLine( yi ));
12732 fschmid 1320
                if (precal) // image data is already grayscale, no need for weighted conversion
11597 jghali 1321
                {
12732 fschmid 1322
                        for( int xi=0; xi < w; ++xi )
1323
                        {
1324
                                r = *s;
1325
                                k = qRed(r);
1326
                                buffer[pending++] = k;
1327
                                s++;
1328
                        }
11597 jghali 1329
                }
12732 fschmid 1330
                else
1331
                {
1332
                        for( int xi=0; xi < w; ++xi )
1333
                        {
1334
                                r = *s;
1335
                                k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
1336
                                buffer[pending++] = k;
1337
                                s++;
1338
                        }
1339
                }
11597 jghali 1340
                if (pending >= bufferSize)
1341
                {
1342
                        success &= filter->writeData(buffer.constData(), pending);
1343
                        pending = 0;
1344
                }
1345
        }
1346
        if (pending)
1347
                success &= filter->writeData(buffer.constData(), pending);
1348
        return success;
1349
}
1350
 
17758 jghali 1351
bool ScImage::writeMonochromeDataToFilter(ScStreamFilter* filter, bool fromCmyk)
1352
{
1353
        QRgb *s;
1354
        QByteArray buffer;
1355
        bool success = true;
1356
        int  h = height();
1357
        int  w = width();
1358
        int  byteCount = 0;
1359
        int  bufferSize = (w + 7) / 8 * h;
1360
        int  value;
1361
        const unsigned char threshold = 127;
1362
        buffer.resize(bufferSize);
1363
        if (buffer.isNull()) // Memory allocation failure
1364
                return false;
1365
        for (int yi = 0; yi < h; ++yi)
1366
        {
1367
                char curByte = 0;
1368
                int bitCount = 0;
1369
                s = (QRgb*)(scanLine( yi ));
1370
                for (int xi = 0; xi < w; ++xi)
1371
                {
1372
                        curByte <<= 1;
1373
                        value = fromCmyk ? (255 - qAlpha(*s)) : qRed(*s);
1374
                        if (value > threshold) // In monochrome images all elements have the same value.
1375
                                curByte |= 1;
1376
                        ++bitCount;
1377
                        if (bitCount == 8)
1378
                        {
1379
                                buffer[byteCount++] = curByte;
1380
                                curByte = 0;
1381
                                bitCount = 0;
1382
                        }
1383
                        ++s;
1384
                }
1385
                // End of line is aligned to byte.
1386
                if (bitCount > 0) {
1387
                        curByte <<=  8-bitCount;
1388
                        buffer[byteCount++] = curByte;
1389
                }
1390
        }
1391
        assert(byteCount == bufferSize);
1392
        success = filter->writeData(buffer.constData(), byteCount);
1393
        return success;
1394
}
1395
 
11597 jghali 1396
bool ScImage::writeCMYKDataToFilter(ScStreamFilter* filter)
1397
{
1398
        QRgb r, *s;
1399
        QByteArray buffer;
1400
        bool success = true;
1401
        int  h = height();
1402
        int  w = width();
1403
        int  pending = 0;
1404
        int  scanLineSize = (4 * w);
1405
        int  bufferSize   = qMax(scanLineSize, (65536 - 65536 % scanLineSize));
1406
        buffer.resize(bufferSize + 16);
1407
        if (buffer.isNull()) // Memory allocation failure
1408
                return false;
1409
        for( int yi=0; yi < h; ++yi )
1410
        {
1411
                s = (QRgb*)(scanLine( yi ));
1412
                for( int xi=0; xi < w; ++xi )
1413
                {
1414
                        r = *s++;
1415
                        buffer[pending++] = static_cast<unsigned char> (qRed(r));
1416
                        buffer[pending++] = static_cast<unsigned char> (qGreen(r));
1417
                        buffer[pending++] = static_cast<unsigned char> (qBlue(r));
1418
                        buffer[pending++] = static_cast<unsigned char> (qAlpha(r));
1419
                }
1420
                if (pending >= bufferSize)
1421
                {
1422
                        success &= filter->writeData(buffer.constData(), pending);
1423
                        pending = 0;
1424
                }
1425
        }
1426
        if (pending)
1427
                success &= filter->writeData(buffer.constData(), pending);
1428
        return success;
1429
}
1430
 
11568 jghali 1431
bool ScImage::writePSImageToFilter(ScStreamFilter* filter, int pl)
1432
{
1433
        QRgb r, *s;
1434
        QByteArray buffer;
1435
        bool success = true;
1436
        int  c, m, y, k;
1437
        int  h = height();
1438
        int  w = width();
1439
        int  pending = 0;
1440
        int  scanLineSize = (pl == -1) ? (4 * w) : w;
1441
        int  bufferSize   = qMax(scanLineSize, (65536 - 65536 % scanLineSize));
1442
        buffer.resize(bufferSize + 16);
1443
        if (buffer.isNull()) // Memory allocation failure
1444
                return false;
1445
        for( int yi=0; yi < h; ++yi )
2004 fschmid 1446
        {
11568 jghali 1447
                s = (QRgb*)(scanLine( yi ));
1448
                for( int xi=0; xi < w; ++xi )
2004 fschmid 1449
                {
11568 jghali 1450
                        r = *s++;
1451
                        c = qRed(r);
1452
                        m = qGreen(r);
1453
                        y = qBlue(r);
1454
                        k = qAlpha(r);
1455
                        if (pl == -1)
2004 fschmid 1456
                        {
11568 jghali 1457
                                buffer[pending++] = static_cast<unsigned char> (c);
1458
                                buffer[pending++] = static_cast<unsigned char> (m);
1459
                                buffer[pending++] = static_cast<unsigned char> (y);
1460
                                buffer[pending++] = static_cast<unsigned char> (k);
2004 fschmid 1461
                        }
11568 jghali 1462
                        else
1463
                        {
1464
                                if (pl == -2)
1465
                                        buffer[pending++] = static_cast<unsigned char> (qMin(255, qRound(0.3 * c + 0.59 * m + 0.11 * y + k)));
1466
                                if (pl == 1)
1467
                                        buffer[pending++] = static_cast<unsigned char> (c);
1468
                                if (pl == 2)
1469
                                        buffer[pending++] = static_cast<unsigned char> (m);
1470
                                if (pl == 3)
1471
                                        buffer[pending++] = static_cast<unsigned char> (y);
1472
                                if (pl == 0)
1473
                                        buffer[pending++] = static_cast<unsigned char> (k);
1474
                        }
2004 fschmid 1475
                }
11568 jghali 1476
                if (pending >= bufferSize)
1477
                {
1478
                        success &= filter->writeData(buffer.constData(), pending);
1479
                        pending = 0;
1480
                }
2004 fschmid 1481
        }
11568 jghali 1482
        if (pending)
1483
                success &= filter->writeData(buffer.constData(), pending);
1484
        return success;
2004 fschmid 1485
}
1486
 
11568 jghali 1487
bool ScImage::writePSImageToFilter(ScStreamFilter* filter, const QByteArray& mask, int pl)
1488
{
1489
        QRgb r, *s;
1490
        QByteArray buffer;
1491
        bool success = true;
1492
        int  c, m, y, k;
1493
        int  h = height();
1494
        int  w = width();
12135 fschmid 1495
        int  pending = 0;
11568 jghali 1496
        int  scanLineSize = (pl == -1) ? (5 * w) : (2 * w);
1497
        int  bufferSize   = qMax(scanLineSize, (65536 - 65536 % scanLineSize));
1498
        if (mask.size() < (h * w))  // Check if mask provide enough data
1499
                return false;
1500
        buffer.resize(bufferSize + 16);
1501
        if (buffer.isNull()) // Check for memory allocation failure
1502
                return false;
1503
        unsigned char* maskData = (unsigned char*) mask.constData();
1504
        for( int yi=0; yi < h; ++yi )
1505
        {
1506
                s = (QRgb*)(scanLine( yi ));
1507
                for( int xi=0; xi < w; ++xi )
1508
                {
1509
                        r = *s++;
1510
                        c = qRed(r);
1511
                        m = qGreen(r);
1512
                        y = qBlue(r);
1513
                        k = qAlpha(r);
1514
                        if (pl == -1)
1515
                        {
1516
                                buffer[pending++] = *maskData++;
1517
                                buffer[pending++] = static_cast<unsigned char> (c);
1518
                                buffer[pending++] = static_cast<unsigned char> (m);
1519
                                buffer[pending++] = static_cast<unsigned char> (y);
1520
                                buffer[pending++] = static_cast<unsigned char> (k);
1521
                        }
1522
                        else
1523
                        {
1524
                                buffer[pending++] = *maskData++;
1525
                                if (pl == -2)
1526
                                        buffer[pending++] = static_cast<unsigned char> (qMin(255, qRound(0.3 * c + 0.59 * m + 0.11 * y + k)));
1527
                                if (pl == 1)
1528
                                        buffer[pending++] = static_cast<unsigned char> (c);
1529
                                if (pl == 2)
1530
                                        buffer[pending++] = static_cast<unsigned char> (m);
1531
                                if (pl == 3)
1532
                                        buffer[pending++] = static_cast<unsigned char> (y);
1533
                                if (pl == 0)
1534
                                        buffer[pending++] = static_cast<unsigned char> (k);
1535
                        }
1536
                }
1537
                if (pending >= bufferSize)
1538
                {
1539
                        success &= filter->writeData(buffer.constData(), pending);
1540
                        pending = 0;
1541
                }
1542
        }
1543
        if (pending)
1544
                success &= filter->writeData(buffer.constData(), pending);
1545
        return success;
1546
}
1547
 
2004 fschmid 1548
void ScImage::scaleImage(int nwidth, int nheight)
1549
{
17431 jghali 1550
        int depth = this->depth();
1551
        if (depth == 32)
1552
        {
1553
                scaleImage32bpp(nwidth, nheight);
1554
                return;
1555
        }
1556
        scaleImageGeneric(nwidth, nheight);
1557
}
1558
 
1559
void ScImage::scaleImage32bpp(int nwidth, int nheight)
1560
{
10561 fschmid 1561
        QImage dst(nwidth, nheight, QImage::Format_ARGB32);
2004 fschmid 1562
        QRgb* xelrow = 0;
1563
        QRgb* tempxelrow = 0;
1564
        register QRgb* xP;
1565
        register QRgb* nxP;
1566
        int rows, cols, rowsread, newrows, newcols;
1567
        register int row, col, needtoreadrow;
1568
        const uchar maxval = 255;
1569
        double xscale, yscale;
1570
        long sxscale, syscale;
1571
        register long fracrowtofill, fracrowleft;
1572
        long* as;
1573
        long* rs;
1574
        long* gs;
1575
        long* bs;
1576
        int rowswritten = 0;
17431 jghali 1577
 
1578
        int depth = this->depth();
1579
        if (depth != 32)
1580
        {
1581
                QImage::operator=(QImage::scaled(nwidth, nheight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
1582
                return;
1583
        }
1584
 
2004 fschmid 1585
        cols = width();
1586
        rows = height();
1587
        newcols = dst.width();
1588
        newrows = dst.height();
1589
        long SCALE;
1590
        long HALFSCALE;
1591
        if (cols > 4096)
1592
        {
1593
                SCALE = 4096;
1594
                HALFSCALE = 2048;
1595
        }
1596
        else
1597
        {
1598
                int fac = 4096;
12214 fschmid 1599
                while ((cols * fac) > 4096)
2004 fschmid 1600
                {
1601
                        fac /= 2;
1602
                }
1603
                SCALE = fac * cols;
1604
                HALFSCALE = fac * cols / 2;
1605
        }
1606
        xscale = (double) newcols / (double) cols;
1607
        yscale = (double) newrows / (double) rows;
1608
        sxscale = (long)(xscale * SCALE);
1609
        syscale = (long)(yscale * SCALE);
1610
        if ( newrows != rows )  /* shortcut Y scaling if possible */
1611
                tempxelrow = new QRgb[cols];
1612
        as = new long[cols];
1613
        rs = new long[cols];
1614
        gs = new long[cols];
1615
        bs = new long[cols];
1616
        rowsread = 0;
1617
        fracrowleft = syscale;
1618
        needtoreadrow = 1;
1619
        for ( col = 0; col < cols; ++col )
1620
                rs[col] = gs[col] =  as[col] = bs[col] = HALFSCALE;
1621
        fracrowtofill = SCALE;
1622
        for ( row = 0; row < newrows; ++row )
1623
        {
1624
                if ( newrows == rows )
1625
                        tempxelrow = xelrow = (QRgb*)scanLine(rowsread++);
1626
                else
1627
                {
1628
                        while ( fracrowleft < fracrowtofill )
1629
                        {
1630
                                if ( needtoreadrow && rowsread < rows )
1631
                                        xelrow = (QRgb*)scanLine(rowsread++);
1632
                                for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
1633
                                {
1634
                                        as[col] += fracrowleft * qAlpha( *xP );
1635
                                        rs[col] += fracrowleft * qRed( *xP );
1636
                                        gs[col] += fracrowleft * qGreen( *xP );
1637
                                        bs[col] += fracrowleft * qBlue( *xP );
1638
                                }
1639
                                fracrowtofill -= fracrowleft;
1640
                                fracrowleft = syscale;
1641
                                needtoreadrow = 1;
1642
                        }
1643
                        if ( needtoreadrow && rowsread < rows )
1644
                        {
1645
                                xelrow = (QRgb*)scanLine(rowsread++);
1646
                                needtoreadrow = 0;
1647
                        }
1648
                        register long a=0;
1649
                        for ( col = 0, xP = xelrow, nxP = tempxelrow; col < cols; ++col, ++xP, ++nxP )
1650
                        {
1651
                                register long r, g, b;
1652
                                a = as[col] + fracrowtofill * qAlpha( *xP );
1653
                                r = rs[col] + fracrowtofill * qRed( *xP );
1654
                                g = gs[col] + fracrowtofill * qGreen( *xP );
1655
                                b = bs[col] + fracrowtofill * qBlue( *xP );
1656
                                r /= SCALE;
1657
                                if ( r > maxval ) r = maxval;
1658
                                g /= SCALE;
1659
                                if ( g > maxval ) g = maxval;
1660
                                b /= SCALE;
1661
                                if ( b > maxval ) b = maxval;
1662
                                a /= SCALE;
1663
                                if ( a > maxval ) a = maxval;
1664
                                *nxP = qRgba( (int)r, (int)g, (int)b , (int)a);
1665
                                rs[col] = as[col] = gs[col] = bs[col] = HALFSCALE;
1666
                        }
1667
                        fracrowleft -= fracrowtofill;
1668
                        if ( fracrowleft == 0 )
1669
                        {
1670
                                fracrowleft = syscale;
1671
                                needtoreadrow = 1;
1672
                        }
1673
                        fracrowtofill = SCALE;
1674
                }
1675
                if ( newcols == cols )
1676
                        memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols*4);
1677
                else
1678
                {
1679
                        register long a, r, g, b;
1680
                        register long fraccoltofill, fraccolleft = 0;
1681
                        register int needcol;
1682
                        nxP = (QRgb*)dst.scanLine(rowswritten++);
19190 jghali 1683
                        QRgb *nxPEnd = nxP + newcols;
2004 fschmid 1684
                        fraccoltofill = SCALE;
1685
                        a = r = g = b = HALFSCALE;
1686
                        needcol = 0;
1687
                        for ( col = 0, xP = tempxelrow; col < cols; ++col, ++xP )
1688
                        {
1689
                                fraccolleft = sxscale;
1690
                                while ( fraccolleft >= fraccoltofill )
1691
                                {
1692
                                        if ( needcol )
1693
                                        {
1694
                                                ++nxP;
1695
                                                a = r = g = b = HALFSCALE;
1696
                                        }
1697
                                        a += fraccoltofill * qAlpha( *xP );
1698
                                        r += fraccoltofill * qRed( *xP );
1699
                                        g += fraccoltofill * qGreen( *xP );
1700
                                        b += fraccoltofill * qBlue( *xP );
1701
                                        r /= SCALE;
1702
                                        if ( r > maxval ) r = maxval;
1703
                                        g /= SCALE;
1704
                                        if ( g > maxval ) g = maxval;
1705
                                        b /= SCALE;
1706
                                        if ( b > maxval ) b = maxval;
1707
                                        a /= SCALE;
1708
                                        if ( a > maxval ) a = maxval;
1709
                                        *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
1710
                                        fraccolleft -= fraccoltofill;
1711
                                        fraccoltofill = SCALE;
1712
                                        needcol = 1;
1713
                                }
1714
                                if ( fraccolleft > 0 )
1715
                                {
1716
                                        if ( needcol )
1717
                                        {
1718
                                                ++nxP;
1719
                                                a = r = g = b = HALFSCALE;
1720
                                                needcol = 0;
1721
                                        }
1722
                                        a += fraccolleft * qAlpha( *xP );
1723
                                        r += fraccolleft * qRed( *xP );
1724
                                        g += fraccolleft * qGreen( *xP );
1725
                                        b += fraccolleft * qBlue( *xP );
1726
                                        fraccoltofill -= fraccolleft;
1727
                                }
1728
                        }
1729
                        if ( fraccoltofill > 0 )
1730
                        {
1731
                                --xP;
19190 jghali 1732
                                a += fraccoltofill * qAlpha( *xP );
2004 fschmid 1733
                                r += fraccoltofill * qRed( *xP );
1734
                                g += fraccoltofill * qGreen( *xP );
1735
                                b += fraccoltofill * qBlue( *xP );
1736
                        }
19190 jghali 1737
                        if (nxP < nxPEnd)
2004 fschmid 1738
                        {
1739
                                r /= SCALE;
1740
                                if ( r > maxval ) r = maxval;
1741
                                g /= SCALE;
1742
                                if ( g > maxval ) g = maxval;
1743
                                b /= SCALE;
1744
                                if ( b > maxval ) b = maxval;
1745
                                a /= SCALE;
1746
                                if ( a > maxval ) a = maxval;
1747
                                *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
19190 jghali 1748
                                while (++nxP != nxPEnd)
1749
                                        nxP[0] = nxP[-1];
2004 fschmid 1750
                        }
1751
                }
1752
        }
1753
        if ( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 1 day
1754
                delete [] tempxelrow;
1755
        if ( as )                               // Avoid purify complaint
1756
                delete [] as;
1757
        if ( rs )                               // Robust, rs might be 0 one day
1758
                delete [] rs;
1759
        if ( gs )                               // Robust, gs might be 0 one day
1760
                delete [] gs;
1761
        if ( bs )                               // Robust, bs might be 0 one day
1762
                delete [] bs;
10664 fschmid 1763
        QImage::operator=(QImage(nwidth, nheight, QImage::Format_ARGB32));
2004 fschmid 1764
        for( int yi=0; yi < dst.height(); ++yi )
1765
        {
1766
                QRgb *s = (QRgb*)(dst.scanLine( yi ));
1767
                QRgb *d = (QRgb*)(scanLine( yi ));
1768
                for(int xi=0; xi < dst.width(); ++xi )
1769
                {
1770
                        (*d) = (*s);
1771
                        s++;
1772
                        d++;
1773
                }
1774
        }
1775
        return;
1776
}
1777
 
17431 jghali 1778
void ScImage::scaleImageGeneric(int nwidth, int nheight)
1779
{
1780
        unsigned char* xelrow = 0;
1781
        unsigned char* tempxelrow = 0;
1782
        register unsigned char* xP;
1783
        register unsigned char* nxP;
1784
        int rows, cols, rowsread, newrows, newcols;
1785
        register int row, col, needtoreadrow;
1786
        const uchar maxval = 255;
1787
        double xscale, yscale;
1788
        long sxscale, syscale;
1789
        register long fracrowtofill, fracrowleft;
1790
        long* ps;
1791
        int rowswritten = 0;
1792
 
1793
        int depth = this->depth();
1794
        Format imgFormat = this->format();
1795
        bool execScaled = (depth == 1 || depth == 4 || depth == 16);
1796
        execScaled |= (imgFormat == QImage::Format_ARGB8565_Premultiplied);
1797
        execScaled |= (imgFormat == QImage::Format_RGB666);
1798
        execScaled |= (imgFormat == QImage::Format_ARGB6666_Premultiplied);
1799
        execScaled |= (imgFormat == QImage::Format_ARGB8555_Premultiplied);
1800
        if (execScaled)
1801
        {
1802
                QImage::operator=(QImage::scaled(nwidth, nheight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
1803
                return;
1804
        }
1805
 
1806
        QImage dst(nwidth, nheight, this->format());
1807
        int nChannels = this->depth() / 8;
1808
 
1809
        cols = width();
1810
        rows = height();
1811
        newcols = dst.width();
1812
        newrows = dst.height();
1813
        long SCALE;
1814
        long HALFSCALE;
1815
        if (cols > 4096)
1816
        {
1817
                SCALE = 4096;
1818
                HALFSCALE = 2048;
1819
        }
1820
        else
1821
        {
1822
                int fac = 4096;
1823
                while ((cols * fac) > 4096)
1824
                {
1825
                        fac /= 2;
1826
                }
1827
                SCALE = fac * cols;
1828
                HALFSCALE = fac * cols / 2;
1829
        }
1830
        xscale = (double) newcols / (double) cols;
1831
        yscale = (double) newrows / (double) rows;
1832
        sxscale = (long)(xscale * SCALE);
1833
        syscale = (long)(yscale * SCALE);
1834
        if ( newrows != rows )  /* shortcut Y scaling if possible */
1835
                tempxelrow = new unsigned char[cols * nChannels];
1836
        ps = new long[cols];
1837
 
1838
        for (int chIndex = 0; chIndex < nChannels; ++chIndex)
1839
        {
1840
                xelrow = 0;
1841
                rowsread = rowswritten = 0;
1842
                fracrowleft = syscale;
1843
                needtoreadrow = 1;
1844
                for (col = 0; col < cols; ++col)
1845
                        ps[col] = HALFSCALE;
1846
                fracrowtofill = SCALE;
1847
                for (row = 0; row < newrows; ++row)
1848
                {
1849
                        if (newrows == rows)
1850
                                tempxelrow = xelrow = scanLine(rowsread++);
1851
                        else
1852
                        {
1853
                                while (fracrowleft < fracrowtofill)
1854
                                {
1855
                                        if (needtoreadrow && rowsread < rows)
1856
                                                xelrow = scanLine(rowsread++);
1857
                                        for (col = 0, xP = xelrow + chIndex; col < cols; ++col, xP += nChannels)
1858
                                                ps[col] += fracrowleft * (*xP);
1859
                                        fracrowtofill -= fracrowleft;
1860
                                        fracrowleft = syscale;
1861
                                        needtoreadrow = 1;
1862
                                }
1863
                                if (needtoreadrow && rowsread < rows)
1864
                                {
1865
                                        xelrow = scanLine(rowsread++);
1866
                                        needtoreadrow = 0;
1867
                                }
1868
                                register long p = 0;
1869
                                xP  = xelrow + chIndex;
1870
                                nxP = tempxelrow + chIndex;
1871
                                for (col = 0; col < cols; ++col, xP += nChannels, nxP += nChannels)
1872
                                {
1873
                                        p = ps[col] + fracrowtofill * (*xP);
1874
                                        p /= SCALE;
1875
                                        if ( p > maxval ) p = maxval;
1876
                                        *nxP = (unsigned char) p;
1877
                                        ps[col] = HALFSCALE;
1878
                                }
1879
                                fracrowleft -= fracrowtofill;
1880
                                if ( fracrowleft == 0 )
1881
                                {
1882
                                        fracrowleft = syscale;
1883
                                        needtoreadrow = 1;
1884
                                }
1885
                                fracrowtofill = SCALE;
1886
                        }
1887
                        if (newcols == cols)
1888
                        {
1889
                                memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols * nChannels);
1890
                        }
1891
                        else
1892
                        {
1893
                                register long p;
1894
                                register long fraccoltofill, fraccolleft = 0;
1895
                                register int needcol;
1896
                                nxP = dst.scanLine(rowswritten++) + chIndex;
19190 jghali 1897
                                unsigned char *nxPEnd = nxP + newcols * nChannels;
17431 jghali 1898
                                fraccoltofill = SCALE;
1899
                                p = HALFSCALE;
1900
                                needcol = 0;
1901
                                for (col = 0, xP = tempxelrow + chIndex; col < cols; ++col, xP += nChannels)
1902
                                {
1903
                                        fraccolleft = sxscale;
1904
                                        while ( fraccolleft >= fraccoltofill )
1905
                                        {
1906
                                                if ( needcol )
1907
                                                {
1908
                                                        nxP += nChannels;
1909
                                                        p = HALFSCALE;
1910
                                                }
1911
                                                p += fraccoltofill * ( *xP );
1912
                                                p /= SCALE;
1913
                                                if ( p > maxval ) p = maxval;
1914
                                                *nxP = (unsigned char) p;
1915
                                                fraccolleft -= fraccoltofill;
1916
                                                fraccoltofill = SCALE;
1917
                                                needcol = 1;
1918
                                        }
1919
                                        if (fraccolleft > 0)
1920
                                        {
1921
                                                if (needcol)
1922
                                                {
1923
                                                        nxP += nChannels;
1924
                                                        p = HALFSCALE;
1925
                                                        needcol = 0;
1926
                                                }
1927
                                                p += fraccolleft * (*xP);
1928
                                                fraccoltofill -= fraccolleft;
1929
                                        }
1930
                                }
1931
                                if (fraccoltofill > 0)
1932
                                {
1933
                                        xP -= nChannels;
19190 jghali 1934
                                        p += fraccoltofill * (*xP);
17431 jghali 1935
                                }
19190 jghali 1936
                                if (nxP < nxPEnd)
17431 jghali 1937
                                {
1938
                                        p /= SCALE;
1939
                                        if ( p > maxval ) p = maxval;
1940
                                        *nxP = (unsigned char) p;
19190 jghali 1941
                                        while ((nxP += nChannels) != nxPEnd)
1942
                                                nxP[0] = nxP[-nChannels];
17431 jghali 1943
                                }
1944
                        }
1945
                }
1946
        }
1947
        if (newrows != rows && tempxelrow)// Robust, tempxelrow might be 0 1 day
1948
                delete [] tempxelrow;
1949
        if (ps)                         // Avoid purify complaint
1950
                delete [] ps;
1951
 
1952
        int scanWidth = dst.width() * nChannels;
1953
        QImage::operator=(QImage(nwidth, nheight, this->format()));
1954
        for( int yi=0; yi < dst.height(); ++yi )
1955
        {
1956
                uchar *s = (dst.scanLine( yi ));
1957
                uchar *d = (scanLine( yi ));
1958
                memcpy(d, s, scanWidth);
1959
        }
1960
        return;
1961
}
1962
 
12141 avox 1963
bool ScImage::getAlpha(QString fn, int page, QByteArray& alpha, bool PDF, bool pdf14, int gsRes, int scaleXSize, int scaleYSize)
2004 fschmid 1964
{
11389 jghali 1965
        bool gotAlpha = false;
14293 jghali 1966
        auto_ptr<ScImgDataLoader> pDataLoader;
2004 fschmid 1967
        imgInfo.valid = false;
1968
        imgInfo.clipPath = "";
1969
        imgInfo.PDSpathData.clear();
1970
        imgInfo.layerInfo.clear();
1971
        QFileInfo fi = QFileInfo(fn);
1972
        if (!fi.exists())
11389 jghali 1973
                return false;
1974
        alpha.resize(0);
10561 fschmid 1975
        QString ext = fi.suffix().toLower();
18717 fschmid 1976
        QString ext2 = getImageType(fn);
1977
        if (ext.isEmpty() || (ext2 != ext))
1978
                ext = ext2;
13990 fschmid 1979
        QList<QByteArray> fmtList = QImageReader::supportedImageFormats();
1980
        QStringList fmtImg;
1981
        for (int i = 0; i < fmtList.count(); i++)
1982
        {
1983
                fmtImg.append( QString(fmtList[i].toLower()) );
1984
        }
10136 cbradney 1985
        if (extensionIndicatesJPEG(ext))
11389 jghali 1986
                return true;
10136 cbradney 1987
        if (extensionIndicatesPDF(ext))
12141 avox 1988
        {
14293 jghali 1989
                pDataLoader.reset( new ScImgDataLoader_PDF() );
12141 avox 1990
        }
10136 cbradney 1991
        else if (extensionIndicatesEPSorPS(ext))
12141 avox 1992
        {
14293 jghali 1993
                pDataLoader.reset( new ScImgDataLoader_PS() );
12141 avox 1994
        }
10136 cbradney 1995
        else if (extensionIndicatesTIFF(ext))
6873 fschmid 1996
        {
14293 jghali 1997
                pDataLoader.reset( new ScImgDataLoader_TIFF() );
1998
                if      (pDataLoader.get())
6873 fschmid 1999
                        pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
2000
        }
10136 cbradney 2001
        else if (extensionIndicatesPSD(ext))
6873 fschmid 2002
        {
14293 jghali 2003
                pDataLoader.reset( new ScImgDataLoader_PSD() );
2004
                if      (pDataLoader.get())
6873 fschmid 2005
                        pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
2006
        }
18958 fschmid 2007
        else if (ext == "ora")
2008
        {
2009
                pDataLoader.reset( new ScImgDataLoader_ORA() );
2010
                if      (pDataLoader.get())
2011
                        pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
2012
        }
13932 fschmid 2013
        else if (ext == "pat")
14293 jghali 2014
                pDataLoader.reset( new ScImgDataLoader_GIMP() );
15796 fschmid 2015
        else if (ext == "pgf")
2016
                pDataLoader.reset( new ScImgDataLoader_PGF() );
14036 fschmid 2017
        else if ((ext == "pct") || (ext == "pic") || (ext == "pict"))
14293 jghali 2018
                pDataLoader.reset( new ScImgDataLoader_PICT() );
14087 fschmid 2019
        else if (ext == "wpg")
14293 jghali 2020
                pDataLoader.reset( new ScImgDataLoader_WPG() );
2021
#ifdef GMAGICK_FOUND
2022
#warning "Compiling with GraphicsMagick support!"
13990 fschmid 2023
        else if (fmtImg.contains(ext))
14293 jghali 2024
                pDataLoader.reset( new ScImgDataLoader_QT() );
5937 jghali 2025
        else
14294 jghali 2026
                pDataLoader .reset( new ScImgDataLoader_GMagick() );
14293 jghali 2027
#else
2028
        else
2029
                pDataLoader.reset( new ScImgDataLoader_QT() );
2030
#endif
2031
 
2032
        if (pDataLoader.get())
2995 fschmid 2033
        {
11468 fschmid 2034
                bool hasAlpha    = false;
12141 avox 2035
                bool alphaLoaded = pDataLoader->preloadAlphaChannel(fn, page, gsRes, hasAlpha);
11468 fschmid 2036
                if (!alphaLoaded || !hasAlpha)
2037
                        return alphaLoaded;
6835 fschmid 2038
                QImage rImage;
13957 herm 2039
                if (pDataLoader->useRawImage() || extensionIndicatesPSD(ext) || extensionIndicatesTIFF(ext))
6835 fschmid 2040
                {
8444 fschmid 2041
                        if (pDataLoader->imageInfoRecord().valid)
2042
                        {
11331 jghali 2043
                                if ((pDataLoader->r_image.channels() == 5) || (pDataLoader->imageInfoRecord().colorspace == ColorSpaceCMYK))
8444 fschmid 2044
                                        rImage = pDataLoader->r_image.convertToQImage(true);
2045
                                else
2046
                                        rImage = pDataLoader->r_image.convertToQImage(false);
2047
                        }
6835 fschmid 2048
                }
2049
                else
2050
                        rImage = pDataLoader->image();
5937 jghali 2051
                if (rImage.isNull())
11389 jghali 2052
                        return false;
11612 jghali 2053
                if ((scaleXSize != 0) && (scaleYSize != 0) && (scaleXSize != rImage.width() || scaleYSize != rImage.height()))
10561 fschmid 2054
                        rImage = rImage.scaled(scaleXSize, scaleYSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
11389 jghali 2055
                int i = 0, w2;
5937 jghali 2056
                unsigned char u;
2057
                int hm = rImage.height();
2058
                int wm = rImage.width();
11389 jghali 2059
                QRgb r, *s;
5937 jghali 2060
                if (pdf14)
2995 fschmid 2061
                {
11389 jghali 2062
                        alpha.resize(hm * wm);
2063
                        if (alpha.size() > 0) // 
2995 fschmid 2064
                        {
11389 jghali 2065
                                for( int yi=0; yi < hm; ++yi )
2995 fschmid 2066
                                {
11389 jghali 2067
                                        s = (QRgb*)(rImage.scanLine( yi ));
2068
                                        for( int xi=0; xi < wm; ++xi )
2069
                                        {
2070
                                                r = *s++;
2071
                                                u = qAlpha(r);
2072
                                                alpha[i++] = u;
2073
                                        }
2995 fschmid 2074
                                }
11389 jghali 2075
                                gotAlpha = true;
2995 fschmid 2076
                        }
2077
                }
5937 jghali 2078
                else
2004 fschmid 2079
                {
11389 jghali 2080
                        uchar * s;
5937 jghali 2081
                        QImage iMask = rImage.createAlphaMask();
11309 fschmid 2082
                        iMask = iMask.convertToFormat(QImage::Format_Mono);
5937 jghali 2083
                        hm = iMask.height();
2084
                        wm = iMask.width();
2085
                        w2 = wm / 8;
2086
                        if ((wm % 8) != 0)
2087
                                w2++;
11389 jghali 2088
                        alpha.resize(hm * w2);
2089
                        if (alpha.size() > 0)
2004 fschmid 2090
                        {
11389 jghali 2091
                                for( int yi=0; yi < hm; ++yi )
2004 fschmid 2092
                                {
11389 jghali 2093
                                        s = iMask.scanLine( yi );
2094
                                        for( int xi=0; xi < w2; ++xi )
2095
                                        {
2096
                                                u = *(s+xi);
2097
                                                if(PDF) u = ~u;
2098
                                                alpha[i++] = u;
2099
                                        }
2004 fschmid 2100
                                }
11389 jghali 2101
                                gotAlpha = true;
2004 fschmid 2102
                        }
2103
                }
2104
        }
11389 jghali 2105
        return gotAlpha;
2004 fschmid 2106
}
2107
 
12141 avox 2108
void ScImage::getEmbeddedProfile(const QString & fn, QByteArray *profile, int *components, int page)
5234 fschmid 2109
{
2110
        Q_ASSERT(profile);
2111
        Q_ASSERT(components);
14179 jghali 2112
        ScColorProfile prof;
5937 jghali 2113
        ScImgDataLoader* pDataLoader = NULL;
2114
 
2115
        profile->resize(0);
2116
        *components = 0;
5234 fschmid 2117
        QFileInfo fi = QFileInfo(fn);
2118
        if (!fi.exists())
2119
                return;
10561 fschmid 2120
        QString ext = fi.suffix().toLower();
18717 fschmid 2121
        QString ext2 = getImageType(fn);
2122
        if (ext.isEmpty() || (ext2 != ext))
2123
                ext = ext2;
5937 jghali 2124
 
10136 cbradney 2125
        if (extensionIndicatesPSD(ext))
5937 jghali 2126
                pDataLoader = new ScImgDataLoader_PSD();
10136 cbradney 2127
        else if (extensionIndicatesEPSorPS(ext))
6744 fschmid 2128
                pDataLoader = new ScImgDataLoader_PS();
10136 cbradney 2129
        else if (extensionIndicatesTIFF(ext))
5937 jghali 2130
                pDataLoader = new ScImgDataLoader_TIFF();
10136 cbradney 2131
        else if (extensionIndicatesJPEG(ext))