23int compress(
const QByteArray &src, QByteArray &dst)
32 const char *start = src.constData();
35 while (remaining > 0) {
38 while ((i < 128) && (remaining - i > 0) && (start[0] == start[i]))
43 dst[dest_ptr++] =
static_cast<char>(-(i - 1));
44 dst[dest_ptr++] = *start;
51 while ((i < 128) && (remaining - (i + 1) > 0) && (start[i] != start[(i + 1)] || remaining - (i + 2) <= 0 || start[i] != start[(i + 2)]))
63 dst[dest_ptr++] =
static_cast<char>(i - 1U);
64 for (j = 0; j < i; j++) {
65 dst[dest_ptr++] = start[j];
87QByteArray
decompress(
const QByteArray &input,
int unpacked_len)
90 output.resize(unpacked_len);
92 const auto *src = input.cbegin();
93 auto *dst = output.begin();
95 while (src < input.end() && dst < output.end()) {
97 const int8_t n = *
reinterpret_cast<const int8_t *
>(src);
101 const int bytes = 1 + n;
102 if (src + bytes > input.cend()) {
103 errFile <<
"Input buffer exhausted in replicate of" << bytes <<
"chars, left" << (input.cend() - src);
106 if (dst + bytes > output.end()) {
107 errFile <<
"Overrun in packbits replicate of" << bytes <<
"chars, left" << (output.end() - dst);
110 std::copy_n(src, bytes, dst);
113 }
else if (n >= -127 && n <= -1) {
114 const int bytes = 1 - n;
115 if (src >= input.cend()) {
116 errFile <<
"Input buffer exhausted in copy";
119 if (dst + bytes > output.end()) {
120 errFile <<
"Output buffer exhausted in copy of" << bytes <<
"chars, left" << (output.end() - dst);
123 const auto byte = *src;
124 std::fill_n(dst, bytes,
byte);
127 }
else if (n == -128) {
132 if (dst < output.end()) {
133 errFile <<
"Packbits decode - unpack left" << (output.end() - dst);
134 std::fill(dst, output.end(), 0);
138 if (src + 1 < input.cend()) {
139 QByteArray leftovers;
140 leftovers.resize(
static_cast<int>(input.cend() - src));
141 std::copy(src, input.cend(), leftovers.begin());
142 errFile <<
"Packbits decode - pack left" << leftovers.size() << leftovers.toHex();
152int compress(
const char *input,
int unpacked_len,
char *dst,
int maxout)
157 stream.data_type = Z_BINARY;
158 stream.next_in =
const_cast<Bytef *
>(
reinterpret_cast<const Bytef *
>(input));
159 stream.avail_in =
static_cast<uInt
>(unpacked_len);
160 stream.next_out =
reinterpret_cast<Bytef *
>(dst);
161 stream.avail_out =
static_cast<uInt
>(maxout);
163 dbgFile <<
"Expected unpacked length:" << unpacked_len <<
", maxout:" << maxout;
165 if (deflateInit(&stream, -1) != Z_OK) {
166 dbgFile <<
"Failed deflate initialization";
170 int flush = Z_PARTIAL_FLUSH;
173 state = deflate(&stream, flush);
174 if (state == Z_STREAM_END) {
175 dbgFile <<
"Finished deflating";
177 }
else if (state != Z_OK) {
178 dbgFile <<
"Error deflating" << state << stream.msg;
181 }
while (stream.avail_in > 0);
183 if (state != Z_OK || stream.avail_in > 0) {
184 dbgFile <<
"Failed deflating" << state << stream.msg;
188 dbgFile <<
"Success, deflated size:" << stream.total_out;
190 return static_cast<int>(stream.total_out);
195 QByteArray output(data.length() * 4,
'\0');
196 const int result =
KisZip::compress(data.constData(), data.size(), output.data(), output.size());
197 output.resize(result);
213 stream.data_type = Z_BINARY;
214 stream.next_in =
const_cast<Bytef *
>(
reinterpret_cast<const Bytef *
>(src));
215 stream.avail_in =
static_cast<uInt
>(packed_len);
216 stream.next_out =
reinterpret_cast<Bytef *
>(dst);
217 stream.avail_out =
static_cast<uInt
>(unpacked_len);
219 if (inflateInit(&stream) != Z_OK)
222 int flush = Z_PARTIAL_FLUSH;
225 state = inflate(&stream, flush);
226 if (state == Z_STREAM_END) {
227 dbgFile <<
"Finished inflating";
229 }
else if (state == Z_DATA_ERROR) {
230 dbgFile <<
"Error inflating" << state << stream.msg;
231 if (inflateSync(&stream) != Z_OK)
235 }
while (stream.avail_out > 0);
237 if ((state != Z_STREAM_END && state != Z_OK) || stream.avail_out > 0) {
238 dbgFile <<
"Failed inflating" << state << stream.msg;
242 return static_cast<int>(stream.total_out);
251 auto *buf =
reinterpret_cast<uint8_t *
>(dst_buf.data());
253 int dst_len = dst_buf.size();
255 while (dst_len > 0) {
269 auto *buf =
reinterpret_cast<uint8_t *
>(dst_buf.data());
271 int dst_len = dst_buf.size();
273 while (dst_len > 0) {
276 buf[2] += buf[0] + ((buf[1] + buf[3]) >> 8);
281 dst_len -= row_size * 2;
289 if (dst_buf.size() == 0)
292 if (color_depth == 32) {
294 errKrita <<
"Unsupported bit depth for prediction";
296 }
else if (color_depth == 16) {
297 psd_unzip_with_prediction<quint16>(dst_buf, row_size);
299 psd_unzip_with_prediction<quint8>(dst_buf, row_size);
315 auto *buf =
reinterpret_cast<uint8_t *
>(dst_buf.data());
317 int dst_len = dst_buf.size();
319 while (dst_len > 0) {
333 auto *buf =
reinterpret_cast<uint8_t *
>(dst_buf.data());
335 int dst_len = dst_buf.size();
337 while (dst_len > 0) {
340 buf[2] -= buf[0] + ((buf[1] + buf[3]) >> 8);
345 dst_len -= row_size * 2;
351 QByteArray dst_buf(src);
352 if (color_depth == 32) {
354 errKrita <<
"Unsupported bit depth for prediction";
356 }
else if (color_depth == 16) {
357 psd_zip_with_prediction<quint16>(dst_buf, row_size);
359 psd_zip_with_prediction<quint8>(dst_buf, row_size);
365QByteArray
decompress(
const QByteArray &data,
int expected_length)
367 QByteArray output(expected_length,
'\0');
378 if (bytes.size() < 1)
381 switch (compressionType) {
391 qFatal(
"Cannot uncompress layer data: invalid compression type");
399 if (bytes.size() < 1)
402 switch (compressionType) {
412 qFatal(
"Cannot compress layer data: invalid compression type");
qreal length(const QPointF &vec)
static QByteArray uncompress(int unpacked_len, QByteArray bytes, psd_compression_type compressionType, int row_size=0, int color_depth=0)
static QByteArray compress(QByteArray bytes, psd_compression_type compressionType, int row_size=0, int color_depth=0)
QByteArray decompress(const QByteArray &input, int unpacked_len)
int compress(const QByteArray &src, QByteArray &dst)
int psd_unzip_without_prediction(const char *src, int packed_len, char *dst, int unpacked_len)
QByteArray decompress(const QByteArray &data, int expected_length)
void psd_zip_with_prediction< uint16_t >(QByteArray &dst_buf, const int row_size)
void psd_unzip_with_prediction< uint8_t >(QByteArray &dst_buf, const int row_size)
void psd_unzip_with_prediction< uint16_t >(QByteArray &dst_buf, const int row_size)
void psd_unzip_with_prediction(QByteArray &dst_buf, int row_size)
void psd_zip_with_prediction< uint8_t >(QByteArray &dst_buf, const int row_size)
void psd_zip_with_prediction(QByteArray &dst_buf, int row_size)
int compress(const char *input, int unpacked_len, char *dst, int maxout)