Qt 4.8
Public Types | Public Functions | Static Public Functions | Private Functions | Properties | List of all members
QTiffHandler Class Reference

#include <qtiffhandler_p.h>

Inheritance diagram for QTiffHandler:
QImageIOHandler

Public Types

enum  Compression { NoCompression = 0, LzwCompression = 1 }
 
- Public Types inherited from QImageIOHandler
enum  ImageOption {
  Size, ClipRect, Description, ScaledClipRect,
  ScaledSize, CompressionRatio, Gamma, Quality,
  Name, SubType, IncrementalReading, Endianness,
  Animation, BackgroundColor, ImageFormat
}
 This enum describes the different options supported by QImageIOHandler. More...
 

Public Functions

bool canRead () const
 Returns true if an image can be read from the device (i. More...
 
QByteArray name () const
 Use format() instead. More...
 
QVariant option (ImageOption option) const
 Returns the value assigned to option as a QVariant. More...
 
 QTiffHandler ()
 
bool read (QImage *image)
 Read an image from the device, and stores it in image. More...
 
void setOption (ImageOption option, const QVariant &value)
 Sets the option option with the value value. More...
 
bool supportsOption (ImageOption option) const
 Returns true if the QImageIOHandler supports the option option; otherwise returns false. More...
 
bool write (const QImage &image)
 Writes the image image to the assigned device. More...
 
- Public Functions inherited from QImageIOHandler
virtual int currentImageNumber () const
 For image formats that support animation, this function returns the sequence number of the current image in the animation. More...
 
virtual QRect currentImageRect () const
 Returns the rect of the current image. More...
 
QIODevicedevice () const
 Returns the device currently assigned to the QImageIOHandler. More...
 
QByteArray format () const
 Returns the format that is currently assigned to QImageIOHandler. More...
 
virtual int imageCount () const
 For image formats that support animation, this function returns the number of images in the animation. More...
 
virtual bool jumpToImage (int imageNumber)
 For image formats that support animation, this function jumps to the image whose sequence number is imageNumber. More...
 
virtual bool jumpToNextImage ()
 For image formats that support animation, this function jumps to the next image. More...
 
virtual int loopCount () const
 For image formats that support animation, this function returns the number of times the animation should loop. More...
 
virtual int nextImageDelay () const
 For image formats that support animation, this function returns the number of milliseconds to wait until reading the next image. More...
 
 QImageIOHandler ()
 Constructs a QImageIOHandler object. More...
 
void setDevice (QIODevice *device)
 Sets the device of the QImageIOHandler to device. More...
 
void setFormat (const QByteArray &format)
 Sets the format of the QImageIOHandler to format. More...
 
void setFormat (const QByteArray &format) const
 Sets the format of the QImageIOHandler to format. More...
 
virtual ~QImageIOHandler ()
 Destructs the QImageIOHandler object. More...
 

Static Public Functions

static bool canRead (QIODevice *device)
 

Private Functions

void convert32BitOrder (void *buffer, int width)
 
void convert32BitOrderBigEndian (void *buffer, int width)
 

Properties

int compression
 

Additional Inherited Members

- Protected Functions inherited from QImageIOHandler
 QImageIOHandler (QImageIOHandlerPrivate &dd)
 Constructs a QImageIOHandler object, using the private member dd. More...
 
- Protected Variables inherited from QImageIOHandler
QScopedPointer< QImageIOHandlerPrivated_ptr
 

Detailed Description

Definition at line 49 of file qtiffhandler_p.h.

Enumerations

◆ Compression

Enumerator
NoCompression 
LzwCompression 

Definition at line 66 of file qtiffhandler_p.h.

Constructors and Destructors

◆ QTiffHandler()

QTiffHandler::QTiffHandler ( )

Definition at line 138 of file qtiffhandler.cpp.

138  : QImageIOHandler()
139 {
141 }
QImageIOHandler()
Constructs a QImageIOHandler object.

Functions

◆ canRead() [1/2]

bool QTiffHandler::canRead ( ) const
virtual

Returns true if an image can be read from the device (i.

e., the image format is supported, the device can be read from and the initial header information suggests that the image can be read); otherwise returns false.

When reimplementing canRead(), make sure that the I/O device (device()) is left in its original state (e.g., by using peek() rather than read()).

See also
read(), QIODevice::peek()

Implements QImageIOHandler.

Definition at line 143 of file qtiffhandler.cpp.

Referenced by QTiffPlugin::capabilities(), createReadHandlerHelper(), option(), and read().

144 {
145  if (canRead(device())) {
146  setFormat("tiff");
147  return true;
148  }
149  return false;
150 }
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
bool canRead() const
Returns true if an image can be read from the device (i.
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.

◆ canRead() [2/2]

bool QTiffHandler::canRead ( QIODevice device)
static

Definition at line 152 of file qtiffhandler.cpp.

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 }
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
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 *,...)
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

◆ convert32BitOrder()

