/src/qtbase/src/gui/image/qbitmap.cpp
Line | Count | Source |
1 | | // Copyright (C) 2016 The Qt Company Ltd. |
2 | | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | | // Qt-Security score:critical reason:data-parser |
4 | | |
5 | | #include "qbitmap.h" |
6 | | #include <qpa/qplatformpixmap.h> |
7 | | #include <qpa/qplatformintegration.h> |
8 | | #include "qimage.h" |
9 | | #include "qscreen.h" |
10 | | #include "qvariant.h" |
11 | | #include <qpainter.h> |
12 | | #include <private/qguiapplication_p.h> |
13 | | |
14 | | #include <memory> |
15 | | |
16 | | QT_BEGIN_NAMESPACE |
17 | | |
18 | | /*! |
19 | | \class QBitmap |
20 | | \inmodule QtGui |
21 | | \brief The QBitmap class provides monochrome (1-bit depth) pixmaps. |
22 | | |
23 | | \ingroup painting |
24 | | \ingroup shared |
25 | | |
26 | | The QBitmap class is a monochrome off-screen paint device used |
27 | | mainly for creating custom QCursor and QBrush objects, |
28 | | constructing QRegion objects, and for setting masks for pixmaps |
29 | | and widgets. |
30 | | |
31 | | QBitmap is a QPixmap subclass ensuring a depth of 1, except for |
32 | | null objects which have a depth of 0. If a pixmap with a depth |
33 | | greater than 1 is assigned to a bitmap, the bitmap will be |
34 | | dithered automatically. |
35 | | |
36 | | Use the QColor objects Qt::color0 and Qt::color1 when drawing on a |
37 | | QBitmap object (or a QPixmap object with depth 1). |
38 | | |
39 | | Painting with Qt::color0 sets the bitmap bits to 0, and painting |
40 | | with Qt::color1 sets the bits to 1. For a bitmap, 0-bits indicate |
41 | | background (or transparent pixels) and 1-bits indicate foreground |
42 | | (or opaque pixels). Use the clear() function to set all the bits |
43 | | to Qt::color0. Note that using the Qt::black and Qt::white colors |
44 | | make no sense because the QColor::pixel() value is not necessarily |
45 | | 0 for black and 1 for white. |
46 | | |
47 | | The QBitmap class provides the transformed() function returning a |
48 | | transformed copy of the bitmap; use the QTransform argument to |
49 | | translate, scale, shear, and rotate the bitmap. In addition, |
50 | | QBitmap provides the static fromData() function which returns a |
51 | | bitmap constructed from the given \c uchar data, and the static |
52 | | fromImage() function returning a converted copy of a QImage |
53 | | object. |
54 | | |
55 | | Just like the QPixmap class, QBitmap is optimized by the use of |
56 | | implicit data sharing. For more information, see the \l {Implicit |
57 | | Data Sharing} documentation. |
58 | | |
59 | | \sa QPixmap, QImage, QImageReader, QImageWriter |
60 | | */ |
61 | | |
62 | | /*! \typedef QBitmap::DataPtr |
63 | | \internal |
64 | | */ |
65 | | |
66 | | /*! |
67 | | Constructs a null bitmap. |
68 | | |
69 | | \sa QPixmap::isNull() |
70 | | */ |
71 | | QBitmap::QBitmap() |
72 | 0 | : QPixmap(QSize(0, 0), QPlatformPixmap::BitmapType) |
73 | 0 | { |
74 | 0 | } |
75 | | |
76 | | /*! |
77 | | \fn QBitmap::QBitmap(int width, int height) |
78 | | |
79 | | Constructs a bitmap with the given \a width and \a height. The pixels |
80 | | inside are uninitialized. |
81 | | |
82 | | \sa clear() |
83 | | */ |
84 | | QBitmap::QBitmap(int w, int h) |
85 | 0 | : QPixmap(QSize(w, h), QPlatformPixmap::BitmapType) |
86 | 0 | { |
87 | 0 | } |
88 | | |
89 | | /*! |
90 | | Constructs a bitmap with the given \a size. The pixels in the |
91 | | bitmap are uninitialized. |
92 | | |
93 | | \sa clear() |
94 | | */ |
95 | | QBitmap::QBitmap(const QSize &size) |
96 | 0 | : QPixmap(size, QPlatformPixmap::BitmapType) |
97 | 0 | { |
98 | 0 | } |
99 | | |
100 | | /*! |
101 | | \internal |
102 | | This dtor must stay empty until Qt 7 (was inline until 6.2). |
103 | | */ |
104 | 0 | QBitmap::~QBitmap() = default; |
105 | | |
106 | | /*! |
107 | | \fn QBitmap::clear() |
108 | | |
109 | | Clears the bitmap, setting all its bits to Qt::color0. |
110 | | */ |
111 | | |
112 | | /*! |
113 | | Constructs a bitmap from the file specified by the given \a |
114 | | fileName. If the file does not exist, or has an unknown format, |
115 | | the bitmap becomes a null bitmap. |
116 | | |
117 | | The \a fileName and \a format parameters are passed on to the |
118 | | QPixmap::load() function. If the file format uses more than 1 bit |
119 | | per pixel, the resulting bitmap will be dithered automatically. |
120 | | |
121 | | \sa QPixmap::isNull(), QImageReader::imageFormat() |
122 | | */ |
123 | | QBitmap::QBitmap(const QString& fileName, const char *format) |
124 | 0 | : QPixmap(QSize(0, 0), QPlatformPixmap::BitmapType) |
125 | 0 | { |
126 | 0 | load(fileName, format, Qt::MonoOnly); |
127 | 0 | } |
128 | | |
129 | | /*! |
130 | | \fn void QBitmap::swap(QBitmap &other) |
131 | | \memberswap{bitmap} |
132 | | */ |
133 | | |
134 | | /*! |
135 | | Returns the bitmap as a QVariant. |
136 | | */ |
137 | | QBitmap::operator QVariant() const |
138 | 0 | { |
139 | 0 | return QVariant::fromValue(*this); |
140 | 0 | } |
141 | | |
142 | | static QBitmap makeBitmap(QImage &&image, Qt::ImageConversionFlags flags) |
143 | 0 | { |
144 | | // make sure image.color(0) == Qt::color0 (white) |
145 | | // and image.color(1) == Qt::color1 (black) |
146 | 0 | const QRgb c0 = QColor(Qt::black).rgb(); |
147 | 0 | const QRgb c1 = QColor(Qt::white).rgb(); |
148 | 0 | if (image.color(0) == c0 && image.color(1) == c1) { |
149 | 0 | image.invertPixels(); |
150 | 0 | image.setColor(0, c1); |
151 | 0 | image.setColor(1, c0); |
152 | 0 | } |
153 | |
|
154 | 0 | std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType)); |
155 | |
|
156 | 0 | data->fromImageInPlace(image, flags | Qt::MonoOnly); |
157 | 0 | return QBitmap::fromPixmap(QPixmap(data.release())); |
158 | 0 | } |
159 | | |
160 | | /*! |
161 | | Returns a copy of the given \a image converted to a bitmap using |
162 | | the specified image conversion \a flags. |
163 | | |
164 | | \sa fromData() |
165 | | */ |
166 | | QBitmap QBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags) |
167 | 0 | { |
168 | 0 | if (image.isNull()) |
169 | 0 | return QBitmap(); |
170 | | |
171 | 0 | return makeBitmap(image.convertToFormat(QImage::Format_MonoLSB, flags), flags); |
172 | 0 | } |
173 | | |
174 | | /*! |
175 | | \since 5.12 |
176 | | \overload |
177 | | |
178 | | Returns a copy of the given \a image converted to a bitmap using |
179 | | the specified image conversion \a flags. |
180 | | |
181 | | \sa fromData() |
182 | | */ |
183 | | QBitmap QBitmap::fromImage(QImage &&image, Qt::ImageConversionFlags flags) |
184 | 0 | { |
185 | 0 | if (image.isNull()) |
186 | 0 | return QBitmap(); |
187 | | |
188 | 0 | return makeBitmap(std::move(image).convertToFormat(QImage::Format_MonoLSB, flags), flags); |
189 | 0 | } |
190 | | |
191 | | /*! |
192 | | Constructs a bitmap with the given \a size, and sets the contents to |
193 | | the \a bits supplied. |
194 | | |
195 | | The bitmap data has to be byte aligned and provided in the bit |
196 | | order specified by \a monoFormat. The mono format must be either |
197 | | QImage::Format_Mono or QImage::Format_MonoLSB. Use |
198 | | QImage::Format_Mono to specify data on the XBM format. |
199 | | |
200 | | \sa fromImage() |
201 | | |
202 | | */ |
203 | | QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format monoFormat) |
204 | 0 | { |
205 | 0 | Q_ASSERT(monoFormat == QImage::Format_Mono || monoFormat == QImage::Format_MonoLSB); |
206 | |
|
207 | 0 | QImage image(size, monoFormat); |
208 | 0 | image.setColor(0, QColor(Qt::color0).rgb()); |
209 | 0 | image.setColor(1, QColor(Qt::color1).rgb()); |
210 | | |
211 | | // Need to memcpy each line separately since QImage is 32bit aligned and |
212 | | // this data is only byte aligned... |
213 | 0 | int bytesPerLine = (size.width() + 7) / 8; |
214 | 0 | for (int y = 0; y < size.height(); ++y) |
215 | 0 | memcpy(image.scanLine(y), bits + bytesPerLine * y, bytesPerLine); |
216 | 0 | return QBitmap::fromImage(std::move(image)); |
217 | 0 | } |
218 | | |
219 | | /*! |
220 | | Returns a copy of the given \a pixmap converted to a bitmap. |
221 | | |
222 | | If the pixmap has a depth greater than 1, the resulting bitmap |
223 | | will be dithered automatically. |
224 | | |
225 | | \since 6.0 |
226 | | |
227 | | \sa QPixmap::depth() |
228 | | */ |
229 | | |
230 | | QBitmap QBitmap::fromPixmap(const QPixmap &pixmap) |
231 | 0 | { |
232 | 0 | if (pixmap.isNull()) { // a null pixmap |
233 | 0 | return QBitmap(0, 0); |
234 | 0 | } else if (pixmap.depth() == 1) { // 1-bit pixmap |
235 | 0 | QBitmap bm; |
236 | 0 | if (pixmap.paintingActive()) { // make a deep copy |
237 | 0 | pixmap.copy().swap(bm); |
238 | 0 | } else { |
239 | 0 | bm.data = pixmap.data; // shallow assignment |
240 | 0 | } |
241 | 0 | return bm; |
242 | 0 | } |
243 | | // n-bit depth pixmap, will dither image |
244 | 0 | return fromImage(pixmap.toImage()); |
245 | 0 | } |
246 | | |
247 | | #if QT_DEPRECATED_SINCE(6, 0) |
248 | | /*! |
249 | | \deprecated [6.0] Use fromPixmap instead. |
250 | | Constructs a bitmap that is a copy of the given \a pixmap. |
251 | | |
252 | | If the pixmap has a depth greater than 1, the resulting bitmap |
253 | | will be dithered automatically. |
254 | | |
255 | | \sa QPixmap::depth(), fromImage(), fromData() |
256 | | */ |
257 | | QBitmap::QBitmap(const QPixmap &pixmap) |
258 | 0 | { |
259 | 0 | *this = QBitmap::fromPixmap(pixmap); |
260 | 0 | } |
261 | | |
262 | | /*! |
263 | | \deprecated [6.0] Use fromPixmap instead. |
264 | | \overload |
265 | | |
266 | | Assigns the given \a pixmap to this bitmap and returns a reference |
267 | | to this bitmap. |
268 | | |
269 | | If the pixmap has a depth greater than 1, the resulting bitmap |
270 | | will be dithered automatically. |
271 | | |
272 | | \sa QPixmap::depth() |
273 | | */ |
274 | | QBitmap &QBitmap::operator=(const QPixmap &pixmap) |
275 | 0 | { |
276 | 0 | *this = QBitmap::fromPixmap(pixmap); |
277 | 0 | return *this; |
278 | 0 | } |
279 | | #endif |
280 | | |
281 | | /*! |
282 | | Returns a copy of this bitmap, transformed according to the given |
283 | | \a matrix. |
284 | | |
285 | | \sa QPixmap::transformed() |
286 | | */ |
287 | | QBitmap QBitmap::transformed(const QTransform &matrix) const |
288 | 0 | { |
289 | 0 | return QBitmap::fromPixmap(QPixmap::transformed(matrix)); |
290 | 0 | } |
291 | | |
292 | | QT_END_NAMESPACE |