libtiff: Merge branch 'tiffinfo_parse_SubIFDs' into 'master'

From fa99e8c88db7a5d462905639c128ca783a5174b9 Mon Sep 17 00:00:00 2001
From: Su Laus <[EMAIL REDACTED]>
Date: Sat, 8 Oct 2022 14:52:24 +0000
Subject: [PATCH] tiffinfo: Updated to parse through SubIFDs and show their
 tags.

---
 test/CMakeLists.txt                    |   1 +
 test/Makefile.am                       |   1 +
 test/common.sh                         |   1 +
 test/images/tiff_with_subifd_chain.tif | Bin 0 -> 19484 bytes
 test/tiffinfo.sh                       |   1 +
 tools/tiffinfo.c                       |  35 ++++++++++++++++++++++++-
 6 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 test/images/tiff_with_subifd_chain.tif

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a7ad8ec1..3554b214 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -372,6 +372,7 @@ add_reader_test(tiffdump "" "images/miniswhite-1c-1b.tiff")
 # tiffinfo
 add_reader_test(tiffinfo "-c -D -d -j -s" "images/custom_dir_EXIF_GPS.tiff")
 add_reader_test(tiffinfo "-c -D -d -j -s" "images/minisblack-1c-16b.tiff")
+add_reader_test(tiffinfo " " "images/tiff_with_subifd_chain.tif")
 
 # tiffcp split/join
 foreach(image ${UNCOMPRESSEDIMAGES})
diff --git a/test/Makefile.am b/test/Makefile.am
index 2da13dbf..09a83065 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -209,6 +209,7 @@ IMAGES_EXTRA_DIST = \
 	images/miniswhite-1c-1b.g3 \
 	images/test_float64_predictor2_le_lzw.tif \
 	images/test_float64_predictor2_be_lzw.tif \
+	images/tiff_with_subifd_chain.tif \
 	$(PNMIMAGES) \
 	$(TIFFIMAGES)
 
diff --git a/test/common.sh b/test/common.sh
index 0219ab3a..3d8e6533 100644
--- a/test/common.sh
+++ b/test/common.sh
@@ -48,6 +48,7 @@ IMG_MINISWHITE_1C_1B_PBM=${IMAGES}/miniswhite-1c-1b.pbm
 IMG_MINISBLACK_1C_8B_PGM=${IMAGES}/minisblack-1c-8b.pgm
 IMG_RGB_3C_16B_PPM=${IMAGES}/rgb-3c-16b.ppm
 IMG_RGB_3C_8B_PPM=${IMAGES}/rgb-3c-8b.ppm
+IMG_TIFF_WITH_SUBIFD_CHAIN=${IMAGES}/tiff_with_subifd_chain.tif
 
 # All uncompressed image files
 IMG_UNCOMPRESSED="${IMG_MINISBLACK_1C_16B} ${IMG_MINISBLACK_1C_8B} ${IMG_MINISWHITE_1C_1B} ${IMG_PALETTE_1C_1B} ${IMG_PALETTE_1C_4B} ${IMG_PALETTE_1C_4B} ${IMG_PALETTE_1C_8B} ${IMG_RGB_3C_8B} ${IMG_RGB_3C_16B}"
