Back to index

scribus-ng  1.3.4.dfsg+svn20071115
scimgdataloader_psd.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 #include "scconfig.h"
00008 #include "scimgdataloader_psd.h"
00009 #include "colorutil.h"
00010 #include "sccolorengine.h"
00011 
00012 #include <qfile.h>
00013 #include <qfileinfo.h>
00014 
00015 #include CMS_INC
00016 
00017 static QDataStream & operator>> ( QDataStream & s, PSDHeader & header )
00018 {
00019        s >> header.signature;
00020        s >> header.version;
00021        for( int i = 0; i < 6; i++ )
00022        {
00023               s >> header.reserved[i];
00024        }
00025        s >> header.channel_count;
00026        s >> header.height;
00027        s >> header.width;
00028        s >> header.depth;
00029        s >> header.color_mode;
00030        return s;
00031 }
00032 
00033 ScImgDataLoader_PSD::ScImgDataLoader_PSD(void)
00034 {
00035        initSupportedFormatList();
00036 }
00037 
00038 void ScImgDataLoader_PSD::initSupportedFormatList(void)
00039 {
00040        m_supportedFormats.clear();
00041        m_supportedFormats.append( "psd" );
00042 }
00043 
00044 void ScImgDataLoader_PSD::loadEmbeddedProfile(const QString& fn)
00045 {
00046        m_embeddedProfile.resize(0);
00047        m_profileComponents = 0;
00048        cmsHPROFILE prof = 0;
00049        QFileInfo fi = QFileInfo(fn);
00050        if (!fi.exists())
00051               return;
00052        QString ext = fi.extension(false).lower();
00053        if (ext == "psd")
00054        {
00055               QFile f(fn);
00056               if (f.open(IO_ReadOnly))
00057               {
00058                      m_imageInfoRecord.xres = 72;
00059                      m_imageInfoRecord.yres = 72;
00060                      QDataStream s( &f );
00061                      s.setByteOrder( QDataStream::BigEndian );
00062                      PSDHeader header;
00063                      s >> header;
00064                      // Check image file format.
00065                      if( s.atEnd() || !IsValid( header ) )
00066                             return;
00067                      // Check if it's a supported format.
00068                      if( !IsSupported( header ) )
00069                             return;
00070                      if( !LoadPSDResources(s, header, s.device()->at()) )
00071                             return;
00072                      if (m_embeddedProfile.size() > 0)
00073                      {
00074                             prof = cmsOpenProfileFromMem(m_embeddedProfile.data(), m_embeddedProfile.size());
00075                             if (prof)
00076                             {
00077                                    if (static_cast<int>(cmsGetColorSpace(prof)) == icSigRgbData)
00078                                           m_profileComponents = 3;
00079                                    if (static_cast<int>(cmsGetColorSpace(prof)) == icSigCmykData)
00080                                           m_profileComponents = 4;
00081                             }
00082                             cmsCloseProfile(prof);
00083                      }
00084                      f.close();
00085               }
00086               else
00087                      return;
00088        }
00089 }
00090 
00091 void ScImgDataLoader_PSD::preloadAlphaChannel(const QString& fn, int res)
00092 {
00093        bool valid = m_imageInfoRecord.isRequest;
00094        QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
00095        initialize();
00096        m_imageInfoRecord.RequestProps = req;
00097        m_imageInfoRecord.isRequest = valid;
00098        QFileInfo fi = QFileInfo(fn);
00099        if (!fi.exists())
00100               return;
00101 
00102        QFile f(fn);
00103        if (f.open(IO_ReadOnly))
00104        {
00105               QDataStream s( &f );
00106               s.setByteOrder( QDataStream::BigEndian );
00107               PSDHeader header;
00108               s >> header;
00109               // Check image file format.
00110               if( s.atEnd() || !IsValid( header ) )
00111                      return;
00112               // Check if it's a supported format.
00113               if( !IsSupported( header ) )
00114                      return;
00115               if( !LoadPSD(s, header) )
00116                      r_image.resize(0);
00117               f.close();
00118               m_imageInfoRecord.valid = true;
00119               if (header.color_mode == CM_CMYK)
00120               {
00121                      if ( maxChannels == 4)
00122                             m_imageInfoRecord.valid = false;
00123               }
00124               else
00125               {
00126                      if ( maxChannels == 3)
00127                             m_imageInfoRecord.valid = false;
00128               }
00129        }
00130 }
00131 
00132 bool ScImgDataLoader_PSD::loadPicture(const QString& fn, int res, bool thumbnail)
00133 {
00134        bool isCMYK = false;
00135        float xres = 72.0, yres = 72.0;
00136        if (!QFile::exists(fn))
00137               return false;
00138        bool valid = m_imageInfoRecord.isRequest;
00139        QMap<int, ImageLoadRequest> req = m_imageInfoRecord.RequestProps;
00140        initialize();
00141        m_imageInfoRecord.RequestProps = req;
00142        m_imageInfoRecord.isRequest = valid;
00143        m_imageInfoRecord.type = 2;
00144        m_imageInfoRecord.exifDataValid = false;
00145        m_imageInfoRecord.layerInfo.clear();
00146        m_imageInfoRecord.PDSpathData.clear();
00147        QFile f(fn);
00148        if (f.open(IO_ReadOnly))
00149        {
00150               m_imageInfoRecord.xres = 72;
00151               m_imageInfoRecord.yres = 72;
00152               QDataStream s( &f );
00153               s.setByteOrder( QDataStream::BigEndian );
00154               PSDHeader header;
00155               s >> header;
00156               // Check image file format.
00157               if( s.atEnd() || !IsValid( header ) )
00158                      return false;
00159               // Check if it's a supported format.
00160               if( !IsSupported( header ) )
00161                      return false;
00162               if (thumbnail)
00163                      header.reserved[0] = 't';
00164               if( !LoadPSD(s, header) )
00165                      return false;
00166               if (m_embeddedProfile.size() > 0)
00167               {
00168                      cmsHPROFILE prof = cmsOpenProfileFromMem(m_embeddedProfile.data(), m_embeddedProfile.size());
00169                      const char *Descriptor;
00170                      Descriptor = cmsTakeProductDesc(prof);
00171                      m_imageInfoRecord.profileName = QString(Descriptor);
00172                      m_imageInfoRecord.isEmbedded = true;
00173               }
00174               if (header.color_mode == CM_CMYK)
00175                      isCMYK = true;
00176               else
00177                      isCMYK = false;
00178               if (header.color_mode == CM_CMYK)
00179                      m_imageInfoRecord.colorspace = 1;
00180               else if (header.color_mode == CM_RGB)
00181                      m_imageInfoRecord.colorspace = 0;
00182               else if (header.color_mode == CM_GRAYSCALE)
00183                      m_imageInfoRecord.colorspace = 2;
00184               else if (header.color_mode == CM_DUOTONE)
00185                      m_imageInfoRecord.colorspace = 3;
00186               xres = m_imageInfoRecord.xres;
00187               yres = m_imageInfoRecord.yres;
00188               f.close();
00189               if (thumbnail)
00190               {
00191                      if (!m_imageInfoRecord.exifInfo.thumbnail.isNull())
00192                      {
00193                             if (isCMYK)
00194                                    r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 5);
00195                             else
00196                                    r_image.create(m_imageInfoRecord.exifInfo.thumbnail.width(), m_imageInfoRecord.exifInfo.thumbnail.height(), 4);
00197                             QRgb *s;
00198                             unsigned char cc, cm, cy, ck;
00199                             uchar *d;
00200                             for( int yit=0; yit < m_imageInfoRecord.exifInfo.thumbnail.height(); ++yit )
00201                             {
00202                                    s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit ));
00203                                    d = r_image.scanLine( yit );
00204                                    for(int xit=0; xit < m_imageInfoRecord.exifInfo.thumbnail.width(); ++xit )
00205                                    {
00206                                           if (isCMYK)
00207                                           {
00208                                                  cc = 255 - qRed(*s);
00209                                                  cm = 255 - qGreen(*s);
00210                                                  cy = 255 - qBlue(*s);
00211                                                  ck = QMIN(QMIN(cc, cm), cy);
00212                                                  d[0] = cc-ck;
00213                                                  d[1] = cm-ck;
00214                                                  d[2] = cy-ck;
00215                                                  d[3] = ck;
00216                                                  d[4] = 255;
00217                                           }
00218                                           else
00219                                           {
00220                                                  d[0] = qRed(*s);
00221                                                  d[1] = qGreen(*s);
00222                                                  d[2] = qBlue(*s);
00223                                                  d[3] = 255;
00224                                           }
00225                                           s++;
00226                                           d += r_image.channels();
00227                                    }
00228                             }
00229                             m_imageInfoRecord.exifInfo.width = header.width;
00230                             m_imageInfoRecord.exifInfo.height = header.height;
00231                             return true;
00232                      }
00233               }
00234               m_imageInfoRecord.exifInfo.width = header.width;
00235               m_imageInfoRecord.exifInfo.height = header.height;
00236               m_imageInfoRecord.BBoxX = 0;
00237               m_imageInfoRecord.BBoxH = r_image.height();
00238               return true;
00239        }
00240        return false;
00241 }
00242 
00243 bool ScImgDataLoader_PSD::LoadPSD( QDataStream & s, const PSDHeader & header)
00244 {
00245        // Create dst image.
00246        m_imageInfoRecord.valid = false;
00247        if (header.color_mode == CM_CMYK)
00248        {
00249               if (!r_image.create(header.width, header.height, 5))
00250                      return false;
00251        }
00252        else
00253        {
00254               if (!r_image.create(header.width, header.height, 4))
00255                      return false;
00256        }
00257        r_image.fill(0);
00258        maxChannels = header.channel_count;
00259        uint tmp;
00260        uint cresStart;
00261        uint cdataStart;
00262        uint ressourceDataLen;
00263        uint startRessource;
00264 
00265        cresStart = s.device()->at();
00266        // Skip mode data. FIX: this is incorrect, it's the Colormap Data for indexed Images
00267        s >> tmp;
00268        cdataStart = s.device()->at();
00269 
00270        LoadPSDResources(s, header, cresStart); 
00271        
00272        s.device()->at( cdataStart + tmp );
00273        s >> ressourceDataLen;
00274        startRessource = s.device()->at();
00275 
00276        if  ((!m_imageInfoRecord.exifInfo.thumbnail.isNull()) && (header.reserved[0] == 't'))
00277               return true;
00278        bool ret = LoadPSDImgData(s, header, startRessource + ressourceDataLen);
00279        return ret;
00280 }
00281 
00282 bool ScImgDataLoader_PSD::LoadPSDResources( QDataStream & s, const PSDHeader & header, uint dataOffset )
00283 {
00284        // Create dst image.
00285        m_imageInfoRecord.valid = false;
00286 
00287        uint tmp;
00288        uint cdataStart;
00289        uint ressourceDataLen;
00290        uint startRessource;
00291 
00292        s.device()->at( dataOffset );
00293 
00294        srand(314159265);
00295        for (int i = 0; i < 4096; i++)
00296               random_table[i] = rand();
00297        int tmpd;
00298        int swap;
00299        for (int i = 0; i < 4096; i++)
00300        {
00301               swap = i + rand() % (4096 - i);
00302               tmpd = random_table[i];
00303               random_table[i] = random_table[swap];
00304               random_table[swap] = tmpd;
00305        }
00306        // Skip mode data. FIX: this is incorrect, it's the Colormap Data for indexed Images
00307        s >> tmp;
00308        cdataStart = s.device()->at();
00309        if (tmp != 0)
00310        {
00311               if ((header.color_mode == CM_DUOTONE))
00312               {
00313                      short signature;
00314                      short count;
00315                      unsigned short c, m, y, k;
00316                      uchar hc, sc, bc;
00317                      ScColor col;
00318                      s >> signature;
00319                      s >> count;
00320                      uint duodataStart = s.device()->at();
00321                      bool specialColour = false;
00322                      for (int cda = 0; cda < count; cda++)
00323                      {
00324                             s >> signature;
00325                             s >> c >> m >> y >> k;
00326                             switch (signature)
00327                             {
00328                                    case 0:       // RGB colour
00329                                           col.setColorRGB(c >> 8, m >> 8, y >> 8);
00330                                           colorTableSc.append(col);
00331                                           break;
00332                                    case 1:       // HSB colour
00333                                           hc = c >> 8;
00334                                           sc = m >> 8;
00335                                           bc = y >> 8;
00336                                           HSVTORGB(hc, sc, bc);
00337                                           col.setColorRGB(hc, sc, bc);
00338                                           colorTableSc.append(col);
00339                                           break;
00340                                    case 2:       // CMYK colour
00341                                           col.setColor(c >> 8, m >> 8, y >> 8, k >> 8);
00342                                           colorTableSc.append(col);
00343                                           break;
00344                                    case 3:       // Pantone
00345                                    case 4:       // Focoltone
00346                                    case 5:       // Truematch
00347                                    case 6:       // Toyo 88 colorfinder 1050
00348                                    case 7:       // LAB colour space
00349                                    case 10: // HKS colors
00350                                           if (colorTableSc.count() == 0)
00351                                                  colorTableSc.append(ScColor(0, 0, 0, 255));
00352                                           else
00353                                                  colorTableSc.append(ScColor(0, 0, 0, 0));
00354                                           specialColour = true;
00355                                           break;
00356                                    case 8: // Grayscale
00357                                           c = qRound((c / 10000.0) * 255);
00358                                           colorTableSc.append(ScColor(0, 0, 0, c));
00359                                           break;
00360                             }
00361                      }
00362                      if (specialColour) // we will only load the grayscale image data and do the colorizing with the Image Effects;
00363                      {
00364                             s.device()->at( duodataStart + 40 );
00365                             uint duoNameStart = s.device()->at();
00366                             uint duoCurveStart = duoNameStart+256;
00367                             for (int cda = 0; cda < count; cda++)
00368                             {
00369                                    QString colName;
00370                                    s.device()->at( duoNameStart + (64 * static_cast<uint>(cda)) );
00371                                    colName = getPascalString(s);
00372                                    s.device()->at( duoCurveStart + (28 * static_cast<uint>(cda)) );
00373                                    FPointArray tmcu;
00374                                    tmcu.resize(0);
00375                                    for (int cu = 0; cu < 13; cu++)
00376                                    {
00377                                           short val;
00378                                           s >> val;
00379                                           if (val != -1)
00380                                                  tmcu.addPoint(cu * 1.0 / 12.0, val / 1000.0);
00381                                    }
00382                                    PSDDuotone_Color colSpec;
00383                                    colSpec.Name = colName;
00384                                    colSpec.Color = colorTableSc[cda];
00385                                    colSpec.Curve = tmcu;
00386                                    m_imageInfoRecord.duotoneColors.append(colSpec);
00387                             }
00388                             // Initialize loading curve tables with default values
00389                             curveTable1.resize(256);
00390                             curveTable2.resize(256);
00391                             curveTable3.resize(256);
00392                             curveTable4.resize(256);
00393                             for (int x = 0 ; x < 256 ; x++)
00394                             {
00395                                    curveTable1[x] = x;
00396                                    curveTable2[x] = x;
00397                                    curveTable3[x] = x;
00398                                    curveTable4[x] = x;
00399                             }
00400                      }
00401                      else
00402                      {
00403                             s.device()->at( duodataStart + 40 );
00404                             uint duoNameStart = s.device()->at();
00405                             uint duoCurveStart = duoNameStart+256;
00406                             for (int cda = 0; cda < count; cda++)
00407                             {
00408                                    s.device()->at( duoCurveStart + (28 * static_cast<uint>(cda)) );
00409                                    FPointArray tmcu;
00410                                    tmcu.resize(0);
00411                                    for (int cu = 0; cu < 13; cu++)
00412                                    {
00413                                           short val;
00414                                           s >> val;
00415                                           if (val != -1)
00416                                                  tmcu.addPoint(cu * 1.0 / 12.0, val / 1000.0);
00417                                    }
00418                                    if (cda == 0)
00419                                    {
00420                                           curveTable1.resize(256);
00421                                           for (int x = 0 ; x < 256 ; x++)
00422                                           {
00423                                                  curveTable1[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00424                                           }
00425                                    }
00426                                    else if (cda == 1)
00427                                    {
00428                                           curveTable2.resize(256);
00429                                           for (int x = 0 ; x < 256 ; x++)
00430                                           {
00431                                                  curveTable2[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00432                                           }
00433                                    }
00434                                    else if (cda == 2)
00435                                    {
00436                                           curveTable3.resize(256);
00437                                           for (int x = 0 ; x < 256 ; x++)
00438                                           {
00439                                                  curveTable3[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00440                                           }
00441                                    }
00442                                    else if (cda == 3)
00443                                    {
00444                                           curveTable4.resize(256);
00445                                           for (int x = 0 ; x < 256 ; x++)
00446                                           {
00447                                                  curveTable4[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(tmcu, x / 255.0) * 255)));
00448                                           }
00449                                    }
00450                             }
00451                      }
00452               }
00453               else
00454               {
00455                      QValueList<uchar> colorTableR;
00456                      QValueList<uchar> colorTableG;
00457                      QValueList<uchar> colorTableB;
00458                      colorTableR.clear();
00459                      colorTableG.clear();
00460                      colorTableB.clear();
00461                      colorTable.clear();
00462                      uchar r;
00463                      for (uint cc = 0; cc < 256; cc++)
00464                      {
00465                             s >> r;
00466                             colorTableR.append(r);
00467                      }
00468                      for (uint cc = 0; cc < 256; cc++)
00469                      {
00470                             s >> r;
00471                             colorTableG.append(r);
00472                      }
00473                      for (uint cc = 0; cc < 256; cc++)
00474                      {
00475                             s >> r;
00476                             colorTableB.append(r);
00477                      }
00478                      for (uint cc = 0; cc < 256; cc++)
00479                      {
00480                             colorTable.append(qRgb(colorTableR[cc], colorTableG[cc], colorTableB[cc]));
00481                      }
00482               }
00483        }
00484        s.device()->at( cdataStart + tmp );
00485        s >> ressourceDataLen;
00486        startRessource = s.device()->at();
00487        if (ressourceDataLen != 0)
00488               parseRessourceData(s, header, ressourceDataLen);
00489        return true;
00490 }
00491 
00492 bool ScImgDataLoader_PSD::LoadPSDImgData( QDataStream & s, const PSDHeader & header, uint dataOffset )
00493 {
00494        uint layerDataLen;
00495        uint startLayers;
00496        s.device()->at( dataOffset );
00497        // Skip the reserved data. FIX: Also incorrect, this is the actual Layer Data for Images with Layers
00498        s >> layerDataLen;
00499        startLayers = s.device()->at();
00500        if (layerDataLen != 0)
00501        {
00502               bool re = parseLayer(s, header);
00503               if (re)
00504               {
00505                      m_imageInfoRecord.valid = true;
00506                      return re;
00507               }
00508               else
00509               {
00510                      // Try to decode simple psd file, no layers
00511                      s.device()->at(startLayers + layerDataLen);
00512                      if(s.atEnd())
00513                             return false;
00514                      return loadLayer( s, header);
00515               }
00516        }
00517        else
00518        {
00519               // Decoding simple psd file, no layers
00520               s.device()->at( s.device()->at() + layerDataLen );
00521               loadLayer( s, header);
00522        }
00523        return true;
00524 }
00525 
00526 bool ScImgDataLoader_PSD::parseLayer( QDataStream & s, const PSDHeader & header )
00527 {
00528        uint addRes, layerinfo, channelLen, signature, extradata, layermasksize, layerRange, dummy;
00529        int top, left, bottom, right;
00530        short numLayers, numChannels;
00531        short channelType;
00532        uchar blendKey[4];
00533        uchar opacity, clipping, flags, filler;
00534        QString layerName, blend;
00535        struct PSDLayer lay;
00536        s >> layerinfo;
00537        s >> numLayers;
00538        if (numLayers < 0)
00539               numLayers = -numLayers;
00540        if (numLayers != 0)
00541        {
00542               for (int layer = 0; layer < numLayers; layer++)
00543               {
00544                      s >> top;
00545                      lay.ypos = top;
00546                      s >> left;
00547                      lay.xpos = left;
00548                      s >> bottom;
00549                      lay.height = bottom - top;
00550                      s >> right;
00551                      lay.width = right - left;
00552                      s >> numChannels;
00553                      maxChannels = QMAX(maxChannels, numChannels);
00554                      if (numChannels > 6) // we don't support images with more than 6 channels yet
00555                      {
00556                             m_imageInfoRecord.layerInfo.clear();
00557                             return false;
00558                      }
00559                      lay.channelType.clear();
00560                      lay.channelLen.clear();
00561                      for (int channels = 0; channels < numChannels; channels++)
00562                      {
00563                             s >> channelType;
00564                             s >> channelLen;
00565                             lay.channelType.append(channelType);
00566                             lay.channelLen.append(channelLen);
00567                      }
00568                      s >> signature;
00569                      blend = "";
00570                      for( int i = 0; i < 4; i++ )
00571                      {
00572                             s >> blendKey[i];
00573                             blend += QChar(blendKey[i]);
00574                      }
00575                      lay.blend = blend;
00576                      s >> opacity;
00577                      lay.opacity = opacity;
00578                      s >> clipping;
00579                      lay.clipping = clipping;
00580                      s >> flags;
00581                      if (flags & 8)
00582                      {
00583                             if (flags & 16)      // Unknown combination of layer flags, probably an adjustment or effects layer
00584                             {
00585                                    m_imageInfoRecord.layerInfo.clear();
00586                                    return false;
00587                             }
00588                      }
00589                      lay.flags = flags;
00590                      s >> filler;
00591                      s >> extradata;
00592                      s >> layermasksize;
00593                      lay.maskYpos = 0;
00594                      lay.maskXpos = 0;
00595                      lay.maskHeight = 0;
00596                      lay.maskWidth = 0;
00597                      if (layermasksize != 0)
00598                      {
00599                             s >> lay.maskYpos;
00600                             s >> lay.maskXpos;
00601                             s >> dummy;
00602                             lay.maskHeight = dummy - lay.maskYpos;
00603                             s >> dummy;
00604                             lay.maskWidth = dummy - lay.maskXpos;
00605                             s >> dummy;
00606                      }
00607                      s >> layerRange;
00608                      s.device()->at( s.device()->at() + layerRange );
00609                      lay.layerName = getLayerString(s);
00610                      m_imageInfoRecord.layerInfo.append(lay);
00611                      s >> signature;
00612                      if( signature == 0x3842494D )
00613                      {
00614                             while (signature == 0x3842494D )
00615                             {
00616                                    s >> signature;
00617                                    s >> addRes;
00618                                    s.device()->at( s.device()->at() + addRes );
00619                                    s >> signature;
00620                             }
00621                             s.device()->at( s.device()->at() - 4 );
00622                      }
00623                      else
00624                      {
00625                             s.device()->at( s.device()->at() - 2 );
00626                             s >> signature;
00627                             if( signature == 0x3842494D )
00628                             {
00629                                    while (signature == 0x3842494D )
00630                                    {
00631                                           s >> signature;
00632                                           s >> addRes;
00633                                           s.device()->at( s.device()->at() + addRes );
00634                                           s >> signature;
00635                                    }
00636                                    s.device()->at( s.device()->at() - 4 );
00637                             }
00638                             else
00639                                    s.device()->at( s.device()->at() - 6 );
00640                      }
00641               }
00642               bool firstLayer = true;
00643               for (int layer = 0; layer < numLayers; layer++)
00644               {
00645                      loadLayerChannels( s, header, m_imageInfoRecord.layerInfo, layer, &firstLayer );
00646               }
00647        }
00648        else
00649        {
00650               s >> numLayers;
00651               loadLayer( s, header);
00652        }
00653        return true;
00654 }
00655 
00656 bool ScImgDataLoader_PSD::loadChannel( QDataStream & s, const PSDHeader & header, QValueList<PSDLayer> &layerInfo, uint layer, int channel, int component, RawImage &tmpImg)
00657 {
00658        uint base = s.device()->at();
00659        uchar cbyte;
00660        ushort compression;
00661        s >> compression;
00662        if( compression > 1 )
00663               return false;
00664        if (compression == 0)
00665        {
00666               int count = layerInfo[layer].channelLen[channel]-2;
00667               uchar *ptr;
00668               for (int i = 0; i < tmpImg.height(); i++)
00669               {
00670                      ptr =  tmpImg.scanLine(i);
00671                      for (int j = 0; j < tmpImg.width(); j++)
00672                      {
00673                             s >> cbyte;
00674                             count--;
00675                             if ((header.color_mode == CM_CMYK) && (component < 4))
00676                                    cbyte = 255 - cbyte;
00677                             if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
00678                             {
00679                                    ptr[0] = cbyte;
00680                                    ptr[1] = cbyte;
00681                                    ptr[2] = cbyte;
00682                             }
00683                             else if ((header.color_mode == CM_DUOTONE) && (component != 3))
00684                             {
00685                                    ptr -= component;
00686                                    putDuotone(ptr, cbyte);
00687                                    ptr += component;
00688                             }
00689                             else if ((header.color_mode == CM_INDEXED) && (component != 3))
00690                             {
00691                                    int ccol = colorTable[cbyte];
00692                                    ptr[0] = qRed(ccol);
00693                                    ptr[1] = qGreen(ccol);
00694                                    ptr[2] = qBlue(ccol);
00695                             }
00696                             else
00697                                    ptr[component] = cbyte;
00698                             if (count == 0)
00699                                    break;
00700                             ptr += tmpImg.channels();
00701                      }
00702                      if (count == 0)
00703                             break;
00704               }
00705        }
00706        else
00707        {
00708               s.device()->at( s.device()->at() + tmpImg.height() * 2 );
00709               uint pixel_count = tmpImg.width();
00710               uchar *ptr;
00711               uchar *ptr2;
00712               uint count, len;
00713               uchar c;
00714               for (int hh = 0; hh < tmpImg.height(); hh++)
00715               {
00716                      count = 0;
00717                      ptr = tmpImg.scanLine(hh);
00718                      ptr2 = ptr+tmpImg.width() * tmpImg.channels();
00719                      ptr += component;
00720                      while( count < pixel_count )
00721                      {
00722                             if(s.atEnd())
00723                                    return false;
00724                             s >> c;
00725                             len = c;
00726                             if( len < 128 )
00727                             {
00728                                    // Copy next len+1 bytes literally.
00729                                    len++;
00730                                    count += len;
00731                                    while( len != 0 )
00732                                    {
00733                                           s >> cbyte;
00734                                           if (ptr < ptr2)
00735                                           {
00736                                                  if ((header.color_mode == CM_CMYK) && (component < 4))
00737                                                         cbyte = 255 - cbyte;
00738                                                  if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
00739                                                  {
00740                                                         ptr -= component;
00741                                                         ptr[0] = cbyte;
00742                                                         ptr[1] = cbyte;
00743                                                         ptr[2] = cbyte;
00744                                                         ptr += component;
00745                                                  }
00746                                                  else if ((header.color_mode == CM_DUOTONE) && (component != 3))
00747                                                  {
00748                                                         ptr -= component;
00749                                                         putDuotone(ptr, cbyte);
00750                                                         ptr += component;
00751                                                  }
00752                                                  else if ((header.color_mode == CM_INDEXED) && (component != 3))
00753                                                  {
00754                                                         ptr -= component;
00755                                                         int ccol = colorTable[cbyte];
00756                                                         ptr[0] = qRed(ccol);
00757                                                         ptr[1] = qGreen(ccol);
00758                                                         ptr[2] = qBlue(ccol);
00759                                                         ptr += component;
00760                                                  }
00761                                                  else
00762                                                  {
00763                                                         *ptr = cbyte;
00764                                                  }
00765                                           }
00766                                           ptr += tmpImg.channels();
00767                                           len--;
00768                                    }
00769                             }
00770                             else if( len > 128 )
00771                             {
00772                                    // Next -len+1 bytes in the dest are replicated from next source byte.
00773                                    // (Interpret len as a negative 8-bit int.)
00774                                    len ^= 0xFF;
00775                                    len += 2;
00776                                    count += len;
00777                                    uchar val;
00778                                    s >> val;
00779                                    if ((header.color_mode == CM_CMYK) && (component < 4))
00780                                           val = 255 - val;
00781                                    while( len != 0 )
00782                                    {
00783                                           if (ptr < ptr2)
00784                                           {
00785                                                  if ((header.color_mode == CM_GRAYSCALE) && (component != 3))
00786                                                  {
00787                                                         ptr -= component;
00788                                                         ptr[0] = val;
00789                                                         ptr[1] = val;
00790                                                         ptr[2] = val;
00791                                                         ptr += component;
00792                                                  }
00793                                                  else if ((header.color_mode == CM_DUOTONE) && (component != 3))
00794                                                  {
00795                                                         ptr -= component;
00796                                                         putDuotone(ptr, val);
00797                                                         ptr += component;
00798                                                  }
00799                                                  else if ((header.color_mode == CM_INDEXED) && (component != 3))
00800                                                  {
00801                                                         ptr -= component;
00802                                                         int ccol = colorTable[val];
00803                                                         ptr[0] = qRed(ccol);
00804                                                         ptr[1] = qGreen(ccol);
00805                                                         ptr[2] = qBlue(ccol);
00806                                                         ptr += component;
00807                                                  }
00808                                                  else
00809                                                         *ptr = val;
00810                                           }
00811                                           ptr += tmpImg.channels();
00812                                           len--;
00813                                    }
00814                             }
00815                             else if( len == 128 )
00816                             {
00817                                    // No-op.
00818                             }
00819                      }
00820               }
00821        }
00822        s.device()->at( base+layerInfo[layer].channelLen[channel] );
00823        return true;
00824 }
00825 
00826 bool ScImgDataLoader_PSD::loadLayerChannels( QDataStream & s, const PSDHeader & header, QValueList<PSDLayer> &layerInfo, uint layer, bool* firstLayer)
00827 {
00828        // Find out if the data is compressed.
00829        // Known values:
00830        //   0: no compression
00831        //   1: RLE compressed
00832        uint base = s.device()->at();
00833        uint base2 = base;
00834        uint channel_num = layerInfo[layer].channelLen.count();
00835        bool hasMask = false;
00836        bool hasAlpha = false;
00837        RawImage r2_image;
00838        RawImage mask;
00839        bool createOk = false;
00840        if (header.color_mode == CM_CMYK)
00841        {
00842               createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, QMAX(channel_num, 5));
00843               r2_image.fill(0);
00844        }
00845        else
00846        {
00847               createOk = r2_image.create(layerInfo[layer].width, layerInfo[layer].height, QMAX(channel_num, 4));
00848               r2_image.fill(0);
00849        }
00850        if( !createOk )
00851        {
00852               for(uint channel = 0; channel < channel_num; channel++)
00853               {
00854                      base2 += layerInfo[layer].channelLen[channel];
00855               }
00856               s.device()->at( base2 );
00857               return false;
00858        }
00859        channel_num = QMIN(channel_num, 39);
00860        uint components[40];
00861        for(uint channel = 0; channel < channel_num; channel++)
00862        {
00863               switch(layerInfo[layer].channelType[channel])
00864               {
00865               case 0:
00866                      components[channel] = 0;
00867                      break;
00868               case 1:
00869                      components[channel] = 1;
00870                      break;
00871               case 2:
00872                      components[channel] = 2;
00873                      break;
00874               case 3:
00875                      components[channel] = 3;
00876                      break;
00877               case -1:
00878                      if (header.color_mode == CM_CMYK)
00879                      {
00880                             if (channel_num == 6)
00881                                    components[channel] = channel_num-2;
00882                             else
00883                                    components[channel] = channel_num-1;
00884                      }
00885                      else
00886                      {
00887                             if (channel_num == 5)
00888                                    components[channel] = channel_num-2;
00889                             else
00890                                    components[channel] = channel_num-1;
00891                      }
00892                      hasAlpha = true;
00893                      break;
00894               case -2:
00895                      components[channel] = channel_num-1;
00896                      break;
00897               }
00898        }
00899        if (!hasAlpha)
00900               r2_image.fill(255);
00901        for(uint channel = 0; channel < channel_num; channel++)
00902        {
00903               if (layerInfo[layer].channelType[channel] == -2)
00904               {
00905                      if (!mask.create( layerInfo[layer].maskWidth, layerInfo[layer].maskHeight, 1 ))
00906                             break;
00907                      mask.fill(0);
00908                      if (!loadChannel(s, header, layerInfo, layer, channel, 0, mask))
00909                             break;
00910                      hasMask = true;
00911               }
00912               if (!loadChannel(s, header, layerInfo, layer, channel, components[channel], r2_image))
00913                      break;
00914        }
00915        for(uint channel = 0; channel < channel_num; channel++)
00916        {
00917               base2 += layerInfo[layer].channelLen[channel];
00918        }
00919        if (header.color_mode == CM_LABCOLOR)
00920        {
00921               cmsHPROFILE hsRGB = cmsCreate_sRGBProfile();
00922               cmsHPROFILE hLab  = cmsCreateLabProfile(NULL);
00923               DWORD inputProfFormat = (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1));
00924               cmsHTRANSFORM xform = cmsCreateTransform(hLab, inputProfFormat, hsRGB, TYPE_RGBA_8, INTENT_PERCEPTUAL, 0);
00925               for (int i = 0; i < r2_image.height(); i++)
00926               {
00927                      LPBYTE ptr = r2_image.scanLine(i);
00928                      cmsDoTransform(xform, ptr, ptr, r2_image.width());
00929               }
00930               cmsDeleteTransform (xform);
00931               cmsCloseProfile(hsRGB);
00932               cmsCloseProfile(hLab);
00933        }
00934        s.device()->at( base2 );
00935        QImage tmpImg2;
00936        if (header.color_mode == CM_CMYK)
00937               tmpImg2 = r2_image.convertToQImage(true);
00938        else
00939               tmpImg2 = r2_image.convertToQImage(false);
00940        QImage imt;
00941        double sx = tmpImg2.width() / 40.0;
00942        double sy = tmpImg2.height() / 40.0;
00943        imt = sy < sx ?  tmpImg2.smoothScale(qRound(tmpImg2.width() / sx), qRound(tmpImg2.height() / sx)) :
00944              tmpImg2.smoothScale(qRound(tmpImg2.width() / sy), qRound(tmpImg2.height() / sy));
00945        layerInfo[layer].thumb = imt.copy();
00946        if (hasMask)
00947        {
00948               QImage imt2;
00949               QImage tmpImg;
00950               tmpImg = mask.convertToQImage(true);
00951               double sx = tmpImg.width() / 40.0;
00952               double sy = tmpImg.height() / 40.0;
00953               imt2 = sy < sx ?  tmpImg.smoothScale(qRound(tmpImg.width() / sx), qRound(tmpImg.height() / sx)) :
00954              tmpImg.smoothScale(qRound(tmpImg.width() / sy), qRound(tmpImg.height() / sy));
00955               imt2.invertPixels();
00956               layerInfo[layer].thumb_mask = imt2.copy();
00957        }
00958        else
00959               layerInfo[layer].thumb_mask = QImage();
00960        if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
00961               m_imageInfoRecord.RequestProps[layer].useMask = m_imageInfoRecord.RequestProps[layer].useMask;
00962        else
00963               m_imageInfoRecord.RequestProps[layer].useMask = true;
00964        bool visible = !(layerInfo[layer].flags & 2);
00965        if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
00966               visible = m_imageInfoRecord.RequestProps[layer].visible;
00967        if (visible)
00968        {
00969               unsigned int startSrcY, startSrcX, startDstY, startDstX;
00970               if (layerInfo[layer].ypos < 0)
00971               {
00972                      startSrcY = abs(layerInfo[layer].ypos);
00973                      startDstY = 0;
00974               }
00975               else
00976               {
00977                      startSrcY = 0;
00978                      startDstY = layerInfo[layer].ypos;
00979               }
00980               if (layerInfo[layer].xpos < 0)
00981               {
00982                      startSrcX = abs(layerInfo[layer].xpos);
00983                      startDstX = 0;
00984               }
00985               else
00986               {
00987                      startSrcX = 0;
00988                      startDstX = layerInfo[layer].xpos;
00989               }
00990               unsigned int startSrcYm, startSrcXm, startDstYm, startDstXm;
00991               if (layerInfo[layer].maskYpos < 0)
00992               {
00993                      startSrcYm = abs(layerInfo[layer].maskYpos);
00994                      startDstYm = 0;
00995               }
00996               else
00997               {
00998                      startSrcYm = 0;
00999                      startDstYm = layerInfo[layer].maskYpos;
01000               }
01001               if (layerInfo[layer].maskXpos < 0)
01002               {
01003                      startSrcXm = abs(layerInfo[layer].maskXpos);
01004                      startDstXm = 0;
01005               }
01006               else
01007               {
01008                      startSrcXm = 0;
01009                      startDstXm = layerInfo[layer].maskXpos;
01010               }
01011               QString layBlend2 = layerInfo[layer].blend;
01012               if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
01013                      layBlend2 = m_imageInfoRecord.RequestProps[layer].blend;
01014               if (layBlend2 == "diss")
01015               {
01016                      hasAlpha = true;
01017                      int layOpa = layerInfo[layer].opacity;
01018                      if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
01019                             layOpa = m_imageInfoRecord.RequestProps[layer].opacity;
01020                      for (int l = 0; l < r2_image.height(); l++)
01021                      {
01022                             srand(random_table[ l  % 4096]);
01023                             for (int k = 0; k < r2_image.width(); k++)
01024                             {
01025                                    int rand_val = rand() & 0xff;
01026                                    if (rand_val > layOpa)
01027                                           r2_image.setAlpha(k, l, 0);
01028                             }
01029                      }
01030               }
01031               if (*firstLayer)
01032               {
01033                      unsigned char *s;
01034                      unsigned char *d;
01035                      for( int yi=static_cast<int>(startSrcY); yi < QMIN(r2_image.height(),  r_image.height()); ++yi )
01036                      {
01037                             s = r2_image.scanLine( yi );
01038                             d = r_image.scanLine( QMIN(static_cast<int>(startDstY),  r_image.height()-1) );
01039                             d += QMIN(static_cast<int>(startDstX), r_image.width()-1) * r_image.channels();
01040                             s += QMIN(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels();
01041                             for(int xi=static_cast<int>(startSrcX); xi < QMIN(r2_image.width(),  r_image.width()); ++xi )
01042                             {
01043                                    d[0] = s[0];
01044                                    d[1] = s[1];
01045                                    d[2] = s[2];
01046                                    if (header.color_mode == CM_RGB)
01047                                    {
01048                                           if (hasAlpha)
01049                                                  d[3] = s[3];
01050                                           else
01051                                                  d[3] = 255;
01052                                    }
01053                                    else
01054                                    {
01055                                           d[3] = s[3];
01056                                           if (hasAlpha)
01057                                                  d[4] = s[4];
01058                                           else
01059                                                  d[4] = 255;
01060                                    }
01061                                    s += r2_image.channels();
01062                                    d += r_image.channels();
01063                             }
01064                             startDstY++;
01065                      }
01066               }
01067               else
01068               {
01069                      unsigned char *s;
01070                      unsigned char *d;
01071                      unsigned char *sm = 0;
01072                      unsigned char r, g, b, src_r, src_g, src_b, src_a, src_alpha, dst_alpha;
01073                      unsigned char a = 0;
01074                      uchar new_r, new_g, new_b;
01075                      unsigned int maxDestX;
01076                      for (int i = static_cast<int>(startSrcY); i < layerInfo[layer].height; i++)
01077                      {
01078                             d = r_image.scanLine(QMIN(static_cast<int>(startDstY),  r_image.height()-1));
01079                             s = r2_image.scanLine(QMIN(i, r2_image.height()-1));
01080                             d += QMIN(static_cast<int>(startDstX),  r_image.width()-1) * r_image.channels();
01081                             s += QMIN(static_cast<int>(startSrcX), r2_image.width()-1) * r2_image.channels();
01082                             sm = 0;
01083                             if (hasMask)
01084                             {
01085                                    sm = mask.scanLine(QMIN(i, mask.height()-1));
01086                                    sm += QMIN(static_cast<int>(startSrcXm), mask.width()-1) * mask.channels();
01087                             }
01088                             startDstY++;
01089                             maxDestX = r_image.width() - startDstX + startSrcX - 1;
01090                             for (unsigned int j = startSrcX; j < QMIN(maxDestX, static_cast<unsigned int>(layerInfo[layer].width)); j++)
01091                             {
01092                                    src_r = s[0];
01093                                    src_g = s[1];
01094                                    src_b = s[2];
01095                                    src_a = s[3];
01096                                    if (hasAlpha)
01097                                    {
01098                                           if (hasMask)
01099                                           {
01100                                                  if (m_imageInfoRecord.RequestProps[layer].useMask)
01101                                                         src_alpha = sm[0];
01102                                                  else
01103                                                         src_alpha = s[channel_num - 2];
01104                                           }
01105                                           else
01106                                                  src_alpha = s[channel_num - 1];
01107                                    }
01108                                    else
01109                                           src_alpha = 255;
01110                                    if ((hasMask) && (m_imageInfoRecord.RequestProps[layer].useMask))
01111                                           src_alpha = sm[0];
01112                                    int layOpa = layerInfo[layer].opacity;
01113                                    if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
01114                                           layOpa = m_imageInfoRecord.RequestProps[layer].opacity;
01115                                    QString layBlend = layerInfo[layer].blend;
01116                                    if ((m_imageInfoRecord.isRequest) && (m_imageInfoRecord.RequestProps.contains(layer)))
01117                                           layBlend = m_imageInfoRecord.RequestProps[layer].blend;
01118                                    if (layBlend != "diss")
01119                                           src_alpha = INT_MULT(src_alpha, layOpa);
01120                                    if (header.color_mode == CM_CMYK)
01121                                           dst_alpha = d[4];
01122                                    else
01123                                           dst_alpha = d[3];
01124                                    if ((dst_alpha > 0) && (src_alpha > 0))
01125                                    {
01126                                           if (layBlend == "mul ")
01127                                           {
01128                                                  src_r = INT_MULT(src_r, d[0]);
01129                                                  src_g = INT_MULT(src_g, d[1]);
01130                                                  src_b = INT_MULT(src_b, d[2]);
01131                                                  if (header.color_mode == CM_CMYK)
01132                                                         src_a = INT_MULT(src_a, d[3]);
01133                                           }
01134                                           else if (layBlend == "scrn")
01135                                           {
01136                                                  src_r = 255 - ((255-src_r) * (255-d[0]) / 128);
01137                                                  src_g = 255 - ((255-src_g) * (255-d[1]) / 128);
01138                                                  src_b = 255 - ((255-src_b) * (255-d[2]) / 128);
01139                                                  if (header.color_mode == CM_CMYK)
01140                                                         src_a = 255 - ((255-src_a) * (255-d[3]) / 128);
01141                                           }
01142                                           else if (layBlend == "over")
01143                                           {
01144                                                  src_g = d[1] < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128);
01145                                                  src_b = d[2] < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128);
01146                                                  src_a = d[3] < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128);
01147                                                  if (header.color_mode == CM_CMYK)
01148                                                         src_r = d[0] < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128);
01149                                           }
01150                                           else if (layBlend == "diff")
01151                                           {
01152                                                  src_r = d[0] > src_r ? d[0] - src_r : src_r - d[0];
01153                                                  src_g = d[1] > src_g ? d[1] - src_g : src_g - d[1];
01154                                                  src_b = d[2] > src_b ? d[2] - src_b : src_b - d[2];
01155                                                  if (header.color_mode == CM_CMYK)
01156                                                         src_a = d[3] > src_a ? d[3] - src_a : src_a - d[3];
01157                                           }
01158                                           else if (layBlend == "dark")
01159                                           {
01160                                                  src_r = d[0]  < src_r ? d[0]  : src_r;
01161                                                  src_g = d[1] < src_g ? d[1] : src_g;
01162                                                  src_b = d[2] < src_b ? d[2] : src_b;
01163                                                  if (header.color_mode == CM_CMYK)
01164                                                         src_a = d[3] < src_a ? d[3] : src_a;
01165                                           }
01166                                           else if (layBlend == "hLit")
01167                                           {
01168                                                  src_r = src_r < 128 ? src_r * d[0] / 128 : 255 - ((255-src_r) * (255-d[0]) / 128);
01169                                                  src_g = src_g < 128 ? src_g * d[1] / 128 : 255 - ((255-src_g) * (255-d[1]) / 128);
01170                                                  src_b = src_b < 128 ? src_b * d[2] / 128 : 255 - ((255-src_b) * (255-d[2]) / 128);
01171                                                  if (header.color_mode == CM_CMYK)
01172                                                         src_a = src_a < 128 ? src_a * d[3] / 128 : 255 - ((255-src_a) * (255-d[3]) / 128);
01173                                           }
01174                                           else if (layBlend == "sLit")
01175                                           {
01176                                                  src_r = src_r * d[0] / 256 + src_r * (255 - ((255-src_r)*(255-d[0]) / 256) - src_r * d[0] / 256) / 256;
01177                                                  src_g = src_g * d[1] / 256 + src_g * (255 - ((255-src_g)*(255-d[1]) / 256) - src_g * d[1] / 256) / 256;
01178                                                  src_b = src_b * d[2] / 256 + src_b * (255 - ((255-src_b)*(255-d[2]) / 256) - src_b * d[2] / 256) / 256;
01179                                                  if (header.color_mode == CM_CMYK)
01180                                                         src_a = src_a * d[3] / 256 + src_a * (255 - ((255-src_a)*(255-d[3]) / 256) - src_a * d[3] / 256) / 256;
01181                                           }
01182                                           else if (layBlend == "lite")
01183                                           {
01184                                                  src_r = d[0] < src_r ? src_r : d[0];
01185                                                  src_g = d[1] < src_g ? src_g : d[1];
01186                                                  src_b = d[2] < src_b ? src_b : d[2];
01187                                                  if (header.color_mode == CM_CMYK)
01188                                                         src_a = d[3] < src_a ? src_a : d[3];
01189                                           }
01190                                           else if (layBlend == "smud")
01191                                           {
01192                                                  src_r = d[0] + src_r - src_r * d[0] / 128;
01193                                                  src_g = d[1] + src_g - src_g * d[1] / 128;
01194                                                  src_b = d[2] + src_b - src_b * d[2] / 128;
01195                                                  if (header.color_mode == CM_CMYK)
01196                                                         src_a = d[3] + src_a - src_a * d[3] / 128;
01197                                           }
01198                                           else if (layBlend == "div ")
01199                                           {
01200                                                  src_r = src_r == 255 ? 255 : ((d[0] * 256) / (255-src_r)) > 255 ? 255 : (d[0] * 256) / (255-src_r);
01201                                                  src_g = src_g == 255 ? 255 : ((d[1] * 256) / (255-src_g)) > 255 ? 255 : (d[1] * 256) / (255-src_g);
01202                                                  src_b = src_b == 255 ? 255 : ((d[2] * 256) / (255-src_b)) > 255 ? 255 : (d[2] * 256) / (255-src_b);
01203                                                  if (header.color_mode == CM_CMYK)
01204                                                         src_a = src_a == 255 ? 255 : ((d[3] * 256) / (255-src_a)) > 255 ? 255 : (d[3] * 256) / (255-src_a);
01205                                           }
01206                                           else if (layBlend == "idiv")
01207                                           {
01208                                                  src_r = src_r == 0 ? 0 : (255 - (((255-d[0]) * 256) / src_r)) < 0 ? 0 : 255 - (((255-d[0]) * 256) / src_r);
01209                                                  src_g = src_g == 0 ? 0 : (255 - (((255-d[1]) * 256) / src_g)) < 0 ? 0 : 255 - (((255-d[1]) * 256) / src_g);
01210                                                  src_b = src_b == 0 ? 0 : (255 - (((255-d[2]) * 256) / src_b)) < 0 ? 0 : 255 - (((255-d[2]) * 256) / src_b);
01211                                                  if (header.color_mode == CM_CMYK)
01212                                                         src_a = src_a == 0 ? 0 : (255 - (((255-d[3]) * 256) / src_a)) < 0 ? 0 : 255 - (((255-d[3]) * 256) / src_a);
01213                                           }
01214                                           else if (layBlend == "hue ")
01215                                           {
01216                                                  if (header.color_mode != CM_CMYK)
01217                                                  {
01218                                                         new_r = d[0];
01219                                                         new_g = d[1];
01220                                                         new_b = d[2];
01221                                                         RGBTOHSV(src_r, src_g, src_b);
01222                                                         RGBTOHSV(new_r, new_g, new_b);
01223                                                         new_r = src_r;
01224                                                         HSVTORGB(new_r, new_g, new_b);
01225                                                         src_r = new_r;
01226                                                         src_g = new_g;
01227                                                         src_b = new_b;
01228                                                  }
01229                                           }
01230                                           else if (layBlend == "sat ")
01231                                           {
01232                                                  if (header.color_mode != CM_CMYK)
01233                                                  {
01234                                                         new_r = d[0];
01235                                                         new_g = d[1];
01236                                                         new_b = d[2];
01237                                                         RGBTOHSV(src_r, src_g, src_b);
01238                                                         RGBTOHSV(new_r, new_g, new_b);
01239                                                         new_g = src_g;
01240                                                         HSVTORGB(new_r, new_g, new_b);
01241                                                         src_r = new_r;
01242                                                         src_g = new_g;
01243                                                         src_b = new_b;
01244                                                  }
01245                                           }
01246                                           else if (layBlend == "lum ")
01247                                           {
01248                                                  if (header.color_mode != CM_CMYK)
01249                                                  {
01250                                                         new_r = d[0];
01251                                                         new_g = d[1];
01252                                                         new_b = d[2];
01253                                                         RGBTOHSV(src_r, src_g, src_b);
01254                                                         RGBTOHSV(new_r, new_g, new_b);
01255                                                         new_b = src_b;
01256                                                         HSVTORGB(new_r, new_g, new_b);
01257                                                         src_r = new_r;
01258                                                         src_g = new_g;
01259                                                         src_b = new_b;
01260                                                  }
01261                                           }
01262                                           else if (layBlend == "colr")
01263                                           {
01264                                                  if (header.color_mode != CM_CMYK)
01265                                                  {
01266                                                         new_r = d[0];
01267                                                         new_g = d[1];
01268                                                         new_b = d[2];
01269                                                         RGBTOHLS(src_r, src_g, src_b);
01270                                                         RGBTOHLS(new_r, new_g, new_b);
01271                                                         new_r = src_r;
01272                                                         new_b = src_b;
01273                                                         HLSTORGB(new_r, new_g, new_b);
01274                                                         src_r = new_r;
01275                                                         src_g = new_g;
01276                                                         src_b = new_b;
01277                                                  }
01278                                           }
01279                                    }
01280                                    if (dst_alpha == 0)
01281                                    {
01282                                           r = src_r;
01283                                           g = src_g;
01284                                           b = src_b;
01285                                           a = src_a;
01286                                    }
01287                                    else
01288                                    {
01289                                           if (src_alpha > 0)
01290                                           {
01291                                                  r = (d[0] * (255 - src_alpha) + src_r * src_alpha) / 255;
01292                                                  g = (d[1] * (255 - src_alpha) + src_g * src_alpha) / 255;
01293                                                  b = (d[2] * (255 - src_alpha) + src_b * src_alpha) / 255;
01294                                                  if (header.color_mode == CM_CMYK)
01295                                                         a = (d[3] * (255 - src_alpha) + src_a * src_alpha) / 255;
01296                                                  if (layBlend != "diss")
01297                                                         src_alpha = dst_alpha + INT_MULT(255 - dst_alpha, src_alpha);
01298                                           }
01299                                    }
01300                                    if (src_alpha > 0)
01301                                    {
01302                                           d[0] = r;
01303                                           d[1] = g;
01304                                           d[2] = b;
01305                                           if (header.color_mode == CM_CMYK)
01306                                           {
01307                                                  d[3] = a;
01308                                                  d[4] = src_alpha;
01309                                           }
01310                                           else
01311                                                  d[3] = src_alpha;
01312                                    }
01313                                    s += r2_image.channels();
01314                                    d += r_image.channels();
01315                                    if (hasMask)
01316                                           sm += mask.channels();
01317                             }
01318                      }
01319               }
01320        }
01321        *firstLayer = false;
01322        return true;
01323 }
01324 
01325 bool ScImgDataLoader_PSD::loadLayer( QDataStream & s, const PSDHeader & header )
01326 {
01327        // Find out if the data is compressed.
01328        // Known values:
01329        //   0: no compression
01330        //   1: RLE compressed
01331        ushort compression;
01332        uchar cbyte;
01333        s >> compression;
01334        if( compression > 1 )
01335        {
01336               // Unknown compression type.
01337               return false;
01338        }
01339        uint channel_num = header.channel_count;
01340        r_image.fill(255);
01341        const uint pixel_count = header.height * header.width;
01342        static const uint components[5] = {0, 1, 2, 3, 4};
01343        if( compression )
01344        {
01345               // Skip row lengths.
01346               ushort w;
01347               for(uint i = 0; i < header.height * header.channel_count; i++)
01348               {
01349                      s >> w;
01350               }
01351               // Read RLE data.
01352               uchar * ptr;
01353               uint count = 0;
01354               uchar c;
01355               uint len;
01356               for(uint channel = 0; channel < channel_num; channel++)
01357               {
01358                      ptr = r_image.bits() + components[channel];
01359                      count = 0;
01360                      while( count < pixel_count )
01361                      {
01362                             if(s.atEnd())
01363                                    return false;
01364                             s >> c;
01365                             len = c;
01366                             if( len < 128 )
01367                             {
01368                                    // Copy next len+1 bytes literally.
01369                                    len++;
01370                                    count += len;
01371                                    if ( count > pixel_count )
01372                                           return false;
01373                                    while( len != 0 )
01374                                    {
01375                                           s >> cbyte;
01376                                           if ((header.color_mode == CM_CMYK) && (components[channel] < 4))
01377                                                  cbyte = 255 - cbyte;
01378                                           if ((header.color_mode == CM_GRAYSCALE) && (components[channel] != 3))
01379                                           {
01380                                                  ptr -= components[channel];
01381                                                  ptr[0] = cbyte;
01382                                                  ptr[1] = cbyte;
01383                                                  ptr[2] = cbyte;
01384                                                  ptr += components[channel];
01385                                           }
01386                                           else if ((header.color_mode == CM_DUOTONE) && (components[channel] != 3))
01387                                           {
01388                                                  ptr -= components[channel];
01389                                                  putDuotone(ptr, cbyte);
01390                                                  ptr += components[channel];
01391                                           }
01392                                           else if ((header.color_mode == CM_INDEXED) && (components[channel] != 3))
01393                                           {
01394                                                  ptr -= components[channel];
01395                                                  int ccol = colorTable[cbyte];
01396                                                  ptr[0] = qRed(ccol);
01397                                                  ptr[1] = qGreen(ccol);
01398                                                  ptr[2] = qBlue(ccol);
01399                                                  ptr += components[channel];
01400                                           }
01401                                           else
01402                                                  *ptr = cbyte;
01403                                           ptr += r_image.channels();
01404                                           len--;
01405                                    }
01406                             }
01407                             else if( len > 128 )
01408                             {
01409                                    // Next -len+1 bytes in the dest are replicated from next source byte.
01410                                    // (Interpret len as a negative 8-bit int.)
01411                                    len ^= 0xFF;
01412                                    len += 2;
01413                                    count += len;
01414                                    if(s.atEnd() || count > pixel_count)
01415                                           return false;
01416                                    uchar val;
01417                                    s >> val;
01418                                    if ((header.color_mode == CM_CMYK) && (components[channel] < 4))
01419                                           val = 255 - val;
01420                                    while( len != 0 )
01421                                    {
01422                                           if ((header.color_mode == CM_GRAYSCALE) && (components[channel] != 3))
01423                                           {
01424                                                  ptr -= components[channel];
01425                                                  ptr[0] = val;
01426                                                  ptr[1] = val;
01427                                                  ptr[2] = val;
01428                                                  ptr += components[channel];
01429                                           }
01430                                           else if ((header.color_mode == CM_DUOTONE) && (components[channel] != 3))
01431                                           {
01432                                                  ptr -= components[channel];
01433                                                  putDuotone(ptr, val);
01434                                                  ptr += components[channel];
01435                                           }
01436                                           else if ((header.color_mode == CM_INDEXED) && (components[channel] != 3))
01437                                           {
01438                                                  ptr -= components[channel];
01439                                                  int ccol = colorTable[val];
01440                                                  ptr[0] = qRed(ccol);
01441                                                  ptr[1] = qGreen(ccol);
01442                                                  ptr[2] = qBlue(ccol);
01443                                                  ptr += components[channel];
01444                                           }
01445                                           else
01446                                                  *ptr = val;
01447                                           ptr += r_image.channels();
01448                                           len--;
01449                                    }
01450                             }
01451                             else if( len == 128 )
01452                             {
01453                                    // No-op.
01454                             }
01455                      }
01456               }
01457        }
01458        else
01459        {
01460               // We're at the raw image data.  It's each channel in order (Red, Green, Blue, Alpha, ...)
01461               // where each channel consists of an 8-bit value for each pixel in the image.
01462               // Read the data by channel.
01463               uchar * ptr;
01464               uint count = 0;
01465               for(uint channel = 0; channel < channel_num; channel++)
01466               {
01467                      ptr =  r_image.bits() + components[channel];
01468                      // Read the data.
01469                      count = pixel_count;
01470                      while( count != 0 )
01471                      {
01472                             s >> cbyte;
01473                             if ((header.color_mode == CM_CMYK) && (components[channel] < 4))
01474                                    cbyte = 255 - cbyte;
01475                             if ((header.color_mode == CM_GRAYSCALE) && (components[channel] != 3))
01476                             {
01477                                    ptr -= components[channel];
01478                                    ptr[0] = cbyte;
01479                                    ptr[1] = cbyte;
01480                                    ptr[2] = cbyte;
01481                                    ptr += components[channel];
01482                             }
01483                             else if ((header.color_mode == CM_DUOTONE) && (components[channel] != 3))
01484                             {
01485                                    ptr -= components[channel];
01486                                    putDuotone(ptr, cbyte);
01487                                    ptr += components[channel];
01488                             }
01489                             else if ((header.color_mode == CM_INDEXED) && (components[channel] != 3))
01490                             {
01491                                    ptr -= components[channel];
01492                                    int ccol = colorTable[cbyte];
01493                                    ptr[0] = qRed(ccol);
01494                                    ptr[1] = qGreen(ccol);
01495                                    ptr[2] = qBlue(ccol);
01496                                    ptr += components[channel];
01497                             }
01498                             else
01499                                    *ptr = cbyte;
01500                             ptr += r_image.channels();
01501                             count--;
01502                      }
01503               }
01504        }
01505        if (header.color_mode == CM_LABCOLOR)
01506        {
01507               cmsHPROFILE hsRGB = cmsCreate_sRGBProfile();
01508               cmsHPROFILE hLab  = cmsCreateLabProfile(NULL);
01509               DWORD inputProfFormat = (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1));
01510               cmsHTRANSFORM xform = cmsCreateTransform(hLab, inputProfFormat, hsRGB, TYPE_RGBA_8, INTENT_PERCEPTUAL, 0);
01511               for (int i = 0; i < r_image.height(); i++)
01512               {
01513                      LPBYTE ptr = r_image.scanLine(i);
01514                      cmsDoTransform(xform, ptr, ptr, r_image.width());
01515               }
01516               cmsDeleteTransform (xform);
01517               cmsCloseProfile(hsRGB);
01518               cmsCloseProfile(hLab);
01519        }
01520        return true;
01521 }
01522 
01523 QString ScImgDataLoader_PSD::getLayerString(QDataStream & s)
01524 {
01525        uchar len, tmp;
01526        uint adj;
01527        QString ret = "";
01528        s >> len;
01529        if (len == 0)
01530        {
01531               s >> tmp;
01532               s >> tmp;
01533               s >> tmp;
01534               return ret;
01535        }
01536        for( int i = 0; i < len; i++ )
01537        {
01538               s >> tmp;
01539               ret += QChar(tmp);
01540        }
01541        adj = 0;
01542        if (((ret.length()+1) % 4) != 0)
01543               adj = 4 - ((ret.length()+1) % 4);
01544        s.device()->at( s.device()->at() + adj );
01545        return ret;
01546 }
01547 
01548 bool ScImgDataLoader_PSD::IsValid( const PSDHeader & header )
01549 {
01550        if( header.signature != 0x38425053 )
01551               return false;
01552        return true;
01553 }
01554 
01555 // Check that the header is supported.
01556 bool ScImgDataLoader_PSD::IsSupported( const PSDHeader & header )
01557 {
01558        if ( header.version != 1 )
01559               return false;
01560        if ( header.channel_count > 16 )
01561               return false;
01562        if ( header.depth != 8 )
01563               return false;
01564        if ((header.color_mode == CM_RGB) || (header.color_mode == CM_CMYK) || (header.color_mode == CM_LABCOLOR)
01565         || (header.color_mode == CM_GRAYSCALE) || (header.color_mode == CM_INDEXED) || (header.color_mode == CM_DUOTONE))
01566               return true;
01567        return false;
01568 }
01569 
01570 void ScImgDataLoader_PSD::putDuotone(uchar *ptr, uchar cbyte)
01571 {
01572        CMYKColor cmyk;
01573        int c, c1, c2, c3, m, m1, m2, m3, y, y1, y2, y3, k, k1, k2, k3;
01574        uchar cb = 255 - cbyte;
01575        ScColor col;
01576        if (colorTableSc.count() == 1)
01577        {
01578               colorTableSc[0].getRawRGBColor(&c, &m, &y);
01579               ptr[0] = QMIN((c * curveTable1[(int)cbyte]) >> 8, 255);
01580               ptr[1] = QMIN((m * curveTable1[(int)cbyte]) >> 8, 255);
01581               ptr[2] = QMIN((y * curveTable1[(int)cbyte]) >> 8, 255);
01582        }
01583        else if (colorTableSc.count() == 2)
01584        {
01585               ScColorEngine::getCMYKValues(colorTableSc[0], NULL, cmyk);
01586               cmyk.getValues(c, m, y, k);
01587               c = QMIN((c * curveTable1[(int)cb]) >> 8, 255);
01588               m = QMIN((m * curveTable1[(int)cb]) >> 8, 255);
01589               y = QMIN((y * curveTable1[(int)cb]) >> 8, 255);
01590               k = QMIN((k * curveTable1[(int)cb]) >> 8, 255);
01591               ScColorEngine::getCMYKValues(colorTableSc[1], NULL, cmyk);
01592               cmyk.getValues(c1, m1, y1, k1);
01593               c1 = QMIN((c1 * curveTable2[(int)cb]) >> 8, 255);
01594               m1 = QMIN((m1 * curveTable2[(int)cb]) >> 8, 255);
01595               y1 = QMIN((y1 * curveTable2[(int)cb]) >> 8, 255);
01596               k1 = QMIN((k1 * curveTable2[(int)cb]) >> 8, 255);
01597               col = ScColor(QMIN(c+c1, 255), QMIN(m+m1, 255), QMIN(y+y1, 255), QMIN(k+k1, 255));
01598               col.getRawRGBColor(&c, &m, &y);
01599               ptr[0] = c;
01600               ptr[1] = m;
01601               ptr[2] = y;
01602        }
01603        else if (colorTableSc.count() == 3)
01604        {
01605               ScColorEngine::getCMYKValues(colorTableSc[0], NULL, cmyk);
01606               cmyk.getValues(c, m, y, k);
01607               c = QMIN((c * curveTable1[(int)cb]) >> 8, 255);
01608               m = QMIN((m * curveTable1[(int)cb]) >> 8, 255);
01609               y = QMIN((y * curveTable1[(int)cb]) >> 8, 255);
01610               k = QMIN((k * curveTable1[(int)cb]) >> 8, 255);
01611               ScColorEngine::getCMYKValues(colorTableSc[1], NULL, cmyk);
01612               cmyk.getValues(c1, m1, y1, k1);
01613               c1 = QMIN((c1 * curveTable2[(int)cb]) >> 8, 255);
01614               m1 = QMIN((m1 * curveTable2[(int)cb]) >> 8, 255);
01615               y1 = QMIN((y1 * curveTable2[(int)cb]) >> 8, 255);
01616               k1 = QMIN((k1 * curveTable2[(int)cb]) >> 8, 255);
01617               ScColorEngine::getCMYKValues(colorTableSc[2], NULL, cmyk);
01618               cmyk.getValues(c2, m2, y2, k2);
01619               c2 = QMIN((c2 * curveTable3[(int)cb]) >> 8, 255);
01620               m2 = QMIN((m2 * curveTable3[(int)cb]) >> 8, 255);
01621               y2 = QMIN((y2 * curveTable3[(int)cb]) >> 8, 255);
01622               k2 = QMIN((k2 * curveTable3[(int)cb]) >> 8, 255);
01623               col = ScColor(QMIN(c+c1+c2, 255), QMIN(m+m1+m2, 255), QMIN(y+y1+y2, 255), QMIN(k+k1+k2, 255));
01624               col.getRawRGBColor(&c, &m, &y);
01625               ptr[0] = c;
01626               ptr[1] = m;
01627               ptr[2] = y;
01628        }
01629        else if (colorTableSc.count() == 4)
01630        {
01631               ScColorEngine::getCMYKValues(colorTableSc[0], NULL, cmyk);
01632               cmyk.getValues(c, m, y, k);
01633               c = QMIN((c * curveTable1[(int)cb]) >> 8, 255);
01634               m = QMIN((m * curveTable1[(int)cb]) >> 8, 255);
01635               y = QMIN((y * curveTable1[(int)cb]) >> 8, 255);
01636               k = QMIN((k * curveTable1[(int)cb]) >> 8, 255);
01637               ScColorEngine::getCMYKValues(colorTableSc[1], NULL, cmyk);
01638               cmyk.getValues(c1, m1, y1, k1);
01639               c1 = QMIN((c1 * curveTable2[(int)cb]) >> 8, 255);
01640               m1 = QMIN((m1 * curveTable2[(int)cb]) >> 8, 255);
01641               y1 = QMIN((y1 * curveTable2[(int)cb]) >> 8, 255);
01642               k1 = QMIN((k1 * curveTable2[(int)cb]) >> 8, 255);
01643               ScColorEngine::getCMYKValues(colorTableSc[2], NULL, cmyk);
01644               cmyk.getValues(c2, m2, y2, k2);
01645               c2 = QMIN((c2 * curveTable3[(int)cb]) >> 8, 255);
01646               m2 = QMIN((m2 * curveTable3[(int)cb]) >> 8, 255);
01647               y2 = QMIN((y2 * curveTable3[(int)cb]) >> 8, 255);
01648               k2 = QMIN((k2 * curveTable3[(int)cb]) >> 8, 255);
01649               ScColorEngine::getCMYKValues(colorTableSc[3], NULL, cmyk);
01650               cmyk.getValues(c3, m3, y3, k3);
01651               c3 = QMIN((c3 * curveTable4[(int)cb]) >> 8, 255);
01652               m3 = QMIN((m3 * curveTable4[(int)cb]) >> 8, 255);
01653               y3 = QMIN((y3 * curveTable4[(int)cb]) >> 8, 255);
01654               k3 = QMIN((k3 * curveTable4[(int)cb]) >> 8, 255);
01655               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));
01656               col.getRawRGBColor(&c, &m, &y);
01657               ptr[0] = c;
01658               ptr[1] = m;
01659               ptr[2] = y;
01660        }
01661 }