596 uint32_t &width = basicInfo.
width;
597 uint32_t &height = basicInfo.
height;
598 float &xres = basicInfo.
xres;
599 float &yres = basicInfo.
yres;
600 uint16_t &depth = basicInfo.
depth;
609 uint8_t &dstDepth = basicInfo.
dstDepth;
612 int32_t alphapos = -1;
613 bool hasPremultipliedAlpha =
false;
615 dbgFile <<
"There are" << nbchannels <<
" channels and" << extrasamplescount
616 <<
" extra channels";
619 for (uint16_t i = 0; i < extrasamplescount; i++) {
620 dbgFile <<
"sample" << i <<
"extra sample count"
621 << extrasamplescount <<
"color channel count"
623 << nbchannels <<
"sample info" << sampleinfo[i];
624 switch (sampleinfo[i]) {
625 case EXTRASAMPLE_ASSOCALPHA:
628 dbgPlugins <<
"Detected associated alpha @ " << i;
629 hasPremultipliedAlpha =
true;
630 alphapos =
static_cast<int32_t
>(extrasamplescount
633 case EXTRASAMPLE_UNASSALPHA:
638 case EXTRASAMPLE_UNSPECIFIED:
640 qWarning() <<
"Extra sample type not defined for this file, "
641 "assuming unassociated alpha.";
646 if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA) {
654 dbgFile <<
"Alpha pos:" << alphapos;
658 char *text =
nullptr;
659 if (TIFFGetField(image, TIFFTAG_ARTIST, &text) == 1) {
662 if (TIFFGetField(image, TIFFTAG_DOCUMENTNAME, &text) == 1) {
665 if (TIFFGetField(image, TIFFTAG_IMAGEDESCRIPTION, &text) == 1) {
669 uint16_t orientation = ORIENTATION_TOPLEFT;
670 if (TIFFGetField(image, TIFFTAG_ORIENTATION, &orientation) == 0) {
671 dbgFile <<
"Orientation not defined, assuming top left";
674 dbgFile <<
"Orientation:" << orientation;
677 uint32_t iptc_profile_size = 0;
678 uint32_t *iptc_profile_data =
nullptr;
679 if (TIFFGetField(image,
680 TIFFTAG_RICHTIFFIPTC,
684 dbgFile <<
"IPTC metadata not found!";
688 uint32_t xmp_size = 0;
689 uint8_t *xmp_data =
nullptr;
690 if (TIFFGetField(image, TIFFTAG_XMLPACKET, &xmp_size, &xmp_data) == 0) {
691 dbgFile <<
"XML metadata not found!";
695 uint16_t planarconfig = PLANARCONFIG_CONTIG;
696 if (TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarconfig) == 0) {
697 dbgFile <<
"Planar configuration is not defined";
703 static_cast<qint32
>(width),
704 static_cast<qint32
>(height),
720 qint32 newwidth = (
m_image->
width() <
static_cast<qint32
>(width))
721 ?
static_cast<qint32
>(width)
723 qint32 newheight = (
m_image->
height() <
static_cast<qint32
>(height))
724 ?
static_cast<qint32
>(height)
731 std::unique_ptr<std::remove_pointer_t<tdata_t>,
decltype(&_TIFFfree)> buf(
737 for (uint8_t *
p : *buf)
746 uint16_t nbcolorsamples = nbchannels - extrasamplescount;
747 const auto poses = [&]() -> std::array<quint8, 5> {
748 switch (color_type) {
749 case PHOTOMETRIC_MINISWHITE:
750 case PHOTOMETRIC_MINISBLACK:
752 case PHOTOMETRIC_CIELAB:
753 case PHOTOMETRIC_ICCLAB:
755 case PHOTOMETRIC_RGB:
756 if (sampletype == SAMPLEFORMAT_IEEEFP) {
761 case PHOTOMETRIC_SEPARATED:
762 return {0, 1, 2, 3, 4};
769 switch (color_type) {
770 case PHOTOMETRIC_MINISWHITE:
771 return makePostProcessor<KisTIFFPostProcessorInvert>(
774 case PHOTOMETRIC_MINISBLACK:
775 return makePostProcessor<KisTIFFPostProcessorDummy>(
778 case PHOTOMETRIC_CIELAB:
779 return makePostProcessor<KisTIFFPostProcessorCIELABtoICCLAB>(
782 case PHOTOMETRIC_ICCLAB:
783 case PHOTOMETRIC_RGB:
784 case PHOTOMETRIC_SEPARATED:
785 return makePostProcessor<KisTIFFPostProcessorDummy>(
795 uint16_t vsubsampling = 1;
796 uint16_t hsubsampling = 1;
797 if (color_type == PHOTOMETRIC_PALETTE) {
800 uint16_t *green =
nullptr;
801 uint16_t *blue =
nullptr;
802 if ((TIFFGetField(image, TIFFTAG_COLORMAP, &red, &green, &blue)) == 0) {
803 dbgFile <<
"Indexed image does not define a palette";
818 hasPremultipliedAlpha,
821 }
else if (color_type == PHOTOMETRIC_YCBCR) {
822 TIFFGetFieldDefaulted(image,
823 TIFFTAG_YCBCRSUBSAMPLING,
826 lineSizeCoeffs[1] = hsubsampling;
827 lineSizeCoeffs[2] = hsubsampling;
828 dbgFile <<
"Subsampling" << 4 << hsubsampling << vsubsampling;
832 static_cast<quint32
>(layer->
image()->
width()),
840 hasPremultipliedAlpha,
845 }
else if (dstDepth == 16) {
846 if (sampletype == SAMPLEFORMAT_IEEEFP) {
850 static_cast<quint32
>(layer->
image()->
width()),
858 hasPremultipliedAlpha,
868 static_cast<quint32
>(layer->
image()->
width()),
876 hasPremultipliedAlpha,
882 }
else if (dstDepth == 32) {
883 if (sampletype == SAMPLEFORMAT_IEEEFP) {
886 static_cast<quint32
>(layer->
image()->
width()),
894 hasPremultipliedAlpha,
903 static_cast<quint32
>(layer->
image()->
width()),
911 hasPremultipliedAlpha,
918 }
else if (dstDepth == 8) {
927 hasPremultipliedAlpha,
931 }
else if (dstDepth == 16) {
932 if (sampletype == SAMPLEFORMAT_IEEEFP) {
942 hasPremultipliedAlpha,
956 hasPremultipliedAlpha,
961 }
else if (dstDepth == 32) {
962 if (sampletype == SAMPLEFORMAT_IEEEFP) {
971 hasPremultipliedAlpha,
984 hasPremultipliedAlpha,
987 std::numeric_limits<uint32_t>::max());
992 dbgFile <<
"Image has an invalid/unsupported color type: "
997 uint32_t compression = COMPRESSION_NONE;
998 TIFFGetFieldDefaulted(image, TIFFTAG_COMPRESSION, &compression, COMPRESSION_NONE);
1000#ifdef HAVE_JPEG_TURBO
1001 uint32_t hasSplitTables = 0;
1002 uint8_t *tables =
nullptr;
1006 auto handle = [&]() -> std::unique_ptr<
void,
decltype(&tjDestroy)> {
1007 if (planarconfig == PLANARCONFIG_CONTIG
1008 && color_type == PHOTOMETRIC_YCBCR
1009 && compression == COMPRESSION_JPEG) {
1010 return {tjInitDecompress(), &tjDestroy};
1012 return {
nullptr, &tjDestroy};
1016 if (color_type == PHOTOMETRIC_YCBCR && compression == COMPRESSION_JPEG
1017 && hsubsampling != 1 && vsubsampling != 1) {
1018 dbgFile <<
"Setting up libjpeg-turbo for handling subsampled JPEG...";
1019 if (!TIFFGetFieldDefaulted(image,
1020 TIFFTAG_JPEGTABLESMODE,
1022 errFile <<
"Error when detecting the JPEG coefficient "
1026 if (hasSplitTables) {
1027 if (!TIFFGetField(image, TIFFTAG_JPEGTABLES, &sz, &tables)) {
1028 errFile <<
"Unable to retrieve the JPEG abbreviated datastream";
1038 && tjDecompressHeader(handle.get(), tables, sz, &width, &height)
1040 errFile << tjGetErrorStr2(handle.get());
1042 i18nc(
"TIFF errors",
1043 "This TIFF file is compressed with JPEG, but "
1044 "libjpeg-turbo could not load its coefficient "
1045 "quantization and/or Huffman coding tables. "
1046 "Please upgrade your version of libjpeg-turbo "
1054 if (TIFFIsTiled(image)) {
1056 uint32_t tileWidth = 0;
1057 uint32_t tileHeight = 0;
1060 TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
1061 TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
1062 tmsize_t tileSize = TIFFTileSize(image);
1064 if (planarconfig == PLANARCONFIG_CONTIG
1065 && !(color_type == PHOTOMETRIC_YCBCR
1066 && compression == COMPRESSION_JPEG && hsubsampling != 1
1067 && vsubsampling != 1)) {
1068 buf.reset(_TIFFmalloc(tileSize));
1072 static_cast<uint8_t *
>(buf.get()),
1074 tileSize / tileHeight);
1075 }
else if (depth >= 16 && depth < 32) {
1078 static_cast<uint8_t *
>(buf.get()),
1080 tileSize / tileHeight);
1084 static_cast<uint8_t *
>(buf.get()),
1086 tileSize / tileHeight);
1088 }
else if (planarconfig == PLANARCONFIG_CONTIG
1089 && color_type == PHOTOMETRIC_YCBCR
1090 && compression == COMPRESSION_JPEG) {
1091#ifdef HAVE_JPEG_TURBO
1092 jpegBuf.resize(tileSize);
1093 ps_buf->resize(nbchannels);
1094 TIFFReadRawTile(image, 0, jpegBuf.data(), tileSize);
1096 int width = tileWidth;
1097 int height = tileHeight;
1098 int jpegSubsamp = TJ_444;
1099 int jpegColorspace = TJCS_YCbCr;
1101 if (tjDecompressHeader3(handle.get(),
1109 errFile << tjGetErrorStr2(handle.get());
1114 for (uint32_t i = 0; i < nbchannels; i++) {
1115 const unsigned long uncompressedTileSize =
1116 tjPlaneSizeYUV(i, width, 0, height, jpegColorspace);
1118 uncompressedTileSize != (
unsigned long)-1,
1120 dbgFile << QString(
"Uncompressed tile size (plane %1): %2")
1122 .arg(uncompressedTileSize)
1125 tsize_t scanLineSize = uncompressedTileSize / tileHeight;
1126 dbgFile << QString(
"scan line size (plane %1): %2")
1132 static_cast<uint8_t *
>(_TIFFmalloc(uncompressedTileSize));
1133 lineSizes[i] = scanLineSize;
1146 "Subsampled YCbCr TIFF files compressed with JPEG cannot "
1151 ps_buf->resize(nbchannels);
1152 tsize_t scanLineSize = tileSize / tileHeight;
1153 dbgFile <<
" scanLineSize for each plan =" << scanLineSize;
1155 for (uint32_t i = 0; i < nbchannels; i++) {
1156 (*ps_buf)[i] =
static_cast<uint8_t *
>(_TIFFmalloc(tileSize));
1157 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
1165 dbgFile <<
"Scanline size =" << TIFFRasterScanlineSize(image)
1166 <<
" / tile size =" << TIFFTileSize(image)
1167 <<
" / tile width =" << tileWidth
1168 <<
" tileSize/tileHeight =" << tileSize / tileHeight;
1170 dbgFile <<
" NbOfTiles =" << TIFFNumberOfTiles(image)
1171 <<
" tileWidth =" << tileWidth <<
" tileSize =" << tileSize;
1173 for (y = 0; y < height; y += tileHeight) {
1174 for (x = 0; x < width; x += tileWidth) {
1175 dbgFile <<
"Reading tile x =" << x <<
" y =" << y;
1176#ifdef HAVE_JPEG_TURBO
1177 if (planarconfig == PLANARCONFIG_CONTIG
1178 && !(color_type == PHOTOMETRIC_YCBCR
1179 && compression == COMPRESSION_JPEG && hsubsampling != 1
1180 && vsubsampling != 1)) {
1182 if (planarconfig == PLANARCONFIG_CONTIG) {
1184 TIFFReadTile(image, buf.get(), x, y, 0, (tsample_t)-1);
1185#ifdef HAVE_JPEG_TURBO
1186 }
else if (planarconfig == PLANARCONFIG_CONTIG
1187 && (color_type == PHOTOMETRIC_YCBCR
1188 && compression == COMPRESSION_JPEG)) {
1190 TIFFComputeTile(image, x, y, 0, (tsample_t)-1);
1191 TIFFReadRawTile(image, tile, jpegBuf.data(), tileSize);
1193 int width = tileWidth;
1194 int height = tileHeight;
1195 int jpegSubsamp = TJ_444;
1196 int jpegColorspace = TJCS_YCbCr;
1198 if (tjDecompressHeader3(handle.get(),
1206 errFile << tjGetErrorStr2(handle.get());
1210 if (tjDecompressToYUVPlanes(handle.get(),
1219 errFile << tjGetErrorStr2(handle.get());
1224 for (uint16_t i = 0; i < nbchannels; i++) {
1225 TIFFReadTile(image, (*ps_buf)[i], x, y, 0, i);
1228 uint32_t realTileWidth =
1229 (x + tileWidth) < width ? tileWidth : width - x;
1230 for (uint32_t yintile = 0;
1231 yintile < tileHeight && y + yintile < height;) {
1232 uint32_t linesread =
1233 tiffReader->copyDataToChannels(x,
1237 yintile += linesread;
1238 tiffstream->moveToLine(yintile);
1240 tiffstream->restart();
1245 tsize_t stripsize = TIFFStripSize(image);
1246 uint32_t rowsPerStrip = 0;
1247 TIFFGetFieldDefaulted(image, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip);
1248 dbgFile << rowsPerStrip <<
"" << height;
1253 if (planarconfig == PLANARCONFIG_CONTIG
1254 && !(color_type == PHOTOMETRIC_YCBCR
1255 && compression == COMPRESSION_JPEG && hsubsampling != 1
1256 && vsubsampling != 1)) {
1257 buf.reset(_TIFFmalloc(stripsize));
1261 static_cast<uint8_t *
>(buf.get()),
1263 stripsize / rowsPerStrip);
1264 }
else if (depth < 32) {
1267 static_cast<uint8_t *
>(buf.get()),
1269 stripsize / rowsPerStrip);
1273 static_cast<uint8_t *
>(buf.get()),
1275 stripsize / rowsPerStrip);
1277 }
else if (planarconfig == PLANARCONFIG_CONTIG
1278 && color_type == PHOTOMETRIC_YCBCR
1279 && compression == COMPRESSION_JPEG) {
1280#ifdef HAVE_JPEG_TURBO
1281 jpegBuf.resize(stripsize);
1282 ps_buf->resize(nbchannels);
1283 TIFFReadRawStrip(image, 0, jpegBuf.data(), stripsize);
1285 int width = basicInfo.
width;
1286 int height = rowsPerStrip;
1287 int jpegSubsamp = TJ_444;
1288 int jpegColorspace = TJCS_YCbCr;
1290 if (tjDecompressHeader3(handle.get(),
1298 errFile << tjGetErrorStr2(handle.get());
1303 for (uint32_t i = 0; i < nbchannels; i++) {
1304 const unsigned long uncompressedStripsize =
1305 tjPlaneSizeYUV(i, width, 0, height, jpegColorspace);
1307 uncompressedStripsize != (
unsigned long)-1,
1309 dbgFile << QString(
"Uncompressed strip size (plane %1): %2")
1311 .arg(uncompressedStripsize);
1312 tsize_t scanLineSize = uncompressedStripsize / rowsPerStrip;
1313 dbgFile << QString(
"scan line size (plane %1): %2")
1316 (*ps_buf)[i] =
static_cast<uint8_t*
>(_TIFFmalloc(uncompressedStripsize));
1317 lineSizes[i] = scanLineSize;
1329 "Subsampled YCbCr TIFF files compressed with JPEG cannot "
1334 ps_buf->resize(nbchannels);
1335 tsize_t scanLineSize = stripsize / rowsPerStrip;
1336 dbgFile <<
" scanLineSize for each plan =" << scanLineSize;
1338 for (uint32_t i = 0; i < nbchannels; i++) {
1339 (*ps_buf)[i] =
static_cast<uint8_t*
>(_TIFFmalloc(stripsize));
1340 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
1349 dbgFile <<
"Scanline size =" << TIFFRasterScanlineSize(image)
1350 <<
" / strip size =" << TIFFStripSize(image)
1351 <<
" / rowsPerStrip =" << rowsPerStrip
1352 <<
" stripsize/rowsPerStrip =" << stripsize / rowsPerStrip;
1354 dbgFile <<
" NbOfStrips =" << TIFFNumberOfStrips(image)
1355 <<
" rowsPerStrip =" << rowsPerStrip
1356 <<
" stripsize =" << stripsize;
1358 for (uint32_t strip = 0; y < height; strip++) {
1359#ifdef HAVE_JPEG_TURBO
1360 if (planarconfig == PLANARCONFIG_CONTIG
1361 && !(color_type == PHOTOMETRIC_YCBCR
1362 && compression == COMPRESSION_JPEG && hsubsampling != 1
1363 && vsubsampling != 1)) {
1365 if (planarconfig == PLANARCONFIG_CONTIG) {
1367 TIFFReadEncodedStrip(image,
1368 TIFFComputeStrip(image, y, 0),
1371#ifdef HAVE_JPEG_TURBO
1372 }
else if (planarconfig == PLANARCONFIG_CONTIG
1373 && (color_type == PHOTOMETRIC_YCBCR
1374 && compression == COMPRESSION_JPEG)) {
1375 TIFFReadRawStrip(image, strip, jpegBuf.data(), stripsize);
1377 int width = basicInfo.
width;
1378 int height = rowsPerStrip;
1379 int jpegSubsamp = TJ_444;
1380 int jpegColorspace = TJCS_YCbCr;
1382 if (tjDecompressHeader3(handle.get(),
1390 errFile << tjGetErrorStr2(handle.get());
1394 if (tjDecompressToYUVPlanes(
1404 errFile << tjGetErrorStr2(handle.get());
1409 for (uint16_t i = 0; i < nbchannels; i++) {
1410 TIFFReadEncodedStrip(image,
1411 TIFFComputeStrip(image, y, i),
1416 for (uint32_t yinstrip = 0;
1417 yinstrip < rowsPerStrip && y < height;) {
1418 uint32_t linesread =
1419 tiffReader->copyDataToChannels(0, y, width, tiffstream);
1421 yinstrip += linesread;
1422 tiffstream->moveToLine(yinstrip);
1424 tiffstream->restart();
1427 tiffReader->finalize();
1439 switch (orientation) {
1440 case ORIENTATION_TOPRIGHT:
1443 case ORIENTATION_BOTRIGHT:
1446 case ORIENTATION_BOTLEFT:
1449 case ORIENTATION_LEFTTOP:
1453 case ORIENTATION_RIGHTTOP:
1456 case ORIENTATION_RIGHTBOT:
1460 case ORIENTATION_LEFTBOT:
1468 if (iptc_profile_size > 0 && iptc_profile_data !=
nullptr) {
1469 dbgFile <<
"Loading IPTC profile. Size: "
1470 <<
sizeof(uint32_t) * iptc_profile_size;
1473 if (TIFFIsByteSwapped(image) != 0) {
1474 TIFFSwabArrayOfLong(iptc_profile_data,
1475 iptc_profile_size /
sizeof(uint32_t));
1482 QByteArray ba(
reinterpret_cast<const char *
>(iptc_profile_data),
1483 static_cast<int>(iptc_profile_size));
1489 if (xmp_size > 0 && xmp_data !=
nullptr) {
1490 dbgFile <<
"Loading XMP data. Size: " << xmp_size;
1496 QByteArray ba(
reinterpret_cast<char *
>(xmp_data),
1497 static_cast<int>(xmp_size));