126void readChildObject(QIODevice &device, QDomElement *parent, QDomDocument *doc,
bool skipKey =
false)
133 key = readVarString<byteOrder>(device);
136 QString OSType = readFixedString<byteOrder>(device);
140 if (OSType ==
"obj ") {
143 }
else if (OSType ==
"Objc" || OSType ==
"GlbO") {
144 readDescriptor<byteOrder>(device, key, parent, doc);
146 }
else if (OSType ==
"VlLs") {
151 for (quint32 i = 0; i < numItems; i++) {
152 readChildObject<byteOrder>(device, &el, doc,
true);
155 }
else if (OSType ==
"doub") {
158 }
else if (OSType ==
"UntF") {
159 const QString unit = readFixedString<byteOrder>(device);
160 const QString
value = readDoubleAsString<byteOrder>(device);
163 el.setAttribute(
"unit", unit);
165 }
else if (OSType ==
"TEXT") {
166 QString unicodeString = readUnicodeString<byteOrder>(device);
169 }
else if (OSType ==
"enum") {
170 const QString typeId = readVarString<byteOrder>(device);
171 const QString
value = readVarString<byteOrder>(device);
174 el.setAttribute(
"typeId", typeId);
176 }
else if (OSType ==
"long") {
179 }
else if (OSType ==
"bool") {
180 const QString
value = readBoolAsString<byteOrder>(device);
183 }
else if (OSType ==
"type") {
185 }
else if (OSType ==
"GlbC") {
187 }
else if (OSType ==
"alis") {
189 }
else if (OSType ==
"tdta") {
191 if (key ==
"EngineData") {
196 QByteArray ba = device.read(len);
198 QDomCDATASection dataSection;
199 dataSection = doc->createCDATASection(ba.toBase64());
200 QDomElement dataElement = doc->createElement(
"node");
201 dataElement.setAttribute(
"type",
"RawData");
202 dataElement.setAttribute(
"key", key);
203 dataElement.appendChild(dataSection);
204 parent->appendChild(dataElement);
243 if (arrayVersion != 3) {
260 QRect arrayRect(x0, y0, x1 - x0, y1 - y0);
265 if (numberOfChannels != 24) {
266 throw ASLParseException(
"VAList: Krita doesn't support ASL files with 'numberOfChannels' flag not equal to 24 (it is not documented)!");
274 if (numPlanes != 1 && numPlanes != 3) {
279 dataPlanes.resize(3);
283 for (
int i = 0; i < numPlanes; i++) {
285 if (!psdread<byteOrder>(device, arrayWritten) || !arrayWritten) {
290 if (!psdread<byteOrder>(device, arrayPlaneLength) || !arrayPlaneLength) {
295 qint64 nextPos = device.pos() + arrayPlaneLength;
307 QRect planeRect(x0, y0, x1 - x0, y1 - y0);
309 if (planeRect != arrayRect) {
316 quint8 useCompression = 9;
327 if (pixelDepth1 != pixelDepth2) {
328 throw ASLParseException(
"VAList: two pixel depths of the plane are not equal (it is not documented)!");
331 if (pixelDepth1 != 1 && pixelDepth1 != 8 && pixelDepth1 != 16) {
332 throw ASLParseException(QString(
"VAList: unsupported pixel depth: %1!").arg(pixelDepth1));
335 const int channelSize = (pixelDepth1 == 1 || pixelDepth1 == 8) ? 1 : 2;
337 const int dataLength = planeRect.width() * planeRect.height() * channelSize;
340 dataPlanes[i] = device.read(arrayPlaneLength - 23);
342 const int numRows = planeRect.height();
345 rowSizes.resize(numRows);
347 for (
int row = 0; row < numRows; row++) {
350 rowSizes[row] = rowSize;
353 for (
int row = 0; row < numRows; row++) {
354 const quint16 rowSize = rowSizes[row];
356 QByteArray compressedData = device.read(rowSize);
358 if (compressedData.size() != rowSize) {
362 dbgFile <<
"Going to decompress the pattern";
364 QByteArray uncompressedData =
367 if (uncompressedData.size() != planeRect.width()) {
371 dataPlanes[i].append(uncompressedData);
374 QByteArray compressedBytes = device.read(arrayPlaneLength - 23);
380 if (dataPlanes[i].size() != dataLength) {
384 if (device.pos() != nextPos) {
385 warnFile <<
"VAList: Data is left out from reading"
386 <<
"(" << device.pos() <<
")";
388 device.seek(nextPos);
391 QImage::Format format{};
393 if (pixelDepth1 == 1 || !
palette.isEmpty()) {
395 format = QImage::Format_Grayscale8;
397 format = QImage::Format_Indexed8;
399 }
else if (pixelDepth1 == 8) {
400 format = QImage::Format_ARGB32;
402 format = QImage::Format_RGBA64;
405 QImage image(arrayRect.size(), format);
407 if (format == QImage::Format_Indexed8) {
410 dbgFile <<
"Loading the data into an image of format" << format << arrayRect <<
"(" << device.pos() <<
")";
412 const int dataLength = arrayRect.width() * arrayRect.height();
414 if (format == QImage::Format_ARGB32) {
415 quint8 *dstPtr = image.bits();
418 for (
int i = 0; i < dataLength; i++) {
419 for (
int j = 2; j >= 0; j--) {
421 if (numPlanes == 1) {
427 *dstPtr++ = dataPlanes[plane][i];
431 }
else if (format == QImage::Format_Indexed8 || format == QImage::Format_Grayscale8) {
432 const auto *dataPlane =
reinterpret_cast<const quint8 *
>(dataPlanes[0].constData());
434 for (
int x = 0; x < arrayRect.height(); x++) {
435 quint8 *dstPtr = image.scanLine(x);
437 for (
int y = 0; y < arrayRect.width(); y++) {
438 *dstPtr++ = dataPlane[x * arrayRect.width() + y];
442 quint16 *dstPtr =
reinterpret_cast<quint16 *
>(image.bits());
444 for (
int i = 0; i < dataLength; i++) {
445 for (
int j = 0; j <= 2; j++) {
446 const int plane = qMin(numPlanes, j);
447 const quint16 *dataPlane =
reinterpret_cast<const quint16 *
>(dataPlanes[plane].constData());
448 *dstPtr++ = qFromBigEndian(dataPlane[i]);
459 return image.convertToFormat(QImage::Format_ARGB32, Qt::AutoColor | Qt::PreferDither);
463qint64
readPattern(QIODevice &device, QDomElement *parent, QDomDocument *doc)
478 if (patternVersion != 1) {
485 dbgFile <<
"Pattern format:" << patternImageMode <<
"(" << device.pos() <<
")";
490 dbgFile <<
"Pattern height:" << patternHeight <<
"(" << device.pos() <<
")";
495 dbgFile <<
"Pattern width:" << patternHeight <<
"(" << device.pos() <<
")";
498 psdread_unicodestring<byteOrder>(device, patternName);
500 dbgFile <<
"Pattern name:" << patternName <<
"(" << device.pos() <<
")";
502 QString patternUuid = readPascalString<byteOrder>(device);
504 dbgFile <<
"Pattern UUID:" << patternUuid <<
"(" << device.pos() <<
")";
527 QString msg = QString(
"Unsupported image mode: %1!").arg(mode);
538 for(
auto i = 0; i < 256; i++) {
542 psdread<byteOrder>(device, r);
543 psdread<byteOrder>(device, g);
544 psdread<byteOrder>(device, b);
552 psdread<byteOrder>(device, validColours);
554 dbgFile <<
"Palette real size:" << validColours <<
"(" << device.pos() <<
")";
558 psdread<byteOrder>(device, transparentIdx);
559 dbgFile <<
"Transparent index:" << transparentIdx <<
"(" << device.pos() <<
")";
562 qGreen(
palette[transparentIdx]),
563 qBlue(
palette[transparentIdx]), 0x00);
570 QDomElement pat = doc->createElement(
"node");
572 pat.setAttribute(
"classId",
"KisPattern");
573 pat.setAttribute(
"type",
"Descriptor");
574 pat.setAttribute(
"name",
"");
577 patternBuf.open(QIODevice::WriteOnly);
581 QString fileName = QString(
"%1.pat").arg(patternUuid);
582 QImage patternImage = readVirtualArrayList<byteOrder>(device, numPlanes,
palette);
583 KoPattern realPattern(patternImage, patternName, fileName);
595 QDomCDATASection dataSection = doc->createCDATASection(qCompress(patternBuf.buffer()).toBase64());
597 QDomElement dataElement = doc->createElement(
"node");
598 dataElement.setAttribute(
"type",
"KisPatternData");
599 dataElement.setAttribute(
"key",
"Data");
601 dataElement.appendChild(dataSection);
602 pat.appendChild(dataElement);
603 parent->appendChild(pat);
605 return sizeof(patternSize) + patternSize;
613 QDomElement root = doc.createElement(
"asl");
614 doc.appendChild(root);
623 const quint32 refSignature = 0x3842534c;
638 if (patternsSize > 0) {
641 QDomElement patternsRoot = doc.createElement(
"node");
642 patternsRoot.setAttribute(
"type",
"List");
644 root.appendChild(patternsRoot);
647 qint64 bytesRead = 0;
648 while (bytesRead < patternsSize) {
649 qint64 chunk =
readPattern(device, &patternsRoot, &doc);
653 warnKrita <<
"WARNING: ASL (emb. pattern):" << e.what();
663 for (
int i = 0; i < (int)numStyles; i++) {
817 if (device.isSequential()) {
818 warnKrita <<
"WARNING: *** KisAslReader::readTypeToolObjectSettings: the supplied"
819 <<
"IO device is sequential. Chances are that"
820 <<
"the fill config will *not* be loaded correctly!";
851 transform = QTransform(xx, xy, yx, yy, tx, ty);
853 QDomElement root = doc.createElement(
"asl");
854 doc.appendChild(root);
856 Private::readDescriptor<byteOrder>(device,
"", &root, &doc);
866 Private::readDescriptor<byteOrder>(device,
"", &root, &doc);
881 warnKrita <<
"WARNING: PSD: TySh section:" << e.what();