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