00001
00002
00003
00004
00005
00006
00007 #include "scconfig.h"
00008 #include "scimgdataloader_psd.h"
00009 #include "util_color.h"
00010 #include "sccolorengine.h"
00011
00012 #include <QFile>
00013 #include <QFileInfo>
00014 #include <QList>
00015
00016 #include CMS_INC
00017
00018 static QDataStream & operator>> ( QDataStream & s, PSDHeader & header )
00019 {
00020 s >> header.signature;
00021 s >> header.version;
00022 for( int i = 0; i < 6; i++ )
00023 {
00024 s >> header.reserved[i];
00025 }
00026 s >> header.channel_count;
00027 s >> header.height;
00028 s >> header.width;
00029 s >> header.depth;
00030 s >> header.color_mode;
00031 return s;
00032 }
00033
00034 ScImgDataLoader_PSD::ScImgDataLoader_PSD(void)
00035 {
00036 initSupportedFormatList();
00037 }
00038
00039 void ScImgDataLoader_PSD::initSupportedFormatList(void)
00040 {
00041 m_supportedFormats.clear();
00042 m_supportedFormats.append( "psd" );
00043 }
00044
00045 void ScImgDataLoader_PSD::loadEmbeddedProfile(const QString& fn)
00046 {
00047 m_embeddedProfile.resize(0);
00048 m_profileComponents = 0;
00049 cmsHPROFILE prof = 0;
00050 QFileInfo fi = QFileInfo(fn);
00051 if (!fi.exists())
00052 return;
00053 QString ext = fi.suffix().toLower();
00054 if (ext == "psd")
00055 {
00056 QFile f(fn);
00057 if (f.open(QIODevice::ReadOnly))
00058 {
00059 m_imageInfoRecord.xres = 72;
00060 m_imageInfoRecord.yres = 72;
00061 QDataStream s( &f );
00062 s.setByteOrder( QDataStream::BigEndian );
00063 PSDHeader header;
00064 s >> header;
00065
00066 if( s.atEnd() || !IsValid( header ) )
00067 return;
00068
00069 if( !IsSupported( header ) )
00070 return;
00071 if( !LoadPSDResources(s, header, s.device()->pos()) )
00072 return;
00073 if (m_embeddedProfile.size() > 0)
00074 {
00075 prof = cmsOpenProfileFromMem(m_embeddedProfile.data(), m_embeddedProfile.size());
00076 if (prof)
00077 {
00078 if (static_cast<int>(cmsGetColorSpace(prof)) == icSigRgbData)
00079 m_profileComponents = 3;
00080 if (static_cast<int>(cmsGetColorSpace(prof)) == icSigCmykData)
00081 m_profileComponents = 4;
00082 }
00083 cmsCloseProfile(prof);
00084 }
00085 f.close();
00086 }
00087 else
00088 return;
00089 }
00090 }
00091
00092 bool ScImgDataLoader_PSD::preloadAlphaChannel(const QString& fn, int res, bool& hasAlpha)
00093 {
00094 bool valid = m_imageInfoRecord.isRequest;
00095 QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
00096 initialize();
00097 hasAlpha = false;
00098 m_imageInfoRecord.RequestProps = req;
00099 m_imageInfoRecord.isRequest = valid;
00100 QFileInfo fi = QFileInfo(fn);
00101 if (!fi.exists())
00102 return false;
00103
00104 QFile f(fn);
00105 if (f.open(QIODevice::ReadOnly))
00106 {
00107 QDataStream s( &f );
00108 s.setByteOrder( QDataStream::BigEndian );
00109 PSDHeader header;
00110 s >> header;
00111
00112 if( s.atEnd() || !IsValid( header ) )
00113 return false;
00114
00115 if( !IsSupported( header ) )
00116 return false;
00117 if( !LoadPSD(s, header) )
00118 r_image.resize(0);
00119 f.close();
00120 m_imageInfoRecord.valid = true;
00121 if (header.color_mode == CM_CMYK)
00122 {
00123 if ( maxChannels == 4)
00124 m_imageInfoRecord.valid = hasAlpha = false;
00125 }
00126 else
00127 {
00128 if ( maxChannels == 3)
00129 m_imageInfoRecord.valid = hasAlpha = false;
00130 }
00131 return true;
00132 }
00133 return false;
00134 }
00135
00136 bool ScImgDataLoader_PSD::loadPicture(const QString& fn, int res, bool thumbnail)
00137 {
00138 bool isCMYK = false;
00139 float xres = 72.0, yres = 72.0;
00140 if (!QFile::exists(fn))
00141 return false;
00142 bool valid = m_imageInfoRecord.isRequest;
00143 QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
00144 initialize();
00145 m_imageInfoRecord.RequestProps = req;
00146 m_imageInfoRecord.isRequest = valid;
00147 m_imageInfoRecord.type = ImageTypePSD;
00148 m_imageInfoRecord.exifDataValid = false;
00149 m_imageInfoRecord.layerInfo.clear();
00150 m_imageInfoRecord.PDSpathData.clear();
00151 QFile f(fn);
00152 if (f.open(QIODevice::ReadOnly))
00153 {
00154 m_imageInfoRecord.xres = 72;
00155 m_imageInfoRecord.yres = 72;
00156 QDataStream s( &f );
00157 s.setByteOrder( QDataStream::BigEndian );
00158 PSDHeader header;
00159 s >> header;
00160
00161 if( s.atEnd() || !IsValid( header ) )
00162 return false;
00163
00164 if( !IsSupported( header ) )
00165 return false;
00166 if (thumbnail)
00167 header.reserved[0] = 't';
00168 if( !LoadPSD(s, header) )
00169 return false;
00170 if (m_embeddedProfile.size() > 0)
00171 {
00172 cmsHPROFILE prof = cmsOpenProfileFromMem(m_embeddedProfile.data(), m_embeddedProfile.size());
00173 const char *Descriptor;
00174 Descriptor = cmsTakeProductDesc(prof);
00175 m_imageInfoRecord.profileName = QString(Descriptor);
00176 m_imageInfoRecord.isEmbedded = true;
00177 }
00178 if (header.color_mode == CM_CMYK)
00179 isCMYK = true;
00180 else
00181 isCMYK = false;
00182 if (header.color_mode == CM_CMYK)
00183 m_imageInfoRecord.colorspace = ColorSpaceCMYK;
00184 else if (header.color_mode == CM_RGB)
00185 m_imageInfoRecord.colorspace = ColorSpaceRGB;
00186 else if (header.color_mode == CM_GRAYSCALE)
00187 m_imageInfoRecord.colorspace = ColorSpaceGray;
00188 else if (header.color_mode == CM_DUOTONE)
00189 m_imageInfoRecord.colorspace = ColorSpaceDuotone;
00190 xres = m_imageInfoRecord.xres;
00191 yres = m_imageInfoRecord.yres;
00192 f.close();
00193 if (thumbnail)
00194 {
00195 if (!m_imageInfoRecord.exifInfo.thumbnail.isNull())
00196 {
00197 if (isCMYK)
00198 r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 5);
00199 else
00200 r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 4);
00201 QRgb *s;
00202 unsigned char cc, cm, cy, ck;
00203 uchar *d;
00204 for( int yit=0; yit < m_imageInfoRecord.exifInfo.thumbnail.height(); ++yit )
00205 {
00206 s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit ));
00207 d = r_image.scanLine( yit );
00208 for(int xit=0; xit < m_imageInfoRecord.exifInfo.thumbnail.width(); ++xit )
00209 {
00210 if (isCMYK)
00211 {
00212 cc = 255 - qRed(*s);
00213 cm = 255 - qGreen(*s);
00214 cy = 255 - qBlue(*s);
00215 ck = qMin(qMin(cc, cm), cy);
00216 d[0] = cc-ck;
00217 d[1] = cm-ck;
00218 d[2] = cy-ck;
00219 d[3] = ck;
00220 d[4] = 255;
00221 }
00222 else
00223 {
00224 d[0] = qRed(*s);
00225 d[1] = qGreen(*s);
00226 d[2] = qBlue(*s);
00227 d[3] = 255;
00228 }
00229 s++;
00230 d += r_image.channels();
00231 }
00232 }
00233 m_imageInfoRecord.exifInfo.width = header.width;
00234 m_imageInfoRecord.exifInfo.height = header.height;
00235 return true;
00236 }
00237 }
00238 m_imageInfoRecord.exifInfo.width = header.width;
00239 m_imageInfoRecord.exifInfo.height = header.height;
00240 m_imageInfoRecord.BBoxX = 0;
00241 m_imageInfoRecord.BBoxH = r_image.height();
00242 return true;
00243 }
00244 return false;
00245 }
00246
00247 bool ScImgDataLoader_PSD::LoadPSD( QDataStream & s, const PSDHeader & header)
00248 {
00249
00250 m_imageInfoRecord.valid = false;
00251 if (header.color_mode == CM_CMYK)
00252 {
00253 if (!r_image.create(header.width, header.height, 5))
00254 return false;
00255 }
00256 else
00257 {
00258 if (!r_image.create(header.width, header.height, 4))
00259 return false;
00260 }
00261 r_image.fill(0);
00262 maxChannels = header.channel_count;
00263 uint tmp;
00264 uint cresStart;
00265 uint cdataStart;
00266 uint ressourceDataLen;
00267 uint startRessource;
00268
00269 cresStart = s.device()->pos();
00270
00271 s >> tmp;
00272 cdataStart = s.device()->pos();
00273
00274 LoadPSDResources(s, header, cresStart);
00275
00276 s.device()->seek( cdataStart + tmp );
00277 s >> ressourceDataLen;
00278 startRessource = s.device()->pos();
00279
00280 if ((!m_imageInfoRecord.exifInfo.thumbnail.isNull()) && (header.reserved[0] == 't'))
00281 return true;
00282 bool ret = LoadPSDImgData(s, header, startRessource + ressourceDataLen);
00283 return ret;
00284 }
00285
00286 bool ScImgDataLoader_PSD::LoadPSDResources( QDataStream & s, const PSDHeader & header, uint dataOffset )
00287 {
00288
00289 m_imageInfoRecord.valid = false;
00290
00291 uint tmp;
00292 uint cdataStart;
00293 uint ressourceDataLen;
00294 uint startRessource;
00295
00296 s.device()->seek( dataOffset );
00297
00298 srand(314159265);
00299 for (int i = 0; i < 4096; i++)
00300 random_table[i] = rand();
00301 int tmpd;
00302 int swap;
00303 for (int i = 0; i < 4096; i++)
00304 {
00305 swap = i + rand() % (4096 - i);
00306 tmpd = random_table[i];
00307 random_table[i] = random_table[swap];
00308 random_table[swap] = tmpd;
00309 }
00310
00311 s >> tmp;
00312 cdataStart = s.device()->pos();
00313 if (tmp != 0)
00314 {
00315 if ((header.color_mode == CM_DUOTONE))
00316 {
00317 short signature;
00318 short count;
00319 unsigned short c, m, y, k;
00320 uchar hc, sc, bc;
00321 ScColor col;
00322 s >> signature;
00323 s >> count;
00324 uint duodataStart = s.device()->pos();
00325 bool specialColour = false;
00326 for (int cda = 0; cda < count; cda++)
00327 {
00328 s >> signature;
00329 s >> c >> m >> y >> k;
00330 switch (signature)
00331 {
00332 case 0:
00333 col.setColorRGB(c >> 8, m >> 8, y >> 8);
00334 colorTableSc.append(col);
00335 break;
00336 case 1:
00337 hc = c >> 8;
00338 sc = m >> 8;
00339 bc = y >> 8;
00340 HSVTORGB(hc, sc, bc);
00341 col.setColorRGB(hc, sc, bc);
00342 colorTableSc.append(col);
00343 break;
00344 case 2:
00345 col.setColor(c >> 8, m >> 8, y >> 8, k >> 8);
00346 colorTableSc.append(col);
00347 break;
00348 case 3:
00349 case 4:
00350 case 5:
00351 case 6:
00352 case 7:
00353 case 10:
00354 if (colorTableSc.count() == 0)
00355 colorTableSc.append(ScColor(0, 0, 0, 255));
00356 else
00357 colorTableSc.append(ScColor(0, 0, 0, 0));
00358 specialColour = true;
00359 break;
00360 case 8:
00361 c = qRound((c / 10000.0) * 255);
00362 colorTableSc.append(ScColor(0, 0, 0, c));
00363 break;
00364 }
00365 }
00366 if (specialColour)
00367 {
00368 s.device()->seek( duodataStart + 40 );
00369 uint duoNameStart = s.device()->pos();
00370 uint duoCurveStart = duoNameStart+256;
00371 for (int cda = 0; cda < count; cda++)
00372 {
00373 QString colName;
00374 s.device()->seek( duoNameStart + (64 * static_cast<uint>(cda)) );
00375 colName = getPascalString(s);
00376 s.device()->seek( duoCurveStart + (28 * static_cast<uint>(cda)) );
00377 FPointArray tmcu;
00378 tmcu.resize(0);
00379 for (int cu = 0; cu < 13; cu++)
00380 {
00381 short val;
00382 s >> val;
00383 if (val != -1)
00384 tmcu.addPoint(cu * 1.0 / 12.0, val / 1000.0);
00385 }
00386 PSDDuotone_Color colSpec;
00387 colSpec.Name = colName;
00388 colSpec.Color = colorTableSc[cda];
00389 colSpec.Curve = tmcu;
00390 m_imageInfoRecord.duotoneColors.append(colSpec);
00391 }
00392
00393 curveTable1.resize(256);
00394 curveTable2.resize(256);
00395 curveTable3.resize(256);
00396 curveTable4.resize(256);
00397 for (int x = 0 ; x < 256 ; x++)
00398 {
00399 curveTable1[x] = x;
00400 curveTable2[x] = x;
00401 curveTable3[x] = x;
00402 curveTable4[x] = x;
00403 }
00404 }
00405 else
00406 {
00407 s.device()->seek( duodataStart + 40 );
00408 uint duoNameStart = s.device()->pos();
00409 uint duoCurveStart = duoNameStart+256;
00410 for (int cda = 0; cda < count; cda++)
00411 {
00412 s.device()->seek( duoCurveStart + (28 * static_cast<uint>(cda)) );
00413 FPointArray tmcu;
00414 tmcu.resize(0);
00415 for (int cu = 0; cu < 13; cu++)
00416 {
00417 short val;
00418 s >> val;
00419 if (val != -1)
00420 tmcu.addPoint(cu * 1.0 / 12.0, val / 1000.0);
00421 }
00422 if (cda == 0)
00423 {
00424 curveTable1.resize(256);
00425 for (int x = 0 ; x < 256 ; x++)
00426 {
00427 curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00428 }
00429 }
00430 else if (cda == 1)
00431 {
00432 curveTable2.resize(256);
00433 for (int x = 0 ; x < 256 ; x++)
00434 {
00435 curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00436 }
00437 }
00438 else if (cda == 2)
00439 {
00440 curveTable3.resize(256);
00441 for (int x = 0 ; x < 256 ; x++)
00442 {
00443 curveTable3[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00444 }
00445 }
00446 else if (cda == 3)
00447 {
00448 curveTable4.resize(256);
00449 for (int x = 0 ; x < 256 ; x++)
00450 {
00451 curveTable4[x] = qMin(255, qMax(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00452 }
00453 }
00454 }
00455 }
00456 }
00457 else
00458 {
00459 QList<uchar> colorTableR;
00460 QList<uchar> colorTableG;
00461 QList<uchar> colorTableB;
00462 colorTableR.clear();
00463 colorTableG.clear();
00464 colorTableB.clear();
00465 colorTable.clear();
00466 uchar r;
00467 for (uint cc = 0; cc < 256; cc++)
00468 {
00469 s >> r;
00470 colorTableR.append(r);
00471 }
00472 for (uint cc = 0; cc < 256; cc++)
00473 {
00474 s >> r;
00475 colorTableG.append(r);
00476 }
00477 for (uint cc = 0; cc < 256; cc++)
00478 {
00479 s >> r;
00480 colorTableB.append(r);
00481 }
00482 for (uint cc = 0; cc < 256; cc++)
00483 {
00484 colorTable.append(qRgb(colorTableR[cc], colorTableG[cc], colorTableB[cc]));
00485 }
00486 }
00487 }
00488 s.device()->seek( cdataStart + tmp );
00489 s >> ressourceDataLen;
00490 startRessource = s.device()->pos();
00491 if (ressourceDataLen != 0)
00492 parseRessourceData(s, header, ressourceDataLen);
00493 return true;
00494 }
00495
00496 bool ScImgDataLoader_PSD::LoadPSDImgData( QDataStream & s, const PSDHeader & header, uint dataOffset )
00497 {
00498 uint layerDataLen;
00499 uint startLayers;
00500 s.device()->seek( dataOffset );
00501
00502 s >> layerDataLen;
00503 startLayers = s.device()->pos();
00504 if (layerDataLen != 0)
00505 {
00506 bool re = parseLayer(s, header);
00507 if (re)
00508 {
00509 m_imageInfoRecord.valid = true;
00510 return re;
00511 }
00512 else
00513 {
00514
00515 s.device()->seek(startLayers + layerDataLen);
00516 if(s.atEnd())
00517 return false;
00518 return loadLayer( s, header);
00519 }
00520 }
00521 else
00522 {
00523
00524 s.device()->seek( s.device()->pos() + layerDataLen );
00525 loadLayer( s, header);
00526 }
00527 return true;
00528 }
00529
00530 bool ScImgDataLoader_PSD::parseLayer( QDataStream & s, const PSDHeader & header )
00531 {
00532 uint addRes, layerinfo, channelLen, signature, extradata, layermasksize, layerRange, dummy;
00533 int top, left, bottom, right;
00534 short numLayers, numChannels;
00535 short channelType;
00536 uchar blendKey[4];
00537 uchar opacity, clipping, flags, filler;
00538 QString layerName, blend;
00539 struct PSDLayer lay;
00540 s >> layerinfo;
00541 s >> numLayers;
00542 if (numLayers < 0)
00543 numLayers = -numLayers;
00544 if (numLayers != 0)
00545 {
00546 for (int layer = 0; layer < numLayers; layer++)
00547 {
00548 s >> top;
00549 lay.ypos = top;
00550 s >> left;
00551 lay.xpos = left;
00552 s >> bottom;
00553 lay.height = bottom - top;
00554 s >> right;
00555 lay.width = right - left;
00556 s >> numChannels;
00557
00558 maxChannels = qMax(maxChannels, (int)numChannels);
00559 if (numChannels > 6)
00560 {
00561 m_imageInfoRecord.layerInfo.clear();
00562 return false;
00563 }
00564 lay.channelType.clear();
00565 lay.channelLen.clear();
00566 for (int channels = 0; channels < numChannels; channels++)
00567 {
00568 s >> channelType;
00569 s >> channelLen;
00570 lay.channelType.append(channelType);
00571 lay.channelLen.append(channelLen);
00572 }
00573 s >> signature;
00574 blend = "";
00575 for( int i = 0; i < 4; i++ )
00576 {
00577 s >> blendKey[i];
00578 blend += QChar(blendKey[i]);
00579 }
00580 lay.blend = blend;
00581 s >> opacity;
00582 lay.opacity = opacity;
00583 s >> clipping;
00584 lay.clipping = clipping;
00585 s >> flags;
00586 if (flags & 8)
00587 {
00588 if (flags & 16)
00589 {
00590 m_imageInfoRecord.layerInfo.clear();
00591 return false;
00592 }
00593 }
00594 lay.flags = flags;
00595 s >> filler;
00596 s >> extradata;
00597 s >> layermasksize;
00598 lay.maskYpos = 0;
00599 lay.maskXpos = 0;
00600 lay.maskHeight = 0;
00601 lay.maskWidth = 0;
00602 if (layermasksize != 0)
00603 {
00604 s >> lay.maskYpos;
00605 s >> lay.maskXpos;
00606 s >> dummy;
00607 lay.maskHeight = dummy - lay.maskYpos;
00608 s >> dummy;
00609 lay.maskWidth = dummy - lay.maskXpos;
00610 s >> dummy;
00611 }
00612 s >> layerRange;
00613 s.device()->seek( s.device()->pos() + layerRange );
00614 lay.layerName = getLayerString(s);
00615 m_imageInfoRecord.layerInfo.append(lay);
00616 s >> signature;
00617 if( signature == 0x3842494D )
00618 {
00619 while (signature == 0x3842494D )
00620 {
00621 s >> signature;
00622 s >> addRes;
00623 s.device()->seek( s.device()->pos() + addRes );
00624 s >> signature;
00625 }
00626 s.device()->seek( s.device()->pos() - 4 );
00627 }
00628 else
00629 {
00630 s.device()->seek( s.device()->pos() - 2 );
00631 s >> signature;
00632 if( signature == 0x3842494D )
00633 {
00634 while (signature == 0x3842494D )
00635 {
00636 s >> signature;
00637 s >> addRes;
00638 s.device()->seek( s.device()->pos() + addRes );
00639 s >> signature;
00640 }
00641 s.device()->seek( s.device()->pos() - 4 );
00642 }
00643 else
00644 s.device()->seek( s.device()->pos() - 6 );
00645 }
00646 }
00647 bool firstLayer = true;
00648 for (int layer = 0; layer < numLayers; layer++)
00649 {
00650 loadLayerChannels( s, header, m_imageInfoRecord.layerInfo, layer, &firstLayer );
00651 }
00652 }
00653 else
00654 {
00655 s >> numLayers;
00656 loadLayer( s, header);
00657 }
00658 return true;
00659 }
00660
00661 bool ScImgDataLoader_PSD::loadChannel( QDataStream & s, const PSDHeader & header, QList<PSDLayer> &layerInfo, uint layer, int channel, int component, RawImage &tmpImg)
00662 {
00663 uint base = s.device()->pos();
00664 uchar cbyte;
00665 ushort compression;
00666 s >> compression;
00667 if( compression > 1 )
00668 return false;
00669 if (compression == 0)
00670 {
00671 int count = layerInfo[layer].channelLen[channel]-2;
00672 uchar *ptr;
00673 for (int i = 0; i < tmpImg.height(); i++)
00674 {
00675 ptr = tmpImg.scanLine(i);
00676 for (int j = 0; j < tmpImg.width(); j++)
00677 {
00678 s >> cbyte;
00679 count--;
00680 if ((header.color_mode == CM_CMYK) && (component < 4))
00681 cbyte = 255 - cbyte;
00682 if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
00683 {
00684 ptr[0] = cbyte;
00685 ptr[1] = cbyte;
00686 ptr[2] = cbyte;
00687 }
00688 else if ((header.color_mode == CM_DUOTONE) && (component != 3))
00689 {
00690 ptr -= component;
00691 putDuotone(ptr, cbyte);
00692 ptr += component;
00693 }
00694 else if ((header.color_mode == CM_INDEXED) && (component != 3))
00695 {
00696 int ccol = colorTable[cbyte];
00697 ptr[0] = qRed(ccol);
00698 ptr[1] = qGreen(ccol);
00699 ptr[2] = qBlue(ccol);
00700 }
00701 else
00702 ptr[component] = cbyte;
00703 if (count == 0)
00704 break;
00705 ptr += tmpImg.channels();
00706 }
00707 if (count == 0)
00708 break;
00709 }
00710 }
00711 else
00712 {
00713 s.device()->seek( s.device()->pos() + tmpImg.height() * 2 );
00714 uint pixel_count = tmpImg.width();
00715 uchar *ptr;
00716 uchar *ptr2;
00717 uint count, len;
00718 uchar c;
00719 for (int hh = 0; hh < tmpImg.height(); hh++)
00720 {
00721 count = 0;
00722 ptr = tmpImg.scanLine(hh);
00723 ptr2 = ptr+tmpImg.width() * tmpImg.channels();
00724 ptr += component;
00725 while( count < pixel_count )
00726 {
00727 if(s.atEnd())
00728 return false;
00729 s >> c;
00730 len = c;
00731 if( len < 128 )
00732 {
00733
00734 len++;
00735 count += len;
00736 while( len != 0 )
00737 {
00738 s >> cbyte;
00739 if (ptr < ptr2)
00740 {
00741 if ((header.color_mode == CM_CMYK) && (component < 4))
00742 cbyte = 255 - cbyte;
00743 if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
00744 {
00745 ptr -= component;
00746 ptr[0] = cbyte;
00747 ptr[1] = cbyte;
00748 ptr[2] = cbyte;
00749 ptr += component;
00750 }
00751 else if ((header.color_mode == CM_DUOTONE) && (component != 3))
00752 {
00753 ptr -= component;
00754 putDuotone(ptr, cbyte);
00755 ptr += component;
00756 }
00757 else if ((header.color_mode == CM_INDEXED) && (component != 3))
00758 {
00759 ptr -= component;
00760 int ccol = colorTable[cbyte];
00761 ptr[0] = qRed(ccol);
00762 ptr[1] = qGreen(ccol);
00763 ptr[2] = qBlue(ccol);
00764 ptr += component;
00765 }
00766 else
00767 {
00768 *ptr = cbyte;
00769 }
00770 }
00771 ptr += tmpImg.channels();
00772 len--;
00773 }
00774 }
00775 else if( len > 128 )
00776 {
00777
00778
00779 len ^= 0xFF;
00780 len += 2;
00781 count += len;
00782 uchar val;
00783 s >> val;
00784 if ((header.color_mode == CM_CMYK) && (component < 4))
00785 val = 255 - val;
00786 while( len != 0 )
00787 {
00788 if (ptr < ptr2)
00789 {
00790 if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
00791 {
00792 ptr -= component;
00793 ptr[0] = val;
00794 ptr[1] = val;
00795 ptr[2] = val;
00796 ptr += component;
00797 }
00798 else if ((header.color_mode == CM_DUOTONE) && (component != 3))
00799 {
00800 ptr -= component;
00801 putDuotone(ptr, val);
00802 ptr += component;
00803 }
00804 else if ((header.color_mode == CM_INDEXED) && (component != 3))
00805 {
00806 ptr -= component;
00807 int ccol = colorTable[val];
00808 ptr[0] = qRed(ccol);
00809 ptr[1] = qGreen(ccol);
00810 ptr[2] = qBlue(ccol);
00811 ptr += component;
00812 }
00813 else
00814 *ptr = val;
00815 }
00816 ptr += tmpImg.channels();
00817 len--;
00818 }
00819 }
00820 else if( len == 128 )
00821 {
00822
00823 }
00824 }
00825 }
00826 }
00827 s.device()->seek( base+layerInfo[layer].channelLen[channel] );
00828 return true;
00829 }
00830
00831 bool ScImgDataLoader_PSD::loadLayerChannels( QDataStream & s, const PSDHeader & header, QList<PSDLayer> &layerInfo, uint layer, bool* firstLayer)
00832 {
00833
00834
00835
00836
00837 uint base = s.device()->pos();
00838 uint base2 = base;
00839 uint channel_num = layerInfo[layer].channelLen.count();
00840 bool hasMask = false;
00841 bool hasAlpha = false;
00842 RawImage r2_image;
00843 RawImage mask;
00844 bool createOk = false;
00845 if (header.color_mode == CM_CMYK)
00846 {
00847 createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, qMax(channel_num, (uint)5));
00848 r2_image.fill(0);
00849 }
00850 else
00851 {
00852 createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, qMax(channel_num, (uint)4));
00853 r2_image.fill(0);
00854 }
00855 if( !createOk )
00856 {
00857 for(uint channel = 0; channel < channel_num; channel++)
00858 {
00859 base2 += layerInfo[layer].channelLen[channel];
00860 }
00861 s.device()->seek( base2 );
00862 return false;
00863 }
00864 channel_num = qMin(channel_num, (uint)39);
00865 uint components[40];
00866 for(uint channel = 0; channel < channel_num; channel++)
00867 {
00868 switch(layerInfo[layer].channelType[channel])
00869 {
00870 case 0:
00871 components[channel] = 0;
00872 break;
00873 case 1:
00874 components[channel] = 1;
00875 break;
00876 case 2:
00877 components[channel] = 2;
00878 break;
00879 case 3:
00880 components[channel] = 3;
00881 break;
00882 case -1:
00883 if (header.color_mode == CM_CMYK)
00884 {
00885 if (channel_num == 6)
00886 components[channel] = channel_num-2;
00887 else
00888 components[channel] = channel_num-1;
00889 }
00890 else
00891 {
00892 if (channel_num == 5)
00893 components[channel] = channel_num-2;
00894 else
00895 {
00896 if (header.color_mode == CM_GRAYSCALE)
00897 components[channel] = 3;
00898 else
00899 components[channel] = channel_num-1;
00900 }
00901 }
00902 hasAlpha = true;
00903 break;
00904 case -2:
00905 components[channel] = channel_num-1;
00906 break;
00907 }
00908 }
00909 if (!hasAlpha)
00910 r2_image.fill(255);
00911 for(uint channel = 0; channel < channel_num; channel++)
00912 {
00913 if (layerInfo[layer].channelType[channel] == -2)
00914 {
00915 if (!mask.create( layerInfo[layer].maskWidth, layerInfo[layer].maskHeight, 1 ))
00916 break;
00917 mask.fill(0);
00918 if (!loadChannel(s, header, layerInfo, layer, channel, 0, mask))
00919 break;
00920 hasMask = true;
00921 }
00922 if (!loadChannel(s, header, layerInfo, layer, channel, components[channel], r2_image))
00923 break;
00924 }
00925 for(uint channel = 0; channel < channel_num; channel++)
00926 {
00927 base2 += layerInfo[layer].channelLen[channel];
00928 }
00929 if (header.color_mode == CM_LABCOLOR)
00930 {
00931 cmsHPROFILE hsRGB = cmsCreate_sRGBProfile();
00932 cmsHPROFILE hLab = cmsCreateLabProfile(NULL);
00933 DWORD inputProfFormat = (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1));
00934 cmsHTRANSFORM xform = cmsCreateTransform(hLab, inputProfFormat, hsRGB, TYPE_RGBA_8, INTENT_PERCEPTUAL, 0);
00935 for (int i = 0; i < r2_image.height(); i++)
00936 {
00937 LPBYTE ptr = r2_image.scanLine(i);
00938 cmsDoTransform(xform, ptr, ptr, r2_image.width());
00939 }
00940 cmsDeleteTransform (xform);
00941 cmsCloseProfile(hsRGB);
00942 cmsCloseProfile(hLab);
00943 }
00944 s.device()->seek( base2 );
00945 QImage tmpImg2;
00946 if (header.color_mode == CM_CMYK)
00947 tmpImg2 = r2_image.convertToQImage(true);
00948 else
00949 tmpImg2 = r2_image.convertToQImage(false);
00950 QImage imt;
00951 double sx = tmpImg2.width() / 40.0;
00952 double sy = tmpImg2.height() / 40.0;
00953 imt = sy < sx ? tmpImg2.scaled(qRound(tmpImg2.width() / sx), qRound(tmpImg2.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) :
00954 tmpImg2.scaled(qRound(tmpImg2.width() / sy), qRound(tmpImg2.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00955 layerInfo[layer].thumb = imt.copy();
00956 if (hasMask)
00957 {
00958 QImage imt2;
00959 QImage tmpImg;
00960 tmpImg = mask.convertToQImage(true);
00961 double sx = tmpImg.width() / 40.0;
00962 double sy = tmpImg.height() / 40.0;
00963 imt2 = sy < sx ? tmpImg.scaled(qRound(tmpImg.width() / sx), qRound(tmpImg.height() / sx), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) :
00964 tmpImg.scaled(qRound(tmpImg.width() / sy), qRound(tmpImg.height() / sy), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00965 imt2.invertPixels();
00966 layerInfo[layer].thumb_mask = imt2.copy();
00967 }
00968 else
00969 layerInfo[layer].thumb_mask = QImage();
00970 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
00971 m_imageInfoRecord.RequestProps[layer].useMask = m_imageInfoRecord.RequestProps[layer].useMask;
00972 else
00973 m_imageInfoRecord.RequestProps[layer].useMask = true;
00974 bool visible = !(layerInfo[layer].flags & 2);
00975 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
00976 visible = m_imageInfoRecord.RequestProps[layer].visible;
00977 if (visible)
00978 {
00979 unsigned int startSrcY, startSrcX, startDstY, startDstX;
00980 if (layerInfo[layer].ypos < 0)
00981 {
00982 startSrcY = abs(layerInfo[layer].ypos);
00983 startDstY = 0;
00984 }
00985 else
00986 {
00987 startSrcY = 0;
00988 startDstY = layerInfo[layer].ypos;
00989 }
00990 if (layerInfo[layer].xpos < 0)
00991 {
00992 startSrcX = abs(layerInfo[layer].xpos);
00993 startDstX = 0;
00994 }
00995 else
00996 {
00997 startSrcX = 0;
00998 startDstX = layerInfo[layer].xpos;
00999 }
01000 unsigned int startSrcYm, startSrcXm, startDstYm, startDstXm;
01001 if (layerInfo[layer].maskYpos < 0)
01002 {
01003 startSrcYm = abs(layerInfo[layer].maskYpos);
01004 startDstYm = 0;
01005 }
01006 else
01007 {
01008 startSrcYm = 0;
01009 startDstYm = layerInfo[layer].maskYpos;
01010 }
01011 if (layerInfo[layer].maskXpos < 0)
01012 {
01013 startSrcXm = abs(layerInfo[layer].maskXpos);
01014 startDstXm = 0;
01015 }
01016 else
01017 {
01018 startSrcXm = 0;
01019 startDstXm = layerInfo[layer].maskXpos;
01020 }
01021 QString layBlend2 = layerInfo[layer].blend;
01022 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
01023 layBlend2 = m_imageInfoRecord.RequestProps[layer].blend;
01024 if (layBlend2 == "diss")
01025 {
01026 hasAlpha = true;
01027 int layOpa = layerInfo[layer].opacity;
01028 if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
01029 layOpa = m_imageInfoRecord.RequestProps[layer].opacity;
01030 for (int l = 0; l < r2_image.height(); l++)
01031 {
01032 srand(random_table[ l % 4096]);
01033 for (int k = 0; k < r2_image.width(); k++)
01034 {
01035 int rand_val = rand() & 0xff;
01036 if (rand_val > layOpa)
01037 r2_image.setAlpha(k, l, 0);
01038 }
01039 }
01040 }
01041 if (*firstLayer)
01042 {
01043 unsigned char *s;
01044 unsigned char *d;
01045 for( int yi=static_cast<int>(startSrcY); yi < qMin(r2_image.height(), r_image.height()); ++yi )
01046 {
01047 s = r2_image.scanLine( yi );
01048 d = r_image.scanLine( qMin(static_cast<int>(startDstY), r_image.height()-1) );
01049 d += qMin(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels();
01050 s += qMin(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels();
01051 for(int xi=static_cast<int>(startSrcX); xi < qMin(r2_image.width(), r_image.width()); ++xi )
01052 {
01053 d[0] = s[0];
01054 d[1] = s[1];
01055 d[2] = s[2];
01056 if (header.color_mode != CM_CMYK)
01057 {
01058 if (hasAlpha)
01059 d[3] = s[3];
01060 else
01061 d[3] = 255;
01062 }
01063 else
01064 {
01065 d[3] = s[3];
01066 if (hasAlpha)
01067 d[4] = s[4];
01068 else
01069 d[4] = 255;
01070 }
01071 s += r2_image.channels();
01072 d += r_image.channels();
01073 }
01074 startDstY++;
01075 }
01076 }
01077 else
01078 {
01079 unsigned char *s;
01080 unsigned char *d;
01081 unsigned char *sm = 0;
01082 unsigned char r, g, b, src_r, src_g, src_b, src_a, src_alpha, dst_alpha;
01083 unsigned char a = 0;
01084 uchar new_r, new_g, new_b;
01085 unsigned int maxDestX;
01086 for (int i = static_cast<int>(startSrcY); i < layerInfo[layer].height; i++)
01087 {
01088 d = r_image.scanLine(qMin(static_cast<int>(startDstY), r_image.height()-1));
01089 s = r2_image.scanLine(qMin(i, r2_image.height()-1));
01090 d += qMin(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels();
01091 s += qMin(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels();
01092 sm = 0;
01093 if (hasMask)
01094 {
01095 sm = mask.scanLine(qMin(i, mask.height()-1));
01096 sm += qMin(static_cast<int>(startSrcXm), mask.width()-1) * mask.channels();
01097 }
01098 startDstY++;
01099 maxDestX = r_image.width() - startDstX + startSrcX - 1;
01100 for (unsigned int j = startSrcX; j < qMin(maxDestX, static_cast<unsigned int>(layerInfo[layer].width)); j++)
01101 {
01102 src_r = s[0];
01103 src_g = s[1];
01104 src_b = s[2];
01105 src_a = s[3];
01106 if (hasAlpha)
01107 {
01108 if (hasMask)
01109 {
01110 if (m_imageInfoRecord.RequestProps[layer].useMask)
01111 src_alpha = sm[0];
01112 else
01113 src_alpha = s[channel_num - 2];
01114 }
01115 else
01116 {
01117 if (header.color_mode == CM_GRAYSCALE)
01118 src_alpha = s[3];
01119 else
01120 src_alpha = s[channel_num - 1];
01121 }
01122 }
01123 else
01124 src_alpha = 255;
01125 if ((hasMask) && (m_imageInfoRecord.RequestProps[layer].useMask))
01126