File indexing completed on 2024-05-12 15:59:39

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Boudewijn Rempt <boud@valdyas.org>
0003  *  SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 #include "psd_layer_record.h"
0008 
0009 #include <QtEndian>
0010 
0011 #include <KoColor.h>
0012 #include <QBuffer>
0013 #include <QDataStream>
0014 #include <QIODevice>
0015 #include <QStringList>
0016 
0017 #include "kis_iterator_ng.h"
0018 #include <algorithm>
0019 #include <kis_debug.h>
0020 #include <kis_node.h>
0021 #include <kis_paint_layer.h>
0022 
0023 #include "compression.h"
0024 #include "psd.h"
0025 #include "psd_header.h"
0026 #include "psd_utils.h"
0027 
0028 #include <KoColorSpace.h>
0029 #include <KoColorSpaceMaths.h>
0030 #include <KoColorSpaceRegistry.h>
0031 #include <KoColorSpaceTraits.h>
0032 
0033 #include <asl/kis_asl_reader_utils.h>
0034 #include <asl/kis_asl_writer_utils.h>
0035 #include <asl/kis_offset_keeper.h>
0036 
0037 #include "psd_pixel_utils.h"
0038 #include <kundo2command.h>
0039 
0040 // Just for pretty debug messages
0041 QString channelIdToChannelType(int channelId, psd_color_mode colormode)
0042 {
0043     switch (channelId) {
0044     case -3:
0045         return "Real User Supplied Layer Mask (when both a user mask and a vector mask are present";
0046     case -2:
0047         return "User Supplied Layer Mask";
0048     case -1:
0049         return "Transparency mask";
0050     case 0:
0051         switch (colormode) {
0052         case Bitmap:
0053         case Indexed:
0054             return QString("bitmap or indexed: %1").arg(channelId);
0055         case Grayscale:
0056         case Gray16:
0057             return "gray";
0058         case RGB:
0059         case RGB48:
0060             return "red";
0061         case Lab:
0062         case Lab48:
0063             return "L";
0064         case CMYK:
0065         case CMYK64:
0066             return "cyan";
0067         case MultiChannel:
0068         case DeepMultichannel:
0069             return QString("multichannel channel %1").arg(channelId);
0070         case DuoTone:
0071         case Duotone16:
0072             return QString("duotone channel %1").arg(channelId);
0073         default:
0074             return QString("unknown: %1").arg(channelId);
0075         };
0076     case 1:
0077         switch (colormode) {
0078         case Bitmap:
0079         case Indexed:
0080             return QString("WARNING bitmap or indexed: %1").arg(channelId);
0081         case Grayscale:
0082         case Gray16:
0083             return QString("WARNING: %1").arg(channelId);
0084         case RGB:
0085         case RGB48:
0086             return "green";
0087         case Lab:
0088         case Lab48:
0089             return "a";
0090         case CMYK:
0091         case CMYK64:
0092             return "Magenta";
0093         case MultiChannel:
0094         case DeepMultichannel:
0095             return QString("multichannel channel %1").arg(channelId);
0096         case DuoTone:
0097         case Duotone16:
0098             return QString("duotone channel %1").arg(channelId);
0099         default:
0100             return QString("unknown: %1").arg(channelId);
0101         };
0102     case 2:
0103         switch (colormode) {
0104         case Bitmap:
0105         case Indexed:
0106             return QString("WARNING bitmap or indexed: %1").arg(channelId);
0107         case Grayscale:
0108         case Gray16:
0109             return QString("WARNING: %1").arg(channelId);
0110         case RGB:
0111         case RGB48:
0112             return "blue";
0113         case Lab:
0114         case Lab48:
0115             return "b";
0116         case CMYK:
0117         case CMYK64:
0118             return "yellow";
0119         case MultiChannel:
0120         case DeepMultichannel:
0121             return QString("multichannel channel %1").arg(channelId);
0122         case DuoTone:
0123         case Duotone16:
0124             return QString("duotone channel %1").arg(channelId);
0125         default:
0126             return QString("unknown: %1").arg(channelId);
0127         };
0128     case 3:
0129         switch (colormode) {
0130         case Bitmap:
0131         case Indexed:
0132             return QString("WARNING bitmap or indexed: %1").arg(channelId);
0133         case Grayscale:
0134         case Gray16:
0135             return QString("WARNING: %1").arg(channelId);
0136         case RGB:
0137         case RGB48:
0138             return QString("alpha: %1").arg(channelId);
0139         case Lab:
0140         case Lab48:
0141             return QString("alpha: %1").arg(channelId);
0142         case CMYK:
0143         case CMYK64:
0144             return "Key";
0145         case MultiChannel:
0146         case DeepMultichannel:
0147             return QString("multichannel channel %1").arg(channelId);
0148         case DuoTone:
0149         case Duotone16:
0150             return QString("duotone channel %1").arg(channelId);
0151         default:
0152             return QString("unknown: %1").arg(channelId);
0153         };
0154     default:
0155         return QString("unknown: %1").arg(channelId);
0156     };
0157 }
0158 
0159 PSDLayerRecord::PSDLayerRecord(const PSDHeader &header)
0160     : top(0)
0161     , left(0)
0162     , bottom(0)
0163     , right(0)
0164     , nChannels(0)
0165     , opacity(0)
0166     , clipping(0)
0167     , transparencyProtected(false)
0168     , visible(true)
0169     , irrelevant(false)
0170     , layerName("UNINITIALIZED")
0171     , infoBlocks(header)
0172     , m_transparencyMaskSizeOffset(0)
0173     , m_header(header)
0174 {
0175 }
0176 
0177 bool PSDLayerRecord::read(QIODevice &io)
0178 {
0179     switch (m_header.byteOrder) {
0180     case psd_byte_order::psdLittleEndian:
0181         return readImpl<psd_byte_order::psdLittleEndian>(io);
0182     default:
0183         return readImpl(io);
0184     }
0185 }
0186 
0187 template<psd_byte_order byteOrder>
0188 bool PSDLayerRecord::readImpl(QIODevice &io)
0189 {
0190     dbgFile << "Going to read layer record. Pos:" << io.pos();
0191 
0192     if (!psdread<byteOrder>(io, top) || !psdread<byteOrder>(io, left) || !psdread<byteOrder>(io, bottom) || !psdread<byteOrder>(io, right)
0193         || !psdread<byteOrder>(io, nChannels)) {
0194         error = "could not read layer record";
0195         return false;
0196     }
0197 
0198     dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
0199 
0200     Q_ASSERT(top <= bottom);
0201     Q_ASSERT(left <= right);
0202     Q_ASSERT(nChannels > 0);
0203 
0204     if (nChannels < 1) {
0205         error = QString("Not enough channels. Got: %1").arg(nChannels);
0206         return false;
0207     }
0208 
0209     if (nChannels > MAX_CHANNELS) {
0210         error = QString("Too many channels. Got: %1").arg(nChannels);
0211         return false;
0212     }
0213 
0214     for (int i = 0; i < nChannels; ++i) {
0215         if (io.atEnd()) {
0216             error = "Could not read enough data for channels";
0217             return false;
0218         }
0219 
0220         ChannelInfo *info = new ChannelInfo;
0221 
0222         if (!psdread<byteOrder>(io, info->channelId)) {
0223             error = "could not read channel id";
0224             delete info;
0225             return false;
0226         }
0227         bool r;
0228         if (m_header.version == 1) {
0229             quint32 channelDataLength;
0230             r = psdread<byteOrder>(io, channelDataLength);
0231             info->channelDataLength = (quint64)channelDataLength;
0232         } else {
0233             r = psdread<byteOrder>(io, info->channelDataLength);
0234         }
0235         if (!r) {
0236             error = "Could not read length for channel data";
0237             delete info;
0238             return false;
0239         }
0240 
0241         dbgFile << "\tchannel" << i << "id" << channelIdToChannelType(info->channelId, m_header.colormode) << "length" << info->channelDataLength << "start"
0242                 << info->channelDataStart << "offset" << info->channelOffset << "channelInfoPosition" << info->channelInfoPosition;
0243 
0244         channelInfoRecords << info;
0245     }
0246 
0247     if (!psd_read_blendmode<byteOrder>(io, blendModeKey)) {
0248         error = QString("Could not read blend mode key. Got: %1").arg(blendModeKey);
0249         return false;
0250     }
0251 
0252     dbgFile << "\tBlend mode" << blendModeKey << "pos" << io.pos();
0253 
0254     if (!psdread<byteOrder>(io, opacity)) {
0255         error = "Could not read opacity";
0256         return false;
0257     }
0258 
0259     dbgFile << "\tOpacity" << opacity << io.pos();
0260 
0261     if (!psdread<byteOrder>(io, clipping)) {
0262         error = "Could not read clipping";
0263         return false;
0264     }
0265 
0266     dbgFile << "\tclipping" << clipping << io.pos();
0267 
0268     quint8 flags;
0269     if (!psdread<byteOrder>(io, flags)) {
0270         error = "Could not read flags";
0271         return false;
0272     }
0273     dbgFile << "\tflags" << flags << io.pos();
0274 
0275     transparencyProtected = flags & 1 ? true : false;
0276 
0277     dbgFile << "\ttransparency protected" << transparencyProtected;
0278 
0279     visible = flags & 2 ? false : true;
0280 
0281     dbgFile << "\tvisible" << visible;
0282 
0283     if (flags & 8) {
0284         irrelevant = flags & 16 ? true : false;
0285     } else {
0286         irrelevant = false;
0287     }
0288 
0289     dbgFile << "\tirrelevant" << irrelevant;
0290 
0291     dbgFile << "\tfiller at " << io.pos();
0292 
0293     quint8 filler;
0294     if (!psdread<byteOrder>(io, filler) || filler != 0) {
0295         error = "Could not read padding";
0296         return false;
0297     }
0298 
0299     dbgFile << "\tGoing to read extra data length" << io.pos();
0300 
0301     quint32 extraDataLength;
0302     if (!psdread<byteOrder>(io, extraDataLength) || io.bytesAvailable() < extraDataLength) {
0303         error = QString("Could not read extra layer data: %1 at pos %2").arg(extraDataLength).arg(io.pos());
0304         return false;
0305     }
0306 
0307     dbgFile << "\tExtra data length" << extraDataLength;
0308 
0309     if (extraDataLength > 0) {
0310         dbgFile << "Going to read extra data field. Bytes available: " << io.bytesAvailable() << "pos" << io.pos();
0311 
0312         // See https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_22582
0313         quint32 layerMaskLength = 1; // invalid...
0314         if (!psdread<byteOrder>(io, layerMaskLength) || io.bytesAvailable() < layerMaskLength) {
0315             error = QString("Could not read layer mask length: %1").arg(layerMaskLength);
0316             return false;
0317         }
0318 
0319         layerMask = {};
0320 
0321         if (layerMaskLength == 0) {
0322             dbgFile << "\tNo layer mask/adjustment layer data. pos" << io.pos();
0323         } else {
0324             dbgFile << "\tReading layer mask/adjustment layer data. Length of block:" << layerMaskLength << "pos"
0325                     << io.pos();
0326 
0327             if (!psdread<byteOrder>(io, layerMask.top) || !psdread<byteOrder>(io, layerMask.left)
0328                 || !psdread<byteOrder>(io, layerMask.bottom) || !psdread<byteOrder>(io, layerMask.right)
0329                 || !psdread<byteOrder>(io, layerMask.defaultColor) || !psdread<byteOrder>(io, flags)) {
0330                 error = "could not read common records of layer mask";
0331                 return false;
0332             }
0333 
0334             layerMask.positionedRelativeToLayer = (flags & 1) != 0;
0335             layerMask.disabled = (flags & 2) != 0;
0336             layerMask.invertLayerMaskWhenBlending = (flags & 4) != 0;
0337             const bool hasMaskParameters = (flags & 8) != 0;
0338 
0339             dbgFile << "\tLayer mask info (original): position relative" << layerMask.positionedRelativeToLayer
0340                     << ", disabled" << layerMask.disabled << ", invert" << layerMask.invertLayerMaskWhenBlending
0341                     << ", needs to read mask parameters" << hasMaskParameters;
0342 
0343             if (layerMaskLength == 20) {
0344                 quint16 padding = 0;
0345                 if (!psdread<byteOrder>(io, padding)) {
0346                     error = "Could not read layer mask padding";
0347                     return false;
0348                 }
0349             } else {
0350                 quint32 remainingBlockLength = layerMaskLength - 18;
0351 
0352                 dbgFile << "\tReading selective records from layer mask info. Remaining block length"
0353                         << remainingBlockLength;
0354 
0355                 if (hasMaskParameters) {
0356                     if (!psdread<byteOrder>(io, flags)) {
0357                         error = "could not read mask parameters";
0358                         return false;
0359                     }
0360 
0361                     remainingBlockLength -= 1;
0362 
0363                     dbgFile << "\t\tMask parameters" << QString::number(flags, 2) << ". Remaining block length"
0364                             << remainingBlockLength;
0365 
0366                     if (flags & 1) {
0367                         quint8 dummy = 0;
0368                         if (!psdread<byteOrder>(io, dummy)) {
0369                             error = "could not read user mask density";
0370                             return false;
0371                         }
0372                         remainingBlockLength -= sizeof(dummy);
0373                     }
0374 
0375                     if (flags & 2) {
0376                         double dummy = 0;
0377                         if (!psdread<byteOrder>(io, dummy)) {
0378                             error = "could not read user mask feather";
0379                             return false;
0380                         }
0381                         remainingBlockLength -= sizeof(dummy);
0382                     }
0383 
0384                     if (flags & 4) {
0385                         quint8 dummy = 0;
0386                         if (!psdread<byteOrder>(io, dummy)) {
0387                             error = "could not read vector mask density";
0388                             return false;
0389                         }
0390                         remainingBlockLength -= sizeof(dummy);
0391                     }
0392 
0393                     if (flags & 8) {
0394                         double dummy = 0;
0395                         if (!psdread<byteOrder>(io, dummy)) {
0396                             error = "could not read vector mask feather";
0397                             return false;
0398                         }
0399                         remainingBlockLength -= sizeof(dummy);
0400                     }
0401                 }
0402 
0403                 if (remainingBlockLength >= 1) {
0404                     if (!psdread<byteOrder>(io, flags)) {
0405                         error = "could not read 'real' mask record";
0406                         return false;
0407                     }
0408 
0409                     layerMask.positionedRelativeToLayer = (flags & 1) != 0;
0410                     layerMask.disabled = (flags & 2) != 0;
0411                     layerMask.invertLayerMaskWhenBlending = (flags & 4) != 0;
0412                     const bool hasMaskParameters = (flags & 8) != 0;
0413 
0414                     dbgFile << "\t\tLayer mask info (real): position relative" << layerMask.positionedRelativeToLayer
0415                             << ", disabled" << layerMask.disabled << ", invert" << layerMask.invertLayerMaskWhenBlending
0416                             << ", needs to read mask parameters" << hasMaskParameters;
0417 
0418                     remainingBlockLength -= 1;
0419 
0420                     dbgFile << "\t\tRemaining block length" << remainingBlockLength;
0421                 }
0422 
0423                 if (remainingBlockLength >= 1) {
0424                     if (!psdread<byteOrder>(io, layerMask.defaultColor)) {
0425                         error = "could not read 'real' default color";
0426                         return false;
0427                     }
0428                     remainingBlockLength -= 1;
0429                     dbgFile << "\t\tRead 'real' default color. Remaining block length" << remainingBlockLength;
0430                 }
0431 
0432                 if (remainingBlockLength >= 16) {
0433                     if (!psdread<byteOrder>(io, layerMask.top) || !psdread<byteOrder>(io, layerMask.left)
0434                         || !psdread<byteOrder>(io, layerMask.bottom) || !psdread<byteOrder>(io, layerMask.right)) {
0435                         error = "could not read 'real' mask rectangle";
0436                         return false;
0437                     }
0438                     remainingBlockLength -= 16;
0439                     dbgFile << "\t\tRead 'real' mask rectangle. Remaining block length" << remainingBlockLength;
0440                 }
0441             }
0442         }
0443 
0444         // layer blending thingies
0445         quint32 blendingDataLength = 0;
0446         if (!psdread<byteOrder>(io, blendingDataLength) || io.bytesAvailable() < blendingDataLength) {
0447             error = "Could not read extra blending data.";
0448             return false;
0449         }
0450 
0451         quint32 blendingNchannels = blendingDataLength > 0 ? (blendingDataLength - 8) / 4 / 2 : 0;
0452 
0453         dbgFile << "\tNumber of blending channels:" << blendingNchannels;
0454 
0455         if (blendingDataLength > 0) {
0456             if (blendingDataLength > 0) {
0457                 if (!psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.blackValues[0])
0458                     || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.blackValues[1])
0459                     || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.whiteValues[0])
0460                     || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.first.whiteValues[1])) {
0461                     error = "Could not read blending black/white values";
0462                     return false;
0463                 }
0464             }
0465             blendingDataLength -= 4;
0466 
0467             if (blendingDataLength > 0) {
0468                 if (!psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.blackValues[0])
0469                     || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.blackValues[1])
0470                     || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.whiteValues[0])
0471                     || !psdread<byteOrder>(io, blendingRanges.compositeGrayRange.second.whiteValues[1])) {
0472                     error = "Could not read blending black/white values";
0473                     return false;
0474                 }
0475             }
0476             blendingDataLength -= 4;
0477 
0478             dbgFile << "\tBlending ranges:";
0479             dbgFile << "\t\tcomposite gray (source) :" << blendingRanges.compositeGrayRange.first;
0480             dbgFile << "\t\tcomposite gray (dest):" << blendingRanges.compositeGrayRange.second;
0481 
0482             for (quint32 i = 0; i < blendingNchannels; ++i) {
0483                 LayerBlendingRanges::LayerBlendingRange src{};
0484                 LayerBlendingRanges::LayerBlendingRange dst{};
0485                 if (!psdread<byteOrder>(io, src.blackValues[0]) || !psdread<byteOrder>(io, src.blackValues[1]) || !psdread<byteOrder>(io, src.whiteValues[0])
0486                     || !psdread<byteOrder>(io, src.whiteValues[1]) || !psdread<byteOrder>(io, dst.blackValues[0]) || !psdread<byteOrder>(io, dst.blackValues[1])
0487                     || !psdread<byteOrder>(io, dst.whiteValues[0]) || !psdread<byteOrder>(io, dst.whiteValues[1])) {
0488                     error = QString("could not read src/dst range for channel %1").arg(i);
0489                     return false;
0490                 }
0491                 dbgFile << "\t\tread range " << src << "to" << dst << "for channel" << i;
0492                 blendingRanges.sourceDestinationRanges << qMakePair(src, dst);
0493             }
0494         }
0495 
0496         dbgFile << "\tGoing to read layer name at" << io.pos();
0497         quint8 layerNameLength;
0498         if (!psdread<byteOrder>(io, layerNameLength)) {
0499             error = "Could not read layer name length";
0500             return false;
0501         }
0502 
0503         dbgFile << "\tlayer name length unpadded" << layerNameLength << "pos" << io.pos();
0504         layerNameLength = ((layerNameLength + 1 + 3) & ~0x03) - 1;
0505 
0506         dbgFile << "\tlayer name length padded" << layerNameLength << "pos" << io.pos();
0507         // XXX: This should use psdread_pascalstring
0508         layerName = io.read(layerNameLength);
0509         dbgFile << "\tlayer name" << layerName << io.pos();
0510 
0511         dbgFile << "\tAbout to read additional info blocks at" << io.pos();
0512 
0513         if (!infoBlocks.read(io)) {
0514             error = infoBlocks.error;
0515             return false;
0516         }
0517 
0518         if (infoBlocks.keys.contains("luni") && !infoBlocks.unicodeLayerName.isEmpty()) {
0519             layerName = infoBlocks.unicodeLayerName;
0520         }
0521 
0522         labelColor = kritaColorLabelIndex(infoBlocks.labelColor);
0523     }
0524 
0525     return valid();
0526 }
0527 
0528 void PSDLayerRecord::write(QIODevice &io,
0529                            KisPaintDeviceSP layerContentDevice,
0530                            KisNodeSP onlyTransparencyMask,
0531                            const QRect &maskRect,
0532                            psd_section_type sectionType,
0533                            const QDomDocument &stylesXmlDoc,
0534                            bool useLfxsLayerStyleFormat)
0535 {
0536     switch (m_header.byteOrder) {
0537     case psd_byte_order::psdLittleEndian:
0538         return writeImpl<psd_byte_order::psdLittleEndian>(io,
0539                                                           layerContentDevice,
0540                                                           onlyTransparencyMask,
0541                                                           maskRect,
0542                                                           sectionType,
0543                                                           stylesXmlDoc,
0544                                                           useLfxsLayerStyleFormat);
0545     default:
0546         return writeImpl(io, layerContentDevice, onlyTransparencyMask, maskRect, sectionType, stylesXmlDoc, useLfxsLayerStyleFormat);
0547     }
0548 }
0549 
0550 template<psd_byte_order byteOrder>
0551 void PSDLayerRecord::writeImpl(QIODevice &io,
0552                                KisPaintDeviceSP layerContentDevice,
0553                                KisNodeSP onlyTransparencyMask,
0554                                const QRect &maskRect,
0555                                psd_section_type sectionType,
0556                                const QDomDocument &stylesXmlDoc,
0557                                bool useLfxsLayerStyleFormat)
0558 {
0559     dbgFile << "writing layer info record"
0560             << "at" << io.pos();
0561 
0562     m_layerContentDevice = layerContentDevice;
0563     m_onlyTransparencyMask = onlyTransparencyMask;
0564     m_onlyTransparencyMaskRect = maskRect;
0565 
0566     dbgFile << "saving layer record for " << layerName << "at pos" << io.pos();
0567     dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels;
0568     Q_ASSERT(left <= right);
0569     Q_ASSERT(top <= bottom);
0570     Q_ASSERT(nChannels > 0);
0571 
0572     try {
0573         {
0574             const QRect layerRect(left, top, right - left, bottom - top);
0575             KisAslWriterUtils::writeRect<byteOrder>(layerRect, io);
0576         }
0577 
0578         {
0579             quint16 realNumberOfChannels = nChannels + bool(m_onlyTransparencyMask);
0580             SAFE_WRITE_EX(byteOrder, io, realNumberOfChannels);
0581         }
0582 
0583         Q_FOREACH (ChannelInfo *channel, channelInfoRecords) {
0584             SAFE_WRITE_EX(byteOrder, io, (quint16)channel->channelId);
0585 
0586             channel->channelInfoPosition = static_cast<int>(io.pos());
0587 
0588             // to be filled in when we know how big channel block is
0589             const quint32 fakeChannelSize = 0;
0590             SAFE_WRITE_EX(byteOrder, io, fakeChannelSize);
0591         }
0592 
0593         if (m_onlyTransparencyMask) {
0594             const quint16 userSuppliedMaskChannelId = -2;
0595             SAFE_WRITE_EX(byteOrder, io, userSuppliedMaskChannelId);
0596 
0597             m_transparencyMaskSizeOffset = io.pos();
0598 
0599             const quint32 fakeTransparencyMaskSize = 0;
0600             SAFE_WRITE_EX(byteOrder, io, fakeTransparencyMaskSize);
0601         }
0602 
0603         // blend mode
0604         dbgFile << ppVar(blendModeKey) << ppVar(io.pos());
0605 
0606         KisAslWriterUtils::writeFixedString<byteOrder>("8BIM", io);
0607         KisAslWriterUtils::writeFixedString<byteOrder>(blendModeKey, io);
0608 
0609         SAFE_WRITE_EX(byteOrder, io, opacity);
0610         SAFE_WRITE_EX(byteOrder, io, clipping); // unused
0611 
0612         // visibility and protection
0613         quint8 flags = 0;
0614         if (transparencyProtected)
0615             flags |= 1;
0616         if (!visible)
0617             flags |= 2;
0618         flags |= (1 << 3);
0619         if (irrelevant) {
0620             flags |= (1 << 4);
0621         }
0622 
0623         SAFE_WRITE_EX(byteOrder, io, flags);
0624 
0625         {
0626             quint8 padding = 0;
0627             SAFE_WRITE_EX(byteOrder, io, padding);
0628         }
0629 
0630         {
0631             // extra fields with their own length tag
0632             KisAslWriterUtils::OffsetStreamPusher<quint32, byteOrder> extraDataSizeTag(io);
0633 
0634             if (m_onlyTransparencyMask) {
0635                 {
0636                     const quint32 layerMaskDataSize = 20; // support simple case only
0637                     SAFE_WRITE_EX(byteOrder, io, layerMaskDataSize);
0638                 }
0639 
0640                 KisAslWriterUtils::writeRect<byteOrder>(m_onlyTransparencyMaskRect, io);
0641 
0642                 {
0643                     // NOTE: in PSD the default color of the mask is stored in 1 byte value!
0644                     //       Even when the mask is actually 16/32 bit! I have no idea how it is
0645                     //       actually treated in this case.
0646                     KIS_ASSERT_RECOVER_NOOP(m_onlyTransparencyMask->paintDevice()->pixelSize() == 1);
0647                     const quint8 defaultPixel = *m_onlyTransparencyMask->paintDevice()->defaultPixel().data();
0648                     SAFE_WRITE_EX(byteOrder, io, defaultPixel);
0649                 }
0650 
0651                 {
0652                     const quint8 maskFlags = 0; // nothing serious
0653                     SAFE_WRITE_EX(byteOrder, io, maskFlags);
0654 
0655                     const quint16 padding = 0; // 2-byte padding
0656                     SAFE_WRITE_EX(byteOrder, io, padding);
0657                 }
0658             } else {
0659                 const quint32 nullLayerMaskDataSize = 0;
0660                 SAFE_WRITE_EX(byteOrder, io, nullLayerMaskDataSize);
0661             }
0662 
0663             {
0664                 // blending ranges are not implemented yet
0665                 const quint32 nullBlendingRangesSize = 0;
0666                 SAFE_WRITE_EX(byteOrder, io, nullBlendingRangesSize);
0667             }
0668 
0669             // layer name: Pascal string, padded to a multiple of 4 bytes.
0670             psdwrite_pascalstring<byteOrder>(io, layerName, 4);
0671 
0672             PsdAdditionalLayerInfoBlock additionalInfoBlock(m_header);
0673 
0674             // write 'luni' data block
0675             additionalInfoBlock.writeLuniBlockEx(io, layerName);
0676 
0677             additionalInfoBlock.writeLclrBlockEx(io, psdLabelColor(labelColor));
0678 
0679             // write 'lsct' data block
0680             if (sectionType != psd_other) {
0681                 additionalInfoBlock.writeLsctBlockEx(io, sectionType, isPassThrough, blendModeKey);
0682             }
0683 
0684             // write 'lfx2' data block
0685             if (!stylesXmlDoc.isNull()) {
0686                 additionalInfoBlock.writeLfx2BlockEx(io, stylesXmlDoc, useLfxsLayerStyleFormat);
0687             }
0688 
0689             // write SoCo, GdFl, PtFl data blocks.
0690             if (!fillConfig.isNull()) {
0691                 additionalInfoBlock.writeFillLayerBlockEx(io, fillConfig, fillType);
0692             }
0693 
0694         }
0695     } catch (KisAslWriterUtils::ASLWriteException &e) {
0696         throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what()));
0697     }
0698 }
0699 
0700 KisPaintDeviceSP PSDLayerRecord::convertMaskDeviceIfNeeded(KisPaintDeviceSP dev)
0701 {
0702     KisPaintDeviceSP result = dev;
0703 
0704     if (m_header.channelDepth == 16) {
0705         result = new KisPaintDevice(*dev);
0706         result->convertTo(KoColorSpaceRegistry::instance()->alpha16());
0707     } else if (m_header.channelDepth == 32) {
0708         result = new KisPaintDevice(*dev);
0709         result->convertTo(KoColorSpaceRegistry::instance()->alpha32f());
0710     }
0711     return result;
0712 }
0713 
0714 quint16 PSDLayerRecord::psdLabelColor(int colorLabelIndex)
0715 {
0716     quint16 color = 0;
0717     switch (colorLabelIndex) {
0718     case 0: // none
0719         color = 0;
0720         break;
0721     case 1: // Blue
0722         color = 5;
0723         break;
0724     case 2: // Green
0725         color = 4;
0726         break;
0727     case 3: // Yellow
0728         color = 3;
0729         break;
0730     case 4: // Orange
0731         color = 2;
0732         break;
0733     case 5: // Brown, don't save.
0734         color = 0;
0735         break;
0736     case 6: // Red
0737         color = 1;
0738         break;
0739     case 7: // Purple
0740         color = 6;
0741         break;
0742     case 8: // Grey
0743         color = 7;
0744         break;
0745     default:
0746         color = 0;
0747     }
0748     return color;
0749 }
0750 
0751 int PSDLayerRecord::kritaColorLabelIndex(quint16 labelColor)
0752 {
0753     int color = 0;
0754     switch (labelColor) {
0755     case 0:
0756         color = 0;
0757         break;
0758     case 1: // red
0759         color = 6;
0760         break;
0761     case 2: // Orange
0762         color = 4;
0763         break;
0764     case 3: // Yellow
0765         color = 3;
0766         break;
0767     case 4: // Green
0768         color = 2;
0769         break;
0770     case 5: // Blue
0771         color = 1;
0772         break;
0773     case 6: // Purple
0774         color = 7;
0775         break;
0776     case 7: // Grey
0777         color = 8;
0778         break;
0779     default:
0780         color = 0;
0781     }
0782     return color;
0783 }
0784 
0785 template<psd_byte_order byteOrder>
0786 void PSDLayerRecord::writeTransparencyMaskPixelData(QIODevice &io)
0787 {
0788     if (m_onlyTransparencyMask) {
0789         KisPaintDeviceSP device = convertMaskDeviceIfNeeded(m_onlyTransparencyMask->paintDevice());
0790 
0791         QByteArray buffer(static_cast<int>(device->pixelSize()) * m_onlyTransparencyMaskRect.width() * m_onlyTransparencyMaskRect.height(), 0);
0792         device->readBytes((quint8 *)buffer.data(), m_onlyTransparencyMaskRect);
0793 
0794         PsdPixelUtils::writeChannelDataRLE(io,
0795                                            (quint8 *)buffer.data(),
0796                                            static_cast<int>(device->pixelSize()),
0797                                            m_onlyTransparencyMaskRect,
0798                                            m_transparencyMaskSizeOffset,
0799                                            -1,
0800                                            true,
0801                                            byteOrder);
0802     }
0803 }
0804 
0805 void PSDLayerRecord::writePixelData(QIODevice &io, psd_compression_type compressionType)
0806 {
0807     try {
0808         switch (m_header.byteOrder) {
0809         case psd_byte_order::psdLittleEndian:
0810             writePixelDataImpl<psd_byte_order::psdLittleEndian>(io, compressionType);
0811             break;
0812         default:
0813             writePixelDataImpl(io, compressionType);
0814             break;
0815         }
0816     } catch (KisAslWriterUtils::ASLWriteException &e) {
0817         throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what()));
0818     }
0819 }
0820 
0821 template<psd_byte_order byteOrder>
0822 void PSDLayerRecord::writePixelDataImpl(QIODevice &io, psd_compression_type compressionType)
0823 {
0824     dbgFile << "writing pixel data for layer" << layerName << "at" << io.pos();
0825 
0826     KisPaintDeviceSP dev = m_layerContentDevice;
0827     const QRect rc(left, top, right - left, bottom - top);
0828 
0829     if (rc.isEmpty()) {
0830         dbgFile << "Layer is empty! Writing placeholder information.";
0831 
0832         for (int i = 0; i < nChannels; i++) {
0833             const ChannelInfo *channelInfo = channelInfoRecords[i];
0834             KisAslWriterUtils::OffsetStreamPusher<quint32, byteOrder> channelBlockSizeExternalTag(io, 0, channelInfo->channelInfoPosition);
0835             SAFE_WRITE_EX(byteOrder, io, static_cast<quint16>(psd_compression_type::Uncompressed));
0836         }
0837 
0838         writeTransparencyMaskPixelData<byteOrder>(io);
0839 
0840         return;
0841     }
0842 
0843     // now write all the channels in display order
0844     dbgFile << "layer" << layerName;
0845 
0846     const int channelSize = m_header.channelDepth / 8;
0847     const psd_color_mode colorMode = m_header.colormode;
0848 
0849     QVector<PsdPixelUtils::ChannelWritingInfo> writingInfoList;
0850     Q_FOREACH (const ChannelInfo *channelInfo, channelInfoRecords) {
0851         writingInfoList << PsdPixelUtils::ChannelWritingInfo(channelInfo->channelId, channelInfo->channelInfoPosition);
0852     }
0853 
0854     PsdPixelUtils::writePixelDataCommon(io, dev, rc, colorMode, channelSize, true, true, writingInfoList, compressionType, byteOrder);
0855     writeTransparencyMaskPixelData<byteOrder>(io);
0856 }
0857 
0858 bool PSDLayerRecord::valid()
0859 {
0860     // XXX: check validity!
0861     return true;
0862 }
0863 
0864 bool PSDLayerRecord::readPixelData(QIODevice &io, KisPaintDeviceSP device)
0865 {
0866     dbgFile << "Reading pixel data for layer" << layerName << "pos" << io.pos();
0867 
0868     const int channelSize = m_header.channelDepth / 8;
0869     const QRect layerRect = QRect(left, top, right - left, bottom - top);
0870 
0871     try {
0872         // WARNING: Pixel data is ALWAYS in big endian!!!
0873         PsdPixelUtils::readChannels(io, device, m_header.colormode, channelSize, layerRect, channelInfoRecords, psd_byte_order::psdBigEndian);
0874     } catch (KisAslReaderUtils::ASLParseException &e) {
0875         device->clear();
0876         error = e.what();
0877         return false;
0878     }
0879 
0880     return true;
0881 }
0882 
0883 QRect PSDLayerRecord::channelRect(ChannelInfo *channel) const
0884 {
0885     QRect result;
0886 
0887     if (channel->channelId < -1) {
0888         result = QRect(layerMask.left, layerMask.top, layerMask.right - layerMask.left, layerMask.bottom - layerMask.top);
0889     } else {
0890         result = QRect(left, top, right - left, bottom - top);
0891     }
0892 
0893     return result;
0894 }
0895 
0896 bool PSDLayerRecord::readMask(QIODevice &io, KisPaintDeviceSP dev, ChannelInfo *channelInfo)
0897 {
0898     KIS_ASSERT_RECOVER(channelInfo->channelId < -1)
0899     {
0900         return false;
0901     }
0902 
0903     dbgFile << "Going to read" << channelIdToChannelType(channelInfo->channelId, m_header.colormode) << "mask";
0904 
0905     QRect maskRect = channelRect(channelInfo);
0906     if (maskRect.isEmpty()) {
0907         dbgFile << "Empty Channel";
0908         return true;
0909     }
0910 
0911     // the device must be a pixel selection
0912     KIS_ASSERT_RECOVER(dev->pixelSize() == 1)
0913     {
0914         return false;
0915     }
0916 
0917     dev->setDefaultPixel(KoColor(&layerMask.defaultColor, dev->colorSpace()));
0918 
0919     const int pixelSize = m_header.channelDepth == 16 ? 2 : m_header.channelDepth == 32 ? 4 : 1;
0920 
0921     QVector<ChannelInfo *> infoRecords;
0922     infoRecords << channelInfo;
0923     PsdPixelUtils::readAlphaMaskChannels(io, dev, pixelSize, maskRect, infoRecords);
0924 
0925     return true;
0926 }
0927 
0928 QDebug operator<<(QDebug dbg, const PSDLayerRecord &layer)
0929 {
0930 #ifndef NODEBUG
0931     dbg.nospace() << "valid: " << const_cast<PSDLayerRecord *>(&layer)->valid();
0932     dbg.nospace() << ", name: " << layer.layerName;
0933     dbg.nospace() << ", top: " << layer.top;
0934     dbg.nospace() << ", left:" << layer.left;
0935     dbg.nospace() << ", bottom: " << layer.bottom;
0936     dbg.nospace() << ", right: " << layer.right;
0937     dbg.nospace() << ", number of channels: " << layer.nChannels;
0938     dbg.nospace() << ", blendModeKey: " << layer.blendModeKey;
0939     dbg.nospace() << ", opacity: " << layer.opacity;
0940     dbg.nospace() << ", clipping: " << layer.clipping;
0941     dbg.nospace() << ", transparency protected: " << layer.transparencyProtected;
0942     dbg.nospace() << ", visible: " << layer.visible;
0943     dbg.nospace() << ", irrelevant: " << layer.irrelevant << "\n";
0944     Q_FOREACH (const ChannelInfo *channel, layer.channelInfoRecords) {
0945         dbg.space() << channel;
0946     }
0947 #endif
0948     return dbg.nospace();
0949 }
0950 
0951 QDebug operator<<(QDebug dbg, const ChannelInfo &channel)
0952 {
0953 #ifndef NODEBUG
0954     dbg.nospace() << "\tChannel type" << channel.channelId << "size: " << channel.channelDataLength << "compression type" << channel.compressionType << "\n";
0955 #endif
0956     return dbg.nospace();
0957 }