Support writing color space profile in JPEG

That way the image formats with color space supports all have both read
and write support.

Change-Id: Ib52ebd56192c4a8a0897a6afc7c4a26020319270
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2019-08-19 12:53:10 +02:00
parent aa6e0e3e30
commit 9e86fdb6e8
2 changed files with 34 additions and 2 deletions

View File

@ -492,6 +492,8 @@ inline my_jpeg_destination_mgr::my_jpeg_destination_mgr(QIODevice *device)
free_in_buffer = max_buf;
}
static constexpr int maxMarkerSize = 65533;
static inline void set_text(const QImage &image, j_compress_ptr cinfo, const QString &description)
{
const QMap<QString, QString> text = qt_getImageText(image, description);
@ -500,12 +502,33 @@ static inline void set_text(const QImage &image, j_compress_ptr cinfo, const QSt
if (!comment.isEmpty())
comment += ": ";
comment += it.value().toUtf8();
if (comment.length() > 65530)
comment.truncate(65530);
if (comment.length() > maxMarkerSize)
comment.truncate(maxMarkerSize);
jpeg_write_marker(cinfo, JPEG_COM, (const JOCTET *)comment.constData(), comment.size());
}
}
static inline void write_icc_profile(const QImage &image, j_compress_ptr cinfo)
{
const QByteArray iccProfile = image.colorSpace().iccProfile();
if (iccProfile.isEmpty())
return;
const QByteArray iccSignature("ICC_PROFILE", 12);
constexpr int maxIccMarkerSize = maxMarkerSize - (12 + 2);
int index = 0;
const int markers = (iccProfile.size() + (maxIccMarkerSize - 1)) / maxIccMarkerSize;
Q_ASSERT(markers < 256);
for (int marker = 1; marker <= markers; ++marker) {
const int len = std::min(iccProfile.size() - index, maxIccMarkerSize);
const QByteArray block = iccSignature
+ QByteArray(1, char(marker)) + QByteArray(1, char(markers))
+ iccProfile.mid(index, len);
jpeg_write_marker(cinfo, JPEG_APP0 + 2, reinterpret_cast<const JOCTET *>(block.constData()), block.size());
index += len;
}
}
static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile int sourceQuality, const QString &description, bool optimize, bool progressive)
{
bool success = false;
@ -586,6 +609,8 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in
jpeg_start_compress(&cinfo, TRUE);
set_text(image, &cinfo, description);
if (cinfo.in_color_space == JCS_RGB)
write_icc_profile(image, &cinfo);
row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
int w = cinfo.image_width;

View File

@ -1914,6 +1914,13 @@ void tst_QImageReader::saveColorSpace()
QCOMPARE(stored, orig);
QCOMPARE(stored.colorSpace(), orig.colorSpace());
buf.open(QIODevice::WriteOnly);
QVERIFY(orig.save(&buf, "jpeg"));
buf.close();
stored = QImage::fromData(buf.buffer(), "jpeg");
QCOMPARE(stored.colorSpace(), orig.colorSpace());
}
void tst_QImageReader::readText_data()