Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tile_compressor_2.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
9#include <QIODevice>
11#define TILE_DATA_SIZE(pixelSize) ((pixelSize) * KisTileData::WIDTH * KisTileData::HEIGHT)
12
13const QString KisTileCompressor2::m_compressionName = "LZF";
14
15
20
25
27{
28 const qint32 tileDataSize = TILE_DATA_SIZE(tile->pixelSize());
29 prepareStreamingBuffer(tileDataSize);
30
31 qint32 bytesWritten;
32
33 tile->lockForRead();
34 compressTileData(tile->tileData(), (quint8*)m_streamingBuffer.data(),
35 m_streamingBuffer.size(), bytesWritten);
36 tile->unlockForRead();
37
38 QString header = getHeader(tile, bytesWritten);
39 bool retval = true;
40 retval = store.write(header.toLatin1());
41 if (!retval) {
42 warnFile << "Failed to write the tile header";
43 }
44 retval = store.write(m_streamingBuffer.data(), bytesWritten);
45 if (!retval) {
46 warnFile << "Failed to write the tile data";
47 }
48 return retval;
49}
50
52{
53 const qint32 tileDataSize = TILE_DATA_SIZE(pixelSize(dm));
54 prepareStreamingBuffer(tileDataSize);
55
56 QByteArray header = stream->readLine(maxHeaderLength());
57
58 QList<QByteArray> headerItems = header.trimmed().split(',');
59 if (headerItems.size() == 4) {
60 qint32 x = headerItems.takeFirst().toInt();
61 qint32 y = headerItems.takeFirst().toInt();
62 QString compressionName = headerItems.takeFirst();
63 qint32 dataSize = headerItems.takeFirst().toInt();
64
65 Q_ASSERT(headerItems.isEmpty());
66 Q_ASSERT(compressionName == m_compressionName);
67
68 qint32 row = yToRow(dm, y);
69 qint32 col = xToCol(dm, x);
70
71 KisTileSP tile = dm->getTile(col, row, true);
72
73 stream->read(m_streamingBuffer.data(), dataSize);
74
75 tile->lockForWrite();
76 bool res = decompressTileData((quint8*)m_streamingBuffer.data(), dataSize, tile->tileData());
77 tile->unlockForWrite();
78 return res;
79 }
80 return false;
81}
82
84{
89 m_streamingBuffer.resize(tileDataSize + 1);
90}
91
93{
94 const qint32 bufferSize = m_compression->outputBufferSize(tileDataSize);
95
96 if (m_linearizationBuffer.size() < tileDataSize) {
97 m_linearizationBuffer.resize(tileDataSize);
98 }
99
100 if (m_compressionBuffer.size() < bufferSize) {
101 m_compressionBuffer.resize(bufferSize);
102 }
103}
104
106 quint8 *buffer,
107 qint32 bufferSize,
108 qint32 &bytesWritten)
109{
110 const qint32 pixelSize = tileData->pixelSize();
111 const qint32 tileDataSize = TILE_DATA_SIZE(pixelSize);
112 qint32 compressedBytes;
113
114 Q_UNUSED(bufferSize);
115 Q_ASSERT(bufferSize >= tileDataSize + 1);
116
117 prepareWorkBuffers(tileDataSize);
118
120 tileDataSize, pixelSize);
121
122 compressedBytes = m_compression->compress((quint8*)m_linearizationBuffer.data(), tileDataSize,
123 (quint8*)m_compressionBuffer.data(), m_compressionBuffer.size());
124
125 if(compressedBytes < tileDataSize) {
126 buffer[0] = COMPRESSED_DATA_FLAG;
127 memcpy(buffer + 1, m_compressionBuffer.data(), compressedBytes);
128 bytesWritten = compressedBytes + 1;
129 }
130 else {
131 buffer[0] = RAW_DATA_FLAG;
132 memcpy(buffer + 1, tileData->data(), tileDataSize);
133 bytesWritten = tileDataSize + 1;
134 }
135}
136
138 qint32 bufferSize,
139 KisTileData *tileData)
140{
141 const qint32 pixelSize = tileData->pixelSize();
142 const qint32 tileDataSize = TILE_DATA_SIZE(pixelSize);
143
144 if(buffer[0] == COMPRESSED_DATA_FLAG) {
145 prepareWorkBuffers(tileDataSize);
146
147 qint32 bytesWritten;
148 bytesWritten = m_compression->decompress(buffer + 1, bufferSize - 1,
149 (quint8*)m_linearizationBuffer.data(), tileDataSize);
150 if (bytesWritten == tileDataSize) {
152 tileData->data(),
153 tileDataSize, pixelSize);
154 return true;
155 }
156 return false;
157 }
158 else {
159 memcpy(tileData->data(), buffer + 1, tileDataSize);
160 return true;
161 }
162 return false;
163
164}
165
167{
168 return TILE_DATA_SIZE(tileData->pixelSize()) + 1;
169}
170
172{
173 static const qint32 QINT32_LENGTH = 11;
174 static const qint32 COMPRESSION_NAME_LENGTH = 5;
175 static const qint32 SEPARATORS_LENGTH = 4;
176
177 return 3 * QINT32_LENGTH + COMPRESSION_NAME_LENGTH + SEPARATORS_LENGTH;
178}
179
181 qint32 compressedSize)
182{
183 qint32 x, y;
184 qint32 width, height;
185 tile->extent().getRect(&x, &y, &width, &height);
186
187 return QString("%1,%2,%3,%4\n").arg(x).arg(y).arg(m_compressionName).arg(compressedSize);
188}
virtual qint32 decompress(const quint8 *input, qint32 inputLength, quint8 *output, qint32 outputLength)=0
static void linearizeColors(quint8 *input, quint8 *output, qint32 dataSize, qint32 pixelSize)
static void delinearizeColors(quint8 *input, quint8 *output, qint32 dataSize, qint32 pixelSize)
virtual qint32 outputBufferSize(qint32 dataSize)=0
virtual qint32 compress(const quint8 *input, qint32 inputLength, quint8 *output, qint32 outputLength)=0
qint32 xToCol(KisTiledDataManager *dm, qint32 x)
qint32 yToRow(KisTiledDataManager *dm, qint32 y)
qint32 pixelSize(KisTiledDataManager *dm)
virtual bool write(const QByteArray &data)=0
KisAbstractCompression * m_compression
static const QString m_compressionName
void prepareStreamingBuffer(qint32 tileDataSize)
bool writeTile(KisTileSP tile, KisPaintDeviceWriter &store) override
bool decompressTileData(quint8 *buffer, qint32 bufferSize, KisTileData *tileData) override
qint32 tileDataBufferSize(KisTileData *tileData) override
void prepareWorkBuffers(qint32 tileDataSize)
QString getHeader(KisTileSP tile, qint32 compressedSize)
bool readTile(QIODevice *io, KisTiledDataManager *dm) override
static const qint8 RAW_DATA_FLAG
static const qint8 COMPRESSED_DATA_FLAG
void compressTileData(KisTileData *tileData, quint8 *buffer, qint32 bufferSize, qint32 &bytesWritten) override
quint32 pixelSize() const
quint8 * data() const
void lockForWrite()
Definition kis_tile.cc:221
void lockForRead() const
Definition kis_tile.cc:208
QRect extent() const
Definition kis_tile.h:99
KisTileData * tileData() const
Definition kis_tile.h:118
void unlockForWrite()
Definition kis_tile.cc:264
void unlockForRead() const
Definition kis_tile.cc:275
qint32 pixelSize() const
Definition kis_tile.h:113
KisTileSP getTile(qint32 col, qint32 row, bool writable)
#define warnFile
Definition kis_debug.h:95
#define TILE_DATA_SIZE(pixelSize)