1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QIMAGE_P_H
41#define QIMAGE_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtGui/qcolorspace.h>
55#include <QtGui/private/qtguiglobal_p.h>
56#include <QtGui/qimage.h>
57#include <QtCore/private/qnumeric_p.h>
58
59#include <QMap>
60#include <QVector>
61
62QT_BEGIN_NAMESPACE
63
64class QImageWriter;
65
66struct Q_GUI_EXPORT QImageData { // internal image data
67 QImageData();
68 ~QImageData();
69 static QImageData *create(const QSize &size, QImage::Format format);
70 static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
71
72 QAtomicInt ref;
73
74 int width;
75 int height;
76 int depth;
77 qsizetype nbytes; // number of bytes data
78 qreal devicePixelRatio;
79 QVector<QRgb> colortable;
80 uchar *data;
81 QImage::Format format;
82 qsizetype bytes_per_line;
83 int ser_no; // serial number
84 int detach_no;
85
86 qreal dpmx; // dots per meter X (or 0)
87 qreal dpmy; // dots per meter Y (or 0)
88 QPoint offset; // offset in pixels
89
90 uint own_data : 1;
91 uint ro_data : 1;
92 uint has_alpha_clut : 1;
93 uint is_cached : 1;
94 uint is_locked : 1;
95
96 QImageCleanupFunction cleanupFunction;
97 void* cleanupInfo;
98
99 bool checkForAlphaPixels() const;
100
101 // Convert the image in-place, minimizing memory reallocation
102 // Return false if the conversion cannot be done in-place.
103 bool convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags);
104
105 QMap<QString, QString> text;
106
107 bool doImageIO(const QImage *image, QImageWriter* io, int quality) const;
108
109 QPaintEngine *paintEngine;
110
111 QColorSpace colorSpace;
112
113 struct ImageSizeParameters {
114 qsizetype bytesPerLine;
115 qsizetype totalSize;
116 bool isValid() const { return bytesPerLine > 0 && totalSize > 0; }
117 };
118 static ImageSizeParameters calculateImageParameters(qsizetype width, qsizetype height, qsizetype depth);
119};
120
121inline QImageData::ImageSizeParameters
122QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetype depth)
123{
124 ImageSizeParameters invalid = { -1, -1 };
125 if (height <= 0)
126 return invalid;
127
128 // calculate the size, taking care of overflows
129 qsizetype bytes_per_line;
130 if (mul_overflow(width, depth, &bytes_per_line))
131 return invalid;
132 if (add_overflow(bytes_per_line, qsizetype(31), &bytes_per_line))
133 return invalid;
134 // bytes per scanline (must be multiple of 4)
135 bytes_per_line = (bytes_per_line >> 5) << 2; // can't overflow
136
137 qsizetype total_size;
138 if (mul_overflow(height, bytes_per_line, &total_size))
139 return invalid;
140 qsizetype dummy;
141 if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
142 return invalid; // why is this here?
143#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
144 // Disallow images where width * depth calculations might overflow
145 if (width > (INT_MAX - 31) / depth)
146 return invalid;
147#endif
148
149 return { bytes_per_line, total_size };
150}
151
152typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
153typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags);
154
155extern Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats];
156extern InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats];
157
158void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
159void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
160bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
161
162void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
163
164const uchar *qt_get_bitflip_array();
165Q_GUI_EXPORT void qGamma_correct_back_to_linear_cs(QImage *image);
166
167#if defined(_M_ARM) // QTBUG-42038
168#pragma optimize("", off)
169#endif
170inline int qt_depthForFormat(QImage::Format format)
171{
172 int depth = 0;
173 switch(format) {
174 case QImage::Format_Invalid:
175 case QImage::NImageFormats:
176 Q_UNREACHABLE();
177 case QImage::Format_Mono:
178 case QImage::Format_MonoLSB:
179 depth = 1;
180 break;
181 case QImage::Format_Indexed8:
182 case QImage::Format_Alpha8:
183 case QImage::Format_Grayscale8:
184 depth = 8;
185 break;
186 case QImage::Format_RGB32:
187 case QImage::Format_ARGB32:
188 case QImage::Format_ARGB32_Premultiplied:
189 case QImage::Format_RGBX8888:
190 case QImage::Format_RGBA8888:
191 case QImage::Format_RGBA8888_Premultiplied:
192 case QImage::Format_BGR30:
193 case QImage::Format_A2BGR30_Premultiplied:
194 case QImage::Format_RGB30:
195 case QImage::Format_A2RGB30_Premultiplied:
196 depth = 32;
197 break;
198 case QImage::Format_RGB555:
199 case QImage::Format_RGB16:
200 case QImage::Format_RGB444:
201 case QImage::Format_ARGB4444_Premultiplied:
202 case QImage::Format_Grayscale16:
203 depth = 16;
204 break;
205 case QImage::Format_RGB666:
206 case QImage::Format_ARGB6666_Premultiplied:
207 case QImage::Format_ARGB8565_Premultiplied:
208 case QImage::Format_ARGB8555_Premultiplied:
209 case QImage::Format_RGB888:
210 depth = 24;
211 break;
212 case QImage::Format_RGBX64:
213 case QImage::Format_RGBA64:
214 case QImage::Format_RGBA64_Premultiplied:
215 depth = 64;
216 break;
217 }
218 return depth;
219}
220
221#if defined(_M_ARM)
222#pragma optimize("", on)
223#endif
224
225inline QImage::Format qt_opaqueVersion(QImage::Format format)
226{
227 switch (format) {
228 case QImage::Format_ARGB8565_Premultiplied:
229 return QImage::Format_RGB16;
230 case QImage::Format_ARGB8555_Premultiplied:
231 return QImage::Format_RGB555;
232 case QImage::Format_ARGB6666_Premultiplied:
233 return QImage::Format_RGB666;
234 case QImage::Format_ARGB4444_Premultiplied:
235 return QImage::Format_RGB444;
236 case QImage::Format_RGBA8888:
237 case QImage::Format_RGBA8888_Premultiplied:
238 return QImage::Format_RGBX8888;
239 case QImage::Format_A2BGR30_Premultiplied:
240 return QImage::Format_BGR30;
241 case QImage::Format_A2RGB30_Premultiplied:
242 return QImage::Format_RGB30;
243 case QImage::Format_RGBA64:
244 case QImage::Format_RGBA64_Premultiplied:
245 return QImage::Format_RGBX64;
246 case QImage::Format_ARGB32_Premultiplied:
247 case QImage::Format_ARGB32:
248 default:
249 return QImage::Format_RGB32;
250 }
251}
252
253inline QImage::Format qt_alphaVersion(QImage::Format format)
254{
255 switch (format) {
256 case QImage::Format_RGB16:
257 return QImage::Format_ARGB8565_Premultiplied;
258 case QImage::Format_RGB555:
259 return QImage::Format_ARGB8555_Premultiplied;
260 case QImage::Format_RGB666:
261 return QImage::Format_ARGB6666_Premultiplied;
262 case QImage::Format_RGB444:
263 return QImage::Format_ARGB4444_Premultiplied;
264 case QImage::Format_RGBX8888:
265 return QImage::Format_RGBA8888_Premultiplied;
266 case QImage::Format_BGR30:
267 return QImage::Format_A2BGR30_Premultiplied;
268 case QImage::Format_RGB30:
269 return QImage::Format_A2RGB30_Premultiplied;
270 case QImage::Format_RGBX64:
271 return QImage::Format_RGBA64_Premultiplied;
272 default:
273 break;
274 }
275 return QImage::Format_ARGB32_Premultiplied;
276}
277
278inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
279{
280 const QImage::Format toFormat = qt_alphaVersion(format);
281 return qt_depthForFormat(format) == qt_depthForFormat(toFormat) ? toFormat : format;
282}
283
284inline QImage::Format qt_opaqueVersionForPainting(QImage::Format format)
285{
286 return qt_opaqueVersion(format);
287}
288
289inline QImage::Format qt_alphaVersionForPainting(QImage::Format format)
290{
291 QImage::Format toFormat = qt_alphaVersion(format);
292#if defined(__ARM_NEON__) || defined(__SSE2__)
293 // If we are switching depth anyway and we have optimized ARGB32PM routines, upgrade to that.
294 if (qt_depthForFormat(format) != qt_depthForFormat(toFormat))
295 toFormat = QImage::Format_ARGB32_Premultiplied;
296#endif
297 return toFormat;
298}
299
300Q_GUI_EXPORT QMap<QString, QString> qt_getImageText(const QImage &image, const QString &description);
301Q_GUI_EXPORT QMap<QString, QString> qt_getImageTextFromDescription(const QString &description);
302
303QT_END_NAMESPACE
304
305#endif // QIMAGE_P_H
306