File indexing completed on 2024-05-12 15:58:51

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KISFASTDEVICEPROCESSINGUTILS_H
0008 #define KISFASTDEVICEPROCESSINGUTILS_H
0009 
0010 #include "kis_random_accessor_ng.h"
0011 #include <KoAlwaysInline.h>
0012 
0013 namespace KritaUtils {
0014 
0015 
0016 /**
0017  * this is a special helper function for iterating
0018  * through pixels in an extremely efficient way. One
0019  * should either pass a functor or a lambda to it.
0020  */
0021 template <class PixelProcessor>
0022 void processTwoDevices(const QRect &rc,
0023                        KisRandomConstAccessorSP srcIt,
0024                        KisRandomAccessorSP dstIt,
0025                        const int srcPixelSize,
0026                        const int dstPixelSize,
0027                        PixelProcessor pixelProcessor)
0028 {
0029     qint32 dstY = rc.y();
0030     qint32 rowsRemaining = rc.height();
0031 
0032     while (rowsRemaining > 0) {
0033         qint32 dstX = rc.x();
0034 
0035         qint32 numContiguousSrcRows = srcIt->numContiguousRows(dstY);
0036         qint32 numContiguousDstRows = dstIt->numContiguousRows(dstY);
0037         qint32 rows = std::min({rowsRemaining, numContiguousSrcRows, numContiguousDstRows});
0038 
0039         qint32 columnsRemaining = rc.width();
0040 
0041         while (columnsRemaining > 0) {
0042 
0043             qint32 numContiguousSrcColumns = srcIt->numContiguousColumns(dstX);
0044             qint32 numContiguousDstColumns = dstIt->numContiguousColumns(dstX);
0045             qint32 columns = std::min({columnsRemaining, numContiguousSrcColumns, numContiguousDstColumns});
0046 
0047             qint32 dstRowStride = dstIt->rowStride(dstX, dstY);
0048             qint32 srcRowStride = srcIt->rowStride(dstX, dstY);
0049 
0050             dstIt->moveTo(dstX, dstY);
0051             srcIt->moveTo(dstX, dstY);
0052 
0053             quint8 *dstRowStart = dstIt->rawData();
0054             const quint8 *srcRowStart = srcIt->rawDataConst();
0055 
0056             for (int i = 0; i < rows; i++) {
0057                 const quint8 *srcPtr = reinterpret_cast<const quint8*>(srcRowStart);
0058                 quint8 *dstPtr = reinterpret_cast<quint8*>(dstRowStart);
0059 
0060                 for (int j = 0; j < columns; j++) {
0061                     pixelProcessor(srcPtr, dstPtr);
0062 
0063                     srcPtr += srcPixelSize;
0064                     dstPtr += dstPixelSize;
0065                 }
0066 
0067                 srcRowStart += srcRowStride;
0068                 dstRowStart += dstRowStride;
0069             }
0070 
0071             dstX += columns;
0072             columnsRemaining -= columns;
0073         }
0074 
0075         dstY += rows;
0076         rowsRemaining -= rows;
0077     }
0078 }
0079 
0080 /**
0081  * this is a special helper function for iterating through pixels in an
0082  * extremely efficient way using strides. One should either pass a functor or a
0083  * lambda to it.
0084  */
0085 template <class PixelProcessor>
0086 void processTwoDevicesWithStrides(const QRect &rc,
0087                                   KisRandomConstAccessorSP srcIt,
0088                                   KisRandomAccessorSP dstIt,
0089                                   PixelProcessor pixelProcessor)
0090 {
0091     qint32 dstY = rc.y();
0092     qint32 rowsRemaining = rc.height();
0093 
0094     while (rowsRemaining > 0) {
0095         qint32 dstX = rc.x();
0096 
0097         qint32 numContiguousSrcRows = srcIt->numContiguousRows(dstY);
0098         qint32 numContiguousDstRows = dstIt->numContiguousRows(dstY);
0099         qint32 rows = std::min({rowsRemaining, numContiguousSrcRows, numContiguousDstRows});
0100 
0101         qint32 columnsRemaining = rc.width();
0102 
0103         while (columnsRemaining > 0) {
0104 
0105             qint32 numContiguousSrcColumns = srcIt->numContiguousColumns(dstX);
0106             qint32 numContiguousDstColumns = dstIt->numContiguousColumns(dstX);
0107             qint32 columns = std::min({columnsRemaining, numContiguousSrcColumns, numContiguousDstColumns});
0108 
0109             qint32 dstRowStride = dstIt->rowStride(dstX, dstY);
0110             qint32 srcRowStride = srcIt->rowStride(dstX, dstY);
0111 
0112             dstIt->moveTo(dstX, dstY);
0113             srcIt->moveTo(dstX, dstY);
0114 
0115             quint8 *dstRowStart = dstIt->rawData();
0116             const quint8 *srcRowStart = srcIt->rawDataConst();
0117 
0118             pixelProcessor(srcRowStart, srcRowStride,
0119                            dstRowStart, dstRowStride,
0120                            rows, columns);
0121 
0122             dstX += columns;
0123             columnsRemaining -= columns;
0124         }
0125 
0126         dstY += rows;
0127         rowsRemaining -= rows;
0128     }
0129 }
0130 
0131 }
0132 
0133 
0134 #endif // KISFASTDEVICEPROCESSINGUTILS_H