Exemplo 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;

}
Exemplo n.º 2
0
void KisGmicSimpleConvertor::convertFromGmicImage(gmic_image<float>& gmicImage, KisPaintDeviceSP dst, float gmicMaxChannelValue)
{
    Q_ASSERT(!dst.isNull());
    const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(),
                                                                                                Float32BitsColorDepthID.id(),
                                                                                                KoColorSpaceRegistry::instance()->rgb8()->profile());
    const KoColorSpace *dstColorSpace = dst->colorSpace();
    if (dstColorSpace == 0)
    {
        dstColorSpace = rgbaFloat32bitcolorSpace;
    }

    KisPaintDeviceSP dev = dst;
    int greenOffset = gmicImage._width * gmicImage._height;
    int blueOffset = greenOffset * 2;
    int alphaOffset = greenOffset * 3;
    QRect rc(0,0,gmicImage._width, gmicImage._height);

    KisRandomAccessorSP it = dev->createRandomAccessorNG(0,0);
    int pos;
    float r,g,b,a;

    int optimalBufferSize = 64; // most common numContiguousColumns, tile size?
    quint8 * floatRGBApixel = new quint8[rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize];
    quint32 pixelSize = rgbaFloat32bitcolorSpace->pixelSize();

    KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent();
    KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags();

    // Krita needs rgba in 0.0...1.0
    float multiplied = KoColorSpaceMathsTraits<float>::unitValue / gmicMaxChannelValue;

    switch (gmicImage._spectrum)
    {
        case 1:
        {
            // convert grayscale to rgba
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = g = b = gmicImage._data[pos] * multiplied;
                            a = KoColorSpaceMathsTraits<float>::unitValue;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }
        case 2:
        {
            // convert grayscale alpha to rgba
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = g = b = gmicImage._data[pos] * multiplied;
                            a = gmicImage._data[pos + greenOffset] * multiplied;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }
        case 3:
        {
            // convert rgb -> rgba
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = gmicImage._data[pos] * multiplied;
                            g = gmicImage._data[pos + greenOffset] * multiplied;
                            b = gmicImage._data[pos + blueOffset ] * multiplied;
                            a = gmicMaxChannelValue * multiplied;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }
        case 4:
        {
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = gmicImage._data[pos] * multiplied;
                            g = gmicImage._data[pos + greenOffset] * multiplied;
                            b = gmicImage._data[pos + blueOffset ] * multiplied;
                            a = gmicImage._data[pos + alphaOffset] * multiplied;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }

        default:
        {
            dbgPlugins << "Unsupported gmic output format : " <<  gmicImage._width << gmicImage._height << gmicImage._depth << gmicImage._spectrum;
        }
    }
}
Exemplo n.º 3
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);
}