summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qjpeghandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image/qjpeghandler.cpp')
-rw-r--r--src/gui/image/qjpeghandler.cpp71
1 files changed, 41 insertions, 30 deletions
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 9cf9947b6c..b07e1e28d3 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -86,9 +86,7 @@ struct my_error_mgr : public jpeg_error_mgr {
jmp_buf setjmp_buffer;
};
-#if defined(Q_C_CALLBACKS)
extern "C" {
-#endif
static void my_error_exit (j_common_ptr cinfo)
{
@@ -106,9 +104,7 @@ static void my_output_message(j_common_ptr cinfo)
qWarning("%s", buffer);
}
-#if defined(Q_C_CALLBACKS)
}
-#endif
static const int max_buf = 4096;
@@ -123,9 +119,7 @@ public:
my_jpeg_source_mgr(QIODevice *device);
};
-#if defined(Q_C_CALLBACKS)
extern "C" {
-#endif
static void qt_init_source(j_decompress_ptr)
{
@@ -185,9 +179,7 @@ static void qt_term_source(j_decompress_ptr cinfo)
src->device->seek(src->device->pos() - src->bytes_in_buffer);
}
-#if defined(Q_C_CALLBACKS)
}
-#endif
inline my_jpeg_source_mgr::my_jpeg_source_mgr(QIODevice *device)
{
@@ -220,7 +212,7 @@ inline static bool read_jpeg_format(QImage::Format &format, j_decompress_ptr cin
bool result = true;
switch (cinfo->output_components) {
case 1:
- format = QImage::Format_Indexed8;
+ format = QImage::Format_Grayscale8;
break;
case 3:
case 4:
@@ -240,7 +232,7 @@ static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info,
QImage::Format format;
switch (info->output_components) {
case 1:
- format = QImage::Format_Indexed8;
+ format = QImage::Format_Grayscale8;
break;
case 3:
case 4:
@@ -250,16 +242,9 @@ static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info,
return false; // unsupported format
}
- if (dest->size() != size || dest->format() != format) {
+ if (dest->size() != size || dest->format() != format)
*dest = QImage(size, format);
- if (format == QImage::Format_Indexed8) {
- dest->setColorCount(256);
- for (int i = 0; i < 256; i++)
- dest->setColor(i, qRgb(i,i,i));
- }
- }
-
return !dest->isNull();
}
@@ -465,9 +450,7 @@ public:
};
-#if defined(Q_C_CALLBACKS)
extern "C" {
-#endif
static void qt_init_destination(j_compress_ptr)
{
@@ -497,9 +480,7 @@ static void qt_term_destination(j_compress_ptr cinfo)
(*cinfo->err->error_exit)((j_common_ptr)cinfo);
}
-#if defined(Q_C_CALLBACKS)
}
-#endif
inline my_jpeg_destination_mgr::my_jpeg_destination_mgr(QIODevice *device)
{
@@ -545,11 +526,14 @@ static inline void set_text(const QImage &image, j_compress_ptr cinfo, const QSt
}
}
-static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile int sourceQuality, const QString &description)
+static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile int sourceQuality, const QString &description, bool optimize, bool progressive)
{
bool success = false;
const QVector<QRgb> cmap = image.colorTable();
+ if (image.format() == QImage::Format_Invalid || image.format() == QImage::Format_Alpha8)
+ return false;
+
struct jpeg_compress_struct cinfo;
JSAMPROW row_pointer[1];
row_pointer[0] = 0;
@@ -573,19 +557,23 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in
cinfo.image_width = image.width();
cinfo.image_height = image.height();
- bool gray=false;
+ bool gray = false;
switch (image.format()) {
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
case QImage::Format_Indexed8:
gray = true;
- for (int i = image.colorCount(); gray && i--;) {
- gray = gray & (qRed(cmap[i]) == qGreen(cmap[i]) &&
- qRed(cmap[i]) == qBlue(cmap[i]));
+ for (int i = image.colorCount(); gray && i; i--) {
+ gray = gray & qIsGray(cmap[i-1]);
}
cinfo.input_components = gray ? 1 : 3;
cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB;
break;
+ case QImage::Format_Grayscale8:
+ gray = true;
+ cinfo.input_components = 1;
+ cinfo.in_color_space = JCS_GRAYSCALE;
+ break;
default:
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
@@ -607,6 +595,11 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in
cinfo.Y_density = (image.dotsPerMeterY()+50) / 100;
}
+ if (optimize)
+ cinfo.optimize_coding = true;
+
+ if (progressive)
+ jpeg_simple_progression(&cinfo);
int quality = sourceQuality >= 0 ? qMin(int(sourceQuality),100) : 75;
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
@@ -670,6 +663,9 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in
}
}
break;
+ case QImage::Format_Grayscale8:
+ memcpy(row, image.constScanLine(cinfo.next_scanline), w);
+ break;
case QImage::Format_RGB888:
memcpy(row, image.constScanLine(cinfo.next_scanline), w * 3);
break;
@@ -726,7 +722,7 @@ public:
};
QJpegHandlerPrivate(QJpegHandler *qq)
- : quality(75), exifOrientation(1), iod_src(0), state(Ready), q(qq)
+ : quality(75), exifOrientation(1), iod_src(0), state(Ready), optimize(false), progressive(false), q(qq)
{}
~QJpegHandlerPrivate()
@@ -759,6 +755,9 @@ public:
State state;
+ bool optimize;
+ bool progressive;
+
QJpegHandler *q;
};
@@ -1063,7 +1062,7 @@ bool QJpegHandler::read(QImage *image)
bool QJpegHandler::write(const QImage &image)
{
- return write_jpeg_image(image, device(), d->quality, d->description);
+ return write_jpeg_image(image, device(), d->quality, d->description, d->optimize, d->progressive);
}
bool QJpegHandler::supportsOption(ImageOption option) const
@@ -1074,7 +1073,9 @@ bool QJpegHandler::supportsOption(ImageOption option) const
|| option == ClipRect
|| option == Description
|| option == Size
- || option == ImageFormat;
+ || option == ImageFormat
+ || option == OptimizedWrite
+ || option == ProgressiveScanWrite;
}
QVariant QJpegHandler::option(ImageOption option) const
@@ -1097,6 +1098,10 @@ QVariant QJpegHandler::option(ImageOption option) const
case ImageFormat:
d->readJpegHeader(device());
return d->format;
+ case OptimizedWrite:
+ return d->optimize;
+ case ProgressiveScanWrite:
+ return d->progressive;
default:
break;
}
@@ -1122,6 +1127,12 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value)
case Description:
d->description = value.toString();
break;
+ case OptimizedWrite:
+ d->optimize = value.toBool();
+ break;
+ case ProgressiveScanWrite:
+ d->progressive = value.toBool();
+ break;
default:
break;
}