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
133 Swaps bitmap \a other with this bitmap. This operation is very
134 fast and never fails.
135*/
136
137/*!
138 Returns the bitmap as a QVariant.
139*/
140QBitmap::operator QVariant() const
141{
142 return QVariant::fromValue(value: *this);
143}
144
145static QBitmap makeBitmap(QImage &&image, Qt::ImageConversionFlags flags)
146{
147 // make sure image.color(0) == Qt::color0 (white)
148 // and image.color(1) == Qt::color1 (black)
149 const QRgb c0 = QColor(Qt::black).rgb();
150 const QRgb c1 = QColor(Qt::white).rgb();
151 if (image.color(i: 0) == c0 && image.color(i: 1) == c1) {
152 image.invertPixels();
153 image.setColor(i: 0, c: c1);
154 image.setColor(i: 1, c: c0);
155 }
156
157 std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(type: QPlatformPixmap::BitmapType));
158
159 data->fromImageInPlace(image, flags: flags | Qt::MonoOnly);
160 return QBitmap::fromPixmap(pixmap: QPixmap(data.release()));
161}
162
163/*!
164 Returns a copy of the given \a image converted to a bitmap using
165 the specified image conversion \a flags.
166
167 \sa fromData()
168*/
169QBitmap QBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
170{
171 if (image.isNull())
172 return QBitmap();
173
174 return makeBitmap(image: image.convertToFormat(f: QImage::Format_MonoLSB, flags), flags);
175}
176
177/*!
178 \since 5.12
179 \overload
180
181 Returns a copy of the given \a image converted to a bitmap using
182 the specified image conversion \a flags.
183
184 \sa fromData()
185*/
186QBitmap QBitmap::fromImage(QImage &&image, Qt::ImageConversionFlags flags)
187{
188 if (image.isNull())
189 return QBitmap();
190
191 return makeBitmap(image: std::move(image).convertToFormat(f: QImage::Format_MonoLSB, flags), flags);
192}
193
194/*!
195 Constructs a bitmap with the given \a size, and sets the contents to
196 the \a bits supplied.
197
198 The bitmap data has to be byte aligned and provided in the bit
199 order specified by \a monoFormat. The mono format must be either
200 QImage::Format_Mono or QImage::Format_MonoLSB. Use
201 QImage::Format_Mono to specify data on the XBM format.
202
203 \sa fromImage()
204
205*/
206QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format monoFormat)
207{
208 Q_ASSERT(monoFormat == QImage::Format_Mono || monoFormat == QImage::Format_MonoLSB);
209
210 QImage image(size, monoFormat);
211 image.setColor(i: 0, c: QColor(Qt::color0).rgb());
212 image.setColor(i: 1, c: QColor(Qt::color1).rgb());
213
214 // Need to memcpy each line separately since QImage is 32bit aligned and
215 // this data is only byte aligned...
216 int bytesPerLine = (size.width() + 7) / 8;
217 for (int y = 0; y < size.height(); ++y)
218 memcpy(dest: image.scanLine(y), src: bits + bytesPerLine * y, n: bytesPerLine);
219 return QBitmap::fromImage(image: std::move(image));
220}
221
222/*!
223 Returns a copy of the given \a pixmap converted to a bitmap.
224
225 If the pixmap has a depth greater than 1, the resulting bitmap
226 will be dithered automatically.
227
228 \since 6.0
229
230 \sa QPixmap::depth()
231*/
232
233QBitmap QBitmap::fromPixmap(const QPixmap &pixmap)
234{
235 if (pixmap.isNull()) { // a null pixmap
236 return QBitmap(0, 0);
237 } else if (pixmap.depth() == 1) { // 1-bit pixmap
238 QBitmap bm;
239 if (pixmap.paintingActive()) { // make a deep copy
240 pixmap.copy().swap(other&: bm);
241 } else {
242 bm.data = pixmap.data; // shallow assignment
243 }
244 return bm;
245 }
246 // n-bit depth pixmap, will dither image
247 return fromImage(image: pixmap.toImage());
248}
249
250#if QT_DEPRECATED_SINCE(6, 0)
251/*!
252 \deprecated [6.0] Use fromPixmap instead.
253 Constructs a bitmap that is a copy of the given \a pixmap.
254
255 If the pixmap has a depth greater than 1, the resulting bitmap
256 will be dithered automatically.
257
258 \sa QPixmap::depth(), fromImage(), fromData()
259*/
260QBitmap::QBitmap(const QPixmap &pixmap)
261{
262 *this = QBitmap::fromPixmap(pixmap);
263}
264
265/*!
266 \deprecated [6.0] Use fromPixmap instead.
267 \overload
268
269 Assigns the given \a pixmap to this bitmap and returns a reference
270 to this bitmap.
271
272 If the pixmap has a depth greater than 1, the resulting bitmap
273 will be dithered automatically.
274
275 \sa QPixmap::depth()
276 */
277QBitmap &QBitmap::operator=(const QPixmap &pixmap)
278{
279 *this = QBitmap::fromPixmap(pixmap);
280 return *this;
281}
282#endif
283
284/*!
285 Returns a copy of this bitmap, transformed according to the given
286 \a matrix.
287
288 \sa QPixmap::transformed()
289 */
290QBitmap QBitmap::transformed(const QTransform &matrix) const
291{
292 return QBitmap::fromPixmap(pixmap: QPixmap::transformed(matrix));
293}
294
295QT_END_NAMESPACE
296

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