diff --git a/test/images/tiff_with_subifd_chain.tif b/test/images/tiff_with_subifd_chain.tif
new file mode 100644
index 0000000000000000000000000000000000000000..7acbba1802e69abb27537cd1422b679d1b3935d7
GIT binary patch
literal 19484
zcmeHNZA?>F7=B6-Q307#P$ybv!3|-4Ord;Kv7&rT9RjwMsoStrWTK8SObp8!LsDb>
ziZN)6i^de@52v^ohKLJU7Q+u`j3LCBY}pSa`?2kZS<GTGv*%oUwILY^f9lQM+vMqe
zdhWTW=RNQ9KKI_<mX&299zYUcvBE-zSW=zG05M^%dRfDK0(o4Rt7B$F@Hr9O8Npp)
z9$^195xm$E3me-W6Klh~iG!At^Xu`LyeeXxvuw1o{VCfIwk05rd>Y%X2CdpSF7mEm
zf_Cgd@@v5uEy9!J>e#KzfXsJ+zlqz+fm17h+8kg>F7S-F<6yr$pgteSDd2Jx0{4jv
zPGHYUpl}s1xd?bbbgl-PU4Uy1kX#J>LR?-899RdGmH;WGz%cP`84xH3Hogbk<$PZy
z;wJ)GDuL=17-BRLTkXRbZvlV5wm0A|(zblFXsY3$N;h0}rtNtf1!KWTvL*gnkb4oQ
zeLl8eQhZlX9WzDS0*4x#+tWf#YP_P(YVT@KNtMm9yww1TY@^I{MaD8JrAUenw;4{P
zBH5%V@(BCriVTtKiX0@@6*-+NuPf3X&ceBwK*KD+F`KLO1~5omoCEAj16Ixj66OI9
ziAy%1Wj;{+CKbN`_?5U~2U^oPw+vwBLSTfr{ubx)Hc*iX%v}WhPV{DRrLzI|JAi#L
ztBUAf0vucVYSpMJL9OR(RmSRNXhlAw$dv*VUic+F<%M5zM>PDBrG$r6k5Z@NPsv9s
zGHV*!iGkOF_UV9c2CyuJol}`{1=6vQ1S3T|Kz-=Z{zg7J+P*2k;RL{&2xKGye-S@S
z1x_Rb+g}?yQnd>I5iRqn=QhAz(a0_3gl<-ZidOOO$wx<Pn+*I(==n3&?3*b`efF*7
zk+WBI-p01dNiSy~u-Pgc_LRhlZLW_idVD!)Qx6r_ZgPa&*{Mg??by^a+~S;fqSRNJ
zXK&xI@KkwS<qco=w#8@G`>XOoLyfuTHtwvtG5q9<RTnDitMk)Sj+TTfcUAY+<$U%2
zrRs*w`5o?WJeS>{Z0>#3a_hq`?{0TNdizg1uh%rXZ`O7HytilT9#28X&>#Ezw(s@a
zeDvg>FZ(~*=Pk@gO$`26`>D6jpPP1kz}K{;u+x)$`i}pzEqx>Vo#*e>H`h2bPH*^n
zu;KHXTmJ91U45{-<pXEOff$oTV>MN7%oUB)jkth#+W+05#RbF#qT>SQI(teq#;qI4
zjpRl=ZTwd@=BgW*>fTeLF|MacZX`F+Ip2uVL}{Y5@n6|U-ALU?-ALV-=}Dn@ns}Oc
zns}Ocno<ADAr37LEe<UXEe<UX9gY7En(KU%YpUlr5{+@M1td3;o9JApiPA)AqO|ef
y5lG!g-ALU?-I(c4T0BiWO*~CJO+3x0zYdB+i$jY;i$jY;i$h1_`HiX0H~#`riL|=_

literal 0
HcmV?d00001

diff --git a/test/tiffinfo.sh b/test/tiffinfo.sh
index cb572483..9764bd51 100755
--- a/test/tiffinfo.sh
+++ b/test/tiffinfo.sh
@@ -4,3 +4,4 @@
 #
 . ${srcdir:-.}/common.sh
 f_test_reader "${TIFFINFO} -c -D -d -j -s " "${IMG_MINISBLACK_1C_16B}"
+f_test_reader "${TIFFINFO}  " "${IMG_TIFF_WITH_SUBIFD_CHAIN}"
diff --git a/tools/tiffinfo.c b/tools/tiffinfo.c
index 36bd9520..c3d79eb7 100644
--- a/tools/tiffinfo.c
+++ b/tools/tiffinfo.c
@@ -151,7 +151,7 @@ main(int argc, char* argv[])
 	multiplefiles = (argc - optind > 1);
 	for (; optind < argc; optind++) {
 		if (multiplefiles)
-			printf("%s:\n", argv[optind]);
+			printf("File %s:\n", argv[optind]);
 		tif = TIFFOpen(argv[optind], chopstrips ? "rC" : "rc");
 		if (tif != NULL) {
 			if (dirnum != -1) {
@@ -168,6 +168,7 @@ main(int argc, char* argv[])
 					tiffinfo(tif, order, flags, 1);
 					if (TIFFGetField(tif, TIFFTAG_EXIFIFD,
 						&offset)) {
+						printf("--- EXIF directory within directory %d \n", curdir);
 						if (TIFFReadEXIFDirectory(tif, offset)) {
 							tiffinfo(tif, order, flags, 0);
 							/*-- Go back to previous directory, (directory is reloaded from file!) */
@@ -176,11 +177,43 @@ main(int argc, char* argv[])
 					}
 					if (TIFFGetField(tif, TIFFTAG_GPSIFD,
 						&offset)) {
+						printf("--- GPS directory within directory %d \n", curdir);
 						if (TIFFReadGPSDirectory(tif, offset)) {
 							tiffinfo(tif, order, flags, 0);
 							TIFFSetDirectory(tif, curdir);
 						}
 					}
+					/*-- Check for SubIFDs --*/
+					uint16_t nCount;
+					void *vPtr;
+					uint64_t *subIFDoffsets = NULL;
+					if (TIFFGetField(tif, TIFFTAG_SUBIFD, &nCount, &vPtr)) {
+						if (nCount > 0) {
+							subIFDoffsets = malloc(nCount * sizeof(uint64_t));
+							if (subIFDoffsets != NULL) {
+								memcpy(subIFDoffsets, vPtr, nCount * sizeof(subIFDoffsets[0]));
+								printf("--- SubIFD image descriptor tag within TIFF directory %d with array of %d SubIFD chains ---\n", curdir, nCount);
+								for (int i = 0; i < nCount; i++) {
+									offset = subIFDoffsets[i];
+									int s = 0;
+									if (TIFFSetSubDirectory(tif, offset)) {
+										/* print info and check for SubIFD chain */
+										do {
+											printf("--- SubIFD %d of chain %d at offset 0x%"PRIx64" (%"PRIu64"):\n", s, i, offset, offset);
+											tiffinfo(tif, order, flags, 0);
+											s++;
+										} while (TIFFReadDirectory(tif));
+									}
+								}
+								TIFFSetDirectory(tif, curdir);
+								free(subIFDoffsets);
+								subIFDoffsets = NULL;
+							} else {
+								fprintf(stderr, "Error: Could not allocate memory for SubIFDs list. SubIFDs not parsed.\n");
+							}
+						}
+					}
+					printf("\n");
 				} while (TIFFReadDirectory(tif));
 			}
 			TIFFClose(tif);