mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-11-30 12:02:42 -05:00
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.
This commit is contained in:
Binary file not shown.
Binary file not shown.
@ -101,11 +101,11 @@ endif()
|
|||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
kimageformats_add_plugin(kimg_pcx SOURCES pcx.cpp)
|
kimageformats_add_plugin(kimg_pcx SOURCES pcx.cpp scanlineconverter.cpp)
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
kimageformats_add_plugin(kimg_pic SOURCES pic.cpp)
|
kimageformats_add_plugin(kimg_pic SOURCES pic.cpp scanlineconverter.cpp)
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ kimageformats_add_plugin(kimg_ras SOURCES ras.cpp)
|
|||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
kimageformats_add_plugin(kimg_rgb SOURCES rgb.cpp)
|
kimageformats_add_plugin(kimg_rgb SOURCES rgb.cpp scanlineconverter.cpp)
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pcx_p.h"
|
#include "pcx_p.h"
|
||||||
|
#include "scanlineconverter_p.h"
|
||||||
#include "util_p.h"
|
#include "util_p.h"
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
@ -621,30 +622,38 @@ static bool writeLine(QDataStream &s, QByteArray &buf)
|
|||||||
return (s.status() == QDataStream::Ok);
|
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) {
|
auto tfmt = image.format();
|
||||||
img.convertTo(QImage::Format_Mono);
|
if (tfmt != QImage::Format_Mono)
|
||||||
}
|
tfmt = QImage::Format_Mono;
|
||||||
if (img.isNull() || img.colorCount() < 1) {
|
|
||||||
|
if (image.isNull() || image.colorCount() < 1) {
|
||||||
return false;
|
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.Bpp = 1;
|
||||||
header.NPlanes = 1;
|
header.NPlanes = 1;
|
||||||
header.BytesPerLine = img.bytesPerLine();
|
header.BytesPerLine = scl.bytesPerLine();
|
||||||
|
if (header.BytesPerLine == 0) {
|
||||||
|
header.BytesPerLine = image.bytesPerLine();
|
||||||
|
}
|
||||||
if (header.BytesPerLine == 0) {
|
if (header.BytesPerLine == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
s << header;
|
s << header;
|
||||||
|
|
||||||
|
auto rgb = image.color(0);
|
||||||
|
auto minIsBlack = (qRed(rgb) + qGreen(rgb) + qBlue(rgb)) / 3 < 127;
|
||||||
QByteArray buf(header.BytesPerLine, 0);
|
QByteArray buf(header.BytesPerLine, 0);
|
||||||
|
|
||||||
for (int y = 0; y < header.height(); ++y) {
|
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?
|
// Invert as QImage uses reverse palette for monochrome images?
|
||||||
for (int i = 0; i < header.BytesPerLine; ++i) {
|
for (int i = 0; i < header.BytesPerLine; ++i) {
|
||||||
@ -658,7 +667,7 @@ static bool writeImage1(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
return true;
|
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.Bpp = 1;
|
||||||
header.NPlanes = 4;
|
header.NPlanes = 4;
|
||||||
@ -668,7 +677,7 @@ static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
header.ColorMap.setColor(i, img.color(i));
|
header.ColorMap.setColor(i, image.color(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
s << header;
|
s << header;
|
||||||
@ -680,7 +689,7 @@ static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int y = 0; y < header.height(); ++y) {
|
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) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
buf[i].fill(0);
|
buf[i].fill(0);
|
||||||
@ -703,18 +712,23 @@ static bool writeImage4(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
return true;
|
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) {
|
auto tfmt = image.format();
|
||||||
img.convertTo(QImage::Format_Grayscale8);
|
if (tfmt == QImage::Format_Grayscale16)
|
||||||
}
|
tfmt = QImage::Format_Grayscale8;
|
||||||
if (img.isNull()) {
|
|
||||||
return false;
|
ScanLineConverter scl(tfmt);
|
||||||
|
if (image.height() > 0) {
|
||||||
|
scl.convertedScanLine(image, 0); // required to calculate bytesPerLine
|
||||||
}
|
}
|
||||||
|
|
||||||
header.Bpp = 8;
|
header.Bpp = 8;
|
||||||
header.NPlanes = 1;
|
header.NPlanes = 1;
|
||||||
header.BytesPerLine = img.bytesPerLine();
|
header.BytesPerLine = scl.bytesPerLine();
|
||||||
|
if (header.BytesPerLine == 0) {
|
||||||
|
header.BytesPerLine = image.bytesPerLine();
|
||||||
|
}
|
||||||
if (header.BytesPerLine == 0) {
|
if (header.BytesPerLine == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -724,7 +738,7 @@ static bool writeImage8(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
QByteArray buf(header.BytesPerLine, 0);
|
QByteArray buf(header.BytesPerLine, 0);
|
||||||
|
|
||||||
for (int y = 0; y < header.height(); ++y) {
|
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) {
|
for (int i = 0; i < header.BytesPerLine; ++i) {
|
||||||
buf[i] = p[i];
|
buf[i] = p[i];
|
||||||
@ -741,18 +755,18 @@ static bool writeImage8(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
|
|
||||||
// Write palette
|
// Write palette
|
||||||
for (int i = 0; i < 256; ++i) {
|
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));
|
s << RGB::from(qRgb(i, i, i));
|
||||||
else
|
else
|
||||||
s << RGB::from(img.color(i));
|
s << RGB::from(image.color(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (s.status() == QDataStream::Ok);
|
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.Bpp = 8;
|
||||||
header.NPlanes = hasAlpha ? 4 : 3;
|
header.NPlanes = hasAlpha ? 4 : 3;
|
||||||
header.BytesPerLine = header.width();
|
header.BytesPerLine = header.width();
|
||||||
@ -760,11 +774,17 @@ static bool writeImage24(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_RGB32) {
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
img.convertTo(hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
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()) {
|
#endif
|
||||||
return false;
|
if (tfmt != QImage::Format_ARGB32 && tfmt != QImage::Format_RGB32) {
|
||||||
|
tfmt = hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32;
|
||||||
}
|
}
|
||||||
|
|
||||||
s << header;
|
s << header;
|
||||||
@ -774,8 +794,10 @@ static bool writeImage24(QImage &img, QDataStream &s, PCXHEADER &header)
|
|||||||
QByteArray b_buf(header.width(), 0);
|
QByteArray b_buf(header.width(), 0);
|
||||||
QByteArray a_buf(header.width(), char(0xFF));
|
QByteArray a_buf(header.width(), char(0xFF));
|
||||||
|
|
||||||
|
ScanLineConverter scl(tfmt);
|
||||||
|
scl.setTargetColorSpace(tcs);
|
||||||
for (int y = 0; y < header.height(); ++y) {
|
for (int y = 0; y < header.height(); ++y) {
|
||||||
auto p = reinterpret_cast<const QRgb *>(img.constScanLine(y));
|
auto p = reinterpret_cast<const QRgb *>(scl.convertedScanLine(image, y));
|
||||||
|
|
||||||
for (int x = 0; x < header.width(); ++x) {
|
for (int x = 0; x < header.width(); ++x) {
|
||||||
auto &&rgb = p[x];
|
auto &&rgb = p[x];
|
||||||
@ -877,16 +899,8 @@ bool PCXHandler::write(const QImage &image)
|
|||||||
QDataStream s(device());
|
QDataStream s(device());
|
||||||
s.setByteOrder(QDataStream::LittleEndian);
|
s.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
QImage img = image;
|
const int w = image.width();
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
const int h = image.height();
|
||||||
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();
|
|
||||||
|
|
||||||
if (w > 65536 || h > 65536) {
|
if (w > 65536 || h > 65536) {
|
||||||
return false;
|
return false;
|
||||||
@ -907,14 +921,14 @@ bool PCXHandler::write(const QImage &image)
|
|||||||
header.PaletteInfo = 1;
|
header.PaletteInfo = 1;
|
||||||
|
|
||||||
auto ok = false;
|
auto ok = false;
|
||||||
if (img.depth() == 1) {
|
if (image.depth() == 1) {
|
||||||
ok = writeImage1(img, s, header);
|
ok = writeImage1(image, s, header);
|
||||||
} else if (img.format() == QImage::Format_Indexed8 && img.colorCount() <= 16) {
|
} else if (image.format() == QImage::Format_Indexed8 && image.colorCount() <= 16) {
|
||||||
ok = writeImage4(img, s, header);
|
ok = writeImage4(image, s, header);
|
||||||
} else if (img.depth() == 8 || img.format() == QImage::Format_Grayscale16) {
|
} else if (image.depth() == 8 || image.format() == QImage::Format_Grayscale16) {
|
||||||
ok = writeImage8(img, s, header);
|
ok = writeImage8(image, s, header);
|
||||||
} else if (img.depth() >= 16) {
|
} else if (image.depth() >= 16) {
|
||||||
ok = writeImage24(img, s, header);
|
ok = writeImage24(image, s, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "pic_p.h"
|
#include "pic_p.h"
|
||||||
#include "rle_p.h"
|
#include "rle_p.h"
|
||||||
|
#include "scanlineconverter_p.h"
|
||||||
#include "util_p.h"
|
#include "util_p.h"
|
||||||
|
|
||||||
#include <QColorSpace>
|
#include <QColorSpace>
|
||||||
@ -263,18 +264,20 @@ bool SoftimagePICHandler::read(QImage *image)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoftimagePICHandler::write(const QImage &_image)
|
bool SoftimagePICHandler::write(const QImage &image)
|
||||||
{
|
{
|
||||||
bool alpha = _image.hasAlphaChannel();
|
bool alpha = image.hasAlphaChannel();
|
||||||
QImage image;
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
auto cs = _image.colorSpace();
|
auto cs = image.colorSpace();
|
||||||
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && _image.format() == QImage::Format_CMYK8888) {
|
auto tfmt = image.format();
|
||||||
image = _image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32);
|
auto tcs = QColorSpace();
|
||||||
|
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && tfmt == QImage::Format_CMYK8888) {
|
||||||
|
tcs = QColorSpace(QColorSpace::SRgb);
|
||||||
|
tfmt = QImage::Format_RGB32;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (image.isNull()) {
|
if (tfmt != QImage::Format_ARGB32 && tfmt != QImage::Format_RGB32) {
|
||||||
image = _image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
tfmt = alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image.width() < 0 || image.height() < 0) {
|
if (image.width() < 0 || image.height() < 0) {
|
||||||
@ -299,8 +302,10 @@ bool SoftimagePICHandler::write(const QImage &_image)
|
|||||||
}
|
}
|
||||||
stream << channels;
|
stream << channels;
|
||||||
|
|
||||||
|
ScanLineConverter scl(tfmt);
|
||||||
|
scl.setTargetColorSpace(tcs);
|
||||||
for (int r = 0; r < image.height(); r++) {
|
for (int r = 0; r < image.height(); r++) {
|
||||||
const QRgb *row = reinterpret_cast<const QRgb *>(image.constScanLine(r));
|
const QRgb *row = reinterpret_cast<const QRgb *>(scl.convertedScanLine(image, r));
|
||||||
|
|
||||||
/* Write the RGB part of the scanline */
|
/* Write the RGB part of the scanline */
|
||||||
auto rgbEqual = [](QRgb p1, QRgb p2) -> bool {
|
auto rgbEqual = [](QRgb p1, QRgb p2) -> bool {
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rgb_p.h"
|
#include "rgb_p.h"
|
||||||
|
#include "scanlineconverter_p.h"
|
||||||
#include "util_p.h"
|
#include "util_p.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -133,8 +134,8 @@ private:
|
|||||||
|
|
||||||
bool writeHeader();
|
bool writeHeader();
|
||||||
bool writeRle();
|
bool writeRle();
|
||||||
bool writeVerbatim(const QImage &);
|
bool writeVerbatim(const QImage &, const QImage::Format&, const QColorSpace&);
|
||||||
bool scanData(const QImage &);
|
bool scanData(const QImage &, const QImage::Format&, const QColorSpace&);
|
||||||
uint compact(uchar *, uchar *);
|
uint compact(uchar *, uchar *);
|
||||||
uchar intensity(uchar);
|
uchar intensity(uchar);
|
||||||
};
|
};
|
||||||
@ -457,7 +458,7 @@ uint SGIImagePrivate::compact(uchar *d, uchar *s)
|
|||||||
return dest - d;
|
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;
|
quint32 *start = _starttab;
|
||||||
QByteArray lineguard(_xsize * 2, 0);
|
QByteArray lineguard(_xsize * 2, 0);
|
||||||
@ -469,6 +470,8 @@ bool SGIImagePrivate::scanData(const QImage &img)
|
|||||||
unsigned y;
|
unsigned y;
|
||||||
uint len;
|
uint len;
|
||||||
|
|
||||||
|
ScanLineConverter scl(tfmt);
|
||||||
|
scl.setTargetColorSpace(tcs);
|
||||||
for (y = 0; y < _ysize; y++) {
|
for (y = 0; y < _ysize; y++) {
|
||||||
const int yPos = _ysize - y - 1; // scanline doesn't do any sanity checking
|
const int yPos = _ysize - y - 1; // scanline doesn't do any sanity checking
|
||||||
if (yPos >= img.height()) {
|
if (yPos >= img.height()) {
|
||||||
@ -476,7 +479,7 @@ bool SGIImagePrivate::scanData(const QImage &img)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, yPos));
|
||||||
|
|
||||||
for (x = 0; x < _xsize; x++) {
|
for (x = 0; x < _xsize; x++) {
|
||||||
buf[x] = intensity(qRed(*c++));
|
buf[x] = intensity(qRed(*c++));
|
||||||
@ -497,7 +500,7 @@ bool SGIImagePrivate::scanData(const QImage &img)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, yPos));
|
||||||
for (x = 0; x < _xsize; x++) {
|
for (x = 0; x < _xsize; x++) {
|
||||||
buf[x] = intensity(qGreen(*c++));
|
buf[x] = intensity(qGreen(*c++));
|
||||||
}
|
}
|
||||||
@ -512,7 +515,7 @@ bool SGIImagePrivate::scanData(const QImage &img)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, yPos));
|
||||||
for (x = 0; x < _xsize; x++) {
|
for (x = 0; x < _xsize; x++) {
|
||||||
buf[x] = intensity(qBlue(*c++));
|
buf[x] = intensity(qBlue(*c++));
|
||||||
}
|
}
|
||||||
@ -532,7 +535,7 @@ bool SGIImagePrivate::scanData(const QImage &img)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, yPos));
|
||||||
for (x = 0; x < _xsize; x++) {
|
for (x = 0; x < _xsize; x++) {
|
||||||
buf[x] = intensity(qAlpha(*c++));
|
buf[x] = intensity(qAlpha(*c++));
|
||||||
}
|
}
|
||||||
@ -683,7 +686,7 @@ bool SGIImagePrivate::writeRle()
|
|||||||
return _stream.status() == QDataStream::Ok;
|
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;
|
_rle = 0;
|
||||||
if (!writeHeader()) {
|
if (!writeHeader()) {
|
||||||
@ -694,11 +697,15 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img)
|
|||||||
unsigned x;
|
unsigned x;
|
||||||
unsigned y;
|
unsigned y;
|
||||||
|
|
||||||
|
ScanLineConverter scl(tfmt);
|
||||||
|
scl.setTargetColorSpace(tcs);
|
||||||
|
QByteArray ba(_xsize, char());
|
||||||
for (y = 0; y < _ysize; y++) {
|
for (y = 0; y < _ysize; y++) {
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, _ysize - y - 1));
|
||||||
for (x = 0; x < _xsize; x++) {
|
for (x = 0; x < _xsize; x++) {
|
||||||
_stream << quint8(qRed(*c++));
|
ba[x] = char(qRed(*c++));
|
||||||
}
|
}
|
||||||
|
_stream.writeRawData(ba.data(), ba.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_zsize == 1) {
|
if (_zsize == 1) {
|
||||||
@ -707,17 +714,19 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img)
|
|||||||
|
|
||||||
if (_zsize != 2) {
|
if (_zsize != 2) {
|
||||||
for (y = 0; y < _ysize; y++) {
|
for (y = 0; y < _ysize; y++) {
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, _ysize - y - 1));
|
||||||
for (x = 0; x < _xsize; x++) {
|
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++) {
|
for (y = 0; y < _ysize; y++) {
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, _ysize - y - 1));
|
||||||
for (x = 0; x < _xsize; x++) {
|
for (x = 0; x < _xsize; x++) {
|
||||||
_stream << quint8(qBlue(*c++));
|
ba[x] = char(qBlue(*c++));
|
||||||
}
|
}
|
||||||
|
_stream.writeRawData(ba.data(), ba.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_zsize == 3) {
|
if (_zsize == 3) {
|
||||||
@ -726,10 +735,11 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (y = 0; y < _ysize; y++) {
|
for (y = 0; y < _ysize; y++) {
|
||||||
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
|
c = reinterpret_cast<const QRgb *>(scl.convertedScanLine(img, _ysize - y - 1));
|
||||||
for (x = 0; x < _xsize; x++) {
|
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;
|
return _stream.status() == QDataStream::Ok;
|
||||||
@ -738,37 +748,35 @@ bool SGIImagePrivate::writeVerbatim(const QImage &img)
|
|||||||
bool SGIImagePrivate::writeImage(const QImage &image)
|
bool SGIImagePrivate::writeImage(const QImage &image)
|
||||||
{
|
{
|
||||||
// qDebug() << "writing "; // TODO add filename
|
// qDebug() << "writing "; // TODO add filename
|
||||||
QImage img = image;
|
if (image.allGray()) {
|
||||||
if (img.allGray()) {
|
|
||||||
_dim = 2, _zsize = 1;
|
_dim = 2, _zsize = 1;
|
||||||
} else {
|
} else {
|
||||||
_dim = 3, _zsize = 3;
|
_dim = 3, _zsize = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hasAlpha = img.hasAlphaChannel();
|
auto hasAlpha = image.hasAlphaChannel();
|
||||||
if (hasAlpha) {
|
if (hasAlpha) {
|
||||||
_dim = 3, _zsize++;
|
_dim = 3, _zsize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
auto cs = image.colorSpace();
|
auto cs = image.colorSpace();
|
||||||
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
|
auto tcs = QColorSpace();
|
||||||
img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32);
|
auto tfmt = image.format();
|
||||||
} else if (hasAlpha && img.format() != QImage::Format_ARGB32) {
|
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
|
#else
|
||||||
if (hasAlpha && img.format() != QImage::Format_ARGB32) {
|
if (hasAlpha && tfmt != QImage::Format_ARGB32) {
|
||||||
#endif
|
#endif
|
||||||
img = img.convertToFormat(QImage::Format_ARGB32);
|
tfmt = QImage::Format_ARGB32;
|
||||||
} else if (!hasAlpha && img.format() != QImage::Format_RGB32) {
|
} else if (!hasAlpha && tfmt != QImage::Format_RGB32) {
|
||||||
img = img.convertToFormat(QImage::Format_RGB32);
|
tfmt = QImage::Format_RGB32;
|
||||||
}
|
|
||||||
if (img.isNull()) {
|
|
||||||
// qDebug() << "can't convert image to depth 32";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int w = img.width();
|
const int w = image.width();
|
||||||
const int h = img.height();
|
const int h = image.height();
|
||||||
|
|
||||||
if (w > 65535 || h > 65535) {
|
if (w > 65535 || h > 65535) {
|
||||||
return false;
|
return false;
|
||||||
@ -785,7 +793,7 @@ bool SGIImagePrivate::writeImage(const QImage &image)
|
|||||||
_starttab = new quint32[_numrows];
|
_starttab = new quint32[_numrows];
|
||||||
_rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32));
|
_rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32));
|
||||||
|
|
||||||
if (!scanData(img)) {
|
if (!scanData(image, tfmt, tcs)) {
|
||||||
// qDebug() << "this can't happen";
|
// qDebug() << "this can't happen";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -799,7 +807,7 @@ bool SGIImagePrivate::writeImage(const QImage &image)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (verbatim_size <= rle_size) {
|
if (verbatim_size <= rle_size) {
|
||||||
return writeVerbatim(img);
|
return writeVerbatim(image, tfmt, tcs);
|
||||||
}
|
}
|
||||||
return writeRle();
|
return writeRle();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user