File indexing completed on 2024-12-22 04:10:34
0001 /* 0002 * SPDX-FileCopyrightText: 2004 C. Boemann <cbo@boemann.dk> 0003 * SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 0009 0010 /* FIXME: Think over SSE here */ 0011 void KisTiledDataManager::writeBytesBody(const quint8 *data, 0012 qint32 x, qint32 y, 0013 qint32 width, qint32 height, 0014 qint32 dataRowStride) 0015 { 0016 if (!data) return; 0017 0018 width = width < 0 ? 0 : width; 0019 height = height < 0 ? 0 : height; 0020 0021 qint32 dataY = 0; 0022 qint32 imageY = y; 0023 qint32 rowsRemaining = height; 0024 const qint32 pixelSize = this->pixelSize(); 0025 0026 if (dataRowStride <= 0) { 0027 dataRowStride = pixelSize * width; 0028 } 0029 0030 while (rowsRemaining > 0) { 0031 0032 qint32 dataX = 0; 0033 qint32 imageX = x; 0034 qint32 columnsRemaining = width; 0035 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX, 0036 imageX + width - 1); 0037 0038 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining); 0039 0040 while (columnsRemaining > 0) { 0041 0042 qint32 numContiguousImageColumns = 0043 numContiguousColumns(imageX, imageY, 0044 imageY + rowsToWork - 1); 0045 0046 qint32 columnsToWork = qMin(numContiguousImageColumns, 0047 columnsRemaining); 0048 0049 KisTileDataWrapper tw(this, imageX, imageY, KisTileDataWrapper::WRITE); 0050 quint8 *tileIt = tw.data(); 0051 0052 0053 const qint32 tileRowStride = rowStride(imageX, imageY); 0054 0055 const quint8 *dataIt = data + 0056 dataX * pixelSize + dataY * dataRowStride; 0057 0058 const qint32 lineSize = columnsToWork * pixelSize; 0059 0060 for (qint32 row = 0; row < rowsToWork; row++) { 0061 memcpy(tileIt, dataIt, lineSize); 0062 tileIt += tileRowStride; 0063 dataIt += dataRowStride; 0064 } 0065 0066 imageX += columnsToWork; 0067 dataX += columnsToWork; 0068 columnsRemaining -= columnsToWork; 0069 } 0070 0071 imageY += rowsToWork; 0072 dataY += rowsToWork; 0073 rowsRemaining -= rowsToWork; 0074 } 0075 } 0076 0077 0078 void KisTiledDataManager::readBytesBody(quint8 *data, 0079 qint32 x, qint32 y, 0080 qint32 width, qint32 height, 0081 qint32 dataRowStride) const 0082 { 0083 if (!data) return; 0084 0085 width = width < 0 ? 0 : width; 0086 height = height < 0 ? 0 : height; 0087 0088 qint32 dataY = 0; 0089 qint32 imageY = y; 0090 qint32 rowsRemaining = height; 0091 const qint32 pixelSize = this->pixelSize(); 0092 0093 if (dataRowStride <= 0) { 0094 dataRowStride = pixelSize * width; 0095 } 0096 0097 while (rowsRemaining > 0) { 0098 0099 qint32 dataX = 0; 0100 qint32 imageX = x; 0101 qint32 columnsRemaining = width; 0102 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX, 0103 imageX + width - 1); 0104 0105 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining); 0106 0107 while (columnsRemaining > 0) { 0108 0109 qint32 numContiguousImageColumns = numContiguousColumns(imageX, imageY, 0110 imageY + rowsToWork - 1); 0111 0112 qint32 columnsToWork = qMin(numContiguousImageColumns, 0113 columnsRemaining); 0114 0115 // XXX: Ugly const cast because of the old pixelPtr design copied from tiles1. 0116 KisTileDataWrapper tw(const_cast<KisTiledDataManager*>(this), imageX, imageY, KisTileDataWrapper::READ); 0117 quint8 *tileIt = tw.data(); 0118 0119 0120 const qint32 tileRowStride = rowStride(imageX, imageY); 0121 0122 quint8 *dataIt = data + 0123 dataX * pixelSize + dataY * dataRowStride; 0124 0125 const qint32 lineSize = columnsToWork * pixelSize; 0126 0127 for (qint32 row = 0; row < rowsToWork; row++) { 0128 memcpy(dataIt, tileIt, lineSize); 0129 tileIt += tileRowStride; 0130 dataIt += dataRowStride; 0131 } 0132 0133 imageX += columnsToWork; 0134 dataX += columnsToWork; 0135 columnsRemaining -= columnsToWork; 0136 } 0137 0138 imageY += rowsToWork; 0139 dataY += rowsToWork; 0140 rowsRemaining -= rowsToWork; 0141 } 0142 } 0143 0144 0145 #define forEachChannel(_idx, _channelSize) \ 0146 for(qint32 _idx=0, _channelSize=channelSizes[_idx]; \ 0147 _idx<numChannels && (_channelSize=channelSizes[_idx], 1); \ 0148 _idx++) 0149 0150 template <bool allChannelsPresent> 0151 void KisTiledDataManager::writePlanarBytesBody(QVector </*const*/ quint8* > planes, 0152 QVector<qint32> channelSizes, 0153 qint32 x, qint32 y, 0154 qint32 width, qint32 height) 0155 { 0156 Q_ASSERT(planes.size() == channelSizes.size()); 0157 Q_ASSERT(planes.size() > 0); 0158 0159 width = width < 0 ? 0 : width; 0160 height = height < 0 ? 0 : height; 0161 0162 const qint32 numChannels = planes.size(); 0163 const qint32 pixelSize = this->pixelSize(); 0164 0165 qint32 dataY = 0; 0166 qint32 imageY = y; 0167 qint32 rowsRemaining = height; 0168 0169 while (rowsRemaining > 0) { 0170 0171 qint32 dataX = 0; 0172 qint32 imageX = x; 0173 qint32 columnsRemaining = width; 0174 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX, 0175 imageX + width - 1); 0176 0177 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining); 0178 0179 while (columnsRemaining > 0) { 0180 0181 qint32 numContiguousImageColumns = 0182 numContiguousColumns(imageX, imageY, 0183 imageY + rowsToWork - 1); 0184 qint32 columnsToWork = qMin(numContiguousImageColumns, 0185 columnsRemaining); 0186 0187 const qint32 dataIdx = dataX + dataY * width; 0188 const qint32 tileRowStride = rowStride(imageX, imageY) - 0189 columnsToWork * pixelSize; 0190 0191 KisTileDataWrapper tw(this, imageX, imageY, 0192 KisTileDataWrapper::WRITE); 0193 quint8 *tileItStart = tw.data(); 0194 0195 0196 forEachChannel(i, channelSize) { 0197 if (allChannelsPresent || planes[i]) { 0198 const quint8* planeIt = planes[i] + dataIdx * channelSize; 0199 qint32 dataStride = (width - columnsToWork) * channelSize; 0200 quint8* tileIt = tileItStart; 0201 0202 for (qint32 row = 0; row < rowsToWork; row++) { 0203 for (int col = 0; col < columnsToWork; col++) { 0204 memcpy(tileIt, planeIt, channelSize); 0205 tileIt += pixelSize; 0206 planeIt += channelSize; 0207 } 0208 0209 tileIt += tileRowStride; 0210 planeIt += dataStride; 0211 } 0212 } 0213 0214 tileItStart += channelSize; 0215 } 0216 0217 imageX += columnsToWork; 0218 dataX += columnsToWork; 0219 columnsRemaining -= columnsToWork; 0220 } 0221 0222 0223 imageY += rowsToWork; 0224 dataY += rowsToWork; 0225 rowsRemaining -= rowsToWork; 0226 } 0227 } 0228 0229 QVector<quint8*> KisTiledDataManager::readPlanarBytesBody(QVector<qint32> channelSizes, 0230 qint32 x, qint32 y, 0231 qint32 width, qint32 height) const 0232 { 0233 Q_ASSERT(channelSizes.size() > 0); 0234 0235 width = width < 0 ? 0 : width; 0236 height = height < 0 ? 0 : height; 0237 0238 const qint32 numChannels = channelSizes.size(); 0239 const qint32 pixelSize = this->pixelSize(); 0240 0241 QVector<quint8*> planes; 0242 forEachChannel(i, channelSize) { 0243 planes.append(new quint8[width * height * channelSize]); 0244 } 0245 0246 qint32 dataY = 0; 0247 qint32 imageY = y; 0248 qint32 rowsRemaining = height; 0249 0250 while (rowsRemaining > 0) { 0251 0252 qint32 dataX = 0; 0253 qint32 imageX = x; 0254 qint32 columnsRemaining = width; 0255 qint32 numContiguousImageRows = numContiguousRows(imageY, imageX, 0256 imageX + width - 1); 0257 0258 qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining); 0259 0260 while (columnsRemaining > 0) { 0261 0262 qint32 numContiguousImageColumns = 0263 numContiguousColumns(imageX, imageY, 0264 imageY + rowsToWork - 1); 0265 qint32 columnsToWork = qMin(numContiguousImageColumns, 0266 columnsRemaining); 0267 0268 const qint32 dataIdx = dataX + dataY * width; 0269 const qint32 tileRowStride = rowStride(imageX, imageY) - 0270 columnsToWork * pixelSize; 0271 0272 // XXX: Ugly const cast because of the old pixelPtr design copied from tiles1. 0273 KisTileDataWrapper tw(const_cast<KisTiledDataManager*>(this), imageX, imageY, 0274 KisTileDataWrapper::READ); 0275 quint8 *tileItStart = tw.data(); 0276 0277 0278 forEachChannel(i, channelSize) { 0279 quint8* planeIt = planes[i] + dataIdx * channelSize; 0280 qint32 dataStride = (width - columnsToWork) * channelSize; 0281 quint8* tileIt = tileItStart; 0282 0283 for (qint32 row = 0; row < rowsToWork; row++) { 0284 for (int col = 0; col < columnsToWork; col++) { 0285 memcpy(planeIt, tileIt, channelSize); 0286 tileIt += pixelSize; 0287 planeIt += channelSize; 0288 } 0289 0290 tileIt += tileRowStride; 0291 planeIt += dataStride; 0292 } 0293 tileItStart += channelSize; 0294 } 0295 0296 imageX += columnsToWork; 0297 dataX += columnsToWork; 0298 columnsRemaining -= columnsToWork; 0299 } 0300 0301 0302 imageY += rowsToWork; 0303 dataY += rowsToWork; 0304 rowsRemaining -= rowsToWork; 0305 } 0306 return planes; 0307 } 0308 0309 0310 0311