Qt 4.8
qimage.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 "qimage.h"
43 #include "qdatastream.h"
44 #include "qbuffer.h"
45 #include "qmap.h"
46 #include "qmatrix.h"
47 #include "qtransform.h"
48 #include "qimagereader.h"
49 #include "qimagewriter.h"
50 #include "qstringlist.h"
51 #include "qvariant.h"
53 #include <ctype.h>
54 #include <stdlib.h>
55 #include <limits.h>
56 #include <math.h>
57 #include <private/qdrawhelper_p.h>
58 #include <private/qmemrotate_p.h>
59 #include <private/qpixmapdata_p.h>
60 #include <private/qimagescale_p.h>
61 #include <private/qsimd_p.h>
62 
63 #include <qhash.h>
64 
65 #if defined(Q_OS_SYMBIAN)
66 #include <private/qpaintengine_raster_symbian_p.h>
67 #else
68 #include <private/qpaintengine_raster_p.h>
69 #endif
70 
71 #include <private/qimage_p.h>
72 #include <private/qfont_p.h>
73 
75 
76 static inline bool checkPixelSize(const QImage::Format format)
77 {
78  switch (format) {
80  return (sizeof(qargb8565) == 3);
82  return (sizeof(qrgb666) == 3);
84  return (sizeof(qargb6666) == 3);
86  return (sizeof(qrgb555) == 2);
88  return (sizeof(qargb8555) == 3);
90  return (sizeof(qrgb888) == 3);
92  return (sizeof(qrgb444) == 2);
94  return (sizeof(qargb4444) == 2);
95  default:
96  return true;
97  }
98 }
99 
100 #if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
101 #pragma message disable narrowptr
102 #endif
103 
104 
105 #define QIMAGE_SANITYCHECK_MEMORY(image) \
106  if ((image).isNull()) { \
107  qWarning("QImage: out of memory, returning null image"); \
108  return QImage(); \
109  }
110 
111 
112 static QImage rotated90(const QImage &src);
113 static QImage rotated180(const QImage &src);
114 static QImage rotated270(const QImage &src);
115 
116 // ### Qt 5: remove
118 {
119  return image.cacheKey();
120 }
121 
123 {
124  return &image.d->colortable;
125 }
126 
128 
130  : ref(0), width(0), height(0), depth(0), nbytes(0), data(0),
131 #ifdef QT3_SUPPORT
132  jumptable(0),
133 #endif
134  format(QImage::Format_ARGB32), bytes_per_line(0),
135  ser_no(qimage_serial_number.fetchAndAddRelaxed(1)),
136  detach_no(0),
137  dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
138  dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
139  offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
140  is_cached(false), paintEngine(0)
141 {
142 }
143 
152 {
153  if (!size.isValid() || numColors < 0 || format == QImage::Format_Invalid)
154  return 0; // invalid parameter(s)
155 
156  if (!checkPixelSize(format)) {
157  qWarning("QImageData::create(): Invalid pixel size for format %i",
158  format);
159  return 0;
160  }
161 
162  uint width = size.width();
163  uint height = size.height();
164  uint depth = qt_depthForFormat(format);
165 
166  switch (format) {
167  case QImage::Format_Mono:
169  numColors = 2;
170  break;
172  numColors = qBound(0, numColors, 256);
173  break;
174  default:
175  numColors = 0;
176  break;
177  }
178 
179  const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
180 
181  // sanity check for potential overflows
182  if (INT_MAX/depth < width
183  || bytes_per_line <= 0
184  || height <= 0
185  || INT_MAX/uint(bytes_per_line) < height
186  || INT_MAX/sizeof(uchar *) < uint(height))
187  return 0;
188 
190  d->colortable.resize(numColors);
191  if (depth == 1) {
192  d->colortable[0] = QColor(Qt::black).rgba();
193  d->colortable[1] = QColor(Qt::white).rgba();
194  } else {
195  for (int i = 0; i < numColors; ++i)
196  d->colortable[i] = 0;
197  }
198 
199  d->width = width;
200  d->height = height;
201  d->depth = depth;
202  d->format = format;
203  d->has_alpha_clut = false;
204  d->is_cached = false;
205 
207 
208  d->nbytes = d->bytes_per_line*height;
209  d->data = (uchar *)malloc(d->nbytes);
210 
211  if (!d->data) {
212  return 0;
213  }
214 
215  d->ref.ref();
216  return d.take();
217 
218 }
219 
221 {
222  if (is_cached)
224  delete paintEngine;
225  if (data && own_data)
226  free(data);
227 #ifdef QT3_SUPPORT
228  if (jumptable)
229  free(jumptable);
230  jumptable = 0;
231 #endif
232  data = 0;
233 }
234 
235 
237 {
238  bool has_alpha_pixels = false;
239 
240  switch (format) {
241 
242  case QImage::Format_Mono:
245  has_alpha_pixels = has_alpha_clut;
246  break;
247 
250  uchar *bits = data;
251  for (int y=0; y<height && !has_alpha_pixels; ++y) {
252  for (int x=0; x<width; ++x)
253  has_alpha_pixels |= (((uint *)bits)[x] & 0xff000000) != 0xff000000;
254  bits += bytes_per_line;
255  }
256  } break;
257 
260  uchar *bits = data;
261  uchar *end_bits = data + bytes_per_line;
262 
263  for (int y=0; y<height && !has_alpha_pixels; ++y) {
264  while (bits < end_bits) {
265  has_alpha_pixels |= bits[0] != 0;
266  bits += 3;
267  }
268  bits = end_bits;
269  end_bits += bytes_per_line;
270  }
271  } break;
272 
274  uchar *bits = data;
275  uchar *end_bits = data + bytes_per_line;
276 
277  for (int y=0; y<height && !has_alpha_pixels; ++y) {
278  while (bits < end_bits) {
279  has_alpha_pixels |= (bits[0] & 0xfc) != 0;
280  bits += 3;
281  }
282  bits = end_bits;
283  end_bits += bytes_per_line;
284  }
285  } break;
286 
288  uchar *bits = data;
289  uchar *end_bits = data + bytes_per_line;
290 
291  for (int y=0; y<height && !has_alpha_pixels; ++y) {
292  while (bits < end_bits) {
293  has_alpha_pixels |= (bits[0] & 0xf0) != 0;
294  bits += 2;
295  }
296  bits = end_bits;
297  end_bits += bytes_per_line;
298  }
299  } break;
300 
301  default:
302  break;
303  }
304 
305  return has_alpha_pixels;
306 }
307 
731 /*****************************************************************************
732  QImage member functions
733  *****************************************************************************/
734 
735 // table to flip bits
736 static const uchar bitflip[256] = {
737  /*
738  open OUT, "| fmt";
739  for $i (0..255) {
740  print OUT (($i >> 7) & 0x01) | (($i >> 5) & 0x02) |
741  (($i >> 3) & 0x04) | (($i >> 1) & 0x08) |
742  (($i << 7) & 0x80) | (($i << 5) & 0x40) |
743  (($i << 3) & 0x20) | (($i << 1) & 0x10), ", ";
744  }
745  close OUT;
746  */
747  0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
748  8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
749  4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
750  12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
751  2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
752  10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
753  6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
754  14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
755  1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
756  9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
757  5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
758  13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
759  3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
760  11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
761  7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
762  15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
763 };
764 
765 const uchar *qt_get_bitflip_array() // called from QPixmap code
766 {
767  return bitflip;
768 }
769 
770 #if defined(QT3_SUPPORT)
771 static QImage::Format formatFor(int depth, QImage::Endian bitOrder)
772 {
774  if (depth == 1) {
775  format = bitOrder == QImage::BigEndian ? QImage::Format_Mono : QImage::Format_MonoLSB;
776  } else if (depth == 8) {
777  format = QImage::Format_Indexed8;
778  } else if (depth == 32) {
779  format = QImage::Format_RGB32;
780  } else if (depth == 24) {
781  format = QImage::Format_RGB888;
782  } else if (depth == 16) {
783  format = QImage::Format_RGB16;
784  } else {
785  qWarning("QImage: Depth %d not supported", depth);
786  format = QImage::Format_Invalid;
787  }
788  return format;
789 }
790 #endif
791 
799  : QPaintDevice()
800 {
801  d = 0;
802 }
803 
815  : QPaintDevice()
816 {
817  d = QImageData::create(QSize(width, height), format, 0);
818 }
819 
830  : QPaintDevice()
831 {
832  d = QImageData::create(size, format, 0);
833 }
834 
835 
836 
838 {
839  QImageData *d = 0;
840 
841  if (format == QImage::Format_Invalid)
842  return d;
843 
844  if (!checkPixelSize(format)) {
845  qWarning("QImageData::create(): Invalid pixel size for format %i",
846  format);
847  return 0;
848  }
849 
850  const int depth = qt_depthForFormat(format);
851  const int calc_bytes_per_line = ((width * depth + 31)/32) * 4;
852  const int min_bytes_per_line = (width * depth + 7)/8;
853 
854  if (bpl <= 0)
855  bpl = calc_bytes_per_line;
856 
857  if (width <= 0 || height <= 0 || !data
858  || INT_MAX/sizeof(uchar *) < uint(height)
859  || INT_MAX/uint(depth) < uint(width)
860  || bpl <= 0
861  || height <= 0
862  || bpl < min_bytes_per_line
863  || INT_MAX/uint(bpl) < uint(height))
864  return d; // invalid parameter(s)
865 
866  d = new QImageData;
867  d->ref.ref();
868 
869  d->own_data = false;
870  d->ro_data = readOnly;
871  d->data = data;
872  d->width = width;
873  d->height = height;
874  d->depth = depth;
875  d->format = format;
876 
877  d->bytes_per_line = bpl;
878  d->nbytes = d->bytes_per_line * height;
879 
880  return d;
881 }
882 
897  : QPaintDevice()
898 {
899  d = QImageData::create(data, width, height, 0, format, false);
900 }
901 
926  : QPaintDevice()
927 {
928  d = QImageData::create(const_cast<uchar*>(data), width, height, 0, format, true);
929 }
930 
945  :QPaintDevice()
946 {
947  d = QImageData::create(data, width, height, bytesPerLine, format, false);
948 }
949 
950 
973  :QPaintDevice()
974 {
975  d = QImageData::create(const_cast<uchar*>(data), width, height, bytesPerLine, format, true);
976 }
977 
996 QImage::QImage(const QString &fileName, const char *format)
997  : QPaintDevice()
998 {
999  d = 0;
1000  load(fileName, format);
1001 }
1002 
1026 #ifndef QT_NO_CAST_FROM_ASCII
1027 QImage::QImage(const char *fileName, const char *format)
1028  : QPaintDevice()
1029 {
1030  // ### Qt 5: if you remove the QImage(const QByteArray &) QT3_SUPPORT
1031  // constructor, remove this constructor as well. The constructor here
1032  // exists so that QImage("foo.png") compiles without ambiguity.
1033  d = 0;
1034  load(QString::fromAscii(fileName), format);
1035 }
1036 #endif
1037 
1038 #ifndef QT_NO_IMAGEFORMAT_XPM
1039 extern bool qt_read_xpm_image_or_array(QIODevice *device, const char * const *source, QImage &image);
1040 
1057 QImage::QImage(const char * const xpm[])
1058  : QPaintDevice()
1059 {
1060  d = 0;
1061  if (!xpm)
1062  return;
1063  if (!qt_read_xpm_image_or_array(0, xpm, *this))
1064  // Issue: Warning because the constructor may be ambigious
1065  qWarning("QImage::QImage(), XPM is not supported");
1066 }
1067 #endif // QT_NO_IMAGEFORMAT_XPM
1068 
1097 QImage::QImage(const QImage &image)
1098  : QPaintDevice()
1099 {
1100  if (image.paintingActive()) {
1101  d = 0;
1102  operator=(image.copy());
1103  } else {
1104  d = image.d;
1105  if (d)
1106  d->ref.ref();
1107  }
1108 }
1109 
1110 #ifdef QT3_SUPPORT
1111 
1136 QImage::QImage(int w, int h, int depth, int colorCount, Endian bitOrder)
1137  : QPaintDevice()
1138 {
1139  d = QImageData::create(QSize(w, h), formatFor(depth, bitOrder), colorCount);
1140 }
1141 
1163 QImage::QImage(const QSize& size, int depth, int numColors, Endian bitOrder)
1164  : QPaintDevice()
1165 {
1166  d = QImageData::create(size, formatFor(depth, bitOrder), numColors);
1167 }
1168 
1194 QImage::QImage(uchar* data, int w, int h, int depth, const QRgb* colortable, int numColors, Endian bitOrder)
1195  : QPaintDevice()
1196 {
1197  d = 0;
1198  Format f = formatFor(depth, bitOrder);
1199  if (f == Format_Invalid)
1200  return;
1201 
1202  const int bytes_per_line = ((w*depth+31)/32)*4; // bytes per scanline
1203  if (w <= 0 || h <= 0 || numColors < 0 || !data
1204  || INT_MAX/sizeof(uchar *) < uint(h)
1205  || INT_MAX/uint(depth) < uint(w)
1206  || bytes_per_line <= 0
1207  || INT_MAX/uint(bytes_per_line) < uint(h))
1208  return; // invalid parameter(s)
1209  d = new QImageData;
1210  d->ref.ref();
1211 
1212  d->own_data = false;
1213  d->data = data;
1214  d->width = w;
1215  d->height = h;
1216  d->depth = depth;
1217  d->format = f;
1218  if (depth == 32)
1219  numColors = 0;
1220 
1221  d->bytes_per_line = bytes_per_line;
1222  d->nbytes = d->bytes_per_line * h;
1223  if (colortable) {
1225  for (int i = 0; i < numColors; ++i)
1226  d->colortable[i] = colortable[i];
1227  } else if (numColors) {
1229  }
1230 }
1231 
1232 #ifdef Q_WS_QWS
1233 
1248 QImage::QImage(uchar* data, int w, int h, int depth, int bpl, const QRgb* colortable, int numColors, Endian bitOrder)
1249  : QPaintDevice()
1250 {
1251  d = 0;
1252  Format f = formatFor(depth, bitOrder);
1253  if (f == Format_Invalid)
1254  return;
1255  if (!data || w <= 0 || h <= 0 || depth <= 0 || numColors < 0
1256  || INT_MAX/sizeof(uchar *) < uint(h)
1257  || INT_MAX/uint(depth) < uint(w)
1258  || bpl <= 0
1259  || INT_MAX/uint(bpl) < uint(h))
1260  return; // invalid parameter(s)
1261 
1262  d = new QImageData;
1263  d->ref.ref();
1264  d->own_data = false;
1265  d->data = data;
1266  d->width = w;
1267  d->height = h;
1268  d->depth = depth;
1269  d->format = f;
1270  if (depth == 32)
1271  numColors = 0;
1272  d->bytes_per_line = bpl;
1273  d->nbytes = d->bytes_per_line * h;
1274  if (colortable) {
1276  for (int i = 0; i < numColors; ++i)
1277  d->colortable[i] = colortable[i];
1278  } else if (numColors) {
1280  }
1281 }
1282 #endif // Q_WS_QWS
1283 #endif // QT3_SUPPORT
1284 
1290 {
1291  if (d && !d->ref.deref())
1292  delete d;
1293 }
1294 
1305 {
1306  if (image.paintingActive()) {
1307  operator=(image.copy());
1308  } else {
1309  if (image.d)
1310  image.d->ref.ref();
1311  if (d && !d->ref.deref())
1312  delete d;
1313  d = image.d;
1314  }
1315  return *this;
1316 }
1317 
1332 int QImage::devType() const
1333 {
1334  return QInternal::Image;
1335 }
1336 
1340 QImage::operator QVariant() const
1341 {
1342  return QVariant(QVariant::Image, this);
1343 }
1344 
1360 {
1361  if (d) {
1362  if (d->is_cached && d->ref == 1)
1364 
1365  if (d->ref != 1 || d->ro_data)
1366  *this = copy();
1367 
1368  if (d)
1369  ++d->detach_no;
1370  }
1371 }
1372 
1373 
1410 QImage QImage::copy(const QRect& r) const
1411 {
1412  if (!d)
1413  return QImage();
1414 
1415  if (r.isNull()) {
1416  QImage image(d->width, d->height, d->format);
1417  if (image.isNull())
1418  return image;
1419 
1420  // Qt for Embedded Linux can create images with non-default bpl
1421  // make sure we don't crash.
1422  if (image.d->nbytes != d->nbytes) {
1423  int bpl = qMin(bytesPerLine(), image.bytesPerLine());
1424  for (int i = 0; i < height(); i++)
1425  memcpy(image.scanLine(i), scanLine(i), bpl);
1426  } else
1427  memcpy(image.bits(), bits(), d->nbytes);
1428  image.d->colortable = d->colortable;
1429  image.d->dpmx = d->dpmx;
1430  image.d->dpmy = d->dpmy;
1431  image.d->offset = d->offset;
1432  image.d->has_alpha_clut = d->has_alpha_clut;
1433 #ifndef QT_NO_IMAGE_TEXT
1434  image.d->text = d->text;
1435 #endif
1436  return image;
1437  }
1438 
1439  int x = r.x();
1440  int y = r.y();
1441  int w = r.width();
1442  int h = r.height();
1443 
1444  int dx = 0;
1445  int dy = 0;
1446  if (w <= 0 || h <= 0)
1447  return QImage();
1448 
1449  QImage image(w, h, d->format);
1450  if (image.isNull())
1451  return image;
1452 
1453  if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) {
1454  // bitBlt will not cover entire image - clear it.
1455  image.fill(0);
1456  if (x < 0) {
1457  dx = -x;
1458  x = 0;
1459  }
1460  if (y < 0) {
1461  dy = -y;
1462  y = 0;
1463  }
1464  }
1465 
1466  image.d->colortable = d->colortable;
1467 
1468  int pixels_to_copy = qMax(w - dx, 0);
1469  if (x > d->width)
1470  pixels_to_copy = 0;
1471  else if (pixels_to_copy > d->width - x)
1472  pixels_to_copy = d->width - x;
1473  int lines_to_copy = qMax(h - dy, 0);
1474  if (y > d->height)
1475  lines_to_copy = 0;
1476  else if (lines_to_copy > d->height - y)
1477  lines_to_copy = d->height - y;
1478 
1479  bool byteAligned = true;
1480  if (d->format == Format_Mono || d->format == Format_MonoLSB)
1481  byteAligned = !(dx & 7) && !(x & 7) && !(pixels_to_copy & 7);
1482 
1483  if (byteAligned) {
1484  const uchar *src = d->data + ((x * d->depth) >> 3) + y * d->bytes_per_line;
1485  uchar *dest = image.d->data + ((dx * d->depth) >> 3) + dy * image.d->bytes_per_line;
1486  const int bytes_to_copy = (pixels_to_copy * d->depth) >> 3;
1487  for (int i = 0; i < lines_to_copy; ++i) {
1488  memcpy(dest, src, bytes_to_copy);
1489  src += d->bytes_per_line;
1490  dest += image.d->bytes_per_line;
1491  }
1492  } else if (d->format == Format_Mono) {
1493  const uchar *src = d->data + y * d->bytes_per_line;
1494  uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1495  for (int i = 0; i < lines_to_copy; ++i) {
1496  for (int j = 0; j < pixels_to_copy; ++j) {
1497  if (src[(x + j) >> 3] & (0x80 >> ((x + j) & 7)))
1498  dest[(dx + j) >> 3] |= (0x80 >> ((dx + j) & 7));
1499  else
1500  dest[(dx + j) >> 3] &= ~(0x80 >> ((dx + j) & 7));
1501  }
1502  src += d->bytes_per_line;
1503  dest += image.d->bytes_per_line;
1504  }
1505  } else { // Format_MonoLSB
1507  const uchar *src = d->data + y * d->bytes_per_line;
1508  uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1509  for (int i = 0; i < lines_to_copy; ++i) {
1510  for (int j = 0; j < pixels_to_copy; ++j) {
1511  if (src[(x + j) >> 3] & (0x1 << ((x + j) & 7)))
1512  dest[(dx + j) >> 3] |= (0x1 << ((dx + j) & 7));
1513  else
1514  dest[(dx + j) >> 3] &= ~(0x1 << ((dx + j) & 7));
1515  }
1516  src += d->bytes_per_line;
1517  dest += image.d->bytes_per_line;
1518  }
1519  }
1520 
1521  image.d->dpmx = dotsPerMeterX();
1522  image.d->dpmy = dotsPerMeterY();
1523  image.d->offset = offset();
1524  image.d->has_alpha_clut = d->has_alpha_clut;
1525 #ifndef QT_NO_IMAGE_TEXT
1526  image.d->text = d->text;
1527 #endif
1528  return image;
1529 }
1530 
1531 
1542 bool QImage::isNull() const
1543 {
1544  return !d;
1545 }
1546 
1557 int QImage::width() const
1558 {
1559  return d ? d->width : 0;
1560 }
1561 
1572 int QImage::height() const
1573 {
1574  return d ? d->height : 0;
1575 }
1576 
1588 {
1589  return d ? QSize(d->width, d->height) : QSize(0, 0);
1590 }
1591 
1604 {
1605  return d ? QRect(0, 0, d->width, d->height) : QRect();
1606 }
1607 
1620 int QImage::depth() const
1621 {
1622  return d ? d->depth : 0;
1623 }
1624 
1637 {
1638  return d ? d->colortable.size() : 0;
1639 }
1640 
1657 {
1658  return d ? d->colortable.size() : 0;
1659 }
1660 
1661 
1662 #ifdef QT3_SUPPORT
1663 
1685 uchar **QImage::jumpTable()
1686 {
1687  if (!d)
1688  return 0;
1689  detach();
1690 
1691  // in case detach() ran out of memory..
1692  if (!d)
1693  return 0;
1694 
1695  if (!d->jumptable) {
1696  d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *));
1697  if (!d->jumptable)
1698  return 0;
1699  uchar *data = d->data;
1700  int height = d->height;
1701  uchar **p = d->jumptable;
1702  while (height--) {
1703  *p++ = data;
1704  data += d->bytes_per_line;
1705  }
1706  }
1707  return d->jumptable;
1708 }
1709 
1713 const uchar * const *QImage::jumpTable() const
1714 {
1715  if (!d)
1716  return 0;
1717  if (!d->jumptable) {
1718  d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *));
1719  if (!d->jumptable)
1720  return 0;
1721  uchar *data = d->data;
1722  int height = d->height;
1723  uchar **p = d->jumptable;
1724  while (height--) {
1725  *p++ = data;
1726  data += d->bytes_per_line;
1727  }
1728  }
1729  return d->jumptable;
1730 }
1731 #endif
1732 
1745 {
1746  if (!d)
1747  return;
1748  detach();
1749 
1750  // In case detach() ran out of memory
1751  if (!d)
1752  return;
1753 
1754  d->colortable = colors;
1755  d->has_alpha_clut = false;
1756  for (int i = 0; i < d->colortable.size(); ++i) {
1757  if (qAlpha(d->colortable.at(i)) != 255) {
1758  d->has_alpha_clut = true;
1759  break;
1760  }
1761  }
1762 }
1763 
1771 {
1772  return d ? d->colortable : QVector<QRgb>();
1773 }
1774 
1775 
1785 int QImage::numBytes() const
1786 {
1787  return d ? d->nbytes : 0;
1788 }
1789 
1801 {
1802  return d ? d->nbytes : 0;
1803 }
1804 
1813 {
1814  return (d && d->height) ? d->nbytes / d->height : 0;
1815 }
1816 
1817 
1829 QRgb QImage::color(int i) const
1830 {
1831  Q_ASSERT(i < colorCount());
1832  return d ? d->colortable.at(i) : QRgb(uint(-1));
1833 }
1834 
1851 {
1852  if (!d)
1853  return;
1854  if (i < 0 || d->depth > 8 || i >= 1<<d->depth) {
1855  qWarning("QImage::setColor: Index out of bound %d", i);
1856  return;
1857  }
1858  detach();
1859 
1860  // In case detach() run out of memory
1861  if (!d)
1862  return;
1863 
1864  if (i >= d->colortable.size())
1865  setColorCount(i+1);
1866  d->colortable[i] = c;
1867  d->has_alpha_clut |= (qAlpha(c) != 255);
1868 }
1869 
1887 {
1888  if (!d)
1889  return 0;
1890 
1891  detach();
1892 
1893  // In case detach() ran out of memory
1894  if (!d)
1895  return 0;
1896 
1897  return d->data + i * d->bytes_per_line;
1898 }
1899 
1903 const uchar *QImage::scanLine(int i) const
1904 {
1905  if (!d)
1906  return 0;
1907 
1908  Q_ASSERT(i >= 0 && i < height());
1909  return d->data + i * d->bytes_per_line;
1910 }
1911 
1912 
1926 const uchar *QImage::constScanLine(int i) const
1927 {
1928  if (!d)
1929  return 0;
1930 
1931  Q_ASSERT(i >= 0 && i < height());
1932  return d->data + i * d->bytes_per_line;
1933 }
1934 
1947 {
1948  if (!d)
1949  return 0;
1950  detach();
1951 
1952  // In case detach ran out of memory...
1953  if (!d)
1954  return 0;
1955 
1956  return d->data;
1957 }
1958 
1969 const uchar *QImage::bits() const
1970 {
1971  return d ? d->data : 0;
1972 }
1973 
1974 
1985 const uchar *QImage::constBits() const
1986 {
1987  return d ? d->data : 0;
1988 }
1989 
2033 {
2034  if (!d)
2035  return;
2036 
2037  detach();
2038 
2039  // In case detach() ran out of memory
2040  if (!d)
2041  return;
2042 
2043  if (d->depth == 1 || d->depth == 8) {
2044  int w = d->width;
2045  if (d->depth == 1) {
2046  if (pixel & 1)
2047  pixel = 0xffffffff;
2048  else
2049  pixel = 0;
2050  w = (w + 7) / 8;
2051  } else {
2052  pixel &= 0xff;
2053  }
2054  qt_rectfill<quint8>(d->data, pixel, 0, 0,
2055  w, d->height, d->bytes_per_line);
2056  return;
2057  } else if (d->depth == 16) {
2058  qt_rectfill<quint16>(reinterpret_cast<quint16*>(d->data), pixel,
2059  0, 0, d->width, d->height, d->bytes_per_line);
2060  return;
2061  } else if (d->depth == 24) {
2062  qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
2063  0, 0, d->width, d->height, d->bytes_per_line);
2064  return;
2065  }
2066 
2067  if (d->format == Format_RGB32)
2068  pixel |= 0xff000000;
2069 
2070  qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
2071  0, 0, d->width, d->height, d->bytes_per_line);
2072 }
2073 
2074 
2088 {
2089  fill(QColor(color));
2090 }
2091 
2092 
2093 
2115 {
2116  if (!d)
2117  return;
2118  detach();
2119 
2120  // In case we run out of memory
2121  if (!d)
2122  return;
2123 
2124  if (d->depth == 32) {
2125  uint pixel = color.rgba();
2127  pixel = PREMUL(pixel);
2128  fill((uint) pixel);
2129 
2130  } else if (d->depth == 16 && d->format == QImage::Format_RGB16) {
2131  qrgb565 p(color.rgba());
2132  fill((uint) p.rawValue());
2133 
2134  } else if (d->depth == 1) {
2135  if (color == Qt::color1)
2136  fill((uint) 1);
2137  else
2138  fill((uint) 0);
2139 
2140  } else if (d->depth == 8) {
2141  uint pixel = 0;
2142  for (int i=0; i<d->colortable.size(); ++i) {
2143  if (color.rgba() == d->colortable.at(i)) {
2144  pixel = i;
2145  break;
2146  }
2147  }
2148  fill(pixel);
2149 
2150  } else {
2151  QPainter p(this);
2153  p.fillRect(rect(), color);
2154  }
2155 
2156 }
2157 
2158 
2159 
2160 
2161 
2162 
2180 {
2181  if (!d)
2182  return;
2183 
2184  detach();
2185 
2186  // In case detach() ran out of memory
2187  if (!d)
2188  return;
2189 
2190  if (depth() != 32) {
2191  // number of used bytes pr line
2192  int bpl = (d->width * d->depth + 7) / 8;
2193  int pad = d->bytes_per_line - bpl;
2194  uchar *sl = d->data;
2195  for (int y=0; y<d->height; ++y) {
2196  for (int x=0; x<bpl; ++x)
2197  *sl++ ^= 0xff;
2198  sl += pad;
2199  }
2200  } else {
2201  quint32 *p = (quint32*)d->data;
2202  quint32 *end = (quint32*)(d->data + d->nbytes);
2203  uint xorbits = (mode == InvertRgba) ? 0xffffffff : 0x00ffffff;
2204  while (p < end)
2205  *p++ ^= xorbits;
2206  }
2207 }
2208 
2231 // Windows defines these
2232 #if defined(write)
2233 # undef write
2234 #endif
2235 #if defined(close)
2236 # undef close
2237 #endif
2238 #if defined(read)
2239 # undef read
2240 #endif
2241 
2253 {
2254  setColorCount(numColors);
2255 }
2256 
2276 {
2277  if (!d) {
2278  qWarning("QImage::setColorCount: null image");
2279  return;
2280  }
2281 
2282  detach();
2283 
2284  // In case detach() ran out of memory
2285  if (!d)
2286  return;
2287 
2288  if (colorCount == d->colortable.size())
2289  return;
2290  if (colorCount <= 0) { // use no color table
2291  d->colortable = QVector<QRgb>();
2292  return;
2293  }
2294  int nc = d->colortable.size();
2295  d->colortable.resize(colorCount);
2296  for (int i = nc; i < colorCount; ++i)
2297  d->colortable[i] = 0;
2298 }
2299 
2306 {
2307  return d ? d->format : Format_Invalid;
2308 }
2309 
2310 
2311 #ifdef QT3_SUPPORT
2312 
2319 bool QImage::hasAlphaBuffer() const
2320 {
2321  if (!d)
2322  return false;
2323 
2324  switch (d->format) {
2325  case Format_ARGB32:
2331  return true;
2332  default:
2333  return false;
2334  }
2335 }
2336 
2348 void QImage::setAlphaBuffer(bool enable)
2349 {
2350  if (!d
2351  || d->format == Format_Mono
2352  || d->format == Format_MonoLSB
2353  || d->format == Format_Indexed8)
2354  return;
2355  if (enable && (d->format == Format_ARGB32 ||
2361  {
2362  return;
2363  }
2364  if (!enable && (d->format == Format_RGB32 ||
2365  d->format == Format_RGB555 ||
2366  d->format == Format_RGB666 ||
2367  d->format == Format_RGB888 ||
2368  d->format == Format_RGB444))
2369  {
2370  return;
2371  }
2372  detach();
2373  d->format = (enable ? Format_ARGB32 : Format_RGB32);
2374 }
2375 
2376 
2400 bool QImage::create(int width, int height, int depth, int numColors, Endian bitOrder)
2401 {
2402  if (d && !d->ref.deref())
2403  delete d;
2404  d = QImageData::create(QSize(width, height), formatFor(depth, bitOrder), numColors);
2405  return true;
2406 }
2407 
2419 bool QImage::create(const QSize& size, int depth, int numColors, QImage::Endian bitOrder)
2420 {
2421  if (d && !d->ref.deref())
2422  delete d;
2423  d = QImageData::create(size, formatFor(depth, bitOrder), numColors);
2424  return true;
2425 }
2426 #endif // QT3_SUPPORT
2427 
2428 /*****************************************************************************
2429  Internal routines for converting image depth.
2430  *****************************************************************************/
2431 
2432 typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
2433 
2434 typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags);
2435 
2436 static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
2437 {
2440  Q_ASSERT(src->width == dest->width);
2441  Q_ASSERT(src->height == dest->height);
2442 
2443  const int src_pad = (src->bytes_per_line >> 2) - src->width;
2444  const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
2445  const QRgb *src_data = (QRgb *) src->data;
2446  QRgb *dest_data = (QRgb *) dest->data;
2447 
2448  for (int i = 0; i < src->height; ++i) {
2449  const QRgb *end = src_data + src->width;
2450  while (src_data < end) {
2451  *dest_data = PREMUL(*src_data);
2452  ++src_data;
2453  ++dest_data;
2454  }
2455  src_data += src_pad;
2456  dest_data += dest_pad;
2457  }
2458 }
2459 
2460 static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
2461 {
2463 
2464  const int pad = (data->bytes_per_line >> 2) - data->width;
2465  QRgb *rgb_data = (QRgb *) data->data;
2466 
2467  for (int i = 0; i < data->height; ++i) {
2468  const QRgb *end = rgb_data + data->width;
2469  while (rgb_data < end) {
2470  *rgb_data = PREMUL(*rgb_data);
2471  ++rgb_data;
2472  }
2473  rgb_data += pad;
2474  }
2476  return true;
2477 }
2478 
2479 static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
2480 {
2482  const int depth = 32;
2483 
2484  const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
2485  const int nbytes = dst_bytes_per_line * data->height;
2486  uchar *const newData = (uchar *)realloc(data->data, nbytes);
2487  if (!newData)
2488  return false;
2489 
2490  data->data = newData;
2491 
2492  // start converting from the end because the end image is bigger than the source
2493  uchar *src_data = newData + data->nbytes; // end of src
2494  quint32 *dest_data = (quint32 *) (newData + nbytes); // end of dest > end of src
2495  const int width = data->width;
2496  const int src_pad = data->bytes_per_line - width;
2497  const int dest_pad = (dst_bytes_per_line >> 2) - width;
2498  if (data->colortable.size() == 0) {
2499  data->colortable.resize(256);
2500  for (int i = 0; i < 256; ++i)
2501  data->colortable[i] = qRgb(i, i, i);
2502  } else {
2503  for (int i = 0; i < data->colortable.size(); ++i)
2504  data->colortable[i] = PREMUL(data->colortable.at(i));
2505 
2506  // Fill the rest of the table in case src_data > colortable.size()
2507  const int oldSize = data->colortable.size();
2508  const QRgb lastColor = data->colortable.at(oldSize - 1);
2509  data->colortable.insert(oldSize, 256 - oldSize, lastColor);
2510  }
2511 
2512  for (int i = 0; i < data->height; ++i) {
2513  src_data -= src_pad;
2514  dest_data -= dest_pad;
2515  for (int pixI = 0; pixI < width; ++pixI) {
2516  --src_data;
2517  --dest_data;
2518  *dest_data = data->colortable.at(*src_data);
2519  }
2520  }
2521 
2522  data->colortable = QVector<QRgb>();
2524  data->bytes_per_line = dst_bytes_per_line;
2525  data->depth = depth;
2526  data->nbytes = nbytes;
2527 
2528  return true;
2529 }
2530 
2531 static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags)
2532 {
2534  const int depth = 32;
2535 
2536  const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
2537  const int nbytes = dst_bytes_per_line * data->height;
2538  uchar *const newData = (uchar *)realloc(data->data, nbytes);
2539  if (!newData)
2540  return false;
2541 
2542  data->data = newData;
2543 
2544  // start converting from the end because the end image is bigger than the source
2545  uchar *src_data = newData + data->nbytes;
2546  quint32 *dest_data = (quint32 *) (newData + nbytes);
2547  const int width = data->width;
2548  const int src_pad = data->bytes_per_line - width;
2549  const int dest_pad = (dst_bytes_per_line >> 2) - width;
2550  if (data->colortable.size() == 0) {
2551  data->colortable.resize(256);
2552  for (int i = 0; i < 256; ++i)
2553  data->colortable[i] = qRgb(i, i, i);
2554  } else {
2555  // Fill the rest of the table in case src_data > colortable.size()
2556  const int oldSize = data->colortable.size();
2557  const QRgb lastColor = data->colortable.at(oldSize - 1);
2558  data->colortable.insert(oldSize, 256 - oldSize, lastColor);
2559  }
2560 
2561  for (int i = 0; i < data->height; ++i) {
2562  src_data -= src_pad;
2563  dest_data -= dest_pad;
2564  for (int pixI = 0; pixI < width; ++pixI) {
2565  --src_data;
2566  --dest_data;
2567  *dest_data = (quint32) data->colortable.at(*src_data);
2568  }
2569  }
2570 
2571  data->colortable = QVector<QRgb>();
2572  data->format = QImage::Format_RGB32;
2573  data->bytes_per_line = dst_bytes_per_line;
2574  data->depth = depth;
2575  data->nbytes = nbytes;
2576 
2577  return true;
2578 }
2579 
2580 static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
2581 {
2583  const int depth = 16;
2584 
2585  const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
2586  const int nbytes = dst_bytes_per_line * data->height;
2587  uchar *const newData = (uchar *)realloc(data->data, nbytes);
2588  if (!newData)
2589  return false;
2590 
2591  data->data = newData;
2592 
2593  // start converting from the end because the end image is bigger than the source
2594  uchar *src_data = newData + data->nbytes;
2595  quint16 *dest_data = (quint16 *) (newData + nbytes);
2596  const int width = data->width;
2597  const int src_pad = data->bytes_per_line - width;
2598  const int dest_pad = (dst_bytes_per_line >> 1) - width;
2599 
2600  quint16 colorTableRGB16[256];
2601  if (data->colortable.isEmpty()) {
2602  for (int i = 0; i < 256; ++i)
2603  colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(qRgb(i, i, i), 0);
2604  } else {
2605  // 1) convert the existing colors to RGB16
2606  const int tableSize = data->colortable.size();
2607  for (int i = 0; i < tableSize; ++i)
2608  colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(data->colortable.at(i), 0);
2609  data->colortable = QVector<QRgb>();
2610 
2611  // 2) fill the rest of the table in case src_data > colortable.size()
2612  const quint16 lastColor = colorTableRGB16[tableSize - 1];
2613  for (int i = tableSize; i < 256; ++i)
2614  colorTableRGB16[i] = lastColor;
2615  }
2616 
2617  for (int i = 0; i < data->height; ++i) {
2618  src_data -= src_pad;
2619  dest_data -= dest_pad;
2620  for (int pixI = 0; pixI < width; ++pixI) {
2621  --src_data;
2622  --dest_data;
2623  *dest_data = colorTableRGB16[*src_data];
2624  }
2625  }
2626 
2627  data->format = QImage::Format_RGB16;
2628  data->bytes_per_line = dst_bytes_per_line;
2629  data->depth = depth;
2630  data->nbytes = nbytes;
2631 
2632  return true;
2633 }
2634 
2635 static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
2636 {
2638  const int depth = 16;
2639 
2640  const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
2641  const int src_bytes_per_line = data->bytes_per_line;
2642  quint32 *src_data = (quint32 *) data->data;
2643  quint16 *dst_data = (quint16 *) data->data;
2644 
2645  for (int i = 0; i < data->height; ++i) {
2646  qt_memconvert(dst_data, src_data, data->width);
2647  src_data = (quint32 *) (((char*)src_data) + src_bytes_per_line);
2648  dst_data = (quint16 *) (((char*)dst_data) + dst_bytes_per_line);
2649  }
2650  data->format = QImage::Format_RGB16;
2651  data->bytes_per_line = dst_bytes_per_line;
2652  data->depth = depth;
2653  data->nbytes = dst_bytes_per_line * data->height;
2654  uchar *const newData = (uchar *)realloc(data->data, data->nbytes);
2655  if (newData) {
2656  data->data = newData;
2657  return true;
2658  } else {
2659  return false;
2660  }
2661 }
2662 
2663 static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
2664 {
2667  Q_ASSERT(src->width == dest->width);
2668  Q_ASSERT(src->height == dest->height);
2669 
2670  const int src_pad = (src->bytes_per_line >> 2) - src->width;
2671  const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
2672  const QRgb *src_data = (QRgb *) src->data;
2673  QRgb *dest_data = (QRgb *) dest->data;
2674 
2675  for (int i = 0; i < src->height; ++i) {
2676  const QRgb *end = src_data + src->width;
2677  while (src_data < end) {
2678  *dest_data = INV_PREMUL(*src_data);
2679  ++src_data;
2680  ++dest_data;
2681  }
2682  src_data += src_pad;
2683  dest_data += dest_pad;
2684  }
2685 }
2686 
2687 static void convert_ARGB_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
2688 {
2691  Q_ASSERT(src->width == dest->width);
2692  Q_ASSERT(src->height == dest->height);
2693 
2694  const int src_pad = (src->bytes_per_line >> 2) - src->width;
2695  const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
2696  const QRgb *src_data = (QRgb *) src->data;
2697  QRgb *dest_data = (QRgb *) dest->data;
2698 
2699  for (int i = 0; i < src->height; ++i) {
2700  const QRgb *end = src_data + src->width;
2701  while (src_data < end) {
2702  *dest_data = 0xff000000 | INV_PREMUL(*src_data);
2703  ++src_data;
2704  ++dest_data;
2705  }
2706  src_data += src_pad;
2707  dest_data += dest_pad;
2708  }
2709 }
2710 
2711 static void swap_bit_order(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
2712 {
2715  Q_ASSERT(src->width == dest->width);
2716  Q_ASSERT(src->height == dest->height);
2717  Q_ASSERT(src->nbytes == dest->nbytes);
2718  Q_ASSERT(src->bytes_per_line == dest->bytes_per_line);
2719 
2720  dest->colortable = src->colortable;
2721 
2722  const uchar *src_data = src->data;
2723  const uchar *end = src->data + src->nbytes;
2724  uchar *dest_data = dest->data;
2725  while (src_data < end) {
2726  *dest_data = bitflip[*src_data];
2727  ++src_data;
2728  ++dest_data;
2729  }
2730 }
2731 
2732 static void mask_alpha_converter(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
2733 {
2734  Q_ASSERT(src->width == dest->width);
2735  Q_ASSERT(src->height == dest->height);
2736 
2737  const int src_pad = (src->bytes_per_line >> 2) - src->width;
2738  const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
2739  const uint *src_data = (const uint *)src->data;
2740  uint *dest_data = (uint *)dest->data;
2741 
2742  for (int i = 0; i < src->height; ++i) {
2743  const uint *end = src_data + src->width;
2744  while (src_data < end) {
2745  *dest_data = *src_data | 0xff000000;
2746  ++src_data;
2747  ++dest_data;
2748  }
2749  src_data += src_pad;
2750  dest_data += dest_pad;
2751  }
2752 }
2753 
2755 {
2756  QVector<QRgb> colorTable = ctbl;
2757  if (format == QImage::Format_RGB32) {
2758  // check if the color table has alpha
2759  for (int i = 0; i < colorTable.size(); ++i)
2760  if (qAlpha(colorTable.at(i) != 0xff))
2761  colorTable[i] = colorTable.at(i) | 0xff000000;
2762  } else if (format == QImage::Format_ARGB32_Premultiplied) {
2763  // check if the color table has alpha
2764  for (int i = 0; i < colorTable.size(); ++i)
2765  colorTable[i] = PREMUL(colorTable.at(i));
2766  }
2767  return colorTable;
2768 }
2769 
2770 //
2771 // dither_to_1: Uses selected dithering algorithm.
2772 //
2773 
2774 static void dither_to_Mono(QImageData *dst, const QImageData *src,
2775  Qt::ImageConversionFlags flags, bool fromalpha)
2776 {
2777  Q_ASSERT(src->width == dst->width);
2778  Q_ASSERT(src->height == dst->height);
2780 
2781  dst->colortable.clear();
2782  dst->colortable.append(0xffffffff);
2783  dst->colortable.append(0xff000000);
2784 
2785  enum { Threshold, Ordered, Diffuse } dithermode;
2786 
2787  if (fromalpha) {
2789  dithermode = Diffuse;
2790  else if ((flags & Qt::AlphaDither_Mask) == Qt::OrderedAlphaDither)
2791  dithermode = Ordered;
2792  else
2793  dithermode = Threshold;
2794  } else {
2795  if ((flags & Qt::Dither_Mask) == Qt::ThresholdDither)
2796  dithermode = Threshold;
2797  else if ((flags & Qt::Dither_Mask) == Qt::OrderedDither)
2798  dithermode = Ordered;
2799  else
2800  dithermode = Diffuse;
2801  }
2802 
2803  int w = src->width;
2804  int h = src->height;
2805  int d = src->depth;
2806  uchar gray[256]; // gray map for 8 bit images
2807  bool use_gray = (d == 8);
2808  if (use_gray) { // make gray map
2809  if (fromalpha) {
2810  // Alpha 0x00 -> 0 pixels (white)
2811  // Alpha 0xFF -> 1 pixels (black)
2812  for (int i = 0; i < src->colortable.size(); i++)
2813  gray[i] = (255 - (src->colortable.at(i) >> 24));
2814  } else {
2815  // Pixel 0x00 -> 1 pixels (black)
2816  // Pixel 0xFF -> 0 pixels (white)
2817  for (int i = 0; i < src->colortable.size(); i++)
2818  gray[i] = qGray(src->colortable.at(i));
2819  }
2820  }
2821 
2822  uchar *dst_data = dst->data;
2823  int dst_bpl = dst->bytes_per_line;
2824  const uchar *src_data = src->data;
2825  int src_bpl = src->bytes_per_line;
2826 
2827  switch (dithermode) {
2828  case Diffuse: {
2829  QScopedArrayPointer<int> lineBuffer(new int[w * 2]);
2830  int *line1 = lineBuffer.data();
2831  int *line2 = lineBuffer.data() + w;
2832  int bmwidth = (w+7)/8;
2833 
2834  int *b1, *b2;
2835  int wbytes = w * (d/8);
2836  register const uchar *p = src->data;
2837  const uchar *end = p + wbytes;
2838  b2 = line2;
2839  if (use_gray) { // 8 bit image
2840  while (p < end)
2841  *b2++ = gray[*p++];
2842  } else { // 32 bit image
2843  if (fromalpha) {
2844  while (p < end) {
2845  *b2++ = 255 - (*(uint*)p >> 24);
2846  p += 4;
2847  }
2848  } else {
2849  while (p < end) {
2850  *b2++ = qGray(*(uint*)p);
2851  p += 4;
2852  }
2853  }
2854  }
2855  for (int y=0; y<h; y++) { // for each scan line...
2856  int *tmp = line1; line1 = line2; line2 = tmp;
2857  bool not_last_line = y < h - 1;
2858  if (not_last_line) { // calc. grayvals for next line
2859  p = src->data + (y+1)*src->bytes_per_line;
2860  end = p + wbytes;
2861  b2 = line2;
2862  if (use_gray) { // 8 bit image
2863  while (p < end)
2864  *b2++ = gray[*p++];
2865  } else { // 24 bit image
2866  if (fromalpha) {
2867  while (p < end) {
2868  *b2++ = 255 - (*(uint*)p >> 24);
2869  p += 4;
2870  }
2871  } else {
2872  while (p < end) {
2873  *b2++ = qGray(*(uint*)p);
2874  p += 4;
2875  }
2876  }
2877  }
2878  }
2879 
2880  int err;
2881  uchar *p = dst->data + y*dst->bytes_per_line;
2882  memset(p, 0, bmwidth);
2883  b1 = line1;
2884  b2 = line2;
2885  int bit = 7;
2886  for (int x=1; x<=w; x++) {
2887  if (*b1 < 128) { // black pixel
2888  err = *b1++;
2889  *p |= 1 << bit;
2890  } else { // white pixel
2891  err = *b1++ - 255;
2892  }
2893  if (bit == 0) {
2894  p++;
2895  bit = 7;
2896  } else {
2897  bit--;
2898  }
2899  if (x < w)
2900  *b1 += (err*7)>>4; // spread error to right pixel
2901  if (not_last_line) {
2902  b2[0] += (err*5)>>4; // pixel below
2903  if (x > 1)
2904  b2[-1] += (err*3)>>4; // pixel below left
2905  if (x < w)
2906  b2[1] += err>>4; // pixel below right
2907  }
2908  b2++;
2909  }
2910  }
2911  } break;
2912  case Ordered: {
2913 
2914  memset(dst->data, 0, dst->nbytes);
2915  if (d == 32) {
2916  for (int i=0; i<h; i++) {
2917  const uint *p = (const uint *)src_data;
2918  const uint *end = p + w;
2919  uchar *m = dst_data;
2920  int bit = 7;
2921  int j = 0;
2922  if (fromalpha) {
2923  while (p < end) {
2924  if ((*p++ >> 24) >= qt_bayer_matrix[j++&15][i&15])
2925  *m |= 1 << bit;
2926  if (bit == 0) {
2927  m++;
2928  bit = 7;
2929  } else {
2930  bit--;
2931  }
2932  }
2933  } else {
2934  while (p < end) {
2935  if ((uint)qGray(*p++) < qt_bayer_matrix[j++&15][i&15])
2936  *m |= 1 << bit;
2937  if (bit == 0) {
2938  m++;
2939  bit = 7;
2940  } else {
2941  bit--;
2942  }
2943  }
2944  }
2945  dst_data += dst_bpl;
2946  src_data += src_bpl;
2947  }
2948  } else
2949  /* (d == 8) */ {
2950  for (int i=0; i<h; i++) {
2951  const uchar *p = src_data;
2952  const uchar *end = p + w;
2953  uchar *m = dst_data;
2954  int bit = 7;
2955  int j = 0;
2956  while (p < end) {
2957  if ((uint)gray[*p++] < qt_bayer_matrix[j++&15][i&15])
2958  *m |= 1 << bit;
2959  if (bit == 0) {
2960  m++;
2961  bit = 7;
2962  } else {
2963  bit--;
2964  }
2965  }
2966  dst_data += dst_bpl;
2967  src_data += src_bpl;
2968  }
2969  }
2970  } break;
2971  default: { // Threshold:
2972  memset(dst->data, 0, dst->nbytes);
2973  if (d == 32) {
2974  for (int i=0; i<h; i++) {
2975  const uint *p = (const uint *)src_data;
2976  const uint *end = p + w;
2977  uchar *m = dst_data;
2978  int bit = 7;
2979  if (fromalpha) {
2980  while (p < end) {
2981  if ((*p++ >> 24) >= 128)
2982  *m |= 1 << bit; // Set mask "on"
2983  if (bit == 0) {
2984  m++;
2985  bit = 7;
2986  } else {
2987  bit--;
2988  }
2989  }
2990  } else {
2991  while (p < end) {
2992  if (qGray(*p++) < 128)
2993  *m |= 1 << bit; // Set pixel "black"
2994  if (bit == 0) {
2995  m++;
2996  bit = 7;
2997  } else {
2998  bit--;
2999  }
3000  }
3001  }
3002  dst_data += dst_bpl;
3003  src_data += src_bpl;
3004  }
3005  } else
3006  if (d == 8) {
3007  for (int i=0; i<h; i++) {
3008  const uchar *p = src_data;
3009  const uchar *end = p + w;
3010  uchar *m = dst_data;
3011  int bit = 7;
3012  while (p < end) {
3013  if (gray[*p++] < 128)
3014  *m |= 1 << bit; // Set mask "on"/ pixel "black"
3015  if (bit == 0) {
3016  m++;
3017  bit = 7;
3018  } else {
3019  bit--;
3020  }
3021  }
3022  dst_data += dst_bpl;
3023  src_data += src_bpl;
3024  }
3025  }
3026  }
3027  }
3028 
3029  if (dst->format == QImage::Format_MonoLSB) {
3030  // need to swap bit order
3031  uchar *sl = dst->data;
3032  int bpl = (dst->width + 7) * dst->depth / 8;
3033  int pad = dst->bytes_per_line - bpl;
3034  for (int y=0; y<dst->height; ++y) {
3035  for (int x=0; x<bpl; ++x) {
3036  *sl = bitflip[*sl];
3037  ++sl;
3038  }
3039  sl += pad;
3040  }
3041  }
3042 }
3043 
3044 static void convert_X_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
3045 {
3046  dither_to_Mono(dst, src, flags, false);
3047 }
3048 
3049 static void convert_ARGB_PM_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
3050 {
3052  convert_ARGB_PM_to_ARGB(tmp.data(), src, flags);
3053  dither_to_Mono(dst, tmp.data(), flags, false);
3054 }
3055 
3056 //
3057 // convert_32_to_8: Converts a 32 bits depth (true color) to an 8 bit
3058 // image with a colormap. If the 32 bit image has more than 256 colors,
3059 // we convert the red,green and blue bytes into a single byte encoded
3060 // as 6 shades of each of red, green and blue.
3061 //
3062 // if dithering is needed, only 1 color at most is available for alpha.
3063 //
3064 struct QRgbMap {
3065  inline QRgbMap() : used(0) { }
3069 };
3070 
3071 static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
3072 {
3075  Q_ASSERT(src->width == dst->width);
3076  Q_ASSERT(src->height == dst->height);
3077 
3078  bool do_quant = (flags & Qt::DitherMode_Mask) == Qt::PreferDither
3079  || src->format == QImage::Format_ARGB32;
3080  uint alpha_mask = src->format == QImage::Format_RGB32 ? 0xff000000 : 0;
3081 
3082  const int tablesize = 997; // prime
3083  QRgbMap table[tablesize];
3084  int pix=0;
3085 
3086  if (!dst->colortable.isEmpty()) {
3087  QVector<QRgb> ctbl = dst->colortable;
3088  dst->colortable.resize(256);
3089  // Preload palette into table.
3090  // Almost same code as pixel insertion below
3091  for (int i = 0; i < dst->colortable.size(); ++i) {
3092  // Find in table...
3093  QRgb p = ctbl.at(i) | alpha_mask;
3094  int hash = p % tablesize;
3095  for (;;) {
3096  if (table[hash].used) {
3097  if (table[hash].rgb == p) {
3098  // Found previous insertion - use it
3099  break;
3100  } else {
3101  // Keep searching...
3102  if (++hash == tablesize) hash = 0;
3103  }
3104  } else {
3105  // Cannot be in table
3106  Q_ASSERT (pix != 256); // too many colors
3107  // Insert into table at this unused position
3108  dst->colortable[pix] = p;
3109  table[hash].pix = pix++;
3110  table[hash].rgb = p;
3111  table[hash].used = 1;
3112  break;
3113  }
3114  }
3115  }
3116  }
3117 
3118  if ((flags & Qt::DitherMode_Mask) != Qt::PreferDither) {
3119  dst->colortable.resize(256);
3120  const uchar *src_data = src->data;
3121  uchar *dest_data = dst->data;
3122  for (int y = 0; y < src->height; y++) { // check if <= 256 colors
3123  const QRgb *s = (const QRgb *)src_data;
3124  uchar *b = dest_data;
3125  for (int x = 0; x < src->width; ++x) {
3126  QRgb p = s[x] | alpha_mask;
3127  int hash = p % tablesize;
3128  for (;;) {
3129  if (table[hash].used) {
3130  if (table[hash].rgb == (p)) {
3131  // Found previous insertion - use it
3132  break;
3133  } else {
3134  // Keep searching...
3135  if (++hash == tablesize) hash = 0;
3136  }
3137  } else {
3138  // Cannot be in table
3139  if (pix == 256) { // too many colors
3140  do_quant = true;
3141  // Break right out
3142  x = src->width;
3143  y = src->height;
3144  } else {
3145  // Insert into table at this unused position
3146  dst->colortable[pix] = p;
3147  table[hash].pix = pix++;
3148  table[hash].rgb = p;
3149  table[hash].used = 1;
3150  }
3151  break;
3152  }
3153  }
3154  *b++ = table[hash].pix; // May occur once incorrectly
3155  }
3156  src_data += src->bytes_per_line;
3157  dest_data += dst->bytes_per_line;
3158  }
3159  }
3160  int numColors = do_quant ? 256 : pix;
3161 
3162  dst->colortable.resize(numColors);
3163 
3164  if (do_quant) { // quantization needed
3165 
3166 #define MAX_R 5
3167 #define MAX_G 5
3168 #define MAX_B 5
3169 #define INDEXOF(r,g,b) (((r)*(MAX_G+1)+(g))*(MAX_B+1)+(b))
3170 
3171  for (int rc=0; rc<=MAX_R; rc++) // build 6x6x6 color cube
3172  for (int gc=0; gc<=MAX_G; gc++)
3173  for (int bc=0; bc<=MAX_B; bc++)
3174  dst->colortable[INDEXOF(rc,gc,bc)] = 0xff000000 | qRgb(rc*255/MAX_R, gc*255/MAX_G, bc*255/MAX_B);
3175 
3176  const uchar *src_data = src->data;
3177  uchar *dest_data = dst->data;
3178  if ((flags & Qt::Dither_Mask) == Qt::ThresholdDither) {
3179  for (int y = 0; y < src->height; y++) {
3180  const QRgb *p = (const QRgb *)src_data;
3181  const QRgb *end = p + src->width;
3182  uchar *b = dest_data;
3183 
3184  while (p < end) {
3185 #define DITHER(p,m) ((uchar) ((p * (m) + 127) / 255))
3186  *b++ =
3187  INDEXOF(
3188  DITHER(qRed(*p), MAX_R),
3189  DITHER(qGreen(*p), MAX_G),
3190  DITHER(qBlue(*p), MAX_B)
3191  );
3192 #undef DITHER
3193  p++;
3194  }
3195  src_data += src->bytes_per_line;
3196  dest_data += dst->bytes_per_line;
3197  }
3198  } else if ((flags & Qt::Dither_Mask) == Qt::DiffuseDither) {
3199  int* line1[3];
3200  int* line2[3];
3201  int* pv[3];
3202  QScopedArrayPointer<int> lineBuffer(new int[src->width * 9]);
3203  line1[0] = lineBuffer.data();
3204  line2[0] = lineBuffer.data() + src->width;
3205  line1[1] = lineBuffer.data() + src->width * 2;
3206  line2[1] = lineBuffer.data() + src->width * 3;
3207  line1[2] = lineBuffer.data() + src->width * 4;
3208  line2[2] = lineBuffer.data() + src->width * 5;
3209  pv[0] = lineBuffer.data() + src->width * 6;
3210  pv[1] = lineBuffer.data() + src->width * 7;
3211  pv[2] = lineBuffer.data() + src->width * 8;
3212 
3213  int endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian);
3214  for (int y = 0; y < src->height; y++) {
3215  const uchar* q = src_data;
3216  const uchar* q2 = y < src->height - 1 ? q + src->bytes_per_line : src->data;
3217  uchar *b = dest_data;
3218  for (int chan = 0; chan < 3; chan++) {
3219  int *l1 = (y&1) ? line2[chan] : line1[chan];
3220  int *l2 = (y&1) ? line1[chan] : line2[chan];
3221  if (y == 0) {
3222  for (int i = 0; i < src->width; i++)
3223  l1[i] = q[i*4+chan+endian];
3224  }
3225  if (y+1 < src->height) {
3226  for (int i = 0; i < src->width; i++)
3227  l2[i] = q2[i*4+chan+endian];
3228  }
3229  // Bi-directional error diffusion
3230  if (y&1) {
3231  for (int x = 0; x < src->width; x++) {
3232  int pix = qMax(qMin(5, (l1[x] * 5 + 128)/ 255), 0);
3233  int err = l1[x] - pix * 255 / 5;
3234  pv[chan][x] = pix;
3235 
3236  // Spread the error around...
3237  if (x + 1< src->width) {
3238  l1[x+1] += (err*7)>>4;
3239  l2[x+1] += err>>4;
3240  }
3241  l2[x]+=(err*5)>>4;
3242  if (x>1)
3243  l2[x-1]+=(err*3)>>4;
3244  }
3245  } else {
3246  for (int x = src->width; x-- > 0;) {
3247  int pix = qMax(qMin(5, (l1[x] * 5 + 128)/ 255), 0);
3248  int err = l1[x] - pix * 255 / 5;
3249  pv[chan][x] = pix;
3250 
3251  // Spread the error around...
3252  if (x > 0) {
3253  l1[x-1] += (err*7)>>4;
3254  l2[x-1] += err>>4;
3255  }
3256  l2[x]+=(err*5)>>4;
3257  if (x + 1 < src->width)
3258  l2[x+1]+=(err*3)>>4;
3259  }
3260  }
3261  }
3262  if (endian) {
3263  for (int x = 0; x < src->width; x++) {
3264  *b++ = INDEXOF(pv[0][x],pv[1][x],pv[2][x]);
3265  }
3266  } else {
3267  for (int x = 0; x < src->width; x++) {
3268  *b++ = INDEXOF(pv[2][x],pv[1][x],pv[0][x]);
3269  }
3270  }
3271  src_data += src->bytes_per_line;
3272  dest_data += dst->bytes_per_line;
3273  }
3274  } else { // OrderedDither
3275  for (int y = 0; y < src->height; y++) {
3276  const QRgb *p = (const QRgb *)src_data;
3277  const QRgb *end = p + src->width;
3278  uchar *b = dest_data;
3279 
3280  int x = 0;
3281  while (p < end) {
3282  uint d = qt_bayer_matrix[y & 15][x & 15] << 8;
3283 
3284 #define DITHER(p, d, m) ((uchar) ((((256 * (m) + (m) + 1)) * (p) + (d)) >> 16))
3285  *b++ =
3286  INDEXOF(
3287  DITHER(qRed(*p), d, MAX_R),
3288  DITHER(qGreen(*p), d, MAX_G),
3289  DITHER(qBlue(*p), d, MAX_B)
3290  );
3291 #undef DITHER
3292 
3293  p++;
3294  x++;
3295  }
3296  src_data += src->bytes_per_line;
3297  dest_data += dst->bytes_per_line;
3298  }
3299  }
3300 
3301  if (src->format != QImage::Format_RGB32
3302  && src->format != QImage::Format_RGB16) {
3303  const int trans = 216;
3304  Q_ASSERT(dst->colortable.size() > trans);
3305  dst->colortable[trans] = 0;
3307  dither_to_Mono(mask.data(), src, flags, true);
3308  uchar *dst_data = dst->data;
3309  const uchar *mask_data = mask->data;
3310  for (int y = 0; y < src->height; y++) {
3311  for (int x = 0; x < src->width ; x++) {
3312  if (!(mask_data[x>>3] & (0x80 >> (x & 7))))
3313  dst_data[x] = trans;
3314  }
3315  mask_data += mask->bytes_per_line;
3316  dst_data += dst->bytes_per_line;
3317  }
3318  dst->has_alpha_clut = true;
3319  }
3320 
3321 #undef MAX_R
3322 #undef MAX_G
3323 #undef MAX_B
3324 #undef INDEXOF
3325 
3326  }
3327 }
3328 
3329 static void convert_ARGB_PM_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
3330 {
3332  convert_ARGB_PM_to_ARGB(tmp.data(), src, flags);
3333  convert_RGB_to_Indexed8(dst, tmp.data(), flags);
3334 }
3335 
3336 static void convert_ARGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
3337 {
3338  convert_RGB_to_Indexed8(dst, src, flags);
3339 }
3340 
3341 static void convert_Indexed8_to_X32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
3342 {
3345  || dest->format == QImage::Format_ARGB32
3347  Q_ASSERT(src->width == dest->width);
3348  Q_ASSERT(src->height == dest->height);
3349 
3351  if (colorTable.size() == 0) {
3352  colorTable.resize(256);
3353  for (int i=0; i<256; ++i)
3354  colorTable[i] = qRgb(i, i, i);
3355  }
3356 
3357  int w = src->width;
3358  const uchar *src_data = src->data;
3359  uchar *dest_data = dest->data;
3360  int tableSize = colorTable.size() - 1;
3361  for (int y = 0; y < src->height; y++) {
3362  uint *p = (uint *)dest_data;
3363  const uchar *b = src_data;
3364  uint *end = p + w;
3365 
3366  while (p < end)
3367  *p++ = colorTable.at(qMin<int>(tableSize, *b++));
3368 
3369  src_data += src->bytes_per_line;
3370  dest_data += dest->bytes_per_line;
3371  }
3372 }
3373 
3374 static void convert_Mono_to_X32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
3375 {
3378  || dest->format == QImage::Format_ARGB32
3380  Q_ASSERT(src->width == dest->width);
3381  Q_ASSERT(src->height == dest->height);
3382 
3384 
3385  // Default to black / white colors
3386  if (colorTable.size() < 2) {
3387  if (colorTable.size() == 0)
3388  colorTable << 0xff000000;
3389  colorTable << 0xffffffff;
3390  }
3391 
3392  const uchar *src_data = src->data;
3393  uchar *dest_data = dest->data;
3394  if (src->format == QImage::Format_Mono) {
3395  for (int y = 0; y < dest->height; y++) {
3396  register uint *p = (uint *)dest_data;
3397  for (int x = 0; x < dest->width; x++)
3398  *p++ = colorTable.at((src_data[x>>3] >> (7 - (x & 7))) & 1);
3399 
3400  src_data += src->bytes_per_line;
3401  dest_data += dest->bytes_per_line;
3402  }
3403  } else {
3404  for (int y = 0; y < dest->height; y++) {
3405  register uint *p = (uint *)dest_data;
3406  for (int x = 0; x < dest->width; x++)
3407  *p++ = colorTable.at((src_data[x>>3] >> (x & 7)) & 1);
3408 
3409  src_data += src->bytes_per_line;
3410  dest_data += dest->bytes_per_line;
3411  }
3412  }
3413 }
3414 
3415 
3416 static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
3417 {
3420  Q_ASSERT(src->width == dest->width);
3421  Q_ASSERT(src->height == dest->height);
3422 
3423  QVector<QRgb> ctbl = src->colortable;
3424  if (ctbl.size() > 2) {
3425  ctbl.resize(2);
3426  } else if (ctbl.size() < 2) {
3427  if (ctbl.size() == 0)
3428  ctbl << 0xff000000;
3429  ctbl << 0xffffffff;
3430  }
3431  dest->colortable = ctbl;
3432  dest->has_alpha_clut = src->has_alpha_clut;
3433 
3434 
3435  const uchar *src_data = src->data;
3436  uchar *dest_data = dest->data;
3437  if (src->format == QImage::Format_Mono) {
3438  for (int y = 0; y < dest->height; y++) {
3439  register uchar *p = dest_data;
3440  for (int x = 0; x < dest->width; x++)
3441  *p++ = (src_data[x>>3] >> (7 - (x & 7))) & 1;
3442  src_data += src->bytes_per_line;
3443  dest_data += dest->bytes_per_line;
3444  }
3445  } else {
3446  for (int y = 0; y < dest->height; y++) {
3447  register uchar *p = dest_data;
3448  for (int x = 0; x < dest->width; x++)
3449  *p++ = (src_data[x>>3] >> (x & 7)) & 1;
3450  src_data += src->bytes_per_line;
3451  dest_data += dest->bytes_per_line;
3452  }
3453  }
3454 }
3455 
3456 #define CONVERT_DECL(DST, SRC) \
3457  static void convert_##SRC##_to_##DST(QImageData *dest, \
3458  const QImageData *src, \
3459  Qt::ImageConversionFlags) \
3460  { \
3461  qt_rectconvert<DST, SRC>(reinterpret_cast<DST*>(dest->data), \
3462  reinterpret_cast<const SRC*>(src->data), \
3463  0, 0, src->width, src->height, \
3464  dest->bytes_per_line, src->bytes_per_line); \
3465  }
3466 
3477 #if !defined(Q_WS_QWS) || (defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16))
3480 #endif
3489 #undef CONVERT_DECL
3490 #define CONVERT_PTR(DST, SRC) convert_##SRC##_to_##DST
3491 
3492 /*
3493  Format_Invalid,
3494  Format_Mono,
3495  Format_MonoLSB,
3496  Format_Indexed8,
3497  Format_RGB32,
3498  Format_ARGB32,
3499  Format_ARGB32_Premultiplied,
3500  Format_RGB16,
3501  Format_ARGB8565_Premultiplied,
3502  Format_RGB666,
3503  Format_ARGB6666_Premultiplied,
3504  Format_RGB555,
3505  Format_ARGB8555_Premultiplied,
3506  Format_RGB888
3507  Format_RGB444
3508  Format_ARGB4444_Premultiplied
3509 */
3510 
3511 
3512 // first index source, second dest
3513 static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] =
3514 {
3515  {
3516  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3517  },
3518  {
3519  0,
3520  0,
3526  0,
3527  0,
3528  0,
3529  0,
3530  0,
3531  0,
3532  0,
3533  0,
3534  0
3535  }, // Format_Mono
3536 
3537  {
3538  0,
3540  0,
3545  0,
3546  0,
3547  0,
3548  0,
3549  0,
3550  0,
3551  0,
3552  0,
3553  0
3554  }, // Format_MonoLSB
3555 
3556  {
3557  0,
3560  0,
3564  0,
3565  0,
3566  0,
3567  0,
3568  0,
3569  0,
3570  0,
3571  0,
3572  0
3573  }, // Format_Indexed8
3574 
3575  {
3576  0,
3580  0,
3592  }, // Format_RGB32
3593 
3594  {
3595  0,
3600  0,
3611  }, // Format_ARGB32
3612 
3613  {
3614  0,
3620  0,
3621  0,
3622  0,
3623  0,
3624  0,
3625  0,
3626  0,
3627  0,
3628  0,
3629  0
3630  }, // Format_ARGB32_Premultiplied
3631 
3632  {
3633  0,
3634  0,
3635  0,
3636  0,
3640  0,
3641  0,
3642  0,
3643  0,
3644 #if !defined(Q_WS_QWS) || (defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16))
3646 #else
3647  0,
3648 #endif
3649  0,
3650  0,
3651  0,
3652  0
3653  }, // Format_RGB16
3654 
3655  {
3656  0,
3657  0,
3658  0,
3659  0,
3663  0,
3664  0,
3665  0,
3666  0,
3667  0,
3668  0,
3669  0,
3670  0,
3671  0
3672  }, // Format_ARGB8565_Premultiplied
3673 
3674  {
3675  0,
3676  0,
3677  0,
3678  0,
3682  0,
3683  0,
3684  0,
3685  0,
3686  0,
3687  0,
3688  0,
3689  0,
3690  0
3691  }, // Format_RGB666
3692 
3693  {
3694  0,
3695  0,
3696  0,
3697  0,
3701  0,
3702  0,
3703  0,
3704  0,
3705  0,
3706  0,
3707  0,
3708  0,
3709  0
3710  }, // Format_ARGB6666_Premultiplied
3711 
3712  {
3713  0,
3714  0,
3715  0,
3716  0,
3720 #if !defined(Q_WS_QWS) || (defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16))
3722 #else
3723  0,
3724 #endif
3725  0,
3726  0,
3727  0,
3728  0,
3729  0,
3730  0,
3731  0,
3732  0
3733  }, // Format_RGB555
3734 
3735  {
3736  0,
3737  0,
3738  0,
3739  0,
3743  0,
3744  0,
3745  0,
3746  0,
3747  0,
3748  0,
3749  0,
3750  0,
3751  0
3752  }, // Format_ARGB8555_Premultiplied
3753 
3754  {
3755  0,
3756  0,
3757  0,
3758  0,
3762  0,
3763  0,
3764  0,
3765  0,
3766  0,
3767  0,
3768  0,
3769  0,
3770  0
3771  }, // Format_RGB888
3772 
3773  {
3774  0,
3775  0,
3776  0,
3777  0,
3781  0,
3782  0,
3783  0,
3784  0,
3785  0,
3786  0,
3787  0,
3788  0,
3789  0
3790  }, // Format_RGB444
3791 
3792  {
3793  0,
3794  0,
3795  0,
3796  0,
3800  0,
3801  0,
3802  0,
3803  0,
3804  0,
3805  0,
3806  0,
3807  0,
3808  0
3809  } // Format_ARGB4444_Premultiplied
3810 };
3811 
3812 static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
3813 {
3814  {
3815  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3816  },
3817  {
3818  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3819  }, // Format_Mono
3820  {
3821  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3822  }, // Format_MonoLSB
3823  {
3824  0,
3825  0,
3826  0,
3827  0,
3828  0,
3832  0,
3833  0,
3834  0,
3835  0,
3836  0,
3837  0,
3838  0,
3839  0,
3840  }, // Format_Indexed8
3841  {
3842  0,
3843  0,
3844  0,
3845  0,
3846  0,
3847  0,
3848  0,
3850  0,
3851  0,
3852  0,
3853  0,
3854  0,
3855  0,
3856  0,
3857  0,
3858  }, // Format_ARGB32
3859  {
3860  0,
3861  0,
3862  0,
3863  0,
3864  0,
3865  0,
3867  0,
3868  0,
3869  0,
3870  0,
3871  0,
3872  0,
3873  0,
3874  0,
3875  0,
3876  }, // Format_ARGB32
3877  {
3878  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3879  }, // Format_ARGB32_Premultiplied
3880  {
3881  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3882  }, // Format_RGB16
3883  {
3884  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3885  }, // Format_ARGB8565_Premultiplied
3886  {
3887  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3888  }, // Format_RGB666
3889  {
3890  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3891  }, // Format_ARGB6666_Premultiplied
3892  {
3893  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3894  }, // Format_RGB555
3895  {
3896  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3897  }, // Format_ARGB8555_Premultiplied
3898  {
3899  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3900  }, // Format_RGB888
3901  {
3902  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3903  }, // Format_RGB444
3904  {
3905  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3906  } // Format_ARGB4444_Premultiplied
3907 };
3908 
3910 {
3911  const uint features = qDetectCPUFeatures();
3912  Q_UNUSED(features);
3913 
3914 #ifdef QT_HAVE_SSE2
3915  if (features & SSE2) {
3916  extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags);
3917  inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2;
3918  }
3919 #endif
3920 #ifdef QT_HAVE_SSSE3
3921  if (features & SSSE3) {
3922  extern void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
3923  converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_ssse3;
3924  converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_ssse3;
3925  converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3;
3926  }
3927 #endif
3928 #ifdef QT_HAVE_NEON
3929  if (features & NEON) {
3930  extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
3931  converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon;
3932  converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon;
3933  converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_neon;
3934  }
3935 #endif
3936 }
3937 
3939 {
3940  extern uchar qt_pow_rgb_gamma[256];
3941 
3942  // gamma correct the pixels back to linear color space...
3943  int h = image->height();
3944  int w = image->width();
3945 
3946  for (int y=0; y<h; ++y) {
3947  uint *pixels = (uint *) image->scanLine(y);
3948  for (int x=0; x<w; ++x) {
3949  uint p = pixels[x];
3950  uint r = qt_pow_rgb_gamma[qRed(p)];
3951  uint g = qt_pow_rgb_gamma[qGreen(p)];
3952  uint b = qt_pow_rgb_gamma[qBlue(p)];
3953  pixels[x] = (r << 16) | (g << 8) | b | 0xff000000;
3954  }
3955  }
3956 }
3957 
3966 QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) const
3967 {
3968  if (!d || d->format == format)
3969  return *this;
3970 
3971  if (format == Format_Invalid || d->format == Format_Invalid)
3972  return QImage();
3973 
3974  const Image_Converter *converterPtr = &converter_map[d->format][format];
3975  Image_Converter converter = *converterPtr;
3976  if (converter) {
3977  QImage image(d->width, d->height, format);
3978 
3980 
3983 
3984 #if !defined(QT_NO_IMAGE_TEXT)
3985  image.d->text = d->text;
3986 #endif // !QT_NO_IMAGE_TEXT
3987 
3988  converter(image.d, d, flags);
3989  return image;
3990  }
3991 
3992  Q_ASSERT(format != QImage::Format_ARGB32);
3994 
3995  QImage image = convertToFormat(Format_ARGB32, flags);
3996  return image.convertToFormat(format, flags);
3997 }
3998 
3999 
4000 
4001 static inline int pixel_distance(QRgb p1, QRgb p2) {
4002  int r1 = qRed(p1);
4003  int g1 = qGreen(p1);
4004  int b1 = qBlue(p1);
4005  int a1 = qAlpha(p1);
4006 
4007  int r2 = qRed(p2);
4008  int g2 = qGreen(p2);
4009  int b2 = qBlue(p2);
4010  int a2 = qAlpha(p2);
4011 
4012  return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) + abs(a1 - a2);
4013 }
4014 
4015 static inline int closestMatch(QRgb pixel, const QVector<QRgb> &clut) {
4016  int idx = 0;
4017  int current_distance = INT_MAX;
4018  for (int i=0; i<clut.size(); ++i) {
4019  int dist = pixel_distance(pixel, clut.at(i));
4020  if (dist < current_distance) {
4021  current_distance = dist;
4022  idx = i;
4023  }
4024  }
4025  return idx;
4026 }
4027 
4029  const QVector<QRgb> &clut) {
4030  QImage dest(src.size(), format);
4032  dest.setColorTable(clut);
4033 
4034 #if !defined(QT_NO_IMAGE_TEXT)
4035  QString textsKeys = src.text();
4036  QStringList textKeyList = textsKeys.split(QLatin1Char('\n'), QString::SkipEmptyParts);
4037  foreach (const QString &textKey, textKeyList) {
4038  QStringList textKeySplitted = textKey.split(QLatin1String(": "));
4039  dest.setText(textKeySplitted[0], textKeySplitted[1]);
4040  }
4041 #endif // !QT_NO_IMAGE_TEXT
4042 
4043  int h = src.height();
4044  int w = src.width();
4045 
4046  QHash<QRgb, int> cache;
4047 
4048  if (format == QImage::Format_Indexed8) {
4049  for (int y=0; y<h; ++y) {
4050  QRgb *src_pixels = (QRgb *) src.scanLine(y);
4051  uchar *dest_pixels = (uchar *) dest.scanLine(y);
4052  for (int x=0; x<w; ++x) {
4053  int src_pixel = src_pixels[x];
4054  int value = cache.value(src_pixel, -1);
4055  if (value == -1) {
4056  value = closestMatch(src_pixel, clut);
4057  cache.insert(src_pixel, value);
4058  }
4059  dest_pixels[x] = (uchar) value;
4060  }
4061  }
4062  } else {
4063  QVector<QRgb> table = clut;
4064  table.resize(2);
4065  for (int y=0; y<h; ++y) {
4066  QRgb *src_pixels = (QRgb *) src.scanLine(y);
4067  for (int x=0; x<w; ++x) {
4068  int src_pixel = src_pixels[x];
4069  int value = cache.value(src_pixel, -1);
4070  if (value == -1) {
4071  value = closestMatch(src_pixel, table);
4072  cache.insert(src_pixel, value);
4073  }
4074  dest.setPixel(x, y, value);
4075  }
4076  }
4077  }
4078 
4079  return dest;
4080 }
4081 
4095 QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags) const
4096 {
4097  if (d->format == format)
4098  return *this;
4099 
4100  if (format <= QImage::Format_Indexed8 && depth() == 32) {
4101  return convertWithPalette(*this, format, colorTable);
4102  }
4103 
4104  const Image_Converter *converterPtr = &converter_map[d->format][format];
4105  Image_Converter converter = *converterPtr;
4106  if (!converter)
4107  return QImage();
4108 
4109  QImage image(d->width, d->height, format);
4111 
4112 #if !defined(QT_NO_IMAGE_TEXT)
4113  image.d->text = d->text;
4114 #endif // !QT_NO_IMAGE_TEXT
4115 
4116  converter(image.d, d, flags);
4117  return image;
4118 }
4119 
4120 #ifdef QT3_SUPPORT
4121 
4134 QImage QImage::convertDepth(int depth, Qt::ImageConversionFlags flags) const
4135 {
4136  if (!d || d->depth == depth)
4137  return *this;
4138 
4139  Format format = formatFor (depth, QImage::LittleEndian);
4140  return convertToFormat(format, flags);
4141 }
4142 #endif
4143 
4165 bool QImage::valid(int x, int y) const
4166 {
4167  return d
4168  && x >= 0 && x < d->width
4169  && y >= 0 && y < d->height;
4170 }
4171 
4194 int QImage::pixelIndex(int x, int y) const
4195 {
4196  if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
4197  qWarning("QImage::pixelIndex: coordinate (%d,%d) out of range", x, y);
4198  return -12345;
4199  }
4200  const uchar * s = scanLine(y);
4201  switch(d->format) {
4202  case Format_Mono:
4203  return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
4204  case Format_MonoLSB:
4205  return (*(s + (x >> 3)) >> (x & 7)) & 1;
4206  case Format_Indexed8:
4207  return (int)s[x];
4208  default:
4209  qWarning("QImage::pixelIndex: Not applicable for %d-bpp images (no palette)", d->depth);
4210  }
4211  return 0;
4212 }
4213 
4214 
4240 QRgb QImage::pixel(int x, int y) const
4241 {
4242  if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
4243  qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y);
4244  return 12345;
4245  }
4246  const uchar * s = scanLine(y);
4247  switch(d->format) {
4248  case Format_Mono:
4249  return d->colortable.at((*(s + (x >> 3)) >> (7- (x & 7))) & 1);
4250  case Format_MonoLSB:
4251  return d->colortable.at((*(s + (x >> 3)) >> (x & 7)) & 1);
4252  case Format_Indexed8:
4253  return d->colortable.at((int)s[x]);
4255  return qt_colorConvert<quint32, qargb8565>(reinterpret_cast<const qargb8565*>(s)[x], 0);
4256  case Format_RGB666:
4257  return qt_colorConvert<quint32, qrgb666>(reinterpret_cast<const qrgb666*>(s)[x], 0);
4259  return qt_colorConvert<quint32, qargb6666>(reinterpret_cast<const qargb6666*>(s)[x], 0);
4260  case Format_RGB555:
4261  return qt_colorConvert<quint32, qrgb555>(reinterpret_cast<const qrgb555*>(s)[x], 0);
4263  return qt_colorConvert<quint32, qargb8555>(reinterpret_cast<const qargb8555*>(s)[x], 0);
4264  case Format_RGB888:
4265  return qt_colorConvert<quint32, qrgb888>(reinterpret_cast<const qrgb888*>(s)[x], 0);
4266  case Format_RGB444:
4267  return qt_colorConvert<quint32, qrgb444>(reinterpret_cast<const qrgb444*>(s)[x], 0);
4269  return qt_colorConvert<quint32, qargb4444>(reinterpret_cast<const qargb4444*>(s)[x], 0);
4270  case Format_RGB16:
4271  return qt_colorConvert<quint32, quint16>(reinterpret_cast<const quint16*>(s)[x], 0);
4272  default:
4273  return ((QRgb*)s)[x];
4274  }
4275 }
4276 
4277 
4311 void QImage::setPixel(int x, int y, uint index_or_rgb)
4312 {
4313  if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
4314  qWarning("QImage::setPixel: coordinate (%d,%d) out of range", x, y);
4315  return;
4316  }
4317  // detach is called from within scanLine
4318  uchar * s = scanLine(y);
4319  if (!s) {
4320  qWarning("setPixel: Out of memory");
4321  return;
4322  }
4323  const quint32p p = quint32p::fromRawData(index_or_rgb);
4324  switch(d->format) {
4325  case Format_Mono:
4326  case Format_MonoLSB:
4327  if (index_or_rgb > 1) {
4328  qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
4329  } else if (format() == Format_MonoLSB) {
4330  if (index_or_rgb==0)
4331  *(s + (x >> 3)) &= ~(1 << (x & 7));
4332  else
4333  *(s + (x >> 3)) |= (1 << (x & 7));
4334  } else {
4335  if (index_or_rgb==0)
4336  *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
4337  else
4338  *(s + (x >> 3)) |= (1 << (7-(x & 7)));
4339  }
4340  break;
4341  case Format_Indexed8:
4342  if (index_or_rgb >= (uint)d->colortable.size()) {
4343  qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
4344  return;
4345  }
4346  s[x] = index_or_rgb;
4347  break;
4348  case Format_RGB32:
4349  //make sure alpha is 255, we depend on it in qdrawhelper for cases
4350  // when image is set as a texture pattern on a qbrush
4351  ((uint *)s)[x] = uint(255 << 24) | index_or_rgb;
4352  break;
4353  case Format_ARGB32:
4355  ((uint *)s)[x] = index_or_rgb;
4356  break;
4357  case Format_RGB16:
4358  ((quint16 *)s)[x] = qt_colorConvert<quint16, quint32p>(p, 0);
4359  break;
4361  ((qargb8565*)s)[x] = qt_colorConvert<qargb8565, quint32p>(p, 0);
4362  break;
4363  case Format_RGB666:
4364  ((qrgb666*)s)[x] = qt_colorConvert<qrgb666, quint32p>(p, 0);
4365  break;
4367  ((qargb6666*)s)[x] = qt_colorConvert<qargb6666, quint32p>(p, 0);
4368  break;
4369  case Format_RGB555:
4370  ((qrgb555*)s)[x] = qt_colorConvert<qrgb555, quint32p>(p, 0);
4371  break;
4373  ((qargb8555*)s)[x] = qt_colorConvert<qargb8555, quint32p>(p, 0);
4374  break;
4375  case Format_RGB888:
4376  ((qrgb888*)s)[x] = qt_colorConvert<qrgb888, quint32p>(p, 0);
4377  break;
4378  case Format_RGB444:
4379  ((qrgb444*)s)[x] = qt_colorConvert<qrgb444, quint32p>(p, 0);
4380  break;
4382  ((qargb4444*)s)[x] = qt_colorConvert<qargb4444, quint32p>(p, 0);
4383  break;
4384  case Format_Invalid:
4385  case NImageFormats:
4386  Q_ASSERT(false);
4387  }
4388 }
4389 
4390 #ifdef QT3_SUPPORT
4391 
4401 QImage QImage::convertBitOrder(Endian bitOrder) const
4402 {
4403  if (!d || isNull() || d->depth != 1 || !(bitOrder == BigEndian || bitOrder == LittleEndian))
4404  return QImage();
4405 
4406  if ((d->format == Format_Mono && bitOrder == BigEndian)
4407  || (d->format == Format_MonoLSB && bitOrder == LittleEndian))
4408  return *this;
4409 
4412 
4413  const uchar *data = d->data;
4414  const uchar *end = data + d->nbytes;
4415  uchar *ndata = image.d->data;
4416  while (data < end)
4417  *ndata++ = bitflip[*data++];
4418 
4421 
4422  image.d->colortable = d->colortable;
4423  return image;
4424 }
4425 #endif
4426 
4435 bool QImage::allGray() const
4436 {
4437  if (!d)
4438  return true;
4439 
4440  if (d->depth == 32) {
4441  int p = width()*height();
4442  const QRgb* b = (const QRgb*)bits();
4443  while (p--)
4444  if (!qIsGray(*b++))
4445  return false;
4446  } else if (d->depth == 16) {
4447  int p = width()*height();
4448  const ushort* b = (const ushort *)bits();
4449  while (p--)
4450  if (!qIsGray(qt_colorConvert<quint32, quint16>(*b++, 0)))
4451  return false;
4452  } else if (d->format == QImage::Format_RGB888) {
4453  int p = width()*height();
4454  const qrgb888* b = (const qrgb888 *)bits();
4455  while (p--)
4456  if (!qIsGray(qt_colorConvert<quint32, qrgb888>(*b++, 0)))
4457  return false;
4458  } else {
4459  if (d->colortable.isEmpty())
4460  return true;
4461  for (int i = 0; i < colorCount(); i++)
4462  if (!qIsGray(d->colortable.at(i)))
4463  return false;
4464  }
4465  return true;
4466 }
4467 
4478 {
4479  if (!d)
4480  return false;
4481 
4482  switch (depth()) {
4483  case 32:
4484  case 24:
4485  case 16:
4486  return allGray();
4487  case 8: {
4488  for (int i = 0; i < colorCount(); i++)
4489  if (d->colortable.at(i) != qRgb(i,i,i))
4490  return false;
4491  return true;
4492  }
4493  }
4494  return false;
4495 }
4496 
4497 
4578 {
4579  if (!d) {
4580  qWarning("QImage::scaled: Image is a null image");
4581  return QImage();
4582  }
4583  if (s.isEmpty())
4584  return QImage();
4585 
4586  QSize newSize = size();
4587  newSize.scale(s, aspectMode);
4588  newSize.rwidth() = qMax(newSize.width(), 1);
4589  newSize.rheight() = qMax(newSize.height(), 1);
4590  if (newSize == size())
4591  return *this;
4592 
4593  QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
4594  QImage img = transformed(wm, mode);
4595  return img;
4596 }
4597 
4616 {
4617  if (!d) {
4618  qWarning("QImage::scaleWidth: Image is a null image");
4619  return QImage();
4620  }
4621  if (w <= 0)
4622  return QImage();
4623 
4624  qreal factor = (qreal) w / width();
4625  QTransform wm = QTransform::fromScale(factor, factor);
4626  return transformed(wm, mode);
4627 }
4628 
4647 {
4648  if (!d) {
4649  qWarning("QImage::scaleHeight: Image is a null image");
4650  return QImage();
4651  }
4652  if (h <= 0)
4653  return QImage();
4654 
4655  qreal factor = (qreal) h / height();
4656  QTransform wm = QTransform::fromScale(factor, factor);
4657  return transformed(wm, mode);
4658 }
4659 
4660 
4680 QMatrix QImage::trueMatrix(const QMatrix &matrix, int w, int h)
4681 {
4682  return trueMatrix(QTransform(matrix), w, h).toAffine();
4683 }
4684 
4699 {
4700  return transformed(QTransform(matrix), mode);
4701 }
4702 
4720 QImage QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
4721 {
4722  if (!d || d->format == QImage::Format_RGB32)
4723  return QImage();
4724 
4725  if (d->depth == 1) {
4726  // A monochrome pixmap, with alpha channels on those two colors.
4727  // Pretty unlikely, so use less efficient solution.
4728  return convertToFormat(Format_Indexed8, flags).createAlphaMask(flags);
4729  }
4730 
4731  QImage mask(d->width, d->height, Format_MonoLSB);
4732  if (!mask.isNull())
4733  dither_to_Mono(mask.d, d, flags, true);
4734  return mask;
4735 }
4736 
4737 #ifndef QT_NO_IMAGE_HEURISTIC_MASK
4738 
4763 {
4764  if (!d)
4765  return QImage();
4766 
4767  if (d->depth != 32) {
4769  return img32.createHeuristicMask(clipTight);
4770  }
4771 
4772 #define PIX(x,y) (*((QRgb*)scanLine(y)+x) & 0x00ffffff)
4773 
4774  int w = width();
4775  int h = height();
4776  QImage m(w, h, Format_MonoLSB);
4778  m.setColorCount(2);
4779  m.setColor(0, QColor(Qt::color0).rgba());
4780  m.setColor(1, QColor(Qt::color1).rgba());
4781  m.fill(0xff);
4782 
4783  QRgb background = PIX(0,0);
4784  if (background != PIX(w-1,0) &&
4785  background != PIX(0,h-1) &&
4786  background != PIX(w-1,h-1)) {
4787  background = PIX(w-1,0);
4788  if (background != PIX(w-1,h-1) &&
4789  background != PIX(0,h-1) &&
4790  PIX(0,h-1) == PIX(w-1,h-1)) {
4791  background = PIX(w-1,h-1);
4792  }
4793  }
4794 
4795  int x,y;
4796  bool done = false;
4797  uchar *ypp, *ypc, *ypn;
4798  while(!done) {
4799  done = true;
4800  ypn = m.scanLine(0);
4801  ypc = 0;
4802  for (y = 0; y < h; y++) {
4803  ypp = ypc;
4804  ypc = ypn;
4805  ypn = (y == h-1) ? 0 : m.scanLine(y+1);
4806  QRgb *p = (QRgb *)scanLine(y);
4807  for (x = 0; x < w; x++) {
4808  // slowness here - it's possible to do six of these tests
4809  // together in one go. oh well.
4810  if ((x == 0 || y == 0 || x == w-1 || y == h-1 ||
4811  !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
4812  !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
4813  !(*(ypp + (x >> 3)) & (1 << (x & 7))) ||
4814  !(*(ypn + (x >> 3)) & (1 << (x & 7)))) &&
4815  ( (*(ypc + (x >> 3)) & (1 << (x & 7)))) &&
4816  ((*p & 0x00ffffff) == background)) {
4817  done = false;
4818  *(ypc + (x >> 3)) &= ~(1 << (x & 7));
4819  }
4820  p++;
4821  }
4822  }
4823  }
4824 
4825  if (!clipTight) {
4826  ypn = m.scanLine(0);
4827  ypc = 0;
4828  for (y = 0; y < h; y++) {
4829  ypp = ypc;
4830  ypc = ypn;
4831  ypn = (y == h-1) ? 0 : m.scanLine(y+1);
4832  QRgb *p = (QRgb *)scanLine(y);
4833  for (x = 0; x < w; x++) {
4834  if ((*p & 0x00ffffff) != background) {
4835  if (x > 0)
4836  *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
4837  if (x < w-1)
4838  *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
4839  if (y > 0)
4840  *(ypp + (x >> 3)) |= (1 << (x & 7));
4841  if (y < h-1)
4842  *(ypn + (x >> 3)) |= (1 << (x & 7));
4843  }
4844  p++;
4845  }
4846  }
4847  }
4848 
4849 #undef PIX
4850 
4851  return m;
4852 }
4853 #endif //QT_NO_IMAGE_HEURISTIC_MASK
4854 
4866 {
4867  if (!d)
4868  return QImage();
4869  QImage maskImage(size(), QImage::Format_MonoLSB);
4870  QIMAGE_SANITYCHECK_MEMORY(maskImage);
4871  maskImage.fill(0);
4872  uchar *s = maskImage.bits();
4873 
4874  if (depth() == 32) {
4875  for (int h = 0; h < d->height; h++) {
4876  const uint *sl = (uint *) scanLine(h);
4877  for (int w = 0; w < d->width; w++) {
4878  if (sl[w] == color)
4879  *(s + (w >> 3)) |= (1 << (w & 7));
4880  }
4881  s += maskImage.bytesPerLine();
4882  }
4883  } else {
4884  for (int h = 0; h < d->height; h++) {
4885  for (int w = 0; w < d->width; w++) {
4886  if ((uint) pixel(w, h) == color)
4887  *(s + (w >> 3)) |= (1 << (w & 7));
4888  }
4889  s += maskImage.bytesPerLine();
4890  }
4891  }
4892  if (mode == Qt::MaskOutColor)
4893  maskImage.invertPixels();
4894  return maskImage;
4895 }
4896 
4897 
4898 /*
4899  This code is contributed by Philipp Lang,
4900  GeneriCom Software Germany (www.generi.com)
4901  under the terms of the QPL, Version 1.0
4902 */
4903 
4922 QImage QImage::mirrored(bool horizontal, bool vertical) const
4923 {
4924  if (!d)
4925  return QImage();
4926 
4927  if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
4928  return *this;
4929 
4930  int w = d->width;
4931  int h = d->height;
4932  // Create result image, copy colormap
4933  QImage result(d->width, d->height, d->format);
4934  QIMAGE_SANITYCHECK_MEMORY(result);
4935 
4936  // check if we ran out of of memory..
4937  if (!result.d)
4938  return QImage();
4939 
4940  result.d->colortable = d->colortable;
4941  result.d->has_alpha_clut = d->has_alpha_clut;
4942 
4943  if (depth() == 1)
4944  w = (w+7)/8;
4945  int dxi = horizontal ? -1 : 1;
4946  int dxs = horizontal ? w-1 : 0;
4947  int dyi = vertical ? -1 : 1;
4948  int dy = vertical ? h-1: 0;
4949 
4950  // 1 bit, 8 bit
4951  if (d->depth == 1 || d->depth == 8) {
4952  for (int sy = 0; sy < h; sy++, dy += dyi) {
4953  quint8* ssl = (quint8*)(d->data + sy*d->bytes_per_line);
4954  quint8* dsl = (quint8*)(result.d->data + dy*result.d->bytes_per_line);
4955  int dx = dxs;
4956  for (int sx = 0; sx < w; sx++, dx += dxi)
4957  dsl[dx] = ssl[sx];
4958  }
4959  }
4960  // 16 bit
4961  else if (d->depth == 16) {
4962  for (int sy = 0; sy < h; sy++, dy += dyi) {
4963  quint16* ssl = (quint16*)(d->data + sy*d->bytes_per_line);
4964  quint16* dsl = (quint16*)(result.d->data + dy*result.d->bytes_per_line);
4965  int dx = dxs;
4966  for (int sx = 0; sx < w; sx++, dx += dxi)
4967  dsl[dx] = ssl[sx];
4968  }
4969  }
4970  // 24 bit
4971  else if (d->depth == 24) {
4972  for (int sy = 0; sy < h; sy++, dy += dyi) {
4973  quint24* ssl = (quint24*)(d->data + sy*d->bytes_per_line);
4974  quint24* dsl = (quint24*)(result.d->data + dy*result.d->bytes_per_line);
4975  int dx = dxs;
4976  for (int sx = 0; sx < w; sx++, dx += dxi)
4977  dsl[dx] = ssl[sx];
4978  }
4979  }
4980  // 32 bit
4981  else if (d->depth == 32) {
4982  for (int sy = 0; sy < h; sy++, dy += dyi) {
4983  quint32* ssl = (quint32*)(d->data + sy*d->bytes_per_line);
4984  quint32* dsl = (quint32*)(result.d->data + dy*result.d->bytes_per_line);
4985  int dx = dxs;
4986  for (int sx = 0; sx < w; sx++, dx += dxi)
4987  dsl[dx] = ssl[sx];
4988  }
4989  }
4990 
4991  // special handling of 1 bit images for horizontal mirroring
4992  if (horizontal && d->depth == 1) {
4993  int shift = width() % 8;
4994  for (int y = h-1; y >= 0; y--) {
4995  quint8* a0 = (quint8*)(result.d->data + y*d->bytes_per_line);
4996  // Swap bytes
4997  quint8* a = a0+dxs;
4998  while (a >= a0) {
4999  *a = bitflip[*a];
5000  a--;
5001  }
5002  // Shift bits if unaligned
5003  if (shift != 0) {
5004  a = a0+dxs;
5005  quint8 c = 0;
5006  if (format() == Format_MonoLSB) {
5007  while (a >= a0) {
5008  quint8 nc = *a << shift;
5009  *a = (*a >> (8-shift)) | c;
5010  --a;
5011  c = nc;
5012  }
5013  } else {
5014  while (a >= a0) {
5015  quint8 nc = *a >> shift;
5016  *a = (*a << (8-shift)) | c;
5017  --a;
5018  c = nc;
5019  }
5020  }
5021  }
5022  }
5023  }
5024 
5025  return result;
5026 }
5027 
5053 {
5054  if (isNull())
5055  return *this;
5056  QImage res;
5057  switch (d->format) {
5058  case Format_Invalid:
5059  case NImageFormats:
5060  Q_ASSERT(false);
5061  break;
5062  case Format_Mono:
5063  case Format_MonoLSB:
5064  case Format_Indexed8:
5065  res = copy();
5067  for (int i = 0; i < res.d->colortable.size(); i++) {
5068  QRgb c = res.d->colortable.at(i);
5069  res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
5070  }
5071  break;
5072  case Format_RGB32:
5073  case Format_ARGB32:
5075  res = QImage(d->width, d->height, d->format);
5077  for (int i = 0; i < d->height; i++) {
5078  uint *q = (uint*)res.scanLine(i);
5079  uint *p = (uint*)constScanLine(i);
5080  uint *end = p + d->width;
5081  while (p < end) {
5082  *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
5083  p++;
5084  q++;
5085  }
5086  }
5087  break;
5088  case Format_RGB16:
5089  res = QImage(d->width, d->height, d->format);
5091  for (int i = 0; i < d->height; i++) {
5092  ushort *q = (ushort*)res.scanLine(i);
5093  const ushort *p = (const ushort*)constScanLine(i);
5094  const ushort *end = p + d->width;
5095  while (p < end) {
5096  *q = ((*p << 11) & 0xf800) | ((*p >> 11) & 0x1f) | (*p & 0x07e0);
5097  p++;
5098  q++;
5099  }
5100  }
5101  break;
5103  res = QImage(d->width, d->height, d->format);
5105  for (int i = 0; i < d->height; i++) {
5106  const quint8 *p = constScanLine(i);
5107  quint8 *q = res.scanLine(i);
5108  const quint8 *end = p + d->width * sizeof(qargb8565);
5109  while (p < end) {
5110  q[0] = p[0];
5111  q[1] = (p[1] & 0xe0) | (p[2] >> 3);
5112  q[2] = (p[2] & 0x07) | (p[1] << 3);
5113  p += sizeof(qargb8565);
5114  q += sizeof(qargb8565);
5115  }
5116  }
5117  break;
5118  case Format_RGB666:
5119  res = QImage(d->width, d->height, d->format);
5121  for (int i = 0; i < d->height; i++) {
5122  qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i));
5123  const qrgb666 *p = reinterpret_cast<const qrgb666*>(constScanLine(i));
5124  const qrgb666 *end = p + d->width;
5125  while (p < end) {
5126  const QRgb rgb = quint32(*p++);
5127  *q++ = qRgb(qBlue(rgb), qGreen(rgb), qRed(rgb));
5128  }
5129  }
5130  break;
5132  res = QImage(d->width, d->height, d->format);
5134  for (int i = 0; i < d->height; i++) {
5135  const quint8 *p = constScanLine(i);
5136  const quint8 *end = p + d->width * sizeof(qargb6666);
5137  quint8 *q = res.scanLine(i);
5138  while (p < end) {
5139  q[0] = (p[1] >> 4) | ((p[2] & 0x3) << 4) | (p[0] & 0xc0);
5140  q[1] = (p[1] & 0xf) | (p[0] << 4);
5141  q[2] = (p[2] & 0xfc) | ((p[0] >> 4) & 0x3);
5142  p += sizeof(qargb6666);
5143  q += sizeof(qargb6666);
5144  }
5145  }
5146  break;
5147  case Format_RGB555:
5148  res = QImage(d->width, d->height, d->format);
5150  for (int i = 0; i < d->height; i++) {
5151  quint16 *q = (quint16*)res.scanLine(i);
5152  const quint16 *p = (const quint16*)constScanLine(i);
5153  const quint16 *end = p + d->width;
5154  while (p < end) {
5155  *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0);
5156  p++;
5157  q++;
5158  }
5159  }
5160  break;
5162  res = QImage(d->width, d->height, d->format);
5164  for (int i = 0; i < d->height; i++) {
5165  const quint8 *p = constScanLine(i);
5166  quint8 *q = res.scanLine(i);
5167  const quint8 *end = p + d->width * sizeof(qargb8555);
5168  while (p < end) {
5169  q[0] = p[0];
5170  q[1] = (p[1] & 0xe0) | (p[2] >> 2);
5171  q[2] = (p[2] & 0x03) | ((p[1] << 2) & 0x7f);
5172  p += sizeof(qargb8555);
5173  q += sizeof(qargb8555);
5174  }
5175  }
5176  break;
5177  case Format_RGB888:
5178  res = QImage(d->width, d->height, d->format);
5180  for (int i = 0; i < d->height; i++) {
5181  quint8 *q = res.scanLine(i);
5182  const quint8 *p = constScanLine(i);
5183  const quint8 *end = p + d->width * sizeof(qrgb888);
5184  while (p < end) {
5185  q[0] = p[2];
5186  q[1] = p[1];
5187  q[2] = p[0];
5188  q += sizeof(qrgb888);
5189  p += sizeof(qrgb888);
5190  }
5191  }
5192  break;
5193  case Format_RGB444:
5195  res = QImage(d->width, d->height, d->format);
5197  for (int i = 0; i < d->height; i++) {
5198  quint16 *q = reinterpret_cast<quint16*>(res.scanLine(i));
5199  const quint16 *p = reinterpret_cast<const quint16*>(constScanLine(i));
5200  const quint16 *end = p + d->width;
5201  while (p < end) {
5202  *q = (*p & 0xf0f0) | ((*p & 0x0f) << 8) | ((*p & 0xf00) >> 8);
5203  p++;
5204  q++;
5205  }
5206  }
5207  break;
5208  }
5209  return res;
5210 }
5211 
5228 bool QImage::load(const QString &fileName, const char* format)
5229 {
5230  if (fileName.isEmpty())
5231  return false;
5232 
5233  QImage image = QImageReader(fileName, format).read();
5234  if (!image.isNull()) {
5235  operator=(image);
5236  return true;
5237  }
5238  return false;
5239 }
5240 
5251 bool QImage::load(QIODevice* device, const char* format)
5252 {
5253  QImage image = QImageReader(device, format).read();
5254  if(!image.isNull()) {
5255  operator=(image);
5256  return true;
5257  }
5258  return false;
5259 }
5260 
5275 bool QImage::loadFromData(const uchar *data, int len, const char *format)
5276 {
5277  QImage image = fromData(data, len, format);
5278  if (!image.isNull()) {
5279  operator=(image);
5280  return true;
5281  }
5282  return false;
5283 }
5284 
5313 QImage QImage::fromData(const uchar *data, int size, const char *format)
5314 {
5315  QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(data), size);
5316  QBuffer b;
5317  b.setData(a);
5319  return QImageReader(&b, format).read();
5320 }
5321 
5346 bool QImage::save(const QString &fileName, const char *format, int quality) const
5347 {
5348  if (isNull())
5349  return false;
5350  QImageWriter writer(fileName, format);
5351  return d->doImageIO(this, &writer, quality);
5352 }
5353 
5368 bool QImage::save(QIODevice* device, const char* format, int quality) const
5369 {
5370  if (isNull())
5371  return false; // nothing to save
5372  QImageWriter writer(device, format);
5373  return d->doImageIO(this, &writer, quality);
5374 }
5375 
5376 /* \internal
5377 */
5378 
5379 bool QImageData::doImageIO(const QImage *image, QImageWriter *writer, int quality) const
5380 {
5381  if (quality > 100 || quality < -1)
5382  qWarning("QPixmap::save: Quality out of range [-1, 100]");
5383  if (quality >= 0)
5384  writer->setQuality(qMin(quality,100));
5385  return writer->write(*image);
5386 }
5387 
5388 /*****************************************************************************
5389  QImage stream functions
5390  *****************************************************************************/
5391 #if !defined(QT_NO_DATASTREAM)
5392 
5407 {
5408  if (s.version() >= 5) {
5409  if (image.isNull()) {
5410  s << (qint32) 0; // null image marker
5411  return s;
5412  } else {
5413  s << (qint32) 1;
5414  // continue ...
5415  }
5416  }
5417  QImageWriter writer(s.device(), s.version() == 1 ? "bmp" : "png");
5418  writer.write(image);
5419  return s;
5420 }
5421 
5436 {
5437  if (s.version() >= 5) {
5438  qint32 nullMarker;
5439  s >> nullMarker;
5440  if (!nullMarker) {
5441  image = QImage(); // null image
5442  return s;
5443  }
5444  }
5445  image = QImageReader(s.device(), 0).read();
5446  return s;
5447 }
5448 #endif // QT_NO_DATASTREAM
5449 
5450 
5451 #ifdef QT3_SUPPORT
5452 
5474 QImage QImage::convertDepthWithPalette(int d, QRgb* palette, int palette_count, Qt::ImageConversionFlags flags) const
5475 {
5476  Format f = formatFor(d, QImage::LittleEndian);
5477  QVector<QRgb> colortable;
5478  for (int i = 0; i < palette_count; ++i)
5479  colortable.append(palette[i]);
5480  return convertToFormat(f, colortable, flags);
5481 }
5482 
5505 void bitBlt(QImage *dst, int dx, int dy, const QImage *src, int sx, int sy, int sw, int sh,
5506  Qt::ImageConversionFlags flags)
5507 {
5508  if (dst->isNull() || src->isNull())
5509  return;
5510  QPainter p(dst);
5511  p.drawImage(QPoint(dx, dy), *src, QRect(sx, sy, sw, sh), flags);
5512 }
5513 #endif
5514 
5531 bool QImage::operator==(const QImage & i) const
5532 {
5533  // same object, or shared?
5534  if (i.d == d)
5535  return true;
5536  if (!i.d || !d)
5537  return false;
5538 
5539  // obviously different stuff?
5540  if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format)
5541  return false;
5542 
5543  if (d->format != Format_RGB32) {
5544  if (d->format >= Format_ARGB32) { // all bits defined
5545  const int n = d->width * d->depth / 8;
5546  if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
5547  if (memcmp(bits(), i.bits(), d->nbytes))
5548  return false;
5549  } else {
5550  for (int y = 0; y < d->height; ++y) {
5551  if (memcmp(scanLine(y), i.scanLine(y), n))
5552  return false;
5553  }
5554  }
5555  } else {
5556  const int w = width();
5557  const int h = height();
5558  const QVector<QRgb> &colortable = d->colortable;
5559  const QVector<QRgb> &icolortable = i.d->colortable;
5560  for (int y=0; y<h; ++y) {
5561  for (int x=0; x<w; ++x) {
5562  if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
5563  return false;
5564  }
5565  }
5566  }
5567  } else {
5568  //alpha channel undefined, so we must mask it out
5569  for(int l = 0; l < d->height; l++) {
5570  int w = d->width;
5571  const uint *p1 = reinterpret_cast<const uint*>(scanLine(l));
5572  const uint *p2 = reinterpret_cast<const uint*>(i.scanLine(l));
5573  while (w--) {
5574  if ((*p1++ & 0x00ffffff) != (*p2++ & 0x00ffffff))
5575  return false;
5576  }
5577  }
5578  }
5579  return true;
5580 }
5581 
5582 
5599 bool QImage::operator!=(const QImage & i) const
5600 {
5601  return !(*this == i);
5602 }
5603 
5604 
5605 
5606 
5616 {
5617  return d ? qRound(d->dpmx) : 0;
5618 }
5619 
5629 {
5630  return d ? qRound(d->dpmy) : 0;
5631 }
5632 
5646 {
5647  if (!d || !x)
5648  return;
5649  detach();
5650 
5651  if (d)
5652  d->dpmx = x;
5653 }
5654 
5668 {
5669  if (!d || !y)
5670  return;
5671  detach();
5672 
5673  if (d)
5674  d->dpmy = y;
5675 }
5676 
5689 {
5690  return d ? d->offset : QPoint();
5691 }
5692 
5693 
5706 {
5707  if (!d)
5708  return;
5709  detach();
5710 
5711  if (d)
5712  d->offset = p;
5713 }
5714 #ifndef QT_NO_IMAGE_TEXT
5715 
5725 {
5726  return d ? QStringList(d->text.keys()) : QStringList();
5727 }
5728 
5737 {
5738  if (!d)
5739  return QString();
5740 
5741  if (!key.isEmpty())
5742  return d->text.value(key);
5743 
5744  QString tmp;
5745  foreach (const QString &key, d->text.keys()) {
5746  if (!tmp.isEmpty())
5747  tmp += QLatin1String("\n\n");
5748  tmp += key + QLatin1String(": ") + d->text.value(key).simplified();
5749  }
5750  return tmp;
5751 }
5752 
5780 void QImage::setText(const QString &key, const QString &value)
5781 {
5782  if (!d)
5783  return;
5784  detach();
5785 
5786  if (d)
5787  d->text.insert(key, value);
5788 }
5789 
5802 QString QImage::text(const char* key, const char* lang) const
5803 {
5804  if (!d)
5805  return QString();
5806  QString k = QString::fromAscii(key);
5807  if (lang && *lang)
5808  k += QLatin1Char('/') + QString::fromAscii(lang);
5809  return d->text.value(k);
5810 }
5811 
5828 {
5829  if (!d)
5830  return QString();
5831  QString k = QString::fromAscii(kl.key);
5832  if (!kl.lang.isEmpty())
5833  k += QLatin1Char('/') + QString::fromAscii(kl.lang);
5834  return d->text.value(k);
5835 }
5836 
5851 {
5852  if (!d)
5853  return QStringList();
5855  QStringList languages;
5856  for (int i = 0; i < keys.size(); ++i) {
5857  int index = keys.at(i).indexOf(QLatin1Char('/'));
5858  if (index > 0)
5859  languages += keys.at(i).mid(index+1);
5860  }
5861 
5862  return languages;
5863 }
5864 
5880 {
5881  QList<QImageTextKeyLang> imageTextKeys;
5882  if (!d)
5883  return imageTextKeys;
5885  for (int i = 0; i < keys.size(); ++i) {
5886  int index = keys.at(i).indexOf(QLatin1Char('/'));
5887  if (index > 0) {
5888  QImageTextKeyLang tkl;
5889  tkl.key = keys.at(i).left(index).toAscii();
5890  tkl.lang = keys.at(i).mid(index+1).toAscii();
5891  imageTextKeys += tkl;
5892  }
5893  }
5894 
5895  return imageTextKeys;
5896 }
5897 
5920 void QImage::setText(const char* key, const char* lang, const QString& s)
5921 {
5922  if (!d)
5923  return;
5924  detach();
5925 
5926  // In case detach() ran out of memory
5927  if (!d)
5928  return;
5929 
5930  QString k = QString::fromAscii(key);
5931  if (lang && *lang)
5932  k += QLatin1Char('/') + QString::fromAscii(lang);
5933  d->text.insert(k, s);
5934 }
5935 
5936 #endif // QT_NO_IMAGE_TEXT
5937 
5938 /*
5939  Sets the image bits to the \a pixmap contents and returns a
5940  reference to the image.
5941 
5942  If the image shares data with other images, it will first
5943  dereference the shared data.
5944 
5945  Makes a call to QPixmap::convertToImage().
5946 */
5947 
5971 {
5972  if (!d)
5973  return 0;
5974 
5975  if (!d->paintEngine) {
5976 #ifdef Q_OS_SYMBIAN
5977  d->paintEngine = new QSymbianRasterPaintEngine(const_cast<QImage *>(this));
5978 #else
5979  d->paintEngine = new QRasterPaintEngine(const_cast<QImage *>(this));
5980 #endif
5981  }
5982 
5983  return d->paintEngine;
5984 }
5985 
5986 
5996 {
5997  if (!d)
5998  return 0;
5999 
6000  switch (metric) {
6001  case PdmWidth:
6002  return d->width;
6003  break;
6004 
6005  case PdmHeight:
6006  return d->height;
6007  break;
6008 
6009  case PdmWidthMM:
6010  return qRound(d->width * 1000 / d->dpmx);
6011  break;
6012 
6013  case PdmHeightMM:
6014  return qRound(d->height * 1000 / d->dpmy);
6015  break;
6016 
6017  case PdmNumColors:
6018  return d->colortable.size();
6019  break;
6020 
6021  case PdmDepth:
6022  return d->depth;
6023  break;
6024 
6025  case PdmDpiX:
6026  return qRound(d->dpmx * 0.0254);
6027  break;
6028 
6029  case PdmDpiY:
6030  return qRound(d->dpmy * 0.0254);
6031  break;
6032 
6033  case PdmPhysicalDpiX:
6034  return qRound(d->dpmx * 0.0254);
6035  break;
6036 
6037  case PdmPhysicalDpiY:
6038  return qRound(d->dpmy * 0.0254);
6039  break;
6040 
6041  default:
6042  qWarning("QImage::metric(): Unhandled metric type %d", metric);
6043  break;
6044  }
6045  return 0;
6046 }
6047 
6048 
6049 
6050 /*****************************************************************************
6051  QPixmap (and QImage) helper functions
6052  *****************************************************************************/
6053 /*
6054  This internal function contains the common (i.e. platform independent) code
6055  to do a transformation of pixel data. It is used by QPixmap::transform() and by
6056  QImage::transform().
6057 
6058  \a trueMat is the true transformation matrix (see QPixmap::trueMatrix()) and
6059  \a xoffset is an offset to the matrix.
6060 
6061  \a msbfirst specifies for 1bpp images, if the MSB or LSB comes first and \a
6062  depth specifies the colordepth of the data.
6063 
6064  \a dptr is a pointer to the destination data, \a dbpl specifies the bits per
6065  line for the destination data, \a p_inc is the offset that we advance for
6066  every scanline and \a dHeight is the height of the destination image.
6067 
6068  \a sprt is the pointer to the source data, \a sbpl specifies the bits per
6069  line of the source data, \a sWidth and \a sHeight are the width and height of
6070  the source data.
6071 */
6072 
6073 #undef IWX_MSB
6074 #define IWX_MSB(b) if (trigx < maxws && trigy < maxhs) { \
6075  if (*(sptr+sbpl*(trigy>>12)+(trigx>>15)) & \
6076  (1 << (7-((trigx>>12)&7)))) \
6077  *dptr |= b; \
6078  } \
6079  trigx += m11; \
6080  trigy += m12;
6081  // END OF MACRO
6082 #undef IWX_LSB
6083 #define IWX_LSB(b) if (trigx < maxws && trigy < maxhs) { \
6084  if (*(sptr+sbpl*(trigy>>12)+(trigx>>15)) & \
6085  (1 << ((trigx>>12)&7))) \
6086  *dptr |= b; \
6087  } \
6088  trigx += m11; \
6089  trigy += m12;
6090  // END OF MACRO
6091 #undef IWX_PIX
6092 #define IWX_PIX(b) if (trigx < maxws && trigy < maxhs) { \
6093  if ((*(sptr+sbpl*(trigy>>12)+(trigx>>15)) & \
6094  (1 << (7-((trigx>>12)&7)))) == 0) \
6095  *dptr &= ~b; \
6096  } \
6097  trigx += m11; \
6098  trigy += m12;
6099  // END OF MACRO
6100 bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth,
6101  uchar *dptr, int dbpl, int p_inc, int dHeight,
6102  const uchar *sptr, int sbpl, int sWidth, int sHeight)
6103 {
6104  int m11 = int(trueMat.m11()*qreal(4096.0));
6105  int m12 = int(trueMat.m12()*qreal(4096.0));
6106  int m21 = int(trueMat.m21()*qreal(4096.0));
6107  int m22 = int(trueMat.m22()*qreal(4096.0));
6108  int dx = qRound(trueMat.dx()*qreal(4096.0));
6109  int dy = qRound(trueMat.dy()*qreal(4096.0));
6110 
6111  int m21ydx = dx + (xoffset<<16) + (m11 + m21) / 2;
6112  int m22ydy = dy + (m12 + m22) / 2;
6113  uint trigx;
6114  uint trigy;
6115  uint maxws = sWidth<<12;
6116  uint maxhs = sHeight<<12;
6117 
6118  for (int y=0; y<dHeight; y++) { // for each target scanline
6119  trigx = m21ydx;
6120  trigy = m22ydy;
6121  uchar *maxp = dptr + dbpl;
6122  if (depth != 1) {
6123  switch (depth) {
6124  case 8: // 8 bpp transform
6125  while (dptr < maxp) {
6126  if (trigx < maxws && trigy < maxhs)
6127  *dptr = *(sptr+sbpl*(trigy>>12)+(trigx>>12));
6128  trigx += m11;
6129  trigy += m12;
6130  dptr++;
6131  }
6132  break;
6133 
6134  case 16: // 16 bpp transform
6135  while (dptr < maxp) {
6136  if (trigx < maxws && trigy < maxhs)
6137  *((ushort*)dptr) = *((ushort *)(sptr+sbpl*(trigy>>12) +
6138  ((trigx>>12)<<1)));
6139  trigx += m11;
6140  trigy += m12;
6141  dptr++;
6142  dptr++;
6143  }
6144  break;
6145 
6146  case 24: // 24 bpp transform
6147  while (dptr < maxp) {
6148  if (trigx < maxws && trigy < maxhs) {
6149  const uchar *p2 = sptr+sbpl*(trigy>>12) + ((trigx>>12)*3);
6150  dptr[0] = p2[0];
6151  dptr[1] = p2[1];
6152  dptr[2] = p2[2];
6153  }
6154  trigx += m11;
6155  trigy += m12;
6156  dptr += 3;
6157  }
6158  break;
6159 
6160  case 32: // 32 bpp transform
6161  while (dptr < maxp) {
6162  if (trigx < maxws && trigy < maxhs)
6163  *((uint*)dptr) = *((uint *)(sptr+sbpl*(trigy>>12) +
6164  ((trigx>>12)<<2)));
6165  trigx += m11;
6166  trigy += m12;
6167  dptr += 4;
6168  }
6169  break;
6170 
6171  default: {
6172  return false;
6173  }
6174  }
6175  } else {
6176  switch (type) {
6178  while (dptr < maxp) {
6179  IWX_MSB(128);
6180  IWX_MSB(64);
6181  IWX_MSB(32);
6182  IWX_MSB(16);
6183  IWX_MSB(8);
6184  IWX_MSB(4);
6185  IWX_MSB(2);
6186  IWX_MSB(1);
6187  dptr++;
6188  }
6189  break;
6191  while (dptr < maxp) {
6192  IWX_LSB(1);
6193  IWX_LSB(2);
6194  IWX_LSB(4);
6195  IWX_LSB(8);
6196  IWX_LSB(16);
6197  IWX_LSB(32);
6198  IWX_LSB(64);
6199  IWX_LSB(128);
6200  dptr++;
6201  }
6202  break;
6203 # if defined(Q_WS_WIN)
6205  while (dptr < maxp) {
6206  IWX_PIX(128);
6207  IWX_PIX(64);
6208  IWX_PIX(32);
6209  IWX_PIX(16);
6210  IWX_PIX(8);
6211  IWX_PIX(4);
6212  IWX_PIX(2);
6213  IWX_PIX(1);
6214  dptr++;
6215  }
6216  break;
6217 # endif
6218  }
6219  }
6220  m21ydx += m21;
6221  m22ydy += m22;
6222  dptr += p_inc;
6223  }
6224  return true;
6225 }
6226 #undef IWX_MSB
6227 #undef IWX_LSB
6228 #undef IWX_PIX
6229 
6268 {
6269  if (!d)
6270  return 0;
6271  else
6272  return d->ser_no;
6273 }
6274 
6283 {
6284  if (!d)
6285  return 0;
6286  else
6287  return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
6288 }
6289 
6302 {
6303  return d && d->ref == 1;
6304 }
6305 
6306 
6330 {
6331  if (!d)
6332  return;
6333 
6334  int w = d->width;
6335  int h = d->height;
6336 
6337  if (w != alphaChannel.d->width || h != alphaChannel.d->height) {
6338  qWarning("QImage::setAlphaChannel: "
6339  "Alpha channel must have same dimensions as the target image");
6340  return;
6341  }
6342 
6343  if (d->paintEngine && d->paintEngine->isActive()) {
6344  qWarning("QImage::setAlphaChannel: "
6345  "Unable to set alpha channel while image is being painted on");
6346  return;
6347  }
6348 
6349  if (d->format == QImage::Format_ARGB32_Premultiplied)
6350  detach();
6351  else
6353 
6354  if (isNull())
6355  return;
6356 
6357  // Slight optimization since alphachannels are returned as 8-bit grays.
6358  if (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()) {
6359  const uchar *src_data = alphaChannel.d->data;
6360  const uchar *dest_data = d->data;
6361  for (int y=0; y<h; ++y) {
6362  const uchar *src = src_data;
6363  QRgb *dest = (QRgb *)dest_data;
6364  for (int x=0; x<w; ++x) {
6365  int alpha = *src;
6366  int destAlpha = qt_div_255(alpha * qAlpha(*dest));
6367  *dest = ((destAlpha << 24)
6368  | (qt_div_255(qRed(*dest) * alpha) << 16)
6369  | (qt_div_255(qGreen(*dest) * alpha) << 8)
6370  | (qt_div_255(qBlue(*dest) * alpha)));
6371  ++dest;
6372  ++src;
6373  }
6374  src_data += alphaChannel.d->bytes_per_line;
6375  dest_data += d->bytes_per_line;
6376  }
6377 
6378  } else {
6379  const QImage sourceImage = alphaChannel.convertToFormat(QImage::Format_RGB32);
6380  if (sourceImage.isNull()) {
6381  qWarning("QImage::setAlphaChannel: out of memory");
6382  return;
6383  }
6384  const uchar *src_data = sourceImage.d->data;
6385  const uchar *dest_data = d->data;
6386  for (int y=0; y<h; ++y) {
6387  const QRgb *src = (const QRgb *) src_data;
6388  QRgb *dest = (QRgb *) dest_data;
6389  for (int x=0; x<w; ++x) {
6390  int alpha = qGray(*src);
6391  int destAlpha = qt_div_255(alpha * qAlpha(*dest));
6392  *dest = ((destAlpha << 24)
6393  | (qt_div_255(qRed(*dest) * alpha) << 16)
6394  | (qt_div_255(qGreen(*dest) * alpha) << 8)
6395  | (qt_div_255(qBlue(*dest) * alpha)));
6396  ++dest;
6397  ++src;
6398  }
6399  src_data += sourceImage.d->bytes_per_line;
6400  dest_data += d->bytes_per_line;
6401  }
6402  }
6403 }
6404 
6405 
6431 {
6432  if (!d)
6433  return QImage();
6434 
6435  int w = d->width;
6436  int h = d->height;
6437 
6438  QImage image(w, h, Format_Indexed8);
6440  image.setColorCount(256);
6441 
6442  // set up gray scale table.
6443  for (int i=0; i<256; ++i)
6444  image.setColor(i, qRgb(i, i, i));
6445 
6446  if (!hasAlphaChannel()) {
6447  image.fill(255);
6448  return image;
6449  }
6450 
6451  if (d->format == Format_Indexed8) {
6452  const uchar *src_data = d->data;
6453  uchar *dest_data = image.d->data;
6454  for (int y=0; y<h; ++y) {
6455  const uchar *src = src_data;
6456  uchar *dest = dest_data;
6457  for (int x=0; x<w; ++x) {
6458  *dest = qAlpha(d->colortable.at(*src));
6459  ++dest;
6460  ++src;
6461  }
6462  src_data += d->bytes_per_line;
6463  dest_data += image.d->bytes_per_line;
6464  }
6465  } else {
6466  QImage alpha32 = *this;
6467  if (d->format != Format_ARGB32 && d->format != Format_ARGB32_Premultiplied)
6468  alpha32 = convertToFormat(Format_ARGB32);
6469  QIMAGE_SANITYCHECK_MEMORY(alpha32);
6470 
6471  const uchar *src_data = alpha32.d->data;
6472  uchar *dest_data = image.d->data;
6473  for (int y=0; y<h; ++y) {
6474  const QRgb *src = (const QRgb *) src_data;
6475  uchar *dest = dest_data;
6476  for (int x=0; x<w; ++x) {
6477  *dest = qAlpha(*src);
6478  ++dest;
6479  ++src;
6480  }
6481  src_data += alpha32.d->bytes_per_line;
6482  dest_data += image.d->bytes_per_line;
6483  }
6484  }
6485 
6486  return image;
6487 }
6488 
6496 {
6497  return d && (d->format == Format_ARGB32_Premultiplied
6498  || d->format == Format_ARGB32
6499  || d->format == Format_ARGB8565_Premultiplied
6500  || d->format == Format_ARGB8555_Premultiplied
6501  || d->format == Format_ARGB6666_Premultiplied
6502  || d->format == Format_ARGB4444_Premultiplied
6503  || (d->has_alpha_clut && (d->format == Format_Indexed8
6504  || d->format == Format_Mono
6505  || d->format == Format_MonoLSB)));
6506 }
6507 
6508 
6524 {
6525  if (!d)
6526  return 0;
6527  int bpc = 0;
6528  switch (d->format) {
6530  break;
6531  case QImage::Format_RGB32:
6532  bpc = 24;
6533  break;
6534  case QImage::Format_RGB666:
6535  bpc = 18;
6536  break;
6537  case QImage::Format_RGB555:
6538  bpc = 15;
6539  break;
6541  bpc = 23;
6542  break;
6543  case QImage::Format_RGB444:
6544  bpc = 12;
6545  break;
6546  default:
6547  bpc = qt_depthForFormat(d->format);
6548  break;
6549  }
6550  return bpc;
6551 }
6552 
6553 
6554 #ifdef QT3_SUPPORT
6555 #if defined(Q_WS_X11)
6557 #include <private/qt_x11_p.h>
6559 #endif
6560 
6561 QImage::Endian QImage::systemBitOrder()
6562 {
6563 #if defined(Q_WS_X11)
6564  return BitmapBitOrder(X11->display) == MSBFirst ? BigEndian : LittleEndian;
6565 #else
6566  return BigEndian;
6567 #endif
6568 }
6569 #endif
6570 
6611 static QImage smoothScaled(const QImage &source, int w, int h) {
6612  QImage src = source;
6613  if (src.format() == QImage::Format_ARGB32)
6615  else if (src.depth() < 32) {
6616  if (src.hasAlphaChannel())
6618  else
6620  }
6621 
6622  return qSmoothScaleImage(src, w, h);
6623 }
6624 
6625 
6626 static QImage rotated90(const QImage &image) {
6627  QImage out(image.height(), image.width(), image.format());
6629  if (image.colorCount() > 0)
6630  out.setColorTable(image.colorTable());
6631  int w = image.width();
6632  int h = image.height();
6633  switch (image.format()) {
6634  case QImage::Format_RGB32:
6635  case QImage::Format_ARGB32:
6637  qt_memrotate270(reinterpret_cast<const quint32*>(image.bits()),
6638  w, h, image.bytesPerLine(),
6639  reinterpret_cast<quint32*>(out.bits()),
6640  out.bytesPerLine());
6641  break;
6642  case QImage::Format_RGB666:
6646  case QImage::Format_RGB888:
6647  qt_memrotate270(reinterpret_cast<const quint24*>(image.bits()),
6648  w, h, image.bytesPerLine(),
6649  reinterpret_cast<quint24*>(out.bits()),
6650  out.bytesPerLine());
6651  break;
6652  case QImage::Format_RGB555:
6653  case QImage::Format_RGB16:
6655  qt_memrotate270(reinterpret_cast<const quint16*>(image.bits()),
6656  w, h, image.bytesPerLine(),
6657  reinterpret_cast<quint16*>(out.bits()),
6658  out.bytesPerLine());
6659  break;
6661  qt_memrotate270(reinterpret_cast<const quint8*>(image.bits()),
6662  w, h, image.bytesPerLine(),
6663  reinterpret_cast<quint8*>(out.bits()),
6664  out.bytesPerLine());
6665  break;
6666  default:
6667  for (int y=0; y<h; ++y) {
6668  if (image.colorCount())
6669  for (int x=0; x<w; ++x)
6670  out.setPixel(h-y-1, x, image.pixelIndex(x, y));
6671  else
6672  for (int x=0; x<w; ++x)
6673  out.setPixel(h-y-1, x, image.pixel(x, y));
6674  }
6675  break;
6676  }
6677  return out;
6678 }
6679 
6680 
6681 static QImage rotated180(const QImage &image) {
6682  return image.mirrored(true, true);
6683 }
6684 
6685 
6686 static QImage rotated270(const QImage &image) {
6687  QImage out(image.height(), image.width(), image.format());
6689  if (image.colorCount() > 0)
6690  out.setColorTable(image.colorTable());
6691  int w = image.width();
6692  int h = image.height();
6693  switch (image.format()) {
6694  case QImage::Format_RGB32:
6695  case QImage::Format_ARGB32:
6697  qt_memrotate90(reinterpret_cast<const quint32*>(image.bits()),
6698  w, h, image.bytesPerLine(),
6699  reinterpret_cast<quint32*>(out.bits()),
6700  out.bytesPerLine());
6701  break;
6702  case QImage::Format_RGB666:
6706  case QImage::Format_RGB888:
6707  qt_memrotate90(reinterpret_cast<const quint24*>(image.bits()),
6708  w, h, image.bytesPerLine(),
6709  reinterpret_cast<quint24*>(out.bits()),
6710  out.bytesPerLine());
6711  break;
6712  case QImage::Format_RGB555:
6713  case QImage::Format_RGB16:
6715  qt_memrotate90(reinterpret_cast<const quint16*>(image.bits()),
6716  w, h, image.bytesPerLine(),
6717  reinterpret_cast<quint16*>(out.bits()),
6718  out.bytesPerLine());
6719  break;
6721  qt_memrotate90(reinterpret_cast<const quint8*>(image.bits()),
6722  w, h, image.bytesPerLine(),
6723  reinterpret_cast<quint8*>(out.bits()),
6724  out.bytesPerLine());
6725  break;
6726  default:
6727  for (int y=0; y<h; ++y) {
6728  if (image.colorCount())
6729  for (int x=0; x<w; ++x)
6730  out.setPixel(y, w-x-1, image.pixelIndex(x, y));
6731  else
6732  for (int x=0; x<w; ++x)
6733  out.setPixel(y, w-x-1, image.pixel(x, y));
6734  }
6735  break;
6736  }
6737  return out;
6738 }
6739 
6758 {
6759  if (!d)
6760  return QImage();
6761 
6762  // source image data
6763  int ws = width();
6764  int hs = height();
6765 
6766  // target image data
6767  int wd;
6768  int hd;
6769 
6770  // compute size of target image
6771  QTransform mat = trueMatrix(matrix, ws, hs);
6772  bool complex_xform = false;
6773  bool scale_xform = false;
6774  if (mat.type() <= QTransform::TxScale) {
6775  if (mat.type() == QTransform::TxNone) // identity matrix
6776  return *this;
6777  else if (mat.m11() == -1. && mat.m22() == -1.)
6778  return rotated180(*this);
6779 
6780  if (mode == Qt::FastTransformation) {
6781  hd = qRound(qAbs(mat.m22()) * hs);
6782  wd = qRound(qAbs(mat.m11()) * ws);
6783  } else {
6784  hd = int(qAbs(mat.m22()) * hs + 0.9999);
6785  wd = int(qAbs(mat.m11()) * ws + 0.9999);
6786  }
6787  scale_xform = true;
6788  } else {
6789  if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
6790  if (mat.m12() == 1. && mat.m21() == -1.)
6791  return rotated90(*this);
6792  else if (mat.m12() == -1. && mat.m21() == 1.)
6793  return rotated270(*this);
6794  }
6795 
6796  QPolygonF a(QRectF(0, 0, ws, hs));
6797  a = mat.map(a);
6798  QRect r = a.boundingRect().toAlignedRect();
6799  wd = r.width();
6800  hd = r.height();
6801  complex_xform = true;
6802  }
6803 
6804  if (wd == 0 || hd == 0)
6805  return QImage();
6806 
6807  // Make use of the optimized algorithm when we're scaling
6808  if (scale_xform && mode == Qt::SmoothTransformation) {
6809  if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
6810  return smoothScaled(mirrored(true, true), wd, hd);
6811  } else if (mat.m11() < 0.0F) { // horizontal flip
6812  return smoothScaled(mirrored(true, false), wd, hd);
6813  } else if (mat.m22() < 0.0F) { // vertical flip
6814  return smoothScaled(mirrored(false, true), wd, hd);
6815  } else { // no flipping
6816  return smoothScaled(*this, wd, hd);
6817  }
6818  }
6819 
6820  int bpp = depth();
6821 
6822  int sbpl = bytesPerLine();
6823  const uchar *sptr = bits();
6824 
6825  QImage::Format target_format = d->format;
6826 
6827  if (complex_xform || mode == Qt::SmoothTransformation) {
6828  if (d->format < QImage::Format_RGB32 || !hasAlphaChannel()) {
6829  switch(d->format) {
6830  case QImage::Format_RGB16:
6831  target_format = Format_ARGB8565_Premultiplied;
6832  break;
6833  case QImage::Format_RGB555:
6834  target_format = Format_ARGB8555_Premultiplied;
6835  break;
6836  case QImage::Format_RGB666:
6837  target_format = Format_ARGB6666_Premultiplied;
6838  break;
6839  case QImage::Format_RGB444:
6840  target_format = Format_ARGB4444_Premultiplied;
6841  break;
6842  default:
6843  target_format = Format_ARGB32_Premultiplied;
6844  break;
6845  }
6846  }
6847  }
6848 
6849  QImage dImage(wd, hd, target_format);
6850  QIMAGE_SANITYCHECK_MEMORY(dImage);
6851 
6852  if (target_format == QImage::Format_MonoLSB
6853  || target_format == QImage::Format_Mono
6854  || target_format == QImage::Format_Indexed8) {
6855  dImage.d->colortable = d->colortable;
6856  dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
6857  }
6858 
6859  dImage.d->dpmx = dotsPerMeterX();
6860  dImage.d->dpmy = dotsPerMeterY();
6861 
6862  switch (bpp) {
6863  // initizialize the data
6864  case 8:
6865  if (dImage.d->colortable.size() < 256) {
6866  // colors are left in the color table, so pick that one as transparent
6867  dImage.d->colortable.append(0x0);
6868  memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.byteCount());
6869  } else {
6870  memset(dImage.bits(), 0, dImage.byteCount());
6871  }
6872  break;
6873  case 1:
6874  case 16:
6875  case 24:
6876  case 32:
6877  memset(dImage.bits(), 0x00, dImage.byteCount());
6878  break;
6879  }
6880 
6881  if (target_format >= QImage::Format_RGB32) {
6882  QPainter p(&dImage);
6883  if (mode == Qt::SmoothTransformation) {
6886  }
6887  p.setTransform(mat);
6888  p.drawImage(QPoint(0, 0), *this);
6889  } else {
6890  bool invertible;
6891  mat = mat.inverted(&invertible); // invert matrix
6892  if (!invertible) // error, return null image
6893  return QImage();
6894 
6895  // create target image (some of the code is from QImage::copy())
6897  int dbpl = dImage.bytesPerLine();
6898  qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
6899  }
6900  return dImage;
6901 }
6902 
6927 QTransform QImage::trueMatrix(const QTransform &matrix, int w, int h)
6928 {
6929  const QRectF rect(0, 0, w, h);
6930  const QRect mapped = matrix.mapRect(rect).toAlignedRect();
6931  const QPoint delta = mapped.topLeft();
6932  return matrix * QTransform().translate(-delta.x(), -delta.y());
6933 }
6934 
6935 bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
6936 {
6937  if (format == newFormat)
6938  return true;
6939 
6940  // No in-place conversion if we have to detach
6941  if (ref > 1)
6942  return false;
6943 
6944  const InPlace_Image_Converter *const converterPtr = &inplace_converter_map[format][newFormat];
6945  InPlace_Image_Converter converter = *converterPtr;
6946  if (converter)
6947  return converter(this, flags);
6948  else
6949  return false;
6950 }
6951 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
void setTransform(const QTransform &transform, bool combine=false)
Sets the world transformation matrix.
Definition: qpainter.cpp:9547
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
QRect toAlignedRect() const
Returns a QRect based on the values of this rectangle that is the smallest possible integer rectangle...
Definition: qrect.cpp:2817
#define MAX_B
static uint hash(const uchar *p, int n)
Definition: qhash.cpp:68
int width
Definition: qimage_p.h:76
QDataStream & operator>>(QDataStream &stream, QImage &image)
Reads an image from the given stream and stores it in the given image.
Definition: qimage.cpp:5435
static void convert_Indexed8_to_X32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:3341
#define IWX_PIX(b)
Definition: qimage.cpp:6092
QRgbMap()
Definition: qimage.cpp:3065
Format
The following image formats are available in Qt.
Definition: qimage.h:91
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
Definition: qbezier.cpp:289
unsigned int QRgb
Definition: qrgb.h:53
qreal dpmy
Definition: qimage_p.h:91
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
static QVector< QRgb > fix_color_table(const QVector< QRgb > &ctbl, QImage::Format format)
Definition: qimage.cpp:2754
const uchar * qt_get_bitflip_array()
Definition: qimage.cpp:765
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 CONVERT_PTR(DST, SRC)
Definition: qimage.cpp:3490
double qreal
Definition: qglobal.h:1193
static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
Definition: qimage.cpp:2460
~QImageData()
Definition: qimage.cpp:220
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
static void convert_ARGB_PM_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
Definition: qimage.cpp:3329
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:2436
Q_CORE_EXPORT QTextStream & ws(QTextStream &s)
uchar qt_pow_rgb_gamma[256]
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
static QImage rotated180(const QImage &src)
Definition: qimage.cpp:6681
QT_DEPRECATED void setNumColors(int)
Resizes the color table to contain numColors entries.
Definition: qimage.cpp:2252
T * data() const
Returns the value of the pointer referenced by this object.
void setColorTable(const QVector< QRgb > colors)
Sets the color table used to translate color indexes to QRgb values, to the specified colors...
Definition: qimage.cpp:1744
uchar used
Definition: qimage.cpp:3067
The QMatrix class specifies 2D transformations of a coordinate system.
Definition: qmatrix.h:61
static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:3416
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
Definition: qrgb.h:66
void setData(const QByteArray &data)
Sets the contents of the internal buffer to be data.
Definition: qbuffer.cpp:315
MaskMode
Definition: qnamespace.h:1490
static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
Definition: qimage.cpp:2635
Q_GUI_EXPORT int qt_defaultDpiY()
Definition: qfont.cpp:201
static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
Definition: qimage.cpp:3071
bool open(OpenMode openMode)
Reimplemented Function
Definition: qbuffer.cpp:338
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
uint has_alpha_clut
Definition: qimage_p.h:96
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
static Expression::Ptr create(Expression *const expr, const YYLTYPE &sourceLocator, const ParserContext *const parseInfo)
Q_GUI_EXPORT int qt_defaultDpiX()
Definition: qfont.cpp:162
T * take()
Returns the value of the pointer referenced by this object.
InvertMode
This enum type is used to describe how pixel values should be inverted in the invertPixels() function...
Definition: qimage.h:90
virtual int metric(PaintDeviceMetric metric) const
Returns the size for the specified metric on the device.
Definition: qimage.cpp:5995
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
Definition: qsimd_p.h:217
QT_DEPRECATED QStringList textLanguages() const
Returns the language identifiers for which some texts are recorded.
Definition: qimage.cpp:5850
bool save(const QString &fileName, const char *format=0, int quality=-1) const
Saves the image to the file with the given fileName, using the given image file format and quality fa...
Definition: qimage.cpp:5346
int byteCount() const
Returns the number of bytes occupied by the image data.
Definition: qimage.cpp:1800
void setQuality(int quality)
This is an image format specific function that sets the quality level of the image to quality...
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false...
Definition: qimage.cpp:6495
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
long ASN1_INTEGER_get ASN1_INTEGER * a
unsigned char quint8
Definition: qglobal.h:934
void qGamma_correct_back_to_linear_cs(QImage *image)
Definition: qimage.cpp:3938
int dotsPerMeterY() const
Returns the number of pixels that fit vertically in a physical meter.
Definition: qimage.cpp:5628
bool ref()
Atomically increments the value of this QAtomicInt.
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
Definition: qtransform.cpp:417
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
static void convert_ARGB_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:2687
The QString class provides a Unicode character string.
Definition: qstring.h:83
static void swap_bit_order(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:2711
QRect rect() const
Returns the enclosing rectangle (0, 0, width(), height()) of the image.
Definition: qimage.cpp:1603
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
QImage rgbSwapped() const
Returns a QImage in which the values of the red and blue components of all pixels have been swapped...
Definition: qimage.cpp:5052
QImageData * d
Definition: qimage.h:336
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QRectF boundingRect() const
Returns the bounding rectangle of the polygon, or QRectF(0,0,0,0) if the polygon is empty...
Definition: qpolygon.cpp:742
QVector< QRgb > colortable
Definition: qimage_p.h:80
TransformationType type() const
Returns the transformation type of this matrix.
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
#define X11
Definition: qt_x11_p.h:724
#define MAX_R
QRgb rgb
Definition: qimage.cpp:3068
void Q_GUI_EXPORT qt_memrotate90(const quint32 *, int, int, int, quint32 *, int)
QRgb pixel(int x, int y) const
Returns the color of the pixel at coordinates (x, y).
Definition: qimage.cpp:4240
void qInitImageConversions()
Definition: qimage.cpp:3909
QStringList keys
QPoint offset() const
Returns the number of pixels by which the image is intended to be offset by when positioning relative...
Definition: qimage.cpp:5688
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
bool load(QIODevice *device, const char *format)
This function reads a QImage from the given device.
Definition: qimage.cpp:5251
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
QImage()
Constructs a null image.
Definition: qimage.cpp:798
QTransform inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qtransform.cpp:364
bool paintingActive() const
Definition: qpaintdevice.h:170
GlobalColor
Definition: qnamespace.h:104
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
static QImageData * create(const QSize &size, QImage::Format format, int numColors=0)
Definition: qimage.cpp:151
QFuture< T > mapped(const Sequence &sequence, MapFunction function)
int pixelIndex(int x, int y) const
Returns the pixel index at (x, y).
Definition: qimage.cpp:4194
static void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha)
Definition: qimage.cpp:2774
#define PIX(x, y)
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
for(int ii=mo->methodOffset();ii< mo->methodCount();++ii)
unsigned char uchar
Definition: qglobal.h:994
void setOffset(const QPoint &)
Sets the number of pixels by which the image is intended to be offset by when positioning relative to...
Definition: qimage.cpp:5705
int width() const
Returns the width.
Definition: qsize.h:126
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
void setRenderHint(RenderHint hint, bool on=true)
Sets the given render hint on the painter if on is true; otherwise clears the render hint...
Definition: qpainter.cpp:7620
static void executeImageHooks(qint64 key)
static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags)
Definition: qimage.cpp:2531
void setColorCount(int)
Resizes the color table to contain colorCount entries.
Definition: qimage.cpp:2275
static int pixel_distance(QRgb p1, QRgb p2)
Definition: qimage.cpp:4001
static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:2663
int detach_no
Definition: qimage_p.h:88
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QT_DEPRECATED int numBytes() const
Returns the number of bytes occupied by the image data.
Definition: qimage.cpp:1785
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
int height
Definition: qimage_p.h:77
qreal dpmx
Definition: qimage_p.h:90
static bool checkPixelSize(const QImage::Format format)
Definition: qimage.cpp:76
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
int ser_no
Definition: qimage_p.h:87
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void setText(const QString &key, const QString &value)
Sets the image text to the given text and associate it with the given key.
Definition: qimage.cpp:5780
The QImageWriter class provides a format independent interface for writing images to files or other d...
Definition: qimagewriter.h:59
Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x)
static void mask_alpha_converter(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:2732
QImageData()
Definition: qimage.cpp:129
#define CONVERT_DECL(DST, SRC)
Definition: qimage.cpp:3456
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
bool deref()
Atomically decrements the value of this QAtomicInt.
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
QString text(const QString &key=QString()) const
Returns the image text associated with the given key.
Definition: qimage.cpp:5736
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
bool operator!=(const QImage &) const
Returns true if this image and the given image have different contents; otherwise returns false...
Definition: qimage.cpp:5599
The QPolygonF class provides a vector of points using floating point precision.
Definition: qpolygon.h:134
TransformationMode
Definition: qnamespace.h:1510
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
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
QBasicAtomicInt qimage_serial_number
Definition: qimage.cpp:127
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
QPoint map(const QPoint &p) const
Creates and returns a QPoint object that is a copy of the given point, mapped into the coordinate sys...
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
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
QT_DEPRECATED int numColors() const
Returns the size of the color table for the image.
Definition: qimage.cpp:1636
QImage createAlphaMask(Qt::ImageConversionFlags flags=Qt::AutoColor) const
Builds and returns a 1-bpp mask from the alpha buffer in this image.
Definition: qimage.cpp:4720
#define QT_XFORM_TYPE_MSBFIRST
bool isGrayscale() const
For 32-bit images, this function is equivalent to allGray().
Definition: qimage.cpp:4477
static QImage rotated90(const QImage &src)
Definition: qimage.cpp:6626
void setDotsPerMeterY(int)
Sets the number of pixels that fit vertically in a physical meter, to y.
Definition: qimage.cpp:5667
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
__int64 qint64
Definition: qglobal.h:942
QImage & operator=(const QImage &)
Assigns a shallow copy of the given image to this image and returns a reference to this image...
Definition: qimage.cpp:1304
bool operator==(const QImage &) const
Returns true if this image and the given image have the same contents; otherwise returns false...
Definition: qimage.cpp:5531
QImage transformed(const QMatrix &matrix, Qt::TransformationMode mode=Qt::FastTransformation) const
Returns a copy of the image that is transformed using the given transformation matrix and transformat...
Definition: qimage.cpp:4698
const uchar * constBits() const
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1985
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
QImage mirrored(bool horizontally=false, bool vertically=true) const
Returns a mirror of the image, mirrored in the horizontal and/or the vertical direction depending on ...
Definition: qimage.cpp:4922
The QScopedArrayPointer class stores a pointer to a dynamically allocated array of objects...
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
Definition: qrgb.h:63
#define QT_XFORM_TYPE_LSBFIRST
int nbytes
Definition: qimage_p.h:79
static void convert_Mono_to_X32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:3374
QImage alphaChannel() const
Returns the alpha channel of the image as a new grayscale QImage in which each pixel&#39;s red...
Definition: qimage.cpp:6430
The QImageReader class provides a format independent interface for reading images from files or other...
Definition: qimagereader.h:62
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
bool valid(int x, int y) const
Returns true if QPoint(x, y) is a valid coordinate pair within the image; otherwise returns false...
Definition: qimage.cpp:4165
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1926
int version() const
Returns the version number of the data serialization format.
Definition: qdatastream.h:212
static void convert_ARGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
Definition: qimage.cpp:3336
static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
Definition: qimage.cpp:2479
int bytes_per_line
Definition: qimage_p.h:86
const uint qt_bayer_matrix[16][16]
QDataStream & operator<<(QDataStream &stream, const QImage &image)
Writes the given image to the given stream as a PNG image, or as a BMP image if the stream&#39;s version ...
Definition: qimage.cpp:5406
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
void insert(int i, const T &t)
Inserts value at index position i in the vector.
Definition: qvector.h:362
Q_GUI_EXPORT_INLINE int qGray(int r, int g, int b)
Definition: qrgb.h:75
static QImage rotated270(const QImage &src)
Definition: qimage.cpp:6686
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
void setPixel(int x, int y, uint index_or_rgb)
Sets the pixel index or color at (x, y) to index_or_rgb.
Definition: qimage.cpp:4311
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
#define IWX_MSB(b)
Definition: qimage.cpp:6074
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
QByteArray lang
Definition: qimage.h:75
static const uchar bitflip[256]
Definition: qimage.cpp:736
QIODevice * device() const
Returns the I/O device currently set, or 0 if no device is currently set.
Definition: qdatastream.h:206
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
Definition: qpainter.cpp:2422
void setDotsPerMeterX(int)
Sets the number of pixels that fit horizontally in a physical meter, to x.
Definition: qimage.cpp:5645
#define DITHER(p, m)
Q_STATIC_INLINE_FUNCTION quint32p fromRawData(quint32 v)
bool checkForAlphaPixels() const
Definition: qimage.cpp:236
QImage scaledToHeight(int h, Qt::TransformationMode mode=Qt::FastTransformation) const
Returns a scaled copy of the image.
Definition: qimage.cpp:4646
int bitPlaneCount() const
Returns the number of bit planes in the image.
Definition: qimage.cpp:6523
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
int colorCount() const
Returns the size of the color table for the image.
Definition: qimage.cpp:1656
void qt_memconvert(DST *dest, const SRC *src, int count)
uint qDetectCPUFeatures()
Definition: qsimd.cpp:382
uint own_data
Definition: qimage_p.h:94
unsigned short ushort
Definition: qglobal.h:995
void Q_GUI_QWS_EXPORT qt_memrotate270(const quint32 *, int, int, int, quint32 *, int)
QImage::Format format
Definition: qimage_p.h:85
static QImage convertWithPalette(const QImage &src, QImage::Format format, const QVector< QRgb > &clut)
Definition: qimage.cpp:4028
Q_GUI_EXPORT qint64 qt_image_id(const QImage &image)
Definition: qimage.cpp:117
uint ro_data
Definition: qimage_p.h:95
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
Definition: qimage.cpp:2580
QPoint offset
Definition: qimage_p.h:92
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
Q_DECL_CONSTEXPR const T & qBound(const T &min, const T &val, const T &max)
Definition: qglobal.h:1219
unsigned int quint32
Definition: qglobal.h:938
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
static QImage smoothScaled(const QImage &source, int w, int h)
Definition: qimage.cpp:6611
bool isDetached() const
Returns true if the image is detached; otherwise returns false.
Definition: qimage.cpp:6301
Definition: qsimd_p.h:222
QByteArray toAscii() const Q_REQUIRED_RESULT
Returns an 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4014
int & rheight()
Returns a reference to the height.
Definition: qsize.h:144
bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth, uchar *dptr, int dbpl, int p_inc, int dHeight, const uchar *sptr, int sbpl, int sWidth, int sHeight)
Definition: qimage.cpp:6100
int height() const
Returns the height.
Definition: qsize.h:129
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
static int closestMatch(QRgb pixel, const QVector< QRgb > &clut)
Definition: qimage.cpp:4015
bool isValid() const
Returns true if both the width and height is equal to or greater than 0; otherwise returns false...
Definition: qsize.h:123
bool(* InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags)
Definition: qimage.cpp:2434
QFactoryLoader * l
int devType() const
Definition: qimage.cpp:1332
QImage scaledToWidth(int w, Qt::TransformationMode mode=Qt::FastTransformation) const
Returns a scaled copy of the image.
Definition: qimage.cpp:4615
~QImage()
Destroys the image and cleans up.
Definition: qimage.cpp:1289
uchar * data
Definition: qimage_p.h:81
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
#define QIMAGE_SANITYCHECK_MEMORY(image)
Definition: qimage.cpp:105
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Definition: qpainter.cpp:5936
static void convert_X_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
Definition: qimage.cpp:3044
quint16 index
QT_DEPRECATED QList< QImageTextKeyLang > textList() const
Returns a list of QImageTextKeyLang objects that enumerate all the texts key/language pairs set for t...
Definition: qimage.cpp:5879
QAtomicInt ref
Definition: qimage_p.h:74
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
Definition: qrgb.h:60
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
Q_STATIC_INLINE_FUNCTION int qt_div_255(int x)
void scale(int w, int h, Qt::AspectRatioMode mode)
Scales the size to a rectangle with the given width and height, according to the specified mode: ...
Definition: qsize.h:138
void(* Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
Definition: qimage.cpp:2432
static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats]
Definition: qimage.cpp:3812
static void convert_ARGB_PM_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
Definition: qimage.cpp:3049
QImage createHeuristicMask(bool clipTight=true) const
Creates and returns a 1-bpp heuristic mask for this image.
Definition: qimage.cpp:4762
QPaintEngine * paintEngine() const
Used by QPainter to retrieve a paint engine for the image.
Definition: qimage.cpp:5970
int qt_depthForFormat(QImage::Format format)
Definition: qimage_p.h:116
const QVector< QRgb > * qt_image_colortable(const QImage &image)
Definition: qimage.cpp:122
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
uchar pix
Definition: qimage.cpp:3066
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
void invertPixels(InvertMode=InvertRgb)
Inverts all pixel values in the image.
Definition: qimage.cpp:2179
static QTransform fromScale(qreal dx, qreal dy)
Creates a matrix which corresponds to a scaling of sx horizontally and sy vertically.
Definition: qtransform.cpp:528
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
#define QT_XFORM_TYPE_WINDOWSPIXMAP
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
#define INV_PREMUL(p)
The QRasterPaintEngine class enables hardware acceleration of painting operations in Qt for Embedded ...
Definition: qsimd_p.h:220
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
#define INDEXOF(r, g, b)
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
QImage scaled(int w, int h, Qt::AspectRatioMode aspectMode=Qt::IgnoreAspectRatio, Qt::TransformationMode mode=Qt::FastTransformation) const
Definition: qimage.h:232
int depth
Definition: qimage_p.h:78
static const KeyPair *const end
#define MAX_G
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
bool qt_read_xpm_image_or_array(QIODevice *device, const char *const *source, QImage &image)
bool write(const QImage &image)
Writes the image image to the assigned device or file name.
bool doImageIO(const QImage *image, QImageWriter *io, int quality) const
Definition: qimage.cpp:5379
#define IWX_LSB(b)
Definition: qimage.cpp:6083
#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
static QString fileName(const QString &fileUrl)
QImage createMaskFromColor(QRgb color, Qt::MaskMode mode=Qt::MaskInColor) const
Creates and returns a mask for this image based on the given color value.
Definition: qimage.cpp:4865
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
static QImage fromData(const uchar *data, int size, const char *format=0)
Constructs a QImage from the first size bytes of the given binary data.
Definition: qimage.cpp:5313
int dotsPerMeterX() const
Returns the number of pixels that fit horizontally in a physical meter.
Definition: qimage.cpp:5615
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QStringList textKeys() const
Returns the text keys for this image.
Definition: qimage.cpp:5724
#define INT_MAX
QVector< QRgb > colorTable() const
Returns a list of the colors contained in the image&#39;s color table, or an empty list if the image does...
Definition: qimage.cpp:1770
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
QByteArray key
Definition: qimage.h:74
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
qint64 cacheKey() const
Returns a number that identifies the contents of this QImage object.
Definition: qimage.cpp:6282
uint is_cached
Definition: qimage_p.h:97
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
static QMatrix trueMatrix(const QMatrix &, int w, int h)
Returns the actual matrix used for transforming an image with the given width, height and matrix...
Definition: qimage.cpp:4680
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
QMap< QString, QString > text
Definition: qimage_p.h:106
static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats]
Definition: qimage.cpp:3513
int & rwidth()
Returns a reference to the width.
Definition: qsize.h:141
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
Definition: qpainter.cpp:7420
bool loadFromData(const uchar *buf, int len, const char *format=0)
Loads an image from the first len bytes of the given binary data.
Definition: qimage.cpp:5275
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
bool allGray() const
Returns true if all the colors in the image are shades of gray (i.e.
Definition: qimage.cpp:4435
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
Q_GUI_EXPORT_INLINE bool qIsGray(QRgb rgb)
Definition: qrgb.h:81
AspectRatioMode
Definition: qnamespace.h:1317