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 */
7 #include "scconfig.h"
8 #include "colormgmt/sccolormgmtengine.h"
9 #include "scimgdataloader_psd.h"
10 #include "util_color.h"
11 #include "sccolorengine.h"
12 #include "scribuscore.h"
13
14 #include <QFile>
15 #include <QFileInfo>
16 #include <QList>
17
operator >>(QDataStream & s,PSDHeader & header)18 static QDataStream & operator>> ( QDataStream & s, PSDHeader & header )
19 {
20 s >> header.signature;
21 s >> header.version;
22 for (int i = 0; i < 6; i++)
23 {
24 s >> header.reserved[i];
25 }
26 s >> header.channel_count;
27 s >> header.height;
28 s >> header.width;
29 s >> header.depth;
30 s >> header.color_mode;
31 return s;
32 }
33
ScImgDataLoader_PSD()34 ScImgDataLoader_PSD::ScImgDataLoader_PSD()
35 {
36 m_maxChannels = 0;
37 initSupportedFormatList();
38 }
39
initSupportedFormatList()40 void ScImgDataLoader_PSD::initSupportedFormatList()
41 {
42 m_supportedFormats.clear();
43 m_supportedFormats.append( "psd" );
44 }
45
loadEmbeddedProfile(const QString & fn,int)46 void ScImgDataLoader_PSD::loadEmbeddedProfile(const QString& fn, int /*page*/)
47 {
48 m_embeddedProfile.resize(0);
49 m_profileComponents = 0;
50
51 ScColorProfile prof;
52 ScColorMgmtEngine engine(ScCore->defaultEngine);
53 QFileInfo fi = QFileInfo(fn);
54 if (!fi.exists())
55 return;
56
57 QString ext = fi.suffix().toLower();
58 if (ext != "psd")
59 return;
60
61 QFile f(fn);
62 if (!f.open(QIODevice::ReadOnly))
63 return;
64
65 m_imageInfoRecord.xres = 72;
66 m_imageInfoRecord.yres = 72;
67 QDataStream s( &f );
68 s.setByteOrder( QDataStream::BigEndian );
69 PSDHeader header;
70 s >> header;
71 // Check image file format.
72 if (s.atEnd() || !IsValid(header))
73 return;
74 // Check if it's a supported format.
75 if (!IsSupported(header))
76 return;
77 if (!LoadPSDResources(s, header, s.device()->pos()))
78 return;
79 if (m_embeddedProfile.size() > 0)
80 {
81 prof = engine.openProfileFromMem(m_embeddedProfile.data());
82 if (prof)
83 {
84 if (prof.colorSpace() == ColorSpace_Rgb)
85 m_profileComponents = 3;
86 if (prof.colorSpace() == ColorSpace_Cmyk)
87 m_profileComponents = 4;
88 if (prof.colorSpace() == ColorSpace_Gray)
89 m_profileComponents = 1;
90 }
91 }
92 f.close();
93 }
94
preloadAlphaChannel(const QString & fn,int,int res,bool & hasAlpha)95 bool ScImgDataLoader_PSD::preloadAlphaChannel(const QString& fn, int /*page*/, int res, bool& hasAlpha)
96 {
97 bool valid = m_imageInfoRecord.isRequest;
98 QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
99 initialize();
100 hasAlpha = false;
101 m_imageInfoRecord.RequestProps = req;
102 m_imageInfoRecord.isRequest = valid;
103 QFileInfo fi = QFileInfo(fn);
104 if (!fi.exists())
105 return false;
106
107 QFile f(fn);
108 if (f.open(QIODevice::ReadOnly))
109 {
110 QDataStream s( &f );
111 s.setByteOrder( QDataStream::BigEndian );
112 PSDHeader header;
113 s >> header;
114 // Check image file format.
115 if (s.atEnd() || !IsValid(header))
116 return false;
117 // Check if it's a supported format.
118 if (!IsSupported(header))
119 return false;
120 if (!LoadPSD(s, header))
121 r_image.resize(0);
122 f.close();
123 m_imageInfoRecord.valid = true;
124 if (header.color_mode == CM_CMYK)
125 m_imageInfoRecord.valid = hasAlpha = (m_maxChannels > 4);
126 else if (header.color_mode == CM_GRAYSCALE)
127 m_imageInfoRecord.valid = hasAlpha = (m_maxChannels > 1);
128 else
129 m_imageInfoRecord.valid = hasAlpha = (m_maxChannels >= 4);
130 return true;
131 }
132 return false;
133 }
134
loadPicture(const QString & fn,int,int res,bool thumbnail)135 bool ScImgDataLoader_PSD::loadPicture(const QString& fn, int /*page*/, int res, bool thumbnail)
136 {
137 ScColorMgmtEngine engine(ScCore->defaultEngine);
138 bool isCMYK = false;
139 if (!QFile::exists(fn))
140 return false;
141 bool valid = m_imageInfoRecord.isRequest;
142 QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
143 initialize();
144 m_imageInfoRecord.RequestProps = req;
145 m_imageInfoRecord.isRequest = valid;
146 m_imageInfoRecord.type = ImageTypePSD;
147 m_imageInfoRecord.exifDataValid = false;
148 m_imageInfoRecord.layerInfo.clear();
149 m_imageInfoRecord.PDSpathData.clear();
150 QFile f(fn);
151 if (f.open(QIODevice::ReadOnly))
152 {
153 m_imageInfoRecord.xres = 72;
154 m_imageInfoRecord.yres = 72;
155 QDataStream s( &f );
156 s.setByteOrder( QDataStream::BigEndian );
157 PSDHeader header;
158 s >> header;
159 // Check image file format.
160 if (s.atEnd() || !IsValid(header))
161 return false;
162 // Check if it's a supported format.
163 if (!IsSupported(header))
164 return false;
165 if (thumbnail)
166 header.reserved[0] = 't';
167 if (!LoadPSD(s, header))
168 return false;
169 if (m_embeddedProfile.size() > 0)
170 {
171 ScColorProfile prof = engine.openProfileFromMem(m_embeddedProfile);
172 m_imageInfoRecord.profileName = prof.productDescription();
173 m_imageInfoRecord.embeddedProfileName = m_imageInfoRecord.profileName;
174 m_imageInfoRecord.isEmbedded = true;
175 }
176 isCMYK = (header.color_mode == CM_CMYK);
177 if (header.color_mode == CM_CMYK)
178 m_imageInfoRecord.colorspace = ColorSpaceCMYK;
179 else if (header.color_mode == CM_RGB)
180 m_imageInfoRecord.colorspace = ColorSpaceRGB;
181 else if (header.color_mode == CM_GRAYSCALE)
182 m_imageInfoRecord.colorspace = ColorSpaceGray;
183 else if (header.color_mode == CM_DUOTONE)
184 m_imageInfoRecord.colorspace = ColorSpaceDuotone;
185 f.close();
186 if (thumbnail)
187 {
188 if (!m_imageInfoRecord.exifInfo.thumbnail.isNull())
189 {
190 if (isCMYK)
191 {
192 r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 5);
193 m_pixelFormat = Format_CMYKA_8;
194 }
195 else
196 {
197 r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 4);
198 m_pixelFormat = Format_RGBA_8;
199 }
200 QRgb *s;
201 unsigned char cc, cm, cy, ck;
202 uchar *d;
203 for (int yit = 0; yit < m_imageInfoRecord.exifInfo.thumbnail.height(); ++yit)
204 {
205 s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit ));
206 d = r_image.scanLine( yit );
207 for (int xit =0 ; xit < m_imageInfoRecord.exifInfo.thumbnail.width(); ++xit)
208 {
209 if (isCMYK)
210 {
211 cc = 255 - qRed(*s);
212 cm = 255 - qGreen(*s);
213 cy = 255 - qBlue(*s);
214 ck = qMin(qMin(cc, cm), cy);
215 d[0] = cc-ck;
216 d[1] = cm-ck;
217 d[2] = cy-ck;
218 d[3] = ck;
219 d[4] = 255;
220 }
221 else
222 {
223 d[0] = qRed(*s);
224 d[1] = qGreen(*s);
225 d[2] = qBlue(*s);
226 d[3] = 255;
227 }
228 s++;
229 d += r_image.channels();
230 }
231 }
232 m_imageInfoRecord.exifInfo.width = header.width;
233 m_imageInfoRecord.exifInfo.height = header.height;
234 return true;
235 }
236 }
237 m_imageInfoRecord.exifInfo.width = header.width;
238 m_imageInfoRecord.exifInfo.height = header.height;
239 m_imageInfoRecord.BBoxX = 0;
240 m_imageInfoRecord.BBoxH = r_image.height();
241 return true;
242 }
243 return false;
244 }
245
LoadPSD(QDataStream & s,const PSDHeader & header)246 bool ScImgDataLoader_PSD::LoadPSD( QDataStream & s, const PSDHeader & header)
247 {
248 // Create dst image.
249 m_imageInfoRecord.valid = false;
250 if (header.color_mode == CM_CMYK)
251 {
252 if (!r_image.create(header.width, header.height, 5))
253 return false;
254 m_pixelFormat = Format_CMYKA_8;
255 }
256 else
257 {
258 if (!r_image.create(header.width, header.height, 4))
259 return false;
260 m_pixelFormat = Format_RGBA_8;
261 }
262 r_image.fill(0);
263 m_maxChannels = header.channel_count;
264 uint tmp;
265 uint cresStart;
266 uint cdataStart;
267 uint resourceDataLen;
268 uint startResource;
269
270 cresStart = s.device()->pos();
271 // Skip mode data. FIX: this is incorrect, it's the Colormap Data for indexed Images
272 s >> tmp;
273 cdataStart = s.device()->pos();
274
275 LoadPSDResources(s, header, cresStart);
276
277 s.device()->seek( cdataStart + tmp );
278 s >> resourceDataLen;
279 startResource = s.device()->pos();
280
281 if ((!m_imageInfoRecord.exifInfo.thumbnail.isNull()) && (header.reserved[0] == 't'))
282 return true;
283 bool ret = LoadPSDImgData(s, header, startResource + resourceDataLen);
284 return ret;
285 }
286
LoadPSDResources(QDataStream & s,const PSDHeader & header,uint dataOffset)287 bool ScImgDataLoader_PSD::LoadPSDResources( QDataStream & s, const PSDHeader & header, uint dataOffset )
288 {
289 // Create dst image.
290 m_imageInfoRecord.valid = false;
291
292 uint tmp;
293 uint cdataStart;
294 uint resourceDataLen;
295 // uint startResource;
296
297 s.device()->seek( dataOffset );
298
299 srand(314159265);
300 for (int i = 0; i < 4096; i++)
301 m_random_table[i] = rand();
302 int tmpd;
303 int swap;
304 for (int i = 0; i < 4096; i++)
305 {
306 swap = i + rand() % (4096 - i);
307 tmpd = m_random_table[i];
308 m_random_table[i] = m_random_table[swap];
309 m_random_table[swap] = tmpd;
310 }
311 // Skip mode data. FIX: this is incorrect, it's the Colormap Data for indexed Images
312 s >> tmp;
313 cdataStart = s.device()->pos();
314 if (tmp != 0)
315 {
316 if ((header.color_mode == CM_DUOTONE))
317 {
318 short signature;
319 short count;
320 unsigned short c, m, y, k;
321 uchar hc, sc, bc;
322 ScColor col;
323 s >> signature;
324 s >> count;
325 uint duodataStart = s.device()->pos();
326 bool specialColour = false;
327 for (int cda = 0; cda < count; cda++)
328 {
329 s >> signature;
330 s >> c >> m >> y >> k;
331 switch (signature)
332 {
333 case 0: // RGB colour
334 col.setRgbColor(c >> 8, m >> 8, y >> 8);
335 m_colorTableSc.append(col);
336 break;
337 case 1: // HSB colour
338 hc = c >> 8;
339 sc = m >> 8;
340 bc = y >> 8;
341 HSVTORGB(hc, sc, bc);
342 col.setRgbColor(hc, sc, bc);
343 m_colorTableSc.append(col);
344 break;
345 case 2: // CMYK colour
346 col.setColor(c >> 8, m >> 8, y >> 8, k >> 8);
347 m_colorTableSc.append(col);
348 break;
349 case 3: // Pantone
350 case 4: // Focoltone
351 case 5: // Truematch
352 case 6: // Toyo 88 colorfinder 1050
353 case 7: // LAB colour space
354 case 10: // HKS colors
355 if (m_colorTableSc.count() == 0)
356 m_colorTableSc.append(ScColor(0, 0, 0, 255));
357 else
358 m_colorTableSc.append(ScColor(0, 0, 0, 0));
359 specialColour = true;
360 break;
361 case 8: // Grayscale
362 c = qRound((c / 10000.0) * 255);
363 m_colorTableSc.append(ScColor(0, 0, 0, c));
364 break;
365 }
366 }
367 if (specialColour) // we will only load the grayscale image data and do the colorizing with the Image Effects;
368 {
369 s.device()->seek( duodataStart + 40 );
370 uint duoNameStart = s.device()->pos();
371 uint duoCurveStart = duoNameStart+256;
372 for (int cda = 0; cda < count; cda++)
373 {
374 QString colName;
375 s.device()->seek( duoNameStart + (64 * static_cast<uint>(cda)) );
376 colName = getPascalString(s);
377 s.device()->seek( duoCurveStart + (28 * static_cast<uint>(cda)) );
378 FPointArray tmcu;
379 tmcu.resize(0);
380 for (int cu = 0; cu < 13; cu++)
381 {
382 short val;
383 s >> val;
384 if (val != -1)
385 tmcu.addPoint(cu * 1.0 / 12.0, val / 1000.0);
386 }
387 PSDDuotone_Color colSpec;
388 colSpec.Name = colName;
389 colSpec.Color = m_colorTableSc[cda];
390 colSpec.Curve = tmcu;
391 m_imageInfoRecord.duotoneColors.append(colSpec);
392 }
393 // Initialize loading curve tables with default values
394 m_curveTable1.resize(256);
395 m_curveTable2.resize(256);
396 m_curveTable3.resize(256);
397 m_curveTable4.resize(256);
398 for (int x = 0 ; x < 256 ; x++)
399 {
400 m_curveTable1[x] = x;
401 m_curveTable2[x] = x;
402 m_curveTable3[x] = x;
403 m_curveTable4[x] = x;
404 }
405 }
406 else
407 {
408 s.device()->seek( duodataStart + 40 );
409 uint duoNameStart = s.device()->pos();
410 uint duoCurveStart = duoNameStart+256;
411 for (int cda = 0; cda < count; cda++)
412 {
413 s.device()->seek( duoCurveStart + (28 * static_cast<uint>(cda)) );
414 FPointArray tmcu;
415 tmcu.resize(0);
416 for (int cu = 0; cu < 13; cu++)
417 {
418 short val;
419 s >> val;
420 if (val != -1)
421 tmcu.addPoint(cu * 1.0 / 12.0, val / 1000.0);
422 }
423 if (cda == 0)
424 {
425 m_curveTable1.resize(256);
426 for (int x = 0 ; x < 256 ; x++)
427 {
428 m_curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
429 }
430 }
431 else if (cda == 1)
432 {
433 m_curveTable2.resize(256);
434 for (int x = 0 ; x < 256 ; x++)
435 {
436 m_curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
437 }
438 }
439 else if (cda == 2)
440 {
441 m_curveTable3.resize(256);
442 for (int x = 0 ; x < 256 ; x++)
443 {
444 m_curveTable3[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
445 }
446 }
447 else if (cda == 3)
448 {
449 m_curveTable4.resize(256);
450 for (int x = 0 ; x < 256 ; x++)
451 {
452 m_curveTable4[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
453 }
454 }
455 }
456 }
457 }
458 else
459 {
460 QList<uchar> colorTableR;
461 QList<uchar> colorTableG;
462 QList<uchar> colorTableB;
463 colorTableR.reserve(256);
464 colorTableG.reserve(256);
465 colorTableB.reserve(256);
466 m_colorTable.clear();
467 m_colorTable.reserve(256);
468 uchar r;
469 for (uint cc = 0; cc < 256; cc++)
470 {
471 s >> r;
472 colorTableR.append(r);
473 }
474 for (uint cc = 0; cc < 256; cc++)
475 {
476 s >> r;
477 colorTableG.append(r);
478 }
479 for (uint cc = 0; cc < 256; cc++)
480 {
481 s >> r;
482 colorTableB.append(r);
483 }
484 for (uint cc = 0; cc < 256; cc++)
485 {
486 m_colorTable.append(qRgb(colorTableR[cc], colorTableG[cc], colorTableB[cc]));
487 }
488 }
489 }
490 s.device()->seek( cdataStart + tmp );
491 s >> resourceDataLen;
492 // startResource = s.device()->pos();
493 if (resourceDataLen != 0)
494 parseResourceData(s, header, resourceDataLen);
495 return true;
496 }
497
LoadPSDImgData(QDataStream & s,const PSDHeader & header,uint dataOffset)498 bool ScImgDataLoader_PSD::LoadPSDImgData( QDataStream & s, const PSDHeader & header, uint dataOffset )
499 {
500 uint layerDataLen;
501 uint startLayers;
502 s.device()->seek( dataOffset );
503 // Skip the reserved data. FIX: Also incorrect, this is the actual Layer Data for Images with Layers
504 s >> layerDataLen;
505 startLayers = s.device()->pos();
506 if (layerDataLen != 0)
507 {
508 bool re = parseLayer(s, header);
509 if (re)
510 {
511 m_imageInfoRecord.valid = true;
512 return re;
513 }
514 // Try to decode simple psd file, no layers
515 s.device()->seek(startLayers + layerDataLen);
516 if (s.atEnd())
517 return false;
518 return loadLayer( s, header);
519 }
520 // Decoding simple psd file, no layers
521 s.device()->seek( s.device()->pos() + layerDataLen );
522 loadLayer( s, header);
523 return true;
524 }
525
parseLayer(QDataStream & s,const PSDHeader & header)526 bool ScImgDataLoader_PSD::parseLayer( QDataStream & s, const PSDHeader & header )
527 {
528 uint addRes, layerinfo, channelLen, signature, extradata, layermasksize, layerRange, dummy;
529 int top, left, bottom, right;
530 short numLayers, numChannels;
531 short channelType;
532 uchar blendKey[4];
533 uchar opacity, clipping, flags, filler;
534 QString blend;
535 struct PSDLayer lay;
536 s >> layerinfo;
537 s >> numLayers;
538 if (numLayers < 0)
539 numLayers = -numLayers;
540 if (numLayers != 0)
541 {
542 for (int layer = 0; layer < numLayers; layer++)
543 {
544 s >> top;
545 lay.ypos = top;
546 s >> left;
547 lay.xpos = left;
548 s >> bottom;
549 lay.height = bottom - top;
550 s >> right;
551 lay.width = right - left;
552 s >> numChannels;
553 // Qt4 check these conversions
554 m_maxChannels = qMax(m_maxChannels, (int)numChannels);
555 if (numChannels > 6) // we don't support images with more than 6 channels yet
556 {
557 m_imageInfoRecord.layerInfo.clear();
558 return false;
559 }
560 lay.channelType.clear();
561 lay.channelLen.clear();
562 for (int channels = 0; channels < numChannels; channels++)
563 {
564 s >> channelType;
565 s >> channelLen;
566 lay.channelType.append(channelType);
567 lay.channelLen.append(channelLen);
568 }
569 s >> signature;
570 blend = "";
571 for (int i = 0; i < 4; i++)
572 {
573 s >> blendKey[i];
574 blend += QChar(blendKey[i]);
575 }
576 lay.blend = blend;
577 s >> opacity;
578 lay.opacity = opacity;
579 s >> clipping;
580 lay.clipping = clipping;
581 s >> flags;
582 if (flags & 8)
583 {
584 if (flags & 16) // Unknown combination of layer flags, probably an adjustment or effects layer
585 {
586 m_imageInfoRecord.layerInfo.clear();
587 return false;
588 }
589 }
590 lay.flags = flags;
591 s >> filler;
592 s >> extradata;
593 s >> layermasksize;
594 lay.maskYpos = 0;
595 lay.maskXpos = 0;
596 lay.maskHeight = 0;
597 lay.maskWidth = 0;
598 if (layermasksize != 0)
599 {
600 s >> lay.maskYpos;
601 s >> lay.maskXpos;
602 s >> dummy;
603 lay.maskHeight = dummy - lay.maskYpos;
604 s >> dummy;
605 lay.maskWidth = dummy - lay.maskXpos;
606 s >> dummy;
607 }
608 s >> layerRange;
609 s.device()->seek( s.device()->pos() + layerRange );
610 lay.layerName = getLayerString(s);
611 m_imageInfoRecord.layerInfo.append(lay);
612 s >> signature;
613 if (signature == 0x3842494D)
614 {
615 while (signature == 0x3842494D )
616 {
617 s >> signature;
618 s >> addRes;
619 s.device()->seek( s.device()->pos() + addRes );
620 s >> signature;
621 }
622 s.device()->seek( s.device()->pos() - 4 );
623 }
624 else
625 {
626 s.device()->seek( s.device()->pos() - 2 );
627 s >> signature;
628 if (signature == 0x3842494D)
629 {
630 while (signature == 0x3842494D )
631 {
632 s >> signature;
633 s >> addRes;
634 s.device()->seek( s.device()->pos() + addRes );
635 s >> signature;
636 }
637 s.device()->seek( s.device()->pos() - 4 );
638 }
639 else
640 s.device()->seek( s.device()->pos() - 6 );
641 }
642 }
643 bool firstLayer = true;
644 for (int layer = 0; layer < numLayers; layer++)
645 {
646 loadLayerChannels( s, header, m_imageInfoRecord.layerInfo, layer, &firstLayer );
647 }
648 }
649 else
650 {
651 s >> numLayers;
652 if (numLayers == 0)
653 return false;
654 loadLayer( s, header);
655 }
656 return true;
657 }
658
loadChannel(QDataStream & s,const PSDHeader & header,QList<PSDLayer> & layerInfo,uint layer,int channel,int component,RawImage & tmpImg)659 bool ScImgDataLoader_PSD::loadChannel( QDataStream & s, const PSDHeader & header, QList<PSDLayer> &layerInfo, uint layer, int channel, int component, RawImage &tmpImg)
660 {
661 uint base = s.device()->pos();
662 uchar cbyte;
663 ushort compression;
664 s >> compression;
665 if (compression > 1)
666 return false;
667 if (compression == 0)
668 {
669 int count = layerInfo[layer].channelLen[channel]-2;
670 uchar *ptr;
671 for (int i = 0; i < tmpImg.height(); i++)
672 {
673 ptr = tmpImg.scanLine(i);
674 for (int j = 0; j < tmpImg.width(); j++)
675 {
676 s >> cbyte;
677 count--;
678 if ((header.color_mode == CM_CMYK) && (component < 4))
679 cbyte = 255 - cbyte;
680 if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
681 {
682 ptr[0] = cbyte;
683 ptr[1] = cbyte;
684 ptr[2] = cbyte;
685 }
686 else if ((header.color_mode == CM_DUOTONE) && (component != 3))
687 {
688 ptr -= component;
689 putDuotone(ptr, cbyte);
690 ptr += component;
691 }
692 else if ((header.color_mode == CM_INDEXED) && (component != 3))
693 {
694 int ccol = m_colorTable[cbyte];
695 ptr[0] = qRed(ccol);
696 ptr[1] = qGreen(ccol);
697 ptr[2] = qBlue(ccol);
698 }
699 else
700 ptr[component] = cbyte;
701 if (count == 0)
702 break;
703 ptr += tmpImg.channels();
704 }
705 if (count == 0)
706 break;
707 }
708 }
709 else
710 {
711 s.device()->seek( s.device()->pos() + tmpImg.height() * 2 );
712 uint pixel_count = tmpImg.width();
713 uchar *ptr;
714 uchar *ptr2;
715 uint count, len;
716 uchar c;
717 for (int hh = 0; hh < tmpImg.height(); hh++)
718 {
719 count = 0;
720 ptr = tmpImg.scanLine(hh);
721 ptr2 = ptr+tmpImg.width() * tmpImg.channels();
722 ptr += component;
723 while (count < pixel_count)
724 {
725 if (s.atEnd())
726 return false;
727 s >> c;
728 len = c;
729 if (len < 128)
730 {
731 // Copy next len+1 bytes literally.
732 len++;
733 count += len;
734 while (len != 0)
735 {
736 s >> cbyte;
737 if (ptr < ptr2)
738 {
739 if ((header.color_mode == CM_CMYK) && (component < 4))
740 cbyte = 255 - cbyte;
741 if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
742 {
743 ptr -= component;
744 ptr[0] = cbyte;
745 ptr[1] = cbyte;
746 ptr[2] = cbyte;
747 ptr += component;
748 }
749 else if ((header.color_mode == CM_DUOTONE) && (component != 3))
750 {
751 ptr -= component;
752 putDuotone(ptr, cbyte);
753 ptr += component;
754 }
755 else if ((header.color_mode == CM_INDEXED) && (component != 3))
756 {
757 ptr -= component;
758 int ccol = m_colorTable[cbyte];
759 ptr[0] = qRed(ccol);
760 ptr[1] = qGreen(ccol);
761 ptr[2] = qBlue(ccol);
762 ptr += component;
763 }
764 else
765 {
766 *ptr = cbyte;
767 }
768 }
769 ptr += tmpImg.channels();
770 len--;
771 }
772 }
773 else if (len > 128)
774 {
775 // Next -len+1 bytes in the dest are replicated from next source byte.
776 // (Interpret len as a negative 8-bit int.)
777 len ^= 0xFF;
778 len += 2;
779 count += len;
780 uchar val;
781 s >> val;
782 if ((header.color_mode == CM_CMYK) && (component < 4))
783 val = 255 - val;
784 while (len != 0)
785 {
786 if (ptr < ptr2)
787 {
788 if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
789 {
790 ptr -= component;
791 ptr[0] = val;
792 ptr[1] = val;
793 ptr[2] = val;
794 ptr += component;
795 }
796 else if ((header.color_mode == CM_DUOTONE) && (component != 3))
797 {
798 ptr -= component;
799 putDuotone(ptr, val);
800 ptr += component;
801 }
802 else if ((header.color_mode == CM_INDEXED) && (component != 3))
803 {
804 ptr -= component;
805 int ccol = m_colorTable[val];
806 ptr[0] = qRed(ccol);
807 ptr[1] = qGreen(ccol);
808 ptr[2] = qBlue(ccol);
809 ptr += component;
810 }
811 else
812 *ptr = val;
813 }
814 ptr += tmpImg.channels();
815 len--;
816 }
817 }
818 else if (len == 128)
819 {
820 // No-op.
821 }
822 }
823 }
824 }
825 s.device()->seek( base+layerInfo[layer].channelLen[channel] );
826 return true;
827 }
828
loadLayerChannels(QDataStream & s,const PSDHeader & header,QList<PSDLayer> & layerInfo,uint layer,bool * firstLayer)829 bool ScImgDataLoader_PSD::loadLayerChannels( QDataStream & s, const PSDHeader & header, QList<PSDLayer> &layerInfo, uint layer, bool* firstLayer)
830 {
831 // Find out if the data is compressed.
832 // Known values:
833 // 0: no compression
834 // 1: RLE compressed
835 uint base = s.device()->pos();
836 uint base2 = base;
837 uint channel_num = layerInfo[layer].channelLen.count();
838 bool hasMask = false;
839 bool hasAlpha = false;
840 RawImage r2_image;
841 RawImage mask;
842 bool createOk = false;
843 ScColorMgmtEngine engine(ScCore->defaultEngine);
844 if (header.color_mode == CM_CMYK)
845 {
846 createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, qMax(channel_num, (uint)5));
847 r2_image.fill(0);
848 }
849 else
850 {
851 createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, qMax(channel_num, (uint)4));
852 r2_image.fill(0);
853 }
854 if (!createOk)
855 {
856 for (uint channel = 0; channel < channel_num; channel++)
857 {
858 base2 += layerInfo[layer].channelLen[channel];
859 }
860 s.device()->seek( base2 );
861 return false;
862 }
863 channel_num = qMin(channel_num, (uint)39);
864 uint components[40];
865 for (uint channel = 0; channel < channel_num; channel++)
866 {
867 switch (layerInfo[layer].channelType[channel])
868 {
869 case 0:
870 components[channel] = 0;
871 break;
872 case 1:
873 components[channel] = 1;
874 break;
875 case 2:
876 components[channel] = 2;
877 break;
878 case 3:
879 components[channel] = 3;
880 break;
881 case -1:
882 if (header.color_mode == CM_CMYK)
883 {
884 if (channel_num == 6)
885 components[channel] = channel_num-2;
886 else
887 components[channel] = channel_num-1;
888 }
889 else
890 {
891 if (channel_num == 5)
892 components[channel] = channel_num-2;
893 else
894 {
895 if (header.color_mode == CM_GRAYSCALE)
896 components[channel] = 3;
897 else
898 components[channel] = channel_num-1;
899 }
900 }
901 hasAlpha = true;
902 break;
903 case -2:
904 components[channel] = channel_num-1;
905 break;
906 }
907 }
908 if (!hasAlpha)
909 r2_image.fill('\xff');
910 for (uint channel = 0; channel < channel_num; channel++)
911 {
912 if (layerInfo[layer].channelType[channel] == -2)
913 {
914 if (!mask.create( layerInfo[layer].maskWidth, layerInfo[layer].maskHeight, 1 ))
915 break;
916 mask.fill(0);
917 if (!loadChannel(s, header, layerInfo, layer, channel, 0, mask))
918 break;
919 hasMask = true;
920 }
921 if (!loadChannel(s, header, layerInfo, layer, channel, components[channel], r2_image))
922 break;
923 }
924 for (uint channel = 0; channel < channel_num; channel++)
925 {
926 base2 += layerInfo[layer].channelLen[channel];
927 }
928 if (header.color_mode == CM_LABCOLOR)
929 {
930 ScColorProfile hsRGB = engine.createProfile_sRGB();
931 ScColorProfile hLab = engine.createProfile_Lab();
932 ScColorTransform xform = engine.createTransform(hLab, Format_LabA_8, hsRGB, Format_RGBA_8, Intent_Perceptual, 0);
933 for (int i = 0; i < r2_image.height(); i++)
934 {
935 uchar* ptr = r2_image.scanLine(i);
936 xform.apply(ptr, ptr, r2_image.width());
937 }
938 }
939 s.device()->seek( base2 );
940 QImage tmpImg2;
941 if (header.color_mode == CM_CMYK)
942 tmpImg2 = r2_image.convertToQImage(true);
943 else
944 tmpImg2 = r2_image.convertToQImage(false);
945 QImage imt;
946 double sx = tmpImg2.width() / 40.0;
947 double sy = tmpImg2.height() / 40.0;
948 imt = sy < sx ? tmpImg2.scaled(qRound(tmpImg2.width() / sx), qRound(tmpImg2.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) :
949 tmpImg2.scaled(qRound(tmpImg2.width() / sy), qRound(tmpImg2.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
950 layerInfo[layer].thumb = imt.copy();
951 if (hasMask)
952 {
953 QImage imt2;
954 QImage tmpImg;
955 tmpImg = mask.convertToQImage(true);
956 double sx = tmpImg.width() / 40.0;
957 double sy = tmpImg.height() / 40.0;
958 imt2 = sy < sx ? tmpImg.scaled(qRound(tmpImg.width() / sx), qRound(tmpImg.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) :
959 tmpImg.scaled(qRound(tmpImg.width() / sy), qRound(tmpImg.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
960 imt2.invertPixels();
961 layerInfo[layer].thumb_mask = imt2.copy();
962 }
963 else
964 layerInfo[layer].thumb_mask = QImage();
965 if (!m_imageInfoRecord.isRequest || !m_imageInfoRecord.RequestProps.contains(layer))
966 m_imageInfoRecord.RequestProps[layer].useMask = true;
967 bool visible = !(layerInfo[layer].flags & 2);
968 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
969 visible = m_imageInfoRecord.RequestProps[layer].visible;
970 if (visible)
971 {
972 unsigned int startSrcY, startSrcX, startDstY, startDstX;
973 if (layerInfo[layer].ypos < 0)
974 {
975 startSrcY = abs(layerInfo[layer].ypos);
976 startDstY = 0;
977 }
978 else
979 {
980 startSrcY = 0;
981 startDstY = layerInfo[layer].ypos;
982 }
983 if (layerInfo[layer].xpos < 0)
984 {
985 startSrcX = abs(layerInfo[layer].xpos);
986 startDstX = 0;
987 }
988 else
989 {
990 startSrcX = 0;
991 startDstX = layerInfo[layer].xpos;
992 }
993 unsigned int startSrcXm; //, startSrcYm, startDstYm, startDstXm;
994 /* if (layerInfo[layer].maskYpos < 0)
995 {
996 startSrcYm = abs(layerInfo[layer].maskYpos);
997 startDstYm = 0;
998 }
999 else
1000 {
1001 startSrcYm = 0;
1002 startDstYm = layerInfo[layer].maskYpos;
1003 }*/
1004 if (layerInfo[layer].maskXpos < 0)
1005 {
1006 startSrcXm = abs(layerInfo[layer].maskXpos);
1007 // startDstXm = 0;
1008 }
1009 else
1010 {
1011 startSrcXm = 0;
1012 // startDstXm = layerInfo[layer].maskXpos;
1013 }
1014 QString layBlend2 = layerInfo[layer].blend;
1015 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
1016 layBlend2 = m_imageInfoRecord.RequestProps[layer].blend;
1017 if (layBlend2 == QLatin1String("diss"))
1018 {
1019 hasAlpha = true;
1020 int layOpa = layerInfo[layer].opacity;
1021 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
1022 layOpa = m_imageInfoRecord.RequestProps[layer].opacity;
1023 for (int l = 0; l < r2_image.height(); l++)
1024 {
1025 srand(m_random_table[ l % 4096]);
1026 for (int k = 0; k < r2_image.width(); k++)
1027 {
1028 int rand_val = rand() & 0xff;
1029 if (rand_val > layOpa)
1030 r2_image.setAlpha(k, l, 0);
1031 }
1032 }
1033 }
1034 if (*firstLayer)
1035 {
1036 unsigned char *s;
1037 unsigned char *d;
1038 for (int yi=static_cast<int>(startSrcY); yi < qMin(r2_image.height(), r_image.height()); ++yi)
1039 {
1040 s = r2_image.scanLine( yi );
1041 d = r_image.scanLine( qMin(static_cast<int>(startDstY), r_image.height()-1) );
1042 d += qMin(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels();
1043 s += qMin(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels();
1044 for (int xi=static_cast<int>(startSrcX); xi < qMin(r2_image.width(), r_image.width()); ++xi)
1045 {
1046 d[0] = s[0];
1047 d[1] = s[1];
1048 d[2] = s[2];
1049 if (header.color_mode != CM_CMYK)
1050 {
1051 if (hasAlpha)
1052 d[3] = s[3];
1053 else
1054 d[3] = 255;
1055 }
1056 else
1057 {
1058 d[3] = s[3];
1059 if (hasAlpha)
1060 d[4] = s[4];
1061 else
1062 d[4] = 255;
1063 }
1064 s += r2_image.channels();
1065 d += r_image.channels();
1066 }
1067 startDstY++;
1068 }
1069 }
1070 else
1071 {
1072 unsigned char *s;
1073 unsigned char *d;
1074 unsigned char *sm = nullptr;
1075 unsigned char r, g, b, src_r, src_g, src_b, src_a, src_alpha, dst_alpha;
1076 unsigned char a = 0;
1077 uchar new_r, new_g, new_b;
1078 unsigned int maxDestX;
1079 for (int i = static_cast<int>(startSrcY); i < layerInfo[layer].height; i++)
1080 {
1081 d = r_image.scanLine(qMin(static_cast<int>(startDstY), r_image.height()-1));
1082 s = r2_image.scanLine(qMin(i, r2_image.height()-1));
1083 d += qMin(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels();
1084 s += qMin(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels();
1085 sm = nullptr;
1086 if (hasMask)
1087 {
1088 sm = mask.scanLine(qMin(i, mask.height()-1));
1089 sm += qMin(static_cast<int>(startSrcXm), mask.width()-1) * mask.channels();
1090 }
1091 startDstY++;
1092 maxDestX = r_image.width() - startDstX + startSrcX - 1;
1093 for (unsigned int j = startSrcX; j < qMin(maxDestX, static_cast<unsigned int>(layerInfo[layer].width)); j++)
1094 {
1095 src_r = s[0];
1096 src_g = s[1];
1097 src_b = s[2];
1098 src_a = s[3];
1099 if (hasAlpha)
1100 {
1101 if (hasMask)
1102 {
1103 if (m_imageInfoRecord.RequestProps[layer].useMask)
1104 src_alpha = sm[0];
1105 else
1106 src_alpha = s[channel_num - 2];
1107 }
1108 else
1109 {
1110 if (header.color_mode == CM_GRAYSCALE)
1111 src_alpha = s[3];
1112 else
1113 src_alpha = s[channel_num - 1];
1114 }
1115 }
1116 else
1117 src_alpha = 255;
1118 if ((hasMask) && (m_imageInfoRecord.RequestProps[layer].useMask))
1119 src_alpha = sm[0];
1120 int layOpa = layerInfo[layer].opacity;
1121 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
1122 layOpa = m_imageInfoRecord.RequestProps[layer].opacity;
1123 QString layBlend = layerInfo[layer].blend;
1124 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
1125 layBlend = m_imageInfoRecord.RequestProps[layer].blend;
1126 if (layBlend != QLatin1String("diss"))
1127 src_alpha = INT_MULT(src_alpha, layOpa);
1128 if (header.color_mode == CM_CMYK)
1129 dst_alpha = d[4];
1130 else
1131 dst_alpha = d[3];
1132 if ((dst_alpha > 0) && (src_alpha > 0))
1133 {
1134 if (layBlend == QLatin1String("mul "))
1135 {
1136 src_r = INT_MULT(src_r, d[0]);
1137 src_g = INT_MULT(src_g, d[1]);
1138 src_b = INT_MULT(src_b, d[2]);
1139 if (header.color_mode == CM_CMYK)
1140 src_a = INT_MULT(src_a, d[3]);
1141 }
1142 else if (layBlend == QLatin1String("scrn"))
1143 {
1144 src_r = 255 - ((255-src_r) * (255-d[0]) / 128);
1145 src_g = 255 - ((255-src_g) * (255-d[1]) / 128);
1146 src_b = 255 - ((255-src_b) * (255-d[2]) / 128);
1147 if (header.color_mode == CM_CMYK)
1148 src_a = 255 - ((255-src_a) * (255-d[3]) / 128);
1149 }
1150 else if (layBlend == QLatin1String("over"))
1151 {
1152 src_g = d[1] < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128);
1153 src_b = d[2] < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128);
1154 src_a = d[3] < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128);
1155 if (header.color_mode == CM_CMYK)
1156 src_r = d[0] < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128);
1157 }
1158 else if (layBlend == QLatin1String("diff"))
1159 {
1160 src_r = d[0] > src_r ? d[0] - src_r : src_r - d[0];
1161 src_g = d[1] > src_g ? d[1] - src_g : src_g - d[1];
1162 src_b = d[2] > src_b ? d[2] - src_b : src_b - d[2];
1163 if (header.color_mode == CM_CMYK)
1164 src_a = d[3] > src_a ? d[3] - src_a : src_a - d[3];
1165 }
1166 else if (layBlend == QLatin1String("dark"))
1167 {
1168 src_r = d[0] < src_r ? d[0] : src_r;
1169 src_g = d[1] < src_g ? d[1] : src_g;
1170 src_b = d[2] < src_b ? d[2] : src_b;
1171 if (header.color_mode == CM_CMYK)
1172 src_a = d[3] < src_a ? d[3] : src_a;
1173 }
1174 else if (layBlend == QLatin1String("hLit"))
1175 {
1176 src_r = src_r < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128);
1177 src_g = src_g < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128);
1178 src_b = src_b < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128);
1179 if (header.color_mode == CM_CMYK)
1180 src_a = src_a < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128);
1181 }
1182 else if (layBlend == QLatin1String("sLit"))
1183 {
1184 src_r = src_r * d[0] / 256 + src_r * (255 - ((255-src_r)*(255-d[0]) / 256) - src_r * d[0] / 256) / 256;
1185 src_g = src_g * d[1] / 256 + src_g * (255 - ((255-src_g)*(255-d[1]) / 256) - src_g * d[1] / 256) / 256;
1186 src_b = src_b * d[2] / 256 + src_b * (255 - ((255-src_b)*(255-d[2]) / 256) - src_b * d[2] / 256) / 256;
1187 if (header.color_mode == CM_CMYK)
1188 src_a = src_a * d[3] / 256 + src_a * (255 - ((255-src_a)*(255-d[3]) / 256) - src_a * d[3] / 256) / 256;
1189 }
1190 else if (layBlend == QLatin1String("lite"))
1191 {
1192 src_r = d[0] < src_r ? src_r : d[0];
1193 src_g = d[1] < src_g ? src_g : d[1];
1194 src_b = d[2] < src_b ? src_b : d[2];
1195 if (header.color_mode == CM_CMYK)
1196 src_a = d[3] < src_a ? src_a : d[3];
1197 }
1198 else if (layBlend == QLatin1String("smud"))
1199 {
1200 src_r = d[0] + src_r - src_r * d[0] / 128;
1201 src_g = d[1] + src_g - src_g * d[1] / 128;
1202 src_b = d[2] + src_b - src_b * d[2] / 128;
1203 if (header.color_mode == CM_CMYK)
1204 src_a = d[3] + src_a - src_a * d[3] / 128;
1205 }
1206 else if (layBlend == QLatin1String("div "))
1207 {
1208 src_r = src_r == 255 ? 255 : ((d[0] * 256) / (255-src_r)) > 255 ? 255 : (d[0] * 256) / (255-src_r);
1209 src_g = src_g == 255 ? 255 : ((d[1] * 256) / (255-src_g)) > 255 ? 255 : (d[1] * 256) / (255-src_g);
1210 src_b = src_b == 255 ? 255 : ((d[2] * 256) / (255-src_b)) > 255 ? 255 : (d[2] * 256) / (255-src_b);
1211 if (header.color_mode == CM_CMYK)
1212 src_a = src_a == 255 ? 255 : ((d[3] * 256) / (255-src_a)) > 255 ? 255 : (d[3] * 256) / (255-src_a);
1213 }
1214 else if (layBlend == QLatin1String("idiv"))
1215 {
1216 src_r = src_r == 0 ? 0 : (255 - (((255-d[0]) * 256) / src_r)) < 0 ? 0 : 255 - (((255-d[0]) * 256) / src_r);
1217 src_g = src_g == 0 ? 0 : (255 - (((255-d[1]) * 256) / src_g)) < 0 ? 0 : 255 - (((255-d[1]) * 256) / src_g);
1218 src_b = src_b == 0 ? 0 : (255 - (((255-d[2]) * 256) / src_b)) < 0 ? 0 : 255 - (((255-d[2]) * 256) / src_b);
1219 if (header.color_mode == CM_CMYK)
1220 src_a = src_a == 0 ? 0 : (255 - (((255-d[3]) * 256) / src_a)) < 0 ? 0 : 255 - (((255-d[3]) * 256) / src_a);
1221 }
1222 else if (layBlend == QLatin1String("hue "))
1223 {
1224 if (header.color_mode != CM_CMYK)
1225 {
1226 new_r = d[0];
1227 new_g = d[1];
1228 new_b = d[2];
1229 RGBTOHSV(src_r, src_g, src_b);
1230 RGBTOHSV(new_r, new_g, new_b);
1231 new_r = src_r;
1232 HSVTORGB(new_r, new_g, new_b);
1233 src_r = new_r;
1234 src_g = new_g;
1235 src_b = new_b;
1236 }
1237 }
1238 else if (layBlend == QLatin1String("sat "))
1239 {
1240 if (header.color_mode != CM_CMYK)
1241 {
1242 new_r = d[0];
1243 new_g = d[1];
1244 new_b = d[2];
1245 RGBTOHSV(src_r, src_g, src_b);
1246 RGBTOHSV(new_r, new_g, new_b);
1247 new_g = src_g;
1248 HSVTORGB(new_r, new_g, new_b);
1249 src_r = new_r;
1250 src_g = new_g;
1251 src_b = new_b;
1252 }
1253 }
1254 else if (layBlend == QLatin1String("lum "))
1255 {
1256 if (header.color_mode != CM_CMYK)
1257 {
1258 new_r = d[0];
1259 new_g = d[1];
1260 new_b = d[2];
1261 RGBTOHSV(src_r, src_g, src_b);
1262 RGBTOHSV(new_r, new_g, new_b);
1263 new_b = src_b;
1264 HSVTORGB(new_r, new_g, new_b);
1265 src_r = new_r;
1266 src_g = new_g;
1267 src_b = new_b;
1268 }
1269 }
1270 else if (layBlend == QLatin1String("colr"))
1271 {
1272 if (header.color_mode != CM_CMYK)
1273 {
1274 new_r = d[0];
1275 new_g = d[1];
1276 new_b = d[2];
1277 RGBTOHLS(src_r, src_g, src_b);
1278 RGBTOHLS(new_r, new_g, new_b);
1279 new_r = src_r;
1280 new_b = src_b;
1281 HLSTORGB(new_r, new_g, new_b);
1282 src_r = new_r;
1283 src_g = new_g;
1284 src_b = new_b;
1285 }
1286 }
1287 }
1288 if (dst_alpha == 0)
1289 {
1290 r = src_r;
1291 g = src_g;
1292 b = src_b;
1293 a = src_a;
1294 }
1295 else
1296 {
1297 if (src_alpha > 0)
1298 {
1299 r = (d[0] * (255 - src_alpha) + src_r * src_alpha) / 255;
1300 g = (d[1] * (255 - src_alpha) + src_g * src_alpha) / 255;
1301 b = (d[2] * (255 - src_alpha) + src_b * src_alpha) / 255;
1302 if (header.color_mode == CM_CMYK)
1303 a = (d[3] * (255 - src_alpha) + src_a * src_alpha) / 255;
1304 if (layBlend != QLatin1String("diss"))
1305 src_alpha = dst_alpha + INT_MULT(255 - dst_alpha, src_alpha);
1306 }
1307 }
1308 if (src_alpha > 0)
1309 {
1310 d[0] = r;
1311 d[1] = g;
1312 d[2] = b;
1313 if (header.color_mode == CM_CMYK)
1314 {
1315 d[3] = a;
1316 d[4] = src_alpha;
1317 }
1318 else
1319 d[3] = src_alpha;
1320 }
1321 s += r2_image.channels();
1322 d += r_image.channels();
1323 if (hasMask)
1324 sm += mask.channels();
1325 }
1326 }
1327 }
1328 }
1329 *firstLayer = false;
1330 return true;
1331 }
1332
loadLayer(QDataStream & s,const PSDHeader & header)1333 bool ScImgDataLoader_PSD::loadLayer( QDataStream & s, const PSDHeader & header )
1334 {
1335 ScColorMgmtEngine engine(ScCore->defaultEngine);
1336 // Find out if the data is compressed.
1337 // Known values:
1338 // 0: no compression
1339 // 1: RLE compressed
1340 ushort compression;
1341 uchar cbyte;
1342 s >> compression;
1343 if (compression > 1)
1344 {
1345 // Unknown compression type.
1346 return false;
1347 }
1348 uint channel_num = header.channel_count;
1349 r_image.fill('\xff');
1350 const uint pixel_count = header.height * header.width;
1351 static const uint components[5] = {0, 1, 2, 3, 4};
1352 if (compression)
1353 {
1354 // Skip row lengths.
1355 ushort w;
1356 for (uint i = 0; i < header.height * header.channel_count; i++)
1357 {
1358 s >> w;
1359 }
1360 // Read RLE data.
1361 uchar * ptr;
1362 uint count = 0;
1363 uchar c;
1364 uint len;
1365 for (uint channel = 0; channel < channel_num; channel++)
1366 {
1367 ptr = r_image.bits() + components[channel];
1368 count = 0;
1369 while (count < pixel_count)
1370 {
1371 if (s.atEnd())
1372 return false;
1373 s >> c;
1374 len = c;
1375 if (len < 128)
1376 {
1377 // Copy next len+1 bytes literally.
1378 len++;
1379 count += len;
1380 if (count > pixel_count)
1381 return false;
1382 while (len != 0)
1383 {
1384 s >> cbyte;
1385 if ((header.color_mode == CM_CMYK) && (components[channel] < 4))
1386 cbyte = 255 - cbyte;
1387 if ((header.color_mode == CM_GRAYSCALE) && (components[channel] != 3))
1388 {
1389 ptr -= components[channel];
1390 ptr[0] = cbyte;
1391 ptr[1] = cbyte;
1392 ptr[2] = cbyte;
1393 ptr += components[channel];
1394 }
1395 else if ((header.color_mode == CM_DUOTONE) && (components[channel] != 3))
1396 {
1397 ptr -= components[channel];
1398 putDuotone(ptr, cbyte);
1399 ptr += components[channel];
1400 }
1401 else if ((header.color_mode == CM_INDEXED) && (components[channel] != 3))
1402 {
1403 ptr -= components[channel];
1404 int ccol = m_colorTable[cbyte];
1405 ptr[0] = qRed(ccol);
1406 ptr[1] = qGreen(ccol);
1407 ptr[2] = qBlue(ccol);
1408 ptr += components[channel];
1409 }
1410 else
1411 *ptr = cbyte;
1412 ptr += r_image.channels();
1413 len--;
1414 }
1415 }
1416 else if (len > 128)
1417 {
1418 // Next -len+1 bytes in the dest are replicated from next source byte.
1419 // (Interpret len as a negative 8-bit int.)
1420 len ^= 0xFF;
1421 len += 2;
1422 count += len;
1423 if (s.atEnd() || count > pixel_count)
1424 return false;
1425 uchar val;
1426 s >> val;
1427 if ((header.color_mode == CM_CMYK) && (components[channel] < 4))
1428 val = 255 - val;
1429 while (len != 0)
1430 {
1431 if ((header.color_mode == CM_GRAYSCALE) && (components[channel] != 3))
1432 {
1433 ptr -= components[channel];
1434 ptr[0] = val;
1435 ptr[1] = val;
1436 ptr[2] = val;
1437 ptr += components[channel];
1438 }
1439 else if ((header.color_mode == CM_DUOTONE) && (components[channel] != 3))
1440 {
1441 ptr -= components[channel];
1442 putDuotone(ptr, val);
1443 ptr += components[channel];
1444 }
1445 else if ((header.color_mode == CM_INDEXED) && (components[channel] != 3))
1446 {
1447 ptr -= components[channel];
1448 int ccol = m_colorTable[val];
1449 ptr[0] = qRed(ccol);
1450 ptr[1] = qGreen(ccol);
1451 ptr[2] = qBlue(ccol);
1452 ptr += components[channel];
1453 }
1454 else
1455 *ptr = val;
1456 ptr += r_image.channels();
1457 len--;
1458 }
1459 }
1460 else if (len == 128)
1461 {
1462 // No-op.
1463 }
1464 }
1465 }
1466 }
1467 else
1468 {
1469 // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
1470 // where each channel consists of an 8-bit value for each pixel in the image.
1471 // Read the data by channel.
1472 uchar * ptr;
1473 uint count = 0;
1474 for (uint channel = 0; channel < channel_num; channel++)
1475 {
1476 ptr = r_image.bits() + components[channel];
1477 // Read the data.
1478 count = pixel_count;
1479 while (count != 0)
1480 {
1481 s >> cbyte;
1482 if ((header.color_mode == CM_CMYK) && (components[channel] < 4))
1483 cbyte = 255 - cbyte;
1484 if ((header.color_mode == CM_GRAYSCALE) && (components[channel] != 3))
1485 {
1486 ptr -= components[channel];
1487 ptr[0] = cbyte;
1488 ptr[1] = cbyte;
1489 ptr[2] = cbyte;
1490 ptr += components[channel];
1491 }
1492 else if ((header.color_mode == CM_DUOTONE) && (components[channel] != 3))
1493 {
1494 ptr -= components[channel];
1495 putDuotone(ptr, cbyte);
1496 ptr += components[channel];
1497 }
1498 else if ((header.color_mode == CM_INDEXED) && (components[channel] != 3))
1499 {
1500 ptr -= components[channel];
1501 int ccol = m_colorTable[cbyte];
1502 ptr[0] = qRed(ccol);
1503 ptr[1] = qGreen(ccol);
1504 ptr[2] = qBlue(ccol);
1505 ptr += components[channel];
1506 }
1507 else
1508 *ptr = cbyte;
1509 ptr += r_image.channels();
1510 count--;
1511 }
1512 }
1513 }
1514 if (header.color_mode == CM_LABCOLOR)
1515 {
1516 ScColorProfile hsRGB = engine.createProfile_sRGB();
1517 ScColorProfile hLab = engine.createProfile_Lab();
1518 ScColorTransform xform = engine.createTransform(hLab, Format_LabA_8, hsRGB, Format_RGBA_8, Intent_Perceptual, 0);
1519 for (int i = 0; i < r_image.height(); i++)
1520 {
1521 uchar* ptr = r_image.scanLine(i);
1522 xform.apply(ptr, ptr, r_image.width());
1523 }
1524 }
1525 return true;
1526 }
1527
getLayerString(QDataStream & s)1528 QString ScImgDataLoader_PSD::getLayerString(QDataStream & s)
1529 {
1530 uchar len, tmp;
1531 uint adj;
1532 QString ret = "";
1533 s >> len;
1534 if (len == 0)
1535 {
1536 s >> tmp;
1537 s >> tmp;
1538 s >> tmp;
1539 return ret;
1540 }
1541 for (int i = 0; i < len; i++)
1542 {
1543 s >> tmp;
1544 ret += QChar(tmp);
1545 }
1546 adj = 0;
1547 if (((ret.length()+1) % 4) != 0)
1548 adj = 4 - ((ret.length()+1) % 4);
1549 s.device()->seek( s.device()->pos() + adj );
1550 return ret;
1551 }
1552
IsValid(const PSDHeader & header)1553 bool ScImgDataLoader_PSD::IsValid( const PSDHeader & header )
1554 {
1555 return header.signature == 0x38425053;
1556 }
1557
1558 // Check that the header is supported.
IsSupported(const PSDHeader & header)1559 bool ScImgDataLoader_PSD::IsSupported( const PSDHeader & header )
1560 {
1561 if ( header.version != 1 )
1562 return false;
1563 if ( header.channel_count > 16 )
1564 return false;
1565 if ( header.depth != 8 )
1566 return false;
1567 return (header.color_mode == CM_RGB) || (header.color_mode == CM_CMYK) || (header.color_mode == CM_LABCOLOR)
1568 || (header.color_mode == CM_GRAYSCALE) || (header.color_mode == CM_INDEXED) || (header.color_mode == CM_DUOTONE);
1569 }
1570
putDuotone(uchar * ptr,uchar cbyte)1571 void ScImgDataLoader_PSD::putDuotone(uchar *ptr, uchar cbyte)
1572 {
1573 CMYKColor cmyk;
1574 int c, c1, c2, c3, m, m1, m2, m3, y, y1, y2, y3, k, k1, k2, k3;
1575 uchar cb = 255 - cbyte;
1576 ScColor col;
1577 if (m_colorTableSc.count() == 1)
1578 {
1579 m_colorTableSc[0].getRawRGBColor(&c, &m, &y);
1580 ptr[0] = qMin((c * m_curveTable1[(int)cbyte]) >> 8, 255);
1581 ptr[1] = qMin((m * m_curveTable1[(int)cbyte]) >> 8, 255);
1582 ptr[2] = qMin((y * m_curveTable1[(int)cbyte]) >> 8, 255);
1583 }
1584 else if (m_colorTableSc.count() == 2)
1585 {
1586 ScColorEngine::getCMYKValues(m_colorTableSc[0], nullptr, cmyk);
1587 cmyk.getValues(c, m, y, k);
1588 c = qMin((c * m_curveTable1[(int)cb]) >> 8, 255);
1589 m = qMin((m * m_curveTable1[(int)cb]) >> 8, 255);
1590 y = qMin((y * m_curveTable1[(int)cb]) >> 8, 255);
1591 k = qMin((k * m_curveTable1[(int)cb]) >> 8, 255);
1592 ScColorEngine::getCMYKValues(m_colorTableSc[1], nullptr, cmyk);
1593 cmyk.getValues(c1, m1, y1, k1);
1594 c1 = qMin((c1 * m_curveTable2[(int)cb]) >> 8, 255);
1595 m1 = qMin((m1 * m_curveTable2[(int)cb]) >> 8, 255);
1596 y1 = qMin((y1 * m_curveTable2[(int)cb]) >> 8, 255);
1597 k1 = qMin((k1 * m_curveTable2[(int)cb]) >> 8, 255);
1598 col = ScColor(qMin(c+c1, 255), qMin(m+m1, 255), qMin(y+y1, 255), qMin(k+k1, 255));
1599 col.getRawRGBColor(&c, &m, &y);
1600 ptr[0] = c;
1601 ptr[1] = m;
1602 ptr[2] = y;
1603 }
1604 else if (m_colorTableSc.count() == 3)
1605 {
1606 ScColorEngine::getCMYKValues(m_colorTableSc[0], nullptr, cmyk);
1607 cmyk.getValues(c, m, y, k);
1608 c = qMin((c * m_curveTable1[(int)cb]) >> 8, 255);
1609 m = qMin((m * m_curveTable1[(int)cb]) >> 8, 255);
1610 y = qMin((y * m_curveTable1[(int)cb]) >> 8, 255);
1611 k = qMin((k * m_curveTable1[(int)cb]) >> 8, 255);
1612 ScColorEngine::getCMYKValues(m_colorTableSc[1], nullptr, cmyk);
1613 cmyk.getValues(c1, m1, y1, k1);
1614 c1 = qMin((c1 * m_curveTable2[(int)cb]) >> 8, 255);
1615 m1 = qMin((m1 * m_curveTable2[(int)cb]) >> 8, 255);
1616 y1 = qMin((y1 * m_curveTable2[(int)cb]) >> 8, 255);
1617 k1 = qMin((k1 * m_curveTable2[(int)cb]) >> 8, 255);
1618 ScColorEngine::getCMYKValues(m_colorTableSc[2], nullptr, cmyk);
1619 cmyk.getValues(c2, m2, y2, k2);
1620 c2 = qMin((c2 * m_curveTable3[(int)cb]) >> 8, 255);
1621 m2 = qMin((m2 * m_curveTable3[(int)cb]) >> 8, 255);
1622 y2 = qMin((y2 * m_curveTable3[(int)cb]) >> 8, 255);
1623 k2 = qMin((k2 * m_curveTable3[(int)cb]) >> 8, 255);
1624 col = ScColor(qMin(c+c1+c2, 255), qMin(m+m1+m2, 255), qMin(y+y1+y2, 255), qMin(k+k1+k2, 255));
1625 col.getRawRGBColor(&c, &m, &y);
1626 ptr[0] = c;
1627 ptr[1] = m;
1628 ptr[2] = y;
1629 }
1630 else if (m_colorTableSc.count() == 4)
1631 {
1632 ScColorEngine::getCMYKValues(m_colorTableSc[0], nullptr, cmyk);
1633 cmyk.getValues(c, m, y, k);
1634 c = qMin((c * m_curveTable1[(int)cb]) >> 8, 255);
1635 m = qMin((m * m_curveTable1[(int)cb]) >> 8, 255);
1636 y = qMin((y * m_curveTable1[(int)cb]) >> 8, 255);
1637 k = qMin((k * m_curveTable1[(int)cb]) >> 8, 255);
1638 ScColorEngine::getCMYKValues(m_colorTableSc[1], nullptr, cmyk);
1639 cmyk.getValues(c1, m1, y1, k1);
1640 c1 = qMin((c1 * m_curveTable2[(int)cb]) >> 8, 255);
1641 m1 = qMin((m1 * m_curveTable2[(int)cb]) >> 8, 255);
1642 y1 = qMin((y1 * m_curveTable2[(int)cb]) >> 8, 255);
1643 k1 = qMin((k1 * m_curveTable2[(int)cb]) >> 8, 255);
1644 ScColorEngine::getCMYKValues(m_colorTableSc[2], nullptr, cmyk);
1645 cmyk.getValues(c2, m2, y2, k2);
1646 c2 = qMin((c2 * m_curveTable3[(int)cb]) >> 8, 255);
1647 m2 = qMin((m2 * m_curveTable3[(int)cb]) >> 8, 255);
1648 y2 = qMin((y2 * m_curveTable3[(int)cb]) >> 8, 255);
1649 k2 = qMin((k2 * m_curveTable3[(int)cb]) >> 8, 255);
1650 ScColorEngine::getCMYKValues(m_colorTableSc[3], nullptr, cmyk);
1651 cmyk.getValues(c3, m3, y3, k3);
1652 c3 = qMin((c3 * m_curveTable4[(int)cb]) >> 8, 255);
1653 m3 = qMin((m3 * m_curveTable4[(int)cb]) >> 8, 255);
1654 y3 = qMin((y3 * m_curveTable4[(int)cb]) >> 8, 255);
1655 k3 = qMin((k3 * m_curveTable4[(int)cb]) >> 8, 255);
1656 col = ScColor(qMin(c+c1+c2+c3, 255), qMin(m+m1+m2+m3, 255), qMin(y+y1+y2+y3, 255), qMin(k+k1+k2+k3, 255));
1657 col.getRawRGBColor(&c, &m, &y);
1658 ptr[0] = c;
1659 ptr[1] = m;
1660 ptr[2] = y;
1661 }
1662 }
1663