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 ==
"spf") {
194 }
else if (key ==
"lclr") {
200 psdread<byteOrder>(io, col1);
201 psdread<byteOrder>(io, col2);
202 psdread<byteOrder>(io, col3);
203 psdread<byteOrder>(io, col4);
204 dbgFile <<
"\t" <<
"layer color:" << col1 << col2 << col3 << col4;
206 }
else if (key ==
"fxrp") {
207 }
else if (key ==
"grdm") {
208 }
else if (key ==
"lsct") {
213 dbgFile <<
"Reading \"lsct\" block:";
217 if (blockSize >= 12) {
219 const quint32 refSignature1 = 0x3842494D;
228 if (blockSize >= 14) {
235 }
else if (key ==
"brst") {
236 }
else if (key ==
"vmsk" || key ==
"vsms") {
238 psdread<byteOrder>(io, version);
241 psdread<byteOrder>(io, flags);
247 quint64 currentPos = 8;
249 bool firstPath =
true;
251 while (currentPos < blockSize) {
253 psdread<byteOrder>(io, recordType);
255 if (recordType == 6) {
257 dbgFile <<
"\trecord" << recordType;
258 }
else if (recordType == 7) {
261 bounds.setTop(psdreadFixedPoint<byteOrder>(io));
262 bounds.setLeft(psdreadFixedPoint<byteOrder>(io));
263 bounds.setBottom(psdreadFixedPoint<byteOrder>(io));
264 bounds.setRight(psdreadFixedPoint<byteOrder>(io));
269 }
else if (recordType == 0 || recordType == 3) {
271 psdread<byteOrder>(io,
length);
274 currentPath.
isClosed = (recordType == 0);
278 currentPath.
isClosed = (recordType == 0);
282 }
else if (recordType == 8) {
284 psdread<byteOrder>(io,
length);
290 node.
control1.setY(psdreadFixedPoint<byteOrder>(io));
291 node.
control1.setX(psdreadFixedPoint<byteOrder>(io));
292 node.
node.setY(psdreadFixedPoint<byteOrder>(io));
293 node.
node.setX(psdreadFixedPoint<byteOrder>(io));
294 node.
control2.setY(psdreadFixedPoint<byteOrder>(io));
295 node.
control2.setX(psdreadFixedPoint<byteOrder>(io));
296 node.
isSmooth = (recordType == 1 || recordType == 4);
299 currentPath.
nodes.append(node);
304 if (!currentPath.
nodes.isEmpty()) {
308 }
else if (key ==
"TySh") {
310 }
else if (key ==
"ffxi") {
311 }
else if (key ==
"lnsr") {
312 }
else if (key ==
"shpa") {
313 }
else if (key ==
"shmd") {
314 }
else if (key ==
"lyvr") {
315 }
else if (key ==
"tsly") {
316 }
else if (key ==
"lmgm") {
317 }
else if (key ==
"vmgm") {
318 }
else if (key ==
"plLd") {
320 }
else if (key ==
"linkD" || key ==
"lnk2" || key ==
"lnk3") {
321 }
else if (key ==
"CgEd") {
322 }
else if (key ==
"Txt2") {
324 QByteArray ba = io.read(blockSize);
327 }
else if (key ==
"pths") {
328 }
else if (key ==
"anFX") {
329 }
else if (key ==
"FMsk") {
330 }
else if (key ==
"SoLd") {
331 }
else if (key ==
"vstk") {
333 }
else if (key ==
"vscg") {
335 QString vscgKey = readFixedString<byteOrder>(io);
337 if (vscgKey ==
"SoCo") {
339 }
else if (vscgKey ==
"GdFl") {
342 }
else if (vscgKey ==
"PtFl") {
347 }
else if (key ==
"sn2P") {
348 }
else if (key ==
"vogk") {
350 }
else if (key ==
"Mtrn" || key ==
"Mt16" || key ==
"Mt32") {
352 }
else if (key ==
"LMsk") {
356 dbgFile <<
"(TIFF) Offset for block handler: " << io.pos() << offset;
357 io.seek(io.pos() - offset);
360 }
else if (key ==
"FXid") {
361 }
else if (key ==
"FEid") {
380 writeLuniBlockExImpl<psd_byte_order::psdLittleEndian>(io, layerName);
388template<psd_
byte_order
byteOrder>
391 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
392 KisAslWriterUtils::writeFixedString<byteOrder>(
"luni", io);
394 KisAslWriterUtils::writeUnicodeString<byteOrder>(layerName, io);
401 writeLsctBlockExImpl<psd_byte_order::psdLittleEndian>(io, sectionType, isPassThrough, blendModeKey);
409template<psd_
byte_order
byteOrder>
412 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
413 KisAslWriterUtils::writeFixedString<byteOrder>(
"lsct", io);
417 QString realBlendModeKey = isPassThrough ? QString(
"pass") : blendModeKey;
419 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
420 KisAslWriterUtils::writeFixedString<byteOrder>(realBlendModeKey, io);
427 writeLfx2BlockExImpl<psd_byte_order::psdLittleEndian>(io, stylesXmlDoc, useLfxsLayerStyleFormat);
435template<psd_
byte_order
byteOrder>
438 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
440 KisAslWriterUtils::writeFixedString<byteOrder>(!useLfxsLayerStyleFormat ?
"lfx2" :
"lfxs", io);
459 writePattBlockExImpl<psd_byte_order::psdLittleEndian>(io, patternsXmlDoc);
471 writeLclrBlockExImpl<psd_byte_order::psdLittleEndian>(io,
labelColor);
483 writeFillLayerBlockExImpl<psd_byte_order::psdLittleEndian>(io,
fillConfig, type);
495 writeVectorMaskImpl<psd_byte_order::psdLittleEndian>(io, mask);
507 writeTypeToolImpl<psd_byte_order::psdLittleEndian>(io, typeTool);
519 writeVectorStrokeDataImpl<psd_byte_order::psdLittleEndian>(io,
vectorStroke);
531 writeVectorOriginationDataImpl<psd_byte_order::psdLittleEndian>(io, vectorOrigination);
539template<psd_
byte_order
byteOrder>
542 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
543 KisAslWriterUtils::writeFixedString<byteOrder>(
"Patt", io);
559template<psd_
byte_order
byteOrder>
562 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
563 KisAslWriterUtils::writeFixedString<byteOrder>(
"lclr", io);
565 const quint32 len = 8;
576template<psd_
byte_order
byteOrder>
579 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
581 KisAslWriterUtils::writeFixedString<byteOrder>(
"SoCo", io);
583 KisAslWriterUtils::writeFixedString<byteOrder>(
"GdFl", io);
585 KisAslWriterUtils::writeFixedString<byteOrder>(
"PtFl", io);
602template<psd_
byte_order
byteOrder>
605 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
606 KisAslWriterUtils::writeFixedString<byteOrder>(
"vmsk", io);
612 len += subPath.
nodes.size() * 26;
632 quint16 recordType = 6;
648 const quint16 halfZero = 0;
657 recordType = subPath.
isClosed? 0: 3;
677 psdwriteFixedPoint<byteOrder>(io, node.
control1.y());
678 psdwriteFixedPoint<byteOrder>(io, node.
control1.x());
679 psdwriteFixedPoint<byteOrder>(io, node.
node.y());
680 psdwriteFixedPoint<byteOrder>(io, node.
node.x());
681 psdwriteFixedPoint<byteOrder>(io, node.
control2.y());
682 psdwriteFixedPoint<byteOrder>(io, node.
control2.x());
687template<psd_
byte_order
byteOrder>
690 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
691 KisAslWriterUtils::writeFixedString<byteOrder>(
"TySh", io);
708template<psd_
byte_order
byteOrder>
711 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
712 KisAslWriterUtils::writeFixedString<byteOrder>(
"vstk", io);
731 writeTxt2BlockExImpl<psd_byte_order::psdLittleEndian>(io, txt2Hash);
739template<psd_
byte_order
byteOrder>
742 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
743 KisAslWriterUtils::writeFixedString<byteOrder>(
"Txt2", io);
746 quint32
length = ba.size();
751template<psd_
byte_order
byteOrder>
754 KisAslWriterUtils::writeFixedString<byteOrder>(
"8BIM", io);
755 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 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 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