summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/image.pri10
-rw-r--r--src/gui/image/qbmphandler.cpp4
-rw-r--r--src/gui/image/qicon.cpp28
-rw-r--r--src/gui/image/qicon_p.h4
-rw-r--r--src/gui/image/qiconloader.cpp29
-rw-r--r--src/gui/image/qiconloader_p.h13
-rw-r--r--src/gui/image/qimage.cpp499
-rw-r--r--src/gui/image/qimage.h11
-rw-r--r--src/gui/image/qimage_conversions.cpp615
-rw-r--r--src/gui/image/qimage_mips_dspr2.cpp20
-rw-r--r--src/gui/image/qimage_mips_dspr2_asm.S92
-rw-r--r--src/gui/image/qimage_p.h6
-rw-r--r--src/gui/image/qimageiohandler.cpp4
-rw-r--r--src/gui/image/qimageiohandler.h4
-rw-r--r--src/gui/image/qimagereader.cpp86
-rw-r--r--src/gui/image/qimagereader.h5
-rw-r--r--src/gui/image/qimagewriter.cpp85
-rw-r--r--src/gui/image/qimagewriter.h6
-rw-r--r--src/gui/image/qjpeghandler.cpp6
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/image/qpicture.h1
-rw-r--r--src/gui/image/qpixmap.cpp27
-rw-r--r--src/gui/image/qppmhandler.cpp4
-rw-r--r--src/gui/image/qxpmhandler.cpp2
24 files changed, 1421 insertions, 142 deletions
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index bbdd0f3da7..7022a6efd0 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -78,12 +78,8 @@ contains(QT_CONFIG, jpeg):include($$PWD/qjpeghandler.pri)
contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri)
# SIMD
-contains(QT_CPU_FEATURES.$$QT_ARCH, neon) {
- SOURCES += image/qimage_neon.cpp
-}
-contains(QT_CPU_FEATURES.$$QT_ARCH, sse2) {
- SOURCES += image/qimage_sse2.cpp
- SSSE3_SOURCES += image/qimage_ssse3.cpp
-}
+SSE2_SOURCES += image/qimage_sse2.cpp
+SSSE3_SOURCES += image/qimage_ssse3.cpp
+NEON_SOURCES += image/qimage_neon.cpp
MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index bb79a139b3..036d0615e3 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -798,6 +798,8 @@ bool QBmpHandler::write(const QImage &img)
case QImage::Format_ARGB4444_Premultiplied:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
image = img.convertToFormat(QImage::Format_ARGB32);
break;
case QImage::Format_RGB16:
@@ -806,6 +808,8 @@ bool QBmpHandler::write(const QImage &img)
case QImage::Format_RGB555:
case QImage::Format_RGB444:
case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
image = img.convertToFormat(QImage::Format_RGB32);
break;
default:
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 681e7e3f79..1e4a9ebe8c 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -989,10 +989,16 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
QImageWriter::supportedImageFormats() functions to retrieve a
complete list of the supported file formats.
- Note: When you add a non-empty filename to a QIcon, the icon becomes
+ If a high resolution version of the image exists (identified by
+ the suffix \c @2x on the base name), it is automatically loaded
+ and added with the \e{device pixel ratio} set to a value of 2.
+ This can be disabled by setting the environment variable
+ \c QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING (see QImageReader).
+
+ \note When you add a non-empty filename to a QIcon, the icon becomes
non-null, even if the file doesn't exist or points to a corrupt file.
- \sa addPixmap()
+ \sa addPixmap(), QPixmap::devicePixelRatio()
*/
void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State state)
{
@@ -1321,8 +1327,20 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QIcon &i)
{
- dbg.nospace() << "QIcon(" << i.name() << ')';
- return dbg.space();
+ QDebugStateSaver saver(dbg);
+ dbg.resetFormat();
+ dbg.nospace();
+ dbg << "QIcon(";
+ if (i.isNull()) {
+ dbg << "null";
+ } else {
+ if (!i.name().isEmpty())
+ dbg << i.name() << ',';
+ dbg << "availableSizes[normal,Off]=" << i.availableSizes()
+ << ",cacheKey=" << showbase << hex << i.cacheKey() << dec << noshowbase;
+ }
+ dbg << ')';
+ return dbg;
}
#endif
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index 68cd4a5452..eb94457f48 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -129,7 +129,7 @@ private:
QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state);
QVector<QPixmapIconEngineEntry> pixmaps;
- friend QDataStream &operator<<(QDataStream &s, const QIcon &icon);
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const QIcon &icon);
friend class QIconThemeEngine;
};
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 9e979023cd..5a4460dea3 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -69,7 +69,7 @@ Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
static QString fallbackTheme()
{
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
- const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconThemeName);
+ const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconFallbackThemeName);
if (themeHint.isValid())
return themeHint.toString();
}
@@ -176,7 +176,6 @@ QIconTheme::QIconTheme(const QString &themeName)
{
QFile themeIndex;
- QList <QIconDirInfo> keyList;
QStringList iconDirs = QIcon::themeSearchPaths();
for ( int i = 0 ; i < iconDirs.size() ; ++i) {
QDir iconDir(iconDirs[i]);
@@ -269,7 +268,7 @@ QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
}
QString contentDir = theme.contentDir() + QLatin1Char('/');
- QList<QIconDirInfo> subDirs = theme.keyList();
+ const QVector<QIconDirInfo> subDirs = theme.keyList();
const QString svgext(QLatin1String(".svg"));
const QString pngext(QLatin1String(".png"));
@@ -333,9 +332,7 @@ QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
QIconLoaderEngine::~QIconLoaderEngine()
{
- while (!m_entries.isEmpty())
- delete m_entries.takeLast();
- Q_ASSERT(m_entries.size() == 0);
+ qDeleteAll(m_entries);
}
QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
@@ -371,10 +368,8 @@ void QIconLoaderEngine::ensureLoaded()
{
if (!(QIconLoader::instance()->themeKey() == m_key)) {
- while (!m_entries.isEmpty())
- delete m_entries.takeLast();
+ qDeleteAll(m_entries);
- Q_ASSERT(m_entries.size() == 0);
m_entries = QIconLoader::instance()->loadIcon(m_iconName);
m_key = QIconLoader::instance()->themeKey();
}
@@ -448,8 +443,10 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
// Note that m_entries are sorted so that png-files
// come first
+ const int numEntries = m_entries.size();
+
// Search for exact matches first
- for (int i = 0; i < m_entries.count(); ++i) {
+ for (int i = 0; i < numEntries; ++i) {
QIconLoaderEngineEntry *entry = m_entries.at(i);
if (directoryMatchesSize(entry->dir, iconsize)) {
return entry;
@@ -459,7 +456,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
// Find the minimum distance icon
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = 0;
- for (int i = 0; i < m_entries.count(); ++i) {
+ for (int i = 0; i < numEntries; ++i) {
QIconLoaderEngineEntry *entry = m_entries.at(i);
int distance = directorySizeDistance(entry->dir, iconsize);
if (distance < minimalSize) {
@@ -564,14 +561,16 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
{
QIconEngine::AvailableSizesArgument &arg
= *reinterpret_cast<QIconEngine::AvailableSizesArgument*>(data);
- const QList<QIconDirInfo> directoryKey = QIconLoader::instance()->theme().keyList();
- arg.sizes.clear();
+ const int N = m_entries.size();
+ QList<QSize> sizes;
+ sizes.reserve(N);
// Gets all sizes from the DirectoryInfo entries
- for (int i = 0 ; i < m_entries.size() ; ++i) {
+ for (int i = 0; i < N; ++i) {
int size = m_entries.at(i)->dir.size;
- arg.sizes.append(QSize(size, size));
+ sizes.append(QSize(size, size));
}
+ arg.sizes.swap(sizes); // commit
}
break;
case QIconEngine::IconNameHook:
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 419d93d576..2495ff4d50 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -62,6 +62,8 @@
#include <private/qicon_p.h>
#include <private/qfactoryloader_p.h>
#include <QtCore/QHash>
+#include <QtCore/QVector>
+#include <QtCore/QTypeInfo>
QT_BEGIN_NAMESPACE
@@ -84,6 +86,7 @@ struct QIconDirInfo
short threshold;
Type type : 4;
};
+Q_DECLARE_TYPEINFO(QIconDirInfo, Q_MOVABLE_TYPE);
class QIconLoaderEngineEntry
{
@@ -99,13 +102,13 @@ public:
struct ScalableEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
QIcon svgIcon;
};
struct PixmapEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
QPixmap basePixmap;
};
@@ -144,18 +147,18 @@ public:
QIconTheme(const QString &name);
QIconTheme() : m_valid(false) {}
QStringList parents() { return m_parents; }
- QList <QIconDirInfo> keyList() { return m_keyList; }
+ QVector<QIconDirInfo> keyList() { return m_keyList; }
QString contentDir() { return m_contentDir; }
bool isValid() { return m_valid; }
private:
QString m_contentDir;
- QList <QIconDirInfo> m_keyList;
+ QVector<QIconDirInfo> m_keyList;
QStringList m_parents;
bool m_valid;
};
-class Q_GUI_EXPORT QIconLoader : public QObject
+class Q_GUI_EXPORT QIconLoader
{
public:
QIconLoader();
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 3c25aa848d..72972ff163 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -222,6 +222,16 @@ bool QImageData::checkForAlphaPixels() const
}
} break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied: {
+ uchar *bits = data;
+ for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ for (int x=0; x<width; ++x)
+ has_alpha_pixels |= (((uint *)bits)[x] & 0xc0000000) != 0xc0000000;
+ bits += bytes_per_line;
+ }
+ } break;
+
case QImage::Format_ARGB8555_Premultiplied:
case QImage::Format_ARGB8565_Premultiplied: {
uchar *bits = data;
@@ -650,7 +660,9 @@ 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. See the notes after the table.
+ 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.
+ See the notes after the table.
\value Format_Invalid The image is invalid.
\value Format_Mono The image is stored using 1-bit per pixel. Bytes are
@@ -701,6 +713,10 @@ bool QImageData::checkForAlphaPixels() const
is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
\value Format_RGBA8888_Premultiplied The image is stored using a
premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
+ \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).
\note Drawing into a QImage with QImage::Format_Indexed8 is not
supported.
@@ -708,6 +724,9 @@ bool QImageData::checkForAlphaPixels() const
\note Do not render into ARGB32 images using QPainter. Using
QImage::Format_ARGB32_Premultiplied is significantly faster.
+ \note Formats with more than 8 bit per color channel will only be processed by the raster engine using 8 bit
+ per color.
+
\sa format(), convertToFormat()
*/
@@ -778,7 +797,6 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
|| INT_MAX/sizeof(uchar *) < uint(height)
|| INT_MAX/uint(depth) < uint(width)
|| bpl <= 0
- || height <= 0
|| bpl < min_bytes_per_line
|| INT_MAX/uint(bpl) < uint(height))
return d; // invalid parameter(s)
@@ -1349,7 +1367,7 @@ void QImage::setColorTable(const QVector<QRgb> colors)
if (!d)
return;
- d->colortable = colors;
+ d->colortable = qMove(const_cast<QVector<QRgb>&>(colors));
d->has_alpha_clut = false;
for (int i = 0; i < d->colortable.size(); ++i) {
if (qAlpha(d->colortable.at(i)) != 255) {
@@ -1372,14 +1390,14 @@ QVector<QRgb> QImage::colorTable() const
/*!
Returns the device pixel ratio for the image. This is the
- ratio between image pixels and device-independent pixels.
+ ratio between \e{device pixels} and \e{device independent pixels}.
Use this function when calculating layout geometry based on
the image size: QSize layoutSize = image.size() / image.devicePixelRatio()
The default value is 1.0.
- \sa setDevicePixelRatio()
+ \sa setDevicePixelRatio(), QImageReader
*/
qreal QImage::devicePixelRatio() const
{
@@ -1404,7 +1422,8 @@ qreal QImage::devicePixelRatio() const
image size will take the ratio into account:
QSize layoutSize = image.size() / image.devicePixelRatio()
The net effect of this is that the image is displayed as
- high-dpi image rather than a large image.
+ high-DPI image rather than a large image
+ (see \l{Drawing High Resolution Versions of Pixmaps and Images}).
\sa devicePixelRatio()
*/
@@ -1670,6 +1689,8 @@ void QImage::fill(uint pixel)
#else
pixel |= 0x000000ff;
#endif
+ if (d->format == Format_BGR30 || d->format == Format_RGB30)
+ pixel |= 0xc0000000;
qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
@@ -1736,6 +1757,14 @@ void QImage::fill(const QColor &color)
case QImage::Format_RGBA8888_Premultiplied:
fill(ARGB2RGBA(qPremultiply(color.rgba())));
break;
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ fill(qConvertArgb32ToA2rgb30<PixelOrderBGR>(color.rgba()));
+ break;
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ fill(qConvertArgb32ToA2rgb30<PixelOrderRGB>(color.rgba()));
+ break;
case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba()));
break;
@@ -1779,6 +1808,9 @@ void QImage::fill(const QColor &color)
is the case for a 1-bit image. Note that the color table is \e not
changed.
+ If the image has a premultiplied alpha channel, the image is first
+ converted to ARGB32 to be inverted and then converted back.
+
\sa {QImage#Image Transformations}{Image Transformations}
*/
@@ -1793,8 +1825,15 @@ void QImage::invertPixels(InvertMode mode)
if (!d)
return;
- if (depth() != 32) {
- // number of used bytes pr line
+ QImage::Format originalFormat = d->format;
+ // Inverting premultiplied pixels would produce invalid image data.
+ if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
+ if (!d->convertInPlace(QImage::Format_ARGB32, 0))
+ *this = convertToFormat(QImage::Format_ARGB32);
+ }
+
+ if (depth() < 32) {
+ // This assumes no alpha-channel as the only formats with non-premultipled alpha are 32bit.
int bpl = (d->width * d->depth + 7) / 8;
int pad = d->bytes_per_line - bpl;
uchar *sl = d->data;
@@ -1806,10 +1845,44 @@ void QImage::invertPixels(InvertMode mode)
} else {
quint32 *p = (quint32*)d->data;
quint32 *end = (quint32*)(d->data + d->nbytes);
- uint xorbits = (mode == InvertRgba) ? 0xffffffff : 0x00ffffff;
+ quint32 xorbits = 0xffffffff;
+ switch (d->format) {
+ case QImage::Format_RGBA8888:
+ if (mode == InvertRgba)
+ break;
+ // no break
+ case QImage::Format_RGBX8888:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ xorbits = 0xffffff00;
+ break;
+#else
+ xorbits = 0x00ffffff;
+ break;
+#endif
+ case QImage::Format_ARGB32:
+ if (mode == InvertRgba)
+ break;
+ // no break
+ case QImage::Format_RGB32:
+ xorbits = 0x00ffffff;
+ break;
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ xorbits = 0x3fffffff;
+ break;
+ default:
+ Q_UNREACHABLE();
+ xorbits = 0;
+ break;
+ }
while (p < end)
*p++ ^= xorbits;
}
+
+ if (originalFormat != d->format) {
+ if (!d->convertInPlace(originalFormat, 0))
+ *this = convertToFormat(originalFormat);
+ }
}
// Windows defines these
@@ -2142,6 +2215,12 @@ QRgb QImage::pixel(int x, int y) const
case Format_RGBA8888: // Match ARGB32 behavior.
case Format_RGBA8888_Premultiplied:
return RGBA2ARGB(reinterpret_cast<const quint32 *>(s)[x]);
+ case Format_BGR30:
+ case Format_A2BGR30_Premultiplied:
+ return qConvertA2rgb30ToArgb32<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
+ case Format_RGB30:
+ case Format_A2RGB30_Premultiplied:
+ return qConvertA2rgb30ToArgb32<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
case Format_RGB16:
return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]);
default:
@@ -2232,6 +2311,18 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
case Format_RGBA8888_Premultiplied:
((uint *)s)[x] = ARGB2RGBA(index_or_rgb);
return;
+ case Format_BGR30:
+ ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderBGR>(index_or_rgb);
+ return;
+ case Format_A2BGR30_Premultiplied:
+ ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderBGR>(index_or_rgb);
+ return;
+ case Format_RGB30:
+ ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderRGB>(index_or_rgb);
+ return;
+ case Format_A2RGB30_Premultiplied:
+ ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
+ return;
case Format_Invalid:
case NImageFormats:
Q_ASSERT(false);
@@ -2961,6 +3052,23 @@ QImage QImage::rgbSwapped_helper() const
}
}
break;
+ case Format_BGR30:
+ case Format_A2BGR30_Premultiplied:
+ case Format_RGB30:
+ case Format_A2RGB30_Premultiplied:
+ res = QImage(d->width, d->height, d->format);
+ QIMAGE_SANITYCHECK_MEMORY(res);
+ for (int i = 0; i < d->height; i++) {
+ uint *q = (uint*)res.scanLine(i);
+ const uint *p = (const uint*)constScanLine(i);
+ const uint *end = p + d->width;
+ while (p < end) {
+ *q = qRgbSwapRgb30(*p);
+ p++;
+ q++;
+ }
+ }
+ break;
default:
res = QImage(d->width, d->height, d->format);
rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
@@ -3021,6 +3129,19 @@ void QImage::rgbSwapped_inplace()
}
}
break;
+ case Format_BGR30:
+ case Format_A2BGR30_Premultiplied:
+ case Format_RGB30:
+ case Format_A2RGB30_Premultiplied:
+ for (int i = 0; i < d->height; i++) {
+ uint *p = (uint*)scanLine(i);
+ uint *end = p + d->width;
+ while (p < end) {
+ *p = qRgbSwapRgb30(*p);
+ p++;
+ }
+ }
+ break;
default:
rgbSwapped_generic(d->width, d->height, this, this, &qPixelLayouts[d->format]);
break;
@@ -4046,6 +4167,8 @@ bool QImage::hasAlphaChannel() const
|| d->format == Format_ARGB4444_Premultiplied
|| d->format == Format_RGBA8888
|| d->format == Format_RGBA8888_Premultiplied
+ || d->format == Format_A2BGR30_Premultiplied
+ || d->format == Format_A2RGB30_Premultiplied
|| (d->has_alpha_clut && (d->format == Format_Indexed8
|| d->format == Format_Mono
|| d->format == Format_MonoLSB)));
@@ -4071,6 +4194,10 @@ int QImage::bitPlaneCount() const
switch (d->format) {
case QImage::Format_Invalid:
break;
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ bpc = 30;
+ break;
case QImage::Format_RGB32:
case QImage::Format_RGBX8888:
bpc = 24;
@@ -4124,6 +4251,10 @@ static QImage rotated90(const QImage &image) {
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
qt_memrotate270(reinterpret_cast<const quint32*>(image.bits()),
w, h, image.bytesPerLine(),
reinterpret_cast<quint32*>(out.bits()),
@@ -4186,6 +4317,10 @@ static QImage rotated270(const QImage &image) {
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
qt_memrotate90(reinterpret_cast<const quint32*>(image.bits()),
w, h, image.bytesPerLine(),
reinterpret_cast<quint32*>(out.bits()),
@@ -4334,6 +4469,12 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
case QImage::Format_RGBX8888:
target_format = Format_RGBA8888_Premultiplied;
break;
+ case QImage::Format_BGR30:
+ target_format = Format_A2BGR30_Premultiplied;
+ break;
+ case QImage::Format_RGB30:
+ target_format = Format_A2RGB30_Premultiplied;
+ break;
default:
target_format = Format_ARGB32_Premultiplied;
break;
@@ -4457,8 +4598,21 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QImage &i)
{
- dbg.nospace() << "QImage(" << i.size() << ')';
- return dbg.space();
+ QDebugStateSaver saver(dbg);
+ dbg.resetFormat();
+ dbg.nospace();
+ dbg << "QImage(";
+ if (i.isNull()) {
+ dbg << "null";
+ } else {
+ dbg << i.size() << ",format=" << i.format() << ",depth=" << i.depth();
+ if (i.colorCount())
+ dbg << ",colorCount=" << i.colorCount();
+ dbg << ",devicePixelRatio=" << i.devicePixelRatio()
+ << ",bytesPerLine=" << i.bytesPerLine() << ",byteCount=" << i.byteCount();
+ }
+ dbg << ')';
+ return dbg;
}
#endif
@@ -4506,4 +4660,325 @@ QDebug operator<<(QDebug dbg, const QImage &i)
\sa textKeys()
*/
+static Q_CONSTEXPR QPixelFormat pixelformats[] = {
+ //QImage::Format_Invalid:
+ QPixelFormat(),
+ //QImage::Format_Mono:
+ QPixelFormat(QPixelFormat::Grayscale,
+ /*RED*/ 1,
+ /*GREEN*/ 0,
+ /*BLUE*/ 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),
+ //QImage::Format_MonoLSB:
+ QPixelFormat(QPixelFormat::Grayscale,
+ /*RED*/ 1,
+ /*GREEN*/ 0,
+ /*BLUE*/ 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),
+ //QImage::Format_Indexed8:
+ QPixelFormat(QPixelFormat::Indexed,
+ /*RED*/ 8,
+ /*GREEN*/ 0,
+ /*BLUE*/ 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),
+ //QImage::Format_RGB32:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB32:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB32_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB16:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 6,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB8565_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 6,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB666:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 6,
+ /*GREEN*/ 6,
+ /*BLUE*/ 6,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB6666_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 6,
+ /*GREEN*/ 6,
+ /*BLUE*/ 6,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 6,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB555:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 5,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB8555_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 5,
+ /*GREEN*/ 5,
+ /*BLUE*/ 5,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB888:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB444:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 4,
+ /*GREEN*/ 4,
+ /*BLUE*/ 4,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_ARGB4444_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 4,
+ /*GREEN*/ 4,
+ /*BLUE*/ 4,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 4,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX8888:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA8888:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA8888_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 8,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_BGR30:
+ QPixelFormat(QPixelFormat::BGR,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_A2BGR30_Premultiplied:
+ QPixelFormat(QPixelFormat::BGR,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGB30:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_A2RGB30_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 10,
+ /*GREEN*/ 10,
+ /*BLUE*/ 10,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 2,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+};
+Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
+
+/*!
+ Returns the QImage::Format as a QPixelFormat
+*/
+QPixelFormat QImage::pixelFormat() const Q_DECL_NOTHROW
+{
+ return toPixelFormat(format());
+}
+
+/*!
+ Converts \a format into a QPixelFormat
+*/
+QPixelFormat QImage::toPixelFormat(QImage::Format format) Q_DECL_NOTHROW
+{
+ Q_ASSERT(static_cast<int>(format) < NImageFormats);
+ return pixelformats[format];
+}
+
+/*!
+ Converts \a format into a QImage::Format
+*/
+QImage::Format QImage::toImageFormat(QPixelFormat format) Q_DECL_NOTHROW
+{
+ for (int i = 0; i < NImageFormats; i++) {
+ if (format == pixelformats[i])
+ return Format(i);
+ }
+ return Format_Invalid;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 4326d5dbbc..3e73462efc 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -45,6 +45,7 @@
#include <QtGui/qtransform.h>
#include <QtGui/qpaintdevice.h>
#include <QtGui/qrgb.h>
+#include <QtGui/qpixelformat.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qrect.h>
#include <QtCore/qstring.h>
@@ -123,6 +124,10 @@ public:
Format_Grayscale2,
Format_Grayscale2LSB
#endif
+ Format_BGR30,
+ Format_A2BGR30_Premultiplied,
+ Format_RGB30,
+ Format_A2RGB30_Premultiplied,
#ifndef Q_QDOC
NImageFormats
#endif
@@ -227,7 +232,7 @@ public:
void setPixel(const QPoint &pt, uint index_or_rgb);
QVector<QRgb> colorTable() const;
- void setColorTable(const QVector<QRgb> colors);
+ void setColorTable(const QVector<QRgb> colors); // ### Qt 6: remove const
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
@@ -305,6 +310,10 @@ public:
QString text(const QString &key = QString()) const;
void setText(const QString &key, const QString &value);
+ QPixelFormat pixelFormat() const Q_DECL_NOTHROW;
+ static QPixelFormat toPixelFormat(QImage::Format format) Q_DECL_NOTHROW;
+ static QImage::Format toImageFormat(QPixelFormat format) Q_DECL_NOTHROW;
+
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED inline QString text(const char* key, const char* lang=0) const;
QT_DEPRECATED inline QList<QImageTextKeyLang> textList() const;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index f2f71b4bad..4fd598a6fe 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -174,6 +174,35 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
return true;
}
+static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = *src_data;
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QImage::Format Format>
+static bool convert_passthrough_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ data->format = Format;
+ return true;
+}
+
static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888);
@@ -406,6 +435,292 @@ static bool convert_RGBA_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversio
return true;
}
+template<QtPixelOrder PixelOrder>
+static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+
+ Q_ASSERT(src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32);
+ Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_A2BGR30_Premultiplied
+ || dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_A2RGB30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertRgb32ToRgb30<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_RGB30_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_BGR30 || src->format == QImage::Format_RGB30);
+ Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertA2rgb30ToArgb32<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_A2RGB30_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB32);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = 0xff000000 | qUnpremultiply(qConvertA2rgb30ToArgb32<PixelOrder>(*src_data));
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_ARGB_PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_RGB30);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertRgb32ToRgb30<PixelOrder>(qUnpremultiply(*src_data));
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_ARGB_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_A2BGR30_Premultiplied || dest->format == QImage::Format_A2RGB30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertArgb32ToA2rgb30<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_A2RGB30_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_A2BGR30_Premultiplied || src->format == QImage::Format_A2RGB30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertA2rgb30ToArgb32<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static inline uint qUnpremultiplyRgb30(uint rgb30)
+{
+ const uint a = rgb30 >> 30;
+ switch (a) {
+ case 0:
+ return 0;
+ case 1: {
+ uint rgb = rgb30 & 0x3fffffff;
+ rgb *= 3;
+ return (a << 30) | rgb;
+ }
+ case 2: {
+ uint rgb = rgb30 & 0x3fffffff;
+ rgb += rgb >> 1;
+ return (a << 30) | rgb;
+ }
+ case 3:
+ return rgb30;
+ }
+ Q_UNREACHABLE();
+ return 0;
+}
+
+static void convert_A2RGB30_PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = 0xc0000000 | qUnpremultiplyRgb30(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static bool convert_A2RGB30_PM_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 2) - data->width;
+ uint *rgb_data = (uint *) data->data;
+
+ for (int i = 0; i < data->height; ++i) {
+ const uint *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = 0xc0000000 | qUnpremultiplyRgb30(*rgb_data);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+
+ if (data->format == QImage::Format_A2RGB30_Premultiplied)
+ data->format = QImage::Format_RGB30;
+ else
+ data->format = QImage::Format_BGR30;
+ return true;
+}
+
+static void convert_BGR30_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB30 || src->format == QImage::Format_BGR30 ||
+ src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30 ||
+ dest->format == QImage::Format_A2RGB30_Premultiplied || dest->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const quint32 *src_data = (quint32 *) src->data;
+ quint32 *dest_data = (quint32 *) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint32 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qRgbSwapRgb30(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static bool convert_BGR30_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGB30 || data->format == QImage::Format_BGR30 ||
+ data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 2) - data->width;
+ uint *rgb_data = (uint *) data->data;
+
+ for (int i = 0; i < data->height; ++i) {
+ const uint *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = qRgbSwapRgb30(*rgb_data);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+
+ switch (data->format) {
+ case QImage::Format_BGR30:
+ data->format = QImage::Format_RGB30;
+ break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ data->format = QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case QImage::Format_RGB30:
+ data->format = QImage::Format_BGR30;
+ break;
+ case QImage::Format_A2RGB30_Premultiplied:
+ data->format = QImage::Format_A2BGR30_Premultiplied;
+ break;
+ default:
+ Q_UNREACHABLE();
+ data->format = QImage::Format_Invalid;
+ return false;
+ }
+ return true;
+}
+
static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
@@ -1559,7 +1874,7 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt
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,
@@ -1580,7 +1895,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_Mono
{
@@ -1602,7 +1917,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
@@ -1624,7 +1939,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_Indexed8
{
@@ -1646,7 +1961,11 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
convert_RGB_to_RGBA,
convert_RGB_to_RGBA,
- convert_RGB_to_RGBA
+ convert_RGB_to_RGBA,
+ convert_RGB_to_RGB30<PixelOrderBGR>,
+ convert_RGB_to_RGB30<PixelOrderBGR>,
+ convert_RGB_to_RGB30<PixelOrderRGB>,
+ convert_RGB_to_RGB30<PixelOrderRGB>,
}, // Format_RGB32
{
@@ -1669,6 +1988,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_to_RGBx,
convert_ARGB_to_RGBA,
convert_ARGB_to_RGBA_PM,
+ convert_RGB_to_RGB30<PixelOrderBGR>,
+ 0,
+ convert_RGB_to_RGB30<PixelOrderRGB>,
+ 0,
}, // Format_ARGB32
{
@@ -1691,6 +2014,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_PM_to_RGBx,
convert_ARGB_PM_to_RGBA,
convert_ARGB_to_RGBA,
+ convert_ARGB_PM_to_RGB30<PixelOrderBGR>,
+ convert_ARGB_to_A2RGB30<PixelOrderBGR>,
+ convert_ARGB_PM_to_RGB30<PixelOrderRGB>,
+ convert_ARGB_to_A2RGB30<PixelOrderRGB>,
}, // Format_ARGB32_Premultiplied
{
@@ -1712,7 +2039,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB16
{
@@ -1734,7 +2061,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
@@ -1756,7 +2083,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB666
{
@@ -1778,7 +2105,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
@@ -1800,7 +2127,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB555
{
@@ -1822,7 +2149,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
@@ -1844,7 +2171,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB888
{
@@ -1866,7 +2193,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_RGB444
{
@@ -1887,7 +2214,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0
+ 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -1909,6 +2236,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
mask_alpha_converter_RGBx,
mask_alpha_converter_RGBx,
+ 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -1935,6 +2263,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0
#endif
+ 0, 0, 0, 0
}, // Format_RGBA8888
{
@@ -1963,19 +2292,121 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0
#endif
- } // Format_RGBA8888_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_RGBA8888_Premultiplied
+
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGB30_to_RGB<PixelOrderBGR>,
+ convert_RGB30_to_RGB<PixelOrderBGR>,
+ convert_RGB30_to_RGB<PixelOrderBGR>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_passthrough,
+ convert_BGR30_to_RGB30,
+ convert_BGR30_to_RGB30
+ }, // Format_BGR30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB<PixelOrderBGR>,
+ 0,
+ convert_A2RGB30_to_ARGB<PixelOrderBGR>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB30,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30
+ }, // Format_BGR30A2_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGB30_to_RGB<PixelOrderRGB>,
+ convert_RGB30_to_RGB<PixelOrderRGB>,
+ convert_RGB30_to_RGB<PixelOrderRGB>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30,
+ convert_BGR30_to_RGB30,
+ 0,
+ 0,
+ convert_passthrough,
+ }, // Format_RGB30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB<PixelOrderRGB>,
+ 0,
+ convert_A2RGB30_to_ARGB<PixelOrderRGB>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30,
+ convert_A2RGB30_PM_to_RGB30,
+ 0,
+ }, // Format_RGB30A2_Premultiplied
};
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
}, // 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
}, // Format_MonoLSB
{
0,
@@ -1996,7 +2427,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
+ 0, 0, 0, 0, 0
}, // Format_Indexed8
{
0,
@@ -2017,7 +2448,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
+ 0, 0, 0, 0, 0
}, // Format_RGB32
{
0,
@@ -2042,7 +2473,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
convert_ARGB_to_RGBA_inplace,
- 0,
+ 0, 0, 0, 0, 0
}, // Format_ARGB32
{
0,
@@ -2063,34 +2494,35 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_ARGB_to_RGBA_inplace
+ convert_ARGB_to_RGBA_inplace,
+ 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
}, // 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
}, // 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
}, // 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
}, // 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
}, // 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
}, // 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
}, // 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
}, // 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
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -2110,8 +2542,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
- 0,
+ convert_passthrough_inplace<QImage::Format_RGBA8888>,
+ convert_passthrough_inplace<QImage::Format_RGBA8888_Premultiplied>,
+ 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -2133,6 +2566,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ 0, 0, 0, 0
}, // Format_RGBA8888
{
0,
@@ -2154,7 +2588,108 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- } // Format_RGBA8888_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_RGBA8888_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>,
+ convert_BGR30_to_RGB30_inplace,
+ convert_BGR30_to_RGB30_inplace
+ }, // Format_BGR30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_A2RGB30_PM_to_RGB30_inplace,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30_inplace
+ }, // Format_BGR30A2_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30_inplace,
+ convert_BGR30_to_RGB30_inplace,
+ 0,
+ convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>
+ }, // Format_RGB30
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_BGR30_to_RGB30_inplace,
+ convert_A2RGB30_PM_to_RGB30_inplace,
+ 0
+ }, // Format_RGB30A2_Premultiplied
};
void qInitImageConversions()
@@ -2176,9 +2711,15 @@ void qInitImageConversions()
#endif
#ifdef QT_COMPILER_SUPPORTS_MIPS_DSPR2
- extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
- inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
- return;
+ if (qCpuHasFeature(DSPR2)) {
+ extern bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConversionFlags);
+ qimage_inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_mips_dspr2;
+
+ extern void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_mips_dspr2;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_mips_dspr2;
+ }
#endif
}
diff --git a/src/gui/image/qimage_mips_dspr2.cpp b/src/gui/image/qimage_mips_dspr2.cpp
index a1c40a16df..f61a2262d2 100644
--- a/src/gui/image/qimage_mips_dspr2.cpp
+++ b/src/gui/image/qimage_mips_dspr2.cpp
@@ -66,4 +66,24 @@ bool convert_ARGB_to_ARGB_PM_inplace_mips_dspr2(QImageData *data, Qt::ImageConve
return true;
}
+extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(uint *dst, const uchar *src, int len);
+
+void convert_RGB888_to_RGB32_mips_dspr2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB888);
+ Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *src_data = (const uchar*) src->data;
+ quint32 *dest_data = (quint32*) dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ qt_convert_rgb888_to_rgb32_mips_dspr2_asm(dest_data, src_data, src->width);
+ src_data += src->bytes_per_line;
+ dest_data = (quint32*) ((uchar*) dest_data + dest->bytes_per_line);
+ }
+}
+
QT_END_NAMESPACE
+
diff --git a/src/gui/image/qimage_mips_dspr2_asm.S b/src/gui/image/qimage_mips_dspr2_asm.S
index 1f03b72dd4..df626586dc 100644
--- a/src/gui/image/qimage_mips_dspr2_asm.S
+++ b/src/gui/image/qimage_mips_dspr2_asm.S
@@ -205,3 +205,95 @@ LEAF_MIPS_DSPR2(premultiply_argb_inplace_mips_asm)
END(premultiply_argb_inplace_mips_asm)
+
+LEAF_MIPS_DSPR2(qt_convert_rgb888_to_rgb32_mips_dspr2_asm)
+/*
+ * Parameters:
+ * a0 - dst *a8r8g8b8
+ * a1 - src *r8g8b8
+ * a2 - len
+ *
+ * R G B r g b R G B r g b R G B r g b . . . -- input
+ * ------- ------- ------- ------- -------
+ * _ R G B _ r g b _ R G B _ r g b _ R G . . -- output
+ *
+ * Register usage:
+ * a2 - tail (len % 4) == (len & 0x3)
+ * t0 - batches (len / 4) == (len >> 2)
+ * t1-t7, s1-s3 - temporary
+ */
+
+ srl t0, a2, 2 /* batches = len / 4 */
+ andi a2, a2, 0x3 /* tail = len % 4 */
+
+ beqz t0, 5f /* if !batches: tail */
+ lui t7, 0xff00 /* [FF 00 00 00] */
+ SAVE_REGS_ON_STACK 8, s1, s2, s3, s0, v0, v1
+
+1: pref 4, 0 (a1) /* hint: read-streamed */
+ pref 5, 0 (a0) /* hint: prepare-write */
+ addiu t0, t0, -1 /* batches-- */
+
+ lbu t1, 0 (a1) /* [__ __ __ R1] */
+ lbu t2, 1 (a1) /* [__ __ __ G1] */
+ lbu t3, 2 (a1) /* [__ __ __ B1] */
+
+ lbu t4, 3 (a1) /* [__ __ __ r2] */
+ lbu t5, 4 (a1) /* [__ __ __ g2] */
+ lbu t6, 5 (a1) /* [__ __ __ b2] */
+
+ lbu s1, 6 (a1) /* [__ __ __ R3] */
+ lbu s2, 7 (a1) /* [__ __ __ G3] */
+ lbu s3, 8 (a1) /* [__ __ __ B3] */
+
+ lbu s0, 9 (a1) /* [__ __ __ r4] */
+ lbu v0, 10 (a1) /* [__ __ __ g4] */
+ lbu v1, 11 (a1) /* [__ __ __ b4] */
+
+ append t1, t2, 8 /* [__ __ R1 G1] */
+ append t4, t5, 8 /* [__ __ r2 g2] */
+ append s1, s2, 8 /* [__ __ R3 G3] */
+ append s0, v0, 8 /* [__ __ r4 g4] */
+ append t1, t3, 8 /* [__ R1 G1 B1] */
+ append t4, t6, 8 /* [__ r2 g2 b2] */
+ append s1, s3, 8 /* [__ R3 G4 B3] */
+ append s0, v1, 8 /* [__ r4 g4 b4] */
+ or t1, t1, t7 /* [FF R1 G1 B1] */
+ or t4, t4, t7 /* [FF r2 g2 b2] */
+ or s1, s1, t7 /* [FF R3 G3 B3] */
+ or s0, s0, t7 /* [FF r4 g4 b4] */
+
+ sw t1, 0 (a0)
+ sw t4, 4 (a0)
+ sw s1, 8 (a0)
+ sw s0, 12 (a0)
+
+ addiu a1, a1, 12 /* src += 4*3 */
+ bnez t0, 1b /* if batches: loop */
+ addiu a0, a0, 16 /* dst += 4 */
+
+ RESTORE_REGS_FROM_STACK 8, s1, s2, s3, s0, v0, v1
+
+ /* handle remaining "tail" (a2) items */
+5: beqz a2, 0f
+ lui t0, 0xff00 /* [FF __ __ __] */
+
+1: lbu t1, 0 (a1) /* [__ __ __ RR] */
+ lbu t2, 1 (a1) /* [__ __ __ GG] */
+ lbu t3, 2 (a1) /* [__ __ __ BB] */
+ sll t1, t1, 16 /* [__ RR __ __] */
+ sll t2, t2, 8 /* [__ __ GG __] */
+ or t0, t0, t1 /* [FF RR __ __] */
+ or t2, t2, t3 /* [__ __ GG BB] */
+ addi a2, a2, -1 /* len-- */
+ or t0, t0, t2 /* [FF RR GG BB] */
+ addiu a1, a1, 3 /* src += 3 */
+ sw t0, 0 (a0)
+ addiu a0, a0, 4 /* dst++ */
+ bnez a2, 1b /* if tail: loop */
+ lui t0, 0xff00 /* [FF __ __ __] */
+
+0: jr ra
+ nop
+
+END(qt_convert_rgb888_to_rgb32_mips_dspr2_asm)
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 81730b92f2..a22e207812 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -130,7 +130,7 @@ inline int qt_depthForFormat(QImage::Format format)
switch(format) {
case QImage::Format_Invalid:
case QImage::NImageFormats:
- Q_ASSERT(false);
+ Q_UNREACHABLE();
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
depth = 1;
@@ -144,6 +144,10 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
depth = 32;
break;
case QImage::Format_RGB555:
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index d67b22c31e..fc0a54f2d2 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -157,6 +157,10 @@
\value ImageFormat The image's data format returned by the handler.
This can be any of the formats listed in QImage::Format.
+
+ \value SupportedSubTypes Image formats that support different saving
+ variants should return a list of supported variant names
+ (QList<QByteArray>) in this option.
*/
/*!
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index 2ba99beab3..0d5a6b7b48 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -42,6 +42,7 @@
#ifndef QIMAGEIOHANDLER_H
#define QIMAGEIOHANDLER_H
+#include <QtCore/qiodevice.h>
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/qscopedpointer.h>
@@ -90,7 +91,8 @@ public:
Endianness,
Animation,
BackgroundColor,
- ImageFormat
+ ImageFormat,
+ SupportedSubTypes
};
virtual QVariant option(ImageOption option) const;
virtual void setOption(ImageOption option, const QVariant &value);
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index a10198a006..3bf002373c 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -74,17 +74,32 @@
that occurred, or errorString() to get a human readable
description of what went wrong.
+ \section1 Formats
+
Call supportedImageFormats() for a list of formats that
QImageReader can read. QImageReader supports all built-in image
formats, in addition to any image format plugins that support
- reading.
+ reading. Call supportedMimeTypes() to obtain a list of supported MIME
+ types, which for example can be passed to QFileDialog::setMimeTypeFilters().
QImageReader autodetects the image format by default, by looking at the
provided (optional) format string, the file name suffix, and the data
stream contents. You can enable or disable this feature, by calling
setAutoDetectImageFormat().
- \sa QImageWriter, QImageIOHandler, QImageIOPlugin
+ \section1 High Resolution Versions of Images
+
+ It is possible to provide high resolution versions of images should a scaling
+ between \e{device pixels} and \e{device independent pixels} be in effect.
+
+ The high resolution version is marked by the suffix \c @2x on the base name.
+ The image read will have its \e{device pixel ratio} set to a value of 2.
+
+ This can be disabled by setting the environment variable
+ \c QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING.
+
+ \sa QImageWriter, QImageIOHandler, QImageIOPlugin, QMimeDatabase
+ \sa QImage::devicePixelRatio(), QPixmap::devicePixelRatio(), QIcon, QPainter::drawPixmap(), QPainter::drawImage(), Qt::AA_UseHighDpiPixmaps
*/
/*!
@@ -125,7 +140,6 @@
#include <qimageiohandler.h>
#include <qlist.h>
#include <qrect.h>
-#include <qset.h>
#include <qsize.h>
#include <qcolor.h>
#include <qvariant.h>
@@ -568,7 +582,7 @@ bool QImageReaderPrivate::initHandler()
// check some preconditions
if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
imageReaderError = QImageReader::DeviceError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Invalid device"));
+ errorString = QImageReader::tr("Invalid device");
return false;
}
@@ -595,7 +609,7 @@ bool QImageReaderPrivate::initHandler()
if (!device->isOpen()) {
imageReaderError = QImageReader::FileNotFoundError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "File not found"));
+ errorString = QImageReader::tr("File not found");
file->setFileName(fileName); // restore the old file name
return false;
}
@@ -604,7 +618,7 @@ bool QImageReaderPrivate::initHandler()
// assign a handler
if (!handler && (handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == 0) {
imageReaderError = QImageReader::UnsupportedFormatError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unsupported image format"));
+ errorString = QImageReader::tr("Unsupported image format");
return false;
}
return true;
@@ -1101,6 +1115,36 @@ bool QImageReader::supportsAnimation() const
}
/*!
+ \since 5.4
+
+ Returns the subtype of the image.
+*/
+QByteArray QImageReader::subType() const
+{
+ if (!d->initHandler())
+ return QByteArray();
+
+ if (d->handler->supportsOption(QImageIOHandler::SubType))
+ return d->handler->option(QImageIOHandler::SubType).toByteArray();
+ return QByteArray();
+}
+
+/*!
+ \since 5.4
+
+ Returns the list of subtypes supported by an image.
+*/
+QList<QByteArray> QImageReader::supportedSubTypes() const
+{
+ if (!d->initHandler())
+ return QList<QByteArray>();
+
+ if (!d->handler->supportsOption(QImageIOHandler::SupportedSubTypes))
+ return d->handler->option(QImageIOHandler::SupportedSubTypes).value< QList<QByteArray> >();
+ return QList<QByteArray>();
+}
+
+/*!
Returns \c true if an image can be read for the device (i.e., the
image format is supported, and the device seems to contain valid
data); otherwise returns \c false.
@@ -1191,7 +1235,7 @@ bool QImageReader::read(QImage *image)
// read the image
if (!d->handler->read(image)) {
d->imageReaderError = InvalidDataError;
- d->errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unable to read image data"));
+ d->errorString = QImageReader::tr("Unable to read image data");
return false;
}
@@ -1384,7 +1428,7 @@ QImageReader::ImageReaderError QImageReader::error() const
QString QImageReader::errorString() const
{
if (d->errorString.isEmpty())
- return QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error"));
+ return QImageReader::tr("Unknown error");
return d->errorString;
}
@@ -1445,11 +1489,11 @@ QByteArray QImageReader::imageFormat(QIODevice *device)
#ifndef QT_NO_IMAGEFORMATPLUGIN
void supportedImageHandlerFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result);
+ QList<QByteArray> *result);
void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result);
+ QList<QByteArray> *result);
#endif
/*!
@@ -1482,7 +1526,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QList<QByteArray> QImageReader::supportedImageFormats()
{
- QSet<QByteArray> formats;
+ QList<QByteArray> formats;
for (int i = 0; i < _qt_NumFormats; ++i)
formats << _qt_BuiltInFormats[i].extension;
@@ -1490,12 +1534,9 @@ QList<QByteArray> QImageReader::supportedImageFormats()
supportedImageHandlerFormats(loader(), QImageIOPlugin::CanRead, &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedFormats;
- for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
- sortedFormats << *it;
-
- std::sort(sortedFormats.begin(), sortedFormats.end());
- return sortedFormats;
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
}
/*!
@@ -1509,7 +1550,7 @@ QList<QByteArray> QImageReader::supportedImageFormats()
QList<QByteArray> QImageReader::supportedMimeTypes()
{
- QSet<QByteArray> mimeTypes;
+ QList<QByteArray> mimeTypes;
for (int i = 0; i < _qt_NumFormats; ++i)
mimeTypes << _qt_BuiltInFormats[i].mimeType;
@@ -1517,12 +1558,9 @@ QList<QByteArray> QImageReader::supportedMimeTypes()
supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanRead, &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedMimeTypes;
- for (QSet<QByteArray>::ConstIterator it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
- sortedMimeTypes << *it;
-
- std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end());
- return sortedMimeTypes;
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 4f3c93af7d..fd23bc8e6c 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -43,6 +43,7 @@
#define QIMAGEREADER_H
#include <QtCore/qbytearray.h>
+#include <QtCore/qcoreapplication.h>
#include <QtGui/qimage.h>
#include <QtGui/qimageiohandler.h>
@@ -58,6 +59,7 @@ class QStringList;
class QImageReaderPrivate;
class Q_GUI_EXPORT QImageReader
{
+ Q_DECLARE_TR_FUNCTIONS(QImageReader)
public:
enum ImageReaderError {
UnknownError,
@@ -111,6 +113,9 @@ public:
bool supportsAnimation() const;
+ QByteArray subType() const;
+ QList<QByteArray> supportedSubTypes() const;
+
bool canRead() const;
QImage read();
bool read(QImage *image);
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index c12dbb6544..b31e312a76 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -259,6 +259,7 @@ public:
float gamma;
QString description;
QString text;
+ QByteArray subType;
// error
QImageWriter::ImageWriterError imageWriterError;
@@ -279,7 +280,7 @@ QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
compression = 0;
gamma = 0.0;
imageWriterError = QImageWriter::UnknownError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Unknown error"));
+ errorString = QImageWriter::tr("Unknown error");
q = qq;
}
@@ -288,19 +289,19 @@ bool QImageWriterPrivate::canWriteHelper()
{
if (!device) {
imageWriterError = QImageWriter::DeviceError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Device is not set"));
+ errorString = QImageWriter::tr("Device is not set");
return false;
}
if (!device->isOpen())
device->open(QIODevice::WriteOnly);
if (!device->isWritable()) {
imageWriterError = QImageWriter::DeviceError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Device not writable"));
+ errorString = QImageWriter::tr("Device not writable");
return false;
}
if (!handler && (handler = createWriteHandlerHelper(device, format)) == 0) {
imageWriterError = QImageWriter::UnsupportedFormatError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Unsupported image format"));
+ errorString = QImageWriter::tr("Unsupported image format");
return false;
}
return true;
@@ -518,6 +519,47 @@ float QImageWriter::gamma() const
}
/*!
+ \since 5.4
+
+ This is an image format specific function that sets the
+ subtype of the image to \a type. Subtype can be used by
+ a handler to determine which format it should use while
+ saving the image.
+
+ For example, saving an image in DDS format with A8R8G8R8 subtype:
+
+ \snippet code/src_gui_image_qimagewriter.cpp 3
+*/
+void QImageWriter::setSubType(const QByteArray &type)
+{
+ d->subType = type;
+}
+
+/*!
+ \since 5.4
+
+ Returns the subtype of the image.
+
+ \sa setSubType()
+*/
+QByteArray QImageWriter::subType() const
+{
+ return d->subType;
+}
+
+/*!
+ \since 5.4
+
+ Returns the list of subtypes supported by an image.
+*/
+QList<QByteArray> QImageWriter::supportedSubTypes() const
+{
+ if (!supportsOption(QImageIOHandler::SupportedSubTypes))
+ return QList<QByteArray>();
+ return d->handler->option(QImageIOHandler::SupportedSubTypes).value< QList<QByteArray> >();
+}
+
+/*!
\obsolete
Use setText() instead.
@@ -618,6 +660,8 @@ bool QImageWriter::write(const QImage &image)
d->handler->setOption(QImageIOHandler::Gamma, d->gamma);
if (!d->description.isEmpty() && d->handler->supportsOption(QImageIOHandler::Description))
d->handler->setOption(QImageIOHandler::Description, d->description);
+ if (!d->subType.isEmpty() && d->handler->supportsOption(QImageIOHandler::SubType))
+ d->handler->setOption(QImageIOHandler::SubType, d->subType);
if (!d->handler->write(image))
return false;
@@ -667,7 +711,7 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
{
if (!d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == 0) {
d->imageWriterError = QImageWriter::UnsupportedFormatError;
- d->errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageWriter, "Unsupported image format"));
+ d->errorString = QImageWriter::tr("Unsupported image format");
return false;
}
@@ -678,7 +722,7 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
#ifndef QT_NO_IMAGEFORMATPLUGIN
void supportedImageHandlerFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result)
+ QList<QByteArray> *result)
{
typedef QMultiMap<int, QString> PluginKeyMap;
typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
@@ -687,6 +731,7 @@ void supportedImageHandlerFormats(QFactoryLoader *loader,
const PluginKeyMapConstIterator cend = keyMap.constEnd();
int i = -1;
QImageIOPlugin *plugin = 0;
+ result->reserve(result->size() + keyMap.size());
for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) {
if (it.key() != i) {
i = it.key();
@@ -694,13 +739,13 @@ void supportedImageHandlerFormats(QFactoryLoader *loader,
}
const QByteArray key = it.value().toLatin1();
if (plugin && (plugin->capabilities(0, key) & cap) != 0)
- result->insert(key);
+ result->append(key);
}
}
void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
- QSet<QByteArray> *result)
+ QList<QByteArray> *result)
{
QList<QJsonObject> metaDataList = loader->metaData();
@@ -713,7 +758,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
const int keyCount = keys.size();
for (int k = 0; k < keyCount; ++k) {
if (plugin && (plugin->capabilities(0, keys.at(k).toString().toLatin1()) & cap) != 0)
- result->insert(mimeTypes.at(k).toString().toLatin1());
+ result->append(mimeTypes.at(k).toString().toLatin1());
}
}
}
@@ -746,7 +791,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
*/
QList<QByteArray> QImageWriter::supportedImageFormats()
{
- QSet<QByteArray> formats;
+ QList<QByteArray> formats;
#ifndef QT_NO_IMAGEFORMAT_BMP
formats << "bmp";
#endif
@@ -770,12 +815,9 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
supportedImageHandlerFormats(loader(), QImageIOPlugin::CanWrite, &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedFormats;
- for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
- sortedFormats << *it;
-
- std::sort(sortedFormats.begin(), sortedFormats.end());
- return sortedFormats;
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
}
/*!
@@ -788,7 +830,7 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
*/
QList<QByteArray> QImageWriter::supportedMimeTypes()
{
- QSet<QByteArray> mimeTypes;
+ QList<QByteArray> mimeTypes;
#ifndef QT_NO_IMAGEFORMAT_BMP
mimeTypes << "image/bmp";
#endif
@@ -814,12 +856,9 @@ QList<QByteArray> QImageWriter::supportedMimeTypes()
supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanWrite, &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
- QList<QByteArray> sortedMimeTypes;
- for (QSet<QByteArray>::ConstIterator it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
- sortedMimeTypes << *it;
-
- std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end());
- return sortedMimeTypes;
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 3f5cf9c454..ee920e6dee 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -43,6 +43,7 @@
#define QIMAGEWRITER_H
#include <QtCore/qbytearray.h>
+#include <QtCore/qcoreapplication.h>
#include <QtCore/qlist.h>
#include <QtGui/qimageiohandler.h>
@@ -55,6 +56,7 @@ class QImage;
class QImageWriterPrivate;
class Q_GUI_EXPORT QImageWriter
{
+ Q_DECLARE_TR_FUNCTIONS(QImageWriter)
public:
enum ImageWriterError {
UnknownError,
@@ -85,6 +87,10 @@ public:
void setGamma(float gamma);
float gamma() const;
+ void setSubType(const QByteArray &type);
+ QByteArray subType() const;
+ QList<QByteArray> supportedSubTypes() const;
+
// Obsolete as of 4.1
void setDescription(const QString &description);
QString description() const;
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 5008b1982b..c1d3ff9a85 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -856,6 +856,7 @@ bool QJpegHandlerPrivate::read(QImage *image)
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len);
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len);
+extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uchar *src, int len);
QJpegHandler::QJpegHandler()
: d(new QJpegHandlerPrivate(this))
@@ -874,6 +875,11 @@ QJpegHandler::QJpegHandler()
rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_ssse3;
}
#endif // QT_COMPILER_SUPPORTS_SSSE3
+#if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
+ if (qCpuHasFeature(DSPR2)) {
+ rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_mips_dspr2_asm;
+ }
+#endif // QT_COMPILER_SUPPORTS_DSPR2
}
QJpegHandler::~QJpegHandler()
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index ec89b405b5..807746a26e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -118,7 +118,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
*/
const char *qt_mfhdr_tag = "QPIC"; // header tag
-static const quint16 mfhdr_maj = 11; // major version #
+static const quint16 mfhdr_maj = QDataStream::Qt_DefaultCompiledVersion; // major version #
static const quint16 mfhdr_min = 0; // minor version #
/*!
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 08445a3143..6420c1bb6f 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -42,6 +42,7 @@
#ifndef QPICTURE_H
#define QPICTURE_H
+#include <QtCore/qiodevice.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qsharedpointer.h>
#include <QtGui/qpaintdevice.h>
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index c6d8d19bb1..88ce48f0e8 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -648,14 +648,14 @@ void QPixmap::setMask(const QBitmap &mask)
/*!
Returns the device pixel ratio for the pixmap. This is the
- ratio between pixmap pixels and device-independent pixels.
+ ratio between \e{device pixels} and \e{device independent pixels}.
Use this function when calculating layout geometry based on
the pixmap size: QSize layoutSize = image.size() / image.devicePixelRatio()
The default value is 1.0.
- \sa setDevicePixelRatio()
+ \sa setDevicePixelRatio(), QImageReader
*/
qreal QPixmap::devicePixelRatio() const
{
@@ -680,7 +680,8 @@ qreal QPixmap::devicePixelRatio() const
pixmap size will take the ratio into account:
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio()
The net effect of this is that the pixmap is displayed as
- high-dpi pixmap rather than a large pixmap.
+ high-DPI pixmap rather than a large pixmap
+ (see \l{Drawing High Resolution Versions of Pixmaps and Images}).
\sa devicePixelRatio()
*/
@@ -1511,7 +1512,8 @@ QBitmap QPixmap::mask() const
return QBitmap();
const QImage img = toImage();
- const QImage image = (img.depth() < 32 ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
+ bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
+ const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
const int w = image.width();
const int h = image.height();
@@ -1723,8 +1725,19 @@ QPlatformPixmap* QPixmap::handle() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPixmap &r)
{
- dbg.nospace() << "QPixmap(" << r.size() << ')';
- return dbg.space();
+ QDebugStateSaver saver(dbg);
+ dbg.resetFormat();
+ dbg.nospace();
+ dbg << "QPixmap(";
+ if (r.isNull()) {
+ dbg << "null";
+ } else {
+ dbg << r.size() << ",depth=" << r.depth()
+ << ",devicePixelRatio=" << r.devicePixelRatio()
+ << ",cacheKey=" << showbase << hex << r.cacheKey() << dec << noshowbase;
+ }
+ dbg << ')';
+ return dbg;
}
#endif
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 39f63a620c..64eaf7f19e 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -275,6 +275,8 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case QImage::Format_RGB888:
case QImage::Format_RGB444:
case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
image = image.convertToFormat(QImage::Format_RGB32);
break;
case QImage::Format_ARGB8565_Premultiplied:
@@ -283,6 +285,8 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case QImage::Format_ARGB4444_Premultiplied:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
image = image.convertToFormat(QImage::Format_ARGB32);
break;
default:
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 5edb866b62..ca87951dbb 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1094,7 +1094,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
return false;
QImage image;
- if (sourceImage.format() != QImage::Format_RGB32 || sourceImage.format() != QImage::Format_ARGB32 || sourceImage.format() != QImage::Format_ARGB32_Premultiplied)
+ if (sourceImage.format() != QImage::Format_RGB32 && sourceImage.format() != QImage::Format_ARGB32 && sourceImage.format() != QImage::Format_ARGB32_Premultiplied)
image = sourceImage.convertToFormat(QImage::Format_RGB32);
else
image = sourceImage;