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)) |