From 12a382e3bc75192a11145ef5cf29ef1baf377dc9 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 13 Sep 2017 12:46:44 +0200 Subject: Fix saving QImage with longer than necessary bytes-per-line We should only copy the minimum bytes-per-line when saving an image. Task-number: QTBUG-30515 Change-Id: Idd34a389cf88210c3f127599ccf54d27d3ec9a06 Reviewed-by: Eirik Aavitsland --- src/gui/image/qbmphandler.cpp | 55 +++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 33 deletions(-) (limited to 'src/gui/image/qbmphandler.cpp') diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 4350a5c192..703c5c0f31 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -562,27 +562,12 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, } // this is also used in qmime_win.cpp -bool qt_write_dib(QDataStream &s, QImage image) +bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int nbits) { - int nbits; - int bpl_bmp; - int bpl = image.bytesPerLine(); - QIODevice* d = s.device(); if (!d->isWritable()) return false; - if (image.depth() == 8 && image.colorCount() <= 16) { - bpl_bmp = (((bpl+1)/2+3)/4)*4; - nbits = 4; - } else if (image.depth() == 32) { - bpl_bmp = ((image.width()*24+31)/32)*4; - nbits = 24; - } else { - bpl_bmp = bpl; - nbits = image.depth(); - } - BMP_INFOHDR bi; bi.biSize = BMP_WIN; // build info header bi.biWidth = image.width(); @@ -617,9 +602,6 @@ bool qt_write_dib(QDataStream &s, QImage image) delete [] color_table; } - if (image.format() == QImage::Format_MonoLSB) - image = image.convertToFormat(QImage::Format_Mono); - int y; if (nbits == 1 || nbits == 8) { // direct output @@ -769,21 +751,17 @@ bool QBmpHandler::read(QImage *image) bool QBmpHandler::write(const QImage &img) { - if (m_format == DibFormat) { - QDataStream dibStream(device()); - dibStream.setByteOrder(QDataStream::LittleEndian); // Intel byte order - return qt_write_dib(dibStream, img); - } - QImage image; switch (img.format()) { case QImage::Format_Mono: - case QImage::Format_MonoLSB: case QImage::Format_Indexed8: case QImage::Format_RGB32: case QImage::Format_ARGB32: image = img; break; + case QImage::Format_MonoLSB: + image = img.convertToFormat(QImage::Format_Mono); + break; case QImage::Format_Alpha8: case QImage::Format_Grayscale8: image = img.convertToFormat(QImage::Format_Indexed8); @@ -796,21 +774,32 @@ bool QBmpHandler::write(const QImage &img) break; } - QIODevice *d = device(); - QDataStream s(d); - BMP_FILEHDR bf; + int nbits; int bpl_bmp; - int bpl = image.bytesPerLine(); + // Calculate a minimum bytes-per-line instead of using whatever value this QImage is using internally. + int bpl = ((image.width() * image.depth() + 31) >> 5) << 2; - // Code partially repeated in qt_write_dib if (image.depth() == 8 && image.colorCount() <= 16) { bpl_bmp = (((bpl+1)/2+3)/4)*4; - } else if (image.depth() == 32) { + nbits = 4; + } else if (image.depth() == 32) { bpl_bmp = ((image.width()*24+31)/32)*4; + nbits = 24; } else { bpl_bmp = bpl; + nbits = image.depth(); } + if (m_format == DibFormat) { + QDataStream dibStream(device()); + dibStream.setByteOrder(QDataStream::LittleEndian); // Intel byte order + return qt_write_dib(dibStream, img, bpl, bpl_bmp, nbits); + } + + QIODevice *d = device(); + QDataStream s(d); + BMP_FILEHDR bf; + // Intel byte order s.setByteOrder(QDataStream::LittleEndian); @@ -825,7 +814,7 @@ bool QBmpHandler::write(const QImage &img) s << bf; // write image - return qt_write_dib(s, image); + return qt_write_dib(s, image, bpl, bpl_bmp, nbits); } bool QBmpHandler::supportsOption(ImageOption option) const -- cgit v1.2.3