Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tiled_data_manager_p.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2004 C. Boemann <cbo@boemann.dk>
3 * SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8
9
10/* FIXME: Think over SSE here */
12 qint32 x, qint32 y,
13 qint32 width, qint32 height,
14 qint32 dataRowStride)
15{
16 if (!data) return;
17
18 width = width < 0 ? 0 : width;
19 height = height < 0 ? 0 : height;
20
21 qint32 dataY = 0;
22 qint32 imageY = y;
23 qint32 rowsRemaining = height;
24 const qint32 pixelSize = this->pixelSize();
25
26 if (dataRowStride <= 0) {
27 dataRowStride = pixelSize * width;
28 }
29
30 while (rowsRemaining > 0) {
31
32 qint32 dataX = 0;
33 qint32 imageX = x;
34 qint32 columnsRemaining = width;
35 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
36 imageX + width - 1);
37
38 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
39
40 while (columnsRemaining > 0) {
41
42 qint32 numContiguousImageColumns =
43 numContiguousColumns(imageX, imageY,
44 imageY + rowsToWork - 1);
45
46 qint32 columnsToWork = qMin(numContiguousImageColumns,
47 columnsRemaining);
48
49 KisTileDataWrapper tw(this, imageX, imageY, KisTileDataWrapper::WRITE);
50 quint8 *tileIt = tw.data();
51
52
53 const qint32 tileRowStride = rowStride(imageX, imageY);
54
55 const quint8 *dataIt = data +
56 dataX * pixelSize + dataY * dataRowStride;
57
58 const qint32 lineSize = columnsToWork * pixelSize;
59
60 for (qint32 row = 0; row < rowsToWork; row++) {
61 memcpy(tileIt, dataIt, lineSize);
62 tileIt += tileRowStride;
63 dataIt += dataRowStride;
64 }
65
66 imageX += columnsToWork;
67 dataX += columnsToWork;
68 columnsRemaining -= columnsToWork;
69 }
70
71 imageY += rowsToWork;
72 dataY += rowsToWork;
73 rowsRemaining -= rowsToWork;
74 }
75}
76
77
79 qint32 x, qint32 y,
80 qint32 width, qint32 height,
81 qint32 dataRowStride) const
82{
83 if (!data) return;
84
85 width = width < 0 ? 0 : width;
86 height = height < 0 ? 0 : height;
87
88 qint32 dataY = 0;
89 qint32 imageY = y;
90 qint32 rowsRemaining = height;
91 const qint32 pixelSize = this->pixelSize();
92
93 if (dataRowStride <= 0) {
94 dataRowStride = pixelSize * width;
95 }
96
97 while (rowsRemaining > 0) {
98
99 qint32 dataX = 0;
100 qint32 imageX = x;
101 qint32 columnsRemaining = width;
102 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
103 imageX + width - 1);
104
105 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
106
107 while (columnsRemaining > 0) {
108
109 qint32 numContiguousImageColumns = numContiguousColumns(imageX, imageY,
110 imageY + rowsToWork - 1);
111
112 qint32 columnsToWork = qMin(numContiguousImageColumns,
113 columnsRemaining);
114
115 // XXX: Ugly const cast because of the old pixelPtr design copied from tiles1.
116 KisTileDataWrapper tw(const_cast<KisTiledDataManager*>(this), imageX, imageY, KisTileDataWrapper::READ);
117 quint8 *tileIt = tw.data();
118
119
120 const qint32 tileRowStride = rowStride(imageX, imageY);
121
122 quint8 *dataIt = data +
123 dataX * pixelSize + dataY * dataRowStride;
124
125 const qint32 lineSize = columnsToWork * pixelSize;
126
127 for (qint32 row = 0; row < rowsToWork; row++) {
128 memcpy(dataIt, tileIt, lineSize);
129 tileIt += tileRowStride;
130 dataIt += dataRowStride;
131 }
132
133 imageX += columnsToWork;
134 dataX += columnsToWork;
135 columnsRemaining -= columnsToWork;
136 }
137
138 imageY += rowsToWork;
139 dataY += rowsToWork;
140 rowsRemaining -= rowsToWork;
141 }
142}
143
144
145#define forEachChannel(_idx, _channelSize) \
146 for(qint32 _idx=0, _channelSize=channelSizes[_idx]; \
147 _idx<numChannels && (_channelSize=channelSizes[_idx], 1); \
148 _idx++)
149
150template <bool allChannelsPresent>
151void KisTiledDataManager::writePlanarBytesBody(QVector </*const*/ quint8* > planes,
152 QVector<qint32> channelSizes,
153 qint32 x, qint32 y,
154 qint32 width, qint32 height)
155{
156 Q_ASSERT(planes.size() == channelSizes.size());
157 Q_ASSERT(planes.size() > 0);
158
159 width = width < 0 ? 0 : width;
160 height = height < 0 ? 0 : height;
161
162 const qint32 numChannels = planes.size();
163 const qint32 pixelSize = this->pixelSize();
164
165 qint32 dataY = 0;
166 qint32 imageY = y;
167 qint32 rowsRemaining = height;
168
169 while (rowsRemaining > 0) {
170
171 qint32 dataX = 0;
172 qint32 imageX = x;
173 qint32 columnsRemaining = width;
174 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
175 imageX + width - 1);
176
177 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
178
179 while (columnsRemaining > 0) {
180
181 qint32 numContiguousImageColumns =
182 numContiguousColumns(imageX, imageY,
183 imageY + rowsToWork - 1);
184 qint32 columnsToWork = qMin(numContiguousImageColumns,
185 columnsRemaining);
186
187 const qint32 dataIdx = dataX + dataY * width;
188 const qint32 tileRowStride = rowStride(imageX, imageY) -
189 columnsToWork * pixelSize;
190
191 KisTileDataWrapper tw(this, imageX, imageY,
193 quint8 *tileItStart = tw.data();
194
195
196 forEachChannel(i, channelSize) {
197 if (allChannelsPresent || planes[i]) {
198 const quint8* planeIt = planes[i] + dataIdx * channelSize;
199 qint32 dataStride = (width - columnsToWork) * channelSize;
200 quint8* tileIt = tileItStart;
201
202 for (qint32 row = 0; row < rowsToWork; row++) {
203 for (int col = 0; col < columnsToWork; col++) {
204 memcpy(tileIt, planeIt, channelSize);
205 tileIt += pixelSize;
206 planeIt += channelSize;
207 }
208
209 tileIt += tileRowStride;
210 planeIt += dataStride;
211 }
212 }
213
214 tileItStart += channelSize;
215 }
216
217 imageX += columnsToWork;
218 dataX += columnsToWork;
219 columnsRemaining -= columnsToWork;
220 }
221
222
223 imageY += rowsToWork;
224 dataY += rowsToWork;
225 rowsRemaining -= rowsToWork;
226 }
227}
228
230 qint32 x, qint32 y,
231 qint32 width, qint32 height) const
232{
233 Q_ASSERT(channelSizes.size() > 0);
234
235 width = width < 0 ? 0 : width;
236 height = height < 0 ? 0 : height;
237
238 const qint32 numChannels = channelSizes.size();
239 const qint32 pixelSize = this->pixelSize();
240
241 QVector<quint8*> planes;
242 forEachChannel(i, channelSize) {
243 planes.append(new quint8[width * height * channelSize]);
244 }
245
246 qint32 dataY = 0;
247 qint32 imageY = y;
248 qint32 rowsRemaining = height;
249
250 while (rowsRemaining > 0) {
251
252 qint32 dataX = 0;
253 qint32 imageX = x;
254 qint32 columnsRemaining = width;
255 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX,
256 imageX + width - 1);
257
258 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
259
260 while (columnsRemaining > 0) {
261
262 qint32 numContiguousImageColumns =
263 numContiguousColumns(imageX, imageY,
264 imageY + rowsToWork - 1);
265 qint32 columnsToWork = qMin(numContiguousImageColumns,
266 columnsRemaining);
267
268 const qint32 dataIdx = dataX + dataY * width;
269 const qint32 tileRowStride = rowStride(imageX, imageY) -
270 columnsToWork * pixelSize;
271
272 // XXX: Ugly const cast because of the old pixelPtr design copied from tiles1.
273 KisTileDataWrapper tw(const_cast<KisTiledDataManager*>(this), imageX, imageY,
275 quint8 *tileItStart = tw.data();
276
277
278 forEachChannel(i, channelSize) {
279 quint8* planeIt = planes[i] + dataIdx * channelSize;
280 qint32 dataStride = (width - columnsToWork) * channelSize;
281 quint8* tileIt = tileItStart;
282
283 for (qint32 row = 0; row < rowsToWork; row++) {
284 for (int col = 0; col < columnsToWork; col++) {
285 memcpy(planeIt, tileIt, channelSize);
286 tileIt += pixelSize;
287 planeIt += channelSize;
288 }
289
290 tileIt += tileRowStride;
291 planeIt += dataStride;
292 }
293 tileItStart += channelSize;
294 }
295
296 imageX += columnsToWork;
297 dataX += columnsToWork;
298 columnsRemaining -= columnsToWork;
299 }
300
301
302 imageY += rowsToWork;
303 dataY += rowsToWork;
304 rowsRemaining -= rowsToWork;
305 }
306 return planes;
307}
308
309
310
311
void readBytesBody(quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride=-1) const
QVector< quint8 * > readPlanarBytesBody(QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const
qint32 rowStride(qint32 x, qint32 y) const
void writePlanarBytesBody(QVector< quint8 * > planes, QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h)
qint32 numContiguousRows(qint32 y, qint32 minX, qint32 maxX) const
qint32 numContiguousColumns(qint32 x, qint32 minY, qint32 maxY) const
void writeBytesBody(const quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride=-1)
#define forEachChannel(_idx, _channelSize)