summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/qgifhandler.cpp13
-rw-r--r--src/gui/image/qjpeghandler.cpp32
-rw-r--r--src/gui/image/qpixmap.cpp43
-rw-r--r--src/gui/image/qpixmap_x11.cpp3
-rw-r--r--src/gui/image/qpnghandler.cpp92
5 files changed, 107 insertions, 76 deletions
diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
index 124d27b..a050baf 100644
--- a/src/gui/image/qgifhandler.cpp
+++ b/src/gui/image/qgifhandler.cpp
@@ -505,17 +505,26 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
code=oldcode;
}
while (code>=clear_code+2) {
+ if (code >= max_code) {
+ state = Error;
+ return -1;
+ }
*sp++=table[1][code];
if (code==table[0][code]) {
state=Error;
- break;
+ return -1;
}
if (sp-stack>=(1<<(max_lzw_bits))*2) {
state=Error;
- break;
+ return -1;
}
code=table[0][code];
}
+ if (code < 0) {
+ state = Error;
+ return -1;
+ }
+
*sp++=firstcode=table[1][code];
code=max_code;
if (code<(1<<max_lzw_bits)) {
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index b9eda05..d47cc82 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -648,22 +648,28 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQ
break;
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
- case QImage::Format_ARGB32_Premultiplied: {
- const QRgb* rgb = (const QRgb*)image.constScanLine(cinfo.next_scanline);
- for (int i=0; i<w; i++) {
- *row++ = qRed(*rgb);
- *row++ = qGreen(*rgb);
- *row++ = qBlue(*rgb);
- ++rgb;
+ case QImage::Format_ARGB32_Premultiplied:
+ {
+ const QRgb* rgb = (const QRgb*)image.constScanLine(cinfo.next_scanline);
+ for (int i=0; i<w; i++) {
+ *row++ = qRed(*rgb);
+ *row++ = qGreen(*rgb);
+ *row++ = qBlue(*rgb);
+ ++rgb;
+ }
}
break;
- }
default:
- for (int i=0; i<w; i++) {
- QRgb pix = image.pixel(i, cinfo.next_scanline);
- *row++ = qRed(pix);
- *row++ = qGreen(pix);
- *row++ = qBlue(pix);
+ {
+ // (Testing shows that this way is actually faster than converting to RGB888 + memcpy)
+ QImage rowImg = image.copy(0, cinfo.next_scanline, w, 1).convertToFormat(QImage::Format_RGB32);
+ const QRgb* rgb = (const QRgb*)rowImg.constScanLine(0);
+ for (int i=0; i<w; i++) {
+ *row++ = qRed(*rgb);
+ *row++ = qGreen(*rgb);
+ *row++ = qBlue(*rgb);
+ ++rgb;
+ }
}
break;
}
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index fa00e95..5383b7c 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -664,14 +664,19 @@ void QPixmap::resize_helper(const QSize &s)
#if defined(Q_WS_X11)
if (x11Data && x11Data->x11_mask) {
- QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pd);
- pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
- RootWindow(x11Data->xinfo.display(),
- x11Data->xinfo.screen()),
- w, h, 1);
- GC gc = XCreateGC(X11->display, pmData->x11_mask, 0, 0);
- XCopyArea(X11->display, x11Data->x11_mask, pmData->x11_mask, gc, 0, 0, qMin(width(), w), qMin(height(), h), 0, 0);
- XFreeGC(X11->display, gc);
+ QPixmapData *newPd = pm.pixmapData();
+ QX11PixmapData *pmData = (newPd && newPd->classId() == QPixmapData::X11Class)
+ ? static_cast<QX11PixmapData*>(newPd) : 0;
+ if (pmData) {
+ pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
+ RootWindow(x11Data->xinfo.display(),
+ x11Data->xinfo.screen()),
+ w, h, 1);
+ GC gc = XCreateGC(X11->display, pmData->x11_mask, 0, 0);
+ XCopyArea(X11->display, x11Data->x11_mask, pmData->x11_mask, gc, 0, 0,
+ qMin(width(), w), qMin(height(), h), 0, 0);
+ XFreeGC(X11->display, gc);
+ }
}
#endif
*this = pm;
@@ -836,7 +841,7 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
% HexString<quint64>(info.size())
% HexString<uint>(data ? data->pixelType() : QPixmapData::PixmapType);
- // Note: If no extension is provided, we try to match the
+ // Note: If no extension is provided, we try to match the
// file against known plugin extensions
if (!info.completeSuffix().isEmpty() && !info.exists())
return false;
@@ -1798,13 +1803,27 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
Returns true if this pixmap has an alpha channel, \e or has a
mask, otherwise returns false.
- \warning This is potentially an expensive operation.
-
\sa hasAlphaChannel(), mask()
*/
bool QPixmap::hasAlpha() const
{
- return data && (data->hasAlphaChannel() || !data->mask().isNull());
+#if defined(Q_WS_X11)
+ if (data && data->hasAlphaChannel())
+ return true;
+ QPixmapData *pd = pixmapData();
+ if (pd && pd->classId() == QPixmapData::X11Class) {
+ QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pd);
+#ifndef QT_NO_XRENDER
+ if (x11Data->picture && x11Data->d == 32)
+ return true;
+#endif
+ if (x11Data->d == 1 || x11Data->x11_mask)
+ return true;
+ }
+ return false;
+#else
+ return data && data->hasAlphaChannel();
+#endif
}
/*!
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 9f8e643..4e4f594 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -1321,7 +1321,6 @@ QBitmap QX11PixmapData::mask() const
return mask;
}
-
/*!
Sets a mask bitmap.
@@ -1549,7 +1548,7 @@ QImage QX11PixmapData::toImage(const QRect &rect) const
if (!xiWrapper.xi)
return QImage();
- if (canTakeQImageFromXImage(xiWrapper))
+ if (!x11_mask && canTakeQImageFromXImage(xiWrapper))
return takeQImageFromXImage(xiWrapper);
QImage image = toImage(xiWrapper, rect);
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index dc54313..935aba0 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -678,41 +678,19 @@ bool QPNGImageWriter::writeImage(const QImage& image, int off_x, int off_y)
return writeImage(image, -1, QString(), off_x, off_y);
}
-bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in, int quality_in, const QString &description,
+bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, int quality_in, const QString &description,
int off_x_in, int off_y_in)
{
#ifdef QT_NO_IMAGE_TEXT
Q_UNUSED(description);
#endif
- QImage image;
- switch (image_in.format()) {
- case QImage::Format_ARGB32_Premultiplied:
- case QImage::Format_ARGB4444_Premultiplied:
- case QImage::Format_ARGB8555_Premultiplied:
- case QImage::Format_ARGB8565_Premultiplied:
- case QImage::Format_ARGB6666_Premultiplied:
- image = image_in.convertToFormat(QImage::Format_ARGB32);
- break;
- case QImage::Format_RGB16:
- case QImage::Format_RGB444:
- case QImage::Format_RGB555:
- case QImage::Format_RGB666:
- case QImage::Format_RGB888:
- image = image_in.convertToFormat(QImage::Format_RGB32);
- break;
- default:
- image = image_in;
- break;
- }
-
QPoint offset = image.offset();
int off_x = off_x_in + offset.x();
int off_y = off_y_in + offset.y();
png_structp png_ptr;
png_infop info_ptr;
- png_bytep* row_pointers;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
if (!png_ptr) {
@@ -743,13 +721,18 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
+
+ int color_type = 0;
+ if (image.colorCount())
+ color_type = PNG_COLOR_TYPE_PALETTE;
+ else if (image.hasAlphaChannel())
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ else
+ color_type = PNG_COLOR_TYPE_RGB;
+
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
- image.depth() == 1 ? 1 : 8 /* per channel */,
- image.depth() == 32
- ? image.format() == QImage::Format_RGB32
- ? PNG_COLOR_TYPE_RGB
- : PNG_COLOR_TYPE_RGB_ALPHA
- : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels
+ image.depth() == 1 ? 1 : 8, // per channel
+ color_type, 0, 0, 0); // sets #channels
if (gamma != 0.0) {
png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
@@ -794,8 +777,9 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_set_swap_alpha(png_ptr);
}
- // Qt==ARGB==Big(ARGB)==Little(BGRA)
- if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
+ && image.format() != QImage::Format_RGB888) {
png_set_bgr(png_ptr);
}
@@ -820,7 +804,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
if (image.depth() != 1)
png_set_packing(png_ptr);
- if (image.format() == QImage::Format_RGB32)
+ if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
png_set_filler(png_ptr, 0,
QSysInfo::ByteOrder == QSysInfo::BigEndian ?
PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
@@ -841,22 +825,36 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_write_chunk(png_ptr, (png_byte*)"gIFg", data, 4);
}
- png_uint_32 width;
- png_uint_32 height;
- int bit_depth;
- int color_type;
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
- 0, 0, 0);
-
- const uchar *data = (static_cast<const QImage *>(&image))->bits();
- int bpl = image.bytesPerLine();
- row_pointers = new png_bytep[height];
- uint y;
- for (y=0; y<height; y++) {
- row_pointers[y] = (png_bytep)(data + y * bpl);
+ int height = image.height();
+ int width = image.width();
+ switch (image.format()) {
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGB888:
+ {
+ png_bytep* row_pointers = new png_bytep[height];
+ for (int y=0; y<height; y++)
+ row_pointers[y] = (png_bytep)image.constScanLine(y);
+ png_write_image(png_ptr, row_pointers);
+ delete [] row_pointers;
+ }
+ break;
+ default:
+ {
+ QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
+ QImage row;
+ png_bytep row_pointers[1];
+ for (int y=0; y<height; y++) {
+ row = image.copy(0, y, width, 1).convertToFormat(fmt);
+ row_pointers[0] = png_bytep(row.constScanLine(0));
+ png_write_rows(png_ptr, row_pointers, 1);
+ }
+ }
+ break;
}
- png_write_image(png_ptr, row_pointers);
- delete [] row_pointers;
png_write_end(png_ptr, info_ptr);
frames_written++;