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