summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKonstantin Ritt <ritt.ks@gmail.com>2012-05-08 14:15:04 +0300
committerQt by Nokia <qt-info@nokia.com>2012-05-16 04:24:50 +0200
commit3cfcceae43a152dbed336679733745c13e3d6228 (patch)
tree7141eacc3c665eacf6523448d7791e18fc2bd816 /src
parent2380765a2b4563bc714f947927d2cd48e2bbb49d (diff)
QJpegHandler: add an embedded text support
texts for the textKeys are stored each in a separate COM(ment) section so that the maximum text's size is almost 65KB Task-number: QTBUG-10568 Task-number: QTBUG-111 Change-Id: I7d693741e10e5d78d497cb0af448160077350bb2 Reviewed-by: aavit <qt_aavit@ovi.com>
Diffstat (limited to 'src')
-rw-r--r--src/gui/image/qjpeghandler.cpp92
1 files changed, 83 insertions, 9 deletions
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 7dcbcf508f..c42977ef10 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -528,7 +528,40 @@ inline my_jpeg_destination_mgr::my_jpeg_destination_mgr(QIODevice *device)
}
-static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQuality)
+static inline void set_text(const QImage &image, j_compress_ptr cinfo, const QString &description)
+{
+ QMap<QString, QString> text;
+ foreach (const QString &key, image.textKeys()) {
+ if (!key.isEmpty())
+ text.insert(key, image.text(key));
+ }
+ foreach (const QString &pair, description.split(QLatin1String("\n\n"))) {
+ int index = pair.indexOf(QLatin1Char(':'));
+ if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) {
+ QString s = pair.simplified();
+ if (!s.isEmpty())
+ text.insert(QLatin1String("Description"), s);
+ } else {
+ QString key = pair.left(index);
+ if (!key.simplified().isEmpty())
+ text.insert(key, pair.mid(index + 2).simplified());
+ }
+ }
+ if (text.isEmpty())
+ return;
+
+ for (QMap<QString, QString>::ConstIterator it = text.constBegin(); it != text.constEnd(); ++it) {
+ QByteArray comment = it.key().toLatin1();
+ if (!comment.isEmpty())
+ comment += ": ";
+ comment += it.value().toLatin1();
+ if (comment.length() > 65530)
+ comment.truncate(65530);
+ jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *)comment.constData(), comment.size());
+ }
+}
+
+static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQuality, const QString &description)
{
bool success = false;
const QVector<QRgb> cmap = image.colorTable();
@@ -600,6 +633,8 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQ
jpeg_start_compress(&cinfo, true);
#endif
+ set_text(image, &cinfo, description);
+
row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
int w = cinfo.image_width;
while (cinfo.next_scanline < cinfo.image_height) {
@@ -734,6 +769,9 @@ public:
QSize scaledSize;
QRect scaledClipRect;
QRect clipRect;
+ QString description;
+ QStringList readTexts;
+
struct jpeg_decompress_struct info;
struct my_jpeg_source_mgr * iod_src;
struct my_error_mgr err;
@@ -760,6 +798,8 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
err.output_message = my_output_message;
if (!setjmp(err.setjmp_buffer)) {
+ jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
+
#if defined(Q_OS_UNIXWARE)
(void) jpeg_read_header(&info, B_TRUE);
#else
@@ -773,6 +813,27 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
format = QImage::Format_Invalid;
read_jpeg_format(format, &info);
+
+ for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
+ if (marker->marker == JPEG_COM) {
+ QString key, value;
+ QString s = QString::fromLatin1((const char *)marker->data, marker->data_length);
+ int index = s.indexOf(QLatin1String(": "));
+ if (index == -1 || s.indexOf(QLatin1Char(' ')) < index) {
+ key = QLatin1String("Description");
+ value = s;
+ } else {
+ key = s.left(index);
+ value = s.mid(index + 2);
+ }
+ if (!description.isEmpty())
+ description += QLatin1String("\n\n");
+ description += key + QLatin1String(": ") + value.simplified();
+ readTexts.append(key);
+ readTexts.append(value);
+ }
+ }
+
state = ReadHeader;
return true;
}
@@ -793,9 +854,16 @@ bool QJpegHandlerPrivate::read(QImage *image)
if(state == ReadHeader)
{
- bool success = read_jpeg_image(image, scaledSize, scaledClipRect, clipRect, quality, &info, &err);
- state = success ? Ready : Error;
- return success;
+ bool success = read_jpeg_image(image, scaledSize, scaledClipRect, clipRect, quality, &info, &err);
+ if (success) {
+ for (int i = 0; i < readTexts.size()-1; i+=2)
+ image->setText(readTexts.at(i), readTexts.at(i+1));
+
+ state = Ready;
+ return true;
+ }
+
+ state = Error;
}
return false;
@@ -863,7 +931,7 @@ bool QJpegHandler::read(QImage *image)
bool QJpegHandler::write(const QImage &image)
{
- return write_jpeg_image(image, device(), d->quality);
+ return write_jpeg_image(image, device(), d->quality, d->description);
}
bool QJpegHandler::supportsOption(ImageOption option) const
@@ -872,6 +940,7 @@ bool QJpegHandler::supportsOption(ImageOption option) const
|| option == ScaledSize
|| option == ScaledClipRect
|| option == ClipRect
+ || option == Description
|| option == Size
|| option == ImageFormat;
}
@@ -887,6 +956,9 @@ QVariant QJpegHandler::option(ImageOption option) const
return d->scaledClipRect;
case ClipRect:
return d->clipRect;
+ case Description:
+ d->readJpegHeader(device());
+ return d->description;
case Size:
d->readJpegHeader(device());
return d->size;
@@ -894,8 +966,10 @@ QVariant QJpegHandler::option(ImageOption option) const
d->readJpegHeader(device());
return d->format;
default:
- return QVariant();
+ break;
}
+
+ return QVariant();
}
void QJpegHandler::setOption(ImageOption option, const QVariant &value)
@@ -913,6 +987,9 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value)
case ClipRect:
d->clipRect = value.toRect();
break;
+ case Description:
+ d->description = value.toString();
+ break;
default:
break;
}
@@ -923,7 +1000,4 @@ QByteArray QJpegHandler::name() const
return "jpeg";
}
-
-
-
QT_END_NAMESPACE