1 /*
2  * DQt - D bindings for the Qt Toolkit
3  *
4  * GNU Lesser General Public License Usage
5  * This file may be used under the terms of the GNU Lesser
6  * General Public License version 3 as published by the Free Software
7  * Foundation and appearing in the file LICENSE.LGPL3 included in the
8  * packaging of this file. Please review the following information to
9  * ensure the GNU Lesser General Public License version 3 requirements
10  * will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
11  */
12 module qt.gui.image;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.bytearray;
17 import qt.core.bytearrayview;
18 import qt.core.global;
19 import qt.core.iodevice;
20 import qt.core.list;
21 import qt.core.metamacros;
22 import qt.core.namespace;
23 import qt.core.point;
24 import qt.core.rect;
25 import qt.core.size;
26 import qt.core.string;
27 import qt.core.stringlist;
28 import qt.core.typeinfo;
29 import qt.core.variant;
30 import qt.gui.color;
31 import qt.gui.colorspace;
32 import qt.gui.colortransform;
33 import qt.gui.paintdevice;
34 import qt.gui.paintengine;
35 import qt.gui.pixelformat;
36 import qt.gui.rgb;
37 import qt.gui.transform;
38 import qt.helpers;
39 version(Cygwin){}else
40 version(Windows)
41     import qt.gui.windowdefs_win;
42 
43 /+ #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
44 Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage);
45 #endif +/
46 
47 
48 
49 
50 struct QImageData;
51 
52 alias QImageCleanupFunction = ExternCPPFunc!(void function(void*));
53 
54 /// Binding for C++ class [QImage](https://doc.qt.io/qt-6/qimage.html).
55 @Q_RELOCATABLE_TYPE extern(C++, class) struct /+ Q_GUI_EXPORT +/ QImage
56 {
57 private:
58     immutable void *vtbl;
59     QPaintDeviceFakeInheritance baseQPaintDeviceInterface;
60 
61     public QPaintDevice paintDevice() return
62     {
63         return cast(QPaintDevice)&this;
64     }
65 
66     alias PaintDeviceMetric = QPaintDevice.PaintDeviceMetric;
67 
68     mixin(Q_GADGET);
69 public:
70     enum InvertMode { InvertRgb, InvertRgba }
71     enum Format {
72         Format_Invalid,
73         Format_Mono,
74         Format_MonoLSB,
75         Format_Indexed8,
76         Format_RGB32,
77         Format_ARGB32,
78         Format_ARGB32_Premultiplied,
79         Format_RGB16,
80         Format_ARGB8565_Premultiplied,
81         Format_RGB666,
82         Format_ARGB6666_Premultiplied,
83         Format_RGB555,
84         Format_ARGB8555_Premultiplied,
85         Format_RGB888,
86         Format_RGB444,
87         Format_ARGB4444_Premultiplied,
88         Format_RGBX8888,
89         Format_RGBA8888,
90         Format_RGBA8888_Premultiplied,
91         Format_BGR30,
92         Format_A2BGR30_Premultiplied,
93         Format_RGB30,
94         Format_A2RGB30_Premultiplied,
95         Format_Alpha8,
96         Format_Grayscale8,
97         Format_RGBX64,
98         Format_RGBA64,
99         Format_RGBA64_Premultiplied,
100         Format_Grayscale16,
101         Format_BGR888,
102         Format_RGBX16FPx4,
103         Format_RGBA16FPx4,
104         Format_RGBA16FPx4_Premultiplied,
105         Format_RGBX32FPx4,
106         Format_RGBA32FPx4,
107         Format_RGBA32FPx4_Premultiplied,
108 /+ #ifndef Q_QDOC +/
109         NImageFormats
110 /+ #endif +/
111     }
112     /+ Q_ENUM(Format) +/
113 
114     @disable this();
115     pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
116     ref typeof(this) rawConstructor()/+ noexcept+/;
117     static typeof(this) create()
118     {
119         typeof(this) r = typeof(this).init;
120         r.rawConstructor();
121         return r;
122     }
123 
124     this(ref const(QSize) size, Format format);
125     this(int width, int height, Format format);
126     this(uchar* data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = null, void* cleanupInfo = null);
127     this(const(uchar)* data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = null, void* cleanupInfo = null);
128     this(uchar* data, int width, int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = null, void* cleanupInfo = null);
129     this(const(uchar)* data, int width, int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = null, void* cleanupInfo = null);
130 
131     version(QT_NO_IMAGEFORMAT_XPM){}else
132     {
133         /+ explicit +/this(const(char**) xpm);
134     }
135     /+ explicit +/this(ref const(QString) fileName, const(char)* format = null);
136 
137     @disable this(this);
138     this(ref const(QImage) );
139     /+ QImage(QImage &&other) noexcept
140         : QPaintDevice(), d(qExchange(other.d, nullptr))
141     {} +/
142     mixin(changeWindowsMangling(q{mangleChangeFunctionType("virtual")}, q{
143     ~this();
144     }));
145 
146     /+ref QImage operator =(ref const(QImage) );+/
147     /+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QImage) +/
148     /+ void swap(QImage &other) noexcept
149     { qSwap(d, other.d); } +/
150 
151     bool isNull() const;
152 
153     mixin(changeWindowsMangling(q{mangleChangeFunctionType("virtual")}, q{
154     int devType() const;
155     }));
156 
157     /+bool operator ==(ref const(QImage) ) const;+/
158     /+bool operator !=(ref const(QImage) ) const;+/
159     /+auto opCast(T : QVariant)() const;+/
160     void detach();
161     bool isDetached() const;
162 
163     /+ [[nodiscard]] QImage copy(const QRect &rect = QRect()) const; +/
164     /+ [[nodiscard]] QImage copy(int x, int y, int w, int h) const
165     { return copy(QRect(x, y, w, h)); } +/
166 
167     Format format() const;
168 
169     /+ [[nodiscard]] +/ QImage convertToFormat(Format f, /+ Qt:: +/qt.core.namespace.ImageConversionFlags flags = /+ Qt:: +/qt.core.namespace.ImageConversionFlag.AutoColor) const/+ &+/
170     { return convertToFormat_helper(f, flags); }
171     /+ [[nodiscard]] QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) &&
172     {
173         if (convertToFormat_inplace(f, flags))
174             return std::move(*this);
175         else
176             return convertToFormat_helper(f, flags);
177     } +/
178     /+ [[nodiscard]] +/ QImage convertToFormat(Format f, ref const(QList!(QRgb)) colorTable,
179                                              /+ Qt:: +/qt.core.namespace.ImageConversionFlags flags = /+ Qt:: +/qt.core.namespace.ImageConversionFlag.AutoColor) const;
180 
181     bool reinterpretAsFormat(Format f);
182     /+ [[nodiscard]] +/ QImage convertedTo(Format f, /+ Qt:: +/qt.core.namespace.ImageConversionFlags flags = /+ Qt:: +/qt.core.namespace.ImageConversionFlag.AutoColor) const/+ &+/
183     { return convertToFormat(f, flags); }
184     /+ [[nodiscard]] QImage convertedTo(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) &&
185     { return convertToFormat(f, flags); } +/
186     void convertTo(Format f, /+ Qt:: +/qt.core.namespace.ImageConversionFlags flags = /+ Qt:: +/qt.core.namespace.ImageConversionFlag.AutoColor);
187 
188     int width() const;
189     int height() const;
190     QSize size() const;
191     QRect rect() const;
192 
193     int depth() const;
194     int colorCount() const;
195     int bitPlaneCount() const;
196 
197     QRgb color(int i) const;
198     void setColor(int i, QRgb c);
199     void setColorCount(int);
200 
201     bool allGray() const;
202     bool isGrayscale() const;
203 
204     uchar* bits();
205     const(uchar)* bits() const;
206     const(uchar)* constBits() const;
207 
208     qsizetype sizeInBytes() const;
209 
210     uchar* scanLine(int);
211     const(uchar)* scanLine(int) const;
212     const(uchar)* constScanLine(int) const;
213     qsizetype bytesPerLine() const;
214 
215     bool valid(int x, int y) const;
216     pragma(inline, true) bool valid(ref const(QPoint) pt) const { return valid(pt.x(), pt.y()); }
217 
218     int pixelIndex(int x, int y) const;
219     pragma(inline, true) int pixelIndex(ref const(QPoint) pt) const { return pixelIndex(pt.x(), pt.y());}
220 
221     QRgb pixel(int x, int y) const;
222     pragma(inline, true) QRgb pixel(ref const(QPoint) pt) const { return pixel(pt.x(), pt.y()); }
223 
224     void setPixel(int x, int y, uint index_or_rgb);
225     pragma(inline, true) void setPixel(ref const(QPoint) pt, uint index_or_rgb) { setPixel(pt.x(), pt.y(), index_or_rgb); }
226 
227     QColor pixelColor(int x, int y) const;
228     pragma(inline, true) QColor pixelColor(ref const(QPoint) pt) const { return pixelColor(pt.x(), pt.y()); }
229 
230     void setPixelColor(int x, int y, ref const(QColor) c);
231     pragma(inline, true) void setPixelColor(ref const(QPoint) pt, ref const(QColor) c) { setPixelColor(pt.x(), pt.y(), c); }
232 
233     QList!(QRgb) colorTable() const;
234     void setColorTable(ref const(QList!(QRgb)) colors);
235 
236     qreal devicePixelRatio() const;
237     void setDevicePixelRatio(qreal scaleFactor);
238     QSizeF deviceIndependentSize() const;
239 
240     void fill(uint pixel);
241     void fill(ref const(QColor) color);
242     void fill(/+ Qt:: +/qt.core.namespace.GlobalColor color);
243 
244 
245     bool hasAlphaChannel() const;
246     void setAlphaChannel(ref const(QImage) alphaChannel);
247     /+ [[nodiscard]] +/ QImage createAlphaMask(/+ Qt:: +/qt.core.namespace.ImageConversionFlags flags = /+ Qt:: +/qt.core.namespace.ImageConversionFlag.AutoColor) const;
248     version(QT_NO_IMAGE_HEURISTIC_MASK){}else
249     {
250         /+ [[nodiscard]] +/ QImage createHeuristicMask(bool clipTight = true) const;
251     }
252     /+ [[nodiscard]] +/ QImage createMaskFromColor(QRgb color, /+ Qt:: +/qt.core.namespace.MaskMode mode = /+ Qt:: +/qt.core.namespace.MaskMode.MaskInColor) const;
253 
254     /+ [[nodiscard]] +/ QImage scaled(int w, int h, /+ Qt:: +/qt.core.namespace.AspectRatioMode aspectMode = /+ Qt:: +/qt.core.namespace.AspectRatioMode.IgnoreAspectRatio,
255                                     /+ Qt:: +/qt.core.namespace.TransformationMode mode = /+ Qt:: +/qt.core.namespace.TransformationMode.FastTransformation) const
256     { auto tmp = QSize(w, h); return scaled(tmp, aspectMode, mode); }
257     /+ [[nodiscard]] +/ QImage scaled(ref const(QSize) s, /+ Qt:: +/qt.core.namespace.AspectRatioMode aspectMode = /+ Qt:: +/qt.core.namespace.AspectRatioMode.IgnoreAspectRatio,
258                                     /+ Qt:: +/qt.core.namespace.TransformationMode mode = /+ Qt:: +/qt.core.namespace.TransformationMode.FastTransformation) const;
259     /+ [[nodiscard]] +/ QImage scaledToWidth(int w, /+ Qt:: +/qt.core.namespace.TransformationMode mode = /+ Qt:: +/qt.core.namespace.TransformationMode.FastTransformation) const;
260     /+ [[nodiscard]] +/ QImage scaledToHeight(int h, /+ Qt:: +/qt.core.namespace.TransformationMode mode = /+ Qt:: +/qt.core.namespace.TransformationMode.FastTransformation) const;
261     /+ [[nodiscard]] +/ QImage transformed(ref const(QTransform) matrix, /+ Qt:: +/qt.core.namespace.TransformationMode mode = /+ Qt:: +/qt.core.namespace.TransformationMode.FastTransformation) const;
262     static QTransform trueMatrix(ref const(QTransform) , int w, int h);
263 
264     /+ [[nodiscard]] +/ QImage mirrored(bool horizontally = false, bool vertically = true) const/+ &+/
265     { return mirrored_helper(horizontally, vertically); }
266     /+ [[nodiscard]] QImage mirrored(bool horizontally = false, bool vertically = true) &&
267     { mirrored_inplace(horizontally, vertically); return std::move(*this); } +/
268     /+ [[nodiscard]] +/ QImage rgbSwapped() const/+ &+/
269     { return rgbSwapped_helper(); }
270     /+ [[nodiscard]] QImage rgbSwapped() &&
271     { rgbSwapped_inplace(); return std::move(*this); } +/
272     void mirror(bool horizontally = false, bool vertically = true)
273     { mirrored_inplace(horizontally, vertically); }
274     void rgbSwap()
275     { rgbSwapped_inplace(); }
276     void invertPixels(InvertMode /+ = InvertRgb +/);
277 
278     QColorSpace colorSpace() const;
279     /+ [[nodiscard]] +/ QImage convertedToColorSpace(ref const(QColorSpace) ) const;
280     void convertToColorSpace(ref const(QColorSpace) );
281     void setColorSpace(ref const(QColorSpace) );
282 
283     void applyColorTransform(ref const(QColorTransform) transform);
284 
285     bool load(QIODevice device, const(char)* format);
286     bool load(ref const(QString) fileName, const(char)* format = null);
287     bool loadFromData(QByteArrayView data, const(char)* format = null);
288     bool loadFromData(const(uchar)* buf, int len, const(char)* format = null); // ### Qt 7: qsizetype
289     bool loadFromData(ref const(QByteArray) data, const(char)* format = null) // ### Qt 7: drop
290     { return loadFromData(QByteArrayView(data), format); }
291 
292     bool save(ref const(QString) fileName, const(char)* format = null, int quality = -1) const;
293     bool save(QIODevice device, const(char)* format = null, int quality = -1) const;
294 
295     static QImage fromData(QByteArrayView data, const(char)* format = null);
296     static QImage fromData(const(uchar)* data, int size, const(char)* format = null); // ### Qt 7: qsizetype
297     static QImage fromData(ref const(QByteArray) data, const(char)* format = null)  // ### Qt 7: drop
298     { return fromData(QByteArrayView(data), format); }
299 
300     qint64 cacheKey() const;
301 
302     mixin(changeWindowsMangling(q{mangleChangeFunctionType("virtual")}, q{
303     QPaintEngine paintEngine() const;
304     }));
305 
306     // Auxiliary data
307     int dotsPerMeterX() const;
308     int dotsPerMeterY() const;
309     void setDotsPerMeterX(int);
310     void setDotsPerMeterY(int);
311     QPoint offset() const;
312     void setOffset(ref const(QPoint));
313 
314     QStringList textKeys() const;
315     QString text(ref const(QString) key = globalInitVar!QString) const;
316     void setText(ref const(QString) key, ref const(QString) value);
317 
318     QPixelFormat pixelFormat() const/+ noexcept+/;
319     static QPixelFormat toPixelFormat(Format format)/+ noexcept+/;
320     static Format toImageFormat(QPixelFormat format)/+ noexcept+/;
321 
322     // Platform specific conversion functions
323 /+ #if defined(Q_OS_DARWIN) || defined(Q_QDOC) +/
324     static if((versionIsSet!("OSX") || versionIsSet!("iOS") || versionIsSet!("TVOS") || versionIsSet!("WatchOS")))
325     {
326         /+ CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED; +/
327     }
328 /+ #endif
329 #if defined(Q_OS_WIN) || defined(Q_QDOC) +/
330     static if((versionIsSet!("Windows") && !versionIsSet!("Cygwin")))
331     {
332         HBITMAP toHBITMAP() const;
333         HICON toHICON(ref const(QImage) mask /+ = {} +/) const;
334         static QImage fromHBITMAP(HBITMAP hbitmap);
335         static QImage fromHICON(HICON icon);
336     }
337 /+ #endif +/
338 
339 protected:
340     mixin(changeWindowsMangling(q{mangleChangeFunctionType("virtual")}, q{
341     /+ virtual +/ int metric(PaintDeviceMetric metric) const;
342     }));
343     QImage mirrored_helper(bool horizontal, bool vertical) const;
344     QImage rgbSwapped_helper() const;
345     void mirrored_inplace(bool horizontal, bool vertical);
346     void rgbSwapped_inplace();
347     QImage convertToFormat_helper(Format format, /+ Qt:: +/qt.core.namespace.ImageConversionFlags flags) const;
348     bool convertToFormat_inplace(Format format, /+ Qt:: +/qt.core.namespace.ImageConversionFlags flags);
349     QImage smoothScaled(int w, int h) const;
350 
351 private:
352     QImageData* d;
353 
354     /+ friend class QRasterPlatformPixmap; +/
355     /+ friend class QBlittablePlatformPixmap; +/
356     /+ friend class QPixmapCacheEntry; +/
357     /+ friend struct QImageData; +/
358 
359 public:
360     alias DataPtr = QImageData*;
361     pragma(inline, true) ref DataPtr data_ptr() return { return d; }
362     mixin(CREATE_CONVENIENCE_WRAPPERS);
363 }
364 
365 /+ Q_DECLARE_SHARED(QImage)
366 
367 // Inline functions...
368 
369 // QImage stream functions
370 
371 #if !defined(QT_NO_DATASTREAM)
372 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QImage &);
373 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QImage &);
374 #endif
375 
376 #ifndef QT_NO_DEBUG_STREAM
377 Q_GUI_EXPORT QDebug operator<<(QDebug, const QImage &);
378 #endif +/
379