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_H |
41 | #define QIMAGE_H |
42 | |
43 | #include <QtGui/qtguiglobal.h> |
44 | #include <QtGui/qcolor.h> |
45 | #include <QtGui/qrgb.h> |
46 | #include <QtGui/qpaintdevice.h> |
47 | #include <QtGui/qpixelformat.h> |
48 | #include <QtGui/qtransform.h> |
49 | #include <QtCore/qbytearray.h> |
50 | #include <QtCore/qrect.h> |
51 | #include <QtCore/qstring.h> |
52 | |
53 | #if QT_DEPRECATED_SINCE(5, 0) |
54 | #include <QtCore/qstringlist.h> |
55 | #endif |
56 | |
57 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
58 | Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage); |
59 | #endif |
60 | |
61 | QT_BEGIN_NAMESPACE |
62 | |
63 | |
64 | class QColorSpace; |
65 | class QColorTransform; |
66 | class QIODevice; |
67 | class QMatrix; |
68 | class QStringList; |
69 | class QTransform; |
70 | class QVariant; |
71 | template <class T> class QList; |
72 | template <class T> class QVector; |
73 | |
74 | struct QImageData; |
75 | class QImageDataMisc; // internal |
76 | #if QT_DEPRECATED_SINCE(5, 0) |
77 | class QImageTextKeyLang { |
78 | public: |
79 | QT_DEPRECATED QImageTextKeyLang(const char* k, const char* l) : key(k), lang(l) { } |
80 | QT_DEPRECATED QImageTextKeyLang() { } |
81 | |
82 | QByteArray key; |
83 | QByteArray lang; |
84 | |
85 | bool operator< (const QImageTextKeyLang& other) const |
86 | { return key < other.key || (key==other.key && lang < other.lang); } |
87 | bool operator== (const QImageTextKeyLang& other) const |
88 | { return key==other.key && lang==other.lang; } |
89 | inline bool operator!= (const QImageTextKeyLang &other) const |
90 | { return !operator==(other); } |
91 | private: |
92 | friend class QImage; |
93 | QImageTextKeyLang(bool /*dummy*/) {} |
94 | }; |
95 | #endif |
96 | |
97 | typedef void (*QImageCleanupFunction)(void*); |
98 | |
99 | class Q_GUI_EXPORT QImage : public QPaintDevice |
100 | { |
101 | Q_GADGET |
102 | public: |
103 | enum InvertMode { InvertRgb, InvertRgba }; |
104 | enum Format { |
105 | Format_Invalid, |
106 | Format_Mono, |
107 | Format_MonoLSB, |
108 | Format_Indexed8, |
109 | Format_RGB32, |
110 | Format_ARGB32, |
111 | Format_ARGB32_Premultiplied, |
112 | Format_RGB16, |
113 | Format_ARGB8565_Premultiplied, |
114 | Format_RGB666, |
115 | Format_ARGB6666_Premultiplied, |
116 | Format_RGB555, |
117 | Format_ARGB8555_Premultiplied, |
118 | Format_RGB888, |
119 | Format_RGB444, |
120 | Format_ARGB4444_Premultiplied, |
121 | Format_RGBX8888, |
122 | Format_RGBA8888, |
123 | Format_RGBA8888_Premultiplied, |
124 | Format_BGR30, |
125 | Format_A2BGR30_Premultiplied, |
126 | Format_RGB30, |
127 | Format_A2RGB30_Premultiplied, |
128 | Format_Alpha8, |
129 | Format_Grayscale8, |
130 | Format_RGBX64, |
131 | Format_RGBA64, |
132 | Format_RGBA64_Premultiplied, |
133 | Format_Grayscale16, |
134 | Format_BGR888, |
135 | #ifndef Q_QDOC |
136 | NImageFormats |
137 | #endif |
138 | }; |
139 | Q_ENUM(Format) |
140 | |
141 | QImage() noexcept; |
142 | QImage(const QSize &size, Format format); |
143 | QImage(int width, int height, Format format); |
144 | QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr); |
145 | QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr); |
146 | QImage(uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr); |
147 | QImage(const uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr); |
148 | |
149 | #ifndef QT_NO_IMAGEFORMAT_XPM |
150 | explicit QImage(const char * const xpm[]); |
151 | #endif |
152 | explicit QImage(const QString &fileName, const char *format = nullptr); |
153 | |
154 | QImage(const QImage &); |
155 | inline QImage(QImage &&other) noexcept |
156 | : QPaintDevice(), d(nullptr) |
157 | { qSwap(d, other.d); } |
158 | ~QImage(); |
159 | |
160 | QImage &operator=(const QImage &); |
161 | inline QImage &operator=(QImage &&other) noexcept |
162 | { qSwap(d, other.d); return *this; } |
163 | inline void swap(QImage &other) noexcept |
164 | { qSwap(d, other.d); } |
165 | |
166 | bool isNull() const; |
167 | |
168 | int devType() const override; |
169 | |
170 | bool operator==(const QImage &) const; |
171 | bool operator!=(const QImage &) const; |
172 | operator QVariant() const; |
173 | void detach(); |
174 | bool isDetached() const; |
175 | |
176 | QImage copy(const QRect &rect = QRect()) const; |
177 | inline QImage copy(int x, int y, int w, int h) const |
178 | { return copy(QRect(x, y, w, h)); } |
179 | |
180 | Format format() const; |
181 | |
182 | #if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) |
183 | Q_REQUIRED_RESULT Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const & |
184 | { return convertToFormat_helper(f, flags); } |
185 | Q_REQUIRED_RESULT Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) && |
186 | { |
187 | if (convertToFormat_inplace(f, flags)) |
188 | return std::move(*this); |
189 | else |
190 | return convertToFormat_helper(f, flags); |
191 | } |
192 | #else |
193 | Q_REQUIRED_RESULT QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const; |
194 | #endif |
195 | Q_REQUIRED_RESULT QImage convertToFormat(Format f, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags = Qt::AutoColor) const; |
196 | bool reinterpretAsFormat(Format f); |
197 | |
198 | void convertTo(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor); |
199 | |
200 | int width() const; |
201 | int height() const; |
202 | QSize size() const; |
203 | QRect rect() const; |
204 | |
205 | int depth() const; |
206 | int colorCount() const; |
207 | int bitPlaneCount() const; |
208 | |
209 | QRgb color(int i) const; |
210 | void setColor(int i, QRgb c); |
211 | void setColorCount(int); |
212 | |
213 | bool allGray() const; |
214 | bool isGrayscale() const; |
215 | |
216 | uchar *bits(); |
217 | const uchar *bits() const; |
218 | const uchar *constBits() const; |
219 | |
220 | #if QT_DEPRECATED_SINCE(5, 10) |
221 | QT_DEPRECATED_X("Use sizeInBytes" ) int byteCount() const; |
222 | #endif |
223 | qsizetype sizeInBytes() const; |
224 | |
225 | uchar *scanLine(int); |
226 | const uchar *scanLine(int) const; |
227 | const uchar *constScanLine(int) const; |
228 | #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) |
229 | qsizetype bytesPerLine() const; |
230 | #else |
231 | int bytesPerLine() const; |
232 | #endif |
233 | |
234 | bool valid(int x, int y) const; |
235 | bool valid(const QPoint &pt) const; |
236 | |
237 | int pixelIndex(int x, int y) const; |
238 | int pixelIndex(const QPoint &pt) const; |
239 | |
240 | QRgb pixel(int x, int y) const; |
241 | QRgb pixel(const QPoint &pt) const; |
242 | |
243 | void setPixel(int x, int y, uint index_or_rgb); |
244 | void setPixel(const QPoint &pt, uint index_or_rgb); |
245 | |
246 | QColor pixelColor(int x, int y) const; |
247 | QColor pixelColor(const QPoint &pt) const; |
248 | |
249 | void setPixelColor(int x, int y, const QColor &c); |
250 | void setPixelColor(const QPoint &pt, const QColor &c); |
251 | |
252 | QVector<QRgb> colorTable() const; |
253 | #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) |
254 | void setColorTable(const QVector<QRgb> &colors); |
255 | #else |
256 | void setColorTable(const QVector<QRgb> colors); |
257 | #endif |
258 | |
259 | qreal devicePixelRatio() const; |
260 | void setDevicePixelRatio(qreal scaleFactor); |
261 | |
262 | void fill(uint pixel); |
263 | void fill(const QColor &color); |
264 | void fill(Qt::GlobalColor color); |
265 | |
266 | |
267 | bool hasAlphaChannel() const; |
268 | void setAlphaChannel(const QImage &alphaChannel); |
269 | #if QT_DEPRECATED_SINCE(5, 15) |
270 | QT_DEPRECATED_X("Use convertToFormat(QImage::Format_Alpha8)" ) |
271 | QImage alphaChannel() const; |
272 | #endif |
273 | QImage createAlphaMask(Qt::ImageConversionFlags flags = Qt::AutoColor) const; |
274 | #ifndef QT_NO_IMAGE_HEURISTIC_MASK |
275 | QImage createHeuristicMask(bool clipTight = true) const; |
276 | #endif |
277 | QImage createMaskFromColor(QRgb color, Qt::MaskMode mode = Qt::MaskInColor) const; |
278 | |
279 | inline QImage scaled(int w, int h, Qt::AspectRatioMode aspectMode = Qt::IgnoreAspectRatio, |
280 | Qt::TransformationMode mode = Qt::FastTransformation) const |
281 | { return scaled(QSize(w, h), aspectMode, mode); } |
282 | QImage scaled(const QSize &s, Qt::AspectRatioMode aspectMode = Qt::IgnoreAspectRatio, |
283 | Qt::TransformationMode mode = Qt::FastTransformation) const; |
284 | QImage scaledToWidth(int w, Qt::TransformationMode mode = Qt::FastTransformation) const; |
285 | QImage scaledToHeight(int h, Qt::TransformationMode mode = Qt::FastTransformation) const; |
286 | #if QT_DEPRECATED_SINCE(5, 15) |
287 | QT_DEPRECATED_X("Use transformed(const QTransform &matrix, Qt::TransformationMode mode)" ) |
288 | QImage transformed(const QMatrix &matrix, Qt::TransformationMode mode = Qt::FastTransformation) const; |
289 | QT_DEPRECATED_X("trueMatrix(const QTransform &, int w, int h)" ) |
290 | static QMatrix trueMatrix(const QMatrix &, int w, int h); |
291 | #endif // QT_DEPRECATED_SINCE(5, 15) |
292 | QImage transformed(const QTransform &matrix, Qt::TransformationMode mode = Qt::FastTransformation) const; |
293 | static QTransform trueMatrix(const QTransform &, int w, int h); |
294 | #if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) |
295 | QImage mirrored(bool horizontally = false, bool vertically = true) const & |
296 | { return mirrored_helper(horizontally, vertically); } |
297 | QImage &&mirrored(bool horizontally = false, bool vertically = true) && |
298 | { mirrored_inplace(horizontally, vertically); return std::move(*this); } |
299 | QImage rgbSwapped() const & |
300 | { return rgbSwapped_helper(); } |
301 | QImage &&rgbSwapped() && |
302 | { rgbSwapped_inplace(); return std::move(*this); } |
303 | #else |
304 | QImage mirrored(bool horizontally = false, bool vertically = true) const; |
305 | QImage rgbSwapped() const; |
306 | #endif |
307 | void invertPixels(InvertMode = InvertRgb); |
308 | |
309 | QColorSpace colorSpace() const; |
310 | QImage convertedToColorSpace(const QColorSpace &) const; |
311 | void convertToColorSpace(const QColorSpace &); |
312 | void setColorSpace(const QColorSpace &); |
313 | |
314 | void applyColorTransform(const QColorTransform &transform); |
315 | |
316 | bool load(QIODevice *device, const char* format); |
317 | bool load(const QString &fileName, const char *format = nullptr); |
318 | bool loadFromData(const uchar *buf, int len, const char *format = nullptr); |
319 | inline bool loadFromData(const QByteArray &data, const char *aformat = nullptr) |
320 | { return loadFromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), aformat); } |
321 | |
322 | bool save(const QString &fileName, const char *format = nullptr, int quality = -1) const; |
323 | bool save(QIODevice *device, const char *format = nullptr, int quality = -1) const; |
324 | |
325 | static QImage fromData(const uchar *data, int size, const char *format = nullptr); |
326 | inline static QImage fromData(const QByteArray &data, const char *format = nullptr) |
327 | { return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); } |
328 | |
329 | #if QT_DEPRECATED_SINCE(5, 0) |
330 | QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } |
331 | #endif |
332 | qint64 cacheKey() const; |
333 | |
334 | QPaintEngine *paintEngine() const override; |
335 | |
336 | // Auxiliary data |
337 | int dotsPerMeterX() const; |
338 | int dotsPerMeterY() const; |
339 | void setDotsPerMeterX(int); |
340 | void setDotsPerMeterY(int); |
341 | QPoint offset() const; |
342 | void setOffset(const QPoint&); |
343 | |
344 | QStringList textKeys() const; |
345 | QString text(const QString &key = QString()) const; |
346 | void setText(const QString &key, const QString &value); |
347 | |
348 | QPixelFormat pixelFormat() const noexcept; |
349 | static QPixelFormat toPixelFormat(QImage::Format format) noexcept; |
350 | static QImage::Format toImageFormat(QPixelFormat format) noexcept; |
351 | |
352 | // Platform specific conversion functions |
353 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
354 | CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED; |
355 | #endif |
356 | |
357 | #if QT_DEPRECATED_SINCE(5, 0) |
358 | QT_DEPRECATED inline QString text(const char *key, const char *lang = nullptr) const; |
359 | QT_DEPRECATED inline QList<QImageTextKeyLang> textList() const; |
360 | QT_DEPRECATED inline QStringList textLanguages() const; |
361 | QT_DEPRECATED inline QString text(const QImageTextKeyLang&) const; |
362 | QT_DEPRECATED inline void setText(const char* key, const char* lang, const QString&); |
363 | #endif |
364 | |
365 | #if QT_DEPRECATED_SINCE(5, 0) |
366 | QT_DEPRECATED inline int numColors() const; |
367 | QT_DEPRECATED inline void setNumColors(int); |
368 | QT_DEPRECATED inline int numBytes() const; |
369 | #endif |
370 | |
371 | protected: |
372 | virtual int metric(PaintDeviceMetric metric) const override; |
373 | QImage mirrored_helper(bool horizontal, bool vertical) const; |
374 | QImage rgbSwapped_helper() const; |
375 | void mirrored_inplace(bool horizontal, bool vertical); |
376 | void rgbSwapped_inplace(); |
377 | QImage convertToFormat_helper(Format format, Qt::ImageConversionFlags flags) const; |
378 | bool convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags); |
379 | QImage smoothScaled(int w, int h) const; |
380 | |
381 | private: |
382 | friend class QWSOnScreenSurface; |
383 | QImageData *d; |
384 | |
385 | friend class QRasterPlatformPixmap; |
386 | friend class QBlittablePlatformPixmap; |
387 | friend class QPixmapCacheEntry; |
388 | friend struct QImageData; |
389 | |
390 | public: |
391 | typedef QImageData * DataPtr; |
392 | inline DataPtr &data_ptr() { return d; } |
393 | }; |
394 | |
395 | Q_DECLARE_SHARED(QImage) |
396 | |
397 | // Inline functions... |
398 | |
399 | inline bool QImage::valid(const QPoint &pt) const { return valid(pt.x(), pt.y()); } |
400 | inline int QImage::pixelIndex(const QPoint &pt) const { return pixelIndex(pt.x(), pt.y());} |
401 | inline QRgb QImage::pixel(const QPoint &pt) const { return pixel(pt.x(), pt.y()); } |
402 | inline void QImage::setPixel(const QPoint &pt, uint index_or_rgb) { setPixel(pt.x(), pt.y(), index_or_rgb); } |
403 | inline QColor QImage::pixelColor(const QPoint &pt) const { return pixelColor(pt.x(), pt.y()); } |
404 | inline void QImage::setPixelColor(const QPoint &pt, const QColor &c) { setPixelColor(pt.x(), pt.y(), c); } |
405 | |
406 | #if QT_DEPRECATED_SINCE(5, 0) |
407 | |
408 | QT_WARNING_PUSH |
409 | QT_WARNING_DISABLE_DEPRECATED |
410 | |
411 | inline QString QImage::text(const char* key, const char* lang) const |
412 | { |
413 | if (!d) |
414 | return QString(); |
415 | QString k = QString::fromLatin1(key); |
416 | if (lang && *lang) |
417 | k += QLatin1Char('/') + QString::fromLatin1(lang); |
418 | return text(k); |
419 | } |
420 | |
421 | inline QList<QImageTextKeyLang> QImage::textList() const |
422 | { |
423 | QList<QImageTextKeyLang> imageTextKeys; |
424 | if (!d) |
425 | return imageTextKeys; |
426 | QStringList keys = textKeys(); |
427 | for (int i = 0; i < keys.size(); ++i) { |
428 | int index = keys.at(i).indexOf(QLatin1Char('/')); |
429 | if (index > 0) { |
430 | QImageTextKeyLang tkl(true); |
431 | tkl.key = keys.at(i).left(index).toLatin1(); |
432 | tkl.lang = keys.at(i).mid(index+1).toLatin1(); |
433 | imageTextKeys += tkl; |
434 | } |
435 | } |
436 | |
437 | return imageTextKeys; |
438 | } |
439 | |
440 | inline QStringList QImage::textLanguages() const |
441 | { |
442 | if (!d) |
443 | return QStringList(); |
444 | QStringList keys = textKeys(); |
445 | QStringList languages; |
446 | for (int i = 0; i < keys.size(); ++i) { |
447 | int index = keys.at(i).indexOf(QLatin1Char('/')); |
448 | if (index > 0) |
449 | languages += keys.at(i).mid(index+1); |
450 | } |
451 | |
452 | return languages; |
453 | } |
454 | |
455 | inline QString QImage::text(const QImageTextKeyLang&kl) const |
456 | { |
457 | if (!d) |
458 | return QString(); |
459 | QString k = QString::fromLatin1(kl.key.constData()); |
460 | if (!kl.lang.isEmpty()) |
461 | k += QLatin1Char('/') + QString::fromLatin1(kl.lang.constData()); |
462 | return text(k); |
463 | } |
464 | |
465 | inline void QImage::setText(const char* key, const char* lang, const QString &s) |
466 | { |
467 | if (!d) |
468 | return; |
469 | detach(); |
470 | |
471 | // In case detach() ran out of memory |
472 | if (!d) |
473 | return; |
474 | |
475 | QString k = QString::fromLatin1(key); |
476 | if (lang && *lang) |
477 | k += QLatin1Char('/') + QString::fromLatin1(lang); |
478 | setText(k, s); |
479 | } |
480 | |
481 | QT_WARNING_POP |
482 | |
483 | inline int QImage::numColors() const |
484 | { |
485 | return colorCount(); |
486 | } |
487 | |
488 | inline void QImage::setNumColors(int n) |
489 | { |
490 | setColorCount(n); |
491 | } |
492 | |
493 | inline int QImage::numBytes() const |
494 | { |
495 | return int(sizeInBytes()); |
496 | } |
497 | #endif |
498 | |
499 | // QImage stream functions |
500 | |
501 | #if !defined(QT_NO_DATASTREAM) |
502 | Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QImage &); |
503 | Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QImage &); |
504 | #endif |
505 | |
506 | #ifndef QT_NO_DEBUG_STREAM |
507 | Q_GUI_EXPORT QDebug operator<<(QDebug, const QImage &); |
508 | #endif |
509 | |
510 | |
511 | QT_END_NAMESPACE |
512 | |
513 | #endif // QIMAGE_H |
514 | |