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