From 5a067130aff47b2966fcb97d3148c3c0c0809d2d Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Sat, 30 Aug 2025 09:17:40 +0200 Subject: [PATCH] Removed the conversion of the entire image to a compatible format when saving from the PCX, PIC, and RGB plugins. For example, the PCX plugin converts all RGB images to RGB(A)32. So if you try to save a 1 GiB RGB888 image, it will be converted to RGB32 image so, you need additional 1.25GiB of ram. The conversion now occurs line by line, significantly saving memory. --- .../write/format/pic/Format_RGBA16FPx4.pic | Bin 10116 -> 9977 bytes .../write/format/rgb/Format_RGBA16FPx4.rgb | Bin 15742 -> 15516 bytes src/imageformats/CMakeLists.txt | 6 +- src/imageformats/pcx.cpp | 110 ++++++++++-------- src/imageformats/pic.cpp | 23 ++-- src/imageformats/rgb.cpp | 76 ++++++------ 6 files changed, 121 insertions(+), 94 deletions(-) diff --git a/autotests/write/format/pic/Format_RGBA16FPx4.pic b/autotests/write/format/pic/Format_RGBA16FPx4.pic index 168094131116c8dcf4b5d3aae6c5cf103d1dcae1..e6ca58d6535eec17e7d354fedab15181ef8407b5 100644 GIT binary patch delta 1898 zcmZvddr;I>6vw~!2Z#!+t0Kw*0`h2vX@oNKfse-5G^sQr(bg0`N@g(oL;WioZP*uY z*k!K^OA2D*>Q08K;W(Byh9o&giD95c(+pYTG-@`9&WN{je!rjAH2tx^bI<3Vd(Pc^ z&pFrq;{DaWEvv&yDJKArDOnFACTVSB*YJIHXYdo}iZDV1J*E*$*7qaAw(ZN`y((gK zsAJ83>?PK4Iwh0DUT9JIoy|(SU7NiZKM`qxi0NrlaJFDKsd9{XWirX#5bK89mFUTN zA3^3@#jDJN5L!uCiN4$*nwbA63MP?kf>{3Wu)d@SOP zM3O$>ozE009~fu1=ols6DOg>!1()_W-lc@;wu>*)2ROoWhj<&>R#POjJ%fCur zmpl}^B9UDZ>Ab2$o*r6IoZjAEr~Jc`D;LFCVhxLHN;J`u^>NGN7zo&i+$C}8JZ(45cblV{`dj;Bqy7G;_|i0?5+-BTWo>Ju)C zO1W;TSGeS#Q#8`RchhIG zRnyz~dgy9<=xU!csYu;7$Dlcs8n-A}Nb?+j^SuU=Et;mW^z7Jnl(`$|qm)|dG7|0Q z)CKI3Xf9FBW#sD2w0x$Nt3#BO`EDcI-%Xp(J1Pg|?|{c(U1>|$k}AMYxt`)NYA7Ln z38!xbaFeQ~x}1{bt@K>8tdP@7GrSl1QTj7_SycjFDz$_Pqg+SQpJk_1n3t$9ODm1i zUNj?@!&ie!_;8iMcFdT=}H=<81xzqb57<$ zZsIGw`4aX8WoKk2d}a~`)wKX8WHYiWc2GDx6=dT@dt0r^|zOB`hvgsuM=ozpHf z^16bo_3W<^V#7#>5(6m#wQhn;23p$WssI20 delta 1990 zcmYjSTTGN!5dO{rf-X=ju)5p@Bn`2F#9~V*)p{kd+A7tpvDQl^V(dfXLjy@|cK^K~ z*M&W@U{M6Y3z1-3iZP8^Q@l{4v|zD|ZG56OHAYR7iYCJ8%>VDI54$t-eRF2cf6mOD zr)ymAH-5gR7l2zS#j*$H4l2{5x|}08%+9okXLb@&brLHdm!m6$56M?J$+;h$MZl796k z1zR2J$a1Xm+iRtW%1Yy_aD3@mg_C`*T4IR3aYcI+YLv?K#kZZiPWt5|^FkRH8O=+{Y4V!Fh5e}F zrLRYp&gG+Hql%7h;<`dvmCivnMlQ2Bi1g?r?86F49G<&9vkIh9%r$-f}%Yf@=+LCk_WxpxJId#-Yn{bDY zPNvR^N^lY4)cwX3TAg5B7R<7}LXz~Yw}{oTwpn@_(kE^yRBF)313vR6PENY{cZGXF zRPHiw^8>pvQsID?FH2}AT>oyh+iE!QJBc9qPU_0)a@bEozlaXOfFhLX~rcNr*;?@PnS6w#O|kd z^Ig)#57EUh38I~8oqX|x=2GE243?MtAbpPIMM+_lN^iBn$;$M%IS$oq9-$_uQPWq_ zi@4>erteVk7P<7UaMrUUVmNhpA8Zlb3M7mq6PcC^V z^Bs;rbE@=`sxxNXKbgxo7tJ^u&A7NaV;~l1E#v?V5Nn^&oV?p$OiwKR2mhstzuaPAE0?p;}CViNnrQ+0Cpp1sN#fJmr16iK^ zA!j@Qku>%lo!!2&6U}ug<&kOL-^s0!eyYidt}xy^qbeC6GJ_ z5!ZS`nI5h-wc-#HaXDK!%pr)%dq?S!TGEDg#_c)DyE{l}hp-N|Q;D{tlT5B7stf(G z4M}$Egekw}v0s^P?n&vuF+v1+ZrHGa$00ul?9BbqP4XDR-f~`^s8!+rjSrM3cjJHU C>4Rke diff --git a/autotests/write/format/rgb/Format_RGBA16FPx4.rgb b/autotests/write/format/rgb/Format_RGBA16FPx4.rgb index bd861173540f9916a42ffd98f076610e5ebdcb4d..7c5d9d8396ad533d4806b185a1f6d9ad5d278130 100644 GIT binary patch literal 15516 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 @@ -621,30 +622,38 @@ static bool writeLine(QDataStream &s, QByteArray &buf) return (s.status() == QDataStream::Ok); } -static bool writeImage1(QImage &img, QDataStream &s, PCXHEADER &header) +static bool writeImage1(const QImage &image, QDataStream &s, PCXHEADER &header) { - if (img.format() != QImage::Format_Mono) { - img.convertTo(QImage::Format_Mono); - } - if (img.isNull() || img.colorCount() < 1) { + auto tfmt = image.format(); + if (tfmt != QImage::Format_Mono) + tfmt = QImage::Format_Mono; + + if (image.isNull() || image.colorCount() < 1) { return false; } - auto rgb = img.color(0); - auto minIsBlack = (qRed(rgb) + qGreen(rgb) + qBlue(rgb)) / 3 < 127; + + ScanLineConverter scl(tfmt); + if (image.height() > 0) { + scl.convertedScanLine(image, 0); // required to calculate bytesPerLine + } header.Bpp = 1; header.NPlanes = 1; - header.BytesPerLine = img.bytesPerLine(); + header.BytesPerLine = scl.bytesPerLine(); + if (header.BytesPerLine == 0) { + header.BytesPerLine = image.bytesPerLine(); + } if (header.BytesPerLine == 0) { return false; } s << header; + auto rgb = image.color(0); + auto minIsBlack = (qRed(rgb) + qGreen(rgb) + qBlue(rgb)) / 3 < 127; QByteArray buf(header.BytesPerLine, 0); - for (int y = 0; y < header.height(); ++y) { - auto p = img.constScanLine(y); + auto p = scl.convertedScanLine(image, y); // Invert as QImage uses reverse palette for monochrome images? for (int i = 0; i < header.BytesPerLine; ++i) { @@ -658,7 +667,7 @@ static bool writeImage1(QImage &img, QDataStream &s, PCXHEADER &header) return true; } -static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header) +static bool writeImage4(const QImage &image, QDataStream &s, PCXHEADER &header) { header.Bpp = 1; header.NPlanes = 4; @@ -668,7 +677,7 @@ static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header) } for (int i = 0; i < 16; ++i) { - header.ColorMap.setColor(i, img.color(i)); + header.ColorMap.setColor(i, image.color(i)); } s << header; @@ -680,7 +689,7 @@ static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header) } for (int y = 0; y < header.height(); ++y) { - auto p = img.constScanLine(y); + auto p = image.constScanLine(y); for (int i = 0; i < 4; ++i) { buf[i].fill(0); @@ -703,18 +712,23 @@ static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header) return true; } -static bool writeImage8(QImage &img, QDataStream &s, PCXHEADER &header) +static bool writeImage8(const QImage &image, QDataStream &s, PCXHEADER &header) { - if (img.format() == QImage::Format_Grayscale16) { - img.convertTo(QImage::Format_Grayscale8); - } - if (img.isNull()) { - return false; + auto tfmt = image.format(); + if (tfmt == QImage::Format_Grayscale16) + tfmt = QImage::Format_Grayscale8; + + ScanLineConverter scl(tfmt); + if (image.height() > 0) { + scl.convertedScanLine(image, 0); // required to calculate bytesPerLine } header.Bpp = 8; header.NPlanes = 1; - header.BytesPerLine = img.bytesPerLine(); + header.BytesPerLine = scl.bytesPerLine(); + if (header.BytesPerLine == 0) { + header.BytesPerLine = image.bytesPerLine(); + } if (header.BytesPerLine == 0) { return false; } @@ -724,7 +738,7 @@ static bool writeImage8(QImage &img, QDataStream &s, PCXHEADER &header) QByteArray buf(header.BytesPerLine, 0); for (int y = 0; y < header.height(); ++y) { - auto p = img.constScanLine(y); + auto p = scl.convertedScanLine(image, y); for (int i = 0; i < header.BytesPerLine; ++i) { buf[i] = p[i]; @@ -741,18 +755,18 @@ static bool writeImage8(QImage &img, QDataStream &s, PCXHEADER &header) // Write palette for (int i = 0; i < 256; ++i) { - if (img.format() != QImage::Format_Indexed8) + if (tfmt != QImage::Format_Indexed8) s << RGB::from(qRgb(i, i, i)); else - s << RGB::from(img.color(i)); + s << RGB::from(image.color(i)); } return (s.status() == QDataStream::Ok); } -static bool writeImage24(QImage &img, QDataStream &s, PCXHEADER &header) +static bool writeImage24(const QImage &image, QDataStream &s, PCXHEADER &header) { - auto hasAlpha = img.hasAlphaChannel(); + auto hasAlpha = image.hasAlphaChannel(); header.Bpp = 8; header.NPlanes = hasAlpha ? 4 : 3; header.BytesPerLine = header.width(); @@ -760,11 +774,17 @@ static bool writeImage24(QImage &img, QDataStream &s, PCXHEADER &header) return false; } - if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_RGB32) { - img.convertTo(hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + auto cs = image.colorSpace(); + auto tcs = QColorSpace(); + auto tfmt = image.format(); + if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && tfmt == QImage::Format_CMYK8888) { + tcs = QColorSpace(QColorSpace::SRgb); + tfmt = QImage::Format_RGB32; } - if (img.isNull()) { - return false; +#endif + if (tfmt != QImage::Format_ARGB32 && tfmt != QImage::Format_RGB32) { + tfmt = hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32; } s << header; @@ -774,8 +794,10 @@ static bool writeImage24(QImage &img, QDataStream &s, PCXHEADER &header) QByteArray b_buf(header.width(), 0); QByteArray a_buf(header.width(), char(0xFF)); + ScanLineConverter scl(tfmt); + scl.setTargetColorSpace(tcs); for (int y = 0; y < header.height(); ++y) { - auto p = reinterpret_cast(img.constScanLine(y)); + auto p = reinterpret_cast(scl.convertedScanLine(image, y)); for (int x = 0; x < header.width(); ++x) { auto &&rgb = p[x]; @@ -877,16 +899,8 @@ bool PCXHandler::write(const QImage &image) QDataStream s(device()); s.setByteOrder(QDataStream::LittleEndian); - QImage img = image; -#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) - auto cs = image.colorSpace(); - if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) { - img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb)); - } -#endif - - const int w = img.width(); - const int h = img.height(); + const int w = image.width(); + const int h = image.height(); if (w > 65536 || h > 65536) { return false; @@ -907,14 +921,14 @@ bool PCXHandler::write(const QImage &image) header.PaletteInfo = 1; auto ok = false; - if (img.depth() == 1) { - ok = writeImage1(img, s, header); - } else if (img.format() == QImage::Format_Indexed8 && img.colorCount() <= 16) { - ok = writeImage4(img, s, header); - } else if (img.depth() == 8 || img.format() == QImage::Format_Grayscale16) { - ok = writeImage8(img, s, header); - } else if (img.depth() >= 16) { - ok = writeImage24(img, s, header); + if (image.depth() == 1) { + ok = writeImage1(image, s, header); + } else if (image.format() == QImage::Format_Indexed8 && image.colorCount() <= 16) { + ok = writeImage4(image, s, header); + } else if (image.depth() == 8 || image.format() == QImage::Format_Grayscale16) { + ok = writeImage8(image, s, header); + } else if (image.depth() >= 16) { + ok = writeImage24(image, s, header); } return ok; diff --git a/src/imageformats/pic.cpp b/src/imageformats/pic.cpp index ecd1ef0..03d5915 100644 --- a/src/imageformats/pic.cpp +++ b/src/imageformats/pic.cpp @@ -15,6 +15,7 @@ #include "pic_p.h" #include "rle_p.h" +#include "scanlineconverter_p.h" #include "util_p.h" #include @@ -263,18 +264,20 @@ bool SoftimagePICHandler::read(QImage *image) return true; } -bool SoftimagePICHandler::write(const QImage &_image) +bool SoftimagePICHandler::write(const QImage &image) { - bool alpha = _image.hasAlphaChannel(); - QImage image; + bool alpha = image.hasAlphaChannel(); #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) - auto cs = _image.colorSpace(); - if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && _image.format() == QImage::Format_CMYK8888) { - image = _image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32); + auto cs = image.colorSpace(); + auto tfmt = image.format(); + auto tcs = QColorSpace(); + if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && tfmt == QImage::Format_CMYK8888) { + tcs = QColorSpace(QColorSpace::SRgb); + tfmt = QImage::Format_RGB32; } #endif - if (image.isNull()) { - image = _image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); + if (tfmt != QImage::Format_ARGB32 && tfmt != QImage::Format_RGB32) { + tfmt = alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32; } if (image.width() < 0 || image.height() < 0) { @@ -299,8 +302,10 @@ bool SoftimagePICHandler::write(const QImage &_image) } stream << channels; + ScanLineConverter scl(tfmt); + scl.setTargetColorSpace(tcs); for (int r = 0; r < image.height(); r++) { - const QRgb *row = reinterpret_cast(image.constScanLine(r)); + const QRgb *row = reinterpret_cast(scl.convertedScanLine(image, r)); /* Write the RGB part of the scanline */ auto rgbEqual = [](QRgb p1, QRgb p2) -> bool { diff --git a/src/imageformats/rgb.cpp b/src/imageformats/rgb.cpp index 9bb6c3c..2c409f6 100644 --- a/src/imageformats/rgb.cpp +++ b/src/imageformats/rgb.cpp @@ -20,6 +20,7 @@ */ #include "rgb_p.h" +#include "scanlineconverter_p.h" #include "util_p.h" #include @@ -133,8 +134,8 @@ private: bool writeHeader(); bool writeRle(); - bool writeVerbatim(const QImage &); - bool scanData(const QImage &); + bool writeVerbatim(const QImage &, const QImage::Format&, const QColorSpace&); + bool scanData(const QImage &, const QImage::Format&, const QColorSpace&); uint compact(uchar *, uchar *); uchar intensity(uchar); }; @@ -457,7 +458,7 @@ uint SGIImagePrivate::compact(uchar *d, uchar *s) return dest - d; } -bool SGIImagePrivate::scanData(const QImage &img) +bool SGIImagePrivate::scanData(const QImage &img, const QImage::Format &tfmt, const QColorSpace &tcs) { quint32 *start = _starttab; QByteArray lineguard(_xsize * 2, 0); @@ -469,6 +470,8 @@ bool SGIImagePrivate::scanData(const QImage &img) unsigned y; uint len; + ScanLineConverter scl(tfmt); + scl.setTargetColorSpace(tcs); for (y = 0; y < _ysize; y++) { const int yPos = _ysize - y - 1; // scanline doesn't do any sanity checking if (yPos >= img.height()) { @@ -476,7 +479,7 @@ bool SGIImagePrivate::scanData(const QImage &img) return false; } - c = reinterpret_cast(img.scanLine(yPos)); + c = reinterpret_cast(scl.convertedScanLine(img, yPos)); for (x = 0; x < _xsize; x++) { buf[x] = intensity(qRed(*c++)); @@ -497,7 +500,7 @@ bool SGIImagePrivate::scanData(const QImage &img) return false; } - c = reinterpret_cast(img.scanLine(yPos)); + c = reinterpret_cast(scl.convertedScanLine(img, yPos)); for (x = 0; x < _xsize; x++) { buf[x] = intensity(qGreen(*c++)); } @@ -512,7 +515,7 @@ bool SGIImagePrivate::scanData(const QImage &img) return false; } - c = reinterpret_cast(img.scanLine(yPos)); + c = reinterpret_cast(scl.convertedScanLine(img, yPos)); for (x = 0; x < _xsize; x++) { buf[x] = intensity(qBlue(*c++)); } @@ -532,7 +535,7 @@ bool SGIImagePrivate::scanData(const QImage &img) return false; } - c = reinterpret_cast(img.scanLine(yPos)); + c = reinterpret_cast(scl.convertedScanLine(img, yPos)); for (x = 0; x < _xsize; x++) { buf[x] = intensity(qAlpha(*c++)); } @@ -683,7 +686,7 @@ bool SGIImagePrivate::writeRle() return _stream.status() == QDataStream::Ok; } -bool SGIImagePrivate::writeVerbatim(const QImage &img) +bool SGIImagePrivate::writeVerbatim(const QImage &img, const QImage::Format &tfmt, const QColorSpace &tcs) { _rle = 0; if (!writeHeader()) { @@ -694,11 +697,15 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img) unsigned x; unsigned y; + ScanLineConverter scl(tfmt); + scl.setTargetColorSpace(tcs); + QByteArray ba(_xsize, char()); for (y = 0; y < _ysize; y++) { - c = reinterpret_cast(img.scanLine(_ysize - y - 1)); + c = reinterpret_cast(scl.convertedScanLine(img, _ysize - y - 1)); for (x = 0; x < _xsize; x++) { - _stream << quint8(qRed(*c++)); + ba[x] = char(qRed(*c++)); } + _stream.writeRawData(ba.data(), ba.size()); } if (_zsize == 1) { @@ -707,17 +714,19 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img) if (_zsize != 2) { for (y = 0; y < _ysize; y++) { - c = reinterpret_cast(img.scanLine(_ysize - y - 1)); + c = reinterpret_cast(scl.convertedScanLine(img, _ysize - y - 1)); for (x = 0; x < _xsize; x++) { - _stream << quint8(qGreen(*c++)); + ba[x] = char(qGreen(*c++)); } + _stream.writeRawData(ba.data(), ba.size()); } for (y = 0; y < _ysize; y++) { - c = reinterpret_cast(img.scanLine(_ysize - y - 1)); + c = reinterpret_cast(scl.convertedScanLine(img, _ysize - y - 1)); for (x = 0; x < _xsize; x++) { - _stream << quint8(qBlue(*c++)); + ba[x] = char(qBlue(*c++)); } + _stream.writeRawData(ba.data(), ba.size()); } if (_zsize == 3) { @@ -726,10 +735,11 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img) } for (y = 0; y < _ysize; y++) { - c = reinterpret_cast(img.scanLine(_ysize - y - 1)); + c = reinterpret_cast(scl.convertedScanLine(img, _ysize - y - 1)); for (x = 0; x < _xsize; x++) { - _stream << quint8(qAlpha(*c++)); + ba[x] = char(qAlpha(*c++)); } + _stream.writeRawData(ba.data(), ba.size()); } return _stream.status() == QDataStream::Ok; @@ -738,37 +748,35 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img) bool SGIImagePrivate::writeImage(const QImage &image) { // qDebug() << "writing "; // TODO add filename - QImage img = image; - if (img.allGray()) { + if (image.allGray()) { _dim = 2, _zsize = 1; } else { _dim = 3, _zsize = 3; } - auto hasAlpha = img.hasAlphaChannel(); + auto hasAlpha = image.hasAlphaChannel(); if (hasAlpha) { _dim = 3, _zsize++; } #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) auto cs = image.colorSpace(); - if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) { - img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32); - } else if (hasAlpha && img.format() != QImage::Format_ARGB32) { + auto tcs = QColorSpace(); + auto tfmt = image.format(); + if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && tfmt == QImage::Format_CMYK8888) { + tcs = QColorSpace(QColorSpace::SRgb); + tfmt = QImage::Format_RGB32; + } else if (hasAlpha && tfmt != QImage::Format_ARGB32) { #else - if (hasAlpha && img.format() != QImage::Format_ARGB32) { + if (hasAlpha && tfmt != QImage::Format_ARGB32) { #endif - img = img.convertToFormat(QImage::Format_ARGB32); - } else if (!hasAlpha && img.format() != QImage::Format_RGB32) { - img = img.convertToFormat(QImage::Format_RGB32); - } - if (img.isNull()) { - // qDebug() << "can't convert image to depth 32"; - return false; + tfmt = QImage::Format_ARGB32; + } else if (!hasAlpha && tfmt != QImage::Format_RGB32) { + tfmt = QImage::Format_RGB32; } - const int w = img.width(); - const int h = img.height(); + const int w = image.width(); + const int h = image.height(); if (w > 65535 || h > 65535) { return false; @@ -785,7 +793,7 @@ bool SGIImagePrivate::writeImage(const QImage &image) _starttab = new quint32[_numrows]; _rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32)); - if (!scanData(img)) { + if (!scanData(image, tfmt, tcs)) { // qDebug() << "this can't happen"; return false; } @@ -799,7 +807,7 @@ bool SGIImagePrivate::writeImage(const QImage &image) } if (verbatim_size <= rle_size) { - return writeVerbatim(img); + return writeVerbatim(image, tfmt, tcs); } return writeRle(); }