11#include <QDomDocument>
46 readImpl<psd_byte_order::psdLittleEndian>(io);
60template<psd_
byte_order
byteOrder>
84 const std::array<quint8, 4> refSignature1 = {
'8',
'B',
'I',
'M'};
85 const std::array<quint8, 4> refSignature2 = {
'8',
'B',
'6',
'4'};
87 if (!TRY_READ_SIGNATURE_2OPS_EX<byteOrder>(io, refSignature1, refSignature2)) {
92 QString key = readFixedString<byteOrder>(io);
93 dbgFile <<
"found info block with key" << key <<
"(" << io.pos() <<
")";
96 if (longBlocks.contains(key)) {
107 if (blockSize % 4U) {
108 dbgFile <<
"(TIFF) WARNING: current block size is NOT a multiple of 4! Fixing...";
109 blockSize += (4U - blockSize % 4U);
113 dbgFile <<
"info block size" << blockSize <<
"(" << io.pos() <<
")";
123 if (
keys.contains(key)) {
124 error =
"Found duplicate entry for key ";
130 if (key ==
"Lr16" ) {
133 dbgFile <<
"Offset for block handler: " << io.pos() << offset;
134 io.seek(io.pos() - offset);
137 }
else if (key ==
"Layr") {
140 dbgFile <<
"(TIFF) Offset for block handler: " << io.pos() << offset;
141 io.seek(io.pos() - offset);
144 }
else if (key ==
"SoCo") {
148 }
else if (key ==
"GdFl") {
152 }
else if (key ==
"PtFl") {
156 }
else if (key ==
"brit") {
157 }
else if (key ==
"levl") {
158 }
else if (key ==
"curv") {
159 }
else if (key ==
"expA") {
160 }
else if (key ==
"vibA") {
161 }
else if (key ==
"hue") {
162 }
else if (key ==
"hue2") {
163 }
else if (key ==
"blnc") {
164 }
else if (key ==
"blwh") {
165 }
else if (key ==
"phfl") {
166 }
else if (key ==
"mixr") {
167 }
else if (key ==
"clrL") {
168 }
else if (key ==
"nvrt") {
169 }
else if (key ==
"post") {
170 }
else if (key ==
"thrs") {
171 }
else if (key ==
"selc") {
172 }
else if (key ==
"lrFX") {
174 }
else if (key ==
"tySh") {
175 }
else if (key ==
"luni") {
179 }
else if (key ==
"lyid") {
181 psdread<byteOrder>(io,
id);
182 dbgFile <<
"\t" <<
"layer ID:" << id;
183 }
else if (key ==
"lfx2" || key ==
"lfxs") {
186 }
else if (key ==
"Patt" || key ==
"Pat2" || key ==
"Pat3") {
189 }
else if (key ==
"Anno") {
190 }
else if (key ==
"clbl") {
191 }
else if (key ==
"infx") {
192 }
else if (key ==
"knko") {
193 }
else if (key ==
"lspf") {
198 psdread<byteOrder>(io, protection);
199 userLock = protection & (1 << 31)?
true:
false;
200 }
else if (key ==
"lclr") {
206 psdread<byteOrder>(io, col1);
207 psdread<byteOrder>(io, col2);
208 psdread<byteOrder>(io, col3);
209 psdread<byteOrder>(io, col4);
210 dbgFile <<
"\t" <<
"layer color:" << col1 << col2 << col3 << col4;
212 }
else if (key ==
"fxrp") {
213 }
else if (key ==
"grdm") {
214 }
else if (key ==
"lsct") {
219 dbgFile <<
"Reading \"lsct\" block:";
223 if (blockSize >= 12) {
225 const quint32 refSignature1 = 0x3842494D;
234 if (blockSize >= 14) {
241 }
else if (key ==
"brst") {
242 }
else if (key ==
"vmsk" || key ==
"vsms") {
244 psdread<byteOrder>(io, version);
247 psdread<byteOrder>(io, flags);
253 quint64 currentPos = 8;
255 bool firstPath =
true;
257 while (currentPos < blockSize) {
259 psdread<byteOrder>(io, recordType);
261 if (recordType == 6) {
263 dbgFile <<
"\trecord" << recordType;
264 }
else if (recordType == 7) {
267 bounds.setTop(psdreadFixedPoint<byteOrder>(io));
268 bounds.setLeft(psdreadFixedPoint<byteOrder>(io));
269 bounds.setBottom(psdreadFixedPoint<byteOrder>(io));
270 bounds.setRight(psdreadFixedPoint<byteOrder>(io));
275 }
else if (recordType == 0 || recordType == 3) {
277 psdread<byteOrder>(io,
length);
280 currentPath.
isClosed = (recordType == 0);
284 currentPath.
isClosed = (recordType == 0);
288 }
else if (recordType == 8) {
290 psdread<byteOrder>(io,
length);
296 node.
control1.setY(psdreadFixedPoint<byteOrder>(io));
297 node.
control1.setX(psdreadFixedPoint<byteOrder>(io));
298 node.
node.setY(psdreadFixedPoint<byteOrder>(io));
299 node.
node.setX(psdreadFixedPoint<byteOrder>(io));
300 node.
control2.setY(psdreadFixedPoint<byteOrder>(io));
301 node.
control2.setX(psdreadFixedPoint<byteOrder>(io));
302 node.
isSmooth = (recordType == 1 || recordType == 4);
305 currentPath.
nodes.append(node);
310 if (!currentPath.
nodes.isEmpty()) {
314 }
else if (key ==
"TySh") {
316 }
else if (key ==
"ffxi") {
317 }
else if (key ==
"lnsr") {
318 }
else if (key ==
"shpa") {
319 }
else if (key ==
"shmd") {
320 }
else if (key ==
"lyvr") {
321 }
else if (key ==
"tsly") {
322 }
else if (key ==
"lmgm") {
323 }
else if (key ==
"vmgm") {
324 }
else if (key ==
"plLd") {
326 }
else if (key ==
"linkD" || key ==
"lnk2" || key ==
"lnk3") {
327 }
else if (key ==
"CgEd") {
328 }
else if (key ==
"Txt2") {
330 QByteArray ba = io.read(blockSize);
333 }
else if (key ==
"pths") {
334 }
else if (key ==
"anFX") {
335 }
else if (key ==
"FMsk") {
336 }
else if (key ==
"SoLd") {
337 }
else if (key ==
"vstk") {
339 }
else if (key ==
"vscg") {
341 QString vscgKey = readFixedString<byteOrder>(io);
343 if (vscgKey ==
"SoCo") {
345 }
else if (vscgKey ==
"GdFl") {
348 }
else if (vscgKey ==
"PtFl") {
353 }
else if (key ==
"sn2P") {
354 }
else if (key ==
"vogk") {
356 }
else if (key ==
"Mtrn" || key ==
"Mt16" || key ==
"Mt32") {
358 }
else if (key ==
"LMsk") {
362 dbgFile <<
"(TIFF) Offset for block handler: " << io.pos() << offset;
363 io.seek(io.pos() - offset);
366 }
else if (key ==
"FXid") {
367 }
else if (key ==
"FEid") {
386 writeLuniBlockExImpl<psd_byte_order::psdLittleEndian>(io, layerName);
394template<psd_
byte_order
byteOrder>
397 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
398 KisAslWriterUtils::writeFixedString<byteOrder>(
"luni", io);
400 KisAslWriterUtils::writeUnicodeString<byteOrder>(layerName, io);
407 writeLsctBlockExImpl<psd_byte_order::psdLittleEndian>(io, sectionType, isPassThrough, blendModeKey);
415template<psd_
byte_order
byteOrder>
418 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
419 KisAslWriterUtils::writeFixedString<byteOrder>(
"lsct", io);
423 QString realBlendModeKey = isPassThrough ? QString(
"pass") : blendModeKey;
425 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
426 KisAslWriterUtils::writeFixedString<byteOrder>(realBlendModeKey, io);
433 writeLfx2BlockExImpl<psd_byte_order::psdLittleEndian>(io, stylesXmlDoc, useLfxsLayerStyleFormat);
441template<psd_
byte_order
byteOrder>
444 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
446 KisAslWriterUtils::writeFixedString<byteOrder>(!useLfxsLayerStyleFormat ?
"lfx2" :
"lfxs", io);
465 writePattBlockExImpl<psd_byte_order::psdLittleEndian>(io, patternsXmlDoc);
477 writeLspfBlockExImpl<psd_byte_order::psdLittleEndian>(io, lock);
489 writeLclrBlockExImpl<psd_byte_order::psdLittleEndian>(io,
labelColor);
501 writeFillLayerBlockExImpl<psd_byte_order::psdLittleEndian>(io,
fillConfig, type);
513 writeVectorMaskImpl<psd_byte_order::psdLittleEndian>(io, mask);
525 writeTypeToolImpl<psd_byte_order::psdLittleEndian>(io, typeTool);
537 writeVectorStrokeDataImpl<psd_byte_order::psdLittleEndian>(io,
vectorStroke);
549 writeVectorOriginationDataImpl<psd_byte_order::psdLittleEndian>(io, vectorOrigination);
557template<psd_
byte_order
byteOrder>
560 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
561 KisAslWriterUtils::writeFixedString<byteOrder>(
"Patt", io);
577template<psd_
byte_order
byteOrder>
580 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
581 KisAslWriterUtils::writeFixedString<byteOrder>(
"lspf", io);
582 const quint32 len = 4;
592template<psd_
byte_order
byteOrder>
595 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
596 KisAslWriterUtils::writeFixedString<byteOrder>(
"lclr", io);
598 const quint32 len = 8;
609template<psd_
byte_order
byteOrder>
612 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
614 KisAslWriterUtils::writeFixedString<byteOrder>(
"SoCo", io);
616 KisAslWriterUtils::writeFixedString<byteOrder>(
"GdFl", io);
618 KisAslWriterUtils::writeFixedString<byteOrder>(
"PtFl", io);
635template<psd_
byte_order
byteOrder>
638 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
639 KisAslWriterUtils::writeFixedString<byteOrder>(
"vmsk", io);
645 len += subPath.
nodes.size() * 26;
665 quint16 recordType = 6;
681 const quint16 halfZero = 0;
690 recordType = subPath.
isClosed? 0: 3;
710 psdwriteFixedPoint<byteOrder>(io, node.
control1.y());
711 psdwriteFixedPoint<byteOrder>(io, node.
control1.x());
712 psdwriteFixedPoint<byteOrder>(io, node.
node.y());
713 psdwriteFixedPoint<byteOrder>(io, node.
node.x());
714 psdwriteFixedPoint<byteOrder>(io, node.
control2.y());
715 psdwriteFixedPoint<byteOrder>(io, node.
control2.x());
720template<psd_
byte_order
byteOrder>
723 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
724 KisAslWriterUtils::writeFixedString<byteOrder>(
"TySh", io);
741template<psd_
byte_order
byteOrder>
744 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
745 KisAslWriterUtils::writeFixedString<byteOrder>(
"vstk", io);
764 writeTxt2BlockExImpl<psd_byte_order::psdLittleEndian>(io, txt2Hash);
772template<psd_
byte_order
byteOrder>
775 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
776 KisAslWriterUtils::writeFixedString<byteOrder>(
"Txt2", io);
779 quint32
length = ba.size();
784template<psd_
byte_order
byteOrder>
787 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
788 KisAslWriterUtils::writeFixedString<byteOrder>(
"vogk", io);
qreal length(const QPointF &vec)
static QDomDocument readLfx2PsdSection(QIODevice &device, psd_byte_order byteOrder=psd_byte_order::psdBigEndian)
static QDomDocument readPsdSectionPattern(QIODevice &device, qint64 bytesLeft, psd_byte_order byteOrder=psd_byte_order::psdBigEndian)
static QDomDocument readTypeToolObjectSettings(QIODevice &device, QTransform &transform, psd_byte_order byteOrder=psd_byte_order::psdBigEndian)
static QDomDocument readVectorOriginationData(QIODevice &device, psd_byte_order byteOrder=psd_byte_order::psdBigEndian)
static QDomDocument readVectorStroke(QIODevice &device, psd_byte_order byteOrder=psd_byte_order::psdBigEndian)
static QDomDocument readFillLayer(QIODevice &device, psd_byte_order byteOrder=psd_byte_order::psdBigEndian)
void writeFillLayerSectionEx(QIODevice &device, const QDomDocument &doc)
void writePsdLfx2SectionEx(QIODevice &device, const QDomDocument &doc)
void writeVectorStrokeDataEx(QIODevice &device, const QDomDocument &doc)
void writeVectorOriginationDataEx(QIODevice &device, const QDomDocument &doc)
void writeTypeToolObjectSettings(QIODevice &device, const QDomDocument &doc, const QDomDocument &warpDoc, const QTransform tf, const QRectF bounds)
static QByteArray writeTxt2FromVariantHash(const QVariantHash doc)
static QVariantHash uncompressKeys(QVariantHash doc)
uncompressKeys One of the problems with the Txt2 block is that older versions of photoshop (cs2-cs3 e...
void writeLfx2BlockEx(QIODevice &io, const QDomDocument &stylesXmlDoc, bool useLfxsLayerStyleFormat)
void writeVectorOriginationDataImpl(QIODevice &io, const QDomDocument &vectorOrigination)
void writeFillLayerBlockEx(QIODevice &io, const QDomDocument &fillConfig, psd_fill_type type)
ExtraLayerInfoBlockHandler m_layerInfoBlockHandler
void writeVmskBlockEx(QIODevice &io, psd_vector_mask mask)
void writeVectorOriginationDataEx(QIODevice &io, const QDomDocument &vectorOrigination)
psd_section_type sectionDividerType
void writeVectorStrokeDataImpl(QIODevice &io, const QDomDocument &vectorStroke)
const PSDHeader & m_header
void writeLspfBlockEx(QIODevice &io, const bool lock)
void writeVectorMaskImpl(QIODevice &io, psd_vector_mask mask)
QVector< QDomDocument > embeddedPatterns
void writeLsctBlockEx(QIODevice &io, psd_section_type sectionType, bool isPassThrough, const QString &blendModeKey)
void writeVectorStrokeDataEx(QIODevice &io, const QDomDocument &vectorStroke)
QDomDocument vectorStroke
void writeLuniBlockEx(QIODevice &io, const QString &layerName)
UserMaskInfoBlockHandler m_userMaskBlockHandler
void writeFillLayerBlockExImpl(QIODevice &io, const QDomDocument &fillConfig, psd_fill_type type)
void writeLfx2BlockExImpl(QIODevice &io, const QDomDocument &stylesXmlDoc, bool useLfxsLayerStyleFormat)
QDomDocument vectorOriginationData
void readImpl(QIODevice &io)
PsdAdditionalLayerInfoBlock(const PSDHeader &header)
void writeLclrBlockExImpl(QIODevice &io, const quint16 &lclr)
bool write(QIODevice &io, KisNodeSP node)
void writeLspfBlockExImpl(QIODevice &io, const bool &lock)
void writeLsctBlockExImpl(QIODevice &io, psd_section_type sectionType, bool isPassThrough, const QString &blendModeKey)
QString sectionDividerBlendMode
void writeLclrBlockEx(QIODevice &io, const quint16 &labelColor)
void writeTxt2BlockEx(QIODevice &io, const QVariantHash txt2Hash)
std::function< bool(QIODevice &)> ExtraLayerInfoBlockHandler
void writePattBlockExImpl(QIODevice &io, const QDomDocument &patternsXmlDoc)
void writePattBlockEx(QIODevice &io, const QDomDocument &patternsXmlDoc)
void writeTxt2BlockExImpl(QIODevice &io, const QVariantHash txt2Hash)
void setExtraLayerInfoBlockHandler(ExtraLayerInfoBlockHandler handler)
void setUserMaskInfoBlockHandler(UserMaskInfoBlockHandler handler)
void writeTypeToolImpl(QIODevice &io, psd_layer_type_shape tool)
QDomDocument layerStyleXml
psd_vector_mask vectorMask
void writeLuniBlockExImpl(QIODevice &io, const QString &layerName)
void writeTypeToolBlockEx(QIODevice &io, psd_layer_type_shape typeTool)
std::function< bool(QIODevice &)> UserMaskInfoBlockHandler
#define GARBAGE_VALUE_MARK
#define SAFE_READ_EX(byteOrder, device, varname)
#define SAFE_READ_SIGNATURE_EX(byteOrder, device, varname, expected)
#define SAFE_WRITE_EX(byteOrder, device, varname)
#define PREPEND_METHOD(msg)
#define SETUP_OFFSET_VERIFIER(name, device, expectedOffset, maxPadding)
QDomDocument textWarpXML()
QDomDocument textDataASLXML()
QList< psd_path_node > nodes
QList< psd_path_sub_path > subPaths
double clipBoardResolution