Qt 4.8
qpixmap_raster.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qpixmap.h"
43 
44 #include <private/qfont_p.h>
45 
46 #include "qpixmap_raster_p.h"
47 #include "qnativeimage_p.h"
48 #include "qimage_p.h"
49 #include "qpaintengine.h"
50 
51 #include "qbitmap.h"
52 #include "qimage.h"
53 #include <QBuffer>
54 #include <QImageReader>
55 #include <private/qimage_p.h>
56 #include <private/qsimd_p.h>
57 #include <private/qwidget_p.h>
58 #include <private/qdrawhelper_p.h>
59 
61 
62 const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
63  0x10, 0x20, 0x40, 0x80 };
64 
66 {
67  QPixmapData *data =
68  new QRasterPixmapData(image.depth() == 1
71 
72  data->fromImage(image, Qt::AutoColor);
73 
74  return QPixmap(data);
75 }
76 
78 {
79  if (pixmap.isNull())
80  return QPixmap();
81 
83  return pixmap;
84 
85  return qt_toRasterPixmap(pixmap.toImage());
86 }
87 
89  : QPixmapData(type, RasterClass)
90 {
91 }
92 
94 {
95 }
96 
98 {
99  return new QRasterPixmapData(pixelType());
100 }
101 
103 {
105 #ifdef Q_WS_QWS
106  if (pixelType() == BitmapType) {
107  format = QImage::Format_Mono;
108  } else {
109  format = QScreen::instance()->pixelFormat();
110  if (format == QImage::Format_Invalid)
112  else if (format == QImage::Format_Indexed8) // currently not supported
113  format = QImage::Format_RGB444;
114  }
115 #else
116  if (pixelType() == BitmapType)
117  format = QImage::Format_MonoLSB;
118  else
119  format = QNativeImage::systemFormat();
120 #endif
121 
122  image = QImage(width, height, format);
123  w = width;
124  h = height;
125  d = image.depth();
126  is_null = (w <= 0 || h <= 0);
127 
128  if (pixelType() == BitmapType && !image.isNull()) {
129  image.setColorCount(2);
130  image.setColor(0, QColor(Qt::color0).rgba());
131  image.setColor(1, QColor(Qt::color1).rgba());
132  }
133 
135 }
136 
137 bool QRasterPixmapData::fromData(const uchar *buffer, uint len, const char *format,
138  Qt::ImageConversionFlags flags)
139 {
140  QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
141  QBuffer b(&a);
143  QImage image = QImageReader(&b, format).read();
144  if (image.isNull())
145  return false;
146 
147  createPixmapForImage(image, flags, /* inplace = */true);
148  return !isNull();
149 }
150 
151 void QRasterPixmapData::fromImage(const QImage &sourceImage,
152  Qt::ImageConversionFlags flags)
153 {
154  Q_UNUSED(flags);
155  QImage image = sourceImage;
156  createPixmapForImage(image, flags, /* inplace = */false);
157 }
158 
160  Qt::ImageConversionFlags flags)
161 {
162  Q_UNUSED(flags);
163  QImage image = imageReader->read();
164  if (image.isNull())
165  return;
166 
167  createPixmapForImage(image, flags, /* inplace = */true);
168 }
169 
170 // from qwindowsurface.cpp
171 extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
172 
174 {
176 }
177 
178 bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
179 {
180  if (!image.isNull())
181  qt_scrollRectInImage(image, rect, QPoint(dx, dy));
182  return true;
183 }
184 
185 void QRasterPixmapData::fill(const QColor &color)
186 {
187  uint pixel;
188 
189  if (image.depth() == 1) {
190  int gray = qGray(color.rgba());
191  // Pick the best approximate color in the image's colortable.
192  if (qAbs(qGray(image.color(0)) - gray) < qAbs(qGray(image.color(1)) - gray))
193  pixel = 0;
194  else
195  pixel = 1;
196  } else if (image.depth() >= 15) {
197  int alpha = color.alpha();
198  if (alpha != 255) {
199  if (!image.hasAlphaChannel()) {
200  QImage::Format toFormat;
201 #if !(defined(QT_HAVE_NEON) || defined(QT_ALWAYS_HAVE_SSE2))
204  else if (image.format() == QImage::Format_RGB666)
206  else if (image.format() == QImage::Format_RGB555)
208  else if (image.format() == QImage::Format_RGB444)
210  else
211 #endif
213 
214  if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) {
215  image.detach();
216  image.d->format = toFormat;
217  } else {
218  image = QImage(image.width(), image.height(), toFormat);
219  }
220  }
221 
222  switch (image.format()) {
224  pixel = qargb8565(color.rgba()).rawValue();
225  break;
227  pixel = qargb8555(color.rgba()).rawValue();
228  break;
230  pixel = qargb6666(color.rgba()).rawValue();
231  break;
233  pixel = qargb4444(color.rgba()).rawValue();
234  break;
235  default:
236  pixel = PREMUL(color.rgba());
237  break;
238  }
239  } else {
240  switch (image.format()) {
242  pixel = qt_colorConvert<quint16, quint32>(color.rgba(), 0);
243  break;
245  pixel = qrgb444(color.rgba()).rawValue();
246  break;
248  pixel = qrgb555(color.rgba()).rawValue();
249  break;
251  pixel = qrgb666(color.rgba()).rawValue();
252  break;
254  pixel = qrgb888(color.rgba()).rawValue();
255  break;
256  default:
257  pixel = color.rgba();
258  break;
259  }
260  }
261  } else {
262  pixel = 0;
263  // ### what about 8 bits
264  }
265 
266  image.fill(pixel);
267 }
268 
270 {
271  if (mask.size().isEmpty()) {
272  if (image.depth() != 1) { // hw: ????
274  }
275  } else {
276  const int w = image.width();
277  const int h = image.height();
278 
279  switch (image.depth()) {
280  case 1: {
281  const QImage imageMask = mask.toImage().convertToFormat(image.format());
282  for (int y = 0; y < h; ++y) {
283  const uchar *mscan = imageMask.scanLine(y);
284  uchar *tscan = image.scanLine(y);
285  int bytesPerLine = image.bytesPerLine();
286  for (int i = 0; i < bytesPerLine; ++i)
287  tscan[i] &= mscan[i];
288  }
289  break;
290  }
291  default: {
292  const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
294  for (int y = 0; y < h; ++y) {
295  const uchar *mscan = imageMask.scanLine(y);
296  QRgb *tscan = (QRgb *)image.scanLine(y);
297  for (int x = 0; x < w; ++x) {
298  if (!(mscan[x>>3] & qt_pixmap_bit_mask[x&7]))
299  tscan[x] = 0;
300  }
301  }
302  break;
303  }
304  }
305  }
306 }
307 
309 {
310  return image.hasAlphaChannel();
311 }
312 
314 {
315  if (!image.isNull()) {
316  QImageData *data = const_cast<QImage &>(image).data_ptr();
317  if (data->paintEngine && data->paintEngine->isActive()
318  && data->paintEngine->paintDevice() == &image)
319  {
320  return image.copy();
321  }
322  }
323 
324  return image;
325 }
326 
328 {
329  if (rect.isNull())
330  return image;
331 
332  QRect clipped = rect.intersected(QRect(0, 0, w, h));
333  const uint du = uint(d);
334  if ((du % 8 == 0) && (((uint(clipped.x()) * du)) % 32 == 0))
335  return QImage(image.scanLine(clipped.y()) + clipped.x() * (du / 8),
336  clipped.width(), clipped.height(),
338  else
339  return image.copy(clipped);
340 }
341 
343 {
344  image.setAlphaChannel(alphaChannel.toImage());
345 }
346 
348 {
349  return image.paintEngine();
350 }
351 
353 {
354  QImageData *d = image.d;
355  if (!d)
356  return 0;
357 
358  // override the image dpi with the screen dpi when rendering to a pixmap
359  switch (metric) {
361  return w;
363  return h;
365  return qRound(d->width * 25.4 / qt_defaultDpiX());
367  return qRound(d->height * 25.4 / qt_defaultDpiY());
369  return d->colortable.size();
371  return this->d;
372  case QPaintDevice::PdmDpiX: // fall-through
374  return qt_defaultDpiX();
375  case QPaintDevice::PdmDpiY: // fall-through
377  return qt_defaultDpiY();
378  default:
379  qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric);
380  break;
381  }
382 
383  return 0;
384 }
385 
386 void QRasterPixmapData::createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace)
387 {
389  if (flags & Qt::NoFormatConversion)
390  format = sourceImage.format();
391  else
392 #ifdef Q_WS_QWS
393  if (pixelType() == BitmapType) {
394  format = QImage::Format_Mono;
395  } else {
396  format = QScreen::instance()->pixelFormat();
397  if (format == QImage::Format_Invalid)
399  else if (format == QImage::Format_Indexed8) // currently not supported
400  format = QImage::Format_RGB444;
401  }
402 
403  if (sourceImage.hasAlphaChannel()
404  && ((flags & Qt::NoOpaqueDetection)
405  || const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
406  switch (format) {
409  break;
412  break;
415  break;
418  break;
419  default:
421  break;
422  }
423  } else if (format == QImage::Format_Invalid) {
425  }
426 #else
427  if (pixelType() == BitmapType) {
428  format = QImage::Format_MonoLSB;
429  } else {
430  if (sourceImage.depth() == 1) {
431  format = sourceImage.hasAlphaChannel()
434  } else {
437 
438 #if !defined(QT_HAVE_NEON) && !defined(QT_ALWAYS_HAVE_SSE2)
439  switch (opaqueFormat) {
442  break;
443  default: // We don't care about the others...
444  break;
445  }
446 #endif
447 
448  if (!sourceImage.hasAlphaChannel()) {
449  format = opaqueFormat;
450  } else if ((flags & Qt::NoOpaqueDetection) == 0
451  && !const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())
452  {
453  // image has alpha format but is really opaque, so try to do a
454  // more efficient conversion
455  if (sourceImage.format() == QImage::Format_ARGB32
456  || sourceImage.format() == QImage::Format_ARGB32_Premultiplied)
457  {
458  if (!inPlace)
459  sourceImage.detach();
460  sourceImage.d->format = QImage::Format_RGB32;
461  }
462  format = opaqueFormat;
463  } else {
464  format = alphaFormat;
465  }
466  }
467  }
468 #endif
469 
470  if (inPlace && sourceImage.d->convertInPlace(format, flags)) {
471  image = sourceImage;
472  } else {
473  image = sourceImage.convertToFormat(format);
474  }
475 
476  if (image.d) {
477  w = image.d->width;
478  h = image.d->height;
479  d = image.d->depth;
480  } else {
481  w = h = d = 0;
482  }
483  is_null = (w <= 0 || h <= 0);
484 
486 }
487 
489 {
490  return &image;
491 }
492 
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
QPixmap qt_toRasterPixmap(const QImage &image)
int width
Definition: qimage_p.h:76
DataPtr & data_ptr()
Definition: qpixmap.h:297
QImage toImage() const
Converts the pixmap to a QImage.
Definition: qpixmap.cpp:542
Format
The following image formats are available in Qt.
Definition: qimage.h:91
unsigned int QRgb
Definition: qrgb.h:53
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:231
int type
Definition: qmetatype.cpp:239
void setColor(int i, QRgb c)
Sets the color at the given index in the color table, to the given to colorValue. ...
Definition: qimage.cpp:1850
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPaintDevice * paintDevice() const
Returns the device that this engine is painting on, if painting is active; otherwise returns 0...
QSize size() const
Returns the size of the pixmap.
Definition: qpixmap.cpp:661
Q_GUI_EXPORT int qt_defaultDpiY()
Definition: qfont.cpp:201
bool open(OpenMode openMode)
Reimplemented Function
Definition: qbuffer.cpp:338
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition: qimage.cpp:2032
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
Q_GUI_EXPORT int qt_defaultDpiX()
Definition: qfont.cpp:162
int width() const
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false...
Definition: qimage.cpp:6495
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
static QImage::Format systemFormat()
long ASN1_INTEGER_get ASN1_INTEGER * a
QRect intersected(const QRect &other) const
Returns the intersection of this rectangle and the given rectangle.
Definition: qrect.h:481
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:57
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
QImageData * d
Definition: qimage.h:336
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
virtual QBitmap mask() const
QVector< QRgb > colortable
Definition: qimage_p.h:80
void copy(const QPixmapData *data, const QRect &rect)
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
void fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags)
PixelType pixelType() const
virtual QPixmap alphaChannel() const
int metric(QPaintDevice::PaintDeviceMetric metric) const
unsigned char uchar
Definition: qglobal.h:994
The QBitmap class provides monochrome (1-bit depth) pixmaps.
Definition: qbitmap.h:55
virtual QImage toImage() const =0
void setColorCount(int)
Resizes the color table to contain colorCount entries.
Definition: qimage.cpp:2275
const uchar qt_pixmap_bit_mask[]
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isActive() const
Returns true if the paint engine is actively drawing; otherwise returns false.
Definition: qpaintengine.h:154
int height
Definition: qimage_p.h:77
void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x)
virtual void fromImage(const QImage &image, Qt::ImageConversionFlags flags)=0
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
void detach()
If multiple images share common data, this image makes a copy of the data and detaches itself from th...
Definition: qimage.cpp:1359
QPaintEngine * paintEngine
Definition: qimage_p.h:110
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
static QScreen * instance()
Returns a pointer to the application&#39;s QScreen instance.
Definition: qscreen_qws.h:201
ClassId classId() const
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
bool hasAlphaChannel() const
void createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace)
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
The QImageReader class provides a format independent interface for reading images from files or other...
Definition: qimagereader.h:62
void resize(int width, int height)
bool scroll(int dx, int dy, const QRect &rect)
Q_GUI_EXPORT_INLINE int qGray(int r, int g, int b)
Definition: qrgb.h:75
void setMask(const QBitmap &mask)
int serialNumber() const
Returns a number that identifies the contents of this QImage object.
Definition: qimage.cpp:6267
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
QImage::Format pixelFormat() const
Returns the pixel format of the screen, or QImage::Format_Invalid if the pixel format is not a suppor...
ushort alpha
Returns the alpha color component of this color.
Definition: qcolor.h:242
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
QImage::Format format
Definition: qimage_p.h:85
void * data_ptr(const QTransform &t)
Definition: qpainter_p.h:81
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
QPixmapData * createCompatiblePixmapData() const
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
QRasterPixmapData(PixelType type)
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
void setAlphaChannel(const QPixmap &alphaChannel)
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
void fill(const QColor &color)
int height() const
QPaintEngine * paintEngine() const
Used by QPainter to retrieve a paint engine for the image.
Definition: qimage.cpp:5970
bool isNull() const
int qt_depthForFormat(QImage::Format format)
Definition: qimage_p.h:116
bool convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags)
Definition: qimage.cpp:6935
QRgb rgba() const
Returns the RGB value of the color, including its alpha.
Definition: qcolor.cpp:1019
void setAlphaChannel(const QImage &alphaChannel)
Sets the alpha channel of this image to the given alphaChannel.
Definition: qimage.cpp:6329
bool isEmpty() const
Returns true if either of the width and height is less than or equal to 0; otherwise returns false...
Definition: qsize.h:120
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
void setSerialNumber(int serNo)
bool fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags)
int depth
Definition: qimage_p.h:78
QPaintEngine * paintEngine() const
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QImage read()
Reads an image from the device.
QRgb color(int i) const
Returns the color in the color table at index i.
Definition: qimage.cpp:1829
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
QImage toImage() const
void fromImage(const QImage &image, Qt::ImageConversionFlags flags)