diff options
Diffstat (limited to 'src/gui/image/qjpeghandler.cpp')
-rw-r--r-- | src/gui/image/qjpeghandler.cpp | 71 |
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; } |