diff options
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qbmphandler.cpp | 4 | ||||
-rw-r--r-- | src/gui/image/qicon.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qimage.cpp | 98 | ||||
-rw-r--r-- | src/gui/image/qimage.h | 16 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 337 | ||||
-rw-r--r-- | src/gui/image/qimage_p.h | 2 | ||||
-rw-r--r-- | src/gui/image/qimagereader.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qjpeghandler.cpp | 31 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 9 | ||||
-rw-r--r-- | src/gui/image/qpnghandler.cpp | 14 | ||||
-rw-r--r-- | src/gui/image/qppmhandler.cpp | 108 |
11 files changed, 480 insertions, 143 deletions
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 21c1a2f813..bf3563932d 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -791,6 +791,10 @@ bool QBmpHandler::write(const QImage &img) case QImage::Format_ARGB32: image = img; break; + case QImage::Format_Alpha8: + case QImage::Format_Grayscale8: + image = img.convertToFormat(QImage::Format_Indexed8); + break; default: if (img.hasAlphaChannel()) image = img.convertToFormat(QImage::Format_ARGB32); diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index adbd21a8a0..f1a384af3a 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1024,7 +1024,7 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State d->engine->addFile(fileName, size, mode, state); // Check if a "@2x" file exists and add it. - static bool disable2xImageLoading = !qgetenv("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING").isEmpty(); + static bool disable2xImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING"); if (!disable2xImageLoading && qApp->devicePixelRatio() > 1.0) { int dotIndex = fileName.lastIndexOf(QLatin1Char('.')); if (dotIndex != -1) { diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 4e10b4cb4b..867cb7c322 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -653,7 +653,8 @@ bool QImageData::checkForAlphaPixels() const The following image formats are available in Qt. Values from Format_ARGB8565_Premultiplied to Format_ARGB4444_Premultiplied were added in Qt 4.4. Values Format_RGBX8888, Format_RGBA8888 and Format_RGBA8888_Premultiplied were added in Qt 5.2. Values Format_BGR30, Format_A2BGR30_Premultiplied, - Format_RGB30, Format_A2RGB30_Premultiplied were added in Qt 5.4. + Format_RGB30, Format_A2RGB30_Premultiplied were added in Qt 5.4. Format_Alpha8 and Format_Grayscale8 + were added in Qt 5.5. See the notes after the table. \value Format_Invalid The image is invalid. @@ -709,6 +710,8 @@ bool QImageData::checkForAlphaPixels() const \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10). \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10). \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). + \value Format_Alpha8 The image is stored using an 8-bit alpha only format. + \value Format_Grayscale8 The image is stored using an 8-bit grayscale format. \note Drawing into a QImage with QImage::Format_Indexed8 is not supported. @@ -2352,6 +2355,10 @@ bool QImage::allGray() const return false; } return true; + case Format_Alpha8: + return false; + case Format_Grayscale8: + return true; case Format_RGB32: case Format_ARGB32: case Format_ARGB32_Premultiplied: @@ -2405,9 +2412,9 @@ bool QImage::allGray() const /*! For 32-bit images, this function is equivalent to allGray(). - For 8-bpp images, this function returns \c true if color(i) is - QRgb(i, i, i) for all indexes of the color table; otherwise - returns \c false. + For color indexed images, this function returns \c true if + color(i) is QRgb(i, i, i) for all indexes of the color table; + otherwise returns \c false. \sa allGray(), {QImage#Image Formats}{Image Formats} */ @@ -2416,12 +2423,19 @@ bool QImage::isGrayscale() const if (!d) return false; + if (d->format == QImage::Format_Alpha8) + return false; + + if (d->format == QImage::Format_Grayscale8) + return true; + switch (depth()) { case 32: case 24: case 16: return allGray(); case 8: { + Q_ASSERT(d->format == QImage::Format_Indexed8); for (int i = 0; i < colorCount(); i++) if (d->colortable.at(i) != qRgb(i,i,i)) return false; @@ -2998,6 +3012,9 @@ QImage QImage::rgbSwapped_helper() const case NImageFormats: Q_ASSERT(false); break; + case Format_Alpha8: + case Format_Grayscale8: + return *this; case Format_Mono: case Format_MonoLSB: case Format_Indexed8: @@ -3084,6 +3101,9 @@ void QImage::rgbSwapped_inplace() case NImageFormats: Q_ASSERT(false); break; + case Format_Alpha8: + case Format_Grayscale8: + return; case Format_Mono: case Format_MonoLSB: case Format_Indexed8: @@ -4017,7 +4037,7 @@ void QImage::setAlphaChannel(const QImage &alphaChannel) return; // Slight optimization since alphachannels are returned as 8-bit grays. - if (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()) { + if (alphaChannel.format() == QImage::Format_Alpha8 ||( alphaChannel.d->depth == 8 && alphaChannel.isGrayscale())) { const uchar *src_data = alphaChannel.d->data; const uchar *dest_data = d->data; for (int y=0; y<h; ++y) { @@ -4075,9 +4095,13 @@ void QImage::setAlphaChannel(const QImage &alphaChannel) Most usecases for this function can be replaced with QPainter and using composition modes. + Note this returns a color-indexed image if you want the alpha channel in + the alpha8 format instead use convertToFormat(Format_Alpha8) on the source + image. + \warning This is an expensive function. - \sa setAlphaChannel(), hasAlphaChannel(), + \sa setAlphaChannel(), hasAlphaChannel(), convertToFormat(), {QPixmap#Pixmap Information}{Pixmap}, {QImage#Image Transformations}{Image Transformations} */ @@ -4087,6 +4111,9 @@ QImage QImage::alphaChannel() const if (!d) return QImage(); + if (d->format == QImage::Format_Alpha8) + return *this; + int w = d->width; int h = d->height; @@ -4264,6 +4291,8 @@ static QImage rotated90(const QImage &image) { reinterpret_cast<quint16*>(out.bits()), out.bytesPerLine()); break; + case QImage::Format_Alpha8: + case QImage::Format_Grayscale8: case QImage::Format_Indexed8: qt_memrotate270(reinterpret_cast<const quint8*>(image.bits()), w, h, image.bytesPerLine(), @@ -4330,6 +4359,8 @@ static QImage rotated270(const QImage &image) { reinterpret_cast<quint16*>(out.bits()), out.bytesPerLine()); break; + case QImage::Format_Alpha8: + case QImage::Format_Grayscale8: case QImage::Format_Indexed8: qt_memrotate90(reinterpret_cast<const quint8*>(image.bits()), w, h, image.bytesPerLine(), @@ -4482,24 +4513,17 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode dImage.d->dpmy = dotsPerMeterY(); dImage.d->devicePixelRatio = devicePixelRatio(); - switch (bpp) { - // initizialize the data - case 8: - if (dImage.d->colortable.size() < 256) { - // colors are left in the color table, so pick that one as transparent - dImage.d->colortable.append(0x0); - memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.byteCount()); - } else { - memset(dImage.bits(), 0, dImage.byteCount()); - } - break; - case 1: - case 16: - case 24: - case 32: - memset(dImage.bits(), 0x00, dImage.byteCount()); - break; - } + // initizialize the data + if (d->format == QImage::Format_Indexed8) { + if (dImage.d->colortable.size() < 256) { + // colors are left in the color table, so pick that one as transparent + dImage.d->colortable.append(0x0); + memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.byteCount()); + } else { + memset(dImage.bits(), 0, dImage.byteCount()); + } + } else + memset(dImage.bits(), 0x00, dImage.byteCount()); if (target_format >= QImage::Format_RGB32) { QPainter p(&dImage); @@ -4935,6 +4959,32 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = { /*PREMULTIPLIED*/ QPixelFormat::Premultiplied, /*INTERPRETATION*/ QPixelFormat::UnsignedInteger, /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian), + //QImage::Format_Alpha8: + QPixelFormat(QPixelFormat::Alpha, + /*First*/ 0, + /*SECOND*/ 0, + /*THIRD*/ 0, + /*FOURTH*/ 0, + /*FIFTH*/ 0, + /*ALPHA*/ 8, + /*ALPHA USAGE*/ QPixelFormat::UsesAlpha, + /*ALPHA POSITION*/ QPixelFormat::AtBeginning, + /*PREMULTIPLIED*/ QPixelFormat::Premultiplied, + /*INTERPRETATION*/ QPixelFormat::UnsignedByte, + /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian), + //QImage::Format_Grayscale8: + QPixelFormat(QPixelFormat::Grayscale, + /*GRAY*/ 8, + /*SECOND*/ 0, + /*THIRD*/ 0, + /*FOURTH*/ 0, + /*FIFTH*/ 0, + /*ALPHA*/ 0, + /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha, + /*ALPHA POSITION*/ QPixelFormat::AtBeginning, + /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied, + /*INTERPRETATION*/ QPixelFormat::UnsignedByte, + /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian), }; Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats); diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 55b8690c77..5ba9a890d4 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -106,20 +106,16 @@ public: Format_RGBX8888, Format_RGBA8888, Format_RGBA8888_Premultiplied, -#if 0 - // reserved for future use - Format_RGB15, - Format_Grayscale16, - Format_Grayscale8, - Format_Grayscale4, - Format_Grayscale4LSB, - Format_Grayscale2, - Format_Grayscale2LSB -#endif Format_BGR30, Format_A2BGR30_Premultiplied, Format_RGB30, Format_A2RGB30_Premultiplied, + Format_Alpha8, + Format_Grayscale8, +#if 0 + // reserved for future use + Format_Grayscale16, +#endif #ifndef Q_QDOC NImageFormats #endif diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index bfa628900f..6009918521 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -1861,11 +1861,154 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt } } +static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_Indexed8); + Q_ASSERT(dest->format == QImage::Format_Alpha8); + + uchar translate[256]; + const QVector<QRgb> &colors = src->colortable; + bool simpleCase = (colors.size() == 256); + for (int i = 0; i < colors.size(); ++i) { + uchar alpha = qAlpha(colors[i]); + translate[i] = alpha; + simpleCase = simpleCase && (alpha == i); + } + + if (simpleCase) + memcpy(dest->data, src->data, src->bytes_per_line * src->height); + else { + int size = src->bytes_per_line * src->height; + for (int i = 0; i < size; ++i) { + dest->data[i] = translate[src->data[i]]; + } + } +} + +static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_Indexed8); + Q_ASSERT(dest->format == QImage::Format_Grayscale8); + + uchar translate[256]; + const QVector<QRgb> &colors = src->colortable; + bool simpleCase = (colors.size() == 256); + for (int i = 0; i < colors.size(); ++i) { + uchar gray = qGray(colors[i]); + translate[i] = gray; + simpleCase = simpleCase && (gray == i); + } + + if (simpleCase) + memcpy(dest->data, src->data, src->bytes_per_line * src->height); + else { + int size = src->bytes_per_line * src->height; + for (int i = 0; i < size; ++i) { + dest->data[i] = translate[src->data[i]]; + } + } +} + +static bool convert_Indexed8_to_Alpha8_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_Indexed8); + + // Just check if this is an Alpha8 in Indexed8 disguise. + const QVector<QRgb> &colors = data->colortable; + if (colors.size() != 256) + return false; + for (int i = 0; i < colors.size(); ++i) { + if (i != qAlpha(colors[i])) + return false; + } + + data->colortable.clear(); + data->format = QImage::Format_Alpha8; + + return true; +} + +static bool convert_Indexed8_to_Grayscale8_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_Indexed8); + + // Just check if this is a Grayscale8 in Indexed8 disguise. + const QVector<QRgb> &colors = data->colortable; + if (colors.size() != 256) + return false; + for (int i = 0; i < colors.size(); ++i) { + if (i != qGray(colors[i])) + return false; + } + + data->colortable.clear(); + data->format = QImage::Format_Grayscale8; + + return true; +} + +static void convert_Alpha8_to_Indexed8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_Alpha8); + Q_ASSERT(dest->format == QImage::Format_Indexed8); + + memcpy(dest->data, src->data, src->bytes_per_line * src->height); + + QVector<QRgb> colors(256); + for (int i=0; i<256; ++i) + colors[i] = qRgba(0, 0, 0, i); + + dest->colortable = colors; +} + +static void convert_Grayscale8_to_Indexed8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_Grayscale8); + Q_ASSERT(dest->format == QImage::Format_Indexed8); + + memcpy(dest->data, src->data, src->bytes_per_line * src->height); + + QVector<QRgb> colors(256); + for (int i=0; i<256; ++i) + colors[i] = qRgb(i, i, i); + + dest->colortable = colors; +} + +static bool convert_Alpha8_to_Indexed8_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_Alpha8); + + QVector<QRgb> colors(256); + for (int i=0; i<256; ++i) + colors[i] = qRgba(0, 0, 0, i); + + data->colortable = colors; + data->format = QImage::Format_Indexed8; + + return true; +} + +static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_Grayscale8); + + QVector<QRgb> colors(256); + for (int i=0; i<256; ++i) + colors[i] = qRgb(i, i, i); + + data->colortable = colors; + data->format = QImage::Format_Indexed8; + + return true; +} + + // first index source, second dest Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] = { { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, @@ -1886,7 +2029,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_Mono { @@ -1908,7 +2051,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_MonoLSB { @@ -1930,7 +2073,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, + convert_Indexed8_to_Alpha8, + convert_Indexed8_to_Grayscale8, }, // Format_Indexed8 { @@ -1957,6 +2102,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_RGB_to_RGB30<PixelOrderBGR>, convert_RGB_to_RGB30<PixelOrderRGB>, convert_RGB_to_RGB30<PixelOrderRGB>, + 0, 0 }, // Format_RGB32 { @@ -1983,6 +2129,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, convert_RGB_to_RGB30<PixelOrderRGB>, 0, + 0, 0 }, // Format_ARGB32 { @@ -2009,6 +2156,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_ARGB_to_A2RGB30<PixelOrderBGR>, convert_ARGB_PM_to_RGB30<PixelOrderRGB>, convert_ARGB_to_A2RGB30<PixelOrderRGB>, + 0, 0 }, // Format_ARGB32_Premultiplied { @@ -2030,7 +2178,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB16 { @@ -2052,7 +2200,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8565_Premultiplied { @@ -2074,7 +2222,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB666 { @@ -2096,7 +2244,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB6666_Premultiplied { @@ -2118,7 +2266,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB555 { @@ -2140,7 +2288,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8555_Premultiplied { @@ -2162,7 +2310,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB888 { @@ -2184,7 +2332,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB444 { @@ -2205,7 +2353,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB4444_Premultiplied { 0, @@ -2227,7 +2375,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, mask_alpha_converter_RGBx, mask_alpha_converter_RGBx, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGBX8888 { 0, @@ -2252,9 +2400,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_ARGB_to_ARGB_PM, #else 0, - 0 + 0, #endif - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888 { @@ -2281,9 +2429,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat #else 0, 0, - 0 + 0, #endif - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888_Premultiplied { @@ -2309,7 +2457,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, convert_passthrough, convert_BGR30_to_RGB30, - convert_BGR30_to_RGB30 + convert_BGR30_to_RGB30, + 0, 0 }, // Format_BGR30 { 0, @@ -2334,7 +2483,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_A2RGB30_PM_to_RGB30, 0, 0, - convert_BGR30_to_RGB30 + convert_BGR30_to_RGB30, + 0, 0 }, // Format_BGR30A2_Premultiplied { 0, @@ -2360,6 +2510,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, convert_passthrough, + 0, 0 }, // Format_RGB30 { 0, @@ -2385,19 +2536,61 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_BGR30_to_RGB30, convert_A2RGB30_PM_to_RGB30, 0, + 0, + 0, }, // Format_RGB30A2_Premultiplied + { + 0, + 0, + 0, + convert_Alpha8_to_Indexed8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, 0, 0, 0 + }, // Format_Alpha8 + { + 0, + 0, + 0, + convert_Grayscale8_to_Indexed8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, 0, 0, 0 + } // Format_Grayscale8 }; InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = { { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_Mono { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_MonoLSB { 0, @@ -2418,7 +2611,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, + convert_Indexed8_to_Alpha8_inplace, + convert_Indexed8_to_Grayscale8_inplace, }, // Format_Indexed8 { 0, @@ -2439,7 +2634,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB32 { 0, @@ -2464,7 +2659,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, convert_ARGB_to_RGBA_inplace, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB32 { 0, @@ -2486,34 +2681,34 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, convert_ARGB_to_RGBA_inplace, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_ARGB32_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB16 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8565_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB666 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB6666_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB555 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8555_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB888 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB444 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB4444_Premultiplied { 0, @@ -2535,7 +2730,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, convert_passthrough_inplace<QImage::Format_RGBA8888>, convert_passthrough_inplace<QImage::Format_RGBA8888_Premultiplied>, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGBX8888 { 0, @@ -2557,7 +2752,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888 { 0, @@ -2579,7 +2774,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888_Premultiplied { 0, @@ -2604,7 +2799,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>, convert_BGR30_to_RGB30_inplace, - convert_BGR30_to_RGB30_inplace + convert_BGR30_to_RGB30_inplace, + 0, 0 }, // Format_BGR30 { 0, @@ -2629,7 +2825,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_A2RGB30_PM_to_RGB30_inplace, 0, 0, - convert_BGR30_to_RGB30_inplace + convert_BGR30_to_RGB30_inplace, + 0, 0 }, // Format_BGR30A2_Premultiplied { 0, @@ -2654,7 +2851,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_BGR30_to_RGB30_inplace, convert_BGR30_to_RGB30_inplace, 0, - convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied> + convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>, + 0, 0 }, // Format_RGB30 { 0, @@ -2679,8 +2877,61 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, convert_BGR30_to_RGB30_inplace, convert_A2RGB30_PM_to_RGB30_inplace, - 0 + 0, + 0, 0 }, // Format_RGB30A2_Premultiplied + { + 0, + 0, + 0, + convert_Alpha8_to_Indexed8_inplace, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0 + }, // Format_Alpha8 + { + 0, + 0, + 0, + convert_Grayscale8_to_Indexed8_inplace, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0 + } // Format_Grayscale8 }; void qInitImageConversions() diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index eec54ed4eb..26c42b988e 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -128,6 +128,8 @@ inline int qt_depthForFormat(QImage::Format format) depth = 1; break; case QImage::Format_Indexed8: + case QImage::Format_Alpha8: + case QImage::Format_Grayscale8: depth = 8; break; case QImage::Format_RGB32: diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index a7a08a6fee..ad84b0a091 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1290,7 +1290,7 @@ bool QImageReader::read(QImage *image) } // successful read; check for "@2x" file name suffix and set device pixel ratio. - static bool disable2xImageLoading = !qgetenv("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING").isEmpty(); + static bool disable2xImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING"); if (!disable2xImageLoading && QFileInfo(fileName()).baseName().endsWith(QLatin1String("@2x"))) { image->setDevicePixelRatio(2.0); } diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index 481101db93..fbcc0608e2 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -220,7 +220,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 +240,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 +250,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(); } @@ -550,6 +543,9 @@ static bool write_jpeg_image(const QImage &image, QIODevice *device, volatile in 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 +569,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; @@ -670,6 +670,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; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 65e7fb0096..9c9db1c9c1 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -203,9 +203,14 @@ void QRasterPlatformPixmap::fill(const QColor &color) pixel = qPremultiply(color.rgba()); const QPixelLayout *layout = &qPixelLayouts[image.format()]; layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0); - } else { + } else if (image.format() == QImage::Format_Alpha8) { + pixel = qAlpha(color.rgba()); + } else if (image.format() == QImage::Format_Grayscale8) { + pixel = qGray(color.rgba()); + } else + { pixel = 0; - // ### what about 8 bits + // ### what about 8 bit indexed? } image.fill(pixel); diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 17a0dd3eb9..d09ed0fda7 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -295,6 +295,15 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal png_set_swap_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); + } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + png_set_expand(png_ptr); + if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale8) { + image = QImage(width, height, QImage::Format_Grayscale8); + if (image.isNull()) + return; + } + + png_read_update_info(png_ptr, info_ptr); } else { if (bit_depth == 16) png_set_strip_16(png_ptr); @@ -666,6 +675,8 @@ QImage::Format QPngHandlerPrivate::readImageFormat() format = QImage::Format_Mono; } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { format = QImage::Format_ARGB32; + } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + format = QImage::Format_Grayscale8; } else { format = QImage::Format_Indexed8; } @@ -857,6 +868,8 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo else color_type = PNG_COLOR_TYPE_PALETTE; } + else if (image.format() == QImage::Format_Grayscale8) + color_type = PNG_COLOR_TYPE_GRAY; else if (image.hasAlphaChannel()) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else @@ -955,6 +968,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo case QImage::Format_Mono: case QImage::Format_MonoLSB: case QImage::Format_Indexed8: + case QImage::Format_Grayscale8: case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_RGB888: diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 314abca9f0..e1c76cce7f 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -122,7 +122,7 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q case '2': // ascii PGM case '5': // raw PGM nbits = 8; - format = QImage::Format_Indexed8; + format = QImage::Format_Grayscale8; break; case '3': // ascii PPM case '6': // raw PPM @@ -200,13 +200,13 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q *p++ = b; } } else if (nbits == 8) { - if (mcc == maxc) { + if (mcc == 255) { while (n--) { *p++ = read_pbm_int(device); } } else { while (n--) { - *p++ = read_pbm_int(device) * maxc / mcc; + *p++ = read_pbm_int(device) * 255 / mcc; } } } else { // 32 bits @@ -233,14 +233,10 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q } } - if (nbits == 1) { // bitmap + if (format == QImage::Format_Mono) { outImage->setColorCount(2); - outImage->setColor(0, qRgb(255,255,255)); // white - outImage->setColor(1, qRgb(0,0,0)); // black - } else if (nbits == 8) { // graymap - outImage->setColorCount(maxc+1); - for (int i=0; i<=maxc; i++) - outImage->setColor(i, qRgb(i*255/maxc,i*255/maxc,i*255/maxc)); + outImage->setColor(0, qRgb(255,255,255)); // white + outImage->setColor(1, qRgb(0,0,0)); // black } return true; @@ -257,6 +253,8 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy if (format == "pbm") { image = image.convertToFormat(QImage::Format_Mono); + } else if (gray) { + image = image.convertToFormat(QImage::Format_Grayscale8); } else { switch (image.format()) { case QImage::Format_Mono: @@ -317,63 +315,77 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy str.append("255\n"); if (out->write(str, str.length()) != str.length()) return false; - QVector<QRgb> color = image.colorTable(); - uint bpl = w*(gray ? 1 : 3); - uchar *buf = new uchar[bpl]; - for (uint y=0; y<h; y++) { - uchar *b = image.scanLine(y); - uchar *p = buf; - uchar *end = buf+bpl; - if (gray) { - while (p < end) { - uchar g = (uchar)qGray(color[*b++]); - *p++ = g; + uint bpl = w * (gray ? 1 : 3); + uchar *buf = new uchar[bpl]; + if (image.format() == QImage::Format_Indexed8) { + QVector<QRgb> color = image.colorTable(); + for (uint y=0; y<h; y++) { + uchar *b = image.scanLine(y); + uchar *p = buf; + uchar *end = buf+bpl; + if (gray) { + while (p < end) { + uchar g = (uchar)qGray(color[*b++]); + *p++ = g; + } + } else { + while (p < end) { + QRgb rgb = color[*b++]; + *p++ = qRed(rgb); + *p++ = qGreen(rgb); + *p++ = qBlue(rgb); + } } - } else { - while (p < end) { - QRgb rgb = color[*b++]; - *p++ = qRed(rgb); - *p++ = qGreen(rgb); - *p++ = qBlue(rgb); + if (bpl != (uint)out->write((char*)buf, bpl)) + return false; + } + } else { + for (uint y=0; y<h; y++) { + uchar *b = image.scanLine(y); + uchar *p = buf; + uchar *end = buf + bpl; + if (gray) { + while (p < end) + *p++ = *b++; + } else { + while (p < end) { + uchar color = *b++; + *p++ = color; + *p++ = color; + *p++ = color; + } } + if (bpl != (uint)out->write((char*)buf, bpl)) + return false; } - if (bpl != (uint)out->write((char*)buf, bpl)) - return false; } delete [] buf; - } break; + } case 32: { - str.insert(1, gray ? '5' : '6'); + str.insert(1, '6'); str.append("255\n"); if (out->write(str, str.length()) != str.length()) return false; - uint bpl = w*(gray ? 1 : 3); + uint bpl = w * 3; uchar *buf = new uchar[bpl]; for (uint y=0; y<h; y++) { QRgb *b = (QRgb*)image.scanLine(y); uchar *p = buf; uchar *end = buf+bpl; - if (gray) { - while (p < end) { - uchar g = (uchar)qGray(*b++); - *p++ = g; - } - } else { - while (p < end) { - QRgb rgb = *b++; - *p++ = qRed(rgb); - *p++ = qGreen(rgb); - *p++ = qBlue(rgb); - } + while (p < end) { + QRgb rgb = *b++; + *p++ = qRed(rgb); + *p++ = qGreen(rgb); + *p++ = qBlue(rgb); } if (bpl != (uint)out->write((char*)buf, bpl)) return false; } delete [] buf; - } break; + } default: return false; @@ -488,11 +500,11 @@ QVariant QPpmHandler::option(ImageOption option) const switch (type) { case '1': // ascii PBM case '4': // raw PBM - format = QImage::Format_Mono; - break; + format = QImage::Format_Mono; + break; case '2': // ascii PGM case '5': // raw PGM - format = QImage::Format_Indexed8; + format = QImage::Format_Grayscale8; break; case '3': // ascii PPM case '6': // raw PPM |