Krita Source Code Documentation
Loading...
Searching...
No Matches
KisQmicSimpleConvertor Class Reference

#include <kis_qmic_simple_convertor.h>

Static Public Member Functions

static QString blendingModeToString (QString blendMode)
 
static void convertFromGmicFast (const KisQMicImage &gmicImage, KisPaintDeviceSP dst, float gmicUnitValue)
 Fast versions.
 
static void convertFromGmicImage (const KisQMicImage &gmicImage, KisPaintDeviceSP dst, float gmicMaxChannelValue)
 
static void convertFromQImage (const QImage &image, KisQMicImage &gmicImage, float gmicUnitValue=1.0)
 
static void convertToGmicImage (KisPaintDeviceSP dev, KisQMicImage &gmicImage, QRect rc=QRect())
 
static void convertToGmicImageFast (KisPaintDeviceSP dev, KisQMicImage &gmicImage, QRect rc=QRect())
 
static QImage convertToQImage (const KisQMicImage &gmicImage, float gmicMaxChannelValue=255.0)
 
static QString stringToBlendingMode (QString str)
 

Detailed Description

Definition at line 18 of file kis_qmic_simple_convertor.h.

Member Function Documentation

◆ blendingModeToString()

QString KisQmicSimpleConvertor::blendingModeToString ( QString blendMode)
static

Definition at line 1087 of file kis_qmic_simple_convertor.cpp.

1088{
1089 static auto reverseModeMap = reverseMap();
1090 if (reverseModeMap.find(blendMode) != reverseModeMap.end())
1091 return reverseModeMap.at(blendMode);
1092 return "alpha";
1093}
std::map< QString, QString > reverseMap()

References reverseMap().

◆ convertFromGmicFast()

void KisQmicSimpleConvertor::convertFromGmicFast ( const KisQMicImage & gmicImage,
KisPaintDeviceSP dst,
float gmicUnitValue )
static

Fast versions.

Definition at line 368 of file kis_qmic_simple_convertor.cpp.

