Qt 4.8
qtiffhandler.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 plugins 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 "qtiffhandler_p.h"
43 #include <qvariant.h>
44 #include <qdebug.h>
45 #include <qimage.h>
46 #include <qglobal.h>
47 extern "C" {
48 #include "tiffio.h"
49 }
50 
52 
53 tsize_t qtiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
54 {
55  QIODevice* device = static_cast<QTiffHandler*>(fd)->device();
56  return device->isReadable() ? device->read(static_cast<char *>(buf), size) : -1;
57 }
58 
59 tsize_t qtiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
60 {
61  return static_cast<QTiffHandler*>(fd)->device()->write(static_cast<char *>(buf), size);
62 }
63 
64 toff_t qtiffSeekProc(thandle_t fd, toff_t off, int whence)
65 {
66  QIODevice *device = static_cast<QTiffHandler*>(fd)->device();
67  switch (whence) {
68  case SEEK_SET:
69  device->seek(off);
70  break;
71  case SEEK_CUR:
72  device->seek(device->pos() + off);
73  break;
74  case SEEK_END:
75  device->seek(device->size() + off);
76  break;
77  }
78 
79  return device->pos();
80 }
81 
82 int qtiffCloseProc(thandle_t /*fd*/)
83 {
84  return 0;
85 }
86 
87 toff_t qtiffSizeProc(thandle_t fd)
88 {
89  return static_cast<QTiffHandler*>(fd)->device()->size();
90 }
91 
92 int qtiffMapProc(thandle_t /*fd*/, tdata_t* /*pbase*/, toff_t* /*psize*/)
93 {
94  return 0;
95 }
96 
97 void qtiffUnmapProc(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/)
98 {
99 }
100 
101 // for 32 bits images
102 inline void rotate_right_mirror_horizontal(QImage *const image)// rotate right->mirrored horizontal
103 {
104  const int height = image->height();
105  const int width = image->width();
106  QImage generated(/* width = */ height, /* height = */ width, image->format());
107  const uint32 *originalPixel = reinterpret_cast<const uint32*>(image->bits());
108  uint32 *const generatedPixels = reinterpret_cast<uint32*>(generated.bits());
109  for (int row=0; row < height; ++row) {
110  for (int col=0; col < width; ++col) {
111  int idx = col * height + row;
112  generatedPixels[idx] = *originalPixel;
113  ++originalPixel;
114  }
115  }
116  *image = generated;
117 }
118 
119 inline void rotate_right_mirror_vertical(QImage *const image) // rotate right->mirrored vertical
120 {
121  const int height = image->height();
122  const int width = image->width();
123  QImage generated(/* width = */ height, /* height = */ width, image->format());
124  const int lastCol = width - 1;
125  const int lastRow = height - 1;
126  const uint32 *pixel = reinterpret_cast<const uint32*>(image->bits());
127  uint32 *const generatedBits = reinterpret_cast<uint32*>(generated.bits());
128  for (int row=0; row < height; ++row) {
129  for (int col=0; col < width; ++col) {
130  int idx = (lastCol - col) * height + (lastRow - row);
131  generatedBits[idx] = *pixel;
132  ++pixel;
133  }
134  }
135  *image = generated;
136 }
137 
139 {
141 }
142 
144 {
145  if (canRead(device())) {
146  setFormat("tiff");
147  return true;
148  }
149  return false;
150 }
151 
153 {
154  if (!device) {
155  qWarning("QTiffHandler::canRead() called with no device");
156  return false;
157  }
158 
159  // current implementation uses TIFFClientOpen which needs to be
160  // able to seek, so sequential devices are not supported
161  int pos = device->pos();
162  if (pos != 0)
163  device->seek(0); // need the magic from the beginning
164  QByteArray header = device->peek(4);
165  if (pos != 0)
166  device->seek(pos); // put it back where we found it
167 
168  return header == QByteArray::fromRawData("\x49\x49\x2A\x00", 4)
169  || header == QByteArray::fromRawData("\x4D\x4D\x00\x2A", 4);
170 }
171 
173 {
174  if (!canRead())
175  return false;
176 
177  TIFF *const tiff = TIFFClientOpen("foo",
178  "r",
179  this,
185  qtiffMapProc,
187 
188  if (!tiff) {
189  return false;
190  }
191  uint32 width;
192  uint32 height;
193  uint16 photometric;
194  if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width)
195  || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height)
196  || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) {
197  TIFFClose(tiff);
198  return false;
199  }
200 
201  // BitsPerSample defaults to 1 according to the TIFF spec.
202  uint16 bitPerSample;
203  if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample))
204  bitPerSample = 1;
205  uint16 samplesPerPixel; // they may be e.g. grayscale with 2 samples per pixel
206  if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel))
207  samplesPerPixel = 1;
208 
209  bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE;
210  if (grayscale && bitPerSample == 1 && samplesPerPixel == 1) {
211  if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono)
212  *image = QImage(width, height, QImage::Format_Mono);
213  QVector<QRgb> colortable(2);
214  if (photometric == PHOTOMETRIC_MINISBLACK) {
215  colortable[0] = 0xff000000;
216  colortable[1] = 0xffffffff;
217  } else {
218  colortable[0] = 0xffffffff;
219  colortable[1] = 0xff000000;
220  }
221  image->setColorTable(colortable);
222 
223  if (!image->isNull()) {
224  for (uint32 y=0; y<height; ++y) {
225  if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
226  TIFFClose(tiff);
227  return false;
228  }
229  }
230  }
231  } else {
232  if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1) {
233  if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8)
234  *image = QImage(width, height, QImage::Format_Indexed8);
235  if (!image->isNull()) {
236  const uint16 tableSize = 256;
237  QVector<QRgb> qtColorTable(tableSize);
238  if (grayscale) {
239  for (int i = 0; i<tableSize; ++i) {
240  const int c = (photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i);
241  qtColorTable[i] = qRgb(c, c, c);
242  }
243  } else {
244  // create the color table
245  uint16 *redTable = 0;
246  uint16 *greenTable = 0;
247  uint16 *blueTable = 0;
248  if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
249  TIFFClose(tiff);
250  return false;
251  }
252  if (!redTable || !greenTable || !blueTable) {
253  TIFFClose(tiff);
254  return false;
255  }
256 
257  for (int i = 0; i<tableSize ;++i) {
258  const int red = redTable[i] / 257;
259  const int green = greenTable[i] / 257;
260  const int blue = blueTable[i] / 257;
261  qtColorTable[i] = qRgb(red, green, blue);
262  }
263  }
264 
265  image->setColorTable(qtColorTable);
266  for (uint32 y=0; y<height; ++y) {
267  if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
268  TIFFClose(tiff);
269  return false;
270  }
271  }
272 
273  // free redTable, greenTable and greenTable done by libtiff
274  }
275  } else {
276  if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32)
277  *image = QImage(width, height, QImage::Format_ARGB32);
278  if (!image->isNull()) {
279  const int stopOnError = 1;
280  if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, stopOnError)) {
281  for (uint32 y=0; y<height; ++y)
282  convert32BitOrder(image->scanLine(y), width);
283  } else {
284  TIFFClose(tiff);
285  return false;
286  }
287  }
288  }
289  }
290 
291  if (image->isNull()) {
292  TIFFClose(tiff);
293  return false;
294  }
295 
296  float resX = 0;
297  float resY = 0;
298  uint16 resUnit;
299  if (!TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit))
300  resUnit = RESUNIT_INCH;
301 
302  if (TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX)
303  && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) {
304  switch(resUnit) {
305  case RESUNIT_CENTIMETER:
306  image->setDotsPerMeterX(qRound(resX * 100));
307  image->setDotsPerMeterY(qRound(resY * 100));
308  break;
309  case RESUNIT_INCH:
310  image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
311  image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
312  break;
313  default:
314  // do nothing as defaults have already
315  // been set within the QImage class
316  break;
317  }
318  }
319 
320  // rotate the image if the orientation is defined in the file
321  uint16 orientationTag;
322  if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &orientationTag)) {
323  if (image->format() == QImage::Format_ARGB32) {
324  // TIFFReadRGBAImageOriented() flip the image but does not rotate them
325  switch (orientationTag) {
326  case 5:
328  break;
329  case 6:
331  break;
332  case 7:
334  break;
335  case 8:
337  break;
338  }
339  } else {
340  switch (orientationTag) {
341  case 1: // default orientation
342  break;
343  case 2: // mirror horizontal
344  *image = image->mirrored(true, false);
345  break;
346  case 3: // mirror both
347  *image = image->mirrored(true, true);
348  break;
349  case 4: // mirror vertical
350  *image = image->mirrored(false, true);
351  break;
352  case 5: // rotate right mirror horizontal
353  {
354  QMatrix transformation;
355  transformation.rotate(90);
356  *image = image->transformed(transformation);
357  *image = image->mirrored(true, false);
358  break;
359  }
360  case 6: // rotate right
361  {
362  QMatrix transformation;
363  transformation.rotate(90);
364  *image = image->transformed(transformation);
365  break;
366  }
367  case 7: // rotate right, mirror vertical
368  {
369  QMatrix transformation;
370  transformation.rotate(90);
371  *image = image->transformed(transformation);
372  *image = image->mirrored(false, true);
373  break;
374  }
375  case 8: // rotate left
376  {
377  QMatrix transformation;
378  transformation.rotate(270);
379  *image = image->transformed(transformation);
380  break;
381  }
382  }
383  }
384  }
385 
386 
387  TIFFClose(tiff);
388  return true;
389 }
390 
391 static bool checkGrayscale(const QVector<QRgb> &colorTable)
392 {
393  if (colorTable.size() != 256)
394  return false;
395 
396  const bool increasing = (colorTable.at(0) == 0xff000000);
397  for (int i = 0; i < 256; ++i) {
398  if ((increasing && colorTable.at(i) != qRgb(i, i, i))
399  || (!increasing && colorTable.at(i) != qRgb(255 - i, 255 - i, 255 - i)))
400  return false;
401  }
402  return true;
403 }
404 
405 bool QTiffHandler::write(const QImage &image)
406 {
407  if (!device()->isWritable())
408  return false;
409 
410  TIFF *const tiff = TIFFClientOpen("foo",
411  "w",
412  this,
418  qtiffMapProc,
420  if (!tiff)
421  return false;
422 
423  const int width = image.width();
424  const int height = image.height();
425 
426  if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
427  || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
428  || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
429  TIFFClose(tiff);
430  return false;
431  }
432 
433  // set the resolution
434  bool resolutionSet = false;
435  const int dotPerMeterX = image.dotsPerMeterX();
436  const int dotPerMeterY = image.dotsPerMeterY();
437  if ((dotPerMeterX % 100) == 0
438  && (dotPerMeterY % 100) == 0) {
439  resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
440  && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
441  && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
442  } else {
443  resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
444  && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast<float>(image.logicalDpiX()))
445  && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast<float>(image.logicalDpiY()));
446  }
447  if (!resolutionSet) {
448  TIFFClose(tiff);
449  return false;
450  }
451 
452  // configure image depth
453  const QImage::Format format = image.format();
454  if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) {
455  uint16 photometric = PHOTOMETRIC_MINISBLACK;
456  if (image.colorTable().at(0) == 0xffffffff)
457  photometric = PHOTOMETRIC_MINISWHITE;
458  if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
459  || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)
460  || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)) {
461  TIFFClose(tiff);
462  return false;
463  }
464 
465  // try to do the conversion in chunks no greater than 16 MB
466  int chunks = (width * height / (1024 * 1024 * 16)) + 1;
467  int chunkHeight = qMax(height / chunks, 1);
468 
469  int y = 0;
470  while (y < height) {
471  QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono);
472 
473  int chunkStart = y;
474  int chunkEnd = y + chunk.height();
475  while (y < chunkEnd) {
476  if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
477  TIFFClose(tiff);
478  return false;
479  }
480  ++y;
481  }
482  }
483  TIFFClose(tiff);
484  } else if (format == QImage::Format_Indexed8) {
485  const QVector<QRgb> colorTable = image.colorTable();
486  bool isGrayscale = checkGrayscale(colorTable);
487  if (isGrayscale) {
488  uint16 photometric = PHOTOMETRIC_MINISBLACK;
489  if (image.colorTable().at(0) == 0xffffffff)
490  photometric = PHOTOMETRIC_MINISWHITE;
491  if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
492  || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
493  || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
494  TIFFClose(tiff);
495  return false;
496  }
497  } else {
498  if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE)
499  || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
500  || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
501  TIFFClose(tiff);
502  return false;
503  }
505  // allocate the color tables
506  uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
507  uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
508  uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
509  if (!redTable || !greenTable || !blueTable) {
510  qFree(redTable);
511  qFree(greenTable);
512  qFree(blueTable);
513  TIFFClose(tiff);
514  return false;
515  }
516 
517  // set the color table
518  const int tableSize = colorTable.size();
519  Q_ASSERT(tableSize <= 256);
520  for (int i = 0; i<tableSize; ++i) {
521  const QRgb color = colorTable.at(i);
522  redTable[i] = qRed(color) * 257;
523  greenTable[i] = qGreen(color) * 257;
524  blueTable[i] = qBlue(color) * 257;
525  }
526 
527  const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable);
528 
529  qFree(redTable);
530  qFree(greenTable);
531  qFree(blueTable);
532 
533  if (!setColorTableSuccess) {
534  TIFFClose(tiff);
535  return false;
536  }
537  }
538 
540  // try to do the conversion in chunks no greater than 16 MB
541  int chunks = (width * height/ (1024 * 1024 * 16)) + 1;
542  int chunkHeight = qMax(height / chunks, 1);
543 
544  int y = 0;
545  while (y < height) {
546  QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y));
547 
548  int chunkStart = y;
549  int chunkEnd = y + chunk.height();
550  while (y < chunkEnd) {
551  if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
552  TIFFClose(tiff);
553  return false;
554  }
555  ++y;
556  }
557  }
558  TIFFClose(tiff);
559 
560  } else {
561  if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
562  || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
563  || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
564  || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
565  TIFFClose(tiff);
566  return false;
567  }
568  // try to do the ARGB32 conversion in chunks no greater than 16 MB
569  int chunks = (width * height * 4 / (1024 * 1024 * 16)) + 1;
570  int chunkHeight = qMax(height / chunks, 1);
571 
572  int y = 0;
573  while (y < height) {
574  QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_ARGB32);
575 
576  int chunkStart = y;
577  int chunkEnd = y + chunk.height();
578  while (y < chunkEnd) {
579  if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
580  convert32BitOrder(chunk.scanLine(y - chunkStart), width);
581  else
582  convert32BitOrderBigEndian(chunk.scanLine(y - chunkStart), width);
583 
584  if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
585  TIFFClose(tiff);
586  return false;
587  }
588  ++y;
589  }
590  }
591  TIFFClose(tiff);
592  }
593 
594  return true;
595 }
596 
598 {
599  return "tiff";
600 }
601 
603 {
604  if (option == Size && canRead()) {
605  QSize imageSize;
606  qint64 pos = device()->pos();
607  TIFF *tiff = TIFFClientOpen("foo",
608  "r",
609  const_cast<QTiffHandler*>(this),
615  qtiffMapProc,
617 
618  if (tiff) {
619  uint32 width = 0;
620  uint32 height = 0;
621  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
622  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
623  imageSize = QSize(width, height);
624  TIFFClose(tiff);
625  }
626  device()->seek(pos);
627  if (imageSize.isValid())
628  return imageSize;
629  } else if (option == CompressionRatio) {
630  return compression;
631  } else if (option == ImageFormat) {
632  return QImage::Format_ARGB32;
633  }
634  return QVariant();
635 }
636 
638 {
639  if (option == CompressionRatio && value.type() == QVariant::Int)
640  compression = value.toInt();
641 }
642 
644 {
645  return option == CompressionRatio
646  || option == Size
647  || option == ImageFormat;
648 }
649 
650 void QTiffHandler::convert32BitOrder(void *buffer, int width)
651 {
652  uint32 *target = reinterpret_cast<uint32 *>(buffer);
653  for (int32 x=0; x<width; ++x) {
654  uint32 p = target[x];
655  // convert between ARGB and ABGR
656  target[x] = (p & 0xff000000)
657  | ((p & 0x00ff0000) >> 16)
658  | (p & 0x0000ff00)
659  | ((p & 0x000000ff) << 16);
660  }
661 }
662 
663 void QTiffHandler::convert32BitOrderBigEndian(void *buffer, int width)
664 {
665  uint32 *target = reinterpret_cast<uint32 *>(buffer);
666  for (int32 x=0; x<width; ++x) {
667  uint32 p = target[x];
668  target[x] = (p & 0xff000000) >> 24
669  | (p & 0x00ff0000) << 8
670  | (p & 0x0000ff00) << 8
671  | (p & 0x000000ff) << 8;
672  }
673 }
674 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
Format
The following image formats are available in Qt.
Definition: qimage.h:91
QByteArray name() const
Use format() instead.
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
unsigned int QRgb
Definition: qrgb.h:53
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
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
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
Definition: qiodevice.cpp:544
QVariant option(ImageOption option) const
Returns the value assigned to option as a QVariant.
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
The QMatrix class specifies 2D transformations of a coordinate system.
Definition: qmatrix.h:61
int logicalDpiY() const
Definition: qpaintdevice.h:96
Q_CORE_EXPORT void qFree(void *ptr)
Definition: qmalloc.cpp:58
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
Q_CORE_EXPORT void * qMalloc(size_t size)
Definition: qmalloc.cpp:53
int dotsPerMeterY() const
Returns the number of pixels that fit vertically in a physical meter.
Definition: qimage.cpp:5628
tsize_t qtiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
static bool checkGrayscale(const QVector< QRgb > &colorTable)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
toff_t qtiffSeekProc(thandle_t fd, toff_t off, int whence)
static void grayscale(const QImage &image, QImage &dest, const QRect &rect=QRect())
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
void qtiffUnmapProc(thandle_t, tdata_t, toff_t)
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
int logicalDpiX() const
Definition: qpaintdevice.h:95
tsize_t qtiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QMatrix & rotate(qreal a)
Rotates the coordinate system the given degrees counterclockwise.
Definition: qmatrix.cpp:990
ImageOption
This enum describes the different options supported by QImageIOHandler.
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
qint64 peek(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, without side effects (i.
Definition: qiodevice.cpp:1563
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
bool canRead() const
Returns true if an image can be read from the device (i.
void setDotsPerMeterY(int)
Sets the number of pixels that fit vertically in a physical meter, to y.
Definition: qimage.cpp:5667
__int64 qint64
Definition: qglobal.h:942
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
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
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
Definition: qrgb.h:63
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
void convert32BitOrderBigEndian(void *buffer, int width)
toff_t qtiffSizeProc(thandle_t fd)
int qtiffMapProc(thandle_t, tdata_t *, toff_t *)
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
void setDotsPerMeterX(int)
Sets the number of pixels that fit horizontally in a physical meter, to x.
Definition: qimage.cpp:5645
The QImageIOHandler class defines the common image I/O interface for all image formats in Qt...
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
void convert32BitOrder(void *buffer, int width)
bool read(QImage *image)
Read an image from the device, and stores it in image.
bool supportsOption(ImageOption option) const
Returns true if the QImageIOHandler supports the option option; otherwise returns false...
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
int qtiffCloseProc(thandle_t)
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
Definition: qrgb.h:60
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
void rotate_right_mirror_horizontal(QImage *const image)
void setOption(ImageOption option, const QVariant &value)
Sets the option option with the value value.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
bool write(const QImage &image)
Writes the image image to the assigned device.
int dotsPerMeterX() const
Returns the number of pixels that fit horizontally in a physical meter.
Definition: qimage.cpp:5615
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
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
void rotate_right_mirror_vertical(QImage *const image)