306 if (!TIFFSetDirectory(tiff, currentDirectory)) {
313 if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width)
314 || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height)
315 || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) {
319 size = QSize(width, height);
321 uint16_t orientationTag;
322 if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &orientationTag))
323 transformation = exif2Qt(orientationTag);
326 uint16_t bitPerSample;
327 if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample))
329 uint16_t samplesPerPixel;
330 if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel))
332 uint16_t sampleFormat;
333 if (!TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat))
334 sampleFormat = SAMPLEFORMAT_VOID;
339 if (
grayscale && bitPerSample == 1 && samplesPerPixel == 1)
340 format = QImage::Format_Mono;
341 else if (
photometric == PHOTOMETRIC_MINISBLACK && bitPerSample == 8 && samplesPerPixel == 1)
342 format = QImage::Format_Grayscale8;
344 format = QImage::Format_Grayscale16;
345 else if ((
grayscale ||
photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1)
346 format = QImage::Format_Indexed8;
347 else if (samplesPerPixel < 4) {
348 bool regular = (samplesPerPixel != 2) && (
photometric == PHOTOMETRIC_RGB ||
photometric == PHOTOMETRIC_MINISBLACK);
349 if (bitPerSample == 16 && regular)
350 format = floatingPoint ? QImage::Format_RGBX16FPx4 : QImage::Format_RGBX64;
351 else if (bitPerSample == 32 && floatingPoint && regular)
352 format = QImage::Format_RGBX32FPx4;
354 format = QImage::Format_RGB32;
357 uint16_t *extrasamples;
362 bool premultiplied =
true;
363 bool gotField = TIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &count, &extrasamples);
364 if (!gotField || !count || extrasamples[0] == EXTRASAMPLE_UNSPECIFIED)
365 premultiplied =
false;
367 if (bitPerSample == 16 &&
photometric == PHOTOMETRIC_RGB) {
369 if (gotField && count && extrasamples[0] == EXTRASAMPLE_UNASSALPHA)
370 premultiplied =
false;
372 format = floatingPoint ? QImage::Format_RGBA16FPx4_Premultiplied : QImage::Format_RGBA64_Premultiplied;
374 format = floatingPoint ? QImage::Format_RGBA16FPx4 : QImage::Format_RGBA64;
376 if (gotField && count && extrasamples[0] == EXTRASAMPLE_UNASSALPHA)
377 premultiplied =
false;
379 format = QImage::Format_RGBA32FPx4_Premultiplied;
381 format = QImage::Format_RGBA32FPx4;
382 }
else if (samplesPerPixel == 4 && bitPerSample == 8 &&
photometric == PHOTOMETRIC_SEPARATED) {
384 const bool gotInkSetField = TIFFGetField(tiff, TIFFTAG_INKSET, &inkSet);
385 if (!gotInkSetField || inkSet == INKSET_CMYK) {
386 format = QImage::Format_CMYK8888;
393 format = QImage::Format_ARGB32_Premultiplied;
395 format = QImage::Format_ARGB32;
428 if (!d->readHeaders(device()))
431 QImage::Format format = d->format;
433 if (!QImageIOHandler::allocateImage(d->size, format, image)) {
438 TIFF *
const tiff = d->tiff;
439 if (TIFFIsTiled(tiff) && TIFFTileSize64(tiff) > uint64_t(image->sizeInBytes()))
441 const quint32 width = d->size.width();
442 const quint32 height = d->size.height();
445 if (format == QImage::Format_Mono || format == QImage::Format_Indexed8) {
446 if (format == QImage::Format_Mono) {
447 QList<QRgb> colortable(2);
448 if (d->photometric == PHOTOMETRIC_MINISBLACK) {
449 colortable[0] = 0xff000000;
450 colortable[1] = 0xffffffff;
452 colortable[0] = 0xffffffff;
453 colortable[1] = 0xff000000;
455 image->setColorTable(colortable);
456 }
else if (format == QImage::Format_Indexed8) {
457 const uint16_t tableSize = 256;
458 QList<QRgb> qtColorTable(tableSize);
460 for (
int i = 0; i<tableSize; ++i) {
461 const int c = (d->photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i);
462 qtColorTable[i] = qRgb(c, c, c);
466 uint16_t *redTable = 0;
467 uint16_t *greenTable = 0;
468 uint16_t *blueTable = 0;
469 if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
473 if (!redTable || !greenTable || !blueTable) {
478 for (
int i = 0; i<tableSize ;++i) {
480 const int red = redTable[i] >> 8;
481 const int green = greenTable[i] >> 8;
482 const int blue = blueTable[i] >> 8;
483 qtColorTable[i] = qRgb(red, green, blue);
486 image->setColorTable(qtColorTable);
490 bool format8bit = (format == QImage::Format_Mono || format == QImage::Format_Indexed8 || format == QImage::Format_Grayscale8);
491 bool format16bit = (format == QImage::Format_Grayscale16);
492 bool formatCmyk32bit = (format == QImage::Format_CMYK8888);
493 bool format64bit = (format == QImage::Format_RGBX64 || format == QImage::Format_RGBA64 || format == QImage::Format_RGBA64_Premultiplied);
494 bool format64fp = (format == QImage::Format_RGBX16FPx4 || format == QImage::Format_RGBA16FPx4 || format == QImage::Format_RGBA16FPx4_Premultiplied);
495 bool format128fp = (format == QImage::Format_RGBX32FPx4 || format == QImage::Format_RGBA32FPx4 || format == QImage::Format_RGBA32FPx4_Premultiplied);
498 if (format8bit || format16bit || formatCmyk32bit || format64bit || format64fp || format128fp) {
499 int bytesPerPixel = image->depth() / 8;
500 if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4)
501 bytesPerPixel = d->photometric == PHOTOMETRIC_RGB ? 6 : 2;
502 else if (format == QImage::Format_RGBX32FPx4)
503 bytesPerPixel = d->photometric == PHOTOMETRIC_RGB ? 12 : 4;
504 if (TIFFIsTiled(tiff)) {
505 quint32 tileWidth, tileLength;
506 TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth);
507 TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength);
508 if (!tileWidth || !tileLength || tileWidth % 16 || tileLength % 16) {
512 quint32 byteWidth = (format == QImage::Format_Mono) ? (width + 7)/8 : (width * bytesPerPixel);
513 quint32 byteTileWidth = (format == QImage::Format_Mono) ? tileWidth/8 : (tileWidth * bytesPerPixel);
514 tmsize_t byteTileSize = TIFFTileSize(tiff);
515 if (byteTileSize > image->sizeInBytes() || byteTileSize / tileLength < byteTileWidth) {
519 uchar *buf = (uchar *)_TIFFmalloc(byteTileSize);
524 for (quint32 y = 0; y < height; y += tileLength) {
525 for (quint32 x = 0; x < width; x += tileWidth) {
526 if (TIFFReadTile(tiff, buf, x, y, 0, 0) < 0) {
531 quint32 linesToCopy = qMin(tileLength, height - y);
532 quint32 byteOffset = (format == QImage::Format_Mono) ? x/8 : (x * bytesPerPixel);
533 quint32 widthToCopy = qMin(byteTileWidth, byteWidth - byteOffset);
534 for (quint32 i = 0; i < linesToCopy; i++) {
535 ::memcpy(image->scanLine(y + i) + byteOffset, buf + (i * byteTileWidth), widthToCopy);
541 if (image->bytesPerLine() < TIFFScanlineSize(tiff)) {
545 for (uint32_t y=0; y<height; ++y) {
546 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
552 if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4) {
553 if (d->photometric == PHOTOMETRIC_RGB)
554 rgb48fixup(image, d->floatingPoint);
557 }
else if (format == QImage::Format_RGBX32FPx4) {
558 if (d->photometric == PHOTOMETRIC_RGB)
564 const int stopOnError = 1;
565 if (TIFFReadRGBAImageOriented(tiff, width, height,
reinterpret_cast<uint32_t *>(image->bits()), qt2Exif(d->transformation), stopOnError)) {
566 for (uint32_t y=0; y<height; ++y)
567 convert32BitOrder(image->scanLine(y), width);
578 if (!TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit))
579 resUnit = RESUNIT_INCH;
581 if (TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX)
582 && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) {
585 case RESUNIT_CENTIMETER:
586 image->setDotsPerMeterX(qRound(resX * 100));
587 image->setDotsPerMeterY(qRound(resY * 100));
590 image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
591 image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
602 if (TIFFGetField(tiff, TIFFTAG_ICCPROFILE, &count, &profile)) {
603 QByteArray iccProfile(
reinterpret_cast<
const char *>(profile), count);
604 image->setColorSpace(QColorSpace::fromIccProfile(iccProfile));
664 TIFF *
const tiff = d->openInternal(
"wB", device());
668 const int width = image.width();
669 const int height = image.height();
670 const int compression = d->compression;
672 if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
673 || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
674 || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
680 bool resolutionSet =
false;
681 const int dotPerMeterX = image.dotsPerMeterX();
682 const int dotPerMeterY = image.dotsPerMeterY();
683 if ((dotPerMeterX % 100) == 0
684 && (dotPerMeterY % 100) == 0) {
685 resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
686 && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
687 && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
689 resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
690 && TIFFSetField(tiff, TIFFTAG_XRESOLUTION,
static_cast<
float>(image.logicalDpiX()))
691 && TIFFSetField(tiff, TIFFTAG_YRESOLUTION,
static_cast<
float>(image.logicalDpiY()));
693 if (!resolutionSet) {
698 bool orientationSet =
false;
699 orientationSet = TIFFSetField(tiff, TIFFTAG_ORIENTATION, qt2Exif(d->transformation));
700 if (!orientationSet) {
705 const QByteArray iccProfile = image.colorSpace().iccProfile();
706 if (!iccProfile.isEmpty()) {
707 if (!TIFFSetField(tiff, TIFFTAG_ICCPROFILE, iccProfile.size(),
reinterpret_cast<
const void *>(iccProfile.constData()))) {
713 const QImage::Format format = image.format();
714 if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) {
715 uint16_t photometric = PHOTOMETRIC_MINISBLACK;
716 if (image.colorTable().at(0) == 0xffffffff)
717 photometric = PHOTOMETRIC_MINISWHITE;
718 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
719 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
720 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)
721 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
727 const int chunks =
int(image.sizeInBytes() / (1024 * 1024 * 16)) + 1;
728 const int chunkHeight = qMax(height / chunks, 1);
732 QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono);
735 int chunkEnd = y + chunk.height();
736 while (y < chunkEnd) {
737 if (TIFFWriteScanline(tiff,
reinterpret_cast<uint32_t *>(chunk.scanLine(y - chunkStart)), y) != 1) {
745 }
else if (format == QImage::Format_Indexed8
746 || format == QImage::Format_Grayscale8
747 || format == QImage::Format_Grayscale16
748 || format == QImage::Format_Alpha8) {
749 QList<QRgb> colorTable = effectiveColorTable(image);
750 bool isGrayscale = checkGrayscale(colorTable);
752 uint16_t photometric = PHOTOMETRIC_MINISBLACK;
753 if (colorTable.at(0) == 0xffffffff)
754 photometric = PHOTOMETRIC_MINISWHITE;
755 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
756 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
757 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, image.depth())
758 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT)
759 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
764 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE)
765 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
766 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
767 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
773 const int tableSize = colorTable.size();
774 Q_ASSERT(tableSize <= 256);
775 QVarLengthArray<uint16_t> redTable(tableSize);
776 QVarLengthArray<uint16_t> greenTable(tableSize);
777 QVarLengthArray<uint16_t> blueTable(tableSize);
780 for (
int i = 0; i<tableSize; ++i) {
781 const QRgb color = colorTable.at(i);
782 redTable[i] = qRed(color) * 257;
783 greenTable[i] = qGreen(color) * 257;
784 blueTable[i] = qBlue(color) * 257;
787 const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable.data(), greenTable.data(), blueTable.data());
789 if (!setColorTableSuccess) {
796 for (
int y = 0; y < height; ++y) {
797 if (TIFFWriteScanline(tiff,
const_cast<uchar *>(image.scanLine(y)), y) != 1) {
803 }
else if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4) {
804 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
805 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
806 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3)
807 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16)
808 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT,
809 format == QImage::Format_RGBX64
811 : SAMPLEFORMAT_IEEEFP)
812 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
816 std::unique_ptr<quint16[]> rgb48line(
new quint16[width * 3]);
817 for (
int y = 0; y < height; ++y) {
818 const quint16 *srcLine =
reinterpret_cast<
const quint16 *>(image.constScanLine(y));
819 for (
int x = 0; x < width; ++x) {
820 rgb48line[x * 3 + 0] = srcLine[x * 4 + 0];
821 rgb48line[x * 3 + 1] = srcLine[x * 4 + 1];
822 rgb48line[x * 3 + 2] = srcLine[x * 4 + 2];
825 if (TIFFWriteScanline(tiff, (
void*)rgb48line.get(), y) != 1) {
831 }
else if (format == QImage::Format_RGBA64
832 || format == QImage::Format_RGBA64_Premultiplied) {
833 const bool premultiplied = image.format() != QImage::Format_RGBA64;
834 const uint16_t extrasamples = premultiplied ? EXTRASAMPLE_ASSOCALPHA : EXTRASAMPLE_UNASSALPHA;
835 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
836 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
837 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
838 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16)
839 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT)
840 || !TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &extrasamples)
841 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
845 for (
int y = 0; y < height; ++y) {
846 if (TIFFWriteScanline(tiff, (
void*)image.scanLine(y), y) != 1) {
852 }
else if (format == QImage::Format_RGBX32FPx4) {
853 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
854 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
855 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3)
856 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32)
857 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP)
858 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
862 std::unique_ptr<
float[]> line(
new float[width * 3]);
863 for (
int y = 0; y < height; ++y) {
864 const float *srcLine =
reinterpret_cast<
const float *>(image.constScanLine(y));
865 for (
int x = 0; x < width; ++x) {
866 line[x * 3 + 0] = srcLine[x * 4 + 0];
867 line[x * 3 + 1] = srcLine[x * 4 + 1];
868 line[x * 3 + 2] = srcLine[x * 4 + 2];
871 if (TIFFWriteScanline(tiff, (
void*)line.get(), y) != 1) {
877 }
else if (format == QImage::Format_RGBA16FPx4 || format == QImage::Format_RGBA32FPx4
878 || format == QImage::Format_RGBA16FPx4_Premultiplied
879 || format == QImage::Format_RGBA32FPx4_Premultiplied) {
880 const bool premultiplied = image.format() != QImage::Format_RGBA16FPx4 && image.format() != QImage::Format_RGBA32FPx4;
881 const uint16_t extrasamples = premultiplied ? EXTRASAMPLE_ASSOCALPHA : EXTRASAMPLE_UNASSALPHA;
882 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
883 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
884 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
885 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, image.depth() == 64 ? 16 : 32)
886 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP)
887 || !TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &extrasamples)
888 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
892 for (
int y = 0; y < height; ++y) {
893 if (TIFFWriteScanline(tiff, (
void*)image.scanLine(y), y) != 1) {
899 }
else if (format == QImage::Format_CMYK8888) {
900 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED)
901 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
902 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
903 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
904 || !TIFFSetField(tiff, TIFFTAG_INKSET, INKSET_CMYK)
905 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
910 for (
int y = 0; y < image.height(); ++y) {
911 if (TIFFWriteScanline(tiff, (
void*)image.scanLine(y), y) != 1) {
918 }
else if (!image.hasAlphaChannel()) {
919 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
920 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
921 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3)
922 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
923 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
928 const int chunks =
int(image.sizeInBytes() / (1024 * 1024 * 16)) + 1;
929 const int chunkHeight = qMax(height / chunks, 1);
933 const QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_RGB888);
936 int chunkEnd = y + chunk.height();
937 while (y < chunkEnd) {
938 if (TIFFWriteScanline(tiff, (
void*)chunk.scanLine(y - chunkStart), y) != 1) {
947 const bool premultiplied = image.format() != QImage::Format_ARGB32
948 && image.format() != QImage::Format_RGBA8888;
949 const uint16_t extrasamples = premultiplied ? EXTRASAMPLE_ASSOCALPHA : EXTRASAMPLE_UNASSALPHA;
950 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
951 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
952 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
953 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
954 || !TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &extrasamples)
955 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
960 const int chunks =
int(image.sizeInBytes() / (1024 * 1024 * 16)) + 1;
961 const int chunkHeight = qMax(height / chunks, 1);
963 const QImage::Format format = premultiplied ? QImage::Format_RGBA8888_Premultiplied
964 : QImage::Format_RGBA8888;
967 const QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(format);
970 int chunkEnd = y + chunk.height();
971 while (y < chunkEnd) {
972 if (TIFFWriteScanline(tiff, (
void*)chunk.scanLine(y - chunkStart), y) != 1) {