Ejemplo n.º 1
0
void KisGmicSimpleConvertor::convertFromGmicFast(gmic_image<float>& gmicImage, KisPaintDeviceSP dst, float gmicUnitValue)
{
    const KoColorSpace * dstColorSpace = dst->colorSpace();
    KoColorTransformation * gmicToDstPixelFormat = createTransformationFromGmic(dstColorSpace,gmicImage._spectrum,gmicUnitValue);
    if (gmicToDstPixelFormat == 0)
    {
            dbgPlugins << "Fall-back to slow color conversion";
            convertFromGmicImage(gmicImage, dst, gmicUnitValue);
            return;
    }

    qint32 x = 0;
    qint32 y = 0;
    qint32 width = gmicImage._width;
    qint32 height = gmicImage._height;

    width  = width < 0  ? 0 : width;
    height = height < 0 ? 0 : height;


    const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(),
                                                                                                Float32BitsColorDepthID.id(),
                                                                                                KoColorSpaceRegistry::instance()->rgb8()->profile());
    // this function always convert to rgba or rgb with various color depth
    quint32 dstNumChannels = rgbaFloat32bitcolorSpace->channelCount();
    // number of channels that we will copy
    quint32 numChannels = gmicImage._spectrum;

    // gmic image has 4, 3, 2, 1 channel
    QVector<float *> planes(dstNumChannels);
    int channelOffset = gmicImage._width * gmicImage._height;
    for (unsigned int channelIndex = 0; channelIndex < gmicImage._spectrum; channelIndex++)
    {
        planes[channelIndex] = gmicImage._data + channelOffset * channelIndex;
    }

    for (unsigned int channelIndex = gmicImage._spectrum; channelIndex < dstNumChannels; channelIndex++)
    {
        planes[channelIndex] = 0; //turn off
    }

    qint32 dataY = 0;
    qint32 imageY = y;
    qint32 rowsRemaining = height;

    const qint32 floatPixelSize = rgbaFloat32bitcolorSpace->pixelSize();

    KisRandomAccessorSP it = dst->createRandomAccessorNG(dst->x(), dst->y()); // 0,0
    int tileWidth = it->numContiguousColumns(dst->x());
    int tileHeight = it->numContiguousRows(dst->y());
    Q_ASSERT(tileWidth == 64);
    Q_ASSERT(tileHeight == 64);
    quint8 * convertedTile = new quint8[rgbaFloat32bitcolorSpace->pixelSize() * tileWidth * tileHeight];

    // grayscale and rgb case does not have alpha, so let's fill 4th channel of rgba tile with opacity opaque
    if (gmicImage._spectrum == 1 || gmicImage._spectrum == 3)
    {
        quint32 nPixels = tileWidth * tileHeight;
        quint32 pixelIndex = 0;
        KoRgbF32Traits::Pixel* srcPixel = reinterpret_cast<KoRgbF32Traits::Pixel*>(convertedTile);
        while (pixelIndex < nPixels)
        {
            srcPixel->alpha = gmicUnitValue;
            ++srcPixel;
            ++pixelIndex;
        }
    }

    while (rowsRemaining > 0) {

        qint32 dataX = 0;
        qint32 imageX = x;
        qint32 columnsRemaining = width;
        qint32 numContiguousImageRows = it->numContiguousRows(imageY);

        qint32 rowsToWork = qMin(numContiguousImageRows, rowsRemaining);

        while (columnsRemaining > 0) {

            qint32 numContiguousImageColumns = it->numContiguousColumns(imageX);
            qint32 columnsToWork = qMin(numContiguousImageColumns, columnsRemaining);

            const qint32 dataIdx = dataX + dataY * width;
            const qint32 tileRowStride = (tileWidth - columnsToWork) * floatPixelSize;

            quint8 *tileItStart = convertedTile;
            // copy gmic channels to float tile
            qint32 channelSize = sizeof(float);
            for(quint32 i=0; i<numChannels; i++)
            {
                float * planeIt = planes[i] + dataIdx;
                qint32 dataStride = (width - columnsToWork);
                quint8* tileIt = tileItStart;

                for (qint32 row = 0; row < rowsToWork; row++) {
                    for (int col = 0; col < columnsToWork; col++) {
                        memcpy(tileIt, planeIt, channelSize);
                        tileIt += floatPixelSize;
                        planeIt += 1;
                    }

                    tileIt += tileRowStride;
                    planeIt += dataStride;
                }
                tileItStart += channelSize;
            }

            it->moveTo(imageX, imageY);
            quint8 *dstTileItStart = it->rawData();
            tileItStart = convertedTile;  // back to the start of the converted tile
            // copy float tile to dst colorspace based on input colorspace (rgb or grayscale)
            for (qint32 row = 0; row < rowsToWork; row++)
            {
                gmicToDstPixelFormat->transform(tileItStart, dstTileItStart, columnsToWork);
                dstTileItStart += dstColorSpace->pixelSize() * tileWidth;
                tileItStart += floatPixelSize * tileWidth;
            }

            imageX += columnsToWork;
            dataX += columnsToWork;
            columnsRemaining -= columnsToWork;
        }


        imageY += rowsToWork;
        dataY += rowsToWork;
        rowsRemaining -= rowsToWork;
    }

    delete [] convertedTile;
    delete gmicToDstPixelFormat;

}
Ejemplo n.º 2
0
void KisPaintDeviceTest::testWrappedRandomAccessor()
{
    const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP dev = createWrapAroundPaintDevice(cs);

    KoColor c1(Qt::red, cs);
    KoColor c2(Qt::green, cs);

    dev->setPixel(3, 3, c1);
    dev->setPixel(18, 18, c2);

    const int pixelSize = dev->pixelSize();

    int x;
    int y;

    x = 3;
    y = 3;
    KisRandomAccessorSP dstIt = dev->createRandomAccessorNG(x, y);

    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);

    x = 23;
    y = 23;
    dstIt->moveTo(x, y);
    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);

    x = 3;
    y = 23;
    dstIt->moveTo(x, y);
    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);

    x = 23;
    y = 3;
    dstIt->moveTo(x, y);
    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);

    x = -17;
    y = 3;
    dstIt->moveTo(x, y);
    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);

    x = 3;
    y = -17;
    dstIt->moveTo(x, y);
    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);

    x = -17;
    y = -17;
    dstIt->moveTo(x, y);
    QVERIFY(!memcmp(dstIt->rawData(), c1.data(), pixelSize));
    QCOMPARE(dstIt->numContiguousColumns(x), 17);
    QCOMPARE(dstIt->numContiguousRows(y), 17);
}