371{
372 dbgPlugins << "convertFromGmicFast";
373 const KoColorSpace *dstColorSpace = dst->colorSpace();
374 const KoColorTransformationSP gmicToDstPixelFormat(
375 createTransformationFromGmic(dstColorSpace,
376 gmicImage.m_spectrum,
377 gmicUnitValue));
378 if (!gmicToDstPixelFormat) {
379 dbgPlugins << "Fall-back to slow color conversion";
380 convertFromGmicImage(gmicImage, dst, gmicUnitValue);
381 return;
382 }
383
384 dst->clear();
385 dst->moveTo(0, 0);
386
387 const qint32 x = 0;
388 const qint32 y = 0;
389 const auto width = static_cast<size_t>(gmicImage.m_width);
390 const auto height = static_cast<size_t>(gmicImage.m_height);
391
392 const auto *rgbaFloat32bitcolorSpace =
397 // this function always convert to rgba or rgb with various color depth
398 const quint32 dstNumChannels = rgbaFloat32bitcolorSpace->channelCount();
399
400 // number of channels that we will copy
401 const int numChannels = gmicImage.m_spectrum;
402
403 // gmic image has 4, 3, 2, 1 channel
404 std::vector<float *> planes(dstNumChannels);
405 const size_t channelOffset = width * height;
406 for (int channelIndex = 0; channelIndex < gmicImage.m_spectrum;
407 channelIndex++) {
408 planes[channelIndex] = gmicImage.m_data + channelOffset * channelIndex;
409 }
410
411 for (int channelIndex = gmicImage.m_spectrum;
412 channelIndex < (int)dstNumChannels;
413 channelIndex++) {
414 planes[channelIndex] = 0; // turn off
415 }
416
417 size_t dataY = 0;
418 int imageY = y;
419 size_t rowsRemaining = height;
420
421 const auto floatPixelSize = rgbaFloat32bitcolorSpace->pixelSize();
422
424 const auto tileWidth =
425 static_cast<size_t>(it->numContiguousColumns(dst->x()));
426 const auto tileHeight =
427 static_cast<size_t>(it->numContiguousRows(dst->y()));
428 Q_ASSERT(tileWidth == 64);
429 Q_ASSERT(tileHeight == 64);
430 std::vector<quint8> convertedTile(
431 static_cast<size_t>(rgbaFloat32bitcolorSpace->pixelSize()) * tileWidth
432 * tileHeight);
433
434 // grayscale and rgb case does not have alpha, so let's fill 4th channel of
435 // rgba tile with opacity opaque
436 if (gmicImage.m_spectrum == 1 || gmicImage.m_spectrum == 3) {
437 const auto nPixels = tileWidth * tileHeight;
438 auto *srcPixel =
439 reinterpret_cast<KoRgbF32Traits::Pixel *>(convertedTile.data());
440 for (size_t pixelIndex = 0; pixelIndex < nPixels;
441 pixelIndex++, srcPixel++) {
442 srcPixel->alpha = gmicUnitValue;
443 }
444 }
445
446 while (rowsRemaining > 0) {
447 size_t dataX = 0;
448 qint32 imageX = x;
449 size_t columnsRemaining = width;
450 const auto numContiguousImageRows =
451 static_cast<size_t>(it->numContiguousRows(imageY));
452
453 size_t rowsToWork = qMin(numContiguousImageRows, rowsRemaining);
454
455 while (columnsRemaining > 0) {
456 const auto numContiguousImageColumns =
457 static_cast<size_t>(it->numContiguousColumns(imageX));
458 auto columnsToWork =
459 qMin(numContiguousImageColumns, columnsRemaining);
460
461 const auto dataIdx = dataX + dataY * width;
462 const auto tileRowStride =
463 (tileWidth - columnsToWork) * floatPixelSize;
464
465 auto *tileItStart = convertedTile.data();
466 // copy gmic channels to float tile
467 const auto channelSize = sizeof(float);
468 for (int i = 0; i < numChannels; i++) {
469 float *planeIt = planes[i] + dataIdx;
470 const auto dataStride = width - columnsToWork;
471 quint8 *tileIt = tileItStart;
472
473 for (size_t row = 0; row < rowsToWork; row++) {
474 for (size_t col = 0; col < columnsToWork; col++) {
475 memcpy(tileIt, planeIt, channelSize);
476 tileIt += floatPixelSize;
477 planeIt += 1;
478 }
479
480 tileIt += tileRowStride;
481 planeIt += dataStride;
482 }
483 tileItStart += channelSize;
484 }
485
486 it->moveTo(imageX, imageY);
487 quint8 *dstTileItStart = it->rawData();
488 tileItStart =
489 convertedTile.data(); // back to the start of the converted tile
490 // copy float tile to dst colorspace based on input colorspace (rgb
491 // or grayscale)
492 for (size_t row = 0; row < rowsToWork; row++) {
493 gmicToDstPixelFormat->transform(
494 tileItStart,
495 dstTileItStart,
496 static_cast<int>(columnsToWork));
497 dstTileItStart += dstColorSpace->pixelSize() * tileWidth;
498 tileItStart += floatPixelSize * tileWidth;
499 }
500
501 imageX += static_cast<int>(columnsToWork);
502 dataX += columnsToWork;
503 columnsRemaining -= columnsToWork;
504 }
505
506 imageY += static_cast<int>(rowsToWork);
507 dataY += rowsToWork;
508 rowsRemaining -= rowsToWork;
509 }
510
511 dst->crop(x, y, static_cast<qint32>(width), static_cast<qint32>(height));
512}
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
virtual quint8 * rawData()=0
void crop(qint32 x, qint32 y, qint32 w, qint32 h)
virtual void clear()
const KoColorSpace * colorSpace() const
void moveTo(qint32 x, qint32 y)
KisRandomAccessorSP createRandomAccessorNG()
static void convertFromGmicImage(const KisQMicImage &gmicImage, KisPaintDeviceSP dst, float gmicMaxChannelValue)
virtual qint32 numContiguousRows(qint32 y) const =0
virtual void moveTo(qint32 x, qint32 y)=0
virtual qint32 numContiguousColumns(qint32 x) const =0
virtual quint32 pixelSize() const =0
virtual quint32 channelCount() const =0
virtual const KoColorProfile * profile() const =0
QString id() const
Definition KoID.cpp:63
#define dbgPlugins
Definition kis_debug.h:51
std::shared_ptr< KoColorTransformation > KoColorTransformationSP
static KoColorTransformation * createTransformationFromGmic(const KoColorSpace *colorSpace, int gmicSpectrum, float gmicUnitValue)
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())

References KoColorSpace::channelCount(), KisPaintDevice::clear(), KisPaintDevice::colorSpace(), KoColorSpaceRegistry::colorSpace(), convertFromGmicImage(), KisPaintDevice::createRandomAccessorNG(), createTransformationFromGmic(), KisPaintDevice::crop(), dbgPlugins, Float32BitsColorDepthID, KoID::id(), KoColorSpaceRegistry::instance(), KisQMicImage::m_data, KisQMicImage::m_height, KisQMicImage::m_spectrum, KisQMicImage::m_width, KisPaintDevice::moveTo(), KisRandomConstAccessorNG::moveTo(), KisRandomConstAccessorNG::numContiguousColumns(), KisRandomConstAccessorNG::numContiguousRows(), KoColorSpace::pixelSize(), KoColorSpace::profile(), KisBaseAccessor::rawData(), KoColorSpaceRegistry::rgb8(), RGBAColorModelID, KisPaintDevice::x(), and KisPaintDevice::y().

