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 gMicNameToName (QString name)
 
static QString nameToGMicName (QString name)
 
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.

◆ gMicNameToName()

QString KisQmicSimpleConvertor::gMicNameToName ( QString name)
static

Decode the GMic-encoded name back into the one with parenthesis

See also
nameToGMicName()

Definition at line 1108 of file kis_qmic_simple_convertor.cpp.

1109{
1110 name.replace(QChar(21), QChar('(')).replace(QChar(22), QChar(')'));
1111 return name;
1112}
const char * name(StandardAction id)

◆ nameToGMicName()

QString KisQmicSimpleConvertor::nameToGMicName ( QString name)
static

A special function that removes all parenthesis from the layer name, since parenthesis are used in GMic to encode layer properties.

The function basically replaces '(' and ')' symbols with \u0015 and \u0016 correspondingly.

Definition at line 1102 of file kis_qmic_simple_convertor.cpp.

1103{
1104 name.replace(QChar('('), QChar(21)).replace(QChar(')'), QChar(22));
1105 return name;
1106}

◆ 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: