mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2026-07-24 08:40:58 -04:00
IFF: read only support to Interchange Format Files
Read-only support for most common Interchange Format Files (IFF). Supports IFF saved by Photoshop for the Amiga and Maya platform and HAM6 coded files. Closes #29
This commit is contained in:
committed by
Albert Astals Cid
parent
e6357c22f7
commit
4f2f2425d3
111
src/imageformats/packbits_p.h
Normal file
111
src/imageformats/packbits_p.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Packbits compression used on many legacy formats (IFF, PSD, TIFF).
|
||||
|
||||
SPDX-FileCopyrightText: 2025 Mirco Miranda <mircomir@outlook.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
#ifndef PACKBITS_P_H
|
||||
#define PACKBITS_P_H
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
/*!
|
||||
* \brief packbitsDecompress
|
||||
* Fast PackBits decompression.
|
||||
* \param input The compressed input buffer.
|
||||
* \param ilen The input buffer size.
|
||||
* \param output The uncompressed target buffer.
|
||||
* \param olen The target buffer size.
|
||||
* \param allowN128 If true, -128 is a valid run length size (false for PSD / TIFF, true for IFF) .
|
||||
* \return The number of valid bytes in the target buffer.
|
||||
*/
|
||||
inline qint64 packbitsDecompress(const char *input, qint64 ilen, char *output, qint64 olen, bool allowN128 = false)
|
||||
{
|
||||
qint64 j = 0;
|
||||
for (qint64 ip = 0, rr = 0, available = olen; j < olen && ip < ilen; available = olen - j) {
|
||||
signed char n = static_cast<signed char>(input[ip++]);
|
||||
if (n == -128 && !allowN128)
|
||||
continue;
|
||||
|
||||
if (n >= 0) {
|
||||
rr = qint64(n) + 1;
|
||||
if (available < rr) {
|
||||
--ip;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ip + rr > ilen)
|
||||
return -1;
|
||||
memcpy(output + j, input + ip, size_t(rr));
|
||||
ip += rr;
|
||||
} else if (ip < ilen) {
|
||||
rr = qint64(1-n);
|
||||
if (available < rr) {
|
||||
--ip;
|
||||
break;
|
||||
}
|
||||
memset(output + j, input[ip++], size_t(rr));
|
||||
}
|
||||
|
||||
j += rr;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief packbitsDecompress
|
||||
* PackBits decompression.
|
||||
* \param input The input device.
|
||||
* \param output The uncompressed target buffer.
|
||||
* \param olen The target buffer size.
|
||||
* \param allowN128 If true, -128 is a valid run length size (false for PSD / TIFF, true for IFF) .
|
||||
* \return The number of valid bytes in the target buffer.
|
||||
*/
|
||||
inline qint64 packbitsDecompress(QIODevice *input, char *output, qint64 olen, bool allowN128 = false)
|
||||
{
|
||||
qint64 j = 0;
|
||||
for (qint64 rr = 0, available = olen; j < olen; available = olen - j) {
|
||||
char n;
|
||||
|
||||
// check the output buffer space for the next run
|
||||
if (available < 129) {
|
||||
if (input->peek(&n, 1) != 1) { // end of data (or error)
|
||||
break;
|
||||
}
|
||||
if (static_cast<signed char>(n) != -128 || allowN128)
|
||||
if ((static_cast<signed char>(n) >= 0 ? qint64(n) + 1 : qint64(1 - n)) > available)
|
||||
break;
|
||||
}
|
||||
|
||||
// decompress
|
||||
if (input->read(&n, 1) != 1) { // end of data (or error)
|
||||
break;
|
||||
}
|
||||
|
||||
if (static_cast<signed char>(n) == -128 && !allowN128) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (static_cast<signed char>(n) >= 0) {
|
||||
rr = input->read(output + j, qint64(n) + 1);
|
||||
if (rr == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char b;
|
||||
if (input->read(&b, 1) != 1) {
|
||||
break;
|
||||
}
|
||||
rr = qint64(1 - static_cast<signed char>(n));
|
||||
std::memset(output + j, b, size_t(rr));
|
||||
}
|
||||
|
||||
j += rr;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
#endif // PACKBITS_P_H
|
||||
Reference in New Issue
Block a user