void QTiffHandler::convert32BitOrder ( void *  buffer,
int  width 
)
private

Definition at line 650 of file qtiffhandler.cpp.

Referenced by read(), and write().

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 }

◆ convert32BitOrderBigEndian()

void QTiffHandler::convert32BitOrderBigEndian ( void *  buffer,
int  width 
)
private

Definition at line 663 of file qtiffhandler.cpp.

Referenced by write().

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 }

◆ name()

QByteArray QTiffHandler::name ( ) const
virtual

Use format() instead.

Reimplemented from QImageIOHandler.

Definition at line 597 of file qtiffhandler.cpp.

598 {
599  return "tiff";
600 }

◆ option()

QVariant QTiffHandler::option ( ImageOption  option) const
virtual

Returns the value assigned to option as a QVariant.

The type of the value depends on the option. For example, option(Size) returns a QSize variant.

See also
setOption(), supportsOption()

Reimplemented from QImageIOHandler.

Definition at line 602 of file qtiffhandler.cpp.

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 }
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QVariant option(ImageOption option) const
Returns the value assigned to option as a QVariant.
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
tsize_t qtiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
toff_t qtiffSeekProc(thandle_t fd, toff_t off, int whence)
void qtiffUnmapProc(thandle_t, tdata_t, toff_t)
tsize_t qtiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
bool canRead() const
Returns true if an image can be read from the device (i.
__int64 qint64
Definition: qglobal.h:942
toff_t qtiffSizeProc(thandle_t fd)
int qtiffMapProc(thandle_t, tdata_t *, toff_t *)
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.
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
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

◆ read()

bool QTiffHandler::read ( QImage image)
virtual

Read an image from the device, and stores it in image.

Returns true if the image is successfully read; otherwise returns false.

For image formats that support incremental loading, and for animation formats, the image handler can assume that image points to the previous frame.

See also
canRead()

Implements QImageIOHandler.

Definition at line 172 of file qtiffhandler.cpp.

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 }
unsigned char c[8]
Definition: qnumeric_p.h:62
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
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
tsize_t qtiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
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
void qtiffUnmapProc(thandle_t, tdata_t, toff_t)
tsize_t qtiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
QMatrix & rotate(qreal a)
Rotates the coordinate system the given degrees counterclockwise.
Definition: qmatrix.cpp:990
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
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
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
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
void setDotsPerMeterX(int)
Sets the number of pixels that fit horizontally in a physical meter, to x.
Definition: qimage.cpp:5645
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
void convert32BitOrder(void *buffer, int width)
int qtiffCloseProc(thandle_t)
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
void rotate_right_mirror_horizontal(QImage *const image)
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)

◆ setOption()

void QTiffHandler::setOption ( ImageOption  option,
const QVariant value 
)
virtual

Sets the option option with the value value.

See also
option(), ImageOption

Reimplemented from QImageIOHandler.

Definition at line 637 of file qtiffhandler.cpp.

638 {
639  if (option == CompressionRatio && value.type() == QVariant::Int)
640  compression = value.toInt();
641 }
QVariant option(ImageOption option) const
Returns the value assigned to option as a QVariant.
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
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901

◆ supportsOption()

bool QTiffHandler::supportsOption ( ImageOption  option) const
virtual

Returns true if the QImageIOHandler supports the option option; otherwise returns false.

For example, if the QImageIOHandler supports the Size option, supportsOption(Size) must return true.

See also
setOption(), option()

Reimplemented from QImageIOHandler.

Definition at line 643 of file qtiffhandler.cpp.

644 {
645  return option == CompressionRatio
646  || option == Size
647  || option == ImageFormat;
648 }
QVariant option(ImageOption option) const
Returns the value assigned to option as a QVariant.

◆ write()

bool QTiffHandler::write ( const QImage image)
virtual

Writes the image image to the assigned device.

Returns true on success; otherwise returns false.

The default implementation does nothing, and simply returns false.

Reimplemented from QImageIOHandler.

Definition at line 405 of file qtiffhandler.cpp.

Referenced by qtiffWriteProc().

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 }
Format
The following image formats are available in Qt.
Definition: qimage.h:91
unsigned int QRgb
Definition: qrgb.h:53
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
int logicalDpiY() const
Definition: qpaintdevice.h:96
Q_CORE_EXPORT void qFree(void *ptr)
Definition: qmalloc.cpp:58
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)
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 logicalDpiX() const
Definition: qpaintdevice.h:95
tsize_t qtiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
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
void convert32BitOrderBigEndian(void *buffer, int width)
toff_t qtiffSizeProc(thandle_t fd)
int qtiffMapProc(thandle_t, tdata_t *, toff_t *)
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 convert32BitOrder(void *buffer, int width)
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
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
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
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886

Properties

◆ compression

int QTiffHandler::compression
private

Definition at line 73 of file qtiffhandler_p.h.

Referenced by option(), QTiffHandler(), setOption(), and write().


The documentation for this class was generated from the following files: