Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tiff_psd_layer_record.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Krita
3 *
4 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
10#include "psd_utils.h"
11
12#include <QBuffer>
13#include <QLatin1String>
16#include <kis_debug.h>
17#include <memory>
18#include <psd_header.h>
19#include <tiff.h>
20
22 uint32_t width,
23 uint32_t height,
24 uint16_t channelDepth,
25 uint16_t nChannels,
26 uint16_t photometricInterpretation,
27 bool hasTransparency)
28 : m_byteOrder(isBigEndian ? psd_byte_order::psdBigEndian : psd_byte_order::psdLittleEndian)
29 , m_width(width)
30 , m_height(height)
31 , m_channelDepth(channelDepth)
32 , m_nChannels(nChannels)
33 , m_hasTransparency(hasTransparency)
34 , m_valid(false)
35{
36 if (photometricInterpretation == PHOTOMETRIC_MINISWHITE || photometricInterpretation == PHOTOMETRIC_MINISBLACK) {
38 } else if (photometricInterpretation == PHOTOMETRIC_RGB) {
40 } else if (photometricInterpretation == PHOTOMETRIC_SEPARATED) {
41 dbgFile << "PSD warning: assuming CMYK for color separations";
43 } else if (photometricInterpretation == PHOTOMETRIC_CIELAB || photometricInterpretation == PHOTOMETRIC_ICCLAB) {
45 } else if (photometricInterpretation == PHOTOMETRIC_PALETTE) {
47 } else {
48 dbgFile << "TIFF PSD error: " << photometricInterpretation << "does not map to a Photoshop supported mode";
50 }
51}
52
53bool KisTiffPsdLayerRecord::read(QIODevice &io)
54{
55 switch (m_byteOrder) {
57 return readImpl<psd_byte_order::psdLittleEndian>(io);
58 default:
59 return readImpl(io);
60 }
61}
62
63bool KisTiffPsdLayerRecord::write(QIODevice &io, KisNodeSP rootLayer, psd_compression_type compressionType)
64{
65 switch (m_byteOrder) {
67 return writeImpl<psd_byte_order::psdLittleEndian>(io, rootLayer, compressionType);
68 default:
69 return writeImpl(io, rootLayer, compressionType);
70 }
71}
72
73template<psd_byte_order byteOrder>
74bool KisTiffPsdLayerRecord::readImpl(QIODevice &device)
75{
76 PSDHeader header;
77 header.version = 1;
78 header.byteOrder = byteOrder;
79 header.width = m_width;
80 header.height = m_height;
82 header.nChannels = m_nChannels;
83 header.colormode = m_colorMode;
84 header.tiffStyleLayerBlock = true;
85 m_record = std::make_shared<PSDLayerMaskSection>(header);
86
87 QLatin1String signature("Adobe Photoshop Document Data Block");
88 QByteArray b = device.read(signature.size() + 1);
89 if (b.size() != signature.size() + 1 || QLatin1String(b) != signature) {
90 m_record->error = QString("Invalid Photoshop data block: %1").arg(QLatin1String(b));
91 return false;
92 }
93
94 if (!m_record->read(device)) {
95 dbgFile << "failed reading PSD section: " << m_record->error;
96 return false;
97 }
98
99 dbgFile << "Resource section: " << m_record->nLayers;
100
101 m_valid = true;
102
103 return true;
104}
105
106template<psd_byte_order byteOrder>
107bool KisTiffPsdLayerRecord::writeImpl(QIODevice &device, KisNodeSP rootLayer, psd_compression_type compressionType)
108{
109 PSDHeader header;
110 header.version = 1;
111 header.byteOrder = byteOrder;
112 header.width = m_width;
113 header.height = m_height;
115 header.nChannels = m_nChannels;
116 header.colormode = m_colorMode;
117 header.tiffStyleLayerBlock = true;
118 m_record = std::make_shared<PSDLayerMaskSection>(header);
119 m_record->hasTransparency = m_hasTransparency;
120
121 QBuffer buf;
122 buf.open(QIODevice::WriteOnly);
123
124 psdwrite(buf, "Adobe Photoshop Document Data Block");
125 psdpad(buf, 1);
126
127 if (!m_record->write(buf, rootLayer, compressionType)) {
128 dbgFile << "failed writing PSD section: " << m_record->error;
129 return false;
130 }
131
132 buf.close();
133
134 // Then get the size
135 qint64 layerSectionLength = buf.size();
136 dbgFile << "layer section has size" << layerSectionLength;
137
138 // and write the whole buffer
139 return (device.write(buf.data()) == layerSectionLength);
140}
141
142std::shared_ptr<PSDLayerMaskSection> KisTiffPsdLayerRecord::record() const
143{
144 return m_record;
145}
146
148{
149 return m_valid;
150}
bool readImpl(QIODevice &device)
bool write(QIODevice &io, KisNodeSP rootLayer, psd_compression_type compressionType)
KisTiffPsdLayerRecord(bool isBigEndian, uint32_t width, uint32_t height, uint16_t channelDepth, uint16_t nChannels, uint16_t photometricInterpretation, bool hasTransparency=false)
std::shared_ptr< PSDLayerMaskSection > record() const
bool writeImpl(QIODevice &device, KisNodeSP rootLayer, psd_compression_type compressionType)
std::shared_ptr< PSDLayerMaskSection > m_record
psd_color_mode colormode
Definition psd_header.h:48
quint16 channelDepth
Definition psd_header.h:47
quint16 version
Definition psd_header.h:43
bool tiffStyleLayerBlock
Definition psd_header.h:50
quint16 nChannels
Definition psd_header.h:44
quint32 height
Definition psd_header.h:45
quint32 width
Definition psd_header.h:46
psd_byte_order byteOrder
Definition psd_header.h:49
#define dbgFile
Definition kis_debug.h:53
psd_byte_order
Definition psd.h:33
psd_compression_type
Definition psd.h:39
@ Lab
Definition psd.h:58
@ RGB
Definition psd.h:54
@ CMYK
Definition psd.h:55
@ COLORMODE_UNKNOWN
Definition psd.h:65
@ Indexed
Definition psd.h:53
@ Grayscale
Definition psd.h:52
bool psdpad(QIODevice &io, quint32 padding)
Definition psd_utils.h:248
std::enable_if_t< std::is_arithmetic< T >::value, bool > psdwrite(QIODevice &io, T v)
Definition psd_utils.h:170