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