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