◆ convertFromGmicImage()

void KisQmicSimpleConvertor::convertFromGmicImage ( const KisQMicImage & gmicImage,
KisPaintDeviceSP dst,
float gmicMaxChannelValue )
static

Definition at line 751 of file kis_qmic_simple_convertor.cpp.

754{
755 dbgPlugins << "convertFromGmicSlow";
756 Q_ASSERT(!dst.isNull());
757 const KoColorSpace *rgbaFloat32bitcolorSpace =
762 const KoColorSpace *dstColorSpace = dst->colorSpace();
763
764 KisPaintDeviceSP dev = dst;
765 const size_t greenOffset =
766 static_cast<size_t>(gmicImage.m_width) * gmicImage.m_height;
767 const size_t blueOffset = greenOffset * 2;
768 const size_t alphaOffset = greenOffset * 3;
769 QRect rc(0,
770 0,
771 static_cast<int>(gmicImage.m_width),
772 static_cast<int>(gmicImage.m_height));
773
774 KisRandomAccessorSP it = dev->createRandomAccessorNG();
775 float r = 0;
776 float g = 0;
777 float b = 0;
778 float a = 1.0;
779
780 const size_t optimalBufferSize =
781 64; // most common numContiguousColumns, tile size?
782 std::vector<quint8> floatRGBApixelStorage(
783 rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize);
784 quint8 *floatRGBApixel = floatRGBApixelStorage.data();
785 const auto pixelSize = rgbaFloat32bitcolorSpace->pixelSize();
786
787 const auto renderingIntent =
789 const auto conversionFlags =
791
792 // Krita needs rgba in 0.0...1.0
793 const float multiplied =
794 KoColorSpaceMathsTraits<float>::unitValue / gmicMaxChannelValue;
795
796 switch (gmicImage.m_spectrum) {
797 case 1: {
798 // convert grayscale to rgba
799 for (int y = 0; y < rc.height(); y++) {
800 int x = 0;
801 while (x < rc.width()) {
802 it->moveTo(x, y);
803 auto numContiguousColumns =
804 qMin(static_cast<size_t>(it->numContiguousColumns(x)),
805 optimalBufferSize);
806 numContiguousColumns =
807 qMin(numContiguousColumns,
808 static_cast<size_t>(rc.width() - x));
809
810 size_t pos = static_cast<size_t>(y) * gmicImage.m_width
811 + static_cast<size_t>(x);
812 for (size_t bx = 0; bx < numContiguousColumns; bx++) {
813 r = g = b = gmicImage.m_data[pos] * multiplied;
815
816 memcpy(floatRGBApixel + bx * pixelSize, &r, 4);
817 memcpy(floatRGBApixel + bx * pixelSize + 4, &g, 4);
818 memcpy(floatRGBApixel + bx * pixelSize + 8, &b, 4);
819 memcpy(floatRGBApixel + bx * pixelSize + 12, &a, 4);
820 pos++;
821 }
822 rgbaFloat32bitcolorSpace->convertPixelsTo(
823 floatRGBApixel,
824 it->rawData(),
825 dstColorSpace,
826 static_cast<quint32>(numContiguousColumns),
827 renderingIntent,
828 conversionFlags);
829 x += static_cast<int>(numContiguousColumns);
830 }
831 }
832 break;
833 }
834 case 2: {
835 // convert grayscale alpha to rgba
836 for (int y = 0; y < rc.height(); y++) {
837 int x = 0;
838 while (x < rc.width()) {
839 it->moveTo(x, y);
840 auto numContiguousColumns =
841 qMin(static_cast<size_t>(it->numContiguousColumns(x)),
842 optimalBufferSize);
843 numContiguousColumns =
844 qMin(numContiguousColumns,
845 static_cast<size_t>(rc.width() - x));
846
847 size_t pos = static_cast<size_t>(y) * gmicImage.m_width
848 + static_cast<size_t>(x);
849 for (size_t bx = 0; bx < numContiguousColumns; bx++) {
850 r = g = b = gmicImage.m_data[pos] * multiplied;
851 a = gmicImage.m_data[pos + greenOffset] * multiplied;
852
853 memcpy(floatRGBApixel + bx * pixelSize, &r, 4);
854 memcpy(floatRGBApixel + bx * pixelSize + 4, &g, 4);
855 memcpy(floatRGBApixel + bx * pixelSize + 8, &b, 4);
856 memcpy(floatRGBApixel + bx * pixelSize + 12, &a, 4);
857 pos++;
858 }
859 rgbaFloat32bitcolorSpace->convertPixelsTo(
860 floatRGBApixel,
861 it->rawData(),
862 dstColorSpace,
863 static_cast<quint32>(numContiguousColumns),
864 renderingIntent,
865 conversionFlags);
866 x += static_cast<int>(numContiguousColumns);
867 }
868 }
869 break;
870 }
871 case 3: {
872 // convert rgb -> rgba
873 for (int y = 0; y < rc.height(); y++) {
874 int x = 0;
875 while (x < rc.width()) {
876 it->moveTo(x, y);
877 auto numContiguousColumns =
878 qMin(static_cast<size_t>(it->numContiguousColumns(x)),
879 optimalBufferSize);
880 numContiguousColumns =
881 qMin(numContiguousColumns,
882 static_cast<size_t>(rc.width() - x));
883
884 size_t pos = static_cast<size_t>(y) * gmicImage.m_width
885 + static_cast<size_t>(x);
886 for (size_t bx = 0; bx < numContiguousColumns; bx++) {
887 r = gmicImage.m_data[pos] * multiplied;
888 g = gmicImage.m_data[pos + greenOffset] * multiplied;
889 b = gmicImage.m_data[pos + blueOffset] * multiplied;
890 a = gmicMaxChannelValue * multiplied;
891
892 memcpy(floatRGBApixel + bx * pixelSize, &r, 4);
893 memcpy(floatRGBApixel + bx * pixelSize + 4, &g, 4);
894 memcpy(floatRGBApixel + bx * pixelSize + 8, &b, 4);
895 memcpy(floatRGBApixel + bx * pixelSize + 12, &a, 4);
896 pos++;
897 }
898 rgbaFloat32bitcolorSpace->convertPixelsTo(
899 floatRGBApixel,
900 it->rawData(),
901 dstColorSpace,
902 static_cast<quint32>(numContiguousColumns),
903 renderingIntent,
904 conversionFlags);
905 x += static_cast<int>(numContiguousColumns);
906 }
907 }
908 break;
909 }
910 case 4: {
911 for (int y = 0; y < rc.height(); y++) {
912 int x = 0;
913 while (x < rc.width()) {
914 it->moveTo(x, y);
915 auto numContiguousColumns =
916 qMin(static_cast<size_t>(it->numContiguousColumns(x)),
917 optimalBufferSize);
918 numContiguousColumns =
919 qMin(numContiguousColumns,
920 static_cast<size_t>(rc.width() - x));
921
922 size_t pos = static_cast<size_t>(y) * gmicImage.m_width
923 + static_cast<size_t>(x);
924 for (size_t bx = 0; bx < numContiguousColumns; bx++) {
925 r = gmicImage.m_data[pos] * multiplied;
926 g = gmicImage.m_data[pos + greenOffset] * multiplied;
927 b = gmicImage.m_data[pos + blueOffset] * multiplied;
928 a = gmicImage.m_data[pos + alphaOffset] * multiplied;
929
930 memcpy(floatRGBApixel + bx * pixelSize, &r, 4);
931 memcpy(floatRGBApixel + bx * pixelSize + 4, &g, 4);
932 memcpy(floatRGBApixel + bx * pixelSize + 8, &b, 4);
933 memcpy(floatRGBApixel + bx * pixelSize + 12, &a, 4);
934 pos++;
935 }
936 rgbaFloat32bitcolorSpace->convertPixelsTo(
937 floatRGBApixel,
938 it->rawData(),
939 dstColorSpace,
940 static_cast<quint32>(numContiguousColumns),
941 renderingIntent,
942 conversionFlags);
943 x += static_cast<int>(numContiguousColumns);
944 }
945 }
946 break;
947 }
948
949 default: {
950 dbgPlugins << "Unsupported gmic output format : " << gmicImage.m_width
951 << gmicImage.m_height << gmicImage.m_spectrum;
952 }
953 }
954}
bool isNull() const
virtual bool convertPixelsTo(const quint8 *src, quint8 *dst, const KoColorSpace *dstColorSpace, quint32 numPixels, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const

References KisPaintDevice::colorSpace(), KoColorSpaceRegistry::colorSpace(), KoColorSpace::convertPixelsTo(), KisPaintDevice::createRandomAccessorNG(), dbgPlugins, Float32BitsColorDepthID, KoID::id(), KoColorSpaceRegistry::instance(), KoColorConversionTransformation::internalConversionFlags(), KoColorConversionTransformation::internalRenderingIntent(), KisSharedPtr< T >::isNull(), KisQMicImage::m_data, KisQMicImage::m_height, KisQMicImage::m_spectrum, KisQMicImage::m_width, KisRandomConstAccessorNG::moveTo(), KisRandomConstAccessorNG::numContiguousColumns(), KoColorSpace::pixelSize(), KoColorSpace::profile(), KisBaseAccessor::rawData(), KoColorSpaceRegistry::rgb8(), and RGBAColorModelID.

◆ convertFromQImage()

void KisQmicSimpleConvertor::convertFromQImage ( const QImage & image,
KisQMicImage & gmicImage,
float gmicUnitValue = 1.0 )
static

Definition at line 988 of file kis_qmic_simple_convertor.cpp.

991{
992 const auto greenOffset =
993 static_cast<size_t>(gmicImage.m_width) * gmicImage.m_height;
994 const size_t blueOffset = greenOffset * 2;
995 const size_t alphaOffset = greenOffset * 3;
996
997 // QImage has 0..255
998 const float qimageUnitValue = 255.0f;
999 const float multiplied = gmicUnitValue / qimageUnitValue;
1000
1001 Q_ASSERT(image.width() == int(gmicImage.m_width));
1002 Q_ASSERT(image.height() == int(gmicImage.m_height));
1003 Q_ASSERT(image.format() == QImage::Format_ARGB32);
1004
1005 switch (gmicImage.m_spectrum) {
1006 case 1: {
1007 for (int y = 0; y < image.height(); y++) {
1008 const QRgb *pixel =
1009 reinterpret_cast<const QRgb *>(image.scanLine(y));
1010 for (int x = 0; x < image.width(); x++) {
1011 const auto pos = static_cast<size_t>(y) * gmicImage.m_width
1012 + static_cast<size_t>(x);
1013 gmicImage.m_data[pos] =
1014 static_cast<float>(qGray(pixel[x])) * multiplied;
1015 }
1016 }
1017 break;
1018 }
1019 case 2: {
1020 for (int y = 0; y < image.height(); y++) {
1021 const QRgb *pixel =
1022 reinterpret_cast<const QRgb *>(image.scanLine(y));
1023 for (int x = 0; x < image.width(); x++) {
1024 const auto pos = static_cast<size_t>(y) * gmicImage.m_width
1025 + static_cast<size_t>(x);
1026 gmicImage.m_data[pos] =
1027 static_cast<float>(qGray(pixel[x])) * multiplied;
1028 gmicImage.m_data[pos + greenOffset] =
1029 static_cast<float>(qAlpha(pixel[x])) * multiplied;
1030 }
1031 }
1032 break;
1033 }
1034 case 3: {
1035 for (int y = 0; y < image.height(); y++) {
1036 const QRgb *pixel =
1037 reinterpret_cast<const QRgb *>(image.scanLine(y));
1038 for (int x = 0; x < image.width(); x++) {
1039 const auto pos = static_cast<size_t>(y) * gmicImage.m_width
1040 + static_cast<size_t>(x);
1041 gmicImage.m_data[pos] =
1042 static_cast<float>(qRed(pixel[x])) * multiplied;
1043 gmicImage.m_data[pos + greenOffset] =
1044 static_cast<float>(qGreen(pixel[x])) * multiplied;
1045 gmicImage.m_data[pos + blueOffset] =
1046 static_cast<float>(qBlue(pixel[x])) * multiplied;
1047 }
1048 }
1049 break;
1050 }
1051 case 4: {
1052 for (int y = 0; y < image.height(); y++) {
1053 const QRgb *pixel =
1054 reinterpret_cast<const QRgb *>(image.scanLine(y));
1055 for (int x = 0; x < image.width(); x++) {
1056 const auto pos = static_cast<size_t>(y) * gmicImage.m_width
1057 + static_cast<size_t>(x);
1058 gmicImage.m_data[pos] =
1059 static_cast<float>(qRed(pixel[x])) * multiplied;
1060 gmicImage.m_data[pos + greenOffset] =
1061 static_cast<float>(qGreen(pixel[x])) * multiplied;
1062 gmicImage.m_data[pos + blueOffset] =
1063 static_cast<float>(qBlue(pixel[x])) * multiplied;
1064 gmicImage.m_data[pos + alphaOffset] =
1065 static_cast<float>(qAlpha(pixel[x])) * multiplied;
1066 }
1067 }
1068 break;
1069 }
1070 default: {
1071 Q_ASSERT(false);
1072 dbgKrita << "Unexpected gmic image format";
1073 break;
1074 }
1075 }
1076}
unsigned int QRgb
#define dbgKrita
Definition kis_debug.h:45

References dbgKrita, KisQMicImage::m_data, KisQMicImage::m_height, KisQMicImage::m_spectrum, and KisQMicImage::m_width.

◆ convertToGmicImage()

void KisQmicSimpleConvertor::convertToGmicImage ( KisPaintDeviceSP dev,
KisQMicImage & gmicImage,
QRect rc = QRect() )
static

Definition at line 662 of file kis_qmic_simple_convertor.cpp.

665{
666 Q_ASSERT(!dev.isNull());
667 Q_ASSERT(gmicImage.m_spectrum == 4); // rgba
668
669 if (rc.isEmpty()) {
670 rc = QRect(0,
671 0,
672 static_cast<int>(gmicImage.m_width),
673 static_cast<int>(gmicImage.m_height));
674 }
675
676 const KoColorSpace *rgbaFloat32bitcolorSpace =
681 Q_CHECK_PTR(rgbaFloat32bitcolorSpace);
682
683 const KoColorTransformationSP pixelToGmicPixelFormat(
684 createTransformation(rgbaFloat32bitcolorSpace));
685
686 const size_t greenOffset =
687 static_cast<size_t>(gmicImage.m_width) * gmicImage.m_height;
688 const size_t blueOffset = greenOffset * 2;
689 const size_t alphaOffset = greenOffset * 3;
690
691 const auto renderingIntent =
693 const auto conversionFlags =
695
696 const KoColorSpace *colorSpace = dev->colorSpace();
698
699 const size_t optimalBufferSize =
700 64; // most common numContiguousColumns, tile size?
701 std::vector<quint8> floatRGBApixelStorage(
702 rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize);
703 quint8 *floatRGBApixel = floatRGBApixelStorage.data();
704
705 const auto pixelSize = rgbaFloat32bitcolorSpace->pixelSize();
706 for (int y = 0; y < rc.height(); y++) {
707 int x = 0;
708 while (x < rc.width()) {
709 it->moveTo(rc.x() + x, rc.y() + y);
710 auto numContiguousColumns =
711 qMin(static_cast<size_t>(it->numContiguousColumns(rc.x() + x)),
712 optimalBufferSize);
713 numContiguousColumns =
714 qMin(numContiguousColumns, static_cast<size_t>(rc.width() - x));
715
716 colorSpace->convertPixelsTo(
717 it->rawDataConst(),
718 floatRGBApixel,
719 rgbaFloat32bitcolorSpace,
720 static_cast<quint32>(numContiguousColumns),
721 renderingIntent,
722 conversionFlags);
723 pixelToGmicPixelFormat->transform(
724 floatRGBApixel,
725 floatRGBApixel,
726 static_cast<qint32>(numContiguousColumns));
727
728 auto pos = static_cast<size_t>(y) * gmicImage.m_width
729 + static_cast<size_t>(x);
730 for (size_t bx = 0; bx < numContiguousColumns; bx++) {
731 memcpy(gmicImage.m_data + pos,
732 floatRGBApixel + bx * pixelSize,
733 4);
734 memcpy(gmicImage.m_data + pos + greenOffset,
735 floatRGBApixel + bx * pixelSize + 4,
736 4);
737 memcpy(gmicImage.m_data + pos + blueOffset,
738 floatRGBApixel + bx * pixelSize + 8,
739 4);
740 memcpy(gmicImage.m_data + pos + alphaOffset,
741 floatRGBApixel + bx * pixelSize + 12,
742 4);
743 pos++;
744 }
745
746 x += static_cast<int>(numContiguousColumns);
747 }
748 }
749}
virtual const quint8 * rawDataConst() const =0
KisRandomConstAccessorSP createRandomConstAccessorNG() const
static KoColorTransformation * createTransformation(const KoColorSpace *colorSpace)

References KisPaintDevice::colorSpace(), KoColorSpaceRegistry::colorSpace(), KoColorSpace::convertPixelsTo(), KisPaintDevice::createRandomConstAccessorNG(), createTransformation(), Float32BitsColorDepthID, KoID::id(), KoColorSpaceRegistry::instance(), KoColorConversionTransformation::internalConversionFlags(), KoColorConversionTransformation::internalRenderingIntent(), KisSharedPtr< T >::isNull(), KisQMicImage::m_data, KisQMicImage::m_height, KisQMicImage::m_spectrum, KisQMicImage::m_width, KisRandomConstAccessorNG::moveTo(), KisRandomConstAccessorNG::numContiguousColumns(), KoColorSpace::pixelSize(), KoColorSpace::profile(), KisBaseConstAccessor::rawDataConst(), KoColorSpaceRegistry::rgb8(), and RGBAColorModelID.

◆ convertToGmicImageFast()

void KisQmicSimpleConvertor::convertToGmicImageFast ( KisPaintDeviceSP dev,
KisQMicImage & gmicImage,
QRect rc = QRect() )
static

Definition at line 514 of file kis_qmic_simple_convertor.cpp.

517{
518 KoColorTransformationSP pixelToGmicPixelFormat(
520 if (!pixelToGmicPixelFormat) {
521 dbgPlugins << "Fall-back to slow color conversion method";
522 convertToGmicImage(dev, gmicImage, rc);
523 return;
524 }
525
526 if (rc.isEmpty()) {
528 << "Image rectangle is empty! Using supplied gmic layer dimension";
529 rc = QRect(0,
530 0,
531 static_cast<int>(gmicImage.m_width),
532 static_cast<int>(gmicImage.m_height));
533 }
534
535 const auto x = rc.x();
536 const auto y = rc.y();
537 const size_t width = rc.width() < 0 ? 0 : static_cast<size_t>(rc.width());
538 const size_t height =
539 rc.height() < 0 ? 0 : static_cast<size_t>(rc.height());
540
541 const qint32 numChannels = 4;
542
543 const size_t greenOffset =
544 static_cast<size_t>(gmicImage.m_width) * gmicImage.m_height;
545 const size_t blueOffset = greenOffset * 2;
546 const size_t alphaOffset = greenOffset * 3;
547
548 const std::array<float *, 4> planes = {gmicImage.m_data,
549 gmicImage.m_data + greenOffset,
550 gmicImage.m_data + blueOffset,
551 gmicImage.m_data + alphaOffset};
552
554 const auto tileWidth = it->numContiguousColumns(dev->x());
555 const auto tileHeight = it->numContiguousRows(dev->y());
556
557 Q_ASSERT(tileWidth == 64);
558 Q_ASSERT(tileHeight == 64);
559
560 const KoColorSpace *rgbaFloat32bitcolorSpace =
565 Q_CHECK_PTR(rgbaFloat32bitcolorSpace);
566 const auto dstPixelSize = rgbaFloat32bitcolorSpace->pixelSize();
567 const auto srcPixelSize = dev->pixelSize();
568
569 std::vector<quint8> dstTile(dstPixelSize * static_cast<size_t>(tileWidth)
570 * static_cast<size_t>(tileHeight));
571
572 size_t dataY = 0;
573 int imageY = y;
574 int imageX = x;
575 it->moveTo(imageX, imageY);
576 size_t rowsRemaining = height;
577
578 while (rowsRemaining > 0) {
579 size_t dataX = 0;
580 imageX = x;
581 size_t columnsRemaining = width;
582 const auto numContiguousImageRows = it->numContiguousRows(imageY);
583
584 const auto rowsToWork =
585 qMin(numContiguousImageRows, static_cast<qint32>(rowsRemaining));
586 const auto convertedTileY = tileHeight - rowsToWork;
587 Q_ASSERT(convertedTileY >= 0);
588
589 while (columnsRemaining > 0) {
590 const auto numContiguousImageColumns =
591 static_cast<size_t>(it->numContiguousColumns(imageX));
592 const auto columnsToWork =
593 qMin(numContiguousImageColumns, columnsRemaining);
594 const auto convertedTileX =
595 tileWidth - static_cast<qint32>(columnsToWork);
596 Q_ASSERT(convertedTileX >= 0);
597
598 const auto dataIdx = dataX + dataY * width;
599 const auto dstTileIndex =
600 convertedTileX + convertedTileY * tileWidth;
601 const auto tileRowStride =
602 (static_cast<size_t>(tileWidth) - columnsToWork) * dstPixelSize;
603 const auto srcTileRowStride =
604 (static_cast<size_t>(tileWidth) - columnsToWork) * srcPixelSize;
605
606 it->moveTo(imageX, imageY);
607 quint8 *tileItStart = dstTile.data() + dstTileIndex * dstPixelSize;
608
609 // transform tile row by row
610 auto *dstTileIt = tileItStart;
611 const auto *srcTileIt = it->rawDataConst();
612
613 auto row = rowsToWork;
614 while (row > 0) {
615 pixelToGmicPixelFormat->transform(
616 srcTileIt,
617 dstTileIt,
618 static_cast<qint32>(columnsToWork));
619 srcTileIt += columnsToWork * srcPixelSize;
620 srcTileIt += srcTileRowStride;
621
622 dstTileIt += columnsToWork * dstPixelSize;
623 dstTileIt += tileRowStride;
624
625 row--;
626 }
627
628 // here we want to copy floats to dstTile, so tileItStart has to
629 // point to float buffer
630 const auto channelSize = sizeof(float);
631 for (size_t i = 0; i < numChannels; i++) {
632 float *planeIt = planes.at(i) + dataIdx;
633 const auto dataStride = (width - columnsToWork);
634 quint8 *tileIt = tileItStart;
635
636 for (int row = 0; row < rowsToWork; row++) {
637 for (size_t col = 0; col < columnsToWork; col++) {
638 memcpy(planeIt, tileIt, channelSize);
639 tileIt += dstPixelSize;
640 planeIt += 1;
641 }
642
643 tileIt += tileRowStride;
644 planeIt += dataStride;
645 }
646 // skip channel in tile: red, green, blue, alpha
647 tileItStart += channelSize;
648 }
649
650 imageX += static_cast<int>(columnsToWork);
651 dataX += columnsToWork;
652 columnsRemaining -= columnsToWork;
653 }
654
655 imageY += static_cast<int>(rowsToWork);
656 dataY += rowsToWork;
657 rowsRemaining -= rowsToWork;
658 }
659}
quint32 pixelSize() const
static void convertToGmicImage(KisPaintDeviceSP dev, KisQMicImage &gmicImage, QRect rc=QRect())

References KisPaintDevice::colorSpace(), KoColorSpaceRegistry::colorSpace(), convertToGmicImage(), KisPaintDevice::createRandomConstAccessorNG(), createTransformation(), dbgPlugins, Float32BitsColorDepthID, KoID::id(), KoColorSpaceRegistry::instance(), KisQMicImage::m_data, KisQMicImage::m_height, KisQMicImage::m_width, KisRandomConstAccessorNG::moveTo(), KisRandomConstAccessorNG::numContiguousColumns(), KisRandomConstAccessorNG::numContiguousRows(), KisPaintDevice::pixelSize(), KoColorSpace::pixelSize(), KoColorSpace::profile(), KisBaseConstAccessor::rawDataConst(), KoColorSpaceRegistry::rgb8(), RGBAColorModelID, KisPaintDevice::x(), and KisPaintDevice::y().

◆ convertToQImage()

QImage KisQmicSimpleConvertor::convertToQImage ( const KisQMicImage & gmicImage,
float gmicMaxChannelValue = 255.0 )
static

Definition at line 956 of file kis_qmic_simple_convertor.cpp.

958{
959 QImage image = QImage(static_cast<int>(gmicImage.m_width),
960 static_cast<int>(gmicImage.m_height),
961 QImage::Format_ARGB32);
962
963 dbgPlugins << image.format() << "first pixel:" << gmicImage.m_data[0]
964 << gmicImage.m_width << gmicImage.m_height
965 << gmicImage.m_spectrum;
966
967 const size_t greenOffset =
968 static_cast<size_t>(gmicImage.m_width) * gmicImage.m_height;
969 const size_t blueOffset = greenOffset * 2;
970
971 // always put 255 to qimage
972 const float multiplied = 255.0f / gmicActualMaxChannelValue;
973
974 for (int y = 0; y < gmicImage.m_height; y++) {
975 QRgb *pixel =
976 reinterpret_cast<QRgb *>(image.scanLine(static_cast<int>(y)));
977 for (int x = 0; x < gmicImage.m_width; x++) {
978 const auto pos = y * gmicImage.m_width + x;
979 const float r = gmicImage.m_data[pos] * multiplied;
980 const float g = gmicImage.m_data[pos + greenOffset] * multiplied;
981 const float b = gmicImage.m_data[pos + blueOffset] * multiplied;
982 pixel[x] = qRgb(int(r), int(g), int(b));
983 }
984 }
985 return image;
986}

References dbgPlugins, KisQMicImage::m_data, KisQMicImage::m_height, KisQMicImage::m_spectrum, and KisQMicImage::m_width.

◆ stringToBlendingMode()

QString KisQmicSimpleConvertor::stringToBlendingMode ( QString str)
static

Definition at line 1095 of file kis_qmic_simple_convertor.cpp.

1096{
1097 if (blendingModeMap.find(blendMode) != blendingModeMap.end())
1098 return blendingModeMap.at(blendMode);
1099 return COMPOSITE_OVER;
1100}
const QString COMPOSITE_OVER
const std::map< QString, QString > blendingModeMap

References blendingModeMap, and COMPOSITE_OVER.


The documentation for this class was generated from the following files: