diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-19 12:53:10 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-20 17:10:19 +0200 |
commit | 9e86fdb6e8004a0eba7d5f4b9a7b1f52275fd207 (patch) | |
tree | 65b1ee8e70e2ad1bdbc7d8c9361c8dded108af04 /src/plugins | |
parent | aa6e0e3e30ec7f330e2fbc02fc9fbe55ef0b6432 (diff) |
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>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/imageformats/jpeg/qjpeghandler.cpp | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 0fb21df1d3..1f1675e490 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -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; |