Rev 22724 | Rev 23235 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5977 | jghali | 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 | */ |
||
10223 | cbradney | 7 | #include <QFile> |
8 | #include <QFileInfo> |
||
9 | #include <QObject> |
||
9803 | fschmid | 10 | #include <QList> |
14170 | jghali | 11 | |
5937 | jghali | 12 | #include "scconfig.h" |
14491 | jghali | 13 | #include "colormgmt/sccolormgmtengine.h" |
5937 | jghali | 14 | #include "scimgdataloader_tiff.h" |
14170 | jghali | 15 | #include "scribuscore.h" |
10203 | cbradney | 16 | #include "util_color.h" |
5937 | jghali | 17 | |
6766 | fschmid | 18 | static void TagExtender(TIFF *tiff) |
19 | { |
||
20 | static const TIFFFieldInfo xtiffFieldInfo[] = |
||
21 | { |
||
18194 | fschmid | 22 | { 37724, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM, true, true, const_cast<char*>("PhotoshopLayerData") } |
6766 | fschmid | 23 | }; |
24 | TIFFMergeFieldInfo(tiff, xtiffFieldInfo, sizeof (xtiffFieldInfo) / sizeof (xtiffFieldInfo[0])); |
||
25 | } |
||
26 | |||
22639 | craig | 27 | ScImgDataLoader_TIFF::ScImgDataLoader_TIFF() |
5937 | jghali | 28 | { |
20837 | jghali | 29 | m_photometric = PHOTOMETRIC_MINISBLACK; |
30 | m_samplesperpixel = 72; |
||
31 | |||
5937 | jghali | 32 | initSupportedFormatList(); |
33 | } |
||
34 | |||
22635 | craig | 35 | void ScImgDataLoader_TIFF::initSupportedFormatList() |
5937 | jghali | 36 | { |
37 | m_supportedFormats.clear(); |
||
38 | m_supportedFormats.append( "tif" ); |
||
39 | m_supportedFormats.append( "tiff" ); |
||
40 | } |
||
41 | |||
12141 | avox | 42 | void ScImgDataLoader_TIFF::loadEmbeddedProfile(const QString& fn, int /*page*/) |
5937 | jghali | 43 | { |
14491 | jghali | 44 | ScColorMgmtEngine engine(ScCore->defaultEngine); |
5937 | jghali | 45 | m_embeddedProfile.resize(0); |
46 | m_profileComponents = 0; |
||
22536 | jghali | 47 | if (!QFile::exists(fn)) |
5937 | jghali | 48 | return; |
6766 | fschmid | 49 | TIFFSetTagExtender(TagExtender); |
10493 | fschmid | 50 | TIFF* tif = TIFFOpen(fn.toLocal8Bit(), "r"); |
22536 | jghali | 51 | if (!tif) |
52 | return; |
||
53 | |||
54 | uint32 EmbedLen = 0; |
||
55 | void* EmbedBuffer; |
||
56 | if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) |
||
5937 | jghali | 57 | { |
22536 | jghali | 58 | QByteArray profArray((const char*) EmbedBuffer, EmbedLen); |
59 | ScColorProfile tiffProf = engine.openProfileFromMem(profArray); |
||
60 | if (tiffProf) |
||
5937 | jghali | 61 | { |
22536 | jghali | 62 | if (tiffProf.colorSpace() == ColorSpace_Rgb) |
63 | m_profileComponents = 3; |
||
64 | if (tiffProf.colorSpace() == ColorSpace_Cmyk) |
||
65 | m_profileComponents = 4; |
||
66 | if (tiffProf.colorSpace() == ColorSpace_Gray) |
||
67 | m_profileComponents = 1; |
||
68 | m_embeddedProfile = profArray; |
||
5937 | jghali | 69 | } |
70 | } |
||
22536 | jghali | 71 | TIFFClose(tif); |
5937 | jghali | 72 | } |
73 | |||
12141 | avox | 74 | bool ScImgDataLoader_TIFF::preloadAlphaChannel(const QString& fn, int page, int res, bool& hasAlpha) |
5937 | jghali | 75 | { |
11620 | jghali | 76 | bool success = true; |
77 | bool valid = m_imageInfoRecord.isRequest; |
||
6873 | fschmid | 78 | QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps; |
5937 | jghali | 79 | initialize(); |
6873 | fschmid | 80 | m_imageInfoRecord.RequestProps = req; |
81 | m_imageInfoRecord.isRequest = valid; |
||
11620 | jghali | 82 | if (!QFile::exists(fn)) |
11468 | fschmid | 83 | return false; |
11620 | jghali | 84 | hasAlpha = false; |
12141 | avox | 85 | if (testAlphaChannelAvailability(fn, page, hasAlpha)) |
8444 | fschmid | 86 | { |
22605 | craig | 87 | if (!hasAlpha) |
11620 | jghali | 88 | success = true; |
22536 | jghali | 89 | else if (loadPicture(fn, page, res, false)) |
8444 | fschmid | 90 | { |
11620 | jghali | 91 | m_imageInfoRecord.valid = true; |
92 | hasAlpha = success = true; |
||
93 | /*if (photometric == PHOTOMETRIC_SEPARATED) |
||
94 | { |
||
95 | if (samplesperpixel == 4) |
||
96 | m_imageInfoRecord.valid = hasAlpha = false; |
||
97 | } |
||
98 | else |
||
99 | { |
||
100 | if (samplesperpixel == 3) |
||
101 | m_imageInfoRecord.valid = hasAlpha = false; |
||
102 | } |
||
103 | if (!hasAlpha) r_image.resize(0);*/ |
||
8444 | fschmid | 104 | } |
105 | } |
||
11620 | jghali | 106 | return success; |
5937 | jghali | 107 | } |
108 | |||
12141 | avox | 109 | int ScImgDataLoader_TIFF::getLayers(const QString& fn, int /*page*/) |
6589 | fschmid | 110 | { |
111 | int layerNum = 1; |
||
112 | int test; |
||
113 | struct PSDLayer lay; |
||
6766 | fschmid | 114 | TIFFSetTagExtender(TagExtender); |
10493 | fschmid | 115 | TIFF* tif = TIFFOpen(fn.toLocal8Bit(), "r"); |
22536 | jghali | 116 | if (!tif) |
117 | return layerNum; |
||
118 | |||
119 | do |
||
6589 | fschmid | 120 | { |
23202 | jghali | 121 | char *layerName = nullptr; |
22536 | jghali | 122 | TIFFGetField(tif, TIFFTAG_PAGENAME, &layerName); |
123 | QString name = QString(layerName); |
||
124 | if (name.isEmpty()) |
||
125 | lay.layerName = QString("Layer #%1").arg(layerNum); |
||
126 | else |
||
127 | lay.layerName = name; |
||
128 | lay.blend = "norm"; |
||
129 | lay.opacity = 255; |
||
130 | lay.flags = 0; |
||
131 | m_imageInfoRecord.layerInfo.append(lay); |
||
132 | m_imageInfoRecord.valid = true; |
||
133 | layerNum++; |
||
134 | test = TIFFReadDirectory(tif); |
||
6589 | fschmid | 135 | } |
22536 | jghali | 136 | while (test == 1); |
137 | TIFFClose(tif); |
||
138 | |||
6589 | fschmid | 139 | return layerNum; |
140 | } |
||
141 | |||
12141 | avox | 142 | bool ScImgDataLoader_TIFF::testAlphaChannelAvailability(const QString& fn, int /*page*/, bool& hasAlpha) |
11620 | jghali | 143 | { |
144 | int test; |
||
18925 | jghali | 145 | |
146 | QByteArray byteOrder(2, ' '); |
||
147 | QFile fo(fn); |
||
148 | if (fo.open(QIODevice::ReadOnly)) |
||
149 | { |
||
150 | fo.read(byteOrder.data(), 1); |
||
151 | fo.close(); |
||
152 | } |
||
153 | |||
11620 | jghali | 154 | TIFFSetTagExtender(TagExtender); |
155 | TIFF* tif = TIFFOpen(fn.toLocal8Bit(), "r"); |
||
18925 | jghali | 156 | if (!tif) |
157 | return false; |
||
158 | |||
159 | uint16 extrasamples, *extratypes; |
||
160 | hasAlpha = false; |
||
161 | do |
||
11620 | jghali | 162 | { |
18925 | jghali | 163 | if (TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &extratypes) == 1) |
11620 | jghali | 164 | { |
18925 | jghali | 165 | for (int i = 0; i < extrasamples; ++i) |
11620 | jghali | 166 | { |
18925 | jghali | 167 | if (extratypes[i] != EXTRASAMPLE_UNSPECIFIED) |
11620 | jghali | 168 | { |
18925 | jghali | 169 | hasAlpha = true; |
170 | break; |
||
171 | } |
||
172 | } |
||
173 | } |
||
174 | test = TIFFReadDirectory(tif); |
||
175 | } |
||
176 | while (test == 1); |
||
177 | |||
178 | if (hasAlpha) |
||
179 | { |
||
180 | TIFFClose(tif); |
||
181 | return true; |
||
182 | } |
||
183 | |||
184 | unsigned int PhotoshopLen2 = 0; |
||
185 | unsigned char* PhotoshopBuffer2; |
||
186 | int gotField = TIFFGetField(tif, 37724, &PhotoshopLen2, &PhotoshopBuffer2); |
||
187 | if (gotField && (PhotoshopLen2 > 40)) |
||
188 | { |
||
189 | m_imageInfoRecord.layerInfo.clear(); |
||
190 | QByteArray arrayPhot = QByteArray::fromRawData((const char*)PhotoshopBuffer2, PhotoshopLen2); |
||
191 | QDataStream s(&arrayPhot, QIODevice::ReadOnly); |
||
192 | if (byteOrder[0] == 'M') |
||
193 | s.setByteOrder(QDataStream::BigEndian); |
||
194 | else |
||
195 | s.setByteOrder(QDataStream::LittleEndian); |
||
196 | |||
197 | QList<PSDLayer> layerInfo; |
||
198 | if (loadLayerInfo(s, layerInfo)) |
||
199 | { |
||
200 | for (int layer = 0; layer < layerInfo.count(); ++layer) |
||
201 | { |
||
202 | const PSDLayer& psdLayer = layerInfo.at(layer); |
||
203 | uint channel_num = psdLayer.channelLen.count(); |
||
204 | for (uint channel = 0; channel < channel_num; ++channel) |
||
205 | { |
||
206 | if (psdLayer.channelType[channel] == -1) |
||
11620 | jghali | 207 | { |
208 | hasAlpha = true; |
||
209 | break; |
||
210 | } |
||
211 | } |
||
18925 | jghali | 212 | if (hasAlpha) break; |
11620 | jghali | 213 | } |
214 | } |
||
215 | } |
||
18925 | jghali | 216 | |
217 | TIFFClose(tif); |
||
218 | return true; |
||
11620 | jghali | 219 | } |
220 | |||
11540 | fschmid | 221 | void ScImgDataLoader_TIFF::unmultiplyRGBA(RawImage *image) |
6589 | fschmid | 222 | { |
11540 | fschmid | 223 | double r1, g1, b1, coeff; |
224 | unsigned char r, g, b, a; |
||
225 | for (int i = 0; i < image->height(); ++i) |
||
226 | { |
||
227 | unsigned int *ptr = (QRgb *) image->scanLine(i); |
||
228 | for (int j = 0; j < image->width(); ++j) |
||
229 | { |
||
230 | r = qRed(*ptr); |
||
231 | g = qGreen(*ptr); |
||
232 | b = qBlue(*ptr); |
||
233 | a = qAlpha(*ptr); |
||
234 | if (a > 0 && a < 255) |
||
235 | { |
||
236 | coeff = 255.0 / a; |
||
237 | r1 = coeff * r; |
||
238 | g1 = coeff * g; |
||
239 | b1 = coeff * b; |
||
240 | r = (r1 <= 255.0) ? (unsigned char) r1 : 255; |
||
241 | g = (g1 <= 255.0) ? (unsigned char) g1 : 255; |
||
242 | b = (b1 <= 255.0) ? (unsigned char) b1 : 255; |
||
243 | *ptr++ = qRgba(r,g,b,a); |
||
244 | } |
||
245 | else |
||
246 | ++ptr; |
||
247 | } |
||
248 | } |
||
249 | } |
||
250 | |||
11543 | jghali | 251 | bool ScImgDataLoader_TIFF::getImageData(TIFF* tif, RawImage *image, uint widtht, uint heightt, uint size, uint16 photometric, uint16 bitspersample, uint16 samplesperpixel, bool &bilevel, bool &isCMYK) |
11540 | fschmid | 252 | { |
22605 | craig | 253 | uint32 *bits = nullptr; |
6589 | fschmid | 254 | if (photometric == PHOTOMETRIC_SEPARATED) |
255 | { |
||
6867 | fschmid | 256 | if (samplesperpixel > 5) |
6589 | fschmid | 257 | { |
11537 | jghali | 258 | if (!getImageData_RGBA(tif, image, widtht, heightt, size, bitspersample, samplesperpixel)) |
259 | return false; |
||
260 | if (bitspersample == 1) |
||
261 | bilevel = true; |
||
262 | isCMYK = false; |
||
15128 | jghali | 263 | m_pixelFormat = Format_RGBA_8; |
6589 | fschmid | 264 | } |
265 | else |
||
266 | { |
||
267 | if (TIFFIsTiled(tif)) |
||
268 | { |
||
269 | uint32 columns, rows; |
||
270 | uint32 *tile_buf; |
||
271 | uint32 xt, yt; |
||
272 | TIFFGetField(tif, TIFFTAG_TILEWIDTH, &columns); |
||
273 | TIFFGetField(tif, TIFFTAG_TILELENGTH, &rows); |
||
274 | tile_buf = (uint32*) _TIFFmalloc(columns*rows*sizeof(uint32)); |
||
22518 | craig | 275 | if (tile_buf == nullptr) |
6589 | fschmid | 276 | { |
277 | TIFFClose(tif); |
||
278 | return false; |
||
279 | } |
||
280 | uint32 tileW = columns, tileH = rows; |
||
281 | for (yt = 0; yt < (uint32) image->height(); yt += rows) |
||
282 | { |
||
283 | if (yt > (uint) image->height()) |
||
284 | break; |
||
285 | if (image->height()-yt < rows) |
||
286 | tileH = image->height()-yt; |
||
287 | tileW = columns; |
||
21933 | craig | 288 | uint32 yi; |
6854 | fschmid | 289 | int chans = image->channels(); |
6589 | fschmid | 290 | for (xt = 0; xt < (uint) image->width(); xt += columns) |
291 | { |
||
292 | TIFFReadTile(tif, tile_buf, xt, yt, 0, 0); |
||
293 | for (yi = 0; yi < tileH; yi++) |
||
6854 | fschmid | 294 | { |
295 | _TIFFmemcpy(image->scanLine(yt+(tileH-1-yi))+xt, tile_buf+tileW*yi, tileW*chans); |
||
296 | } |
||
6589 | fschmid | 297 | } |
298 | } |
||
299 | _TIFFfree(tile_buf); |
||
300 | } |
||
301 | else |
||
302 | { |
||
303 | tsize_t bytesperrow = TIFFScanlineSize(tif); |
||
304 | bits = (uint32 *) _TIFFmalloc(bytesperrow); |
||
6854 | fschmid | 305 | int chans = image->channels(); |
6589 | fschmid | 306 | if (bits) |
307 | { |
||
308 | for (unsigned int y = 0; y < heightt; y++) |
||
309 | { |
||
310 | if (TIFFReadScanline(tif, bits, y, 0)) |
||
311 | { |
||
12244 | fschmid | 312 | /* The code below allows loading of CMYK TIFFs generated by ImageMagick, |
313 | currently commented out because its an ugly hack atm |
||
314 | When converting 8-bit PNGs with an alpha channel to CMYK Tiff, ImageMagick |
||
315 | creates a 16-bit CMYK Tiff !?!?? |
||
316 | if (bitspersample > 8) |
||
317 | { |
||
318 | uchar *ptrT = image->scanLine(y); |
||
319 | uchar *ptrS = (uchar*)bits; |
||
320 | for (unsigned int x = 0; x < widtht; x++) |
||
321 | { |
||
322 | ptrT[0] = ptrS[1]; |
||
323 | ptrT[1] = ptrS[3]; |
||
324 | ptrT[2] = ptrS[5]; |
||
325 | ptrT[3] = ptrS[7]; |
||
326 | if (samplesperpixel > 4) |
||
327 | ptrT[4] = ptrS[9]; |
||
328 | ptrT += chans; |
||
329 | ptrS += chans * 2; |
||
330 | } |
||
331 | } |
||
332 | else */ |
||
333 | memcpy(image->scanLine(y), bits, chans * widtht); |
||
6589 | fschmid | 334 | } |
335 | } |
||
336 | _TIFFfree(bits); |
||
337 | } |
||
338 | } |
||
339 | isCMYK = true; |
||
15182 | jghali | 340 | m_pixelFormat = (image->channels() == 5) ? Format_CMYKA_8 : Format_CMYK_8; |
6589 | fschmid | 341 | } |
342 | } |
||
343 | else |
||
344 | { |
||
11537 | jghali | 345 | if (!getImageData_RGBA(tif, image, widtht, heightt, size, bitspersample, samplesperpixel)) |
346 | return false; |
||
347 | if (bitspersample == 1) |
||
348 | bilevel = true; |
||
15128 | jghali | 349 | m_pixelFormat = Format_RGBA_8; |
11537 | jghali | 350 | } |
351 | return true; |
||
352 | } |
||
353 | |||
354 | bool ScImgDataLoader_TIFF::getImageData_RGBA(TIFF* tif, RawImage *image, uint widtht, uint heightt, uint size, uint16 bitspersample, uint16 samplesperpixel) |
||
355 | { |
||
356 | uint32* bits = (uint32 *) _TIFFmalloc(size * sizeof(uint32)); |
||
23202 | jghali | 357 | if (!bits) |
358 | return false; |
||
359 | |||
22605 | craig | 360 | uint16 extrasamples(0), *extratypes(nullptr); |
11543 | jghali | 361 | if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &extratypes)) |
362 | extrasamples = 0; |
||
23202 | jghali | 363 | |
364 | bool gotData = false; |
||
365 | if (TIFFReadRGBAImage(tif, widtht, heightt, bits, 0)) |
||
11537 | jghali | 366 | { |
23202 | jghali | 367 | for (unsigned int y = 0; y < heightt; y++) |
6589 | fschmid | 368 | { |
23202 | jghali | 369 | memcpy(image->scanLine(heightt - 1 - y), bits + y * widtht, widtht * image->channels()); |
370 | if (QSysInfo::ByteOrder == QSysInfo::BigEndian) |
||
6589 | fschmid | 371 | { |
23202 | jghali | 372 | unsigned char *s = image->scanLine( heightt - 1 - y ); |
373 | unsigned char r, g, b, a; |
||
374 | for (uint xi=0; xi < widtht; ++xi) |
||
7115 | fschmid | 375 | { |
23202 | jghali | 376 | r = s[0]; |
377 | g = s[1]; |
||
378 | b = s[2]; |
||
379 | a = s[3]; |
||
380 | s[0] = a; |
||
381 | s[1] = b; |
||
382 | s[2] = g; |
||
383 | s[3] = r; |
||
384 | s += image->channels(); |
||
7115 | fschmid | 385 | } |
6589 | fschmid | 386 | } |
387 | } |
||
23202 | jghali | 388 | if (extrasamples > 0 && extratypes[0] == EXTRASAMPLE_ASSOCALPHA) |
389 | unmultiplyRGBA(image); |
||
390 | gotData = true; |
||
6589 | fschmid | 391 | } |
23202 | jghali | 392 | _TIFFfree(bits); |
393 | |||
11537 | jghali | 394 | return gotData; |
6589 | fschmid | 395 | } |
396 | |||
22635 | craig | 397 | void ScImgDataLoader_TIFF::blendOntoTarget(RawImage *tmp, int layOpa, const QString& layBlend, bool cmyk, bool useMask) |
6589 | fschmid | 398 | { |
6850 | fschmid | 399 | if (layBlend == "diss") |
6589 | fschmid | 400 | { |
401 | for (int l = 0; l < tmp->height(); l++) |
||
402 | { |
||
20691 | craig | 403 | srand(m_random_table[ l % 4096]); |
6589 | fschmid | 404 | for (int k = 0; k < tmp->width(); k++) |
405 | { |
||
406 | int rand_val = rand() & 0xff; |
||
407 | if (rand_val > layOpa) |
||
6850 | fschmid | 408 | tmp->setAlpha(k, l, 0); |
6589 | fschmid | 409 | } |
410 | } |
||
411 | } |
||
6850 | fschmid | 412 | int w = r_image.width(); |
413 | int h = r_image.height(); |
||
22536 | jghali | 414 | for (int yi=0; yi < h; ++yi) |
6589 | fschmid | 415 | { |
6850 | fschmid | 416 | unsigned char *s = tmp->scanLine( yi ); |
417 | unsigned char *d = r_image.scanLine( yi ); |
||
7980 | fschmid | 418 | unsigned char r, g, b, src_r, src_g, src_b, src_a, src_alpha, dst_alpha; |
419 | unsigned char a = 0; |
||
22536 | jghali | 420 | for (int xi=0; xi < w; ++xi) |
6589 | fschmid | 421 | { |
422 | src_r = s[0]; |
||
423 | src_g = s[1]; |
||
424 | src_b = s[2]; |
||
425 | src_a = s[3]; |
||
6850 | fschmid | 426 | if (r_image.channels() == 5) |
6589 | fschmid | 427 | { |
6850 | fschmid | 428 | dst_alpha = d[4]; |
6873 | fschmid | 429 | if (useMask) |
430 | src_alpha = s[4]; |
||
431 | else |
||
432 | src_alpha = 255; |
||
6850 | fschmid | 433 | } |
434 | else |
||
435 | { |
||
6854 | fschmid | 436 | if (cmyk) |
437 | { |
||
438 | dst_alpha = 255; |
||
439 | src_alpha = 255; |
||
440 | } |
||
441 | else |
||
442 | { |
||
443 | dst_alpha = d[3]; |
||
444 | src_alpha = s[3]; |
||
445 | } |
||
6850 | fschmid | 446 | } |
6873 | fschmid | 447 | if (layBlend != "diss") |
448 | src_alpha = INT_MULT(src_alpha, layOpa); |
||
6850 | fschmid | 449 | if ((dst_alpha > 0) && (src_alpha > 0)) |
450 | { |
||
451 | if (layBlend == "mul ") |
||
6589 | fschmid | 452 | { |
453 | src_r = INT_MULT(src_r, d[0]); |
||
454 | src_g = INT_MULT(src_g, d[1]); |
||
455 | src_b = INT_MULT(src_b, d[2]); |
||
6850 | fschmid | 456 | if (cmyk) |
457 | src_a = INT_MULT(src_a, d[3]); |
||
6589 | fschmid | 458 | } |
6850 | fschmid | 459 | else if (layBlend == "scrn") |
6589 | fschmid | 460 | { |
461 | src_r = 255 - ((255-src_r) * (255-d[0]) / 128); |
||
462 | src_g = 255 - ((255-src_g) * (255-d[1]) / 128); |
||
463 | src_b = 255 - ((255-src_b) * (255-d[2]) / 128); |
||
6850 | fschmid | 464 | if (cmyk) |
465 | src_a = 255 - ((255-src_a) * (255-d[3]) / 128); |
||
6589 | fschmid | 466 | } |
6850 | fschmid | 467 | else if (layBlend == "over") |
6589 | fschmid | 468 | { |
469 | src_r = d[0] < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128); |
||
470 | src_g = d[1] < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128); |
||
471 | src_b = d[2] < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128); |
||
6850 | fschmid | 472 | if (cmyk) |
473 | src_a = d[3] < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128); |
||
6589 | fschmid | 474 | } |
6850 | fschmid | 475 | else if (layBlend == "diff") |
6589 | fschmid | 476 | { |
477 | src_r = d[0] > src_r ? d[0] - src_r : src_r - d[0]; |
||
478 | src_g = d[1] > src_g ? d[1] - src_g : src_g - d[1]; |
||
479 | src_b = d[2] > src_b ? d[2] - src_b : src_b - d[2]; |
||
6850 | fschmid | 480 | if (cmyk) |
481 | src_a = d[3] > src_a ? d[3] - src_a : src_a - d[3]; |
||
6589 | fschmid | 482 | } |
6850 | fschmid | 483 | else if (layBlend == "dark") |
6589 | fschmid | 484 | { |
485 | src_r = d[0] < src_r ? d[0] : src_r; |
||
486 | src_g = d[1] < src_g ? d[1] : src_g; |
||
487 | src_b = d[2] < src_b ? d[2] : src_b; |
||
6850 | fschmid | 488 | if (cmyk) |
489 | src_a = d[3] < src_a ? d[3] : src_a; |
||
6589 | fschmid | 490 | } |
6850 | fschmid | 491 | else if (layBlend == "hLit") |
6589 | fschmid | 492 | { |
493 | src_r = src_r < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128); |
||
494 | src_g = src_g < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128); |
||
495 | src_b = src_b < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128); |
||
6850 | fschmid | 496 | if (cmyk) |
497 | src_a = src_a < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128); |
||
6589 | fschmid | 498 | } |
6850 | fschmid | 499 | else if (layBlend == "sLit") |
6589 | fschmid | 500 | { |
501 | src_r = src_r * d[0] / 256 + src_r * (255 - ((255-src_r)*(255-d[0]) / 256) - src_r * d[0] / 256) / 256; |
||
502 | src_g = src_g * d[1] / 256 + src_g * (255 - ((255-src_g)*(255-d[1]) / 256) - src_g * d[1] / 256) / 256; |
||
503 | src_b = src_b * d[2] / 256 + src_b * (255 - ((255-src_b)*(255-d[2]) / 256) - src_b * d[2] / 256) / 256; |
||
6850 | fschmid | 504 | if (cmyk) |
505 | src_a = src_a * d[3] / 256 + src_a * (255 - ((255-src_a)*(255-d[3]) / 256) - src_a * d[3] / 256) / 256; |
||
6589 | fschmid | 506 | } |
6850 | fschmid | 507 | else if (layBlend == "lite") |
6589 | fschmid | 508 | { |
509 | src_r = d[0] < src_r ? src_r : d[0]; |
||
510 | src_g = d[1] < src_g ? src_g : d[1]; |
||
511 | src_b = d[2] < src_b ? src_b : d[2]; |
||
6850 | fschmid | 512 | if (cmyk) |
513 | src_a = d[3] < src_a ? src_a : d[3]; |
||
6589 | fschmid | 514 | } |
6850 | fschmid | 515 | else if (layBlend == "smud") |
6589 | fschmid | 516 | { |
517 | src_r = d[0] + src_r - src_r * d[0] / 128; |
||
518 | src_g = d[1] + src_g - src_g * d[1] / 128; |
||
519 | src_b = d[2] + src_b - src_b * d[2] / 128; |
||
6850 | fschmid | 520 | if (cmyk) |
521 | src_a = d[3] + src_a - src_a * d[3] / 128; |
||
6589 | fschmid | 522 | } |
6850 | fschmid | 523 | else if (layBlend == "div ") |
6589 | fschmid | 524 | { |
525 | src_r = src_r == 255 ? 255 : ((d[0] * 256) / (255-src_r)) > 255 ? 255 : (d[0] * 256) / (255-src_r); |
||
526 | src_g = src_g == 255 ? 255 : ((d[1] * 256) / (255-src_g)) > 255 ? 255 : (d[1] * 256) / (255-src_g); |
||
527 | src_b = src_b == 255 ? 255 : ((d[2] * 256) / (255-src_b)) > 255 ? 255 : (d[2] * 256) / (255-src_b); |
||
6850 | fschmid | 528 | if (cmyk) |
529 | src_a = src_a == 255 ? 255 : ((d[3] * 256) / (255-src_a)) > 255 ? 255 : (d[3] * 256) / (255-src_a); |
||
6589 | fschmid | 530 | } |
6850 | fschmid | 531 | else if (layBlend == "idiv") |
6589 | fschmid | 532 | { |
533 | src_r = src_r == 0 ? 0 : (255 - (((255-d[0]) * 256) / src_r)) < 0 ? 0 : 255 - (((255-d[0]) * 256) / src_r); |
||
534 | src_g = src_g == 0 ? 0 : (255 - (((255-d[1]) * 256) / src_g)) < 0 ? 0 : 255 - (((255-d[1]) * 256) / src_g); |
||
535 | src_b = src_b == 0 ? 0 : (255 - (((255-d[2]) * 256) / src_b)) < 0 ? 0 : 255 - (((255-d[2]) * 256) / src_b); |
||
6850 | fschmid | 536 | if (cmyk) |
537 | src_a = src_a == 0 ? 0 : (255 - (((255-d[3]) * 256) / src_a)) < 0 ? 0 : 255 - (((255-d[3]) * 256) / src_a); |
||
6589 | fschmid | 538 | } |
6850 | fschmid | 539 | else if (layBlend == "hue ") |
6589 | fschmid | 540 | { |
6850 | fschmid | 541 | if (!cmyk) |
6589 | fschmid | 542 | { |
543 | uchar new_r = d[0]; |
||
544 | uchar new_g = d[1]; |
||
545 | uchar new_b = d[2]; |
||
546 | RGBTOHSV(src_r, src_g, src_b); |
||
547 | RGBTOHSV(new_r, new_g, new_b); |
||
548 | new_r = src_r; |
||
549 | HSVTORGB(new_r, new_g, new_b); |
||
550 | src_r = new_r; |
||
551 | src_g = new_g; |
||
552 | src_b = new_b; |
||
553 | } |
||
554 | } |
||
6850 | fschmid | 555 | else if (layBlend == "sat ") |
6589 | fschmid | 556 | { |
6850 | fschmid | 557 | if (!cmyk) |
6589 | fschmid | 558 | { |
559 | uchar new_r = d[0]; |
||
560 | uchar new_g = d[1]; |
||
561 | uchar new_b = d[2]; |
||
562 | RGBTOHSV(src_r, src_g, src_b); |
||
563 | RGBTOHSV(new_r, new_g, new_b); |
||
564 | new_g = src_g; |
||
565 | HSVTORGB(new_r, new_g, new_b); |
||
566 | src_r = new_r; |
||
567 | src_g = new_g; |
||
568 | src_b = new_b; |
||
569 | } |
||
570 | } |
||
6850 | fschmid | 571 | else if (layBlend == "lum ") |
6589 | fschmid | 572 | { |
6850 | fschmid | 573 | if (!cmyk) |
6589 | fschmid | 574 | { |
575 | uchar new_r = d[0]; |
||
576 | uchar new_g = d[1]; |
||
577 | uchar new_b = d[2]; |
||
578 | RGBTOHSV(src_r, src_g, src_b); |
||
579 | RGBTOHSV(new_r, new_g, new_b); |
||
580 | new_b = src_b; |
||
581 | HSVTORGB(new_r, new_g, new_b); |
||
582 | src_r = new_r; |
||
583 | src_g = new_g; |
||
584 | src_b = new_b; |
||
585 | } |
||
586 | } |
||
6850 | fschmid | 587 | else if (layBlend == "colr") |
6589 | fschmid | 588 | { |
6850 | fschmid | 589 | if (!cmyk) |
6589 | fschmid | 590 | { |
591 | uchar new_r = d[0]; |
||
592 | uchar new_g = d[1]; |
||
593 | uchar new_b = d[2]; |
||
594 | RGBTOHLS(src_r, src_g, src_b); |
||
595 | RGBTOHLS(new_r, new_g, new_b); |
||
596 | new_r = src_r; |
||
597 | new_b = src_b; |
||
598 | HLSTORGB(new_r, new_g, new_b); |
||
599 | src_r = new_r; |
||
600 | src_g = new_g; |
||
601 | src_b = new_b; |
||
602 | } |
||
603 | } |
||
604 | } |
||
6850 | fschmid | 605 | if (dst_alpha == 0) |
6589 | fschmid | 606 | { |
6850 | fschmid | 607 | r = src_r; |
608 | g = src_g; |
||
609 | b = src_b; |
||
610 | a = src_a; |
||
6589 | fschmid | 611 | } |
612 | else |
||
613 | { |
||
6850 | fschmid | 614 | if (src_alpha > 0) |
6589 | fschmid | 615 | { |
6850 | fschmid | 616 | r = (d[0] * (255 - src_alpha) + src_r * src_alpha) / 255; |
617 | g = (d[1] * (255 - src_alpha) + src_g * src_alpha) / 255; |
||
618 | b = (d[2] * (255 - src_alpha) + src_b * src_alpha) / 255; |
||
619 | if (cmyk) |
||
620 | a = (d[3] * (255 - src_alpha) + src_a * src_alpha) / 255; |
||
621 | if (layBlend != "diss") |
||
622 | src_alpha = dst_alpha + INT_MULT(255 - dst_alpha, src_alpha); |
||
6589 | fschmid | 623 | } |
624 | } |
||
6850 | fschmid | 625 | if (src_alpha > 0) |
6589 | fschmid | 626 | { |
627 | d[0] = r; |
||
628 | d[1] = g; |
||
629 | d[2] = b; |
||
6854 | fschmid | 630 | if (r_image.channels() == 5) |
6589 | fschmid | 631 | { |
632 | d[3] = a; |
||
6850 | fschmid | 633 | d[4] = src_alpha; |
6589 | fschmid | 634 | } |
6850 | fschmid | 635 | else |
6854 | fschmid | 636 | { |
637 | if (cmyk) |
||
638 | d[3] = a; |
||
639 | else |
||
640 | d[3] = src_alpha; |
||
641 | } |
||
6589 | fschmid | 642 | } |
6850 | fschmid | 643 | d += r_image.channels(); |
644 | s += tmp->channels(); |
||
6589 | fschmid | 645 | } |
646 | } |
||
647 | } |
||
648 | |||
12141 | avox | 649 | bool ScImgDataLoader_TIFF::loadPicture(const QString& fn, int page, int res, bool thumbnail) |
5937 | jghali | 650 | { |
14491 | jghali | 651 | ScColorMgmtEngine engine(ScCore->defaultEngine); |
5937 | jghali | 652 | bool bilevel = false; |
6766 | fschmid | 653 | bool failedPS = false; |
654 | bool foundPS = false; |
||
5937 | jghali | 655 | short resolutionunit = 0; |
656 | float xres = 72.0, yres = 72.0; |
||
657 | if (!QFile::exists(fn)) |
||
658 | return false; |
||
10562 | fschmid | 659 | QByteArray byteOrder(2, ' '); |
6770 | fschmid | 660 | QFile fo(fn); |
8501 | cbradney | 661 | if (fo.open(QIODevice::ReadOnly)) |
6770 | fschmid | 662 | { |
10562 | fschmid | 663 | fo.read(byteOrder.data(), 1); |
6770 | fschmid | 664 | fo.close(); |
665 | } |
||
6589 | fschmid | 666 | srand(314159265); |
667 | for (int i = 0; i < 4096; i++) |
||
20691 | craig | 668 | m_random_table[i] = rand(); |
6589 | fschmid | 669 | for (int i = 0; i < 4096; i++) |
670 | { |
||
671 | int tmp; |
||
672 | int swap = i + rand() % (4096 - i); |
||
20691 | craig | 673 | tmp = m_random_table[i]; |
674 | m_random_table[i] = m_random_table[swap]; |
||
675 | m_random_table[swap] = tmp; |
||
6589 | fschmid | 676 | } |
22536 | jghali | 677 | |
678 | initialize(); |
||
679 | |||
6589 | fschmid | 680 | int test; |
681 | bool valid = m_imageInfoRecord.isRequest; |
||
682 | QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps; |
||
683 | m_imageInfoRecord.RequestProps = req; |
||
684 | m_imageInfoRecord.isRequest = valid; |
||
11331 | jghali | 685 | m_imageInfoRecord.type = ImageTypeTIF; |
12141 | avox | 686 | getLayers(fn, page); |
22536 | jghali | 687 | |
6766 | fschmid | 688 | TIFFSetTagExtender(TagExtender); |
10493 | fschmid | 689 | TIFF* tif = TIFFOpen(fn.toLocal8Bit(), "r"); |
22536 | jghali | 690 | if (!tif) |
691 | return false; |
||
5937 | jghali | 692 | |
22536 | jghali | 693 | bool isCMYK = false; |
694 | unsigned int widtht, heightt, size; |
||
22605 | craig | 695 | char *description=nullptr, *copyright=nullptr, *datetime=nullptr, *artist=nullptr, *scannerMake=nullptr, *scannerModel=nullptr; |
22536 | jghali | 696 | uint16 bitspersample, fillorder, planar; |
5937 | jghali | 697 | |
22536 | jghali | 698 | TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &widtht); |
699 | TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &heightt); |
||
700 | TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres); |
||
701 | TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres); |
||
702 | TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT , &resolutionunit); |
||
703 | size = widtht * heightt; |
||
704 | TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &m_photometric); |
||
705 | TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar); |
||
706 | TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); |
||
707 | TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &m_samplesperpixel); |
||
708 | TIFFGetField(tif, TIFFTAG_FILLORDER, &fillorder); |
||
709 | |||
710 | TIFFGetField(tif, TIFFTAG_MAKE, &scannerMake); |
||
711 | TIFFGetField(tif, TIFFTAG_MODEL, &scannerModel); |
||
712 | TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &description); |
||
713 | TIFFGetField(tif, TIFFTAG_COPYRIGHT, ©right); |
||
714 | TIFFGetField(tif, TIFFTAG_DATETIME, &datetime); |
||
715 | TIFFGetField(tif, TIFFTAG_ARTIST, &artist); |
||
716 | m_imageInfoRecord.exifInfo.cameraName = QString(scannerModel); |
||
717 | m_imageInfoRecord.exifInfo.cameraVendor = QString(scannerMake); |
||
718 | m_imageInfoRecord.exifInfo.comment = QString(description); |
||
719 | m_imageInfoRecord.exifInfo.userComment = QString(copyright); |
||
720 | m_imageInfoRecord.exifInfo.width = widtht; |
||
721 | m_imageInfoRecord.exifInfo.height = heightt; |
||
722 | m_imageInfoRecord.exifInfo.dateTime = QString(datetime); |
||
723 | m_imageInfoRecord.exifInfo.artist = QString(artist); |
||
724 | m_imageInfoRecord.exifInfo.thumbnail = QImage(); |
||
725 | m_imageInfoRecord.exifDataValid = true; |
||
726 | uint32 EmbedLen = 0; |
||
727 | void* EmbedBuffer; |
||
728 | if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) |
||
729 | { |
||
730 | QByteArray profArray((const char*) EmbedBuffer, EmbedLen); |
||
731 | ScColorProfile tiffProf = engine.openProfileFromMem(profArray); |
||
732 | m_embeddedProfile = profArray; |
||
733 | m_imageInfoRecord.profileName = tiffProf.productDescription(); |
||
734 | m_imageInfoRecord.isEmbedded = true; |
||
735 | } |
||
736 | else |
||
737 | { |
||
738 | m_imageInfoRecord.isEmbedded = false; |
||
739 | m_imageInfoRecord.profileName = ""; |
||
740 | } |
||
741 | unsigned int PhotoshopLen = 0; |
||
742 | unsigned char* PhotoshopBuffer; |
||
743 | if (TIFFGetField(tif, TIFFTAG_PHOTOSHOP, &PhotoshopLen, &PhotoshopBuffer) ) |
||
744 | { |
||
745 | if (PhotoshopLen != 0) |
||
5937 | jghali | 746 | { |
22536 | jghali | 747 | QByteArray arrayPhot = QByteArray((const char*)PhotoshopBuffer,PhotoshopLen); |
748 | QDataStream strPhot(&arrayPhot,QIODevice::ReadOnly); |
||
749 | strPhot.setByteOrder( QDataStream::BigEndian ); |
||
750 | PSDHeader fakeHeader; |
||
751 | fakeHeader.width = widtht; |
||
752 | fakeHeader.height = heightt; |
||
753 | parseRessourceData(strPhot, fakeHeader, PhotoshopLen); |
||
754 | m_imageInfoRecord.exifInfo.width = widtht; |
||
755 | m_imageInfoRecord.exifInfo.height = heightt; |
||
756 | if (!m_imageInfoRecord.valid) |
||
22605 | craig | 757 | m_imageInfoRecord.valid = (m_imageInfoRecord.PDSpathData.size())>0; |
22536 | jghali | 758 | if (thumbnail) |
5937 | jghali | 759 | { |
22536 | jghali | 760 | if (m_photometric == PHOTOMETRIC_SEPARATED) |
6766 | fschmid | 761 | { |
22536 | jghali | 762 | isCMYK = true; |
763 | m_imageInfoRecord.colorspace = ColorSpaceCMYK; |
||
764 | } |
||
765 | else if (m_samplesperpixel == 1) |
||
766 | { |
||
767 | m_imageInfoRecord.colorspace = ColorSpaceGray; |
||
768 | isCMYK = false; |
||
769 | } |
||
770 | else |
||
771 | m_imageInfoRecord.colorspace = ColorSpaceRGB; |
||
772 | if (bitspersample == 1) |
||
773 | bilevel = true; |
||
774 | if (!m_imageInfoRecord.exifInfo.thumbnail.isNull()) |
||
775 | { |
||
776 | if (isCMYK) |
||
6766 | fschmid | 777 | { |
22536 | jghali | 778 | r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 5); |
779 | m_pixelFormat = Format_CMYKA_8;; |
||
6766 | fschmid | 780 | } |
22536 | jghali | 781 | else |
12732 | fschmid | 782 | { |
22536 | jghali | 783 | r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 4); |
784 | m_pixelFormat = (m_imageInfoRecord.colorspace == ColorSpaceCMYK) ? Format_CMYK_8 : Format_RGBA_8; |
||
12732 | fschmid | 785 | } |
22536 | jghali | 786 | r_image.fill(0); |
787 | QRgb *s; |
||
788 | uchar *d; |
||
789 | unsigned char cc, cm, cy, ck; |
||
790 | for (int yit=0; yit < m_imageInfoRecord.exifInfo.thumbnail.height(); ++yit) |
||
6766 | fschmid | 791 | { |
22536 | jghali | 792 | s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit )); |
793 | d = r_image.scanLine( yit ); |
||
794 | for (int xit=0; xit < m_imageInfoRecord.exifInfo.thumbnail.width(); ++xit) |
||
15128 | jghali | 795 | { |
22536 | jghali | 796 | if (isCMYK) |
6766 | fschmid | 797 | { |
22536 | jghali | 798 | cc = 255 - qRed(*s); |
799 | cm = 255 - qGreen(*s); |
||
800 | cy = 255 - qBlue(*s); |
||
801 | ck = qMin(qMin(cc, cm), cy); |
||
802 | d[0] = cc-ck; |
||
803 | d[1] = cm-ck; |
||
804 | d[2] = cy-ck; |
||
805 | d[3] = ck; |
||
806 | d[4] = 255; |
||
6766 | fschmid | 807 | } |
22536 | jghali | 808 | else |
809 | { |
||
810 | d[0] = qRed(*s); |
||
811 | d[1] = qGreen(*s); |
||
812 | d[2] = qBlue(*s); |
||
813 | d[3] = 255; |
||
814 | } |
||
815 | s++; |
||
816 | d += r_image.channels(); |
||
6766 | fschmid | 817 | } |
818 | } |
||
22536 | jghali | 819 | TIFFClose(tif); |
820 | return true; |
||
6766 | fschmid | 821 | } |
5937 | jghali | 822 | } |
823 | } |
||
22536 | jghali | 824 | } |
18925 | jghali | 825 | |
22536 | jghali | 826 | unsigned int PhotoshopLen2 = 0; |
827 | unsigned char* PhotoshopBuffer2; |
||
828 | int gotField = TIFFGetField(tif, 37724, &PhotoshopLen2, &PhotoshopBuffer2); |
||
829 | if (gotField && (PhotoshopLen2 > 40)) |
||
830 | { |
||
831 | m_imageInfoRecord.layerInfo.clear(); |
||
832 | QByteArray arrayPhot = QByteArray::fromRawData((const char*)PhotoshopBuffer2, PhotoshopLen2); |
||
833 | QDataStream s(&arrayPhot,QIODevice::ReadOnly); |
||
834 | if (byteOrder[0] == 'M') |
||
835 | s.setByteOrder( QDataStream::BigEndian ); |
||
836 | else |
||
837 | s.setByteOrder( QDataStream::LittleEndian ); |
||
18925 | jghali | 838 | |
22536 | jghali | 839 | failedPS = !loadLayerInfo(s, m_imageInfoRecord.layerInfo); |
840 | if (!failedPS) |
||
6589 | fschmid | 841 | { |
6850 | fschmid | 842 | int chans = 4; |
22536 | jghali | 843 | int numChannels = m_imageInfoRecord.layerInfo.last().channelType.count(); |
844 | int numLayers = m_imageInfoRecord.layerInfo.count(); |
||
845 | PSDHeader fakeHeader; |
||
846 | fakeHeader.width = widtht; |
||
847 | fakeHeader.height = heightt; |
||
848 | fakeHeader.channel_count = numChannels; |
||
849 | fakeHeader.depth = 8; |
||
20691 | craig | 850 | if (m_photometric == PHOTOMETRIC_SEPARATED) |
6589 | fschmid | 851 | { |
22536 | jghali | 852 | isCMYK = true; |
853 | fakeHeader.color_mode = CM_CMYK; |
||
854 | chans = 5; |
||
6850 | fschmid | 855 | } |
22536 | jghali | 856 | else if (m_samplesperpixel == 1) |
857 | { |
||
858 | fakeHeader.color_mode = CM_GRAYSCALE; |
||
859 | isCMYK = false; |
||
860 | chans = 4; |
||
861 | } |
||
6850 | fschmid | 862 | else |
22536 | jghali | 863 | { |
864 | fakeHeader.color_mode = CM_RGB; |
||
865 | isCMYK = false; |
||
6850 | fschmid | 866 | chans = 4; |
22536 | jghali | 867 | } |
6850 | fschmid | 868 | if (!r_image.create(widtht, heightt, chans)) |
6589 | fschmid | 869 | return false; |
8767 | fschmid | 870 | r_image.fill(0); |
22536 | jghali | 871 | bool firstLayer = true; |
872 | for (int layer = 0; layer < numLayers; layer++) |
||
6589 | fschmid | 873 | { |
22536 | jghali | 874 | loadLayerChannels( s, fakeHeader, m_imageInfoRecord.layerInfo, layer, &firstLayer ); |
6589 | fschmid | 875 | } |
22536 | jghali | 876 | arrayPhot.clear(); |
6766 | fschmid | 877 | TIFFClose(tif); |
22536 | jghali | 878 | foundPS = true; |
879 | if (m_imageInfoRecord.layerInfo.count() == 1) |
||
880 | m_imageInfoRecord.layerInfo.clear(); |
||
6589 | fschmid | 881 | } |
22536 | jghali | 882 | else |
5937 | jghali | 883 | { |
22536 | jghali | 884 | arrayPhot.clear(); |
885 | getLayers(fn, page); |
||
5937 | jghali | 886 | } |
22536 | jghali | 887 | } |
888 | |||
889 | if (xres <= 1.0 || yres <= 1.0) |
||
890 | { |
||
891 | xres = yres = 72.0; |
||
892 | QFileInfo qfi(fn); |
||
893 | m_message = QObject::tr("%1 may be corrupted : missing resolution tags").arg(qfi.fileName()); |
||
894 | m_msgType = warningMsg; |
||
895 | } |
||
896 | if ((!foundPS) || (failedPS)) |
||
897 | { |
||
898 | int chans = 4; |
||
899 | if (m_photometric == PHOTOMETRIC_SEPARATED) |
||
5937 | jghali | 900 | { |
22536 | jghali | 901 | if (m_samplesperpixel > 5) |
902 | chans = 4; |
||
903 | else |
||
904 | chans = m_samplesperpixel; |
||
5937 | jghali | 905 | } |
22536 | jghali | 906 | else |
907 | chans = 4; |
||
908 | if (!r_image.create(widtht, heightt, chans)) |
||
15182 | jghali | 909 | { |
22536 | jghali | 910 | TIFFClose(tif); |
911 | return false; |
||
15182 | jghali | 912 | } |
22536 | jghali | 913 | r_image.fill(0); |
914 | int layerNum = 0; |
||
915 | do |
||
15182 | jghali | 916 | { |
22536 | jghali | 917 | RawImage tmpImg; |
918 | if (!tmpImg.create(widtht, heightt, chans)) |
||
17758 | jghali | 919 | { |
22536 | jghali | 920 | TIFFClose(tif); |
921 | return false; |
||
17758 | jghali | 922 | } |
22536 | jghali | 923 | |
924 | tmpImg.fill(0); |
||
925 | if (!getImageData(tif, &tmpImg, widtht, heightt, size, m_photometric, bitspersample, m_samplesperpixel, bilevel, isCMYK)) |
||
926 | { |
||
927 | TIFFClose(tif); |
||
928 | return false; |
||
929 | } |
||
930 | bool visible = true; |
||
931 | bool useMask = true; |
||
932 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum))) |
||
933 | visible = m_imageInfoRecord.RequestProps[layerNum].visible; |
||
22700 | craig | 934 | QString layBlend("norm"); |
22536 | jghali | 935 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum))) |
936 | layBlend = m_imageInfoRecord.RequestProps[layerNum].blend; |
||
937 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum))) |
||
938 | useMask = m_imageInfoRecord.RequestProps[layerNum].useMask; |
||
939 | int layOpa = 255; |
||
940 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layerNum))) |
||
941 | layOpa = m_imageInfoRecord.RequestProps[layerNum].opacity; |
||
942 | if (visible) |
||
943 | { |
||
944 | if ((layerNum == 0) && (layBlend != "diss")) |
||
945 | r_image = tmpImg; |
||
946 | else |
||
947 | blendOntoTarget(&tmpImg, layOpa, layBlend, isCMYK, useMask); |
||
948 | } |
||
949 | //JG Copy should not be necessary as QImage is implicitly shared in Qt4 |
||
950 | QImage imt; //QImage imt = tmpImg.copy(); |
||
951 | double sx = tmpImg.width() / 40.0; |
||
952 | double sy = tmpImg.height() / 40.0; |
||
22605 | craig | 953 | imt = tmpImg.convertToQImage(chans > 4); |
22536 | jghali | 954 | imt = sy < sx ? imt.scaled(qRound(imt.width() / sx), qRound(imt.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) : |
955 | imt.scaled(qRound(imt.width() / sy), qRound(imt.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); |
||
956 | m_imageInfoRecord.layerInfo[layerNum].thumb = imt.copy(); |
||
957 | if (chans > 4) |
||
958 | { |
||
959 | QImage imt2 = imt.createAlphaMask(); |
||
960 | imt2.invertPixels(); |
||
961 | m_imageInfoRecord.layerInfo[layerNum].thumb_mask = imt2.copy(); |
||
962 | } |
||
17758 | jghali | 963 | else |
22536 | jghali | 964 | m_imageInfoRecord.layerInfo[layerNum].thumb_mask = QImage(); |
965 | layerNum++; |
||
966 | |||
967 | if ((m_imageInfoRecord.layerInfo.count() == 1) && (chans < 5)) |
||
968 | m_imageInfoRecord.layerInfo.clear(); |
||
969 | test = TIFFReadDirectory(tif); |
||
970 | |||
971 | // #10415 : check that image size for the current directory is the same as the main one |
||
972 | // Some progs use tiff directory to store previews, we do not handle such case |
||
973 | // and may perform reads in non allocated blocks if we continue |
||
974 | while (test == 1) |
||
17758 | jghali | 975 | { |
22536 | jghali | 976 | unsigned int dirWidth(0), dirHeight(0); |
977 | TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &dirWidth); |
||
978 | TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &dirHeight); |
||
979 | if (dirWidth == widtht && dirHeight == heightt) |
||
980 | break; |
||
981 | test = TIFFReadDirectory(tif); |
||
982 | layerNum++; |
||
17758 | jghali | 983 | } |
15182 | jghali | 984 | } |
22536 | jghali | 985 | while (test == 1); |
986 | TIFFClose(tif); |
||
987 | } |
||
988 | if (resolutionunit == RESUNIT_INCH) |
||
989 | { |
||
990 | m_image.setDotsPerMeterX ((int) (xres / 0.0254)); |
||
991 | m_image.setDotsPerMeterY ((int) (yres / 0.0254)); |
||
992 | m_imageInfoRecord.xres = qRound(xres); |
||
993 | m_imageInfoRecord.yres = qRound(yres); |
||
994 | } |
||
995 | else if (resolutionunit == RESUNIT_CENTIMETER) |
||
996 | { |
||
997 | m_image.setDotsPerMeterX ((int) (xres * 100.0)); |
||
998 | m_image.setDotsPerMeterY ((int) (yres * 100.0)); |
||
999 | m_imageInfoRecord.xres = qRound(xres*2.54); |
||
1000 | m_imageInfoRecord.yres = qRound(yres*2.54); |
||
1001 | } |
||
1002 | if (isCMYK) |
||
1003 | { |
||
1004 | m_imageInfoRecord.colorspace = ColorSpaceCMYK; |
||
1005 | m_pixelFormat = (r_image.channels() == 5) ? Format_CMYKA_8 : Format_CMYK_8; |
||
1006 | } |
||
1007 | else if (m_samplesperpixel == 1) |
||
1008 | { |
||
1009 | // Do not set m_pixelFormat here as the real pixel format is most probably different than gray |
||
1010 | if (bitspersample == 1) |
||
1011 | m_imageInfoRecord.colorspace = ColorSpaceMonochrome; |
||
5937 | jghali | 1012 | else |
22536 | jghali | 1013 | m_imageInfoRecord.colorspace = ColorSpaceGray; |
5937 | jghali | 1014 | } |
22536 | jghali | 1015 | else |
1016 | { |
||
1017 | m_imageInfoRecord.colorspace = ColorSpaceRGB; |
||
1018 | m_pixelFormat = Format_RGBA_8; |
||
1019 | } |
||
1020 | m_imageInfoRecord.BBoxX = 0; |
||
1021 | m_imageInfoRecord.BBoxH = r_image.height(); |
||
1022 | if ((m_imageInfoRecord.layerInfo.isEmpty()) && (m_imageInfoRecord.PDSpathData.isEmpty())) |
||
1023 | m_imageInfoRecord.valid = false; |
||
1024 | else |
||
1025 | m_imageInfoRecord.valid = true; |
||
1026 | return true; |
||
5937 | jghali | 1027 | } |
6736 | fschmid | 1028 | |
1029 | QString ScImgDataLoader_TIFF::getLayerString(QDataStream & s) |
||
1030 | { |
||
1031 | uchar len, tmp; |
||
1032 | uint adj; |
||
1033 | QString ret = ""; |
||
1034 | s >> len; |
||
1035 | if (len == 0) |
||
1036 | { |
||
1037 | s >> tmp; |
||
1038 | s >> tmp; |
||
1039 | s >> tmp; |
||
1040 | return ret; |
||
1041 | } |
||
22536 | jghali | 1042 | for (int i = 0; i < len; i++) |
6736 | fschmid | 1043 | { |
1044 | s >> tmp; |
||
1045 | ret += QChar(tmp); |
||
1046 | } |
||
1047 | adj = 0; |
||
1048 | if (((ret.length()+1) % 4) != 0) |
||
1049 | adj = 4 - ((ret.length()+1) % 4); |
||
10562 | fschmid | 1050 | s.device()->seek( s.device()->pos() + adj ); |
6736 | fschmid | 1051 | return ret; |
1052 | } |
||
6766 | fschmid | 1053 | |
9803 | fschmid | 1054 | bool ScImgDataLoader_TIFF::loadChannel( QDataStream & s, const PSDHeader & header, QList<PSDLayer> &layerInfo, uint layer, int channel, int component, RawImage &tmpImg) |
6766 | fschmid | 1055 | { |
10562 | fschmid | 1056 | uint base = s.device()->pos(); |
6766 | fschmid | 1057 | uchar cbyte; |
1058 | ushort compression; |
||
1059 | s >> compression; |
||
22536 | jghali | 1060 | if (compression > 1) |
6766 | fschmid | 1061 | return false; |
1062 | if (compression == 0) |
||
1063 | { |
||
1064 | int count = layerInfo[layer].channelLen[channel]-2; |
||
1065 | for (int i = 0; i < tmpImg.height(); i++) |
||
1066 | { |
||
1067 | uchar *ptr = tmpImg.scanLine(i); |
||
1068 | for (int j = 0; j < tmpImg.width(); j++) |
||
1069 | { |
||
1070 | s >> cbyte; |
||
1071 | count--; |
||
6850 | fschmid | 1072 | if ((header.color_mode == CM_CMYK) && (component < 4)) |
6766 | fschmid | 1073 | cbyte = 255 - cbyte; |
12732 | fschmid | 1074 | if ((header.color_mode == CM_GRAYSCALE) && (component != 3)) |
1075 | { |
||
1076 | ptr[0] = cbyte; |
||
1077 | ptr[1] = cbyte; |
||
1078 | ptr[2] = cbyte; |
||
1079 | } |
||
1080 | else |
||
1081 | ptr[component] = cbyte; |
||
6766 | fschmid | 1082 | if (count == 0) |
1083 | break; |
||
6850 | fschmid | 1084 | ptr += tmpImg.channels(); |
6766 | fschmid | 1085 | } |
1086 | if (count == 0) |
||
1087 | break; |
||
1088 | } |
||
1089 | } |
||
1090 | else |
||
1091 | { |
||
10562 | fschmid | 1092 | s.device()->seek( s.device()->pos() + tmpImg.height() * 2 ); |
6766 | fschmid | 1093 | uint pixel_count = tmpImg.width(); |
1094 | for (int hh = 0; hh < tmpImg.height(); hh++) |
||
1095 | { |
||
1096 | uint count = 0; |
||
1097 | uchar *ptr = tmpImg.scanLine(hh); |
||
6850 | fschmid | 1098 | uchar *ptr2 = ptr+tmpImg.width() * tmpImg.channels(); |
6766 | fschmid | 1099 | ptr += component; |
22724 | jghali | 1100 | while (count < pixel_count) |
6766 | fschmid | 1101 | { |
1102 | uchar c; |
||
22536 | jghali | 1103 | if (s.atEnd()) |
6766 | fschmid | 1104 | return false; |
1105 | s >> c; |
||
1106 | uint len = c; |
||
22536 | jghali | 1107 | if (len < 128) |
6766 | fschmid | 1108 | { |
1109 | // Copy next len+1 bytes literally. |
||
1110 | len++; |
||
1111 | count += len; |
||
22724 | jghali | 1112 | while (len != 0) |
6766 | fschmid | 1113 | { |
1114 | s >> cbyte; |
||
1115 | if (ptr < ptr2) |
||
1116 | { |
||
6850 | fschmid | 1117 | if ((header.color_mode == CM_CMYK) && (component < 4)) |
6766 | fschmid | 1118 | cbyte = 255 - cbyte; |
12732 | fschmid | 1119 | if ((header.color_mode == CM_GRAYSCALE) && (component != 3)) |
1120 | { |
||
1121 | ptr -= component; |
||
1122 | ptr[0] = cbyte; |
||
1123 | ptr[1] = cbyte; |
||
1124 | ptr[2] = cbyte; |
||
1125 | ptr += component; |
||
1126 | } |
||
1127 | else |
||
1128 | *ptr = cbyte; |
||
6766 | fschmid | 1129 | } |
6850 | fschmid | 1130 | ptr += tmpImg.channels(); |
6766 | fschmid | 1131 | len--; |
1132 | } |
||
1133 | } |
||
22536 | jghali | 1134 | else if (len > 128) |
6766 | fschmid | 1135 | { |
1136 | // Next -len+1 bytes in the dest are replicated from next source byte. |
||
1137 | // (Interpret len as a negative 8-bit int.) |
||
1138 | len ^= 0xFF; |
||
1139 | len += 2; |
||
1140 | count += len; |
||
1141 | uchar val; |
||
1142 | s >> val; |
||
6850 | fschmid | 1143 | if ((header.color_mode == CM_CMYK) && (component < 4)) |
6766 | fschmid | 1144 | val = 255 - val; |
22724 | jghali | 1145 | while (len != 0) |
6766 | fschmid | 1146 | { |
1147 | if (ptr < ptr2) |
||
12732 | fschmid | 1148 | { |
1149 | if ((header.color_mode == CM_GRAYSCALE) && (component != 3)) |
||
1150 | { |
||
1151 | ptr -= component; |
||
1152 | ptr[0] = val; |
||
1153 | ptr[1] = val; |
||
1154 | ptr[2] = val; |
||
1155 | ptr += component; |
||
1156 | } |
||
1157 | else |
||
1158 | *ptr = val; |
||
1159 | } |
||
6850 | fschmid | 1160 | ptr += tmpImg.channels(); |
6766 | fschmid | 1161 | len--; |
1162 | } |
||
1163 | } |
||
22536 | jghali | 1164 | else if (len == 128) |
6766 | fschmid | 1165 | { |
1166 | // No-op. |
||
1167 | } |
||
1168 | } |
||
1169 | } |
||
1170 | } |
||
10562 | fschmid | 1171 | s.device()->seek( base+layerInfo[layer].channelLen[channel] ); |
6766 | fschmid | 1172 | return true; |
1173 | } |
||
1174 | |||
18925 | jghali | 1175 | bool ScImgDataLoader_TIFF::loadLayerInfo(QDataStream & s, QList<PSDLayer> &layerInfo) |
1176 | { |
||
1177 | bool failedPS = false; |
||
1178 | uint addRes, layerinfo, channelLen, signature, extradata, layermasksize, layerRange, dummy; |
||
1179 | int top, left, bottom, right; |
||
1180 | short numLayers, numChannels; |
||
1181 | short channelType; |
||
1182 | uchar blendKey[4]; |
||
1183 | uchar opacity, clipping, flags, filler; |
||
21939 | craig | 1184 | QString blend; |
18925 | jghali | 1185 | |
1186 | layerInfo.clear(); |
||
1187 | |||
1188 | struct PSDLayer lay; |
||
1189 | do |
||
1190 | { |
||
22536 | jghali | 1191 | if (s.atEnd()) |
18925 | jghali | 1192 | { |
1193 | layerInfo.clear(); |
||
1194 | failedPS = true; |
||
1195 | break; |
||
1196 | } |
||
1197 | s >> signature; |
||
1198 | } |
||
1199 | while (signature != 0x4c617972); |
||
1200 | |||
1201 | if (failedPS) |
||
1202 | return false; |
||
1203 | |||
1204 | s >> layerinfo; |
||
1205 | s >> numLayers; |
||
1206 | if (numLayers < 0) |
||
1207 | numLayers = -numLayers; |
||
1208 | if (numLayers == 0) |
||
1209 | return true; |
||
1210 | |||
1211 | QDataStream::ByteOrder byteOrder = s.byteOrder(); |
||
1212 | |||
1213 | for (int layer = 0; layer < numLayers; layer++) |
||
1214 | { |
||
1215 | s >> top; |
||
1216 | lay.ypos = top; |
||
1217 | s >> left; |
||
1218 | lay.xpos = left; |
||
1219 | s >> bottom; |
||
1220 | lay.height = bottom - top; |
||
1221 | s >> right; |
||
1222 | lay.width = right - left; |
||
1223 | s >> numChannels; |
||
1224 | if (numChannels > 6) // we don't support images with more than 6 channels yet |
||
1225 | { |
||
1226 | m_imageInfoRecord.layerInfo.clear(); |
||
1227 | failedPS = true; |
||
1228 | break; |
||
1229 | } |
||
1230 | lay.channelType.clear(); |
||
1231 | lay.channelLen.clear(); |
||
1232 | for (int channels = 0; channels < numChannels; channels++) |
||
1233 | { |
||
1234 | s >> channelType; |
||
1235 | s >> channelLen; |
||
1236 | lay.channelType.append(channelType); |
||
1237 | lay.channelLen.append(channelLen); |
||
1238 | } |
||
1239 | s >> signature; |
||
1240 | blend = ""; |
||
22536 | jghali | 1241 | for (int i = 0; i < 4; i++) |
18925 | jghali | 1242 | { |
1243 | s >> blendKey[i]; |
||
1244 | if (byteOrder == QDataStream::BigEndian) |
||
1245 | blend.append(QChar(blendKey[i])); |
||
1246 | else |
||
1247 | blend.prepend(QChar(blendKey[i])); |
||
1248 | } |
||
1249 | lay.blend = blend; |
||
1250 | s >> opacity; |
||
1251 | lay.opacity = opacity; |
||
1252 | s >> clipping; |
||
1253 | lay.clipping = clipping; |
||
1254 | s >> flags; |
||
1255 | if (flags & 8) |
||
1256 | { |
||
1257 | if (flags & 16) // Unknown combination of layer flags, probably an adjustment or effects layer |
||
1258 | { |
||
1259 | layerInfo.clear(); |
||
1260 | failedPS = true; |
||
1261 | break; |
||
1262 | } |
||
1263 | } |
||
1264 | lay.flags = flags; |
||
1265 | s >> filler; |
||
1266 | s >> extradata; |
||
1267 | s >> layermasksize; |
||
1268 | lay.maskYpos = 0; |
||
1269 | lay.maskXpos = 0; |
||
1270 | lay.maskHeight = 0; |
||
1271 | lay.maskWidth = 0; |
||
1272 | if (layermasksize != 0) |
||
1273 | { |
||
1274 | s >> lay.maskYpos; |
||
1275 | s >> lay.maskXpos; |
||
1276 | s >> dummy; |
||
1277 | lay.maskHeight = dummy - lay.maskYpos; |
||
1278 | s >> dummy; |
||
1279 | lay.maskWidth = dummy - lay.maskXpos; |
||
1280 | s >> dummy; |
||
1281 | } |
||
1282 | s >> layerRange; |
||
1283 | s.device()->seek( s.device()->pos() + layerRange ); |
||
1284 | lay.layerName = getLayerString(s); |
||
1285 | layerInfo.append(lay); |
||
1286 | s >> signature; |
||
22536 | jghali | 1287 | if (signature == 0x3842494D) |
18925 | jghali | 1288 | { |
22536 | jghali | 1289 | while (signature == 0x3842494D) |
18925 | jghali | 1290 | { |
1291 | s >> signature; |
||
1292 | s >> addRes; |
||
1293 | s.device()->seek( s.device()->pos() + addRes ); |
||
1294 | s >> signature; |
||
1295 | } |
||
1296 | s.device()->seek( s.device()->pos() - 4 ); |
||
1297 | } |
||
1298 | else |
||
1299 | { |
||
1300 | s.device()->seek( s.device()->pos() - 2 ); |
||
1301 | s >> signature; |
||
22536 | jghali | 1302 | if (signature == 0x3842494D) |
18925 | jghali | 1303 | { |
22536 | jghali | 1304 | while (signature == 0x3842494D) |
18925 | jghali | 1305 | { |
1306 | s >> signature; |
||
1307 | s >> addRes; |
||
1308 | s.device()->seek( s.device()->pos() + addRes ); |
||
1309 | s >> signature; |
||
1310 | } |
||
1311 | s.device()->seek( s.device()->pos() - 4 ); |
||
1312 | } |
||
1313 | else |
||
1314 | s.device()->seek( s.device()->pos() - 6 ); |
||
1315 | } |
||
1316 | } |
||
1317 | |||
1318 | return (!failedPS && (layerInfo.count() >= 0)); |
||
1319 | } |
||
1320 | |||
9803 | fschmid | 1321 | bool ScImgDataLoader_TIFF::loadLayerChannels( QDataStream & s, const PSDHeader & header, QList<PSDLayer> &layerInfo, uint layer, bool* firstLayer) |
6766 | fschmid | 1322 | { |
1323 | // Find out if the data is compressed. |
||
1324 | // Known values: |
||
1325 | // 0: no compression |
||
1326 | // 1: RLE compressed |
||
10562 | fschmid | 1327 | uint base = s.device()->pos(); |
6766 | fschmid | 1328 | uint base2 = base; |
1329 | uint channel_num = layerInfo[layer].channelLen.count(); |
||
6850 | fschmid | 1330 | bool hasMask = false; |
1331 | bool hasAlpha = false; |
||
1332 | RawImage r2_image; |
||
1333 | RawImage mask; |
||
1334 | bool createOk = false; |
||
1335 | if (header.color_mode == CM_CMYK) |
||
6766 | fschmid | 1336 | { |
8574 | jghali | 1337 | createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, qMax(channel_num, (uint) 5)); |
6850 | fschmid | 1338 | r2_image.fill(0); |
1339 | } |
||
1340 | else |
||
1341 | { |
||
8574 | jghali | 1342 | createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, qMax(channel_num, (uint) 4)); |
6850 | fschmid | 1343 | r2_image.fill(0); |
1344 | } |
||
22536 | jghali | 1345 | if (!createOk) |
6850 | fschmid | 1346 | { |
22536 | jghali | 1347 | for (uint channel = 0; channel < channel_num; channel++) |
6766 | fschmid | 1348 | { |
1349 | base2 += layerInfo[layer].channelLen[channel]; |
||
1350 | } |
||
10562 | fschmid | 1351 | s.device()->seek( base2 ); |
6766 | fschmid | 1352 | return false; |
1353 | } |
||
8574 | jghali | 1354 | channel_num = qMin(channel_num, (uint) 39); |
6766 | fschmid | 1355 | uint components[40]; |
22536 | jghali | 1356 | for (uint channel = 0; channel < channel_num; channel++) |
6766 | fschmid | 1357 | { |
22724 | jghali | 1358 | switch (layerInfo[layer].channelType[channel]) |
6766 | fschmid | 1359 | { |
1360 | case 0: |
||
6850 | fschmid | 1361 | components[channel] = 0; |
6766 | fschmid | 1362 | break; |
1363 | case 1: |
||
1364 | components[channel] = 1; |
||
1365 | break; |
||
1366 | case 2: |
||
6850 | fschmid | 1367 | components[channel] = 2; |
6766 | fschmid | 1368 | break; |
1369 | case 3: |
||
1370 | components[channel] = 3; |
||
1371 | break; |
||
1372 | case -1: |
||
6850 | fschmid | 1373 | if (header.color_mode == CM_CMYK) |
1374 | { |
||
1375 | if (channel_num == 6) |
||
1376 | components[channel] = channel_num-2; |
||
1377 | else |
||
1378 | components[channel] = channel_num-1; |
||
1379 | } |
||
1380 | else |
||
1381 | { |
||
1382 | if (channel_num == 5) |
||
1383 | components[channel] = channel_num-2; |
||
1384 | else |
||
12732 | fschmid | 1385 | { |
1386 | if (header.color_mode == CM_GRAYSCALE) |
||
1387 | components[channel] = 3; |
||
1388 | else |
||
1389 | components[channel] = channel_num-1; |
||
1390 | } |
||
6850 | fschmid | 1391 | } |
1392 | hasAlpha = true; |
||
1393 | break; |
||
6766 | fschmid | 1394 | case -2: |
6850 | fschmid | 1395 | components[channel] = channel_num-1; |
6766 | fschmid | 1396 | break; |
1397 | } |
||
1398 | } |
||
6850 | fschmid | 1399 | if (!hasAlpha) |
11543 | jghali | 1400 | r2_image.fill((char) 255); |
22536 | jghali | 1401 | for (uint channel = 0; channel < channel_num; channel++) |
6766 | fschmid | 1402 | { |
1403 | if (layerInfo[layer].channelType[channel] == -2) |
||
1404 | { |
||
6850 | fschmid | 1405 | if (!mask.create( layerInfo[layer].maskWidth, layerInfo[layer].maskHeight, 1 )) |
6766 | fschmid | 1406 | break; |
6850 | fschmid | 1407 | mask.fill(0); |
1408 | if (!loadChannel(s, header, layerInfo, layer, channel, 0, mask)) |
||
6766 | fschmid | 1409 | break; |
6850 | fschmid | 1410 | hasMask = true; |
6766 | fschmid | 1411 | } |
6850 | fschmid | 1412 | if (!loadChannel(s, header, layerInfo, layer, channel, components[channel], r2_image)) |
1413 | break; |
||
6766 | fschmid | 1414 | } |
22536 | jghali | 1415 | for (uint channel = 0; channel < channel_num; channel++) |
6766 | fschmid | 1416 | { |
1417 | base2 += layerInfo[layer].channelLen[channel]; |
||
1418 | } |
||
10562 | fschmid | 1419 | s.device()->seek( base2 ); |
6850 | fschmid | 1420 | QImage tmpImg2; |
6766 | fschmid | 1421 | if (header.color_mode == CM_CMYK) |
6850 | fschmid | 1422 | tmpImg2 = r2_image.convertToQImage(true); |
1423 | else |
||
1424 | tmpImg2 = r2_image.convertToQImage(false); |
||
6766 | fschmid | 1425 | QImage imt; |
6850 | fschmid | 1426 | double sx = tmpImg2.width() / 40.0; |
1427 | double sy = tmpImg2.height() / 40.0; |
||
10562 | fschmid | 1428 | imt = sy < sx ? tmpImg2.scaled(qRound(tmpImg2.width() / sx), qRound(tmpImg2.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) : |
1429 | tmpImg2.scaled(qRound(tmpImg2.width() / sy), qRound(tmpImg2.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); |
||
6766 | fschmid | 1430 | layerInfo[layer].thumb = imt.copy(); |
6850 | fschmid | 1431 | if (hasMask) |
6766 | fschmid | 1432 | { |
6850 | fschmid | 1433 | QImage imt2; |
1434 | QImage tmpImg; |
||
1435 | tmpImg = mask.convertToQImage(true); |
||
1436 | double sx = tmpImg.width() / 40.0; |
||
1437 | double sy = tmpImg.height() / 40.0; |
||
10562 | fschmid | 1438 | imt2 = sy < sx ? tmpImg.scaled(qRound(tmpImg.width() / sx), qRound(tmpImg.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) : |
1439 | tmpImg.scaled(qRound(tmpImg.width() / sy), qRound(tmpImg.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); |
||
6766 | fschmid | 1440 | imt2.invertPixels(); |
1441 | layerInfo[layer].thumb_mask = imt2.copy(); |
||
1442 | } |
||
1443 | else |
||
1444 | layerInfo[layer].thumb_mask = QImage(); |
||
22533 | jghali | 1445 | if (!m_imageInfoRecord.isRequest || !m_imageInfoRecord.RequestProps.contains(layer)) |
6766 | fschmid | 1446 | m_imageInfoRecord.RequestProps[layer].useMask = true; |
1447 | bool visible = !(layerInfo[layer].flags & 2); |
||
1448 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer))) |
||
1449 | visible = m_imageInfoRecord.RequestProps[layer].visible; |
||
1450 | if (visible) |
||
1451 | { |
||
1452 | unsigned int startSrcY, startSrcX, startDstY, startDstX; |
||
1453 | if (layerInfo[layer].ypos < 0) |
||
1454 | { |
||
1455 | startSrcY = abs(layerInfo[layer].ypos); |
||
1456 | startDstY = 0; |
||
1457 | } |
||
1458 | else |
||
1459 | { |
||
1460 | startSrcY = 0; |
||
1461 | startDstY = layerInfo[layer].ypos; |
||
1462 | } |
||
1463 | if (layerInfo[layer].xpos < 0) |
||
1464 | { |
||
1465 | startSrcX = abs(layerInfo[layer].xpos); |
||
1466 | startDstX = 0; |
||
1467 | } |
||
1468 | else |
||
1469 | { |
||
1470 | startSrcX = 0; |
||
1471 | startDstX = layerInfo[layer].xpos; |
||
1472 | } |
||
19730 | fschmid | 1473 | unsigned int startSrcXm; //, startSrcYm, startDstYm, startDstXm; |
1474 | /* if (layerInfo[layer].maskYpos < 0) |
||
6766 | fschmid | 1475 | { |
1476 | startSrcYm = abs(layerInfo[layer].maskYpos); |
||
1477 | startDstYm = 0; |
||
1478 | } |
||
1479 | else |
||
1480 | { |
||
1481 | startSrcYm = 0; |
||
1482 | startDstYm = layerInfo[layer].maskYpos; |
||
19730 | fschmid | 1483 | }*/ |
6766 | fschmid | 1484 | if (layerInfo[layer].maskXpos < 0) |
1485 | { |
||
1486 | startSrcXm = abs(layerInfo[layer].maskXpos); |
||
19730 | fschmid | 1487 | // startDstXm = 0; |
6766 | fschmid | 1488 | } |
1489 | else |
||
1490 | { |
||
1491 | startSrcXm = 0; |
||
19730 | fschmid | 1492 | // startDstXm = layerInfo[layer].maskXpos; |
6766 | fschmid | 1493 | } |
1494 | QString layBlend2 = layerInfo[layer].blend; |
||
1495 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer))) |
||
1496 | layBlend2 = m_imageInfoRecord.RequestProps[layer].blend; |
||
6850 | fschmid | 1497 | if (layBlend2 == "diss") |
6766 | fschmid | 1498 | { |
6850 | fschmid | 1499 | hasAlpha = true; |
6766 | fschmid | 1500 | int layOpa = layerInfo[layer].opacity; |
1501 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer))) |
||
1502 | layOpa = m_imageInfoRecord.RequestProps[layer].opacity; |
||
6850 | fschmid | 1503 | for (int l = 0; l < r2_image.height(); l++) |
6766 | fschmid | 1504 | { |
20691 | craig | 1505 | srand(m_random_table[ l % 4096]); |
6850 | fschmid | 1506 | for (int k = 0; k < r2_image.width(); k++) |
6766 | fschmid | 1507 | { |
1508 | int rand_val = rand() & 0xff; |
||
1509 | if (rand_val > layOpa) |
||
6850 | fschmid | 1510 | r2_image.setAlpha(k, l, 0); |
6766 | fschmid | 1511 | } |
1512 | } |
||
1513 | } |
||
1514 | if (*firstLayer) |
||
1515 | { |
||
22536 | jghali | 1516 | for (int yi=static_cast<int>(startSrcY); yi < qMin(r2_image.height(), r_image.height()); ++yi) |
6766 | fschmid | 1517 | { |
6850 | fschmid | 1518 | unsigned char *s = r2_image.scanLine( yi ); |
8562 | jghali | 1519 | unsigned char *d = r_image.scanLine( qMin(static_cast<int>(startDstY), r_image.height()-1) ); |
1520 | d += qMin(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels(); |
||
1521 | s += qMin(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels(); |
||
22536 | jghali | 1522 | for (int xi=static_cast<int>(startSrcX); xi < qMin(r2_image.width(), r_image.width()); ++xi ) |
6766 | fschmid | 1523 | { |
6850 | fschmid | 1524 | d[0] = s[0]; |
1525 | d[1] = s[1]; |
||
1526 | d[2] = s[2]; |
||
1527 | if (header.color_mode == CM_RGB) |
||
1528 | { |
||
1529 | if (hasAlpha) |
||
1530 | d[3] = s[3]; |
||
1531 | else |
||
1532 | d[3] = 255; |
||
1533 | } |
||
1534 | else |
||
1535 | { |
||
1536 | d[3] = s[3]; |
||
1537 | if (hasAlpha) |
||
1538 | d[4] = s[4]; |
||
1539 | else |
||
1540 | d[4] = 255; |
||
1541 | } |
||
1542 | s += r2_image.channels(); |
||
1543 | d += r_image.channels(); |
||
6766 | fschmid | 1544 | } |
1545 | startDstY++; |
||
1546 | } |
||
1547 | } |
||
1548 | else |
||
1549 | { |
||
1550 | for (int i = static_cast<int>(startSrcY); i < layerInfo[layer].height; i++) |
||
1551 | { |
||
8562 | jghali | 1552 | unsigned char *d = r_image.scanLine(qMin(static_cast<int>(startDstY), r_image.height()-1)); |
1553 | unsigned char *s = r2_image.scanLine(qMin(i, r2_image.height()-1)); |
||
1554 | d += qMin(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels(); |
||
1555 | s += qMin(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels(); |
||
22605 | craig | 1556 | unsigned char *sm = nullptr; |
6850 | fschmid | 1557 | if (hasMask) |
6766 | fschmid | 1558 | { |
8562 | jghali | 1559 | sm = mask.scanLine(qMin(i, mask.height()-1)); |
1560 | sm += qMin(static_cast<int>(startSrcXm), mask.width()-1) * mask.channels(); |
||
6766 | fschmid | 1561 | } |
1562 | startDstY++; |
||
7980 | fschmid | 1563 | unsigned char r, g, b, src_r, src_g, src_b, src_a, src_alpha, dst_alpha; |
1564 | unsigned char a = 0; |
||
6850 | fschmid | 1565 | unsigned int maxDestX = r_image.width() - startDstX + startSrcX - 1; |
8562 | jghali | 1566 | for (unsigned int j = startSrcX; j < qMin(maxDestX, static_cast<unsigned int>(layerInfo[layer].width)); j++) |
6766 | fschmid | 1567 | { |
1568 | src_r = s[0]; |
||
1569 | src_g = s[1]; |
||
1570 | src_b = s[2]; |
||
1571 | src_a = s[3]; |
||
6850 | fschmid | 1572 | if (hasAlpha) |
1573 | { |
||
6854 | fschmid | 1574 | if (hasMask) |
1575 | { |
||
1576 | if (m_imageInfoRecord.RequestProps[layer].useMask) |
||
1577 | src_alpha = sm[0]; |
||
1578 | else |
||
1579 | src_alpha = s[channel_num - 2]; |
||
1580 | } |
||
6850 | fschmid | 1581 | else |
1582 | src_alpha = s[channel_num - 1]; |
||
1583 | } |
||
6854 | fschmid | 1584 | else |
1585 | src_alpha = 255; |
||
6850 | fschmid | 1586 | if ((hasMask) && (m_imageInfoRecord.RequestProps[layer].useMask)) |
1587 | src_alpha = sm[0]; |
||
1588 | int layOpa = layerInfo[layer].opacity; |
||
1589 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer))) |
||
1590 | layOpa = m_imageInfoRecord.RequestProps[layer].opacity; |
||
6766 | fschmid | 1591 | QString layBlend = layerInfo[layer].blend; |
1592 | if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer))) |
||
1593 | layBlend = m_imageInfoRecord.RequestProps[layer].blend; |
||
6850 | fschmid | 1594 | if (layBlend != "diss") |
1595 | src_alpha = INT_MULT(src_alpha, layOpa); |
||
1596 | if (header.color_mode == CM_CMYK) |
||
1597 | dst_alpha = d[4]; |
||
1598 | else |
||
1599 | dst_alpha = d[3]; |
||
1600 | if ((dst_alpha > 0) && (src_alpha > 0)) |
||
6766 | fschmid | 1601 | { |
6850 | fschmid | 1602 | if (layBlend == "mul ") |
6766 | fschmid | 1603 | { |
1604 | src_r = INT_MULT(src_r, d[0]); |
||
1605 | src_g = INT_MULT(src_g, d[1]); |
||
1606 | src_b = INT_MULT(src_b, d[2]); |
||
6850 | fschmid | 1607 | if (header.color_mode == CM_CMYK) |
1608 | src_a = INT_MULT(src_a, d[3]); |
||
6766 | fschmid | 1609 | } |
6850 | fschmid | 1610 | else if (layBlend == "scrn") |
6766 | fschmid | 1611 | { |
1612 | src_r = 255 - ((255-src_r) * (255-d[0]) / 128); |
||
1613 | src_g = 255 - ((255-src_g) * (255-d[1]) / 128); |
||
1614 | src_b = 255 - ((255-src_b) * (255-d[2]) / 128); |
||
6850 | fschmid | 1615 | if (header.color_mode == CM_CMYK) |
1616 | src_a = 255 - ((255-src_a) * (255-d[3]) / 128); |
||
6766 | fschmid | 1617 | } |
6850 | fschmid | 1618 | else if (layBlend == "over") |
6766 | fschmid | 1619 | { |
1620 | src_g = d[1] < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128); |
||
1621 | src_b = d[2] < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128); |
||
1622 | src_a = d[3] < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128); |
||
6850 | fschmid | 1623 | if (header.color_mode == CM_CMYK) |
6766 | fschmid | 1624 | src_r = d[0] < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128); |
1625 | } |
||
6850 | fschmid | 1626 | else if (layBlend == "diff") |
6766 | fschmid | 1627 | { |
1628 | src_r = d[0] > src_r ? d[0] - src_r : src_r - d[0]; |
||
1629 | src_g = d[1] > src_g ? d[1] - src_g : src_g - d[1]; |
||
1630 | src_b = d[2] > src_b ? d[2] - src_b : src_b - d[2]; |
||
6850 | fschmid | 1631 | if (header.color_mode == CM_CMYK) |
1632 | src_a = d[3] > src_a ? d[3] - src_a : src_a - d[3]; |
||
6766 | fschmid | 1633 | } |
6850 | fschmid | 1634 | else if (layBlend == "dark") |
6766 | fschmid | 1635 | { |
1636 | src_r = d[0] < src_r ? d[0] : src_r; |
||
1637 | src_g = d[1] < src_g ? d[1] : src_g; |
||
1638 | src_b = d[2] < src_b ? d[2] : src_b; |
||
6850 | fschmid | 1639 | if (header.color_mode == CM_CMYK) |
1640 | src_a = d[3] < src_a ? d[3] : src_a; |
||
6766 | fschmid | 1641 | } |
6850 | fschmid | 1642 | else if (layBlend == "hLit") |
6766 | fschmid | 1643 | { |
1644 | src_r = src_r < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128); |
||
1645 | src_g = src_g < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128); |
||
1646 | src_b = src_b < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128); |
||
6850 | fschmid | 1647 | if (header.color_mode == CM_CMYK) |
1648 | src_a = src_a < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128); |
||
6766 | fschmid | 1649 | } |
6850 | fschmid | 1650 | else if (layBlend == "sLit") |
6766 | fschmid | 1651 | { |
1652 | src_r = src_r * d[0] / 256 + src_r * (255 - ((255-src_r)*(255-d[0]) / 256) - src_r * d[0] / 256) / 256; |
||
1653 | src_g = src_g * d[1] / 256 + src_g * (255 - ((255-src_g)*(255-d[1]) / 256) - src_g * d[1] / 256) / 256; |
||
1654 | src_b = src_b * d[2] / 256 + src_b * (255 - ((255-src_b)*(255-d[2]) / 256) - src_b * d[2] / 256) / 256; |
||
6850 | fschmid | 1655 | if (header.color_mode == CM_CMYK) |
1656 | src_a = src_a * d[3] / 256 + src_a * (255 - ((255-src_a)*(255-d[3]) / 256) - src_a * d[3] / 256) / 256; |
||
6766 | fschmid | 1657 | } |
6850 | fschmid | 1658 | else if (layBlend == "lite") |
6766 | fschmid | 1659 | { |
1660 | src_r = d[0] < src_r ? src_r : d[0]; |
||
1661 | src_g = d[1] < src_g ? src_g : d[1]; |
||
1662 | src_b = d[2] < src_b ? src_b : d[2]; |
||
6850 | fschmid | 1663 | if (header.color_mode == CM_CMYK) |
1664 | src_a = d[3] < src_a ? src_a : d[3]; |
||
6766 | fschmid | 1665 | } |
6850 | fschmid | 1666 | else if (layBlend == "smud") |
6766 | fschmid | 1667 | { |
1668 | src_r = d[0] + src_r - src_r * d[0] / 128; |
||
1669 | src_g = d[1] + src_g - src_g * d[1] / 128; |
||
1670 | src_b = d[2] + src_b - src_b * d[2] / 128; |
||
6850 | fschmid | 1671 | if (header.color_mode == CM_CMYK) |
1672 | src_a = d[3] + src_a - src_a * d[3] / 128; |
||
6766 | fschmid | 1673 | } |
6850 | fschmid | 1674 | else if (layBlend == "div ") |
6766 | fschmid | 1675 | { |
1676 | src_r = src_r == 255 ? 255 : ((d[0] * 256) / (255-src_r)) > 255 ? 255 : (d[0] * 256) / (255-src_r); |
||
1677 | src_g = src_g == 255 ? 255 : ((d[1] * 256) / (255-src_g)) > 255 ? 255 : (d[1] * 256) / (255-src_g); |
||
1678 | src_b = src_b == 255 ? 255 : ((d[2] * 256) / (255-src_b)) > 255 ? 255 : (d[2] * 256) / (255-src_b); |
||
6850 | fschmid | 1679 | if (header.color_mode == CM_CMYK) |
1680 | src_a = src_a == 255 ? 255 : ((d[3] * 256) / (255-src_a)) > 255 ? 255 : (d[3] * 256) / (255-src_a); |
||
6766 | fschmid | 1681 | } |
6850 | fschmid | 1682 | else if (layBlend == "idiv") |
6766 | fschmid | 1683 | { |
1684 | src_r = src_r == 0 ? 0 : (255 - (((255-d[0]) * 256) / src_r)) < 0 ? 0 : 255 - (((255-d[0]) * 256) / src_r); |
||
1685 | src_g = src_g == 0 ? 0 : (255 - (((255-d[1]) * 256) / src_g)) < 0 ? 0 : 255 - (((255-d[1]) * 256) / src_g); |
||
1686 | src_b = src_b == 0 ? 0 : (255 - (((255-d[2]) * 256) / src_b)) < 0 ? 0 : 255 - (((255-d[2]) * 256) / src_b); |
||
6850 | fschmid | 1687 | if (header.color_mode == CM_CMYK) |
1688 | src_a = src_a == 0 ? 0 : (255 - (((255-d[3]) * 256) / src_a)) < 0 ? 0 : 255 - (((255-d[3]) * 256) / src_a); |
||
6766 | fschmid | 1689 | } |
6850 | fschmid | 1690 | else if (layBlend == "hue ") |
6766 | fschmid | 1691 | { |
6850 | fschmid | 1692 | if (header.color_mode != CM_CMYK) |
6766 | fschmid | 1693 | { |
1694 | uchar new_r = d[0]; |
||
1695 | uchar new_g = d[1]; |
||
1696 | uchar new_b = d[2]; |
||
1697 | RGBTOHSV(src_r, src_g, src_b); |
||
1698 | RGBTOHSV(new_r, new_g, new_b); |
||
1699 | new_r = src_r; |
||
1700 | HSVTORGB(new_r, new_g, new_b); |
||
1701 | src_r = new_r; |
||
1702 | src_g = new_g; |
||
1703 | src_b = new_b; |
||
1704 | } |
||
1705 | } |
||
6850 | fschmid | 1706 | else if (layBlend == "sat ") |
6766 | fschmid | 1707 | { |
6850 | fschmid | 1708 | if (header.color_mode != CM_CMYK) |
6766 | fschmid | 1709 | { |
1710 | uchar new_r = d[0]; |
||
1711 | uchar new_g = d[1]; |
||
1712 | uchar new_b = d[2]; |
||
1713 | RGBTOHSV(src_r, src_g, src_b); |
||
1714 | RGBTOHSV(new_r, new_g, new_b); |
||
1715 | new_g = src_g; |
||
1716 | HSVTORGB(new_r, new_g, new_b); |
||
1717 | src_r = new_r; |
||
1718 | src_g = new_g; |
||
1719 | src_b = new_b; |
||
1720 | } |
||
1721 | } |
||
6850 | fschmid | 1722 | else if (layBlend == "lum ") |
6766 | fschmid | 1723 | { |
6850 | fschmid | 1724 | if (header.color_mode != CM_CMYK) |
6766 | fschmid | 1725 | { |
1726 | uchar new_r = d[0]; |
||
1727 | uchar new_g = d[1]; |
||
1728 | uchar new_b = d[2]; |
||
1729 | RGBTOHSV(src_r, src_g, src_b); |
||
1730 | RGBTOHSV(new_r, new_g, new_b); |
||
1731 | new_b = src_b; |
||
1732 | HSVTORGB(new_r, new_g, new_b); |
||
1733 | src_r = new_r; |
||
1734 | src_g = new_g; |
||
1735 | src_b = new_b; |
||
1736 | } |
||
1737 | } |
||
6850 | fschmid | 1738 | else if (layBlend == "colr") |
6766 | fschmid | 1739 | { |
6850 | fschmid | 1740 | if (header.color_mode != CM_CMYK) |
6766 | fschmid | 1741 | { |
1742 | uchar new_r = d[0]; |
||
1743 | uchar new_g = d[1]; |
||
1744 | uchar new_b = d[2]; |
||
1745 | RGBTOHLS(src_r, src_g, src_b); |
||
1746 | RGBTOHLS(new_r, new_g, new_b); |
||
1747 | new_r = src_r; |
||
1748 | new_b = src_b; |
||
1749 | HLSTORGB(new_r, new_g, new_b); |
||
1750 | src_r = new_r; |
||
1751 | src_g = new_g; |
||
1752 | src_b = new_b; |
||
1753 | } |
||
1754 | } |
||
1755 | } |
||
6850 | fschmid | 1756 | if (dst_alpha == 0) |
6766 | fschmid | 1757 | { |
6850 | fschmid | 1758 | r = src_r; |
1759 | g = src_g; |
||
1760 | b = src_b; |
||
1761 | a = src_a; |
||
6766 | fschmid | 1762 | } |
1763 | else |
||
1764 | { |
||
6850 | fschmid | 1765 | if (src_alpha > 0) |
6766 | fschmid | 1766 | { |
6850 | fschmid | 1767 | r = (d[0] * (255 - src_alpha) + src_r * src_alpha) / 255; |
1768 | g = (d[1] * (255 - src_alpha) + src_g * src_alpha) / 255; |
||
1769 | b = (d[2] * (255 - src_alpha) + src_b * src_alpha) / 255; |
||
1770 | if (header.color_mode == CM_CMYK) |
||
1771 | a = (d[3] * (255 - src_alpha) + src_a * src_alpha) / 255; |
||
1772 | if (layBlend != "diss") |
||
1773 | src_alpha = dst_alpha + INT_MULT(255 - dst_alpha, src_alpha); |
||
6766 | fschmid | 1774 | } |
1775 | } |
||
6850 | fschmid | 1776 | if (src_alpha > 0) |
6766 | fschmid | 1777 | { |
1778 | d[0] = r; |
||
1779 | d[1] = g; |
||
1780 | d[2] = b; |
||
6850 | fschmid | 1781 | if (header.color_mode == CM_CMYK) |
6766 | fschmid | 1782 | { |
1783 | d[3] = a; |
||
6850 | fschmid | 1784 | d[4] = src_alpha; |
6766 | fschmid | 1785 | } |
6850 | fschmid | 1786 | else |
1787 | d[3] = src_alpha; |
||
6766 | fschmid | 1788 | } |
6850 | fschmid | 1789 | s += r2_image.channels(); |
1790 | d += r_image.channels(); |
||
1791 | if (hasMask) |
||
1792 | sm += mask.channels(); |
||
6766 | fschmid | 1793 | } |
1794 | } |
||
1795 | } |
||
1796 | } |
||
1797 | *firstLayer = false; |
||
1798 | return true; |
||
1799 | } |