426 TIFF *
const tiff = d->
tiff;
427 if (TIFFIsTiled(tiff) && TIFFTileSize64(tiff) > uint64_t(
image->sizeInBytes()))
435 QList<QRgb> colortable(2);
437 colortable[0] = 0xff000000;
438 colortable[1] = 0xffffffff;
440 colortable[0] = 0xffffffff;
441 colortable[1] = 0xff000000;
443 image->setColorTable(colortable);
445 const uint16_t tableSize = 256;
446 QList<QRgb> qtColorTable(tableSize);
448 for (
int i = 0;
i<tableSize; ++
i) {
449 const int c = (d->
photometric == PHOTOMETRIC_MINISBLACK) ?
i : (255 -
i);
454 uint16_t *redTable = 0;
455 uint16_t *greenTable = 0;
456 uint16_t *blueTable = 0;
457 if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
461 if (!redTable || !greenTable || !blueTable) {
466 for (
int i = 0;
i<tableSize ;++
i) {
468 const int red = redTable[
i] >> 8;
469 const int green = greenTable[
i] >> 8;
470 const int blue = blueTable[
i] >> 8;
474 image->setColorTable(qtColorTable);
486 if (format8bit || format16bit || formatCmyk32bit || format64bit || format64fp || format128fp) {
487 int bytesPerPixel =
image->depth() / 8;
489 bytesPerPixel = d->
photometric == PHOTOMETRIC_RGB ? 6 : 2;
491 bytesPerPixel = d->
photometric == PHOTOMETRIC_RGB ? 12 : 4;
492 if (TIFFIsTiled(tiff)) {
494 TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth);
495 TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength);
496 if (!tileWidth || !tileLength || tileWidth % 16 || tileLength % 16) {
502 tmsize_t byteTileSize = TIFFTileSize(tiff);
503 if (byteTileSize >
image->sizeInBytes() || byteTileSize / tileLength < byteTileWidth) {
514 if (TIFFReadTile(tiff,
buf,
x,
y, 0, 0) < 0) {
521 quint32 widthToCopy =
qMin(byteTileWidth, byteWidth - byteOffset);
523 ::memcpy(
image->scanLine(
y +
i) + byteOffset,
buf + (
i * byteTileWidth), widthToCopy);
529 if (
image->bytesPerLine() < TIFFScanlineSize(tiff)) {
534 if (TIFFReadScanline(tiff,
image->scanLine(
y),
y, 0) < 0) {
552 const int stopOnError = 1;
566 if (!TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit))
567 resUnit = RESUNIT_INCH;
569 if (TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX)
570 && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) {
573 case RESUNIT_CENTIMETER:
578 image->setDotsPerMeterX(
qRound(resX * (100 / 2.54)));
579 image->setDotsPerMeterY(
qRound(resY * (100 / 2.54)));
590 if (TIFFGetField(tiff, TIFFTAG_ICCPROFILE, &
count, &profile)) {
649 if (!
device()->isWritable())
660 if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH,
width)
661 || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH,
height)
662 || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
668 bool resolutionSet =
false;
669 const int dotPerMeterX =
image.dotsPerMeterX();
670 const int dotPerMeterY =
image.dotsPerMeterY();
671 if ((dotPerMeterX % 100) == 0
672 && (dotPerMeterY % 100) == 0) {
673 resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
674 && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
675 && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
677 resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
678 && TIFFSetField(tiff, TIFFTAG_XRESOLUTION,
static_cast<float>(
image.logicalDpiX()))
679 && TIFFSetField(tiff, TIFFTAG_YRESOLUTION,
static_cast<float>(
image.logicalDpiY()));
681 if (!resolutionSet) {
686 bool orientationSet =
false;
688 if (!orientationSet) {
695 if (!TIFFSetField(tiff, TIFFTAG_ICCPROFILE, iccProfile.
size(),
reinterpret_cast<const void *
>(iccProfile.
constData()))) {
703 uint16_t photometric = PHOTOMETRIC_MINISBLACK;
704 if (
image.colorTable().at(0) == 0xffffffff)
705 photometric = PHOTOMETRIC_MINISWHITE;
706 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
707 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
708 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)
715 const int chunks = int(
image.sizeInBytes() / (1024 * 1024 * 16)) + 1;
716 const int chunkHeight =
qMax(
height / chunks, 1);
723 int chunkEnd =
y + chunk.
height();
724 while (
y < chunkEnd) {
725 if (TIFFWriteScanline(tiff,
reinterpret_cast<uint32_t *
>(chunk.
scanLine(
y - chunkStart)),
y) != 1) {
740 uint16_t photometric = PHOTOMETRIC_MINISBLACK;
741 if (colorTable.at(0) == 0xffffffff)
742 photometric = PHOTOMETRIC_MINISWHITE;
743 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
744 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
745 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE,
image.depth())
746 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT)
752 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE)
753 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
754 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
761 const int tableSize = colorTable.size();
763 QVarLengthArray<uint16_t> redTable(tableSize);
764 QVarLengthArray<uint16_t> greenTable(tableSize);
765 QVarLengthArray<uint16_t> blueTable(tableSize);
768 for (
int i = 0;
i<tableSize; ++
i) {
775 const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable.data(), greenTable.data(), blueTable.data());
777 if (!setColorTableSuccess) {
785 if (TIFFWriteScanline(tiff,
const_cast<uchar *
>(
image.scanLine(
y)),
y) != 1) {
792 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
793 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
794 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3)
795 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16)
796 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT,
799 : SAMPLEFORMAT_IEEEFP)
800 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
804 std::unique_ptr<quint16[]> rgb48line(
new quint16[
width * 3]);
808 rgb48line[
x * 3 + 0] = srcLine[
x * 4 + 0];
809 rgb48line[
x * 3 + 1] = srcLine[
x * 4 + 1];
810 rgb48line[
x * 3 + 2] = srcLine[
x * 4 + 2];
813 if (TIFFWriteScanline(tiff, (
void*)rgb48line.get(),
y) != 1) {
822 const uint16_t extrasamples = premultiplied ? EXTRASAMPLE_ASSOCALPHA : EXTRASAMPLE_UNASSALPHA;
823 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
824 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
825 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
826 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16)
827 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT)
828 || !TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &extrasamples)
829 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
834 if (TIFFWriteScanline(tiff, (
void*)
image.scanLine(
y),
y) != 1) {
841 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
842 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
843 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3)
844 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32)
845 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP)
846 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
850 std::unique_ptr<float[]>
line(
new float[
width * 3]);
852 const float *srcLine =
reinterpret_cast<const float *
>(
image.constScanLine(
y));
854 line[
x * 3 + 0] = srcLine[
x * 4 + 0];
855 line[
x * 3 + 1] = srcLine[
x * 4 + 1];
856 line[
x * 3 + 2] = srcLine[
x * 4 + 2];
859 if (TIFFWriteScanline(tiff, (
void*)
line.get(),
y) != 1) {
869 const uint16_t extrasamples = premultiplied ? EXTRASAMPLE_ASSOCALPHA : EXTRASAMPLE_UNASSALPHA;
870 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
871 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
872 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
873 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE,
image.depth() == 64 ? 16 : 32)
874 || !TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP)
875 || !TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &extrasamples)
876 || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiff, 0))) {
881 if (TIFFWriteScanline(tiff, (
void*)
image.scanLine(
y),
y) != 1) {
888 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED)
889 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
890 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
891 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
892 || !TIFFSetField(tiff, TIFFTAG_INKSET, INKSET_CMYK)
898 for (
int y = 0;
y <
image.height(); ++
y) {
899 if (TIFFWriteScanline(tiff, (
void*)
image.scanLine(
y),
y) != 1) {
906 }
else if (!
image.hasAlphaChannel()) {
907 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
908 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
909 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3)
910 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
916 const int chunks = int(
image.sizeInBytes() / (1024 * 1024 * 16)) + 1;
917 const int chunkHeight =
qMax(
height / chunks, 1);
924 int chunkEnd =
y + chunk.
height();
925 while (
y < chunkEnd) {
926 if (TIFFWriteScanline(tiff, (
void*)chunk.
scanLine(
y - chunkStart),
y) != 1) {
937 const uint16_t extrasamples = premultiplied ? EXTRASAMPLE_ASSOCALPHA : EXTRASAMPLE_UNASSALPHA;
938 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
939 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression ==
NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
940 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
941 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
942 || !TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &extrasamples)
948 const int chunks = int(
image.sizeInBytes() / (1024 * 1024 * 16)) + 1;
949 const int chunkHeight =
qMax(
height / chunks, 1);
958 int chunkEnd =
y + chunk.
height();
959 while (
y < chunkEnd) {
960 if (TIFFWriteScanline(tiff, (
void*)chunk.
scanLine(
y - chunkStart),
y) != 1) {