xref: /aosp_15_r20/external/pdfium/third_party/libtiff/tif_dirwrite.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker /*
2*3ac0a46fSAndroid Build Coastguard Worker  * Copyright (c) 1988-1997 Sam Leffler
3*3ac0a46fSAndroid Build Coastguard Worker  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4*3ac0a46fSAndroid Build Coastguard Worker  *
5*3ac0a46fSAndroid Build Coastguard Worker  * Permission to use, copy, modify, distribute, and sell this software and
6*3ac0a46fSAndroid Build Coastguard Worker  * its documentation for any purpose is hereby granted without fee, provided
7*3ac0a46fSAndroid Build Coastguard Worker  * that (i) the above copyright notices and this permission notice appear in
8*3ac0a46fSAndroid Build Coastguard Worker  * all copies of the software and related documentation, and (ii) the names of
9*3ac0a46fSAndroid Build Coastguard Worker  * Sam Leffler and Silicon Graphics may not be used in any advertising or
10*3ac0a46fSAndroid Build Coastguard Worker  * publicity relating to the software without the specific, prior written
11*3ac0a46fSAndroid Build Coastguard Worker  * permission of Sam Leffler and Silicon Graphics.
12*3ac0a46fSAndroid Build Coastguard Worker  *
13*3ac0a46fSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14*3ac0a46fSAndroid Build Coastguard Worker  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15*3ac0a46fSAndroid Build Coastguard Worker  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16*3ac0a46fSAndroid Build Coastguard Worker  *
17*3ac0a46fSAndroid Build Coastguard Worker  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18*3ac0a46fSAndroid Build Coastguard Worker  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19*3ac0a46fSAndroid Build Coastguard Worker  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20*3ac0a46fSAndroid Build Coastguard Worker  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21*3ac0a46fSAndroid Build Coastguard Worker  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22*3ac0a46fSAndroid Build Coastguard Worker  * OF THIS SOFTWARE.
23*3ac0a46fSAndroid Build Coastguard Worker  */
24*3ac0a46fSAndroid Build Coastguard Worker 
25*3ac0a46fSAndroid Build Coastguard Worker /*
26*3ac0a46fSAndroid Build Coastguard Worker  * TIFF Library.
27*3ac0a46fSAndroid Build Coastguard Worker  *
28*3ac0a46fSAndroid Build Coastguard Worker  * Directory Write Support Routines.
29*3ac0a46fSAndroid Build Coastguard Worker  */
30*3ac0a46fSAndroid Build Coastguard Worker #include "tiffiop.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include <float.h> /*--: for Rational2Double */
32*3ac0a46fSAndroid Build Coastguard Worker #include <math.h>  /*--: for Rational2Double */
33*3ac0a46fSAndroid Build Coastguard Worker 
34*3ac0a46fSAndroid Build Coastguard Worker #ifdef HAVE_IEEEFP
35*3ac0a46fSAndroid Build Coastguard Worker #define TIFFCvtNativeToIEEEFloat(tif, n, fp)
36*3ac0a46fSAndroid Build Coastguard Worker #define TIFFCvtNativeToIEEEDouble(tif, n, dp)
37*3ac0a46fSAndroid Build Coastguard Worker #else
38*3ac0a46fSAndroid Build Coastguard Worker extern void TIFFCvtNativeToIEEEFloat(TIFF *tif, uint32_t n, float *fp);
39*3ac0a46fSAndroid Build Coastguard Worker extern void TIFFCvtNativeToIEEEDouble(TIFF *tif, uint32_t n, double *dp);
40*3ac0a46fSAndroid Build Coastguard Worker #endif
41*3ac0a46fSAndroid Build Coastguard Worker 
42*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
43*3ac0a46fSAndroid Build Coastguard Worker                                  uint64_t *pdiroff);
44*3ac0a46fSAndroid Build Coastguard Worker 
45*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSampleformatArray(TIFF *tif, uint32_t *ndir,
46*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
47*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
48*3ac0a46fSAndroid Build Coastguard Worker                                                   double *value);
49*3ac0a46fSAndroid Build Coastguard Worker 
50*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagAscii(TIFF *tif, uint32_t *ndir,
51*3ac0a46fSAndroid Build Coastguard Worker                                       TIFFDirEntry *dir, uint16_t tag,
52*3ac0a46fSAndroid Build Coastguard Worker                                       uint32_t count, char *value);
53*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagUndefinedArray(TIFF *tif, uint32_t *ndir,
54*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
55*3ac0a46fSAndroid Build Coastguard Worker                                                uint32_t count, uint8_t *value);
56*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagByteArray(TIFF *tif, uint32_t *ndir,
57*3ac0a46fSAndroid Build Coastguard Worker                                           TIFFDirEntry *dir, uint16_t tag,
58*3ac0a46fSAndroid Build Coastguard Worker                                           uint32_t count, uint8_t *value);
59*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSbyteArray(TIFF *tif, uint32_t *ndir,
60*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
61*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, int8_t *value);
62*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShort(TIFF *tif, uint32_t *ndir,
63*3ac0a46fSAndroid Build Coastguard Worker                                       TIFFDirEntry *dir, uint16_t tag,
64*3ac0a46fSAndroid Build Coastguard Worker                                       uint16_t value);
65*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShortArray(TIFF *tif, uint32_t *ndir,
66*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
67*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, uint16_t *value);
68*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShortPerSample(TIFF *tif, uint32_t *ndir,
69*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
70*3ac0a46fSAndroid Build Coastguard Worker                                                uint16_t value);
71*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSshortArray(TIFF *tif, uint32_t *ndir,
72*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
73*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t count, int16_t *value);
74*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLong(TIFF *tif, uint32_t *ndir,
75*3ac0a46fSAndroid Build Coastguard Worker                                      TIFFDirEntry *dir, uint16_t tag,
76*3ac0a46fSAndroid Build Coastguard Worker                                      uint32_t value);
77*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLongArray(TIFF *tif, uint32_t *ndir,
78*3ac0a46fSAndroid Build Coastguard Worker                                           TIFFDirEntry *dir, uint16_t tag,
79*3ac0a46fSAndroid Build Coastguard Worker                                           uint32_t count, uint32_t *value);
80*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSlongArray(TIFF *tif, uint32_t *ndir,
81*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
82*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, int32_t *value);
83*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir,
84*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
85*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, uint64_t *value);
86*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir,
87*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
88*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t count, int64_t *value);
89*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagRational(TIFF *tif, uint32_t *ndir,
90*3ac0a46fSAndroid Build Coastguard Worker                                          TIFFDirEntry *dir, uint16_t tag,
91*3ac0a46fSAndroid Build Coastguard Worker                                          double value);
92*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagRationalArray(TIFF *tif, uint32_t *ndir,
93*3ac0a46fSAndroid Build Coastguard Worker                                               TIFFDirEntry *dir, uint16_t tag,
94*3ac0a46fSAndroid Build Coastguard Worker                                               uint32_t count, float *value);
95*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSrationalArray(TIFF *tif, uint32_t *ndir,
96*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
97*3ac0a46fSAndroid Build Coastguard Worker                                                uint32_t count, float *value);
98*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagFloatArray(TIFF *tif, uint32_t *ndir,
99*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
100*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, float *value);
101*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagDoubleArray(TIFF *tif, uint32_t *ndir,
102*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
103*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t count, double *value);
104*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagIfdArray(TIFF *tif, uint32_t *ndir,
105*3ac0a46fSAndroid Build Coastguard Worker                                          TIFFDirEntry *dir, uint16_t tag,
106*3ac0a46fSAndroid Build Coastguard Worker                                          uint32_t count, uint32_t *value);
107*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShortLong(TIFF *tif, uint32_t *ndir,
108*3ac0a46fSAndroid Build Coastguard Worker                                           TIFFDirEntry *dir, uint16_t tag,
109*3ac0a46fSAndroid Build Coastguard Worker                                           uint32_t value);
110*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir,
111*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
112*3ac0a46fSAndroid Build Coastguard Worker                                                uint32_t count, uint64_t *value);
113*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir,
114*3ac0a46fSAndroid Build Coastguard Worker                                              TIFFDirEntry *dir, uint16_t tag,
115*3ac0a46fSAndroid Build Coastguard Worker                                              uint32_t count, uint64_t *value);
116*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir,
117*3ac0a46fSAndroid Build Coastguard Worker                                          TIFFDirEntry *dir);
118*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir,
119*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir);
120*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir,
121*3ac0a46fSAndroid Build Coastguard Worker                                        TIFFDirEntry *dir);
122*3ac0a46fSAndroid Build Coastguard Worker 
123*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedAscii(TIFF *tif, uint32_t *ndir,
124*3ac0a46fSAndroid Build Coastguard Worker                                              TIFFDirEntry *dir, uint16_t tag,
125*3ac0a46fSAndroid Build Coastguard Worker                                              uint32_t count, char *value);
126*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF *tif, uint32_t *ndir,
127*3ac0a46fSAndroid Build Coastguard Worker                                                       TIFFDirEntry *dir,
128*3ac0a46fSAndroid Build Coastguard Worker                                                       uint16_t tag,
129*3ac0a46fSAndroid Build Coastguard Worker                                                       uint32_t count,
130*3ac0a46fSAndroid Build Coastguard Worker                                                       uint8_t *value);
131*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedByteArray(TIFF *tif, uint32_t *ndir,
132*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir,
133*3ac0a46fSAndroid Build Coastguard Worker                                                  uint16_t tag, uint32_t count,
134*3ac0a46fSAndroid Build Coastguard Worker                                                  uint8_t *value);
135*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF *tif, uint32_t *ndir,
136*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
137*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
138*3ac0a46fSAndroid Build Coastguard Worker                                                   int8_t *value);
139*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedShort(TIFF *tif, uint32_t *ndir,
140*3ac0a46fSAndroid Build Coastguard Worker                                              TIFFDirEntry *dir, uint16_t tag,
141*3ac0a46fSAndroid Build Coastguard Worker                                              uint16_t value);
142*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedShortArray(TIFF *tif, uint32_t *ndir,
143*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
144*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
145*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t *value);
146*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF *tif, uint32_t *ndir,
147*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFDirEntry *dir,
148*3ac0a46fSAndroid Build Coastguard Worker                                                    uint16_t tag, uint32_t count,
149*3ac0a46fSAndroid Build Coastguard Worker                                                    int16_t *value);
150*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedLong(TIFF *tif, uint32_t *ndir,
151*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
152*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t value);
153*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedLongArray(TIFF *tif, uint32_t *ndir,
154*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir,
155*3ac0a46fSAndroid Build Coastguard Worker                                                  uint16_t tag, uint32_t count,
156*3ac0a46fSAndroid Build Coastguard Worker                                                  uint32_t *value);
157*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF *tif, uint32_t *ndir,
158*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
159*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
160*3ac0a46fSAndroid Build Coastguard Worker                                                   int32_t *value);
161*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF *tif, uint32_t *ndir,
162*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
163*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
164*3ac0a46fSAndroid Build Coastguard Worker                                                   uint64_t *value);
165*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF *tif, uint32_t *ndir,
166*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFDirEntry *dir,
167*3ac0a46fSAndroid Build Coastguard Worker                                                    uint16_t tag, uint32_t count,
168*3ac0a46fSAndroid Build Coastguard Worker                                                    int64_t *value);
169*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedRational(TIFF *tif, uint32_t *ndir,
170*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFDirEntry *dir, uint16_t tag,
171*3ac0a46fSAndroid Build Coastguard Worker                                                 double value);
172*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir,
173*3ac0a46fSAndroid Build Coastguard Worker                                                      TIFFDirEntry *dir,
174*3ac0a46fSAndroid Build Coastguard Worker                                                      uint16_t tag,
175*3ac0a46fSAndroid Build Coastguard Worker                                                      uint32_t count,
176*3ac0a46fSAndroid Build Coastguard Worker                                                      float *value);
177*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir,
178*3ac0a46fSAndroid Build Coastguard Worker                                                       TIFFDirEntry *dir,
179*3ac0a46fSAndroid Build Coastguard Worker                                                       uint16_t tag,
180*3ac0a46fSAndroid Build Coastguard Worker                                                       uint32_t count,
181*3ac0a46fSAndroid Build Coastguard Worker                                                       float *value);
182*3ac0a46fSAndroid Build Coastguard Worker 
183*3ac0a46fSAndroid Build Coastguard Worker /*--: Rational2Double: New functions to support true double-precision for custom
184*3ac0a46fSAndroid Build Coastguard Worker  * rational tag types. */
185*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagRationalDoubleArray(TIFF *tif, uint32_t *ndir,
186*3ac0a46fSAndroid Build Coastguard Worker                                                     TIFFDirEntry *dir,
187*3ac0a46fSAndroid Build Coastguard Worker                                                     uint16_t tag,
188*3ac0a46fSAndroid Build Coastguard Worker                                                     uint32_t count,
189*3ac0a46fSAndroid Build Coastguard Worker                                                     double *value);
190*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSrationalDoubleArray(TIFF *tif, uint32_t *ndir,
191*3ac0a46fSAndroid Build Coastguard Worker                                                      TIFFDirEntry *dir,
192*3ac0a46fSAndroid Build Coastguard Worker                                                      uint16_t tag,
193*3ac0a46fSAndroid Build Coastguard Worker                                                      uint32_t count,
194*3ac0a46fSAndroid Build Coastguard Worker                                                      double *value);
195*3ac0a46fSAndroid Build Coastguard Worker static int
196*3ac0a46fSAndroid Build Coastguard Worker TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir,
197*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFDirEntry *dir, uint16_t tag,
198*3ac0a46fSAndroid Build Coastguard Worker                                                 uint32_t count, double *value);
199*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
200*3ac0a46fSAndroid Build Coastguard Worker     TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count,
201*3ac0a46fSAndroid Build Coastguard Worker     double *value);
202*3ac0a46fSAndroid Build Coastguard Worker static void DoubleToRational(double value, uint32_t *num, uint32_t *denom);
203*3ac0a46fSAndroid Build Coastguard Worker static void DoubleToSrational(double value, int32_t *num, int32_t *denom);
204*3ac0a46fSAndroid Build Coastguard Worker 
205*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF *tif, uint32_t *ndir,
206*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
207*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
208*3ac0a46fSAndroid Build Coastguard Worker                                                   float *value);
209*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF *tif, uint32_t *ndir,
210*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFDirEntry *dir,
211*3ac0a46fSAndroid Build Coastguard Worker                                                    uint16_t tag, uint32_t count,
212*3ac0a46fSAndroid Build Coastguard Worker                                                    double *value);
213*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF *tif, uint32_t *ndir,
214*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFDirEntry *dir, uint16_t tag,
215*3ac0a46fSAndroid Build Coastguard Worker                                                 uint32_t count,
216*3ac0a46fSAndroid Build Coastguard Worker                                                 uint32_t *value);
217*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF *tif, uint32_t *ndir,
218*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir,
219*3ac0a46fSAndroid Build Coastguard Worker                                                  uint16_t tag, uint32_t count,
220*3ac0a46fSAndroid Build Coastguard Worker                                                  uint64_t *value);
221*3ac0a46fSAndroid Build Coastguard Worker 
222*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagData(TIFF *tif, uint32_t *ndir,
223*3ac0a46fSAndroid Build Coastguard Worker                                      TIFFDirEntry *dir, uint16_t tag,
224*3ac0a46fSAndroid Build Coastguard Worker                                      uint16_t datatype, uint32_t count,
225*3ac0a46fSAndroid Build Coastguard Worker                                      uint32_t datalength, void *data);
226*3ac0a46fSAndroid Build Coastguard Worker 
227*3ac0a46fSAndroid Build Coastguard Worker static int TIFFLinkDirectory(TIFF *);
228*3ac0a46fSAndroid Build Coastguard Worker 
229*3ac0a46fSAndroid Build Coastguard Worker /*
230*3ac0a46fSAndroid Build Coastguard Worker  * Write the contents of the current directory
231*3ac0a46fSAndroid Build Coastguard Worker  * to the specified file.  This routine doesn't
232*3ac0a46fSAndroid Build Coastguard Worker  * handle overwriting a directory with auxiliary
233*3ac0a46fSAndroid Build Coastguard Worker  * storage that's been changed.
234*3ac0a46fSAndroid Build Coastguard Worker  */
TIFFWriteDirectory(TIFF * tif)235*3ac0a46fSAndroid Build Coastguard Worker int TIFFWriteDirectory(TIFF *tif)
236*3ac0a46fSAndroid Build Coastguard Worker {
237*3ac0a46fSAndroid Build Coastguard Worker     return TIFFWriteDirectorySec(tif, TRUE, TRUE, NULL);
238*3ac0a46fSAndroid Build Coastguard Worker }
239*3ac0a46fSAndroid Build Coastguard Worker 
240*3ac0a46fSAndroid Build Coastguard Worker /*
241*3ac0a46fSAndroid Build Coastguard Worker  * This is an advanced writing function that must be used in a particular
242*3ac0a46fSAndroid Build Coastguard Worker  * sequence, and generally together with TIFFForceStrileArrayWriting(),
243*3ac0a46fSAndroid Build Coastguard Worker  * to make its intended effect. Its aim is to modify the location
244*3ac0a46fSAndroid Build Coastguard Worker  * where the [Strip/Tile][Offsets/ByteCounts] arrays are located in the file.
245*3ac0a46fSAndroid Build Coastguard Worker  * More precisely, when TIFFWriteCheck() will be called, the tag entries for
246*3ac0a46fSAndroid Build Coastguard Worker  * those arrays will be written with type = count = offset = 0 as a temporary
247*3ac0a46fSAndroid Build Coastguard Worker  * value.
248*3ac0a46fSAndroid Build Coastguard Worker  *
249*3ac0a46fSAndroid Build Coastguard Worker  * Its effect is only valid for the current directory, and before
250*3ac0a46fSAndroid Build Coastguard Worker  * TIFFWriteDirectory() is first called, and  will be reset when
251*3ac0a46fSAndroid Build Coastguard Worker  * changing directory.
252*3ac0a46fSAndroid Build Coastguard Worker  *
253*3ac0a46fSAndroid Build Coastguard Worker  * The typical sequence of calls is:
254*3ac0a46fSAndroid Build Coastguard Worker  * TIFFOpen()
255*3ac0a46fSAndroid Build Coastguard Worker  * [ TIFFCreateDirectory(tif) ]
256*3ac0a46fSAndroid Build Coastguard Worker  * Set fields with calls to TIFFSetField(tif, ...)
257*3ac0a46fSAndroid Build Coastguard Worker  * TIFFDeferStrileArrayWriting(tif)
258*3ac0a46fSAndroid Build Coastguard Worker  * TIFFWriteCheck(tif, ...)
259*3ac0a46fSAndroid Build Coastguard Worker  * TIFFWriteDirectory(tif)
260*3ac0a46fSAndroid Build Coastguard Worker  * ... potentially create other directories and come back to the above directory
261*3ac0a46fSAndroid Build Coastguard Worker  * TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file
262*3ac0a46fSAndroid Build Coastguard Worker  *
263*3ac0a46fSAndroid Build Coastguard Worker  * Returns 1 in case of success, 0 otherwise.
264*3ac0a46fSAndroid Build Coastguard Worker  */
TIFFDeferStrileArrayWriting(TIFF * tif)265*3ac0a46fSAndroid Build Coastguard Worker int TIFFDeferStrileArrayWriting(TIFF *tif)
266*3ac0a46fSAndroid Build Coastguard Worker {
267*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFDeferStrileArrayWriting";
268*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_mode == O_RDONLY)
269*3ac0a46fSAndroid Build Coastguard Worker     {
270*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, tif->tif_name, "File opened in read-only mode");
271*3ac0a46fSAndroid Build Coastguard Worker         return 0;
272*3ac0a46fSAndroid Build Coastguard Worker     }
273*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_diroff != 0)
274*3ac0a46fSAndroid Build Coastguard Worker     {
275*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Directory has already been written");
276*3ac0a46fSAndroid Build Coastguard Worker         return 0;
277*3ac0a46fSAndroid Build Coastguard Worker     }
278*3ac0a46fSAndroid Build Coastguard Worker 
279*3ac0a46fSAndroid Build Coastguard Worker     tif->tif_dir.td_deferstrilearraywriting = TRUE;
280*3ac0a46fSAndroid Build Coastguard Worker     return 1;
281*3ac0a46fSAndroid Build Coastguard Worker }
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker /*
284*3ac0a46fSAndroid Build Coastguard Worker  * Similar to TIFFWriteDirectory(), writes the directory out
285*3ac0a46fSAndroid Build Coastguard Worker  * but leaves all data structures in memory so that it can be
286*3ac0a46fSAndroid Build Coastguard Worker  * written again.  This will make a partially written TIFF file
287*3ac0a46fSAndroid Build Coastguard Worker  * readable before it is successfully completed/closed.
288*3ac0a46fSAndroid Build Coastguard Worker  */
TIFFCheckpointDirectory(TIFF * tif)289*3ac0a46fSAndroid Build Coastguard Worker int TIFFCheckpointDirectory(TIFF *tif)
290*3ac0a46fSAndroid Build Coastguard Worker {
291*3ac0a46fSAndroid Build Coastguard Worker     int rc;
292*3ac0a46fSAndroid Build Coastguard Worker     /* Setup the strips arrays, if they haven't already been. */
293*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_dir.td_stripoffset_p == NULL)
294*3ac0a46fSAndroid Build Coastguard Worker         (void)TIFFSetupStrips(tif);
295*3ac0a46fSAndroid Build Coastguard Worker     rc = TIFFWriteDirectorySec(tif, TRUE, FALSE, NULL);
296*3ac0a46fSAndroid Build Coastguard Worker     (void)TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
297*3ac0a46fSAndroid Build Coastguard Worker     return rc;
298*3ac0a46fSAndroid Build Coastguard Worker }
299*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteCustomDirectory(TIFF * tif,uint64_t * pdiroff)300*3ac0a46fSAndroid Build Coastguard Worker int TIFFWriteCustomDirectory(TIFF *tif, uint64_t *pdiroff)
301*3ac0a46fSAndroid Build Coastguard Worker {
302*3ac0a46fSAndroid Build Coastguard Worker     return TIFFWriteDirectorySec(tif, FALSE, FALSE, pdiroff);
303*3ac0a46fSAndroid Build Coastguard Worker }
304*3ac0a46fSAndroid Build Coastguard Worker 
305*3ac0a46fSAndroid Build Coastguard Worker /*
306*3ac0a46fSAndroid Build Coastguard Worker  * Similar to TIFFWriteDirectory(), but if the directory has already
307*3ac0a46fSAndroid Build Coastguard Worker  * been written once, it is relocated to the end of the file, in case it
308*3ac0a46fSAndroid Build Coastguard Worker  * has changed in size.  Note that this will result in the loss of the
309*3ac0a46fSAndroid Build Coastguard Worker  * previously used directory space.
310*3ac0a46fSAndroid Build Coastguard Worker  */
TIFFRewriteDirectory(TIFF * tif)311*3ac0a46fSAndroid Build Coastguard Worker int TIFFRewriteDirectory(TIFF *tif)
312*3ac0a46fSAndroid Build Coastguard Worker {
313*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFRewriteDirectory";
314*3ac0a46fSAndroid Build Coastguard Worker 
315*3ac0a46fSAndroid Build Coastguard Worker     /* We don't need to do anything special if it hasn't been written. */
316*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_diroff == 0)
317*3ac0a46fSAndroid Build Coastguard Worker         return TIFFWriteDirectory(tif);
318*3ac0a46fSAndroid Build Coastguard Worker 
319*3ac0a46fSAndroid Build Coastguard Worker     /*
320*3ac0a46fSAndroid Build Coastguard Worker      * Find and zero the pointer to this directory, so that TIFFLinkDirectory
321*3ac0a46fSAndroid Build Coastguard Worker      * will cause it to be added after this directories current pre-link.
322*3ac0a46fSAndroid Build Coastguard Worker      */
323*3ac0a46fSAndroid Build Coastguard Worker     uint64_t torewritediroff = tif->tif_diroff;
324*3ac0a46fSAndroid Build Coastguard Worker 
325*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
326*3ac0a46fSAndroid Build Coastguard Worker     {
327*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_header.classic.tiff_diroff == tif->tif_diroff)
328*3ac0a46fSAndroid Build Coastguard Worker         {
329*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_header.classic.tiff_diroff = 0;
330*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_diroff = 0;
331*3ac0a46fSAndroid Build Coastguard Worker 
332*3ac0a46fSAndroid Build Coastguard Worker             TIFFSeekFile(tif, 4, SEEK_SET);
333*3ac0a46fSAndroid Build Coastguard Worker             if (!WriteOK(tif, &(tif->tif_header.classic.tiff_diroff), 4))
334*3ac0a46fSAndroid Build Coastguard Worker             {
335*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, tif->tif_name, "Error updating TIFF header");
336*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
337*3ac0a46fSAndroid Build Coastguard Worker             }
338*3ac0a46fSAndroid Build Coastguard Worker         }
339*3ac0a46fSAndroid Build Coastguard Worker         else if (tif->tif_diroff > 0xFFFFFFFFU)
340*3ac0a46fSAndroid Build Coastguard Worker         {
341*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
342*3ac0a46fSAndroid Build Coastguard Worker                           "tif->tif_diroff exceeds 32 bit range allowed for "
343*3ac0a46fSAndroid Build Coastguard Worker                           "Classic TIFF");
344*3ac0a46fSAndroid Build Coastguard Worker             return (0);
345*3ac0a46fSAndroid Build Coastguard Worker         }
346*3ac0a46fSAndroid Build Coastguard Worker         else
347*3ac0a46fSAndroid Build Coastguard Worker         {
348*3ac0a46fSAndroid Build Coastguard Worker             uint32_t nextdir;
349*3ac0a46fSAndroid Build Coastguard Worker             nextdir = tif->tif_header.classic.tiff_diroff;
350*3ac0a46fSAndroid Build Coastguard Worker             while (1)
351*3ac0a46fSAndroid Build Coastguard Worker             {
352*3ac0a46fSAndroid Build Coastguard Worker                 uint16_t dircount;
353*3ac0a46fSAndroid Build Coastguard Worker                 uint32_t nextnextdir;
354*3ac0a46fSAndroid Build Coastguard Worker 
355*3ac0a46fSAndroid Build Coastguard Worker                 if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2))
356*3ac0a46fSAndroid Build Coastguard Worker                 {
357*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module,
358*3ac0a46fSAndroid Build Coastguard Worker                                   "Error fetching directory count");
359*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
360*3ac0a46fSAndroid Build Coastguard Worker                 }
361*3ac0a46fSAndroid Build Coastguard Worker                 if (tif->tif_flags & TIFF_SWAB)
362*3ac0a46fSAndroid Build Coastguard Worker                     TIFFSwabShort(&dircount);
363*3ac0a46fSAndroid Build Coastguard Worker                 (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
364*3ac0a46fSAndroid Build Coastguard Worker                 if (!ReadOK(tif, &nextnextdir, 4))
365*3ac0a46fSAndroid Build Coastguard Worker                 {
366*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module, "Error fetching directory link");
367*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
368*3ac0a46fSAndroid Build Coastguard Worker                 }
369*3ac0a46fSAndroid Build Coastguard Worker                 if (tif->tif_flags & TIFF_SWAB)
370*3ac0a46fSAndroid Build Coastguard Worker                     TIFFSwabLong(&nextnextdir);
371*3ac0a46fSAndroid Build Coastguard Worker                 if (nextnextdir == tif->tif_diroff)
372*3ac0a46fSAndroid Build Coastguard Worker                 {
373*3ac0a46fSAndroid Build Coastguard Worker                     uint32_t m;
374*3ac0a46fSAndroid Build Coastguard Worker                     m = 0;
375*3ac0a46fSAndroid Build Coastguard Worker                     (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12,
376*3ac0a46fSAndroid Build Coastguard Worker                                        SEEK_SET);
377*3ac0a46fSAndroid Build Coastguard Worker                     if (!WriteOK(tif, &m, 4))
378*3ac0a46fSAndroid Build Coastguard Worker                     {
379*3ac0a46fSAndroid Build Coastguard Worker                         TIFFErrorExtR(tif, module,
380*3ac0a46fSAndroid Build Coastguard Worker                                       "Error writing directory link");
381*3ac0a46fSAndroid Build Coastguard Worker                         return (0);
382*3ac0a46fSAndroid Build Coastguard Worker                     }
383*3ac0a46fSAndroid Build Coastguard Worker                     tif->tif_diroff = 0;
384*3ac0a46fSAndroid Build Coastguard Worker                     /* Force a full-traversal to reach the zeroed pointer */
385*3ac0a46fSAndroid Build Coastguard Worker                     tif->tif_lastdiroff = 0;
386*3ac0a46fSAndroid Build Coastguard Worker                     break;
387*3ac0a46fSAndroid Build Coastguard Worker                 }
388*3ac0a46fSAndroid Build Coastguard Worker                 nextdir = nextnextdir;
389*3ac0a46fSAndroid Build Coastguard Worker             }
390*3ac0a46fSAndroid Build Coastguard Worker         }
391*3ac0a46fSAndroid Build Coastguard Worker         /* Remove skipped offset from IFD loop directory list. */
392*3ac0a46fSAndroid Build Coastguard Worker         _TIFFRemoveEntryFromDirectoryListByOffset(tif, torewritediroff);
393*3ac0a46fSAndroid Build Coastguard Worker     }
394*3ac0a46fSAndroid Build Coastguard Worker     else
395*3ac0a46fSAndroid Build Coastguard Worker     {
396*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_header.big.tiff_diroff == tif->tif_diroff)
397*3ac0a46fSAndroid Build Coastguard Worker         {
398*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_header.big.tiff_diroff = 0;
399*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_diroff = 0;
400*3ac0a46fSAndroid Build Coastguard Worker 
401*3ac0a46fSAndroid Build Coastguard Worker             TIFFSeekFile(tif, 8, SEEK_SET);
402*3ac0a46fSAndroid Build Coastguard Worker             if (!WriteOK(tif, &(tif->tif_header.big.tiff_diroff), 8))
403*3ac0a46fSAndroid Build Coastguard Worker             {
404*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, tif->tif_name, "Error updating TIFF header");
405*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
406*3ac0a46fSAndroid Build Coastguard Worker             }
407*3ac0a46fSAndroid Build Coastguard Worker         }
408*3ac0a46fSAndroid Build Coastguard Worker         else
409*3ac0a46fSAndroid Build Coastguard Worker         {
410*3ac0a46fSAndroid Build Coastguard Worker             uint64_t nextdir;
411*3ac0a46fSAndroid Build Coastguard Worker             nextdir = tif->tif_header.big.tiff_diroff;
412*3ac0a46fSAndroid Build Coastguard Worker             while (1)
413*3ac0a46fSAndroid Build Coastguard Worker             {
414*3ac0a46fSAndroid Build Coastguard Worker                 uint64_t dircount64;
415*3ac0a46fSAndroid Build Coastguard Worker                 uint16_t dircount;
416*3ac0a46fSAndroid Build Coastguard Worker                 uint64_t nextnextdir;
417*3ac0a46fSAndroid Build Coastguard Worker 
418*3ac0a46fSAndroid Build Coastguard Worker                 if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
419*3ac0a46fSAndroid Build Coastguard Worker                 {
420*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module,
421*3ac0a46fSAndroid Build Coastguard Worker                                   "Error fetching directory count");
422*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
423*3ac0a46fSAndroid Build Coastguard Worker                 }
424*3ac0a46fSAndroid Build Coastguard Worker                 if (tif->tif_flags & TIFF_SWAB)
425*3ac0a46fSAndroid Build Coastguard Worker                     TIFFSwabLong8(&dircount64);
426*3ac0a46fSAndroid Build Coastguard Worker                 if (dircount64 > 0xFFFF)
427*3ac0a46fSAndroid Build Coastguard Worker                 {
428*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module,
429*3ac0a46fSAndroid Build Coastguard Worker                                   "Sanity check on tag count failed, likely "
430*3ac0a46fSAndroid Build Coastguard Worker                                   "corrupt TIFF");
431*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
432*3ac0a46fSAndroid Build Coastguard Worker                 }
433*3ac0a46fSAndroid Build Coastguard Worker                 dircount = (uint16_t)dircount64;
434*3ac0a46fSAndroid Build Coastguard Worker                 (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
435*3ac0a46fSAndroid Build Coastguard Worker                 if (!ReadOK(tif, &nextnextdir, 8))
436*3ac0a46fSAndroid Build Coastguard Worker                 {
437*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module, "Error fetching directory link");
438*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
439*3ac0a46fSAndroid Build Coastguard Worker                 }
440*3ac0a46fSAndroid Build Coastguard Worker                 if (tif->tif_flags & TIFF_SWAB)
441*3ac0a46fSAndroid Build Coastguard Worker                     TIFFSwabLong8(&nextnextdir);
442*3ac0a46fSAndroid Build Coastguard Worker                 if (nextnextdir == tif->tif_diroff)
443*3ac0a46fSAndroid Build Coastguard Worker                 {
444*3ac0a46fSAndroid Build Coastguard Worker                     uint64_t m;
445*3ac0a46fSAndroid Build Coastguard Worker                     m = 0;
446*3ac0a46fSAndroid Build Coastguard Worker                     (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20,
447*3ac0a46fSAndroid Build Coastguard Worker                                        SEEK_SET);
448*3ac0a46fSAndroid Build Coastguard Worker                     if (!WriteOK(tif, &m, 8))
449*3ac0a46fSAndroid Build Coastguard Worker                     {
450*3ac0a46fSAndroid Build Coastguard Worker                         TIFFErrorExtR(tif, module,
451*3ac0a46fSAndroid Build Coastguard Worker                                       "Error writing directory link");
452*3ac0a46fSAndroid Build Coastguard Worker                         return (0);
453*3ac0a46fSAndroid Build Coastguard Worker                     }
454*3ac0a46fSAndroid Build Coastguard Worker                     tif->tif_diroff = 0;
455*3ac0a46fSAndroid Build Coastguard Worker                     /* Force a full-traversal to reach the zeroed pointer */
456*3ac0a46fSAndroid Build Coastguard Worker                     tif->tif_lastdiroff = 0;
457*3ac0a46fSAndroid Build Coastguard Worker                     break;
458*3ac0a46fSAndroid Build Coastguard Worker                 }
459*3ac0a46fSAndroid Build Coastguard Worker                 nextdir = nextnextdir;
460*3ac0a46fSAndroid Build Coastguard Worker             }
461*3ac0a46fSAndroid Build Coastguard Worker         }
462*3ac0a46fSAndroid Build Coastguard Worker         /* Remove skipped offset from IFD loop directory list. */
463*3ac0a46fSAndroid Build Coastguard Worker         _TIFFRemoveEntryFromDirectoryListByOffset(tif, torewritediroff);
464*3ac0a46fSAndroid Build Coastguard Worker     }
465*3ac0a46fSAndroid Build Coastguard Worker 
466*3ac0a46fSAndroid Build Coastguard Worker     /*
467*3ac0a46fSAndroid Build Coastguard Worker      * Now use TIFFWriteDirectory() normally.
468*3ac0a46fSAndroid Build Coastguard Worker      */
469*3ac0a46fSAndroid Build Coastguard Worker 
470*3ac0a46fSAndroid Build Coastguard Worker     return TIFFWriteDirectory(tif);
471*3ac0a46fSAndroid Build Coastguard Worker }
472*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectorySec(TIFF * tif,int isimage,int imagedone,uint64_t * pdiroff)473*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
474*3ac0a46fSAndroid Build Coastguard Worker                                  uint64_t *pdiroff)
475*3ac0a46fSAndroid Build Coastguard Worker {
476*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectorySec";
477*3ac0a46fSAndroid Build Coastguard Worker     uint32_t ndir;
478*3ac0a46fSAndroid Build Coastguard Worker     TIFFDirEntry *dir;
479*3ac0a46fSAndroid Build Coastguard Worker     uint32_t dirsize;
480*3ac0a46fSAndroid Build Coastguard Worker     void *dirmem;
481*3ac0a46fSAndroid Build Coastguard Worker     uint32_t m;
482*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_mode == O_RDONLY)
483*3ac0a46fSAndroid Build Coastguard Worker         return (1);
484*3ac0a46fSAndroid Build Coastguard Worker 
485*3ac0a46fSAndroid Build Coastguard Worker     _TIFFFillStriles(tif);
486*3ac0a46fSAndroid Build Coastguard Worker 
487*3ac0a46fSAndroid Build Coastguard Worker     /*
488*3ac0a46fSAndroid Build Coastguard Worker      * Clear write state so that subsequent images with
489*3ac0a46fSAndroid Build Coastguard Worker      * different characteristics get the right buffers
490*3ac0a46fSAndroid Build Coastguard Worker      * setup for them.
491*3ac0a46fSAndroid Build Coastguard Worker      */
492*3ac0a46fSAndroid Build Coastguard Worker     if (imagedone)
493*3ac0a46fSAndroid Build Coastguard Worker     {
494*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_POSTENCODE)
495*3ac0a46fSAndroid Build Coastguard Worker         {
496*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_flags &= ~TIFF_POSTENCODE;
497*3ac0a46fSAndroid Build Coastguard Worker             if (!(*tif->tif_postencode)(tif))
498*3ac0a46fSAndroid Build Coastguard Worker             {
499*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
500*3ac0a46fSAndroid Build Coastguard Worker                               "Error post-encoding before directory write");
501*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
502*3ac0a46fSAndroid Build Coastguard Worker             }
503*3ac0a46fSAndroid Build Coastguard Worker         }
504*3ac0a46fSAndroid Build Coastguard Worker         (*tif->tif_close)(tif); /* shutdown encoder */
505*3ac0a46fSAndroid Build Coastguard Worker         /*
506*3ac0a46fSAndroid Build Coastguard Worker          * Flush any data that might have been written
507*3ac0a46fSAndroid Build Coastguard Worker          * by the compression close+cleanup routines.  But
508*3ac0a46fSAndroid Build Coastguard Worker          * be careful not to write stuff if we didn't add data
509*3ac0a46fSAndroid Build Coastguard Worker          * in the previous steps as the "rawcc" data may well be
510*3ac0a46fSAndroid Build Coastguard Worker          * a previously read tile/strip in mixed read/write mode.
511*3ac0a46fSAndroid Build Coastguard Worker          */
512*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_rawcc > 0 && (tif->tif_flags & TIFF_BEENWRITING) != 0)
513*3ac0a46fSAndroid Build Coastguard Worker         {
514*3ac0a46fSAndroid Build Coastguard Worker             if (!TIFFFlushData1(tif))
515*3ac0a46fSAndroid Build Coastguard Worker             {
516*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
517*3ac0a46fSAndroid Build Coastguard Worker                               "Error flushing data before directory write");
518*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
519*3ac0a46fSAndroid Build Coastguard Worker             }
520*3ac0a46fSAndroid Build Coastguard Worker         }
521*3ac0a46fSAndroid Build Coastguard Worker         if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
522*3ac0a46fSAndroid Build Coastguard Worker         {
523*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, tif->tif_rawdata);
524*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_rawdata = NULL;
525*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_rawcc = 0;
526*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_rawdatasize = 0;
527*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_rawdataoff = 0;
528*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_rawdataloaded = 0;
529*3ac0a46fSAndroid Build Coastguard Worker         }
530*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_flags &= ~(TIFF_BEENWRITING | TIFF_BUFFERSETUP);
531*3ac0a46fSAndroid Build Coastguard Worker     }
532*3ac0a46fSAndroid Build Coastguard Worker 
533*3ac0a46fSAndroid Build Coastguard Worker     if (TIFFFieldSet(tif, FIELD_COMPRESSION) &&
534*3ac0a46fSAndroid Build Coastguard Worker         (tif->tif_dir.td_compression == COMPRESSION_DEFLATE))
535*3ac0a46fSAndroid Build Coastguard Worker     {
536*3ac0a46fSAndroid Build Coastguard Worker         TIFFWarningExtR(tif, module,
537*3ac0a46fSAndroid Build Coastguard Worker                         "Creating TIFF with legacy Deflate codec identifier, "
538*3ac0a46fSAndroid Build Coastguard Worker                         "COMPRESSION_ADOBE_DEFLATE is more widely supported");
539*3ac0a46fSAndroid Build Coastguard Worker     }
540*3ac0a46fSAndroid Build Coastguard Worker     dir = NULL;
541*3ac0a46fSAndroid Build Coastguard Worker     dirmem = NULL;
542*3ac0a46fSAndroid Build Coastguard Worker     dirsize = 0;
543*3ac0a46fSAndroid Build Coastguard Worker     while (1)
544*3ac0a46fSAndroid Build Coastguard Worker     {
545*3ac0a46fSAndroid Build Coastguard Worker         ndir = 0;
546*3ac0a46fSAndroid Build Coastguard Worker         if (isimage)
547*3ac0a46fSAndroid Build Coastguard Worker         {
548*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
549*3ac0a46fSAndroid Build Coastguard Worker             {
550*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortLong(tif, &ndir, dir,
551*3ac0a46fSAndroid Build Coastguard Worker                                                     TIFFTAG_IMAGEWIDTH,
552*3ac0a46fSAndroid Build Coastguard Worker                                                     tif->tif_dir.td_imagewidth))
553*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
554*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortLong(
555*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_IMAGELENGTH,
556*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_imagelength))
557*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
558*3ac0a46fSAndroid Build Coastguard Worker             }
559*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_TILEDIMENSIONS))
560*3ac0a46fSAndroid Build Coastguard Worker             {
561*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortLong(tif, &ndir, dir,
562*3ac0a46fSAndroid Build Coastguard Worker                                                     TIFFTAG_TILEWIDTH,
563*3ac0a46fSAndroid Build Coastguard Worker                                                     tif->tif_dir.td_tilewidth))
564*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
565*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortLong(tif, &ndir, dir,
566*3ac0a46fSAndroid Build Coastguard Worker                                                     TIFFTAG_TILELENGTH,
567*3ac0a46fSAndroid Build Coastguard Worker                                                     tif->tif_dir.td_tilelength))
568*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
569*3ac0a46fSAndroid Build Coastguard Worker             }
570*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_RESOLUTION))
571*3ac0a46fSAndroid Build Coastguard Worker             {
572*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
573*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFTAG_XRESOLUTION,
574*3ac0a46fSAndroid Build Coastguard Worker                                                    tif->tif_dir.td_xresolution))
575*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
576*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
577*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFTAG_YRESOLUTION,
578*3ac0a46fSAndroid Build Coastguard Worker                                                    tif->tif_dir.td_yresolution))
579*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
580*3ac0a46fSAndroid Build Coastguard Worker             }
581*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_POSITION))
582*3ac0a46fSAndroid Build Coastguard Worker             {
583*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
584*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFTAG_XPOSITION,
585*3ac0a46fSAndroid Build Coastguard Worker                                                    tif->tif_dir.td_xposition))
586*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
587*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
588*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFTAG_YPOSITION,
589*3ac0a46fSAndroid Build Coastguard Worker                                                    tif->tif_dir.td_yposition))
590*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
591*3ac0a46fSAndroid Build Coastguard Worker             }
592*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_SUBFILETYPE))
593*3ac0a46fSAndroid Build Coastguard Worker             {
594*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagLong(tif, &ndir, dir,
595*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFTAG_SUBFILETYPE,
596*3ac0a46fSAndroid Build Coastguard Worker                                                tif->tif_dir.td_subfiletype))
597*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
598*3ac0a46fSAndroid Build Coastguard Worker             }
599*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_BITSPERSAMPLE))
600*3ac0a46fSAndroid Build Coastguard Worker             {
601*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortPerSample(
602*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_BITSPERSAMPLE,
603*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_bitspersample))
604*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
605*3ac0a46fSAndroid Build Coastguard Worker             }
606*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_COMPRESSION))
607*3ac0a46fSAndroid Build Coastguard Worker             {
608*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
609*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_COMPRESSION,
610*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_compression))
611*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
612*3ac0a46fSAndroid Build Coastguard Worker             }
613*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_PHOTOMETRIC))
614*3ac0a46fSAndroid Build Coastguard Worker             {
615*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
616*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_PHOTOMETRIC,
617*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_photometric))
618*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
619*3ac0a46fSAndroid Build Coastguard Worker             }
620*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_THRESHHOLDING))
621*3ac0a46fSAndroid Build Coastguard Worker             {
622*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
623*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_THRESHHOLDING,
624*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_threshholding))
625*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
626*3ac0a46fSAndroid Build Coastguard Worker             }
627*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_FILLORDER))
628*3ac0a46fSAndroid Build Coastguard Worker             {
629*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
630*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_FILLORDER,
631*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_fillorder))
632*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
633*3ac0a46fSAndroid Build Coastguard Worker             }
634*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_ORIENTATION))
635*3ac0a46fSAndroid Build Coastguard Worker             {
636*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
637*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_ORIENTATION,
638*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_orientation))
639*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
640*3ac0a46fSAndroid Build Coastguard Worker             }
641*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
642*3ac0a46fSAndroid Build Coastguard Worker             {
643*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(
644*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_SAMPLESPERPIXEL,
645*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_samplesperpixel))
646*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
647*3ac0a46fSAndroid Build Coastguard Worker             }
648*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
649*3ac0a46fSAndroid Build Coastguard Worker             {
650*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortLong(
651*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_ROWSPERSTRIP,
652*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_rowsperstrip))
653*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
654*3ac0a46fSAndroid Build Coastguard Worker             }
655*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_MINSAMPLEVALUE))
656*3ac0a46fSAndroid Build Coastguard Worker             {
657*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortPerSample(
658*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_MINSAMPLEVALUE,
659*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_minsamplevalue))
660*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
661*3ac0a46fSAndroid Build Coastguard Worker             }
662*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
663*3ac0a46fSAndroid Build Coastguard Worker             {
664*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortPerSample(
665*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_MAXSAMPLEVALUE,
666*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_maxsamplevalue))
667*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
668*3ac0a46fSAndroid Build Coastguard Worker             }
669*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_PLANARCONFIG))
670*3ac0a46fSAndroid Build Coastguard Worker             {
671*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
672*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_PLANARCONFIG,
673*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_planarconfig))
674*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
675*3ac0a46fSAndroid Build Coastguard Worker             }
676*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_RESOLUTIONUNIT))
677*3ac0a46fSAndroid Build Coastguard Worker             {
678*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
679*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_RESOLUTIONUNIT,
680*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_resolutionunit))
681*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
682*3ac0a46fSAndroid Build Coastguard Worker             }
683*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_PAGENUMBER))
684*3ac0a46fSAndroid Build Coastguard Worker             {
685*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortArray(
686*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_PAGENUMBER, 2,
687*3ac0a46fSAndroid Build Coastguard Worker                         &tif->tif_dir.td_pagenumber[0]))
688*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
689*3ac0a46fSAndroid Build Coastguard Worker             }
690*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS))
691*3ac0a46fSAndroid Build Coastguard Worker             {
692*3ac0a46fSAndroid Build Coastguard Worker                 if (!isTiled(tif))
693*3ac0a46fSAndroid Build Coastguard Worker                 {
694*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagLongLong8Array(
695*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, TIFFTAG_STRIPBYTECOUNTS,
696*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_nstrips,
697*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_stripbytecount_p))
698*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
699*3ac0a46fSAndroid Build Coastguard Worker                 }
700*3ac0a46fSAndroid Build Coastguard Worker                 else
701*3ac0a46fSAndroid Build Coastguard Worker                 {
702*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagLongLong8Array(
703*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, TIFFTAG_TILEBYTECOUNTS,
704*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_nstrips,
705*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_stripbytecount_p))
706*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
707*3ac0a46fSAndroid Build Coastguard Worker                 }
708*3ac0a46fSAndroid Build Coastguard Worker             }
709*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_STRIPOFFSETS))
710*3ac0a46fSAndroid Build Coastguard Worker             {
711*3ac0a46fSAndroid Build Coastguard Worker                 if (!isTiled(tif))
712*3ac0a46fSAndroid Build Coastguard Worker                 {
713*3ac0a46fSAndroid Build Coastguard Worker                     /* td_stripoffset_p might be NULL in an odd OJPEG case. See
714*3ac0a46fSAndroid Build Coastguard Worker                      *  tif_dirread.c around line 3634.
715*3ac0a46fSAndroid Build Coastguard Worker                      * XXX: OJPEG hack.
716*3ac0a46fSAndroid Build Coastguard Worker                      * If a) compression is OJPEG, b) it's not a tiled TIFF,
717*3ac0a46fSAndroid Build Coastguard Worker                      * and c) the number of strips is 1,
718*3ac0a46fSAndroid Build Coastguard Worker                      * then we tolerate the absence of stripoffsets tag,
719*3ac0a46fSAndroid Build Coastguard Worker                      * because, presumably, all required data is in the
720*3ac0a46fSAndroid Build Coastguard Worker                      * JpegInterchangeFormat stream.
721*3ac0a46fSAndroid Build Coastguard Worker                      * We can get here when using tiffset on such a file.
722*3ac0a46fSAndroid Build Coastguard Worker                      * See http://bugzilla.maptools.org/show_bug.cgi?id=2500
723*3ac0a46fSAndroid Build Coastguard Worker                      */
724*3ac0a46fSAndroid Build Coastguard Worker                     if (tif->tif_dir.td_stripoffset_p != NULL &&
725*3ac0a46fSAndroid Build Coastguard Worker                         !TIFFWriteDirectoryTagLongLong8Array(
726*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, TIFFTAG_STRIPOFFSETS,
727*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_nstrips,
728*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_stripoffset_p))
729*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
730*3ac0a46fSAndroid Build Coastguard Worker                 }
731*3ac0a46fSAndroid Build Coastguard Worker                 else
732*3ac0a46fSAndroid Build Coastguard Worker                 {
733*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagLongLong8Array(
734*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, TIFFTAG_TILEOFFSETS,
735*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_nstrips,
736*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_stripoffset_p))
737*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
738*3ac0a46fSAndroid Build Coastguard Worker                 }
739*3ac0a46fSAndroid Build Coastguard Worker             }
740*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_COLORMAP))
741*3ac0a46fSAndroid Build Coastguard Worker             {
742*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagColormap(tif, &ndir, dir))
743*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
744*3ac0a46fSAndroid Build Coastguard Worker             }
745*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_EXTRASAMPLES))
746*3ac0a46fSAndroid Build Coastguard Worker             {
747*3ac0a46fSAndroid Build Coastguard Worker                 if (tif->tif_dir.td_extrasamples)
748*3ac0a46fSAndroid Build Coastguard Worker                 {
749*3ac0a46fSAndroid Build Coastguard Worker                     uint16_t na;
750*3ac0a46fSAndroid Build Coastguard Worker                     uint16_t *nb;
751*3ac0a46fSAndroid Build Coastguard Worker                     TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &na, &nb);
752*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagShortArray(
753*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, TIFFTAG_EXTRASAMPLES, na, nb))
754*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
755*3ac0a46fSAndroid Build Coastguard Worker                 }
756*3ac0a46fSAndroid Build Coastguard Worker             }
757*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_SAMPLEFORMAT))
758*3ac0a46fSAndroid Build Coastguard Worker             {
759*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortPerSample(
760*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_SAMPLEFORMAT,
761*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_sampleformat))
762*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
763*3ac0a46fSAndroid Build Coastguard Worker             }
764*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_SMINSAMPLEVALUE))
765*3ac0a46fSAndroid Build Coastguard Worker             {
766*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagSampleformatArray(
767*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_SMINSAMPLEVALUE,
768*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_samplesperpixel,
769*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_sminsamplevalue))
770*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
771*3ac0a46fSAndroid Build Coastguard Worker             }
772*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_SMAXSAMPLEVALUE))
773*3ac0a46fSAndroid Build Coastguard Worker             {
774*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagSampleformatArray(
775*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_SMAXSAMPLEVALUE,
776*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_samplesperpixel,
777*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_smaxsamplevalue))
778*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
779*3ac0a46fSAndroid Build Coastguard Worker             }
780*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_IMAGEDEPTH))
781*3ac0a46fSAndroid Build Coastguard Worker             {
782*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagLong(tif, &ndir, dir,
783*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFTAG_IMAGEDEPTH,
784*3ac0a46fSAndroid Build Coastguard Worker                                                tif->tif_dir.td_imagedepth))
785*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
786*3ac0a46fSAndroid Build Coastguard Worker             }
787*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_TILEDEPTH))
788*3ac0a46fSAndroid Build Coastguard Worker             {
789*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagLong(tif, &ndir, dir,
790*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFTAG_TILEDEPTH,
791*3ac0a46fSAndroid Build Coastguard Worker                                                tif->tif_dir.td_tiledepth))
792*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
793*3ac0a46fSAndroid Build Coastguard Worker             }
794*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_HALFTONEHINTS))
795*3ac0a46fSAndroid Build Coastguard Worker             {
796*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortArray(
797*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_HALFTONEHINTS, 2,
798*3ac0a46fSAndroid Build Coastguard Worker                         &tif->tif_dir.td_halftonehints[0]))
799*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
800*3ac0a46fSAndroid Build Coastguard Worker             }
801*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_YCBCRSUBSAMPLING))
802*3ac0a46fSAndroid Build Coastguard Worker             {
803*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShortArray(
804*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_YCBCRSUBSAMPLING, 2,
805*3ac0a46fSAndroid Build Coastguard Worker                         &tif->tif_dir.td_ycbcrsubsampling[0]))
806*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
807*3ac0a46fSAndroid Build Coastguard Worker             }
808*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_YCBCRPOSITIONING))
809*3ac0a46fSAndroid Build Coastguard Worker             {
810*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(
811*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_YCBCRPOSITIONING,
812*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_ycbcrpositioning))
813*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
814*3ac0a46fSAndroid Build Coastguard Worker             }
815*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_REFBLACKWHITE))
816*3ac0a46fSAndroid Build Coastguard Worker             {
817*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagRationalArray(
818*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_REFERENCEBLACKWHITE, 6,
819*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_refblackwhite))
820*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
821*3ac0a46fSAndroid Build Coastguard Worker             }
822*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_TRANSFERFUNCTION))
823*3ac0a46fSAndroid Build Coastguard Worker             {
824*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagTransferfunction(tif, &ndir, dir))
825*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
826*3ac0a46fSAndroid Build Coastguard Worker             }
827*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_INKNAMES))
828*3ac0a46fSAndroid Build Coastguard Worker             {
829*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagAscii(
830*3ac0a46fSAndroid Build Coastguard Worker                         tif, &ndir, dir, TIFFTAG_INKNAMES,
831*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_inknameslen, tif->tif_dir.td_inknames))
832*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
833*3ac0a46fSAndroid Build Coastguard Worker             }
834*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
835*3ac0a46fSAndroid Build Coastguard Worker             {
836*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
837*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFTAG_NUMBEROFINKS,
838*3ac0a46fSAndroid Build Coastguard Worker                                                 tif->tif_dir.td_numberofinks))
839*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
840*3ac0a46fSAndroid Build Coastguard Worker             }
841*3ac0a46fSAndroid Build Coastguard Worker             if (TIFFFieldSet(tif, FIELD_SUBIFD))
842*3ac0a46fSAndroid Build Coastguard Worker             {
843*3ac0a46fSAndroid Build Coastguard Worker                 if (!TIFFWriteDirectoryTagSubifd(tif, &ndir, dir))
844*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
845*3ac0a46fSAndroid Build Coastguard Worker             }
846*3ac0a46fSAndroid Build Coastguard Worker             {
847*3ac0a46fSAndroid Build Coastguard Worker                 uint32_t n;
848*3ac0a46fSAndroid Build Coastguard Worker                 for (n = 0; n < tif->tif_nfields; n++)
849*3ac0a46fSAndroid Build Coastguard Worker                 {
850*3ac0a46fSAndroid Build Coastguard Worker                     const TIFFField *o;
851*3ac0a46fSAndroid Build Coastguard Worker                     o = tif->tif_fields[n];
852*3ac0a46fSAndroid Build Coastguard Worker                     if ((o->field_bit >= FIELD_CODEC) &&
853*3ac0a46fSAndroid Build Coastguard Worker                         (TIFFFieldSet(tif, o->field_bit)))
854*3ac0a46fSAndroid Build Coastguard Worker                     {
855*3ac0a46fSAndroid Build Coastguard Worker                         switch (o->get_field_type)
856*3ac0a46fSAndroid Build Coastguard Worker                         {
857*3ac0a46fSAndroid Build Coastguard Worker                             case TIFF_SETGET_ASCII:
858*3ac0a46fSAndroid Build Coastguard Worker                             {
859*3ac0a46fSAndroid Build Coastguard Worker                                 uint32_t pa;
860*3ac0a46fSAndroid Build Coastguard Worker                                 char *pb;
861*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_type == TIFF_ASCII);
862*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_readcount == TIFF_VARIABLE);
863*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_passcount == 0);
864*3ac0a46fSAndroid Build Coastguard Worker                                 TIFFGetField(tif, o->field_tag, &pb);
865*3ac0a46fSAndroid Build Coastguard Worker                                 pa = (uint32_t)(strlen(pb));
866*3ac0a46fSAndroid Build Coastguard Worker                                 if (!TIFFWriteDirectoryTagAscii(
867*3ac0a46fSAndroid Build Coastguard Worker                                         tif, &ndir, dir, (uint16_t)o->field_tag,
868*3ac0a46fSAndroid Build Coastguard Worker                                         pa, pb))
869*3ac0a46fSAndroid Build Coastguard Worker                                     goto bad;
870*3ac0a46fSAndroid Build Coastguard Worker                             }
871*3ac0a46fSAndroid Build Coastguard Worker                             break;
872*3ac0a46fSAndroid Build Coastguard Worker                             case TIFF_SETGET_UINT16:
873*3ac0a46fSAndroid Build Coastguard Worker                             {
874*3ac0a46fSAndroid Build Coastguard Worker                                 uint16_t p;
875*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_type == TIFF_SHORT);
876*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_readcount == 1);
877*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_passcount == 0);
878*3ac0a46fSAndroid Build Coastguard Worker                                 TIFFGetField(tif, o->field_tag, &p);
879*3ac0a46fSAndroid Build Coastguard Worker                                 if (!TIFFWriteDirectoryTagShort(
880*3ac0a46fSAndroid Build Coastguard Worker                                         tif, &ndir, dir, (uint16_t)o->field_tag,
881*3ac0a46fSAndroid Build Coastguard Worker                                         p))
882*3ac0a46fSAndroid Build Coastguard Worker                                     goto bad;
883*3ac0a46fSAndroid Build Coastguard Worker                             }
884*3ac0a46fSAndroid Build Coastguard Worker                             break;
885*3ac0a46fSAndroid Build Coastguard Worker                             case TIFF_SETGET_UINT32:
886*3ac0a46fSAndroid Build Coastguard Worker                             {
887*3ac0a46fSAndroid Build Coastguard Worker                                 uint32_t p;
888*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_type == TIFF_LONG);
889*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_readcount == 1);
890*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_passcount == 0);
891*3ac0a46fSAndroid Build Coastguard Worker                                 TIFFGetField(tif, o->field_tag, &p);
892*3ac0a46fSAndroid Build Coastguard Worker                                 if (!TIFFWriteDirectoryTagLong(
893*3ac0a46fSAndroid Build Coastguard Worker                                         tif, &ndir, dir, (uint16_t)o->field_tag,
894*3ac0a46fSAndroid Build Coastguard Worker                                         p))
895*3ac0a46fSAndroid Build Coastguard Worker                                     goto bad;
896*3ac0a46fSAndroid Build Coastguard Worker                             }
897*3ac0a46fSAndroid Build Coastguard Worker                             break;
898*3ac0a46fSAndroid Build Coastguard Worker                             case TIFF_SETGET_C32_UINT8:
899*3ac0a46fSAndroid Build Coastguard Worker                             {
900*3ac0a46fSAndroid Build Coastguard Worker                                 uint32_t pa;
901*3ac0a46fSAndroid Build Coastguard Worker                                 void *pb;
902*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_type == TIFF_UNDEFINED);
903*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_readcount == TIFF_VARIABLE2);
904*3ac0a46fSAndroid Build Coastguard Worker                                 assert(o->field_passcount == 1);
905*3ac0a46fSAndroid Build Coastguard Worker                                 TIFFGetField(tif, o->field_tag, &pa, &pb);
906*3ac0a46fSAndroid Build Coastguard Worker                                 if (!TIFFWriteDirectoryTagUndefinedArray(
907*3ac0a46fSAndroid Build Coastguard Worker                                         tif, &ndir, dir, (uint16_t)o->field_tag,
908*3ac0a46fSAndroid Build Coastguard Worker                                         pa, pb))
909*3ac0a46fSAndroid Build Coastguard Worker                                     goto bad;
910*3ac0a46fSAndroid Build Coastguard Worker                             }
911*3ac0a46fSAndroid Build Coastguard Worker                             break;
912*3ac0a46fSAndroid Build Coastguard Worker                             default:
913*3ac0a46fSAndroid Build Coastguard Worker                                 TIFFErrorExtR(
914*3ac0a46fSAndroid Build Coastguard Worker                                     tif, module,
915*3ac0a46fSAndroid Build Coastguard Worker                                     "Cannot write tag %" PRIu32 " (%s)",
916*3ac0a46fSAndroid Build Coastguard Worker                                     TIFFFieldTag(o),
917*3ac0a46fSAndroid Build Coastguard Worker                                     o->field_name ? o->field_name : "unknown");
918*3ac0a46fSAndroid Build Coastguard Worker                                 goto bad;
919*3ac0a46fSAndroid Build Coastguard Worker                         }
920*3ac0a46fSAndroid Build Coastguard Worker                     }
921*3ac0a46fSAndroid Build Coastguard Worker                 }
922*3ac0a46fSAndroid Build Coastguard Worker             }
923*3ac0a46fSAndroid Build Coastguard Worker         }
924*3ac0a46fSAndroid Build Coastguard Worker         for (m = 0; m < (uint32_t)(tif->tif_dir.td_customValueCount); m++)
925*3ac0a46fSAndroid Build Coastguard Worker         {
926*3ac0a46fSAndroid Build Coastguard Worker             uint16_t tag =
927*3ac0a46fSAndroid Build Coastguard Worker                 (uint16_t)tif->tif_dir.td_customValues[m].info->field_tag;
928*3ac0a46fSAndroid Build Coastguard Worker             uint32_t count = tif->tif_dir.td_customValues[m].count;
929*3ac0a46fSAndroid Build Coastguard Worker             switch (tif->tif_dir.td_customValues[m].info->field_type)
930*3ac0a46fSAndroid Build Coastguard Worker             {
931*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_ASCII:
932*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagAscii(
933*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
934*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
935*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
936*3ac0a46fSAndroid Build Coastguard Worker                     break;
937*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_UNDEFINED:
938*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagUndefinedArray(
939*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
940*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
941*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
942*3ac0a46fSAndroid Build Coastguard Worker                     break;
943*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_BYTE:
944*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagByteArray(
945*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
946*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
947*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
948*3ac0a46fSAndroid Build Coastguard Worker                     break;
949*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_SBYTE:
950*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagSbyteArray(
951*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
952*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
953*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
954*3ac0a46fSAndroid Build Coastguard Worker                     break;
955*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_SHORT:
956*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagShortArray(
957*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
958*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
959*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
960*3ac0a46fSAndroid Build Coastguard Worker                     break;
961*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_SSHORT:
962*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagSshortArray(
963*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
964*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
965*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
966*3ac0a46fSAndroid Build Coastguard Worker                     break;
967*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_LONG:
968*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagLongArray(
969*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
970*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
971*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
972*3ac0a46fSAndroid Build Coastguard Worker                     break;
973*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_SLONG:
974*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagSlongArray(
975*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
976*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
977*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
978*3ac0a46fSAndroid Build Coastguard Worker                     break;
979*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_LONG8:
980*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagLong8Array(
981*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
982*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
983*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
984*3ac0a46fSAndroid Build Coastguard Worker                     break;
985*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_SLONG8:
986*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagSlong8Array(
987*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
988*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
989*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
990*3ac0a46fSAndroid Build Coastguard Worker                     break;
991*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_RATIONAL:
992*3ac0a46fSAndroid Build Coastguard Worker                 {
993*3ac0a46fSAndroid Build Coastguard Worker                     /*-- Rational2Double: For Rationals evaluate
994*3ac0a46fSAndroid Build Coastguard Worker                      * "set_field_type" to determine internal storage size. */
995*3ac0a46fSAndroid Build Coastguard Worker                     int tv_size;
996*3ac0a46fSAndroid Build Coastguard Worker                     tv_size = TIFFFieldSetGetSize(
997*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_customValues[m].info);
998*3ac0a46fSAndroid Build Coastguard Worker                     if (tv_size == 8)
999*3ac0a46fSAndroid Build Coastguard Worker                     {
1000*3ac0a46fSAndroid Build Coastguard Worker                         if (!TIFFWriteDirectoryTagRationalDoubleArray(
1001*3ac0a46fSAndroid Build Coastguard Worker                                 tif, &ndir, dir, tag, count,
1002*3ac0a46fSAndroid Build Coastguard Worker                                 tif->tif_dir.td_customValues[m].value))
1003*3ac0a46fSAndroid Build Coastguard Worker                             goto bad;
1004*3ac0a46fSAndroid Build Coastguard Worker                     }
1005*3ac0a46fSAndroid Build Coastguard Worker                     else
1006*3ac0a46fSAndroid Build Coastguard Worker                     {
1007*3ac0a46fSAndroid Build Coastguard Worker                         /*-- default should be tv_size == 4 */
1008*3ac0a46fSAndroid Build Coastguard Worker                         if (!TIFFWriteDirectoryTagRationalArray(
1009*3ac0a46fSAndroid Build Coastguard Worker                                 tif, &ndir, dir, tag, count,
1010*3ac0a46fSAndroid Build Coastguard Worker                                 tif->tif_dir.td_customValues[m].value))
1011*3ac0a46fSAndroid Build Coastguard Worker                             goto bad;
1012*3ac0a46fSAndroid Build Coastguard Worker                         /*-- ToDo: After Testing, this should be removed and
1013*3ac0a46fSAndroid Build Coastguard Worker                          * tv_size==4 should be set as default. */
1014*3ac0a46fSAndroid Build Coastguard Worker                         if (tv_size != 4)
1015*3ac0a46fSAndroid Build Coastguard Worker                         {
1016*3ac0a46fSAndroid Build Coastguard Worker                             TIFFErrorExtR(tif,
1017*3ac0a46fSAndroid Build Coastguard Worker                                           "TIFFLib: _TIFFWriteDirectorySec()",
1018*3ac0a46fSAndroid Build Coastguard Worker                                           "Rational2Double: .set_field_type is "
1019*3ac0a46fSAndroid Build Coastguard Worker                                           "not 4 but %d",
1020*3ac0a46fSAndroid Build Coastguard Worker                                           tv_size);
1021*3ac0a46fSAndroid Build Coastguard Worker                         }
1022*3ac0a46fSAndroid Build Coastguard Worker                     }
1023*3ac0a46fSAndroid Build Coastguard Worker                 }
1024*3ac0a46fSAndroid Build Coastguard Worker                 break;
1025*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_SRATIONAL:
1026*3ac0a46fSAndroid Build Coastguard Worker                 {
1027*3ac0a46fSAndroid Build Coastguard Worker                     /*-- Rational2Double: For Rationals evaluate
1028*3ac0a46fSAndroid Build Coastguard Worker                      * "set_field_type" to determine internal storage size. */
1029*3ac0a46fSAndroid Build Coastguard Worker                     int tv_size;
1030*3ac0a46fSAndroid Build Coastguard Worker                     tv_size = TIFFFieldSetGetSize(
1031*3ac0a46fSAndroid Build Coastguard Worker                         tif->tif_dir.td_customValues[m].info);
1032*3ac0a46fSAndroid Build Coastguard Worker                     if (tv_size == 8)
1033*3ac0a46fSAndroid Build Coastguard Worker                     {
1034*3ac0a46fSAndroid Build Coastguard Worker                         if (!TIFFWriteDirectoryTagSrationalDoubleArray(
1035*3ac0a46fSAndroid Build Coastguard Worker                                 tif, &ndir, dir, tag, count,
1036*3ac0a46fSAndroid Build Coastguard Worker                                 tif->tif_dir.td_customValues[m].value))
1037*3ac0a46fSAndroid Build Coastguard Worker                             goto bad;
1038*3ac0a46fSAndroid Build Coastguard Worker                     }
1039*3ac0a46fSAndroid Build Coastguard Worker                     else
1040*3ac0a46fSAndroid Build Coastguard Worker                     {
1041*3ac0a46fSAndroid Build Coastguard Worker                         /*-- default should be tv_size == 4 */
1042*3ac0a46fSAndroid Build Coastguard Worker                         if (!TIFFWriteDirectoryTagSrationalArray(
1043*3ac0a46fSAndroid Build Coastguard Worker                                 tif, &ndir, dir, tag, count,
1044*3ac0a46fSAndroid Build Coastguard Worker                                 tif->tif_dir.td_customValues[m].value))
1045*3ac0a46fSAndroid Build Coastguard Worker                             goto bad;
1046*3ac0a46fSAndroid Build Coastguard Worker                         /*-- ToDo: After Testing, this should be removed and
1047*3ac0a46fSAndroid Build Coastguard Worker                          * tv_size==4 should be set as default. */
1048*3ac0a46fSAndroid Build Coastguard Worker                         if (tv_size != 4)
1049*3ac0a46fSAndroid Build Coastguard Worker                         {
1050*3ac0a46fSAndroid Build Coastguard Worker                             TIFFErrorExtR(tif,
1051*3ac0a46fSAndroid Build Coastguard Worker                                           "TIFFLib: _TIFFWriteDirectorySec()",
1052*3ac0a46fSAndroid Build Coastguard Worker                                           "Rational2Double: .set_field_type is "
1053*3ac0a46fSAndroid Build Coastguard Worker                                           "not 4 but %d",
1054*3ac0a46fSAndroid Build Coastguard Worker                                           tv_size);
1055*3ac0a46fSAndroid Build Coastguard Worker                         }
1056*3ac0a46fSAndroid Build Coastguard Worker                     }
1057*3ac0a46fSAndroid Build Coastguard Worker                 }
1058*3ac0a46fSAndroid Build Coastguard Worker                 break;
1059*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_FLOAT:
1060*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagFloatArray(
1061*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
1062*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
1063*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
1064*3ac0a46fSAndroid Build Coastguard Worker                     break;
1065*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_DOUBLE:
1066*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagDoubleArray(
1067*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
1068*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
1069*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
1070*3ac0a46fSAndroid Build Coastguard Worker                     break;
1071*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_IFD:
1072*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagIfdArray(
1073*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
1074*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
1075*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
1076*3ac0a46fSAndroid Build Coastguard Worker                     break;
1077*3ac0a46fSAndroid Build Coastguard Worker                 case TIFF_IFD8:
1078*3ac0a46fSAndroid Build Coastguard Worker                     if (!TIFFWriteDirectoryTagIfdIfd8Array(
1079*3ac0a46fSAndroid Build Coastguard Worker                             tif, &ndir, dir, tag, count,
1080*3ac0a46fSAndroid Build Coastguard Worker                             tif->tif_dir.td_customValues[m].value))
1081*3ac0a46fSAndroid Build Coastguard Worker                         goto bad;
1082*3ac0a46fSAndroid Build Coastguard Worker                     break;
1083*3ac0a46fSAndroid Build Coastguard Worker                 default:
1084*3ac0a46fSAndroid Build Coastguard Worker                     assert(0); /* we should never get here */
1085*3ac0a46fSAndroid Build Coastguard Worker                     break;
1086*3ac0a46fSAndroid Build Coastguard Worker             }
1087*3ac0a46fSAndroid Build Coastguard Worker         }
1088*3ac0a46fSAndroid Build Coastguard Worker         if (dir != NULL)
1089*3ac0a46fSAndroid Build Coastguard Worker             break;
1090*3ac0a46fSAndroid Build Coastguard Worker         dir = _TIFFmallocExt(tif, ndir * sizeof(TIFFDirEntry));
1091*3ac0a46fSAndroid Build Coastguard Worker         if (dir == NULL)
1092*3ac0a46fSAndroid Build Coastguard Worker         {
1093*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Out of memory");
1094*3ac0a46fSAndroid Build Coastguard Worker             goto bad;
1095*3ac0a46fSAndroid Build Coastguard Worker         }
1096*3ac0a46fSAndroid Build Coastguard Worker         if (isimage)
1097*3ac0a46fSAndroid Build Coastguard Worker         {
1098*3ac0a46fSAndroid Build Coastguard Worker             if ((tif->tif_diroff == 0) && (!TIFFLinkDirectory(tif)))
1099*3ac0a46fSAndroid Build Coastguard Worker                 goto bad;
1100*3ac0a46fSAndroid Build Coastguard Worker         }
1101*3ac0a46fSAndroid Build Coastguard Worker         else
1102*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_diroff =
1103*3ac0a46fSAndroid Build Coastguard Worker                 (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1));
1104*3ac0a46fSAndroid Build Coastguard Worker         if (pdiroff != NULL)
1105*3ac0a46fSAndroid Build Coastguard Worker             *pdiroff = tif->tif_diroff;
1106*3ac0a46fSAndroid Build Coastguard Worker         if (!(tif->tif_flags & TIFF_BIGTIFF))
1107*3ac0a46fSAndroid Build Coastguard Worker             dirsize = 2 + ndir * 12 + 4;
1108*3ac0a46fSAndroid Build Coastguard Worker         else
1109*3ac0a46fSAndroid Build Coastguard Worker             dirsize = 8 + ndir * 20 + 8;
1110*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dataoff = tif->tif_diroff + dirsize;
1111*3ac0a46fSAndroid Build Coastguard Worker         if (!(tif->tif_flags & TIFF_BIGTIFF))
1112*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_dataoff = (uint32_t)tif->tif_dataoff;
1113*3ac0a46fSAndroid Build Coastguard Worker         if ((tif->tif_dataoff < tif->tif_diroff) ||
1114*3ac0a46fSAndroid Build Coastguard Worker             (tif->tif_dataoff < (uint64_t)dirsize))
1115*3ac0a46fSAndroid Build Coastguard Worker         {
1116*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
1117*3ac0a46fSAndroid Build Coastguard Worker             goto bad;
1118*3ac0a46fSAndroid Build Coastguard Worker         }
1119*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_dataoff & 1)
1120*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_dataoff++;
1121*3ac0a46fSAndroid Build Coastguard Worker         if (isimage)
1122*3ac0a46fSAndroid Build Coastguard Worker         {
1123*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
1124*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_curdir = 0;
1125*3ac0a46fSAndroid Build Coastguard Worker             else
1126*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_curdir++;
1127*3ac0a46fSAndroid Build Coastguard Worker         }
1128*3ac0a46fSAndroid Build Coastguard Worker     }
1129*3ac0a46fSAndroid Build Coastguard Worker     if (isimage)
1130*3ac0a46fSAndroid Build Coastguard Worker     {
1131*3ac0a46fSAndroid Build Coastguard Worker         if (TIFFFieldSet(tif, FIELD_SUBIFD) && (tif->tif_subifdoff == 0))
1132*3ac0a46fSAndroid Build Coastguard Worker         {
1133*3ac0a46fSAndroid Build Coastguard Worker             uint32_t na;
1134*3ac0a46fSAndroid Build Coastguard Worker             TIFFDirEntry *nb;
1135*3ac0a46fSAndroid Build Coastguard Worker             for (na = 0, nb = dir;; na++, nb++)
1136*3ac0a46fSAndroid Build Coastguard Worker             {
1137*3ac0a46fSAndroid Build Coastguard Worker                 if (na == ndir)
1138*3ac0a46fSAndroid Build Coastguard Worker                 {
1139*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module, "Cannot find SubIFD tag");
1140*3ac0a46fSAndroid Build Coastguard Worker                     goto bad;
1141*3ac0a46fSAndroid Build Coastguard Worker                 }
1142*3ac0a46fSAndroid Build Coastguard Worker                 if (nb->tdir_tag == TIFFTAG_SUBIFD)
1143*3ac0a46fSAndroid Build Coastguard Worker                     break;
1144*3ac0a46fSAndroid Build Coastguard Worker             }
1145*3ac0a46fSAndroid Build Coastguard Worker             if (!(tif->tif_flags & TIFF_BIGTIFF))
1146*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_subifdoff = tif->tif_diroff + 2 + na * 12 + 8;
1147*3ac0a46fSAndroid Build Coastguard Worker             else
1148*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_subifdoff = tif->tif_diroff + 8 + na * 20 + 12;
1149*3ac0a46fSAndroid Build Coastguard Worker         }
1150*3ac0a46fSAndroid Build Coastguard Worker     }
1151*3ac0a46fSAndroid Build Coastguard Worker     dirmem = _TIFFmallocExt(tif, dirsize);
1152*3ac0a46fSAndroid Build Coastguard Worker     if (dirmem == NULL)
1153*3ac0a46fSAndroid Build Coastguard Worker     {
1154*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
1155*3ac0a46fSAndroid Build Coastguard Worker         goto bad;
1156*3ac0a46fSAndroid Build Coastguard Worker     }
1157*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
1158*3ac0a46fSAndroid Build Coastguard Worker     {
1159*3ac0a46fSAndroid Build Coastguard Worker         uint8_t *n;
1160*3ac0a46fSAndroid Build Coastguard Worker         uint32_t nTmp;
1161*3ac0a46fSAndroid Build Coastguard Worker         TIFFDirEntry *o;
1162*3ac0a46fSAndroid Build Coastguard Worker         n = dirmem;
1163*3ac0a46fSAndroid Build Coastguard Worker         *(uint16_t *)n = (uint16_t)ndir;
1164*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
1165*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabShort((uint16_t *)n);
1166*3ac0a46fSAndroid Build Coastguard Worker         n += 2;
1167*3ac0a46fSAndroid Build Coastguard Worker         o = dir;
1168*3ac0a46fSAndroid Build Coastguard Worker         for (m = 0; m < ndir; m++)
1169*3ac0a46fSAndroid Build Coastguard Worker         {
1170*3ac0a46fSAndroid Build Coastguard Worker             *(uint16_t *)n = o->tdir_tag;
1171*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
1172*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabShort((uint16_t *)n);
1173*3ac0a46fSAndroid Build Coastguard Worker             n += 2;
1174*3ac0a46fSAndroid Build Coastguard Worker             *(uint16_t *)n = o->tdir_type;
1175*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
1176*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabShort((uint16_t *)n);
1177*3ac0a46fSAndroid Build Coastguard Worker             n += 2;
1178*3ac0a46fSAndroid Build Coastguard Worker             nTmp = (uint32_t)o->tdir_count;
1179*3ac0a46fSAndroid Build Coastguard Worker             _TIFFmemcpy(n, &nTmp, 4);
1180*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
1181*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong((uint32_t *)n);
1182*3ac0a46fSAndroid Build Coastguard Worker             n += 4;
1183*3ac0a46fSAndroid Build Coastguard Worker             /* This is correct. The data has been */
1184*3ac0a46fSAndroid Build Coastguard Worker             /* swabbed previously in TIFFWriteDirectoryTagData */
1185*3ac0a46fSAndroid Build Coastguard Worker             _TIFFmemcpy(n, &o->tdir_offset, 4);
1186*3ac0a46fSAndroid Build Coastguard Worker             n += 4;
1187*3ac0a46fSAndroid Build Coastguard Worker             o++;
1188*3ac0a46fSAndroid Build Coastguard Worker         }
1189*3ac0a46fSAndroid Build Coastguard Worker         nTmp = (uint32_t)tif->tif_nextdiroff;
1190*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
1191*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong(&nTmp);
1192*3ac0a46fSAndroid Build Coastguard Worker         _TIFFmemcpy(n, &nTmp, 4);
1193*3ac0a46fSAndroid Build Coastguard Worker     }
1194*3ac0a46fSAndroid Build Coastguard Worker     else
1195*3ac0a46fSAndroid Build Coastguard Worker     {
1196*3ac0a46fSAndroid Build Coastguard Worker         uint8_t *n;
1197*3ac0a46fSAndroid Build Coastguard Worker         TIFFDirEntry *o;
1198*3ac0a46fSAndroid Build Coastguard Worker         n = dirmem;
1199*3ac0a46fSAndroid Build Coastguard Worker         *(uint64_t *)n = ndir;
1200*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
1201*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8((uint64_t *)n);
1202*3ac0a46fSAndroid Build Coastguard Worker         n += 8;
1203*3ac0a46fSAndroid Build Coastguard Worker         o = dir;
1204*3ac0a46fSAndroid Build Coastguard Worker         for (m = 0; m < ndir; m++)
1205*3ac0a46fSAndroid Build Coastguard Worker         {
1206*3ac0a46fSAndroid Build Coastguard Worker             *(uint16_t *)n = o->tdir_tag;
1207*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
1208*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabShort((uint16_t *)n);
1209*3ac0a46fSAndroid Build Coastguard Worker             n += 2;
1210*3ac0a46fSAndroid Build Coastguard Worker             *(uint16_t *)n = o->tdir_type;
1211*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
1212*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabShort((uint16_t *)n);
1213*3ac0a46fSAndroid Build Coastguard Worker             n += 2;
1214*3ac0a46fSAndroid Build Coastguard Worker             _TIFFmemcpy(n, &o->tdir_count, 8);
1215*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
1216*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong8((uint64_t *)n);
1217*3ac0a46fSAndroid Build Coastguard Worker             n += 8;
1218*3ac0a46fSAndroid Build Coastguard Worker             _TIFFmemcpy(n, &o->tdir_offset, 8);
1219*3ac0a46fSAndroid Build Coastguard Worker             n += 8;
1220*3ac0a46fSAndroid Build Coastguard Worker             o++;
1221*3ac0a46fSAndroid Build Coastguard Worker         }
1222*3ac0a46fSAndroid Build Coastguard Worker         _TIFFmemcpy(n, &tif->tif_nextdiroff, 8);
1223*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
1224*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8((uint64_t *)n);
1225*3ac0a46fSAndroid Build Coastguard Worker     }
1226*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, dir);
1227*3ac0a46fSAndroid Build Coastguard Worker     dir = NULL;
1228*3ac0a46fSAndroid Build Coastguard Worker     if (!SeekOK(tif, tif->tif_diroff))
1229*3ac0a46fSAndroid Build Coastguard Worker     {
1230*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "IO error writing directory");
1231*3ac0a46fSAndroid Build Coastguard Worker         goto bad;
1232*3ac0a46fSAndroid Build Coastguard Worker     }
1233*3ac0a46fSAndroid Build Coastguard Worker     if (!WriteOK(tif, dirmem, (tmsize_t)dirsize))
1234*3ac0a46fSAndroid Build Coastguard Worker     {
1235*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "IO error writing directory");
1236*3ac0a46fSAndroid Build Coastguard Worker         goto bad;
1237*3ac0a46fSAndroid Build Coastguard Worker     }
1238*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, dirmem);
1239*3ac0a46fSAndroid Build Coastguard Worker     if (imagedone)
1240*3ac0a46fSAndroid Build Coastguard Worker     {
1241*3ac0a46fSAndroid Build Coastguard Worker         TIFFFreeDirectory(tif);
1242*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_flags &= ~TIFF_DIRTYDIRECT;
1243*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_flags &= ~TIFF_DIRTYSTRIP;
1244*3ac0a46fSAndroid Build Coastguard Worker         (*tif->tif_cleanup)(tif);
1245*3ac0a46fSAndroid Build Coastguard Worker         /*
1246*3ac0a46fSAndroid Build Coastguard Worker          * Reset directory-related state for subsequent
1247*3ac0a46fSAndroid Build Coastguard Worker          * directories.
1248*3ac0a46fSAndroid Build Coastguard Worker          */
1249*3ac0a46fSAndroid Build Coastguard Worker         TIFFCreateDirectory(tif);
1250*3ac0a46fSAndroid Build Coastguard Worker     }
1251*3ac0a46fSAndroid Build Coastguard Worker     return (1);
1252*3ac0a46fSAndroid Build Coastguard Worker bad:
1253*3ac0a46fSAndroid Build Coastguard Worker     if (dir != NULL)
1254*3ac0a46fSAndroid Build Coastguard Worker         _TIFFfreeExt(tif, dir);
1255*3ac0a46fSAndroid Build Coastguard Worker     if (dirmem != NULL)
1256*3ac0a46fSAndroid Build Coastguard Worker         _TIFFfreeExt(tif, dirmem);
1257*3ac0a46fSAndroid Build Coastguard Worker     return (0);
1258*3ac0a46fSAndroid Build Coastguard Worker }
1259*3ac0a46fSAndroid Build Coastguard Worker 
TIFFClampDoubleToInt8(double val)1260*3ac0a46fSAndroid Build Coastguard Worker static int8_t TIFFClampDoubleToInt8(double val)
1261*3ac0a46fSAndroid Build Coastguard Worker {
1262*3ac0a46fSAndroid Build Coastguard Worker     if (val > 127)
1263*3ac0a46fSAndroid Build Coastguard Worker         return 127;
1264*3ac0a46fSAndroid Build Coastguard Worker     if (val < -128 || val != val)
1265*3ac0a46fSAndroid Build Coastguard Worker         return -128;
1266*3ac0a46fSAndroid Build Coastguard Worker     return (int8_t)val;
1267*3ac0a46fSAndroid Build Coastguard Worker }
1268*3ac0a46fSAndroid Build Coastguard Worker 
TIFFClampDoubleToInt16(double val)1269*3ac0a46fSAndroid Build Coastguard Worker static int16_t TIFFClampDoubleToInt16(double val)
1270*3ac0a46fSAndroid Build Coastguard Worker {
1271*3ac0a46fSAndroid Build Coastguard Worker     if (val > 32767)
1272*3ac0a46fSAndroid Build Coastguard Worker         return 32767;
1273*3ac0a46fSAndroid Build Coastguard Worker     if (val < -32768 || val != val)
1274*3ac0a46fSAndroid Build Coastguard Worker         return -32768;
1275*3ac0a46fSAndroid Build Coastguard Worker     return (int16_t)val;
1276*3ac0a46fSAndroid Build Coastguard Worker }
1277*3ac0a46fSAndroid Build Coastguard Worker 
TIFFClampDoubleToInt32(double val)1278*3ac0a46fSAndroid Build Coastguard Worker static int32_t TIFFClampDoubleToInt32(double val)
1279*3ac0a46fSAndroid Build Coastguard Worker {
1280*3ac0a46fSAndroid Build Coastguard Worker     if (val > 0x7FFFFFFF)
1281*3ac0a46fSAndroid Build Coastguard Worker         return 0x7FFFFFFF;
1282*3ac0a46fSAndroid Build Coastguard Worker     if (val < -0x7FFFFFFF - 1 || val != val)
1283*3ac0a46fSAndroid Build Coastguard Worker         return -0x7FFFFFFF - 1;
1284*3ac0a46fSAndroid Build Coastguard Worker     return (int32_t)val;
1285*3ac0a46fSAndroid Build Coastguard Worker }
1286*3ac0a46fSAndroid Build Coastguard Worker 
TIFFClampDoubleToUInt8(double val)1287*3ac0a46fSAndroid Build Coastguard Worker static uint8_t TIFFClampDoubleToUInt8(double val)
1288*3ac0a46fSAndroid Build Coastguard Worker {
1289*3ac0a46fSAndroid Build Coastguard Worker     if (val < 0)
1290*3ac0a46fSAndroid Build Coastguard Worker         return 0;
1291*3ac0a46fSAndroid Build Coastguard Worker     if (val > 255 || val != val)
1292*3ac0a46fSAndroid Build Coastguard Worker         return 255;
1293*3ac0a46fSAndroid Build Coastguard Worker     return (uint8_t)val;
1294*3ac0a46fSAndroid Build Coastguard Worker }
1295*3ac0a46fSAndroid Build Coastguard Worker 
TIFFClampDoubleToUInt16(double val)1296*3ac0a46fSAndroid Build Coastguard Worker static uint16_t TIFFClampDoubleToUInt16(double val)
1297*3ac0a46fSAndroid Build Coastguard Worker {
1298*3ac0a46fSAndroid Build Coastguard Worker     if (val < 0)
1299*3ac0a46fSAndroid Build Coastguard Worker         return 0;
1300*3ac0a46fSAndroid Build Coastguard Worker     if (val > 65535 || val != val)
1301*3ac0a46fSAndroid Build Coastguard Worker         return 65535;
1302*3ac0a46fSAndroid Build Coastguard Worker     return (uint16_t)val;
1303*3ac0a46fSAndroid Build Coastguard Worker }
1304*3ac0a46fSAndroid Build Coastguard Worker 
TIFFClampDoubleToUInt32(double val)1305*3ac0a46fSAndroid Build Coastguard Worker static uint32_t TIFFClampDoubleToUInt32(double val)
1306*3ac0a46fSAndroid Build Coastguard Worker {
1307*3ac0a46fSAndroid Build Coastguard Worker     if (val < 0)
1308*3ac0a46fSAndroid Build Coastguard Worker         return 0;
1309*3ac0a46fSAndroid Build Coastguard Worker     if (val > 0xFFFFFFFFU || val != val)
1310*3ac0a46fSAndroid Build Coastguard Worker         return 0xFFFFFFFFU;
1311*3ac0a46fSAndroid Build Coastguard Worker     return (uint32_t)val;
1312*3ac0a46fSAndroid Build Coastguard Worker }
1313*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSampleformatArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)1314*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSampleformatArray(TIFF *tif, uint32_t *ndir,
1315*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
1316*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
1317*3ac0a46fSAndroid Build Coastguard Worker                                                   double *value)
1318*3ac0a46fSAndroid Build Coastguard Worker {
1319*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagSampleformatArray";
1320*3ac0a46fSAndroid Build Coastguard Worker     void *conv;
1321*3ac0a46fSAndroid Build Coastguard Worker     uint32_t i;
1322*3ac0a46fSAndroid Build Coastguard Worker     int ok;
1323*3ac0a46fSAndroid Build Coastguard Worker     conv = _TIFFmallocExt(tif, count * sizeof(double));
1324*3ac0a46fSAndroid Build Coastguard Worker     if (conv == NULL)
1325*3ac0a46fSAndroid Build Coastguard Worker     {
1326*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
1327*3ac0a46fSAndroid Build Coastguard Worker         return (0);
1328*3ac0a46fSAndroid Build Coastguard Worker     }
1329*3ac0a46fSAndroid Build Coastguard Worker 
1330*3ac0a46fSAndroid Build Coastguard Worker     switch (tif->tif_dir.td_sampleformat)
1331*3ac0a46fSAndroid Build Coastguard Worker     {
1332*3ac0a46fSAndroid Build Coastguard Worker         case SAMPLEFORMAT_IEEEFP:
1333*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_dir.td_bitspersample <= 32)
1334*3ac0a46fSAndroid Build Coastguard Worker             {
1335*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1336*3ac0a46fSAndroid Build Coastguard Worker                     ((float *)conv)[i] = _TIFFClampDoubleToFloat(value[i]);
1337*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagFloatArray(tif, ndir, dir, tag, count,
1338*3ac0a46fSAndroid Build Coastguard Worker                                                      (float *)conv);
1339*3ac0a46fSAndroid Build Coastguard Worker             }
1340*3ac0a46fSAndroid Build Coastguard Worker             else
1341*3ac0a46fSAndroid Build Coastguard Worker             {
1342*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagDoubleArray(tif, ndir, dir, tag,
1343*3ac0a46fSAndroid Build Coastguard Worker                                                       count, value);
1344*3ac0a46fSAndroid Build Coastguard Worker             }
1345*3ac0a46fSAndroid Build Coastguard Worker             break;
1346*3ac0a46fSAndroid Build Coastguard Worker         case SAMPLEFORMAT_INT:
1347*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_dir.td_bitspersample <= 8)
1348*3ac0a46fSAndroid Build Coastguard Worker             {
1349*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1350*3ac0a46fSAndroid Build Coastguard Worker                     ((int8_t *)conv)[i] = TIFFClampDoubleToInt8(value[i]);
1351*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagSbyteArray(tif, ndir, dir, tag, count,
1352*3ac0a46fSAndroid Build Coastguard Worker                                                      (int8_t *)conv);
1353*3ac0a46fSAndroid Build Coastguard Worker             }
1354*3ac0a46fSAndroid Build Coastguard Worker             else if (tif->tif_dir.td_bitspersample <= 16)
1355*3ac0a46fSAndroid Build Coastguard Worker             {
1356*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1357*3ac0a46fSAndroid Build Coastguard Worker                     ((int16_t *)conv)[i] = TIFFClampDoubleToInt16(value[i]);
1358*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagSshortArray(tif, ndir, dir, tag,
1359*3ac0a46fSAndroid Build Coastguard Worker                                                       count, (int16_t *)conv);
1360*3ac0a46fSAndroid Build Coastguard Worker             }
1361*3ac0a46fSAndroid Build Coastguard Worker             else
1362*3ac0a46fSAndroid Build Coastguard Worker             {
1363*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1364*3ac0a46fSAndroid Build Coastguard Worker                     ((int32_t *)conv)[i] = TIFFClampDoubleToInt32(value[i]);
1365*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagSlongArray(tif, ndir, dir, tag, count,
1366*3ac0a46fSAndroid Build Coastguard Worker                                                      (int32_t *)conv);
1367*3ac0a46fSAndroid Build Coastguard Worker             }
1368*3ac0a46fSAndroid Build Coastguard Worker             break;
1369*3ac0a46fSAndroid Build Coastguard Worker         case SAMPLEFORMAT_UINT:
1370*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_dir.td_bitspersample <= 8)
1371*3ac0a46fSAndroid Build Coastguard Worker             {
1372*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1373*3ac0a46fSAndroid Build Coastguard Worker                     ((uint8_t *)conv)[i] = TIFFClampDoubleToUInt8(value[i]);
1374*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagByteArray(tif, ndir, dir, tag, count,
1375*3ac0a46fSAndroid Build Coastguard Worker                                                     (uint8_t *)conv);
1376*3ac0a46fSAndroid Build Coastguard Worker             }
1377*3ac0a46fSAndroid Build Coastguard Worker             else if (tif->tif_dir.td_bitspersample <= 16)
1378*3ac0a46fSAndroid Build Coastguard Worker             {
1379*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1380*3ac0a46fSAndroid Build Coastguard Worker                     ((uint16_t *)conv)[i] = TIFFClampDoubleToUInt16(value[i]);
1381*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagShortArray(tif, ndir, dir, tag, count,
1382*3ac0a46fSAndroid Build Coastguard Worker                                                      (uint16_t *)conv);
1383*3ac0a46fSAndroid Build Coastguard Worker             }
1384*3ac0a46fSAndroid Build Coastguard Worker             else
1385*3ac0a46fSAndroid Build Coastguard Worker             {
1386*3ac0a46fSAndroid Build Coastguard Worker                 for (i = 0; i < count; ++i)
1387*3ac0a46fSAndroid Build Coastguard Worker                     ((uint32_t *)conv)[i] = TIFFClampDoubleToUInt32(value[i]);
1388*3ac0a46fSAndroid Build Coastguard Worker                 ok = TIFFWriteDirectoryTagLongArray(tif, ndir, dir, tag, count,
1389*3ac0a46fSAndroid Build Coastguard Worker                                                     (uint32_t *)conv);
1390*3ac0a46fSAndroid Build Coastguard Worker             }
1391*3ac0a46fSAndroid Build Coastguard Worker             break;
1392*3ac0a46fSAndroid Build Coastguard Worker         default:
1393*3ac0a46fSAndroid Build Coastguard Worker             ok = 0;
1394*3ac0a46fSAndroid Build Coastguard Worker     }
1395*3ac0a46fSAndroid Build Coastguard Worker 
1396*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, conv);
1397*3ac0a46fSAndroid Build Coastguard Worker     return (ok);
1398*3ac0a46fSAndroid Build Coastguard Worker }
1399*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagAscii(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,char * value)1400*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagAscii(TIFF *tif, uint32_t *ndir,
1401*3ac0a46fSAndroid Build Coastguard Worker                                       TIFFDirEntry *dir, uint16_t tag,
1402*3ac0a46fSAndroid Build Coastguard Worker                                       uint32_t count, char *value)
1403*3ac0a46fSAndroid Build Coastguard Worker {
1404*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1405*3ac0a46fSAndroid Build Coastguard Worker     {
1406*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1407*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1408*3ac0a46fSAndroid Build Coastguard Worker     }
1409*3ac0a46fSAndroid Build Coastguard Worker     return (
1410*3ac0a46fSAndroid Build Coastguard Worker         TIFFWriteDirectoryTagCheckedAscii(tif, ndir, dir, tag, count, value));
1411*3ac0a46fSAndroid Build Coastguard Worker }
1412*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagUndefinedArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint8_t * value)1413*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagUndefinedArray(TIFF *tif, uint32_t *ndir,
1414*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
1415*3ac0a46fSAndroid Build Coastguard Worker                                                uint32_t count, uint8_t *value)
1416*3ac0a46fSAndroid Build Coastguard Worker {
1417*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1418*3ac0a46fSAndroid Build Coastguard Worker     {
1419*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1420*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1421*3ac0a46fSAndroid Build Coastguard Worker     }
1422*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedUndefinedArray(tif, ndir, dir, tag,
1423*3ac0a46fSAndroid Build Coastguard Worker                                                        count, value));
1424*3ac0a46fSAndroid Build Coastguard Worker }
1425*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagByteArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint8_t * value)1426*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagByteArray(TIFF *tif, uint32_t *ndir,
1427*3ac0a46fSAndroid Build Coastguard Worker                                           TIFFDirEntry *dir, uint16_t tag,
1428*3ac0a46fSAndroid Build Coastguard Worker                                           uint32_t count, uint8_t *value)
1429*3ac0a46fSAndroid Build Coastguard Worker {
1430*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1431*3ac0a46fSAndroid Build Coastguard Worker     {
1432*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1433*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1434*3ac0a46fSAndroid Build Coastguard Worker     }
1435*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedByteArray(tif, ndir, dir, tag, count,
1436*3ac0a46fSAndroid Build Coastguard Worker                                                   value));
1437*3ac0a46fSAndroid Build Coastguard Worker }
1438*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSbyteArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int8_t * value)1439*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSbyteArray(TIFF *tif, uint32_t *ndir,
1440*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
1441*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, int8_t *value)
1442*3ac0a46fSAndroid Build Coastguard Worker {
1443*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1444*3ac0a46fSAndroid Build Coastguard Worker     {
1445*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1446*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1447*3ac0a46fSAndroid Build Coastguard Worker     }
1448*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedSbyteArray(tif, ndir, dir, tag, count,
1449*3ac0a46fSAndroid Build Coastguard Worker                                                    value));
1450*3ac0a46fSAndroid Build Coastguard Worker }
1451*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagShort(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint16_t value)1452*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShort(TIFF *tif, uint32_t *ndir,
1453*3ac0a46fSAndroid Build Coastguard Worker                                       TIFFDirEntry *dir, uint16_t tag,
1454*3ac0a46fSAndroid Build Coastguard Worker                                       uint16_t value)
1455*3ac0a46fSAndroid Build Coastguard Worker {
1456*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1457*3ac0a46fSAndroid Build Coastguard Worker     {
1458*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1459*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1460*3ac0a46fSAndroid Build Coastguard Worker     }
1461*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag, value));
1462*3ac0a46fSAndroid Build Coastguard Worker }
1463*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagShortArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint16_t * value)1464*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShortArray(TIFF *tif, uint32_t *ndir,
1465*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
1466*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, uint16_t *value)
1467*3ac0a46fSAndroid Build Coastguard Worker {
1468*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1469*3ac0a46fSAndroid Build Coastguard Worker     {
1470*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1471*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1472*3ac0a46fSAndroid Build Coastguard Worker     }
1473*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, tag, count,
1474*3ac0a46fSAndroid Build Coastguard Worker                                                    value));
1475*3ac0a46fSAndroid Build Coastguard Worker }
1476*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagShortPerSample(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint16_t value)1477*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShortPerSample(TIFF *tif, uint32_t *ndir,
1478*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
1479*3ac0a46fSAndroid Build Coastguard Worker                                                uint16_t value)
1480*3ac0a46fSAndroid Build Coastguard Worker {
1481*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagShortPerSample";
1482*3ac0a46fSAndroid Build Coastguard Worker     uint16_t *m;
1483*3ac0a46fSAndroid Build Coastguard Worker     uint16_t *na;
1484*3ac0a46fSAndroid Build Coastguard Worker     uint16_t nb;
1485*3ac0a46fSAndroid Build Coastguard Worker     int o;
1486*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1487*3ac0a46fSAndroid Build Coastguard Worker     {
1488*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1489*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1490*3ac0a46fSAndroid Build Coastguard Worker     }
1491*3ac0a46fSAndroid Build Coastguard Worker     m = _TIFFmallocExt(tif, tif->tif_dir.td_samplesperpixel * sizeof(uint16_t));
1492*3ac0a46fSAndroid Build Coastguard Worker     if (m == NULL)
1493*3ac0a46fSAndroid Build Coastguard Worker     {
1494*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
1495*3ac0a46fSAndroid Build Coastguard Worker         return (0);
1496*3ac0a46fSAndroid Build Coastguard Worker     }
1497*3ac0a46fSAndroid Build Coastguard Worker     for (na = m, nb = 0; nb < tif->tif_dir.td_samplesperpixel; na++, nb++)
1498*3ac0a46fSAndroid Build Coastguard Worker         *na = value;
1499*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagCheckedShortArray(
1500*3ac0a46fSAndroid Build Coastguard Worker         tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, m);
1501*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, m);
1502*3ac0a46fSAndroid Build Coastguard Worker     return (o);
1503*3ac0a46fSAndroid Build Coastguard Worker }
1504*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSshortArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int16_t * value)1505*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSshortArray(TIFF *tif, uint32_t *ndir,
1506*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
1507*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t count, int16_t *value)
1508*3ac0a46fSAndroid Build Coastguard Worker {
1509*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1510*3ac0a46fSAndroid Build Coastguard Worker     {
1511*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1512*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1513*3ac0a46fSAndroid Build Coastguard Worker     }
1514*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedSshortArray(tif, ndir, dir, tag, count,
1515*3ac0a46fSAndroid Build Coastguard Worker                                                     value));
1516*3ac0a46fSAndroid Build Coastguard Worker }
1517*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagLong(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t value)1518*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLong(TIFF *tif, uint32_t *ndir,
1519*3ac0a46fSAndroid Build Coastguard Worker                                      TIFFDirEntry *dir, uint16_t tag,
1520*3ac0a46fSAndroid Build Coastguard Worker                                      uint32_t value)
1521*3ac0a46fSAndroid Build Coastguard Worker {
1522*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1523*3ac0a46fSAndroid Build Coastguard Worker     {
1524*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1525*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1526*3ac0a46fSAndroid Build Coastguard Worker     }
1527*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedLong(tif, ndir, dir, tag, value));
1528*3ac0a46fSAndroid Build Coastguard Worker }
1529*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagLongArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint32_t * value)1530*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLongArray(TIFF *tif, uint32_t *ndir,
1531*3ac0a46fSAndroid Build Coastguard Worker                                           TIFFDirEntry *dir, uint16_t tag,
1532*3ac0a46fSAndroid Build Coastguard Worker                                           uint32_t count, uint32_t *value)
1533*3ac0a46fSAndroid Build Coastguard Worker {
1534*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1535*3ac0a46fSAndroid Build Coastguard Worker     {
1536*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1537*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1538*3ac0a46fSAndroid Build Coastguard Worker     }
1539*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count,
1540*3ac0a46fSAndroid Build Coastguard Worker                                                   value));
1541*3ac0a46fSAndroid Build Coastguard Worker }
1542*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSlongArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int32_t * value)1543*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSlongArray(TIFF *tif, uint32_t *ndir,
1544*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
1545*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, int32_t *value)
1546*3ac0a46fSAndroid Build Coastguard Worker {
1547*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1548*3ac0a46fSAndroid Build Coastguard Worker     {
1549*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1550*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1551*3ac0a46fSAndroid Build Coastguard Worker     }
1552*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedSlongArray(tif, ndir, dir, tag, count,
1553*3ac0a46fSAndroid Build Coastguard Worker                                                    value));
1554*3ac0a46fSAndroid Build Coastguard Worker }
1555*3ac0a46fSAndroid Build Coastguard Worker 
1556*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
1557*3ac0a46fSAndroid Build Coastguard Worker /*                 TIFFWriteDirectoryTagLong8Array()                    */
1558*3ac0a46fSAndroid Build Coastguard Worker /*                                                                      */
1559*3ac0a46fSAndroid Build Coastguard Worker /*      Write either Long8 or Long array depending on file type.        */
1560*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
TIFFWriteDirectoryTagLong8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint64_t * value)1561*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir,
1562*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
1563*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, uint64_t *value)
1564*3ac0a46fSAndroid Build Coastguard Worker {
1565*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagLong8Array";
1566*3ac0a46fSAndroid Build Coastguard Worker     uint64_t *ma;
1567*3ac0a46fSAndroid Build Coastguard Worker     uint32_t mb;
1568*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *p;
1569*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *q;
1570*3ac0a46fSAndroid Build Coastguard Worker     int o;
1571*3ac0a46fSAndroid Build Coastguard Worker 
1572*3ac0a46fSAndroid Build Coastguard Worker     /* is this just a counting pass? */
1573*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1574*3ac0a46fSAndroid Build Coastguard Worker     {
1575*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1576*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1577*3ac0a46fSAndroid Build Coastguard Worker     }
1578*3ac0a46fSAndroid Build Coastguard Worker 
1579*3ac0a46fSAndroid Build Coastguard Worker     /* We always write Long8 for BigTIFF, no checking needed. */
1580*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_BIGTIFF)
1581*3ac0a46fSAndroid Build Coastguard Worker         return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
1582*3ac0a46fSAndroid Build Coastguard Worker                                                        count, value));
1583*3ac0a46fSAndroid Build Coastguard Worker 
1584*3ac0a46fSAndroid Build Coastguard Worker     /*
1585*3ac0a46fSAndroid Build Coastguard Worker     ** For classic tiff we want to verify everything is in range for long
1586*3ac0a46fSAndroid Build Coastguard Worker     ** and convert to long format.
1587*3ac0a46fSAndroid Build Coastguard Worker     */
1588*3ac0a46fSAndroid Build Coastguard Worker     p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
1589*3ac0a46fSAndroid Build Coastguard Worker     if (p == NULL)
1590*3ac0a46fSAndroid Build Coastguard Worker     {
1591*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
1592*3ac0a46fSAndroid Build Coastguard Worker         return (0);
1593*3ac0a46fSAndroid Build Coastguard Worker     }
1594*3ac0a46fSAndroid Build Coastguard Worker 
1595*3ac0a46fSAndroid Build Coastguard Worker     for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
1596*3ac0a46fSAndroid Build Coastguard Worker     {
1597*3ac0a46fSAndroid Build Coastguard Worker         if (*ma > 0xFFFFFFFF)
1598*3ac0a46fSAndroid Build Coastguard Worker         {
1599*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
1600*3ac0a46fSAndroid Build Coastguard Worker                           "Attempt to write unsigned long value %" PRIu64
1601*3ac0a46fSAndroid Build Coastguard Worker                           " larger than 0xFFFFFFFF for tag %d in Classic TIFF "
1602*3ac0a46fSAndroid Build Coastguard Worker                           "file. TIFF file writing aborted",
1603*3ac0a46fSAndroid Build Coastguard Worker                           *ma, tag);
1604*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, p);
1605*3ac0a46fSAndroid Build Coastguard Worker             return (0);
1606*3ac0a46fSAndroid Build Coastguard Worker         }
1607*3ac0a46fSAndroid Build Coastguard Worker         *q = (uint32_t)(*ma);
1608*3ac0a46fSAndroid Build Coastguard Worker     }
1609*3ac0a46fSAndroid Build Coastguard Worker 
1610*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count, p);
1611*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, p);
1612*3ac0a46fSAndroid Build Coastguard Worker 
1613*3ac0a46fSAndroid Build Coastguard Worker     return (o);
1614*3ac0a46fSAndroid Build Coastguard Worker }
1615*3ac0a46fSAndroid Build Coastguard Worker 
1616*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
1617*3ac0a46fSAndroid Build Coastguard Worker /*                 TIFFWriteDirectoryTagSlong8Array()                   */
1618*3ac0a46fSAndroid Build Coastguard Worker /*                                                                      */
1619*3ac0a46fSAndroid Build Coastguard Worker /*      Write either SLong8 or SLong array depending on file type.      */
1620*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
TIFFWriteDirectoryTagSlong8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int64_t * value)1621*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir,
1622*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
1623*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t count, int64_t *value)
1624*3ac0a46fSAndroid Build Coastguard Worker {
1625*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagSlong8Array";
1626*3ac0a46fSAndroid Build Coastguard Worker     int64_t *ma;
1627*3ac0a46fSAndroid Build Coastguard Worker     uint32_t mb;
1628*3ac0a46fSAndroid Build Coastguard Worker     int32_t *p;
1629*3ac0a46fSAndroid Build Coastguard Worker     int32_t *q;
1630*3ac0a46fSAndroid Build Coastguard Worker     int o;
1631*3ac0a46fSAndroid Build Coastguard Worker 
1632*3ac0a46fSAndroid Build Coastguard Worker     /* is this just a counting pass? */
1633*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1634*3ac0a46fSAndroid Build Coastguard Worker     {
1635*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1636*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1637*3ac0a46fSAndroid Build Coastguard Worker     }
1638*3ac0a46fSAndroid Build Coastguard Worker     /* We always write SLong8 for BigTIFF, no checking needed. */
1639*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_BIGTIFF)
1640*3ac0a46fSAndroid Build Coastguard Worker         return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag,
1641*3ac0a46fSAndroid Build Coastguard Worker                                                         count, value));
1642*3ac0a46fSAndroid Build Coastguard Worker 
1643*3ac0a46fSAndroid Build Coastguard Worker     /*
1644*3ac0a46fSAndroid Build Coastguard Worker     ** For classic tiff we want to verify everything is in range for signed-long
1645*3ac0a46fSAndroid Build Coastguard Worker     ** and convert to signed-long format.
1646*3ac0a46fSAndroid Build Coastguard Worker     */
1647*3ac0a46fSAndroid Build Coastguard Worker     p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
1648*3ac0a46fSAndroid Build Coastguard Worker     if (p == NULL)
1649*3ac0a46fSAndroid Build Coastguard Worker     {
1650*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
1651*3ac0a46fSAndroid Build Coastguard Worker         return (0);
1652*3ac0a46fSAndroid Build Coastguard Worker     }
1653*3ac0a46fSAndroid Build Coastguard Worker 
1654*3ac0a46fSAndroid Build Coastguard Worker     for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
1655*3ac0a46fSAndroid Build Coastguard Worker     {
1656*3ac0a46fSAndroid Build Coastguard Worker         if (*ma > (2147483647))
1657*3ac0a46fSAndroid Build Coastguard Worker         {
1658*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
1659*3ac0a46fSAndroid Build Coastguard Worker                           "Attempt to write signed long value %" PRIi64
1660*3ac0a46fSAndroid Build Coastguard Worker                           " larger than 0x7FFFFFFF (2147483647) for tag %d in "
1661*3ac0a46fSAndroid Build Coastguard Worker                           "Classic TIFF file. TIFF writing to file aborted",
1662*3ac0a46fSAndroid Build Coastguard Worker                           *ma, tag);
1663*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, p);
1664*3ac0a46fSAndroid Build Coastguard Worker             return (0);
1665*3ac0a46fSAndroid Build Coastguard Worker         }
1666*3ac0a46fSAndroid Build Coastguard Worker         else if (*ma < (-2147483647 - 1))
1667*3ac0a46fSAndroid Build Coastguard Worker         {
1668*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
1669*3ac0a46fSAndroid Build Coastguard Worker                           "Attempt to write signed long value %" PRIi64
1670*3ac0a46fSAndroid Build Coastguard Worker                           " smaller than 0x80000000 (-2147483648) for tag %d "
1671*3ac0a46fSAndroid Build Coastguard Worker                           "in Classic TIFF file. TIFF writing to file aborted",
1672*3ac0a46fSAndroid Build Coastguard Worker                           *ma, tag);
1673*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, p);
1674*3ac0a46fSAndroid Build Coastguard Worker             return (0);
1675*3ac0a46fSAndroid Build Coastguard Worker         }
1676*3ac0a46fSAndroid Build Coastguard Worker         *q = (int32_t)(*ma);
1677*3ac0a46fSAndroid Build Coastguard Worker     }
1678*3ac0a46fSAndroid Build Coastguard Worker 
1679*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagCheckedSlongArray(tif, ndir, dir, tag, count, p);
1680*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, p);
1681*3ac0a46fSAndroid Build Coastguard Worker 
1682*3ac0a46fSAndroid Build Coastguard Worker     return (o);
1683*3ac0a46fSAndroid Build Coastguard Worker }
1684*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagRational(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,double value)1685*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagRational(TIFF *tif, uint32_t *ndir,
1686*3ac0a46fSAndroid Build Coastguard Worker                                          TIFFDirEntry *dir, uint16_t tag,
1687*3ac0a46fSAndroid Build Coastguard Worker                                          double value)
1688*3ac0a46fSAndroid Build Coastguard Worker {
1689*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1690*3ac0a46fSAndroid Build Coastguard Worker     {
1691*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1692*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1693*3ac0a46fSAndroid Build Coastguard Worker     }
1694*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedRational(tif, ndir, dir, tag, value));
1695*3ac0a46fSAndroid Build Coastguard Worker }
1696*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagRationalArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,float * value)1697*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagRationalArray(TIFF *tif, uint32_t *ndir,
1698*3ac0a46fSAndroid Build Coastguard Worker                                               TIFFDirEntry *dir, uint16_t tag,
1699*3ac0a46fSAndroid Build Coastguard Worker                                               uint32_t count, float *value)
1700*3ac0a46fSAndroid Build Coastguard Worker {
1701*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1702*3ac0a46fSAndroid Build Coastguard Worker     {
1703*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1704*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1705*3ac0a46fSAndroid Build Coastguard Worker     }
1706*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedRationalArray(tif, ndir, dir, tag,
1707*3ac0a46fSAndroid Build Coastguard Worker                                                       count, value));
1708*3ac0a46fSAndroid Build Coastguard Worker }
1709*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSrationalArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,float * value)1710*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSrationalArray(TIFF *tif, uint32_t *ndir,
1711*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
1712*3ac0a46fSAndroid Build Coastguard Worker                                                uint32_t count, float *value)
1713*3ac0a46fSAndroid Build Coastguard Worker {
1714*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1715*3ac0a46fSAndroid Build Coastguard Worker     {
1716*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1717*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1718*3ac0a46fSAndroid Build Coastguard Worker     }
1719*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedSrationalArray(tif, ndir, dir, tag,
1720*3ac0a46fSAndroid Build Coastguard Worker                                                        count, value));
1721*3ac0a46fSAndroid Build Coastguard Worker }
1722*3ac0a46fSAndroid Build Coastguard Worker 
1723*3ac0a46fSAndroid Build Coastguard Worker /*-- Rational2Double: additional write functions */
TIFFWriteDirectoryTagRationalDoubleArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)1724*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagRationalDoubleArray(TIFF *tif, uint32_t *ndir,
1725*3ac0a46fSAndroid Build Coastguard Worker                                                     TIFFDirEntry *dir,
1726*3ac0a46fSAndroid Build Coastguard Worker                                                     uint16_t tag,
1727*3ac0a46fSAndroid Build Coastguard Worker                                                     uint32_t count,
1728*3ac0a46fSAndroid Build Coastguard Worker                                                     double *value)
1729*3ac0a46fSAndroid Build Coastguard Worker {
1730*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1731*3ac0a46fSAndroid Build Coastguard Worker     {
1732*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1733*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1734*3ac0a46fSAndroid Build Coastguard Worker     }
1735*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedRationalDoubleArray(tif, ndir, dir, tag,
1736*3ac0a46fSAndroid Build Coastguard Worker                                                             count, value));
1737*3ac0a46fSAndroid Build Coastguard Worker }
1738*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSrationalDoubleArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)1739*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSrationalDoubleArray(TIFF *tif, uint32_t *ndir,
1740*3ac0a46fSAndroid Build Coastguard Worker                                                      TIFFDirEntry *dir,
1741*3ac0a46fSAndroid Build Coastguard Worker                                                      uint16_t tag,
1742*3ac0a46fSAndroid Build Coastguard Worker                                                      uint32_t count,
1743*3ac0a46fSAndroid Build Coastguard Worker                                                      double *value)
1744*3ac0a46fSAndroid Build Coastguard Worker {
1745*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1746*3ac0a46fSAndroid Build Coastguard Worker     {
1747*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1748*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1749*3ac0a46fSAndroid Build Coastguard Worker     }
1750*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
1751*3ac0a46fSAndroid Build Coastguard Worker         tif, ndir, dir, tag, count, value));
1752*3ac0a46fSAndroid Build Coastguard Worker }
1753*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagFloatArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,float * value)1754*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagFloatArray(TIFF *tif, uint32_t *ndir,
1755*3ac0a46fSAndroid Build Coastguard Worker                                            TIFFDirEntry *dir, uint16_t tag,
1756*3ac0a46fSAndroid Build Coastguard Worker                                            uint32_t count, float *value)
1757*3ac0a46fSAndroid Build Coastguard Worker {
1758*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1759*3ac0a46fSAndroid Build Coastguard Worker     {
1760*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1761*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1762*3ac0a46fSAndroid Build Coastguard Worker     }
1763*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedFloatArray(tif, ndir, dir, tag, count,
1764*3ac0a46fSAndroid Build Coastguard Worker                                                    value));
1765*3ac0a46fSAndroid Build Coastguard Worker }
1766*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagDoubleArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)1767*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagDoubleArray(TIFF *tif, uint32_t *ndir,
1768*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
1769*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t count, double *value)
1770*3ac0a46fSAndroid Build Coastguard Worker {
1771*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1772*3ac0a46fSAndroid Build Coastguard Worker     {
1773*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1774*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1775*3ac0a46fSAndroid Build Coastguard Worker     }
1776*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedDoubleArray(tif, ndir, dir, tag, count,
1777*3ac0a46fSAndroid Build Coastguard Worker                                                     value));
1778*3ac0a46fSAndroid Build Coastguard Worker }
1779*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagIfdArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint32_t * value)1780*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagIfdArray(TIFF *tif, uint32_t *ndir,
1781*3ac0a46fSAndroid Build Coastguard Worker                                          TIFFDirEntry *dir, uint16_t tag,
1782*3ac0a46fSAndroid Build Coastguard Worker                                          uint32_t count, uint32_t *value)
1783*3ac0a46fSAndroid Build Coastguard Worker {
1784*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1785*3ac0a46fSAndroid Build Coastguard Worker     {
1786*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1787*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1788*3ac0a46fSAndroid Build Coastguard Worker     }
1789*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, tag, count,
1790*3ac0a46fSAndroid Build Coastguard Worker                                                  value));
1791*3ac0a46fSAndroid Build Coastguard Worker }
1792*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagShortLong(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t value)1793*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagShortLong(TIFF *tif, uint32_t *ndir,
1794*3ac0a46fSAndroid Build Coastguard Worker                                           TIFFDirEntry *dir, uint16_t tag,
1795*3ac0a46fSAndroid Build Coastguard Worker                                           uint32_t value)
1796*3ac0a46fSAndroid Build Coastguard Worker {
1797*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1798*3ac0a46fSAndroid Build Coastguard Worker     {
1799*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1800*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1801*3ac0a46fSAndroid Build Coastguard Worker     }
1802*3ac0a46fSAndroid Build Coastguard Worker     if (value <= 0xFFFF)
1803*3ac0a46fSAndroid Build Coastguard Worker         return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag,
1804*3ac0a46fSAndroid Build Coastguard Worker                                                   (uint16_t)value));
1805*3ac0a46fSAndroid Build Coastguard Worker     else
1806*3ac0a46fSAndroid Build Coastguard Worker         return (TIFFWriteDirectoryTagCheckedLong(tif, ndir, dir, tag, value));
1807*3ac0a46fSAndroid Build Coastguard Worker }
1808*3ac0a46fSAndroid Build Coastguard Worker 
_WriteAsType(TIFF * tif,uint64_t strile_size,uint64_t uncompressed_threshold)1809*3ac0a46fSAndroid Build Coastguard Worker static int _WriteAsType(TIFF *tif, uint64_t strile_size,
1810*3ac0a46fSAndroid Build Coastguard Worker                         uint64_t uncompressed_threshold)
1811*3ac0a46fSAndroid Build Coastguard Worker {
1812*3ac0a46fSAndroid Build Coastguard Worker     const uint16_t compression = tif->tif_dir.td_compression;
1813*3ac0a46fSAndroid Build Coastguard Worker     if (compression == COMPRESSION_NONE)
1814*3ac0a46fSAndroid Build Coastguard Worker     {
1815*3ac0a46fSAndroid Build Coastguard Worker         return strile_size > uncompressed_threshold;
1816*3ac0a46fSAndroid Build Coastguard Worker     }
1817*3ac0a46fSAndroid Build Coastguard Worker     else if (compression == COMPRESSION_JPEG ||
1818*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_LZW ||
1819*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_ADOBE_DEFLATE ||
1820*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_DEFLATE ||
1821*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_LZMA ||
1822*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_LERC ||
1823*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_ZSTD ||
1824*3ac0a46fSAndroid Build Coastguard Worker              compression == COMPRESSION_WEBP || compression == COMPRESSION_JXL)
1825*3ac0a46fSAndroid Build Coastguard Worker     {
1826*3ac0a46fSAndroid Build Coastguard Worker         /* For a few select compression types, we assume that in the worst */
1827*3ac0a46fSAndroid Build Coastguard Worker         /* case the compressed size will be 10 times the uncompressed size */
1828*3ac0a46fSAndroid Build Coastguard Worker         /* This is overly pessismistic ! */
1829*3ac0a46fSAndroid Build Coastguard Worker         return strile_size >= uncompressed_threshold / 10;
1830*3ac0a46fSAndroid Build Coastguard Worker     }
1831*3ac0a46fSAndroid Build Coastguard Worker     return 1;
1832*3ac0a46fSAndroid Build Coastguard Worker }
1833*3ac0a46fSAndroid Build Coastguard Worker 
WriteAsLong8(TIFF * tif,uint64_t strile_size)1834*3ac0a46fSAndroid Build Coastguard Worker static int WriteAsLong8(TIFF *tif, uint64_t strile_size)
1835*3ac0a46fSAndroid Build Coastguard Worker {
1836*3ac0a46fSAndroid Build Coastguard Worker     return _WriteAsType(tif, strile_size, 0xFFFFFFFFU);
1837*3ac0a46fSAndroid Build Coastguard Worker }
1838*3ac0a46fSAndroid Build Coastguard Worker 
WriteAsLong4(TIFF * tif,uint64_t strile_size)1839*3ac0a46fSAndroid Build Coastguard Worker static int WriteAsLong4(TIFF *tif, uint64_t strile_size)
1840*3ac0a46fSAndroid Build Coastguard Worker {
1841*3ac0a46fSAndroid Build Coastguard Worker     return _WriteAsType(tif, strile_size, 0xFFFFU);
1842*3ac0a46fSAndroid Build Coastguard Worker }
1843*3ac0a46fSAndroid Build Coastguard Worker 
1844*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
1845*3ac0a46fSAndroid Build Coastguard Worker /*                TIFFWriteDirectoryTagLongLong8Array()                 */
1846*3ac0a46fSAndroid Build Coastguard Worker /*                                                                      */
1847*3ac0a46fSAndroid Build Coastguard Worker /*      Write out LONG8 array and write a SHORT/LONG/LONG8 depending    */
1848*3ac0a46fSAndroid Build Coastguard Worker /*      on strile size and Classic/BigTIFF mode.                        */
1849*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
1850*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagLongLong8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint64_t * value)1851*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir,
1852*3ac0a46fSAndroid Build Coastguard Worker                                                TIFFDirEntry *dir, uint16_t tag,
1853*3ac0a46fSAndroid Build Coastguard Worker                                                uint32_t count, uint64_t *value)
1854*3ac0a46fSAndroid Build Coastguard Worker {
1855*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagLongLong8Array";
1856*3ac0a46fSAndroid Build Coastguard Worker     int o;
1857*3ac0a46fSAndroid Build Coastguard Worker     int write_aslong4;
1858*3ac0a46fSAndroid Build Coastguard Worker 
1859*3ac0a46fSAndroid Build Coastguard Worker     /* is this just a counting pass? */
1860*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1861*3ac0a46fSAndroid Build Coastguard Worker     {
1862*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1863*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1864*3ac0a46fSAndroid Build Coastguard Worker     }
1865*3ac0a46fSAndroid Build Coastguard Worker 
1866*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_dir.td_deferstrilearraywriting)
1867*3ac0a46fSAndroid Build Coastguard Worker     {
1868*3ac0a46fSAndroid Build Coastguard Worker         return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0,
1869*3ac0a46fSAndroid Build Coastguard Worker                                          NULL);
1870*3ac0a46fSAndroid Build Coastguard Worker     }
1871*3ac0a46fSAndroid Build Coastguard Worker 
1872*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_BIGTIFF)
1873*3ac0a46fSAndroid Build Coastguard Worker     {
1874*3ac0a46fSAndroid Build Coastguard Worker         int write_aslong8 = 1;
1875*3ac0a46fSAndroid Build Coastguard Worker         /* In the case of ByteCounts array, we may be able to write them on */
1876*3ac0a46fSAndroid Build Coastguard Worker         /* LONG if the strip/tilesize is not too big. */
1877*3ac0a46fSAndroid Build Coastguard Worker         /* Also do that for count > 1 in the case someone would want to create
1878*3ac0a46fSAndroid Build Coastguard Worker          */
1879*3ac0a46fSAndroid Build Coastguard Worker         /* a single-strip file with a growing height, in which case using */
1880*3ac0a46fSAndroid Build Coastguard Worker         /* LONG8 will be safer. */
1881*3ac0a46fSAndroid Build Coastguard Worker         if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
1882*3ac0a46fSAndroid Build Coastguard Worker         {
1883*3ac0a46fSAndroid Build Coastguard Worker             write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
1884*3ac0a46fSAndroid Build Coastguard Worker         }
1885*3ac0a46fSAndroid Build Coastguard Worker         else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
1886*3ac0a46fSAndroid Build Coastguard Worker         {
1887*3ac0a46fSAndroid Build Coastguard Worker             write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
1888*3ac0a46fSAndroid Build Coastguard Worker         }
1889*3ac0a46fSAndroid Build Coastguard Worker         if (write_aslong8)
1890*3ac0a46fSAndroid Build Coastguard Worker         {
1891*3ac0a46fSAndroid Build Coastguard Worker             return TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
1892*3ac0a46fSAndroid Build Coastguard Worker                                                           count, value);
1893*3ac0a46fSAndroid Build Coastguard Worker         }
1894*3ac0a46fSAndroid Build Coastguard Worker     }
1895*3ac0a46fSAndroid Build Coastguard Worker 
1896*3ac0a46fSAndroid Build Coastguard Worker     write_aslong4 = 1;
1897*3ac0a46fSAndroid Build Coastguard Worker     if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
1898*3ac0a46fSAndroid Build Coastguard Worker     {
1899*3ac0a46fSAndroid Build Coastguard Worker         write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
1900*3ac0a46fSAndroid Build Coastguard Worker     }
1901*3ac0a46fSAndroid Build Coastguard Worker     else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
1902*3ac0a46fSAndroid Build Coastguard Worker     {
1903*3ac0a46fSAndroid Build Coastguard Worker         write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
1904*3ac0a46fSAndroid Build Coastguard Worker     }
1905*3ac0a46fSAndroid Build Coastguard Worker     if (write_aslong4)
1906*3ac0a46fSAndroid Build Coastguard Worker     {
1907*3ac0a46fSAndroid Build Coastguard Worker         /*
1908*3ac0a46fSAndroid Build Coastguard Worker         ** For classic tiff we want to verify everything is in range for LONG
1909*3ac0a46fSAndroid Build Coastguard Worker         ** and convert to long format.
1910*3ac0a46fSAndroid Build Coastguard Worker         */
1911*3ac0a46fSAndroid Build Coastguard Worker 
1912*3ac0a46fSAndroid Build Coastguard Worker         uint32_t *p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
1913*3ac0a46fSAndroid Build Coastguard Worker         uint32_t *q;
1914*3ac0a46fSAndroid Build Coastguard Worker         uint64_t *ma;
1915*3ac0a46fSAndroid Build Coastguard Worker         uint32_t mb;
1916*3ac0a46fSAndroid Build Coastguard Worker 
1917*3ac0a46fSAndroid Build Coastguard Worker         if (p == NULL)
1918*3ac0a46fSAndroid Build Coastguard Worker         {
1919*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Out of memory");
1920*3ac0a46fSAndroid Build Coastguard Worker             return (0);
1921*3ac0a46fSAndroid Build Coastguard Worker         }
1922*3ac0a46fSAndroid Build Coastguard Worker 
1923*3ac0a46fSAndroid Build Coastguard Worker         for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
1924*3ac0a46fSAndroid Build Coastguard Worker         {
1925*3ac0a46fSAndroid Build Coastguard Worker             if (*ma > 0xFFFFFFFF)
1926*3ac0a46fSAndroid Build Coastguard Worker             {
1927*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
1928*3ac0a46fSAndroid Build Coastguard Worker                               "Attempt to write value larger than 0xFFFFFFFF "
1929*3ac0a46fSAndroid Build Coastguard Worker                               "in LONG array.");
1930*3ac0a46fSAndroid Build Coastguard Worker                 _TIFFfreeExt(tif, p);
1931*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
1932*3ac0a46fSAndroid Build Coastguard Worker             }
1933*3ac0a46fSAndroid Build Coastguard Worker             *q = (uint32_t)(*ma);
1934*3ac0a46fSAndroid Build Coastguard Worker         }
1935*3ac0a46fSAndroid Build Coastguard Worker 
1936*3ac0a46fSAndroid Build Coastguard Worker         o = TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count,
1937*3ac0a46fSAndroid Build Coastguard Worker                                                   p);
1938*3ac0a46fSAndroid Build Coastguard Worker         _TIFFfreeExt(tif, p);
1939*3ac0a46fSAndroid Build Coastguard Worker     }
1940*3ac0a46fSAndroid Build Coastguard Worker     else
1941*3ac0a46fSAndroid Build Coastguard Worker     {
1942*3ac0a46fSAndroid Build Coastguard Worker         uint16_t *p = _TIFFmallocExt(tif, count * sizeof(uint16_t));
1943*3ac0a46fSAndroid Build Coastguard Worker         uint16_t *q;
1944*3ac0a46fSAndroid Build Coastguard Worker         uint64_t *ma;
1945*3ac0a46fSAndroid Build Coastguard Worker         uint32_t mb;
1946*3ac0a46fSAndroid Build Coastguard Worker 
1947*3ac0a46fSAndroid Build Coastguard Worker         if (p == NULL)
1948*3ac0a46fSAndroid Build Coastguard Worker         {
1949*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Out of memory");
1950*3ac0a46fSAndroid Build Coastguard Worker             return (0);
1951*3ac0a46fSAndroid Build Coastguard Worker         }
1952*3ac0a46fSAndroid Build Coastguard Worker 
1953*3ac0a46fSAndroid Build Coastguard Worker         for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
1954*3ac0a46fSAndroid Build Coastguard Worker         {
1955*3ac0a46fSAndroid Build Coastguard Worker             if (*ma > 0xFFFF)
1956*3ac0a46fSAndroid Build Coastguard Worker             {
1957*3ac0a46fSAndroid Build Coastguard Worker                 /* Should not happen normally given the check we did before */
1958*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
1959*3ac0a46fSAndroid Build Coastguard Worker                               "Attempt to write value larger than 0xFFFF in "
1960*3ac0a46fSAndroid Build Coastguard Worker                               "SHORT array.");
1961*3ac0a46fSAndroid Build Coastguard Worker                 _TIFFfreeExt(tif, p);
1962*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
1963*3ac0a46fSAndroid Build Coastguard Worker             }
1964*3ac0a46fSAndroid Build Coastguard Worker             *q = (uint16_t)(*ma);
1965*3ac0a46fSAndroid Build Coastguard Worker         }
1966*3ac0a46fSAndroid Build Coastguard Worker 
1967*3ac0a46fSAndroid Build Coastguard Worker         o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, tag, count,
1968*3ac0a46fSAndroid Build Coastguard Worker                                                    p);
1969*3ac0a46fSAndroid Build Coastguard Worker         _TIFFfreeExt(tif, p);
1970*3ac0a46fSAndroid Build Coastguard Worker     }
1971*3ac0a46fSAndroid Build Coastguard Worker 
1972*3ac0a46fSAndroid Build Coastguard Worker     return (o);
1973*3ac0a46fSAndroid Build Coastguard Worker }
1974*3ac0a46fSAndroid Build Coastguard Worker 
1975*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
1976*3ac0a46fSAndroid Build Coastguard Worker /*                 TIFFWriteDirectoryTagIfdIfd8Array()                  */
1977*3ac0a46fSAndroid Build Coastguard Worker /*                                                                      */
1978*3ac0a46fSAndroid Build Coastguard Worker /*      Write either IFD8 or IFD array depending on file type.          */
1979*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
1980*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagIfdIfd8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint64_t * value)1981*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir,
1982*3ac0a46fSAndroid Build Coastguard Worker                                              TIFFDirEntry *dir, uint16_t tag,
1983*3ac0a46fSAndroid Build Coastguard Worker                                              uint32_t count, uint64_t *value)
1984*3ac0a46fSAndroid Build Coastguard Worker {
1985*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagIfdIfd8Array";
1986*3ac0a46fSAndroid Build Coastguard Worker     uint64_t *ma;
1987*3ac0a46fSAndroid Build Coastguard Worker     uint32_t mb;
1988*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *p;
1989*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *q;
1990*3ac0a46fSAndroid Build Coastguard Worker     int o;
1991*3ac0a46fSAndroid Build Coastguard Worker 
1992*3ac0a46fSAndroid Build Coastguard Worker     /* is this just a counting pass? */
1993*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
1994*3ac0a46fSAndroid Build Coastguard Worker     {
1995*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
1996*3ac0a46fSAndroid Build Coastguard Worker         return (1);
1997*3ac0a46fSAndroid Build Coastguard Worker     }
1998*3ac0a46fSAndroid Build Coastguard Worker 
1999*3ac0a46fSAndroid Build Coastguard Worker     /* We always write IFD8 for BigTIFF, no checking needed. */
2000*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_BIGTIFF)
2001*3ac0a46fSAndroid Build Coastguard Worker         return TIFFWriteDirectoryTagCheckedIfd8Array(tif, ndir, dir, tag, count,
2002*3ac0a46fSAndroid Build Coastguard Worker                                                      value);
2003*3ac0a46fSAndroid Build Coastguard Worker 
2004*3ac0a46fSAndroid Build Coastguard Worker     /*
2005*3ac0a46fSAndroid Build Coastguard Worker     ** For classic tiff we want to verify everything is in range for IFD
2006*3ac0a46fSAndroid Build Coastguard Worker     ** and convert to long format.
2007*3ac0a46fSAndroid Build Coastguard Worker     */
2008*3ac0a46fSAndroid Build Coastguard Worker 
2009*3ac0a46fSAndroid Build Coastguard Worker     p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
2010*3ac0a46fSAndroid Build Coastguard Worker     if (p == NULL)
2011*3ac0a46fSAndroid Build Coastguard Worker     {
2012*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2013*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2014*3ac0a46fSAndroid Build Coastguard Worker     }
2015*3ac0a46fSAndroid Build Coastguard Worker 
2016*3ac0a46fSAndroid Build Coastguard Worker     for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
2017*3ac0a46fSAndroid Build Coastguard Worker     {
2018*3ac0a46fSAndroid Build Coastguard Worker         if (*ma > 0xFFFFFFFF)
2019*3ac0a46fSAndroid Build Coastguard Worker         {
2020*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
2021*3ac0a46fSAndroid Build Coastguard Worker                           "Attempt to write value larger than 0xFFFFFFFF in "
2022*3ac0a46fSAndroid Build Coastguard Worker                           "Classic TIFF file.");
2023*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, p);
2024*3ac0a46fSAndroid Build Coastguard Worker             return (0);
2025*3ac0a46fSAndroid Build Coastguard Worker         }
2026*3ac0a46fSAndroid Build Coastguard Worker         *q = (uint32_t)(*ma);
2027*3ac0a46fSAndroid Build Coastguard Worker     }
2028*3ac0a46fSAndroid Build Coastguard Worker 
2029*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, tag, count, p);
2030*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, p);
2031*3ac0a46fSAndroid Build Coastguard Worker 
2032*3ac0a46fSAndroid Build Coastguard Worker     return (o);
2033*3ac0a46fSAndroid Build Coastguard Worker }
2034*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagColormap(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir)2035*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir,
2036*3ac0a46fSAndroid Build Coastguard Worker                                          TIFFDirEntry *dir)
2037*3ac0a46fSAndroid Build Coastguard Worker {
2038*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagColormap";
2039*3ac0a46fSAndroid Build Coastguard Worker     uint32_t m;
2040*3ac0a46fSAndroid Build Coastguard Worker     uint16_t *n;
2041*3ac0a46fSAndroid Build Coastguard Worker     int o;
2042*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
2043*3ac0a46fSAndroid Build Coastguard Worker     {
2044*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
2045*3ac0a46fSAndroid Build Coastguard Worker         return (1);
2046*3ac0a46fSAndroid Build Coastguard Worker     }
2047*3ac0a46fSAndroid Build Coastguard Worker     m = (1 << tif->tif_dir.td_bitspersample);
2048*3ac0a46fSAndroid Build Coastguard Worker     n = _TIFFmallocExt(tif, 3 * m * sizeof(uint16_t));
2049*3ac0a46fSAndroid Build Coastguard Worker     if (n == NULL)
2050*3ac0a46fSAndroid Build Coastguard Worker     {
2051*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2052*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2053*3ac0a46fSAndroid Build Coastguard Worker     }
2054*3ac0a46fSAndroid Build Coastguard Worker     _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], m * sizeof(uint16_t));
2055*3ac0a46fSAndroid Build Coastguard Worker     _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], m * sizeof(uint16_t));
2056*3ac0a46fSAndroid Build Coastguard Worker     _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], m * sizeof(uint16_t));
2057*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, TIFFTAG_COLORMAP,
2058*3ac0a46fSAndroid Build Coastguard Worker                                                3 * m, n);
2059*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, n);
2060*3ac0a46fSAndroid Build Coastguard Worker     return (o);
2061*3ac0a46fSAndroid Build Coastguard Worker }
2062*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagTransferfunction(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir)2063*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir,
2064*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir)
2065*3ac0a46fSAndroid Build Coastguard Worker {
2066*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagTransferfunction";
2067*3ac0a46fSAndroid Build Coastguard Worker     uint32_t m;
2068*3ac0a46fSAndroid Build Coastguard Worker     uint16_t n;
2069*3ac0a46fSAndroid Build Coastguard Worker     uint16_t *o;
2070*3ac0a46fSAndroid Build Coastguard Worker     int p;
2071*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
2072*3ac0a46fSAndroid Build Coastguard Worker     {
2073*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
2074*3ac0a46fSAndroid Build Coastguard Worker         return (1);
2075*3ac0a46fSAndroid Build Coastguard Worker     }
2076*3ac0a46fSAndroid Build Coastguard Worker     m = (1 << tif->tif_dir.td_bitspersample);
2077*3ac0a46fSAndroid Build Coastguard Worker     n = tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples;
2078*3ac0a46fSAndroid Build Coastguard Worker     /*
2079*3ac0a46fSAndroid Build Coastguard Worker      * Check if the table can be written as a single column,
2080*3ac0a46fSAndroid Build Coastguard Worker      * or if it must be written as 3 columns.  Note that we
2081*3ac0a46fSAndroid Build Coastguard Worker      * write a 3-column tag if there are 2 samples/pixel and
2082*3ac0a46fSAndroid Build Coastguard Worker      * a single column of data won't suffice--hmm.
2083*3ac0a46fSAndroid Build Coastguard Worker      */
2084*3ac0a46fSAndroid Build Coastguard Worker     if (n > 3)
2085*3ac0a46fSAndroid Build Coastguard Worker         n = 3;
2086*3ac0a46fSAndroid Build Coastguard Worker     if (n == 3)
2087*3ac0a46fSAndroid Build Coastguard Worker     {
2088*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_dir.td_transferfunction[2] == NULL ||
2089*3ac0a46fSAndroid Build Coastguard Worker             !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
2090*3ac0a46fSAndroid Build Coastguard Worker                          tif->tif_dir.td_transferfunction[2],
2091*3ac0a46fSAndroid Build Coastguard Worker                          m * sizeof(uint16_t)))
2092*3ac0a46fSAndroid Build Coastguard Worker             n = 2;
2093*3ac0a46fSAndroid Build Coastguard Worker     }
2094*3ac0a46fSAndroid Build Coastguard Worker     if (n == 2)
2095*3ac0a46fSAndroid Build Coastguard Worker     {
2096*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_dir.td_transferfunction[1] == NULL ||
2097*3ac0a46fSAndroid Build Coastguard Worker             !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
2098*3ac0a46fSAndroid Build Coastguard Worker                          tif->tif_dir.td_transferfunction[1],
2099*3ac0a46fSAndroid Build Coastguard Worker                          m * sizeof(uint16_t)))
2100*3ac0a46fSAndroid Build Coastguard Worker             n = 1;
2101*3ac0a46fSAndroid Build Coastguard Worker     }
2102*3ac0a46fSAndroid Build Coastguard Worker     if (n == 0)
2103*3ac0a46fSAndroid Build Coastguard Worker         n = 1;
2104*3ac0a46fSAndroid Build Coastguard Worker     o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t));
2105*3ac0a46fSAndroid Build Coastguard Worker     if (o == NULL)
2106*3ac0a46fSAndroid Build Coastguard Worker     {
2107*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2108*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2109*3ac0a46fSAndroid Build Coastguard Worker     }
2110*3ac0a46fSAndroid Build Coastguard Worker     _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0],
2111*3ac0a46fSAndroid Build Coastguard Worker                 m * sizeof(uint16_t));
2112*3ac0a46fSAndroid Build Coastguard Worker     if (n > 1)
2113*3ac0a46fSAndroid Build Coastguard Worker         _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1],
2114*3ac0a46fSAndroid Build Coastguard Worker                     m * sizeof(uint16_t));
2115*3ac0a46fSAndroid Build Coastguard Worker     if (n > 2)
2116*3ac0a46fSAndroid Build Coastguard Worker         _TIFFmemcpy(&o[2 * m], tif->tif_dir.td_transferfunction[2],
2117*3ac0a46fSAndroid Build Coastguard Worker                     m * sizeof(uint16_t));
2118*3ac0a46fSAndroid Build Coastguard Worker     p = TIFFWriteDirectoryTagCheckedShortArray(
2119*3ac0a46fSAndroid Build Coastguard Worker         tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, n * m, o);
2120*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, o);
2121*3ac0a46fSAndroid Build Coastguard Worker     return (p);
2122*3ac0a46fSAndroid Build Coastguard Worker }
2123*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagSubifd(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir)2124*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir,
2125*3ac0a46fSAndroid Build Coastguard Worker                                        TIFFDirEntry *dir)
2126*3ac0a46fSAndroid Build Coastguard Worker {
2127*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagSubifd";
2128*3ac0a46fSAndroid Build Coastguard Worker     uint64_t m;
2129*3ac0a46fSAndroid Build Coastguard Worker     int n;
2130*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_dir.td_nsubifd == 0)
2131*3ac0a46fSAndroid Build Coastguard Worker         return (1);
2132*3ac0a46fSAndroid Build Coastguard Worker     if (dir == NULL)
2133*3ac0a46fSAndroid Build Coastguard Worker     {
2134*3ac0a46fSAndroid Build Coastguard Worker         (*ndir)++;
2135*3ac0a46fSAndroid Build Coastguard Worker         return (1);
2136*3ac0a46fSAndroid Build Coastguard Worker     }
2137*3ac0a46fSAndroid Build Coastguard Worker     m = tif->tif_dataoff;
2138*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
2139*3ac0a46fSAndroid Build Coastguard Worker     {
2140*3ac0a46fSAndroid Build Coastguard Worker         uint32_t *o;
2141*3ac0a46fSAndroid Build Coastguard Worker         uint64_t *pa;
2142*3ac0a46fSAndroid Build Coastguard Worker         uint32_t *pb;
2143*3ac0a46fSAndroid Build Coastguard Worker         uint16_t p;
2144*3ac0a46fSAndroid Build Coastguard Worker         o = _TIFFmallocExt(tif, tif->tif_dir.td_nsubifd * sizeof(uint32_t));
2145*3ac0a46fSAndroid Build Coastguard Worker         if (o == NULL)
2146*3ac0a46fSAndroid Build Coastguard Worker         {
2147*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Out of memory");
2148*3ac0a46fSAndroid Build Coastguard Worker             return (0);
2149*3ac0a46fSAndroid Build Coastguard Worker         }
2150*3ac0a46fSAndroid Build Coastguard Worker         pa = tif->tif_dir.td_subifd;
2151*3ac0a46fSAndroid Build Coastguard Worker         pb = o;
2152*3ac0a46fSAndroid Build Coastguard Worker         for (p = 0; p < tif->tif_dir.td_nsubifd; p++)
2153*3ac0a46fSAndroid Build Coastguard Worker         {
2154*3ac0a46fSAndroid Build Coastguard Worker             assert(pa != 0);
2155*3ac0a46fSAndroid Build Coastguard Worker 
2156*3ac0a46fSAndroid Build Coastguard Worker             /* Could happen if an classicTIFF has a SubIFD of type LONG8 (which
2157*3ac0a46fSAndroid Build Coastguard Worker              * is illegal) */
2158*3ac0a46fSAndroid Build Coastguard Worker             if (*pa > 0xFFFFFFFFUL)
2159*3ac0a46fSAndroid Build Coastguard Worker             {
2160*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module, "Illegal value for SubIFD tag");
2161*3ac0a46fSAndroid Build Coastguard Worker                 _TIFFfreeExt(tif, o);
2162*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
2163*3ac0a46fSAndroid Build Coastguard Worker             }
2164*3ac0a46fSAndroid Build Coastguard Worker             *pb++ = (uint32_t)(*pa++);
2165*3ac0a46fSAndroid Build Coastguard Worker         }
2166*3ac0a46fSAndroid Build Coastguard Worker         n = TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, TIFFTAG_SUBIFD,
2167*3ac0a46fSAndroid Build Coastguard Worker                                                  tif->tif_dir.td_nsubifd, o);
2168*3ac0a46fSAndroid Build Coastguard Worker         _TIFFfreeExt(tif, o);
2169*3ac0a46fSAndroid Build Coastguard Worker     }
2170*3ac0a46fSAndroid Build Coastguard Worker     else
2171*3ac0a46fSAndroid Build Coastguard Worker         n = TIFFWriteDirectoryTagCheckedIfd8Array(
2172*3ac0a46fSAndroid Build Coastguard Worker             tif, ndir, dir, TIFFTAG_SUBIFD, tif->tif_dir.td_nsubifd,
2173*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_dir.td_subifd);
2174*3ac0a46fSAndroid Build Coastguard Worker     if (!n)
2175*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2176*3ac0a46fSAndroid Build Coastguard Worker     /*
2177*3ac0a46fSAndroid Build Coastguard Worker      * Total hack: if this directory includes a SubIFD
2178*3ac0a46fSAndroid Build Coastguard Worker      * tag then force the next <n> directories to be
2179*3ac0a46fSAndroid Build Coastguard Worker      * written as ``sub directories'' of this one.  This
2180*3ac0a46fSAndroid Build Coastguard Worker      * is used to write things like thumbnails and
2181*3ac0a46fSAndroid Build Coastguard Worker      * image masks that one wants to keep out of the
2182*3ac0a46fSAndroid Build Coastguard Worker      * normal directory linkage access mechanism.
2183*3ac0a46fSAndroid Build Coastguard Worker      */
2184*3ac0a46fSAndroid Build Coastguard Worker     tif->tif_flags |= TIFF_INSUBIFD;
2185*3ac0a46fSAndroid Build Coastguard Worker     tif->tif_nsubifd = tif->tif_dir.td_nsubifd;
2186*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_dir.td_nsubifd == 1)
2187*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_subifdoff = 0;
2188*3ac0a46fSAndroid Build Coastguard Worker     else
2189*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_subifdoff = m;
2190*3ac0a46fSAndroid Build Coastguard Worker     return (1);
2191*3ac0a46fSAndroid Build Coastguard Worker }
2192*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedAscii(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,char * value)2193*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedAscii(TIFF *tif, uint32_t *ndir,
2194*3ac0a46fSAndroid Build Coastguard Worker                                              TIFFDirEntry *dir, uint16_t tag,
2195*3ac0a46fSAndroid Build Coastguard Worker                                              uint32_t count, char *value)
2196*3ac0a46fSAndroid Build Coastguard Worker {
2197*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(char) == 1);
2198*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_ASCII, count,
2199*3ac0a46fSAndroid Build Coastguard Worker                                       count, value));
2200*3ac0a46fSAndroid Build Coastguard Worker }
2201*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint8_t * value)2202*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF *tif, uint32_t *ndir,
2203*3ac0a46fSAndroid Build Coastguard Worker                                                       TIFFDirEntry *dir,
2204*3ac0a46fSAndroid Build Coastguard Worker                                                       uint16_t tag,
2205*3ac0a46fSAndroid Build Coastguard Worker                                                       uint32_t count,
2206*3ac0a46fSAndroid Build Coastguard Worker                                                       uint8_t *value)
2207*3ac0a46fSAndroid Build Coastguard Worker {
2208*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint8_t) == 1);
2209*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_UNDEFINED,
2210*3ac0a46fSAndroid Build Coastguard Worker                                       count, count, value));
2211*3ac0a46fSAndroid Build Coastguard Worker }
2212*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedByteArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint8_t * value)2213*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedByteArray(TIFF *tif, uint32_t *ndir,
2214*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir,
2215*3ac0a46fSAndroid Build Coastguard Worker                                                  uint16_t tag, uint32_t count,
2216*3ac0a46fSAndroid Build Coastguard Worker                                                  uint8_t *value)
2217*3ac0a46fSAndroid Build Coastguard Worker {
2218*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint8_t) == 1);
2219*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_BYTE, count,
2220*3ac0a46fSAndroid Build Coastguard Worker                                       count, value));
2221*3ac0a46fSAndroid Build Coastguard Worker }
2222*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedSbyteArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int8_t * value)2223*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF *tif, uint32_t *ndir,
2224*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
2225*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
2226*3ac0a46fSAndroid Build Coastguard Worker                                                   int8_t *value)
2227*3ac0a46fSAndroid Build Coastguard Worker {
2228*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(int8_t) == 1);
2229*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SBYTE, count,
2230*3ac0a46fSAndroid Build Coastguard Worker                                       count, value));
2231*3ac0a46fSAndroid Build Coastguard Worker }
2232*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedShort(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint16_t value)2233*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedShort(TIFF *tif, uint32_t *ndir,
2234*3ac0a46fSAndroid Build Coastguard Worker                                              TIFFDirEntry *dir, uint16_t tag,
2235*3ac0a46fSAndroid Build Coastguard Worker                                              uint16_t value)
2236*3ac0a46fSAndroid Build Coastguard Worker {
2237*3ac0a46fSAndroid Build Coastguard Worker     uint16_t m;
2238*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint16_t) == 2);
2239*3ac0a46fSAndroid Build Coastguard Worker     m = value;
2240*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2241*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabShort(&m);
2242*3ac0a46fSAndroid Build Coastguard Worker     return (
2243*3ac0a46fSAndroid Build Coastguard Worker         TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SHORT, 1, 2, &m));
2244*3ac0a46fSAndroid Build Coastguard Worker }
2245*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedShortArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint16_t * value)2246*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedShortArray(TIFF *tif, uint32_t *ndir,
2247*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
2248*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
2249*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t *value)
2250*3ac0a46fSAndroid Build Coastguard Worker {
2251*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x80000000);
2252*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint16_t) == 2);
2253*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2254*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfShort(value, count);
2255*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SHORT, count,
2256*3ac0a46fSAndroid Build Coastguard Worker                                       count * 2, value));
2257*3ac0a46fSAndroid Build Coastguard Worker }
2258*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedSshortArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int16_t * value)2259*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF *tif, uint32_t *ndir,
2260*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFDirEntry *dir,
2261*3ac0a46fSAndroid Build Coastguard Worker                                                    uint16_t tag, uint32_t count,
2262*3ac0a46fSAndroid Build Coastguard Worker                                                    int16_t *value)
2263*3ac0a46fSAndroid Build Coastguard Worker {
2264*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x80000000);
2265*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(int16_t) == 2);
2266*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2267*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfShort((uint16_t *)value, count);
2268*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SSHORT, count,
2269*3ac0a46fSAndroid Build Coastguard Worker                                       count * 2, value));
2270*3ac0a46fSAndroid Build Coastguard Worker }
2271*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedLong(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t value)2272*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedLong(TIFF *tif, uint32_t *ndir,
2273*3ac0a46fSAndroid Build Coastguard Worker                                             TIFFDirEntry *dir, uint16_t tag,
2274*3ac0a46fSAndroid Build Coastguard Worker                                             uint32_t value)
2275*3ac0a46fSAndroid Build Coastguard Worker {
2276*3ac0a46fSAndroid Build Coastguard Worker     uint32_t m;
2277*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint32_t) == 4);
2278*3ac0a46fSAndroid Build Coastguard Worker     m = value;
2279*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2280*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabLong(&m);
2281*3ac0a46fSAndroid Build Coastguard Worker     return (
2282*3ac0a46fSAndroid Build Coastguard Worker         TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG, 1, 4, &m));
2283*3ac0a46fSAndroid Build Coastguard Worker }
2284*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedLongArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint32_t * value)2285*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedLongArray(TIFF *tif, uint32_t *ndir,
2286*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir,
2287*3ac0a46fSAndroid Build Coastguard Worker                                                  uint16_t tag, uint32_t count,
2288*3ac0a46fSAndroid Build Coastguard Worker                                                  uint32_t *value)
2289*3ac0a46fSAndroid Build Coastguard Worker {
2290*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x40000000);
2291*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint32_t) == 4);
2292*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2293*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong(value, count);
2294*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG, count,
2295*3ac0a46fSAndroid Build Coastguard Worker                                       count * 4, value));
2296*3ac0a46fSAndroid Build Coastguard Worker }
2297*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedSlongArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int32_t * value)2298*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF *tif, uint32_t *ndir,
2299*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
2300*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
2301*3ac0a46fSAndroid Build Coastguard Worker                                                   int32_t *value)
2302*3ac0a46fSAndroid Build Coastguard Worker {
2303*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x40000000);
2304*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(int32_t) == 4);
2305*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2306*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong((uint32_t *)value, count);
2307*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG, count,
2308*3ac0a46fSAndroid Build Coastguard Worker                                       count * 4, value));
2309*3ac0a46fSAndroid Build Coastguard Worker }
2310*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedLong8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint64_t * value)2311*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF *tif, uint32_t *ndir,
2312*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
2313*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
2314*3ac0a46fSAndroid Build Coastguard Worker                                                   uint64_t *value)
2315*3ac0a46fSAndroid Build Coastguard Worker {
2316*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x20000000);
2317*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint64_t) == 8);
2318*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
2319*3ac0a46fSAndroid Build Coastguard Worker     {
2320*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, "TIFFWriteDirectoryTagCheckedLong8Array",
2321*3ac0a46fSAndroid Build Coastguard Worker                       "LONG8 not allowed for ClassicTIFF");
2322*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2323*3ac0a46fSAndroid Build Coastguard Worker     }
2324*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2325*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong8(value, count);
2326*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG8, count,
2327*3ac0a46fSAndroid Build Coastguard Worker                                       count * 8, value));
2328*3ac0a46fSAndroid Build Coastguard Worker }
2329*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedSlong8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,int64_t * value)2330*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF *tif, uint32_t *ndir,
2331*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFDirEntry *dir,
2332*3ac0a46fSAndroid Build Coastguard Worker                                                    uint16_t tag, uint32_t count,
2333*3ac0a46fSAndroid Build Coastguard Worker                                                    int64_t *value)
2334*3ac0a46fSAndroid Build Coastguard Worker {
2335*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x20000000);
2336*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(int64_t) == 8);
2337*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
2338*3ac0a46fSAndroid Build Coastguard Worker     {
2339*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, "TIFFWriteDirectoryTagCheckedSlong8Array",
2340*3ac0a46fSAndroid Build Coastguard Worker                       "SLONG8 not allowed for ClassicTIFF");
2341*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2342*3ac0a46fSAndroid Build Coastguard Worker     }
2343*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2344*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong8((uint64_t *)value, count);
2345*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG8, count,
2346*3ac0a46fSAndroid Build Coastguard Worker                                       count * 8, value));
2347*3ac0a46fSAndroid Build Coastguard Worker }
2348*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedRational(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,double value)2349*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedRational(TIFF *tif, uint32_t *ndir,
2350*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFDirEntry *dir, uint16_t tag,
2351*3ac0a46fSAndroid Build Coastguard Worker                                                 double value)
2352*3ac0a46fSAndroid Build Coastguard Worker {
2353*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagCheckedRational";
2354*3ac0a46fSAndroid Build Coastguard Worker     uint32_t m[2];
2355*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint32_t) == 4);
2356*3ac0a46fSAndroid Build Coastguard Worker     if (value < 0)
2357*3ac0a46fSAndroid Build Coastguard Worker     {
2358*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Negative value is illegal");
2359*3ac0a46fSAndroid Build Coastguard Worker         return 0;
2360*3ac0a46fSAndroid Build Coastguard Worker     }
2361*3ac0a46fSAndroid Build Coastguard Worker     else if (value != value)
2362*3ac0a46fSAndroid Build Coastguard Worker     {
2363*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Not-a-number value is illegal");
2364*3ac0a46fSAndroid Build Coastguard Worker         return 0;
2365*3ac0a46fSAndroid Build Coastguard Worker     }
2366*3ac0a46fSAndroid Build Coastguard Worker     /*--Rational2Double: New function also used for non-custom rational tags.
2367*3ac0a46fSAndroid Build Coastguard Worker      *  However, could be omitted here, because
2368*3ac0a46fSAndroid Build Coastguard Worker      * TIFFWriteDirectoryTagCheckedRational() is not used by code for custom
2369*3ac0a46fSAndroid Build Coastguard Worker      * tags, only by code for named-tiff-tags like FIELD_RESOLUTION and
2370*3ac0a46fSAndroid Build Coastguard Worker      * FIELD_POSITION */
2371*3ac0a46fSAndroid Build Coastguard Worker     else
2372*3ac0a46fSAndroid Build Coastguard Worker     {
2373*3ac0a46fSAndroid Build Coastguard Worker         DoubleToRational(value, &m[0], &m[1]);
2374*3ac0a46fSAndroid Build Coastguard Worker     }
2375*3ac0a46fSAndroid Build Coastguard Worker 
2376*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2377*3ac0a46fSAndroid Build Coastguard Worker     {
2378*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabLong(&m[0]);
2379*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabLong(&m[1]);
2380*3ac0a46fSAndroid Build Coastguard Worker     }
2381*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_RATIONAL, 1, 8,
2382*3ac0a46fSAndroid Build Coastguard Worker                                       &m[0]));
2383*3ac0a46fSAndroid Build Coastguard Worker }
2384*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedRationalArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,float * value)2385*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir,
2386*3ac0a46fSAndroid Build Coastguard Worker                                                      TIFFDirEntry *dir,
2387*3ac0a46fSAndroid Build Coastguard Worker                                                      uint16_t tag,
2388*3ac0a46fSAndroid Build Coastguard Worker                                                      uint32_t count,
2389*3ac0a46fSAndroid Build Coastguard Worker                                                      float *value)
2390*3ac0a46fSAndroid Build Coastguard Worker {
2391*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagCheckedRationalArray";
2392*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *m;
2393*3ac0a46fSAndroid Build Coastguard Worker     float *na;
2394*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *nb;
2395*3ac0a46fSAndroid Build Coastguard Worker     uint32_t nc;
2396*3ac0a46fSAndroid Build Coastguard Worker     int o;
2397*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint32_t) == 4);
2398*3ac0a46fSAndroid Build Coastguard Worker     m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
2399*3ac0a46fSAndroid Build Coastguard Worker     if (m == NULL)
2400*3ac0a46fSAndroid Build Coastguard Worker     {
2401*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2402*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2403*3ac0a46fSAndroid Build Coastguard Worker     }
2404*3ac0a46fSAndroid Build Coastguard Worker     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
2405*3ac0a46fSAndroid Build Coastguard Worker     {
2406*3ac0a46fSAndroid Build Coastguard Worker         DoubleToRational(*na, &nb[0], &nb[1]);
2407*3ac0a46fSAndroid Build Coastguard Worker     }
2408*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2409*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong(m, count * 2);
2410*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_RATIONAL, count,
2411*3ac0a46fSAndroid Build Coastguard Worker                                   count * 8, &m[0]);
2412*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, m);
2413*3ac0a46fSAndroid Build Coastguard Worker     return (o);
2414*3ac0a46fSAndroid Build Coastguard Worker }
2415*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedSrationalArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,float * value)2416*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir,
2417*3ac0a46fSAndroid Build Coastguard Worker                                                       TIFFDirEntry *dir,
2418*3ac0a46fSAndroid Build Coastguard Worker                                                       uint16_t tag,
2419*3ac0a46fSAndroid Build Coastguard Worker                                                       uint32_t count,
2420*3ac0a46fSAndroid Build Coastguard Worker                                                       float *value)
2421*3ac0a46fSAndroid Build Coastguard Worker {
2422*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagCheckedSrationalArray";
2423*3ac0a46fSAndroid Build Coastguard Worker     int32_t *m;
2424*3ac0a46fSAndroid Build Coastguard Worker     float *na;
2425*3ac0a46fSAndroid Build Coastguard Worker     int32_t *nb;
2426*3ac0a46fSAndroid Build Coastguard Worker     uint32_t nc;
2427*3ac0a46fSAndroid Build Coastguard Worker     int o;
2428*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(int32_t) == 4);
2429*3ac0a46fSAndroid Build Coastguard Worker     m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
2430*3ac0a46fSAndroid Build Coastguard Worker     if (m == NULL)
2431*3ac0a46fSAndroid Build Coastguard Worker     {
2432*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2433*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2434*3ac0a46fSAndroid Build Coastguard Worker     }
2435*3ac0a46fSAndroid Build Coastguard Worker     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
2436*3ac0a46fSAndroid Build Coastguard Worker     {
2437*3ac0a46fSAndroid Build Coastguard Worker         DoubleToSrational(*na, &nb[0], &nb[1]);
2438*3ac0a46fSAndroid Build Coastguard Worker     }
2439*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2440*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
2441*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SRATIONAL, count,
2442*3ac0a46fSAndroid Build Coastguard Worker                                   count * 8, &m[0]);
2443*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, m);
2444*3ac0a46fSAndroid Build Coastguard Worker     return (o);
2445*3ac0a46fSAndroid Build Coastguard Worker }
2446*3ac0a46fSAndroid Build Coastguard Worker 
2447*3ac0a46fSAndroid Build Coastguard Worker /*-- Rational2Double: additional write functions for double arrays */
2448*3ac0a46fSAndroid Build Coastguard Worker static int
TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)2449*3ac0a46fSAndroid Build Coastguard Worker TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir,
2450*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFDirEntry *dir, uint16_t tag,
2451*3ac0a46fSAndroid Build Coastguard Worker                                                 uint32_t count, double *value)
2452*3ac0a46fSAndroid Build Coastguard Worker {
2453*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] =
2454*3ac0a46fSAndroid Build Coastguard Worker         "TIFFWriteDirectoryTagCheckedRationalDoubleArray";
2455*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *m;
2456*3ac0a46fSAndroid Build Coastguard Worker     double *na;
2457*3ac0a46fSAndroid Build Coastguard Worker     uint32_t *nb;
2458*3ac0a46fSAndroid Build Coastguard Worker     uint32_t nc;
2459*3ac0a46fSAndroid Build Coastguard Worker     int o;
2460*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint32_t) == 4);
2461*3ac0a46fSAndroid Build Coastguard Worker     m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
2462*3ac0a46fSAndroid Build Coastguard Worker     if (m == NULL)
2463*3ac0a46fSAndroid Build Coastguard Worker     {
2464*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2465*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2466*3ac0a46fSAndroid Build Coastguard Worker     }
2467*3ac0a46fSAndroid Build Coastguard Worker     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
2468*3ac0a46fSAndroid Build Coastguard Worker     {
2469*3ac0a46fSAndroid Build Coastguard Worker         DoubleToRational(*na, &nb[0], &nb[1]);
2470*3ac0a46fSAndroid Build Coastguard Worker     }
2471*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2472*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong(m, count * 2);
2473*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_RATIONAL, count,
2474*3ac0a46fSAndroid Build Coastguard Worker                                   count * 8, &m[0]);
2475*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, m);
2476*3ac0a46fSAndroid Build Coastguard Worker     return (o);
2477*3ac0a46fSAndroid Build Coastguard Worker } /*-- TIFFWriteDirectoryTagCheckedRationalDoubleArray() ------- */
2478*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedSrationalDoubleArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)2479*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
2480*3ac0a46fSAndroid Build Coastguard Worker     TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count,
2481*3ac0a46fSAndroid Build Coastguard Worker     double *value)
2482*3ac0a46fSAndroid Build Coastguard Worker {
2483*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] =
2484*3ac0a46fSAndroid Build Coastguard Worker         "TIFFWriteDirectoryTagCheckedSrationalDoubleArray";
2485*3ac0a46fSAndroid Build Coastguard Worker     int32_t *m;
2486*3ac0a46fSAndroid Build Coastguard Worker     double *na;
2487*3ac0a46fSAndroid Build Coastguard Worker     int32_t *nb;
2488*3ac0a46fSAndroid Build Coastguard Worker     uint32_t nc;
2489*3ac0a46fSAndroid Build Coastguard Worker     int o;
2490*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(int32_t) == 4);
2491*3ac0a46fSAndroid Build Coastguard Worker     m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
2492*3ac0a46fSAndroid Build Coastguard Worker     if (m == NULL)
2493*3ac0a46fSAndroid Build Coastguard Worker     {
2494*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Out of memory");
2495*3ac0a46fSAndroid Build Coastguard Worker         return (0);
2496*3ac0a46fSAndroid Build Coastguard Worker     }
2497*3ac0a46fSAndroid Build Coastguard Worker     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
2498*3ac0a46fSAndroid Build Coastguard Worker     {
2499*3ac0a46fSAndroid Build Coastguard Worker         DoubleToSrational(*na, &nb[0], &nb[1]);
2500*3ac0a46fSAndroid Build Coastguard Worker     }
2501*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2502*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
2503*3ac0a46fSAndroid Build Coastguard Worker     o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SRATIONAL, count,
2504*3ac0a46fSAndroid Build Coastguard Worker                                   count * 8, &m[0]);
2505*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, m);
2506*3ac0a46fSAndroid Build Coastguard Worker     return (o);
2507*3ac0a46fSAndroid Build Coastguard Worker } /*--- TIFFWriteDirectoryTagCheckedSrationalDoubleArray() -------- */
2508*3ac0a46fSAndroid Build Coastguard Worker 
2509*3ac0a46fSAndroid Build Coastguard Worker /** -----  Rational2Double: Double To Rational Conversion
2510*3ac0a46fSAndroid Build Coastguard Worker ----------------------------------------------------------
2511*3ac0a46fSAndroid Build Coastguard Worker * There is a mathematical theorem to convert real numbers into a rational
2512*3ac0a46fSAndroid Build Coastguard Worker (integer fraction) number.
2513*3ac0a46fSAndroid Build Coastguard Worker * This is called "continuous fraction" which uses the Euclidean algorithm to
2514*3ac0a46fSAndroid Build Coastguard Worker find the greatest common divisor (GCD).
2515*3ac0a46fSAndroid Build Coastguard Worker *  (ref. e.g. https://de.wikipedia.org/wiki/Kettenbruch or
2516*3ac0a46fSAndroid Build Coastguard Worker https://en.wikipedia.org/wiki/Continued_fraction
2517*3ac0a46fSAndroid Build Coastguard Worker *             https://en.wikipedia.org/wiki/Euclidean_algorithm)
2518*3ac0a46fSAndroid Build Coastguard Worker * The following functions implement the
2519*3ac0a46fSAndroid Build Coastguard Worker * - ToRationalEuclideanGCD()		auxiliary function which mainly
2520*3ac0a46fSAndroid Build Coastguard Worker implements euclidean GCD
2521*3ac0a46fSAndroid Build Coastguard Worker * - DoubleToRational()			conversion function for un-signed
2522*3ac0a46fSAndroid Build Coastguard Worker rationals
2523*3ac0a46fSAndroid Build Coastguard Worker * - DoubleToSrational()			conversion function for signed rationals
2524*3ac0a46fSAndroid Build Coastguard Worker ------------------------------------------------------------------------------------------------------------------*/
2525*3ac0a46fSAndroid Build Coastguard Worker 
2526*3ac0a46fSAndroid Build Coastguard Worker /**---- ToRationalEuclideanGCD() -----------------------------------------
2527*3ac0a46fSAndroid Build Coastguard Worker * Calculates the rational fractional of a double input value
2528*3ac0a46fSAndroid Build Coastguard Worker * using the Euclidean algorithm to find the greatest common divisor (GCD)
2529*3ac0a46fSAndroid Build Coastguard Worker ------------------------------------------------------------------------*/
ToRationalEuclideanGCD(double value,int blnUseSignedRange,int blnUseSmallRange,uint64_t * ullNum,uint64_t * ullDenom)2530*3ac0a46fSAndroid Build Coastguard Worker static void ToRationalEuclideanGCD(double value, int blnUseSignedRange,
2531*3ac0a46fSAndroid Build Coastguard Worker                                    int blnUseSmallRange, uint64_t *ullNum,
2532*3ac0a46fSAndroid Build Coastguard Worker                                    uint64_t *ullDenom)
2533*3ac0a46fSAndroid Build Coastguard Worker {
2534*3ac0a46fSAndroid Build Coastguard Worker     /* Internally, the integer variables can be bigger than the external ones,
2535*3ac0a46fSAndroid Build Coastguard Worker      * as long as the result will fit into the external variable size.
2536*3ac0a46fSAndroid Build Coastguard Worker      */
2537*3ac0a46fSAndroid Build Coastguard Worker     uint64_t numSum[3] = {0, 1, 0}, denomSum[3] = {1, 0, 0};
2538*3ac0a46fSAndroid Build Coastguard Worker     uint64_t aux, bigNum, bigDenom;
2539*3ac0a46fSAndroid Build Coastguard Worker     uint64_t returnLimit;
2540*3ac0a46fSAndroid Build Coastguard Worker     int i;
2541*3ac0a46fSAndroid Build Coastguard Worker     uint64_t nMax;
2542*3ac0a46fSAndroid Build Coastguard Worker     double fMax;
2543*3ac0a46fSAndroid Build Coastguard Worker     unsigned long maxDenom;
2544*3ac0a46fSAndroid Build Coastguard Worker     /*-- nMax and fMax defines the initial accuracy of the starting fractional,
2545*3ac0a46fSAndroid Build Coastguard Worker      *   or better, the highest used integer numbers used within the starting
2546*3ac0a46fSAndroid Build Coastguard Worker      * fractional (bigNum/bigDenom). There are two approaches, which can
2547*3ac0a46fSAndroid Build Coastguard Worker      * accidentally lead to different accuracies just depending on the value.
2548*3ac0a46fSAndroid Build Coastguard Worker      *   Therefore, blnUseSmallRange steers this behavior.
2549*3ac0a46fSAndroid Build Coastguard Worker      *   For long long nMax = ((9223372036854775807-1)/2); for long nMax =
2550*3ac0a46fSAndroid Build Coastguard Worker      * ((2147483647-1)/2);
2551*3ac0a46fSAndroid Build Coastguard Worker      */
2552*3ac0a46fSAndroid Build Coastguard Worker     if (blnUseSmallRange)
2553*3ac0a46fSAndroid Build Coastguard Worker     {
2554*3ac0a46fSAndroid Build Coastguard Worker         nMax = (uint64_t)((2147483647 - 1) / 2); /* for ULONG range */
2555*3ac0a46fSAndroid Build Coastguard Worker     }
2556*3ac0a46fSAndroid Build Coastguard Worker     else
2557*3ac0a46fSAndroid Build Coastguard Worker     {
2558*3ac0a46fSAndroid Build Coastguard Worker         nMax = ((9223372036854775807 - 1) / 2); /* for ULLONG range */
2559*3ac0a46fSAndroid Build Coastguard Worker     }
2560*3ac0a46fSAndroid Build Coastguard Worker     fMax = (double)nMax;
2561*3ac0a46fSAndroid Build Coastguard Worker 
2562*3ac0a46fSAndroid Build Coastguard Worker     /*-- For the Euclidean GCD define the denominator range, so that it stays
2563*3ac0a46fSAndroid Build Coastguard Worker      * within size of unsigned long variables. maxDenom should be LONG_MAX for
2564*3ac0a46fSAndroid Build Coastguard Worker      * negative values and ULONG_MAX for positive ones. Also the final returned
2565*3ac0a46fSAndroid Build Coastguard Worker      * value of ullNum and ullDenom is limited according to signed- or
2566*3ac0a46fSAndroid Build Coastguard Worker      * unsigned-range.
2567*3ac0a46fSAndroid Build Coastguard Worker      */
2568*3ac0a46fSAndroid Build Coastguard Worker     if (blnUseSignedRange)
2569*3ac0a46fSAndroid Build Coastguard Worker     {
2570*3ac0a46fSAndroid Build Coastguard Worker         maxDenom = 2147483647UL; /*LONG_MAX = 0x7FFFFFFFUL*/
2571*3ac0a46fSAndroid Build Coastguard Worker         returnLimit = maxDenom;
2572*3ac0a46fSAndroid Build Coastguard Worker     }
2573*3ac0a46fSAndroid Build Coastguard Worker     else
2574*3ac0a46fSAndroid Build Coastguard Worker     {
2575*3ac0a46fSAndroid Build Coastguard Worker         maxDenom = 0xFFFFFFFFUL; /*ULONG_MAX = 0xFFFFFFFFUL*/
2576*3ac0a46fSAndroid Build Coastguard Worker         returnLimit = maxDenom;
2577*3ac0a46fSAndroid Build Coastguard Worker     }
2578*3ac0a46fSAndroid Build Coastguard Worker 
2579*3ac0a46fSAndroid Build Coastguard Worker     /*-- First generate a rational fraction (bigNum/bigDenom) which represents
2580*3ac0a46fSAndroid Build Coastguard Worker      *the value as a rational number with the highest accuracy. Therefore,
2581*3ac0a46fSAndroid Build Coastguard Worker      *uint64_t (uint64_t) is needed. This rational fraction is then reduced
2582*3ac0a46fSAndroid Build Coastguard Worker      *using the Euclidean algorithm to find the greatest common divisor (GCD).
2583*3ac0a46fSAndroid Build Coastguard Worker      *   bigNum   = big numinator of value without fraction (or cut residual
2584*3ac0a46fSAndroid Build Coastguard Worker      *fraction) bigDenom = big denominator of value
2585*3ac0a46fSAndroid Build Coastguard Worker      *-- Break-criteria so that uint64_t cast to "bigNum" introduces no error
2586*3ac0a46fSAndroid Build Coastguard Worker      *and bigDenom has no overflow, and stop with enlargement of fraction when
2587*3ac0a46fSAndroid Build Coastguard Worker      *the double-value of it reaches an integer number without fractional part.
2588*3ac0a46fSAndroid Build Coastguard Worker      */
2589*3ac0a46fSAndroid Build Coastguard Worker     bigDenom = 1;
2590*3ac0a46fSAndroid Build Coastguard Worker     while ((value != floor(value)) && (value < fMax) && (bigDenom < nMax))
2591*3ac0a46fSAndroid Build Coastguard Worker     {
2592*3ac0a46fSAndroid Build Coastguard Worker         bigDenom <<= 1;
2593*3ac0a46fSAndroid Build Coastguard Worker         value *= 2;
2594*3ac0a46fSAndroid Build Coastguard Worker     }
2595*3ac0a46fSAndroid Build Coastguard Worker     bigNum = (uint64_t)value;
2596*3ac0a46fSAndroid Build Coastguard Worker 
2597*3ac0a46fSAndroid Build Coastguard Worker     /*-- Start Euclidean algorithm to find the greatest common divisor (GCD) --
2598*3ac0a46fSAndroid Build Coastguard Worker      */
2599*3ac0a46fSAndroid Build Coastguard Worker #define MAX_ITERATIONS 64
2600*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < MAX_ITERATIONS; i++)
2601*3ac0a46fSAndroid Build Coastguard Worker     {
2602*3ac0a46fSAndroid Build Coastguard Worker         uint64_t val;
2603*3ac0a46fSAndroid Build Coastguard Worker         /* if bigDenom is not zero, calculate integer part of fraction. */
2604*3ac0a46fSAndroid Build Coastguard Worker         if (bigDenom == 0)
2605*3ac0a46fSAndroid Build Coastguard Worker         {
2606*3ac0a46fSAndroid Build Coastguard Worker             break;
2607*3ac0a46fSAndroid Build Coastguard Worker         }
2608*3ac0a46fSAndroid Build Coastguard Worker         val = bigNum / bigDenom;
2609*3ac0a46fSAndroid Build Coastguard Worker 
2610*3ac0a46fSAndroid Build Coastguard Worker         /* Set bigDenom to reminder of bigNum/bigDenom and bigNum to previous
2611*3ac0a46fSAndroid Build Coastguard Worker          * denominator bigDenom. */
2612*3ac0a46fSAndroid Build Coastguard Worker         aux = bigNum;
2613*3ac0a46fSAndroid Build Coastguard Worker         bigNum = bigDenom;
2614*3ac0a46fSAndroid Build Coastguard Worker         bigDenom = aux % bigDenom;
2615*3ac0a46fSAndroid Build Coastguard Worker 
2616*3ac0a46fSAndroid Build Coastguard Worker         /* calculate next denominator and check for its given maximum */
2617*3ac0a46fSAndroid Build Coastguard Worker         aux = val;
2618*3ac0a46fSAndroid Build Coastguard Worker         if (denomSum[1] * val + denomSum[0] >= maxDenom)
2619*3ac0a46fSAndroid Build Coastguard Worker         {
2620*3ac0a46fSAndroid Build Coastguard Worker             aux = (maxDenom - denomSum[0]) / denomSum[1];
2621*3ac0a46fSAndroid Build Coastguard Worker             if (aux * 2 >= val || denomSum[1] >= maxDenom)
2622*3ac0a46fSAndroid Build Coastguard Worker                 i = (MAX_ITERATIONS +
2623*3ac0a46fSAndroid Build Coastguard Worker                      1); /* exit but execute rest of for-loop */
2624*3ac0a46fSAndroid Build Coastguard Worker             else
2625*3ac0a46fSAndroid Build Coastguard Worker                 break;
2626*3ac0a46fSAndroid Build Coastguard Worker         }
2627*3ac0a46fSAndroid Build Coastguard Worker         /* calculate next numerator to numSum2 and save previous one to numSum0;
2628*3ac0a46fSAndroid Build Coastguard Worker          * numSum1 just copy of numSum2. */
2629*3ac0a46fSAndroid Build Coastguard Worker         numSum[2] = aux * numSum[1] + numSum[0];
2630*3ac0a46fSAndroid Build Coastguard Worker         numSum[0] = numSum[1];
2631*3ac0a46fSAndroid Build Coastguard Worker         numSum[1] = numSum[2];
2632*3ac0a46fSAndroid Build Coastguard Worker         /* calculate next denominator to denomSum2 and save previous one to
2633*3ac0a46fSAndroid Build Coastguard Worker          * denomSum0; denomSum1 just copy of denomSum2. */
2634*3ac0a46fSAndroid Build Coastguard Worker         denomSum[2] = aux * denomSum[1] + denomSum[0];
2635*3ac0a46fSAndroid Build Coastguard Worker         denomSum[0] = denomSum[1];
2636*3ac0a46fSAndroid Build Coastguard Worker         denomSum[1] = denomSum[2];
2637*3ac0a46fSAndroid Build Coastguard Worker     }
2638*3ac0a46fSAndroid Build Coastguard Worker 
2639*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check and adapt for final variable size and return values; reduces
2640*3ac0a46fSAndroid Build Coastguard Worker      * internal accuracy; denominator is kept in ULONG-range with maxDenom -- */
2641*3ac0a46fSAndroid Build Coastguard Worker     while (numSum[1] > returnLimit || denomSum[1] > returnLimit)
2642*3ac0a46fSAndroid Build Coastguard Worker     {
2643*3ac0a46fSAndroid Build Coastguard Worker         numSum[1] = numSum[1] / 2;
2644*3ac0a46fSAndroid Build Coastguard Worker         denomSum[1] = denomSum[1] / 2;
2645*3ac0a46fSAndroid Build Coastguard Worker     }
2646*3ac0a46fSAndroid Build Coastguard Worker 
2647*3ac0a46fSAndroid Build Coastguard Worker     /* return values */
2648*3ac0a46fSAndroid Build Coastguard Worker     *ullNum = numSum[1];
2649*3ac0a46fSAndroid Build Coastguard Worker     *ullDenom = denomSum[1];
2650*3ac0a46fSAndroid Build Coastguard Worker 
2651*3ac0a46fSAndroid Build Coastguard Worker } /*-- ToRationalEuclideanGCD() -------------- */
2652*3ac0a46fSAndroid Build Coastguard Worker 
2653*3ac0a46fSAndroid Build Coastguard Worker /**---- DoubleToRational() -----------------------------------------------
2654*3ac0a46fSAndroid Build Coastguard Worker * Calculates the rational fractional of a double input value
2655*3ac0a46fSAndroid Build Coastguard Worker * for UN-SIGNED rationals,
2656*3ac0a46fSAndroid Build Coastguard Worker * using the Euclidean algorithm to find the greatest common divisor (GCD)
2657*3ac0a46fSAndroid Build Coastguard Worker ------------------------------------------------------------------------*/
DoubleToRational(double value,uint32_t * num,uint32_t * denom)2658*3ac0a46fSAndroid Build Coastguard Worker static void DoubleToRational(double value, uint32_t *num, uint32_t *denom)
2659*3ac0a46fSAndroid Build Coastguard Worker {
2660*3ac0a46fSAndroid Build Coastguard Worker     /*---- UN-SIGNED RATIONAL ---- */
2661*3ac0a46fSAndroid Build Coastguard Worker     double dblDiff, dblDiff2;
2662*3ac0a46fSAndroid Build Coastguard Worker     uint64_t ullNum, ullDenom, ullNum2, ullDenom2;
2663*3ac0a46fSAndroid Build Coastguard Worker 
2664*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for negative values. If so it is an error. */
2665*3ac0a46fSAndroid Build Coastguard Worker     /* Test written that way to catch NaN */
2666*3ac0a46fSAndroid Build Coastguard Worker     if (!(value >= 0))
2667*3ac0a46fSAndroid Build Coastguard Worker     {
2668*3ac0a46fSAndroid Build Coastguard Worker         *num = *denom = 0;
2669*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExt(0, "TIFFLib: DoubleToRational()",
2670*3ac0a46fSAndroid Build Coastguard Worker                      " Negative Value for Unsigned Rational given.");
2671*3ac0a46fSAndroid Build Coastguard Worker         return;
2672*3ac0a46fSAndroid Build Coastguard Worker     }
2673*3ac0a46fSAndroid Build Coastguard Worker 
2674*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for too big numbers (> ULONG_MAX) -- */
2675*3ac0a46fSAndroid Build Coastguard Worker     if (value > 0xFFFFFFFFUL)
2676*3ac0a46fSAndroid Build Coastguard Worker     {
2677*3ac0a46fSAndroid Build Coastguard Worker         *num = 0xFFFFFFFFU;
2678*3ac0a46fSAndroid Build Coastguard Worker         *denom = 0;
2679*3ac0a46fSAndroid Build Coastguard Worker         return;
2680*3ac0a46fSAndroid Build Coastguard Worker     }
2681*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for easy integer numbers -- */
2682*3ac0a46fSAndroid Build Coastguard Worker     if (value == (uint32_t)(value))
2683*3ac0a46fSAndroid Build Coastguard Worker     {
2684*3ac0a46fSAndroid Build Coastguard Worker         *num = (uint32_t)value;
2685*3ac0a46fSAndroid Build Coastguard Worker         *denom = 1;
2686*3ac0a46fSAndroid Build Coastguard Worker         return;
2687*3ac0a46fSAndroid Build Coastguard Worker     }
2688*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for too small numbers for "unsigned long" type rationals -- */
2689*3ac0a46fSAndroid Build Coastguard Worker     if (value < 1.0 / (double)0xFFFFFFFFUL)
2690*3ac0a46fSAndroid Build Coastguard Worker     {
2691*3ac0a46fSAndroid Build Coastguard Worker         *num = 0;
2692*3ac0a46fSAndroid Build Coastguard Worker         *denom = 0xFFFFFFFFU;
2693*3ac0a46fSAndroid Build Coastguard Worker         return;
2694*3ac0a46fSAndroid Build Coastguard Worker     }
2695*3ac0a46fSAndroid Build Coastguard Worker 
2696*3ac0a46fSAndroid Build Coastguard Worker     /*-- There are two approaches using the Euclidean algorithm,
2697*3ac0a46fSAndroid Build Coastguard Worker      *   which can accidentally lead to different accuracies just depending on
2698*3ac0a46fSAndroid Build Coastguard Worker      * the value. Try both and define which one was better.
2699*3ac0a46fSAndroid Build Coastguard Worker      */
2700*3ac0a46fSAndroid Build Coastguard Worker     ToRationalEuclideanGCD(value, FALSE, FALSE, &ullNum, &ullDenom);
2701*3ac0a46fSAndroid Build Coastguard Worker     ToRationalEuclideanGCD(value, FALSE, TRUE, &ullNum2, &ullDenom2);
2702*3ac0a46fSAndroid Build Coastguard Worker     /*-- Double-Check, that returned values fit into ULONG :*/
2703*3ac0a46fSAndroid Build Coastguard Worker     if (ullNum > 0xFFFFFFFFUL || ullDenom > 0xFFFFFFFFUL ||
2704*3ac0a46fSAndroid Build Coastguard Worker         ullNum2 > 0xFFFFFFFFUL || ullDenom2 > 0xFFFFFFFFUL)
2705*3ac0a46fSAndroid Build Coastguard Worker     {
2706*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExt(0, "TIFFLib: DoubleToRational()",
2707*3ac0a46fSAndroid Build Coastguard Worker                      " Num or Denom exceeds ULONG: val=%14.6f, num=%12" PRIu64
2708*3ac0a46fSAndroid Build Coastguard Worker                      ", denom=%12" PRIu64 " | num2=%12" PRIu64
2709*3ac0a46fSAndroid Build Coastguard Worker                      ", denom2=%12" PRIu64 "",
2710*3ac0a46fSAndroid Build Coastguard Worker                      value, ullNum, ullDenom, ullNum2, ullDenom2);
2711*3ac0a46fSAndroid Build Coastguard Worker         assert(0);
2712*3ac0a46fSAndroid Build Coastguard Worker     }
2713*3ac0a46fSAndroid Build Coastguard Worker 
2714*3ac0a46fSAndroid Build Coastguard Worker     /* Check, which one has higher accuracy and take that. */
2715*3ac0a46fSAndroid Build Coastguard Worker     dblDiff = fabs(value - ((double)ullNum / (double)ullDenom));
2716*3ac0a46fSAndroid Build Coastguard Worker     dblDiff2 = fabs(value - ((double)ullNum2 / (double)ullDenom2));
2717*3ac0a46fSAndroid Build Coastguard Worker     if (dblDiff < dblDiff2)
2718*3ac0a46fSAndroid Build Coastguard Worker     {
2719*3ac0a46fSAndroid Build Coastguard Worker         *num = (uint32_t)ullNum;
2720*3ac0a46fSAndroid Build Coastguard Worker         *denom = (uint32_t)ullDenom;
2721*3ac0a46fSAndroid Build Coastguard Worker     }
2722*3ac0a46fSAndroid Build Coastguard Worker     else
2723*3ac0a46fSAndroid Build Coastguard Worker     {
2724*3ac0a46fSAndroid Build Coastguard Worker         *num = (uint32_t)ullNum2;
2725*3ac0a46fSAndroid Build Coastguard Worker         *denom = (uint32_t)ullDenom2;
2726*3ac0a46fSAndroid Build Coastguard Worker     }
2727*3ac0a46fSAndroid Build Coastguard Worker } /*-- DoubleToRational() -------------- */
2728*3ac0a46fSAndroid Build Coastguard Worker 
2729*3ac0a46fSAndroid Build Coastguard Worker /**---- DoubleToSrational() -----------------------------------------------
2730*3ac0a46fSAndroid Build Coastguard Worker * Calculates the rational fractional of a double input value
2731*3ac0a46fSAndroid Build Coastguard Worker * for SIGNED rationals,
2732*3ac0a46fSAndroid Build Coastguard Worker * using the Euclidean algorithm to find the greatest common divisor (GCD)
2733*3ac0a46fSAndroid Build Coastguard Worker ------------------------------------------------------------------------*/
DoubleToSrational(double value,int32_t * num,int32_t * denom)2734*3ac0a46fSAndroid Build Coastguard Worker static void DoubleToSrational(double value, int32_t *num, int32_t *denom)
2735*3ac0a46fSAndroid Build Coastguard Worker {
2736*3ac0a46fSAndroid Build Coastguard Worker     /*---- SIGNED RATIONAL ----*/
2737*3ac0a46fSAndroid Build Coastguard Worker     int neg = 1;
2738*3ac0a46fSAndroid Build Coastguard Worker     double dblDiff, dblDiff2;
2739*3ac0a46fSAndroid Build Coastguard Worker     uint64_t ullNum, ullDenom, ullNum2, ullDenom2;
2740*3ac0a46fSAndroid Build Coastguard Worker 
2741*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for negative values and use then the positive one for internal
2742*3ac0a46fSAndroid Build Coastguard Worker      * calculations, but take the sign into account before returning. */
2743*3ac0a46fSAndroid Build Coastguard Worker     if (value < 0)
2744*3ac0a46fSAndroid Build Coastguard Worker     {
2745*3ac0a46fSAndroid Build Coastguard Worker         neg = -1;
2746*3ac0a46fSAndroid Build Coastguard Worker         value = -value;
2747*3ac0a46fSAndroid Build Coastguard Worker     }
2748*3ac0a46fSAndroid Build Coastguard Worker 
2749*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for too big numbers (> LONG_MAX) -- */
2750*3ac0a46fSAndroid Build Coastguard Worker     if (value > 0x7FFFFFFFL)
2751*3ac0a46fSAndroid Build Coastguard Worker     {
2752*3ac0a46fSAndroid Build Coastguard Worker         *num = 0x7FFFFFFFL;
2753*3ac0a46fSAndroid Build Coastguard Worker         *denom = 0;
2754*3ac0a46fSAndroid Build Coastguard Worker         return;
2755*3ac0a46fSAndroid Build Coastguard Worker     }
2756*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for easy numbers -- */
2757*3ac0a46fSAndroid Build Coastguard Worker     if (value == (int32_t)(value))
2758*3ac0a46fSAndroid Build Coastguard Worker     {
2759*3ac0a46fSAndroid Build Coastguard Worker         *num = (int32_t)(neg * value);
2760*3ac0a46fSAndroid Build Coastguard Worker         *denom = 1;
2761*3ac0a46fSAndroid Build Coastguard Worker         return;
2762*3ac0a46fSAndroid Build Coastguard Worker     }
2763*3ac0a46fSAndroid Build Coastguard Worker     /*-- Check for too small numbers for "long" type rationals -- */
2764*3ac0a46fSAndroid Build Coastguard Worker     if (value < 1.0 / (double)0x7FFFFFFFL)
2765*3ac0a46fSAndroid Build Coastguard Worker     {
2766*3ac0a46fSAndroid Build Coastguard Worker         *num = 0;
2767*3ac0a46fSAndroid Build Coastguard Worker         *denom = 0x7FFFFFFFL;
2768*3ac0a46fSAndroid Build Coastguard Worker         return;
2769*3ac0a46fSAndroid Build Coastguard Worker     }
2770*3ac0a46fSAndroid Build Coastguard Worker 
2771*3ac0a46fSAndroid Build Coastguard Worker     /*-- There are two approaches using the Euclidean algorithm,
2772*3ac0a46fSAndroid Build Coastguard Worker      *   which can accidentally lead to different accuracies just depending on
2773*3ac0a46fSAndroid Build Coastguard Worker      * the value. Try both and define which one was better. Furthermore, set
2774*3ac0a46fSAndroid Build Coastguard Worker      * behavior of ToRationalEuclideanGCD() to the range of signed-long.
2775*3ac0a46fSAndroid Build Coastguard Worker      */
2776*3ac0a46fSAndroid Build Coastguard Worker     ToRationalEuclideanGCD(value, TRUE, FALSE, &ullNum, &ullDenom);
2777*3ac0a46fSAndroid Build Coastguard Worker     ToRationalEuclideanGCD(value, TRUE, TRUE, &ullNum2, &ullDenom2);
2778*3ac0a46fSAndroid Build Coastguard Worker     /*-- Double-Check, that returned values fit into LONG :*/
2779*3ac0a46fSAndroid Build Coastguard Worker     if (ullNum > 0x7FFFFFFFL || ullDenom > 0x7FFFFFFFL ||
2780*3ac0a46fSAndroid Build Coastguard Worker         ullNum2 > 0x7FFFFFFFL || ullDenom2 > 0x7FFFFFFFL)
2781*3ac0a46fSAndroid Build Coastguard Worker     {
2782*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExt(0, "TIFFLib: DoubleToSrational()",
2783*3ac0a46fSAndroid Build Coastguard Worker                      " Num or Denom exceeds LONG: val=%14.6f, num=%12" PRIu64
2784*3ac0a46fSAndroid Build Coastguard Worker                      ", denom=%12" PRIu64 " | num2=%12" PRIu64
2785*3ac0a46fSAndroid Build Coastguard Worker                      ", denom2=%12" PRIu64 "",
2786*3ac0a46fSAndroid Build Coastguard Worker                      neg * value, ullNum, ullDenom, ullNum2, ullDenom2);
2787*3ac0a46fSAndroid Build Coastguard Worker         assert(0);
2788*3ac0a46fSAndroid Build Coastguard Worker     }
2789*3ac0a46fSAndroid Build Coastguard Worker 
2790*3ac0a46fSAndroid Build Coastguard Worker     /* Check, which one has higher accuracy and take that. */
2791*3ac0a46fSAndroid Build Coastguard Worker     dblDiff = fabs(value - ((double)ullNum / (double)ullDenom));
2792*3ac0a46fSAndroid Build Coastguard Worker     dblDiff2 = fabs(value - ((double)ullNum2 / (double)ullDenom2));
2793*3ac0a46fSAndroid Build Coastguard Worker     if (dblDiff < dblDiff2)
2794*3ac0a46fSAndroid Build Coastguard Worker     {
2795*3ac0a46fSAndroid Build Coastguard Worker         *num = (int32_t)(neg * (long)ullNum);
2796*3ac0a46fSAndroid Build Coastguard Worker         *denom = (int32_t)ullDenom;
2797*3ac0a46fSAndroid Build Coastguard Worker     }
2798*3ac0a46fSAndroid Build Coastguard Worker     else
2799*3ac0a46fSAndroid Build Coastguard Worker     {
2800*3ac0a46fSAndroid Build Coastguard Worker         *num = (int32_t)(neg * (long)ullNum2);
2801*3ac0a46fSAndroid Build Coastguard Worker         *denom = (int32_t)ullDenom2;
2802*3ac0a46fSAndroid Build Coastguard Worker     }
2803*3ac0a46fSAndroid Build Coastguard Worker } /*-- DoubleToSrational() --------------*/
2804*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedFloatArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,float * value)2805*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF *tif, uint32_t *ndir,
2806*3ac0a46fSAndroid Build Coastguard Worker                                                   TIFFDirEntry *dir,
2807*3ac0a46fSAndroid Build Coastguard Worker                                                   uint16_t tag, uint32_t count,
2808*3ac0a46fSAndroid Build Coastguard Worker                                                   float *value)
2809*3ac0a46fSAndroid Build Coastguard Worker {
2810*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x40000000);
2811*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(float) == 4);
2812*3ac0a46fSAndroid Build Coastguard Worker     TIFFCvtNativeToIEEEFloat(tif, count, &value);
2813*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2814*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfFloat(value, count);
2815*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_FLOAT, count,
2816*3ac0a46fSAndroid Build Coastguard Worker                                       count * 4, value));
2817*3ac0a46fSAndroid Build Coastguard Worker }
2818*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedDoubleArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,double * value)2819*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF *tif, uint32_t *ndir,
2820*3ac0a46fSAndroid Build Coastguard Worker                                                    TIFFDirEntry *dir,
2821*3ac0a46fSAndroid Build Coastguard Worker                                                    uint16_t tag, uint32_t count,
2822*3ac0a46fSAndroid Build Coastguard Worker                                                    double *value)
2823*3ac0a46fSAndroid Build Coastguard Worker {
2824*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x20000000);
2825*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(double) == 8);
2826*3ac0a46fSAndroid Build Coastguard Worker     TIFFCvtNativeToIEEEDouble(tif, count, &value);
2827*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2828*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfDouble(value, count);
2829*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_DOUBLE, count,
2830*3ac0a46fSAndroid Build Coastguard Worker                                       count * 8, value));
2831*3ac0a46fSAndroid Build Coastguard Worker }
2832*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedIfdArray(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint32_t * value)2833*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF *tif, uint32_t *ndir,
2834*3ac0a46fSAndroid Build Coastguard Worker                                                 TIFFDirEntry *dir, uint16_t tag,
2835*3ac0a46fSAndroid Build Coastguard Worker                                                 uint32_t count, uint32_t *value)
2836*3ac0a46fSAndroid Build Coastguard Worker {
2837*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x40000000);
2838*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint32_t) == 4);
2839*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2840*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong(value, count);
2841*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD, count,
2842*3ac0a46fSAndroid Build Coastguard Worker                                       count * 4, value));
2843*3ac0a46fSAndroid Build Coastguard Worker }
2844*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagCheckedIfd8Array(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint32_t count,uint64_t * value)2845*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF *tif, uint32_t *ndir,
2846*3ac0a46fSAndroid Build Coastguard Worker                                                  TIFFDirEntry *dir,
2847*3ac0a46fSAndroid Build Coastguard Worker                                                  uint16_t tag, uint32_t count,
2848*3ac0a46fSAndroid Build Coastguard Worker                                                  uint64_t *value)
2849*3ac0a46fSAndroid Build Coastguard Worker {
2850*3ac0a46fSAndroid Build Coastguard Worker     assert(count < 0x20000000);
2851*3ac0a46fSAndroid Build Coastguard Worker     assert(sizeof(uint64_t) == 8);
2852*3ac0a46fSAndroid Build Coastguard Worker     assert(tif->tif_flags & TIFF_BIGTIFF);
2853*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
2854*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabArrayOfLong8(value, count);
2855*3ac0a46fSAndroid Build Coastguard Worker     return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD8, count,
2856*3ac0a46fSAndroid Build Coastguard Worker                                       count * 8, value));
2857*3ac0a46fSAndroid Build Coastguard Worker }
2858*3ac0a46fSAndroid Build Coastguard Worker 
TIFFWriteDirectoryTagData(TIFF * tif,uint32_t * ndir,TIFFDirEntry * dir,uint16_t tag,uint16_t datatype,uint32_t count,uint32_t datalength,void * data)2859*3ac0a46fSAndroid Build Coastguard Worker static int TIFFWriteDirectoryTagData(TIFF *tif, uint32_t *ndir,
2860*3ac0a46fSAndroid Build Coastguard Worker                                      TIFFDirEntry *dir, uint16_t tag,
2861*3ac0a46fSAndroid Build Coastguard Worker                                      uint16_t datatype, uint32_t count,
2862*3ac0a46fSAndroid Build Coastguard Worker                                      uint32_t datalength, void *data)
2863*3ac0a46fSAndroid Build Coastguard Worker {
2864*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFWriteDirectoryTagData";
2865*3ac0a46fSAndroid Build Coastguard Worker     uint32_t m;
2866*3ac0a46fSAndroid Build Coastguard Worker     m = 0;
2867*3ac0a46fSAndroid Build Coastguard Worker     while (m < (*ndir))
2868*3ac0a46fSAndroid Build Coastguard Worker     {
2869*3ac0a46fSAndroid Build Coastguard Worker         assert(dir[m].tdir_tag != tag);
2870*3ac0a46fSAndroid Build Coastguard Worker         if (dir[m].tdir_tag > tag)
2871*3ac0a46fSAndroid Build Coastguard Worker             break;
2872*3ac0a46fSAndroid Build Coastguard Worker         m++;
2873*3ac0a46fSAndroid Build Coastguard Worker     }
2874*3ac0a46fSAndroid Build Coastguard Worker     if (m < (*ndir))
2875*3ac0a46fSAndroid Build Coastguard Worker     {
2876*3ac0a46fSAndroid Build Coastguard Worker         uint32_t n;
2877*3ac0a46fSAndroid Build Coastguard Worker         for (n = *ndir; n > m; n--)
2878*3ac0a46fSAndroid Build Coastguard Worker             dir[n] = dir[n - 1];
2879*3ac0a46fSAndroid Build Coastguard Worker     }
2880*3ac0a46fSAndroid Build Coastguard Worker     dir[m].tdir_tag = tag;
2881*3ac0a46fSAndroid Build Coastguard Worker     dir[m].tdir_type = datatype;
2882*3ac0a46fSAndroid Build Coastguard Worker     dir[m].tdir_count = count;
2883*3ac0a46fSAndroid Build Coastguard Worker     dir[m].tdir_offset.toff_long8 = 0;
2884*3ac0a46fSAndroid Build Coastguard Worker     if (datalength <= ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
2885*3ac0a46fSAndroid Build Coastguard Worker     {
2886*3ac0a46fSAndroid Build Coastguard Worker         if (data && datalength)
2887*3ac0a46fSAndroid Build Coastguard Worker         {
2888*3ac0a46fSAndroid Build Coastguard Worker             _TIFFmemcpy(&dir[m].tdir_offset, data, datalength);
2889*3ac0a46fSAndroid Build Coastguard Worker         }
2890*3ac0a46fSAndroid Build Coastguard Worker     }
2891*3ac0a46fSAndroid Build Coastguard Worker     else
2892*3ac0a46fSAndroid Build Coastguard Worker     {
2893*3ac0a46fSAndroid Build Coastguard Worker         uint64_t na, nb;
2894*3ac0a46fSAndroid Build Coastguard Worker         na = tif->tif_dataoff;
2895*3ac0a46fSAndroid Build Coastguard Worker         nb = na + datalength;
2896*3ac0a46fSAndroid Build Coastguard Worker         if (!(tif->tif_flags & TIFF_BIGTIFF))
2897*3ac0a46fSAndroid Build Coastguard Worker             nb = (uint32_t)nb;
2898*3ac0a46fSAndroid Build Coastguard Worker         if ((nb < na) || (nb < datalength))
2899*3ac0a46fSAndroid Build Coastguard Worker         {
2900*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
2901*3ac0a46fSAndroid Build Coastguard Worker             return (0);
2902*3ac0a46fSAndroid Build Coastguard Worker         }
2903*3ac0a46fSAndroid Build Coastguard Worker         if (!SeekOK(tif, na))
2904*3ac0a46fSAndroid Build Coastguard Worker         {
2905*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "IO error writing tag data");
2906*3ac0a46fSAndroid Build Coastguard Worker             return (0);
2907*3ac0a46fSAndroid Build Coastguard Worker         }
2908*3ac0a46fSAndroid Build Coastguard Worker         if (datalength >= 0x80000000UL)
2909*3ac0a46fSAndroid Build Coastguard Worker         {
2910*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
2911*3ac0a46fSAndroid Build Coastguard Worker                           "libtiff does not allow writing more than 2147483647 "
2912*3ac0a46fSAndroid Build Coastguard Worker                           "bytes in a tag");
2913*3ac0a46fSAndroid Build Coastguard Worker             return (0);
2914*3ac0a46fSAndroid Build Coastguard Worker         }
2915*3ac0a46fSAndroid Build Coastguard Worker         if (!WriteOK(tif, data, (tmsize_t)datalength))
2916*3ac0a46fSAndroid Build Coastguard Worker         {
2917*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "IO error writing tag data");
2918*3ac0a46fSAndroid Build Coastguard Worker             return (0);
2919*3ac0a46fSAndroid Build Coastguard Worker         }
2920*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dataoff = nb;
2921*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_dataoff & 1)
2922*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_dataoff++;
2923*3ac0a46fSAndroid Build Coastguard Worker         if (!(tif->tif_flags & TIFF_BIGTIFF))
2924*3ac0a46fSAndroid Build Coastguard Worker         {
2925*3ac0a46fSAndroid Build Coastguard Worker             uint32_t o;
2926*3ac0a46fSAndroid Build Coastguard Worker             o = (uint32_t)na;
2927*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
2928*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong(&o);
2929*3ac0a46fSAndroid Build Coastguard Worker             _TIFFmemcpy(&dir[m].tdir_offset, &o, 4);
2930*3ac0a46fSAndroid Build Coastguard Worker         }
2931*3ac0a46fSAndroid Build Coastguard Worker         else
2932*3ac0a46fSAndroid Build Coastguard Worker         {
2933*3ac0a46fSAndroid Build Coastguard Worker             dir[m].tdir_offset.toff_long8 = na;
2934*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
2935*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong8(&dir[m].tdir_offset.toff_long8);
2936*3ac0a46fSAndroid Build Coastguard Worker         }
2937*3ac0a46fSAndroid Build Coastguard Worker     }
2938*3ac0a46fSAndroid Build Coastguard Worker     (*ndir)++;
2939*3ac0a46fSAndroid Build Coastguard Worker     return (1);
2940*3ac0a46fSAndroid Build Coastguard Worker }
2941*3ac0a46fSAndroid Build Coastguard Worker 
2942*3ac0a46fSAndroid Build Coastguard Worker /*
2943*3ac0a46fSAndroid Build Coastguard Worker  * Link the current directory into the directory chain for the file.
2944*3ac0a46fSAndroid Build Coastguard Worker  */
TIFFLinkDirectory(TIFF * tif)2945*3ac0a46fSAndroid Build Coastguard Worker static int TIFFLinkDirectory(TIFF *tif)
2946*3ac0a46fSAndroid Build Coastguard Worker {
2947*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFLinkDirectory";
2948*3ac0a46fSAndroid Build Coastguard Worker 
2949*3ac0a46fSAndroid Build Coastguard Worker     tif->tif_diroff = (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1));
2950*3ac0a46fSAndroid Build Coastguard Worker 
2951*3ac0a46fSAndroid Build Coastguard Worker     /*
2952*3ac0a46fSAndroid Build Coastguard Worker      * Handle SubIFDs
2953*3ac0a46fSAndroid Build Coastguard Worker      */
2954*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_INSUBIFD)
2955*3ac0a46fSAndroid Build Coastguard Worker     {
2956*3ac0a46fSAndroid Build Coastguard Worker         if (!(tif->tif_flags & TIFF_BIGTIFF))
2957*3ac0a46fSAndroid Build Coastguard Worker         {
2958*3ac0a46fSAndroid Build Coastguard Worker             uint32_t m;
2959*3ac0a46fSAndroid Build Coastguard Worker             m = (uint32_t)tif->tif_diroff;
2960*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
2961*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong(&m);
2962*3ac0a46fSAndroid Build Coastguard Worker             (void)TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
2963*3ac0a46fSAndroid Build Coastguard Worker             if (!WriteOK(tif, &m, 4))
2964*3ac0a46fSAndroid Build Coastguard Worker             {
2965*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
2966*3ac0a46fSAndroid Build Coastguard Worker                               "Error writing SubIFD directory link");
2967*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
2968*3ac0a46fSAndroid Build Coastguard Worker             }
2969*3ac0a46fSAndroid Build Coastguard Worker             /*
2970*3ac0a46fSAndroid Build Coastguard Worker              * Advance to the next SubIFD or, if this is
2971*3ac0a46fSAndroid Build Coastguard Worker              * the last one configured, revert back to the
2972*3ac0a46fSAndroid Build Coastguard Worker              * normal directory linkage.
2973*3ac0a46fSAndroid Build Coastguard Worker              */
2974*3ac0a46fSAndroid Build Coastguard Worker             if (--tif->tif_nsubifd)
2975*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_subifdoff += 4;
2976*3ac0a46fSAndroid Build Coastguard Worker             else
2977*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_flags &= ~TIFF_INSUBIFD;
2978*3ac0a46fSAndroid Build Coastguard Worker             return (1);
2979*3ac0a46fSAndroid Build Coastguard Worker         }
2980*3ac0a46fSAndroid Build Coastguard Worker         else
2981*3ac0a46fSAndroid Build Coastguard Worker         {
2982*3ac0a46fSAndroid Build Coastguard Worker             uint64_t m;
2983*3ac0a46fSAndroid Build Coastguard Worker             m = tif->tif_diroff;
2984*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
2985*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong8(&m);
2986*3ac0a46fSAndroid Build Coastguard Worker             (void)TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
2987*3ac0a46fSAndroid Build Coastguard Worker             if (!WriteOK(tif, &m, 8))
2988*3ac0a46fSAndroid Build Coastguard Worker             {
2989*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
2990*3ac0a46fSAndroid Build Coastguard Worker                               "Error writing SubIFD directory link");
2991*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
2992*3ac0a46fSAndroid Build Coastguard Worker             }
2993*3ac0a46fSAndroid Build Coastguard Worker             /*
2994*3ac0a46fSAndroid Build Coastguard Worker              * Advance to the next SubIFD or, if this is
2995*3ac0a46fSAndroid Build Coastguard Worker              * the last one configured, revert back to the
2996*3ac0a46fSAndroid Build Coastguard Worker              * normal directory linkage.
2997*3ac0a46fSAndroid Build Coastguard Worker              */
2998*3ac0a46fSAndroid Build Coastguard Worker             if (--tif->tif_nsubifd)
2999*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_subifdoff += 8;
3000*3ac0a46fSAndroid Build Coastguard Worker             else
3001*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_flags &= ~TIFF_INSUBIFD;
3002*3ac0a46fSAndroid Build Coastguard Worker             return (1);
3003*3ac0a46fSAndroid Build Coastguard Worker         }
3004*3ac0a46fSAndroid Build Coastguard Worker     }
3005*3ac0a46fSAndroid Build Coastguard Worker 
3006*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
3007*3ac0a46fSAndroid Build Coastguard Worker     {
3008*3ac0a46fSAndroid Build Coastguard Worker         uint32_t m;
3009*3ac0a46fSAndroid Build Coastguard Worker         uint32_t nextdir;
3010*3ac0a46fSAndroid Build Coastguard Worker         m = (uint32_t)(tif->tif_diroff);
3011*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3012*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong(&m);
3013*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_header.classic.tiff_diroff == 0)
3014*3ac0a46fSAndroid Build Coastguard Worker         {
3015*3ac0a46fSAndroid Build Coastguard Worker             /*
3016*3ac0a46fSAndroid Build Coastguard Worker              * First directory, overwrite offset in header.
3017*3ac0a46fSAndroid Build Coastguard Worker              */
3018*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_header.classic.tiff_diroff = (uint32_t)tif->tif_diroff;
3019*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_lastdiroff = tif->tif_diroff;
3020*3ac0a46fSAndroid Build Coastguard Worker             (void)TIFFSeekFile(tif, 4, SEEK_SET);
3021*3ac0a46fSAndroid Build Coastguard Worker             if (!WriteOK(tif, &m, 4))
3022*3ac0a46fSAndroid Build Coastguard Worker             {
3023*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header");
3024*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3025*3ac0a46fSAndroid Build Coastguard Worker             }
3026*3ac0a46fSAndroid Build Coastguard Worker             return (1);
3027*3ac0a46fSAndroid Build Coastguard Worker         }
3028*3ac0a46fSAndroid Build Coastguard Worker         /*
3029*3ac0a46fSAndroid Build Coastguard Worker          * Not the first directory, search to the last and append.
3030*3ac0a46fSAndroid Build Coastguard Worker          */
3031*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_lastdiroff != 0)
3032*3ac0a46fSAndroid Build Coastguard Worker         {
3033*3ac0a46fSAndroid Build Coastguard Worker             nextdir = (uint32_t)tif->tif_lastdiroff;
3034*3ac0a46fSAndroid Build Coastguard Worker         }
3035*3ac0a46fSAndroid Build Coastguard Worker         else
3036*3ac0a46fSAndroid Build Coastguard Worker         {
3037*3ac0a46fSAndroid Build Coastguard Worker             nextdir = tif->tif_header.classic.tiff_diroff;
3038*3ac0a46fSAndroid Build Coastguard Worker         }
3039*3ac0a46fSAndroid Build Coastguard Worker 
3040*3ac0a46fSAndroid Build Coastguard Worker         while (1)
3041*3ac0a46fSAndroid Build Coastguard Worker         {
3042*3ac0a46fSAndroid Build Coastguard Worker             uint16_t dircount;
3043*3ac0a46fSAndroid Build Coastguard Worker             uint32_t nextnextdir;
3044*3ac0a46fSAndroid Build Coastguard Worker 
3045*3ac0a46fSAndroid Build Coastguard Worker             if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2))
3046*3ac0a46fSAndroid Build Coastguard Worker             {
3047*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module, "Error fetching directory count");
3048*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3049*3ac0a46fSAndroid Build Coastguard Worker             }
3050*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
3051*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabShort(&dircount);
3052*3ac0a46fSAndroid Build Coastguard Worker             (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
3053*3ac0a46fSAndroid Build Coastguard Worker             if (!ReadOK(tif, &nextnextdir, 4))
3054*3ac0a46fSAndroid Build Coastguard Worker             {
3055*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module, "Error fetching directory link");
3056*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3057*3ac0a46fSAndroid Build Coastguard Worker             }
3058*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
3059*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong(&nextnextdir);
3060*3ac0a46fSAndroid Build Coastguard Worker             if (nextnextdir == 0)
3061*3ac0a46fSAndroid Build Coastguard Worker             {
3062*3ac0a46fSAndroid Build Coastguard Worker                 (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
3063*3ac0a46fSAndroid Build Coastguard Worker                 if (!WriteOK(tif, &m, 4))
3064*3ac0a46fSAndroid Build Coastguard Worker                 {
3065*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module, "Error writing directory link");
3066*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
3067*3ac0a46fSAndroid Build Coastguard Worker                 }
3068*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_lastdiroff = tif->tif_diroff;
3069*3ac0a46fSAndroid Build Coastguard Worker                 break;
3070*3ac0a46fSAndroid Build Coastguard Worker             }
3071*3ac0a46fSAndroid Build Coastguard Worker             nextdir = nextnextdir;
3072*3ac0a46fSAndroid Build Coastguard Worker         }
3073*3ac0a46fSAndroid Build Coastguard Worker     }
3074*3ac0a46fSAndroid Build Coastguard Worker     else
3075*3ac0a46fSAndroid Build Coastguard Worker     {
3076*3ac0a46fSAndroid Build Coastguard Worker         uint64_t m;
3077*3ac0a46fSAndroid Build Coastguard Worker         uint64_t nextdir;
3078*3ac0a46fSAndroid Build Coastguard Worker         m = tif->tif_diroff;
3079*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3080*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8(&m);
3081*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_header.big.tiff_diroff == 0)
3082*3ac0a46fSAndroid Build Coastguard Worker         {
3083*3ac0a46fSAndroid Build Coastguard Worker             /*
3084*3ac0a46fSAndroid Build Coastguard Worker              * First directory, overwrite offset in header.
3085*3ac0a46fSAndroid Build Coastguard Worker              */
3086*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_header.big.tiff_diroff = tif->tif_diroff;
3087*3ac0a46fSAndroid Build Coastguard Worker             tif->tif_lastdiroff = tif->tif_diroff;
3088*3ac0a46fSAndroid Build Coastguard Worker             (void)TIFFSeekFile(tif, 8, SEEK_SET);
3089*3ac0a46fSAndroid Build Coastguard Worker             if (!WriteOK(tif, &m, 8))
3090*3ac0a46fSAndroid Build Coastguard Worker             {
3091*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header");
3092*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3093*3ac0a46fSAndroid Build Coastguard Worker             }
3094*3ac0a46fSAndroid Build Coastguard Worker             return (1);
3095*3ac0a46fSAndroid Build Coastguard Worker         }
3096*3ac0a46fSAndroid Build Coastguard Worker         /*
3097*3ac0a46fSAndroid Build Coastguard Worker          * Not the first directory, search to the last and append.
3098*3ac0a46fSAndroid Build Coastguard Worker          */
3099*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_lastdiroff != 0)
3100*3ac0a46fSAndroid Build Coastguard Worker         {
3101*3ac0a46fSAndroid Build Coastguard Worker             nextdir = tif->tif_lastdiroff;
3102*3ac0a46fSAndroid Build Coastguard Worker         }
3103*3ac0a46fSAndroid Build Coastguard Worker         else
3104*3ac0a46fSAndroid Build Coastguard Worker         {
3105*3ac0a46fSAndroid Build Coastguard Worker             nextdir = tif->tif_header.big.tiff_diroff;
3106*3ac0a46fSAndroid Build Coastguard Worker         }
3107*3ac0a46fSAndroid Build Coastguard Worker         while (1)
3108*3ac0a46fSAndroid Build Coastguard Worker         {
3109*3ac0a46fSAndroid Build Coastguard Worker             uint64_t dircount64;
3110*3ac0a46fSAndroid Build Coastguard Worker             uint16_t dircount;
3111*3ac0a46fSAndroid Build Coastguard Worker             uint64_t nextnextdir;
3112*3ac0a46fSAndroid Build Coastguard Worker 
3113*3ac0a46fSAndroid Build Coastguard Worker             if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
3114*3ac0a46fSAndroid Build Coastguard Worker             {
3115*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module, "Error fetching directory count");
3116*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3117*3ac0a46fSAndroid Build Coastguard Worker             }
3118*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
3119*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong8(&dircount64);
3120*3ac0a46fSAndroid Build Coastguard Worker             if (dircount64 > 0xFFFF)
3121*3ac0a46fSAndroid Build Coastguard Worker             {
3122*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(
3123*3ac0a46fSAndroid Build Coastguard Worker                     tif, module,
3124*3ac0a46fSAndroid Build Coastguard Worker                     "Sanity check on tag count failed, likely corrupt TIFF");
3125*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3126*3ac0a46fSAndroid Build Coastguard Worker             }
3127*3ac0a46fSAndroid Build Coastguard Worker             dircount = (uint16_t)dircount64;
3128*3ac0a46fSAndroid Build Coastguard Worker             (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
3129*3ac0a46fSAndroid Build Coastguard Worker             if (!ReadOK(tif, &nextnextdir, 8))
3130*3ac0a46fSAndroid Build Coastguard Worker             {
3131*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module, "Error fetching directory link");
3132*3ac0a46fSAndroid Build Coastguard Worker                 return (0);
3133*3ac0a46fSAndroid Build Coastguard Worker             }
3134*3ac0a46fSAndroid Build Coastguard Worker             if (tif->tif_flags & TIFF_SWAB)
3135*3ac0a46fSAndroid Build Coastguard Worker                 TIFFSwabLong8(&nextnextdir);
3136*3ac0a46fSAndroid Build Coastguard Worker             if (nextnextdir == 0)
3137*3ac0a46fSAndroid Build Coastguard Worker             {
3138*3ac0a46fSAndroid Build Coastguard Worker                 (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
3139*3ac0a46fSAndroid Build Coastguard Worker                 if (!WriteOK(tif, &m, 8))
3140*3ac0a46fSAndroid Build Coastguard Worker                 {
3141*3ac0a46fSAndroid Build Coastguard Worker                     TIFFErrorExtR(tif, module, "Error writing directory link");
3142*3ac0a46fSAndroid Build Coastguard Worker                     return (0);
3143*3ac0a46fSAndroid Build Coastguard Worker                 }
3144*3ac0a46fSAndroid Build Coastguard Worker                 tif->tif_lastdiroff = tif->tif_diroff;
3145*3ac0a46fSAndroid Build Coastguard Worker                 break;
3146*3ac0a46fSAndroid Build Coastguard Worker             }
3147*3ac0a46fSAndroid Build Coastguard Worker             nextdir = nextnextdir;
3148*3ac0a46fSAndroid Build Coastguard Worker         }
3149*3ac0a46fSAndroid Build Coastguard Worker     }
3150*3ac0a46fSAndroid Build Coastguard Worker     return (1);
3151*3ac0a46fSAndroid Build Coastguard Worker }
3152*3ac0a46fSAndroid Build Coastguard Worker 
3153*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
3154*3ac0a46fSAndroid Build Coastguard Worker /*                          TIFFRewriteField()                          */
3155*3ac0a46fSAndroid Build Coastguard Worker /*                                                                      */
3156*3ac0a46fSAndroid Build Coastguard Worker /*      Rewrite a field in the directory on disk without regard to      */
3157*3ac0a46fSAndroid Build Coastguard Worker /*      updating the TIFF directory structure in memory.  Currently     */
3158*3ac0a46fSAndroid Build Coastguard Worker /*      only supported for field that already exist in the on-disk      */
3159*3ac0a46fSAndroid Build Coastguard Worker /*      directory.  Mainly used for updating stripoffset /              */
3160*3ac0a46fSAndroid Build Coastguard Worker /*      stripbytecount values after the directory is already on         */
3161*3ac0a46fSAndroid Build Coastguard Worker /*      disk.                                                           */
3162*3ac0a46fSAndroid Build Coastguard Worker /*                                                                      */
3163*3ac0a46fSAndroid Build Coastguard Worker /*      Returns zero on failure, and one on success.                    */
3164*3ac0a46fSAndroid Build Coastguard Worker /************************************************************************/
3165*3ac0a46fSAndroid Build Coastguard Worker 
_TIFFRewriteField(TIFF * tif,uint16_t tag,TIFFDataType in_datatype,tmsize_t count,void * data)3166*3ac0a46fSAndroid Build Coastguard Worker int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
3167*3ac0a46fSAndroid Build Coastguard Worker                       tmsize_t count, void *data)
3168*3ac0a46fSAndroid Build Coastguard Worker {
3169*3ac0a46fSAndroid Build Coastguard Worker     static const char module[] = "TIFFResetField";
3170*3ac0a46fSAndroid Build Coastguard Worker     /* const TIFFField* fip = NULL; */
3171*3ac0a46fSAndroid Build Coastguard Worker     uint16_t dircount;
3172*3ac0a46fSAndroid Build Coastguard Worker     tmsize_t dirsize;
3173*3ac0a46fSAndroid Build Coastguard Worker     uint8_t direntry_raw[20];
3174*3ac0a46fSAndroid Build Coastguard Worker     uint16_t entry_tag = 0;
3175*3ac0a46fSAndroid Build Coastguard Worker     uint16_t entry_type = 0;
3176*3ac0a46fSAndroid Build Coastguard Worker     uint64_t entry_count = 0;
3177*3ac0a46fSAndroid Build Coastguard Worker     uint64_t entry_offset = 0;
3178*3ac0a46fSAndroid Build Coastguard Worker     int value_in_entry = 0;
3179*3ac0a46fSAndroid Build Coastguard Worker     uint64_t read_offset;
3180*3ac0a46fSAndroid Build Coastguard Worker     uint8_t *buf_to_write = NULL;
3181*3ac0a46fSAndroid Build Coastguard Worker     TIFFDataType datatype;
3182*3ac0a46fSAndroid Build Coastguard Worker 
3183*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3184*3ac0a46fSAndroid Build Coastguard Worker     /*      Find field definition.                                          */
3185*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3186*3ac0a46fSAndroid Build Coastguard Worker     /*fip =*/TIFFFindField(tif, tag, TIFF_ANY);
3187*3ac0a46fSAndroid Build Coastguard Worker 
3188*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3189*3ac0a46fSAndroid Build Coastguard Worker     /*      Do some checking this is a straight forward case.               */
3190*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3191*3ac0a46fSAndroid Build Coastguard Worker     if (isMapped(tif))
3192*3ac0a46fSAndroid Build Coastguard Worker     {
3193*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(
3194*3ac0a46fSAndroid Build Coastguard Worker             tif, module,
3195*3ac0a46fSAndroid Build Coastguard Worker             "Memory mapped files not currently supported for this operation.");
3196*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3197*3ac0a46fSAndroid Build Coastguard Worker     }
3198*3ac0a46fSAndroid Build Coastguard Worker 
3199*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_diroff == 0)
3200*3ac0a46fSAndroid Build Coastguard Worker     {
3201*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(
3202*3ac0a46fSAndroid Build Coastguard Worker             tif, module,
3203*3ac0a46fSAndroid Build Coastguard Worker             "Attempt to reset field on directory not already on disk.");
3204*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3205*3ac0a46fSAndroid Build Coastguard Worker     }
3206*3ac0a46fSAndroid Build Coastguard Worker 
3207*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3208*3ac0a46fSAndroid Build Coastguard Worker     /*      Read the directory entry count.                                 */
3209*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3210*3ac0a46fSAndroid Build Coastguard Worker     if (!SeekOK(tif, tif->tif_diroff))
3211*3ac0a46fSAndroid Build Coastguard Worker     {
3212*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "%s: Seek error accessing TIFF directory",
3213*3ac0a46fSAndroid Build Coastguard Worker                       tif->tif_name);
3214*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3215*3ac0a46fSAndroid Build Coastguard Worker     }
3216*3ac0a46fSAndroid Build Coastguard Worker 
3217*3ac0a46fSAndroid Build Coastguard Worker     read_offset = tif->tif_diroff;
3218*3ac0a46fSAndroid Build Coastguard Worker 
3219*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
3220*3ac0a46fSAndroid Build Coastguard Worker     {
3221*3ac0a46fSAndroid Build Coastguard Worker         if (!ReadOK(tif, &dircount, sizeof(uint16_t)))
3222*3ac0a46fSAndroid Build Coastguard Worker         {
3223*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "%s: Can not read TIFF directory count",
3224*3ac0a46fSAndroid Build Coastguard Worker                           tif->tif_name);
3225*3ac0a46fSAndroid Build Coastguard Worker             return 0;
3226*3ac0a46fSAndroid Build Coastguard Worker         }
3227*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3228*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabShort(&dircount);
3229*3ac0a46fSAndroid Build Coastguard Worker         dirsize = 12;
3230*3ac0a46fSAndroid Build Coastguard Worker         read_offset += 2;
3231*3ac0a46fSAndroid Build Coastguard Worker     }
3232*3ac0a46fSAndroid Build Coastguard Worker     else
3233*3ac0a46fSAndroid Build Coastguard Worker     {
3234*3ac0a46fSAndroid Build Coastguard Worker         uint64_t dircount64;
3235*3ac0a46fSAndroid Build Coastguard Worker         if (!ReadOK(tif, &dircount64, sizeof(uint64_t)))
3236*3ac0a46fSAndroid Build Coastguard Worker         {
3237*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "%s: Can not read TIFF directory count",
3238*3ac0a46fSAndroid Build Coastguard Worker                           tif->tif_name);
3239*3ac0a46fSAndroid Build Coastguard Worker             return 0;
3240*3ac0a46fSAndroid Build Coastguard Worker         }
3241*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3242*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8(&dircount64);
3243*3ac0a46fSAndroid Build Coastguard Worker         dircount = (uint16_t)dircount64;
3244*3ac0a46fSAndroid Build Coastguard Worker         dirsize = 20;
3245*3ac0a46fSAndroid Build Coastguard Worker         read_offset += 8;
3246*3ac0a46fSAndroid Build Coastguard Worker     }
3247*3ac0a46fSAndroid Build Coastguard Worker 
3248*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3249*3ac0a46fSAndroid Build Coastguard Worker     /*      Read through directory to find target tag.                      */
3250*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3251*3ac0a46fSAndroid Build Coastguard Worker     while (dircount > 0)
3252*3ac0a46fSAndroid Build Coastguard Worker     {
3253*3ac0a46fSAndroid Build Coastguard Worker         if (!ReadOK(tif, direntry_raw, dirsize))
3254*3ac0a46fSAndroid Build Coastguard Worker         {
3255*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "%s: Can not read TIFF directory entry.",
3256*3ac0a46fSAndroid Build Coastguard Worker                           tif->tif_name);
3257*3ac0a46fSAndroid Build Coastguard Worker             return 0;
3258*3ac0a46fSAndroid Build Coastguard Worker         }
3259*3ac0a46fSAndroid Build Coastguard Worker 
3260*3ac0a46fSAndroid Build Coastguard Worker         memcpy(&entry_tag, direntry_raw + 0, sizeof(uint16_t));
3261*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3262*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabShort(&entry_tag);
3263*3ac0a46fSAndroid Build Coastguard Worker 
3264*3ac0a46fSAndroid Build Coastguard Worker         if (entry_tag == tag)
3265*3ac0a46fSAndroid Build Coastguard Worker             break;
3266*3ac0a46fSAndroid Build Coastguard Worker 
3267*3ac0a46fSAndroid Build Coastguard Worker         read_offset += dirsize;
3268*3ac0a46fSAndroid Build Coastguard Worker     }
3269*3ac0a46fSAndroid Build Coastguard Worker 
3270*3ac0a46fSAndroid Build Coastguard Worker     if (entry_tag != tag)
3271*3ac0a46fSAndroid Build Coastguard Worker     {
3272*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "%s: Could not find tag %" PRIu16 ".",
3273*3ac0a46fSAndroid Build Coastguard Worker                       tif->tif_name, tag);
3274*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3275*3ac0a46fSAndroid Build Coastguard Worker     }
3276*3ac0a46fSAndroid Build Coastguard Worker 
3277*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3278*3ac0a46fSAndroid Build Coastguard Worker     /*      Extract the type, count and offset for this entry.              */
3279*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3280*3ac0a46fSAndroid Build Coastguard Worker     memcpy(&entry_type, direntry_raw + 2, sizeof(uint16_t));
3281*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
3282*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabShort(&entry_type);
3283*3ac0a46fSAndroid Build Coastguard Worker 
3284*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
3285*3ac0a46fSAndroid Build Coastguard Worker     {
3286*3ac0a46fSAndroid Build Coastguard Worker         uint32_t value;
3287*3ac0a46fSAndroid Build Coastguard Worker 
3288*3ac0a46fSAndroid Build Coastguard Worker         memcpy(&value, direntry_raw + 4, sizeof(uint32_t));
3289*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3290*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong(&value);
3291*3ac0a46fSAndroid Build Coastguard Worker         entry_count = value;
3292*3ac0a46fSAndroid Build Coastguard Worker 
3293*3ac0a46fSAndroid Build Coastguard Worker         memcpy(&value, direntry_raw + 8, sizeof(uint32_t));
3294*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3295*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong(&value);
3296*3ac0a46fSAndroid Build Coastguard Worker         entry_offset = value;
3297*3ac0a46fSAndroid Build Coastguard Worker     }
3298*3ac0a46fSAndroid Build Coastguard Worker     else
3299*3ac0a46fSAndroid Build Coastguard Worker     {
3300*3ac0a46fSAndroid Build Coastguard Worker         memcpy(&entry_count, direntry_raw + 4, sizeof(uint64_t));
3301*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3302*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8(&entry_count);
3303*3ac0a46fSAndroid Build Coastguard Worker 
3304*3ac0a46fSAndroid Build Coastguard Worker         memcpy(&entry_offset, direntry_raw + 12, sizeof(uint64_t));
3305*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3306*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8(&entry_offset);
3307*3ac0a46fSAndroid Build Coastguard Worker     }
3308*3ac0a46fSAndroid Build Coastguard Worker 
3309*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3310*3ac0a46fSAndroid Build Coastguard Worker     /*      When a dummy tag was written due to TIFFDeferStrileArrayWriting() */
3311*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3312*3ac0a46fSAndroid Build Coastguard Worker     if (entry_offset == 0 && entry_count == 0 && entry_type == 0)
3313*3ac0a46fSAndroid Build Coastguard Worker     {
3314*3ac0a46fSAndroid Build Coastguard Worker         if (tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS)
3315*3ac0a46fSAndroid Build Coastguard Worker         {
3316*3ac0a46fSAndroid Build Coastguard Worker             entry_type =
3317*3ac0a46fSAndroid Build Coastguard Worker                 (tif->tif_flags & TIFF_BIGTIFF) ? TIFF_LONG8 : TIFF_LONG;
3318*3ac0a46fSAndroid Build Coastguard Worker         }
3319*3ac0a46fSAndroid Build Coastguard Worker         else
3320*3ac0a46fSAndroid Build Coastguard Worker         {
3321*3ac0a46fSAndroid Build Coastguard Worker             int write_aslong8 = 1;
3322*3ac0a46fSAndroid Build Coastguard Worker             if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
3323*3ac0a46fSAndroid Build Coastguard Worker             {
3324*3ac0a46fSAndroid Build Coastguard Worker                 write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
3325*3ac0a46fSAndroid Build Coastguard Worker             }
3326*3ac0a46fSAndroid Build Coastguard Worker             else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
3327*3ac0a46fSAndroid Build Coastguard Worker             {
3328*3ac0a46fSAndroid Build Coastguard Worker                 write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
3329*3ac0a46fSAndroid Build Coastguard Worker             }
3330*3ac0a46fSAndroid Build Coastguard Worker             if (write_aslong8)
3331*3ac0a46fSAndroid Build Coastguard Worker             {
3332*3ac0a46fSAndroid Build Coastguard Worker                 entry_type = TIFF_LONG8;
3333*3ac0a46fSAndroid Build Coastguard Worker             }
3334*3ac0a46fSAndroid Build Coastguard Worker             else
3335*3ac0a46fSAndroid Build Coastguard Worker             {
3336*3ac0a46fSAndroid Build Coastguard Worker                 int write_aslong4 = 1;
3337*3ac0a46fSAndroid Build Coastguard Worker                 if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
3338*3ac0a46fSAndroid Build Coastguard Worker                 {
3339*3ac0a46fSAndroid Build Coastguard Worker                     write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
3340*3ac0a46fSAndroid Build Coastguard Worker                 }
3341*3ac0a46fSAndroid Build Coastguard Worker                 else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
3342*3ac0a46fSAndroid Build Coastguard Worker                 {
3343*3ac0a46fSAndroid Build Coastguard Worker                     write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
3344*3ac0a46fSAndroid Build Coastguard Worker                 }
3345*3ac0a46fSAndroid Build Coastguard Worker                 if (write_aslong4)
3346*3ac0a46fSAndroid Build Coastguard Worker                 {
3347*3ac0a46fSAndroid Build Coastguard Worker                     entry_type = TIFF_LONG;
3348*3ac0a46fSAndroid Build Coastguard Worker                 }
3349*3ac0a46fSAndroid Build Coastguard Worker                 else
3350*3ac0a46fSAndroid Build Coastguard Worker                 {
3351*3ac0a46fSAndroid Build Coastguard Worker                     entry_type = TIFF_SHORT;
3352*3ac0a46fSAndroid Build Coastguard Worker                 }
3353*3ac0a46fSAndroid Build Coastguard Worker             }
3354*3ac0a46fSAndroid Build Coastguard Worker         }
3355*3ac0a46fSAndroid Build Coastguard Worker     }
3356*3ac0a46fSAndroid Build Coastguard Worker 
3357*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3358*3ac0a46fSAndroid Build Coastguard Worker     /*      What data type do we want to write this as?                     */
3359*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3360*3ac0a46fSAndroid Build Coastguard Worker     if (TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags & TIFF_BIGTIFF))
3361*3ac0a46fSAndroid Build Coastguard Worker     {
3362*3ac0a46fSAndroid Build Coastguard Worker         if (in_datatype == TIFF_LONG8)
3363*3ac0a46fSAndroid Build Coastguard Worker             datatype = entry_type == TIFF_SHORT ? TIFF_SHORT : TIFF_LONG;
3364*3ac0a46fSAndroid Build Coastguard Worker         else if (in_datatype == TIFF_SLONG8)
3365*3ac0a46fSAndroid Build Coastguard Worker             datatype = TIFF_SLONG;
3366*3ac0a46fSAndroid Build Coastguard Worker         else if (in_datatype == TIFF_IFD8)
3367*3ac0a46fSAndroid Build Coastguard Worker             datatype = TIFF_IFD;
3368*3ac0a46fSAndroid Build Coastguard Worker         else
3369*3ac0a46fSAndroid Build Coastguard Worker             datatype = in_datatype;
3370*3ac0a46fSAndroid Build Coastguard Worker     }
3371*3ac0a46fSAndroid Build Coastguard Worker     else
3372*3ac0a46fSAndroid Build Coastguard Worker     {
3373*3ac0a46fSAndroid Build Coastguard Worker         if (in_datatype == TIFF_LONG8 &&
3374*3ac0a46fSAndroid Build Coastguard Worker             (entry_type == TIFF_SHORT || entry_type == TIFF_LONG ||
3375*3ac0a46fSAndroid Build Coastguard Worker              entry_type == TIFF_LONG8))
3376*3ac0a46fSAndroid Build Coastguard Worker             datatype = entry_type;
3377*3ac0a46fSAndroid Build Coastguard Worker         else if (in_datatype == TIFF_SLONG8 &&
3378*3ac0a46fSAndroid Build Coastguard Worker                  (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8))
3379*3ac0a46fSAndroid Build Coastguard Worker             datatype = entry_type;
3380*3ac0a46fSAndroid Build Coastguard Worker         else if (in_datatype == TIFF_IFD8 &&
3381*3ac0a46fSAndroid Build Coastguard Worker                  (entry_type == TIFF_IFD || entry_type == TIFF_IFD8))
3382*3ac0a46fSAndroid Build Coastguard Worker             datatype = entry_type;
3383*3ac0a46fSAndroid Build Coastguard Worker         else
3384*3ac0a46fSAndroid Build Coastguard Worker             datatype = in_datatype;
3385*3ac0a46fSAndroid Build Coastguard Worker     }
3386*3ac0a46fSAndroid Build Coastguard Worker 
3387*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3388*3ac0a46fSAndroid Build Coastguard Worker     /*      Prepare buffer of actual data to write.  This includes          */
3389*3ac0a46fSAndroid Build Coastguard Worker     /*      swabbing as needed.                                             */
3390*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3391*3ac0a46fSAndroid Build Coastguard Worker     buf_to_write = (uint8_t *)_TIFFCheckMalloc(
3392*3ac0a46fSAndroid Build Coastguard Worker         tif, count, TIFFDataWidth(datatype), "for field buffer.");
3393*3ac0a46fSAndroid Build Coastguard Worker     if (!buf_to_write)
3394*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3395*3ac0a46fSAndroid Build Coastguard Worker 
3396*3ac0a46fSAndroid Build Coastguard Worker     if (datatype == in_datatype)
3397*3ac0a46fSAndroid Build Coastguard Worker         memcpy(buf_to_write, data, count * TIFFDataWidth(datatype));
3398*3ac0a46fSAndroid Build Coastguard Worker     else if (datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8)
3399*3ac0a46fSAndroid Build Coastguard Worker     {
3400*3ac0a46fSAndroid Build Coastguard Worker         tmsize_t i;
3401*3ac0a46fSAndroid Build Coastguard Worker 
3402*3ac0a46fSAndroid Build Coastguard Worker         for (i = 0; i < count; i++)
3403*3ac0a46fSAndroid Build Coastguard Worker         {
3404*3ac0a46fSAndroid Build Coastguard Worker             ((int32_t *)buf_to_write)[i] = (int32_t)((int64_t *)data)[i];
3405*3ac0a46fSAndroid Build Coastguard Worker             if ((int64_t)((int32_t *)buf_to_write)[i] != ((int64_t *)data)[i])
3406*3ac0a46fSAndroid Build Coastguard Worker             {
3407*3ac0a46fSAndroid Build Coastguard Worker                 _TIFFfreeExt(tif, buf_to_write);
3408*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
3409*3ac0a46fSAndroid Build Coastguard Worker                               "Value exceeds 32bit range of output type.");
3410*3ac0a46fSAndroid Build Coastguard Worker                 return 0;
3411*3ac0a46fSAndroid Build Coastguard Worker             }
3412*3ac0a46fSAndroid Build Coastguard Worker         }
3413*3ac0a46fSAndroid Build Coastguard Worker     }
3414*3ac0a46fSAndroid Build Coastguard Worker     else if ((datatype == TIFF_LONG && in_datatype == TIFF_LONG8) ||
3415*3ac0a46fSAndroid Build Coastguard Worker              (datatype == TIFF_IFD && in_datatype == TIFF_IFD8))
3416*3ac0a46fSAndroid Build Coastguard Worker     {
3417*3ac0a46fSAndroid Build Coastguard Worker         tmsize_t i;
3418*3ac0a46fSAndroid Build Coastguard Worker 
3419*3ac0a46fSAndroid Build Coastguard Worker         for (i = 0; i < count; i++)
3420*3ac0a46fSAndroid Build Coastguard Worker         {
3421*3ac0a46fSAndroid Build Coastguard Worker             ((uint32_t *)buf_to_write)[i] = (uint32_t)((uint64_t *)data)[i];
3422*3ac0a46fSAndroid Build Coastguard Worker             if ((uint64_t)((uint32_t *)buf_to_write)[i] !=
3423*3ac0a46fSAndroid Build Coastguard Worker                 ((uint64_t *)data)[i])
3424*3ac0a46fSAndroid Build Coastguard Worker             {
3425*3ac0a46fSAndroid Build Coastguard Worker                 _TIFFfreeExt(tif, buf_to_write);
3426*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
3427*3ac0a46fSAndroid Build Coastguard Worker                               "Value exceeds 32bit range of output type.");
3428*3ac0a46fSAndroid Build Coastguard Worker                 return 0;
3429*3ac0a46fSAndroid Build Coastguard Worker             }
3430*3ac0a46fSAndroid Build Coastguard Worker         }
3431*3ac0a46fSAndroid Build Coastguard Worker     }
3432*3ac0a46fSAndroid Build Coastguard Worker     else if (datatype == TIFF_SHORT && in_datatype == TIFF_LONG8)
3433*3ac0a46fSAndroid Build Coastguard Worker     {
3434*3ac0a46fSAndroid Build Coastguard Worker         tmsize_t i;
3435*3ac0a46fSAndroid Build Coastguard Worker 
3436*3ac0a46fSAndroid Build Coastguard Worker         for (i = 0; i < count; i++)
3437*3ac0a46fSAndroid Build Coastguard Worker         {
3438*3ac0a46fSAndroid Build Coastguard Worker             ((uint16_t *)buf_to_write)[i] = (uint16_t)((uint64_t *)data)[i];
3439*3ac0a46fSAndroid Build Coastguard Worker             if ((uint64_t)((uint16_t *)buf_to_write)[i] !=
3440*3ac0a46fSAndroid Build Coastguard Worker                 ((uint64_t *)data)[i])
3441*3ac0a46fSAndroid Build Coastguard Worker             {
3442*3ac0a46fSAndroid Build Coastguard Worker                 _TIFFfreeExt(tif, buf_to_write);
3443*3ac0a46fSAndroid Build Coastguard Worker                 TIFFErrorExtR(tif, module,
3444*3ac0a46fSAndroid Build Coastguard Worker                               "Value exceeds 16bit range of output type.");
3445*3ac0a46fSAndroid Build Coastguard Worker                 return 0;
3446*3ac0a46fSAndroid Build Coastguard Worker             }
3447*3ac0a46fSAndroid Build Coastguard Worker         }
3448*3ac0a46fSAndroid Build Coastguard Worker     }
3449*3ac0a46fSAndroid Build Coastguard Worker     else
3450*3ac0a46fSAndroid Build Coastguard Worker     {
3451*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "Unhandled type conversion.");
3452*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3453*3ac0a46fSAndroid Build Coastguard Worker     }
3454*3ac0a46fSAndroid Build Coastguard Worker 
3455*3ac0a46fSAndroid Build Coastguard Worker     if (TIFFDataWidth(datatype) > 1 && (tif->tif_flags & TIFF_SWAB))
3456*3ac0a46fSAndroid Build Coastguard Worker     {
3457*3ac0a46fSAndroid Build Coastguard Worker         if (TIFFDataWidth(datatype) == 2)
3458*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabArrayOfShort((uint16_t *)buf_to_write, count);
3459*3ac0a46fSAndroid Build Coastguard Worker         else if (TIFFDataWidth(datatype) == 4)
3460*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabArrayOfLong((uint32_t *)buf_to_write, count);
3461*3ac0a46fSAndroid Build Coastguard Worker         else if (TIFFDataWidth(datatype) == 8)
3462*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabArrayOfLong8((uint64_t *)buf_to_write, count);
3463*3ac0a46fSAndroid Build Coastguard Worker     }
3464*3ac0a46fSAndroid Build Coastguard Worker 
3465*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3466*3ac0a46fSAndroid Build Coastguard Worker     /*      Is this a value that fits into the directory entry?             */
3467*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3468*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
3469*3ac0a46fSAndroid Build Coastguard Worker     {
3470*3ac0a46fSAndroid Build Coastguard Worker         if (TIFFDataWidth(datatype) * count <= 4)
3471*3ac0a46fSAndroid Build Coastguard Worker         {
3472*3ac0a46fSAndroid Build Coastguard Worker             entry_offset = read_offset + 8;
3473*3ac0a46fSAndroid Build Coastguard Worker             value_in_entry = 1;
3474*3ac0a46fSAndroid Build Coastguard Worker         }
3475*3ac0a46fSAndroid Build Coastguard Worker     }
3476*3ac0a46fSAndroid Build Coastguard Worker     else
3477*3ac0a46fSAndroid Build Coastguard Worker     {
3478*3ac0a46fSAndroid Build Coastguard Worker         if (TIFFDataWidth(datatype) * count <= 8)
3479*3ac0a46fSAndroid Build Coastguard Worker         {
3480*3ac0a46fSAndroid Build Coastguard Worker             entry_offset = read_offset + 12;
3481*3ac0a46fSAndroid Build Coastguard Worker             value_in_entry = 1;
3482*3ac0a46fSAndroid Build Coastguard Worker         }
3483*3ac0a46fSAndroid Build Coastguard Worker     }
3484*3ac0a46fSAndroid Build Coastguard Worker 
3485*3ac0a46fSAndroid Build Coastguard Worker     if ((tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS) &&
3486*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
3487*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
3488*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0)
3489*3ac0a46fSAndroid Build Coastguard Worker     {
3490*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripoffset_entry.tdir_type = datatype;
3491*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripoffset_entry.tdir_count = count;
3492*3ac0a46fSAndroid Build Coastguard Worker     }
3493*3ac0a46fSAndroid Build Coastguard Worker     else if ((tag == TIFFTAG_TILEBYTECOUNTS ||
3494*3ac0a46fSAndroid Build Coastguard Worker               tag == TIFFTAG_STRIPBYTECOUNTS) &&
3495*3ac0a46fSAndroid Build Coastguard Worker              tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
3496*3ac0a46fSAndroid Build Coastguard Worker              tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
3497*3ac0a46fSAndroid Build Coastguard Worker              tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0)
3498*3ac0a46fSAndroid Build Coastguard Worker     {
3499*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype;
3500*3ac0a46fSAndroid Build Coastguard Worker         tif->tif_dir.td_stripbytecount_entry.tdir_count = count;
3501*3ac0a46fSAndroid Build Coastguard Worker     }
3502*3ac0a46fSAndroid Build Coastguard Worker 
3503*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3504*3ac0a46fSAndroid Build Coastguard Worker     /*      If the tag type, and count match, then we just write it out     */
3505*3ac0a46fSAndroid Build Coastguard Worker     /*      over the old values without altering the directory entry at     */
3506*3ac0a46fSAndroid Build Coastguard Worker     /*      all.                                                            */
3507*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3508*3ac0a46fSAndroid Build Coastguard Worker     if (entry_count == (uint64_t)count && entry_type == (uint16_t)datatype)
3509*3ac0a46fSAndroid Build Coastguard Worker     {
3510*3ac0a46fSAndroid Build Coastguard Worker         if (!SeekOK(tif, entry_offset))
3511*3ac0a46fSAndroid Build Coastguard Worker         {
3512*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, buf_to_write);
3513*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module,
3514*3ac0a46fSAndroid Build Coastguard Worker                           "%s: Seek error accessing TIFF directory",
3515*3ac0a46fSAndroid Build Coastguard Worker                           tif->tif_name);
3516*3ac0a46fSAndroid Build Coastguard Worker             return 0;
3517*3ac0a46fSAndroid Build Coastguard Worker         }
3518*3ac0a46fSAndroid Build Coastguard Worker         if (!WriteOK(tif, buf_to_write, count * TIFFDataWidth(datatype)))
3519*3ac0a46fSAndroid Build Coastguard Worker         {
3520*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, buf_to_write);
3521*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Error writing directory link");
3522*3ac0a46fSAndroid Build Coastguard Worker             return (0);
3523*3ac0a46fSAndroid Build Coastguard Worker         }
3524*3ac0a46fSAndroid Build Coastguard Worker 
3525*3ac0a46fSAndroid Build Coastguard Worker         _TIFFfreeExt(tif, buf_to_write);
3526*3ac0a46fSAndroid Build Coastguard Worker         return 1;
3527*3ac0a46fSAndroid Build Coastguard Worker     }
3528*3ac0a46fSAndroid Build Coastguard Worker 
3529*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3530*3ac0a46fSAndroid Build Coastguard Worker     /*      Otherwise, we write the new tag data at the end of the file.    */
3531*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3532*3ac0a46fSAndroid Build Coastguard Worker     if (!value_in_entry)
3533*3ac0a46fSAndroid Build Coastguard Worker     {
3534*3ac0a46fSAndroid Build Coastguard Worker         entry_offset = TIFFSeekFile(tif, 0, SEEK_END);
3535*3ac0a46fSAndroid Build Coastguard Worker 
3536*3ac0a46fSAndroid Build Coastguard Worker         if (!WriteOK(tif, buf_to_write, count * TIFFDataWidth(datatype)))
3537*3ac0a46fSAndroid Build Coastguard Worker         {
3538*3ac0a46fSAndroid Build Coastguard Worker             _TIFFfreeExt(tif, buf_to_write);
3539*3ac0a46fSAndroid Build Coastguard Worker             TIFFErrorExtR(tif, module, "Error writing directory link");
3540*3ac0a46fSAndroid Build Coastguard Worker             return (0);
3541*3ac0a46fSAndroid Build Coastguard Worker         }
3542*3ac0a46fSAndroid Build Coastguard Worker     }
3543*3ac0a46fSAndroid Build Coastguard Worker     else
3544*3ac0a46fSAndroid Build Coastguard Worker     {
3545*3ac0a46fSAndroid Build Coastguard Worker         if (count * TIFFDataWidth(datatype) == 4)
3546*3ac0a46fSAndroid Build Coastguard Worker         {
3547*3ac0a46fSAndroid Build Coastguard Worker             uint32_t value;
3548*3ac0a46fSAndroid Build Coastguard Worker             memcpy(&value, buf_to_write, count * TIFFDataWidth(datatype));
3549*3ac0a46fSAndroid Build Coastguard Worker             entry_offset = value;
3550*3ac0a46fSAndroid Build Coastguard Worker         }
3551*3ac0a46fSAndroid Build Coastguard Worker         else
3552*3ac0a46fSAndroid Build Coastguard Worker         {
3553*3ac0a46fSAndroid Build Coastguard Worker             memcpy(&entry_offset, buf_to_write,
3554*3ac0a46fSAndroid Build Coastguard Worker                    count * TIFFDataWidth(datatype));
3555*3ac0a46fSAndroid Build Coastguard Worker         }
3556*3ac0a46fSAndroid Build Coastguard Worker     }
3557*3ac0a46fSAndroid Build Coastguard Worker 
3558*3ac0a46fSAndroid Build Coastguard Worker     _TIFFfreeExt(tif, buf_to_write);
3559*3ac0a46fSAndroid Build Coastguard Worker     buf_to_write = 0;
3560*3ac0a46fSAndroid Build Coastguard Worker 
3561*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3562*3ac0a46fSAndroid Build Coastguard Worker     /*      Adjust the directory entry.                                     */
3563*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3564*3ac0a46fSAndroid Build Coastguard Worker     entry_type = datatype;
3565*3ac0a46fSAndroid Build Coastguard Worker     entry_count = (uint64_t)count;
3566*3ac0a46fSAndroid Build Coastguard Worker     memcpy(direntry_raw + 2, &entry_type, sizeof(uint16_t));
3567*3ac0a46fSAndroid Build Coastguard Worker     if (tif->tif_flags & TIFF_SWAB)
3568*3ac0a46fSAndroid Build Coastguard Worker         TIFFSwabShort((uint16_t *)(direntry_raw + 2));
3569*3ac0a46fSAndroid Build Coastguard Worker 
3570*3ac0a46fSAndroid Build Coastguard Worker     if (!(tif->tif_flags & TIFF_BIGTIFF))
3571*3ac0a46fSAndroid Build Coastguard Worker     {
3572*3ac0a46fSAndroid Build Coastguard Worker         uint32_t value;
3573*3ac0a46fSAndroid Build Coastguard Worker 
3574*3ac0a46fSAndroid Build Coastguard Worker         value = (uint32_t)entry_count;
3575*3ac0a46fSAndroid Build Coastguard Worker         memcpy(direntry_raw + 4, &value, sizeof(uint32_t));
3576*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3577*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong((uint32_t *)(direntry_raw + 4));
3578*3ac0a46fSAndroid Build Coastguard Worker 
3579*3ac0a46fSAndroid Build Coastguard Worker         value = (uint32_t)entry_offset;
3580*3ac0a46fSAndroid Build Coastguard Worker         memcpy(direntry_raw + 8, &value, sizeof(uint32_t));
3581*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3582*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong((uint32_t *)(direntry_raw + 8));
3583*3ac0a46fSAndroid Build Coastguard Worker     }
3584*3ac0a46fSAndroid Build Coastguard Worker     else
3585*3ac0a46fSAndroid Build Coastguard Worker     {
3586*3ac0a46fSAndroid Build Coastguard Worker         memcpy(direntry_raw + 4, &entry_count, sizeof(uint64_t));
3587*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3588*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8((uint64_t *)(direntry_raw + 4));
3589*3ac0a46fSAndroid Build Coastguard Worker 
3590*3ac0a46fSAndroid Build Coastguard Worker         memcpy(direntry_raw + 12, &entry_offset, sizeof(uint64_t));
3591*3ac0a46fSAndroid Build Coastguard Worker         if (tif->tif_flags & TIFF_SWAB)
3592*3ac0a46fSAndroid Build Coastguard Worker             TIFFSwabLong8((uint64_t *)(direntry_raw + 12));
3593*3ac0a46fSAndroid Build Coastguard Worker     }
3594*3ac0a46fSAndroid Build Coastguard Worker 
3595*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3596*3ac0a46fSAndroid Build Coastguard Worker     /*      Write the directory entry out to disk.                          */
3597*3ac0a46fSAndroid Build Coastguard Worker     /* -------------------------------------------------------------------- */
3598*3ac0a46fSAndroid Build Coastguard Worker     if (!SeekOK(tif, read_offset))
3599*3ac0a46fSAndroid Build Coastguard Worker     {
3600*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "%s: Seek error accessing TIFF directory",
3601*3ac0a46fSAndroid Build Coastguard Worker                       tif->tif_name);
3602*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3603*3ac0a46fSAndroid Build Coastguard Worker     }
3604*3ac0a46fSAndroid Build Coastguard Worker 
3605*3ac0a46fSAndroid Build Coastguard Worker     if (!WriteOK(tif, direntry_raw, dirsize))
3606*3ac0a46fSAndroid Build Coastguard Worker     {
3607*3ac0a46fSAndroid Build Coastguard Worker         TIFFErrorExtR(tif, module, "%s: Can not write TIFF directory entry.",
3608*3ac0a46fSAndroid Build Coastguard Worker                       tif->tif_name);
3609*3ac0a46fSAndroid Build Coastguard Worker         return 0;
3610*3ac0a46fSAndroid Build Coastguard Worker     }
3611*3ac0a46fSAndroid Build Coastguard Worker 
3612*3ac0a46fSAndroid Build Coastguard Worker     return 1;
3613*3ac0a46fSAndroid Build Coastguard Worker }
3614