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

source code of qtbase/src/gui/image/qbitmap.cpp