| File: | libs/tiff-4.0.2/libtiff/tif_write.c |
| Location: | line 303, column 24 |
| Description: | Division by zero |
| 1 | /* $Id: tif_write.c,v 1.36 2011-02-18 20:53:04 fwarmerdam Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 1988-1997 Sam Leffler | |||
| 5 | * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |||
| 6 | * | |||
| 7 | * Permission to use, copy, modify, distribute, and sell this software and | |||
| 8 | * its documentation for any purpose is hereby granted without fee, provided | |||
| 9 | * that (i) the above copyright notices and this permission notice appear in | |||
| 10 | * all copies of the software and related documentation, and (ii) the names of | |||
| 11 | * Sam Leffler and Silicon Graphics may not be used in any advertising or | |||
| 12 | * publicity relating to the software without the specific, prior written | |||
| 13 | * permission of Sam Leffler and Silicon Graphics. | |||
| 14 | * | |||
| 15 | * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, | |||
| 16 | * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | |||
| 17 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |||
| 18 | * | |||
| 19 | * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR | |||
| 20 | * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | |||
| 21 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |||
| 22 | * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | |||
| 23 | * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| 24 | * OF THIS SOFTWARE. | |||
| 25 | */ | |||
| 26 | ||||
| 27 | /* | |||
| 28 | * TIFF Library. | |||
| 29 | * | |||
| 30 | * Scanline-oriented Write Support | |||
| 31 | */ | |||
| 32 | #include "tiffiop.h" | |||
| 33 | #include <stdio.h> | |||
| 34 | ||||
| 35 | #define STRIPINCR20 20 /* expansion factor on strip array */ | |||
| 36 | ||||
| 37 | #define WRITECHECKSTRIPS(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),0, module)) \ | |||
| 38 | (((tif)->tif_flags&TIFF_BEENWRITING0x00040) || TIFFWriteCheck((tif),0,module)) | |||
| 39 | #define WRITECHECKTILES(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),1, module)) \ | |||
| 40 | (((tif)->tif_flags&TIFF_BEENWRITING0x00040) || TIFFWriteCheck((tif),1,module)) | |||
| 41 | #define BUFFERCHECK(tif)((((tif)->tif_flags & 0x00010) && tif->tif_rawdata ) || TIFFWriteBufferSetup((tif), ((void*)0), (tmsize_t) -1)) \ | |||
| 42 | ((((tif)->tif_flags & TIFF_BUFFERSETUP0x00010) && tif->tif_rawdata) || \ | |||
| 43 | TIFFWriteBufferSetup((tif), NULL((void*)0), (tmsize_t) -1)) | |||
| 44 | ||||
| 45 | static int TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module); | |||
| 46 | static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc); | |||
| 47 | ||||
| 48 | int | |||
| 49 | TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) | |||
| 50 | { | |||
| 51 | static const char module[] = "TIFFWriteScanline"; | |||
| 52 | register TIFFDirectory *td; | |||
| 53 | int status, imagegrew = 0; | |||
| 54 | uint32 strip; | |||
| 55 | ||||
| 56 | if (!WRITECHECKSTRIPS(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),0, module))) | |||
| 57 | return (-1); | |||
| 58 | /* | |||
| 59 | * Handle delayed allocation of data buffer. This | |||
| 60 | * permits it to be sized more intelligently (using | |||
| 61 | * directory information). | |||
| 62 | */ | |||
| 63 | if (!BUFFERCHECK(tif)((((tif)->tif_flags & 0x00010) && tif->tif_rawdata ) || TIFFWriteBufferSetup((tif), ((void*)0), (tmsize_t) -1))) | |||
| 64 | return (-1); | |||
| 65 | tif->tif_flags |= TIFF_BUF4WRITE0x100000; /* not strictly sure this is right*/ | |||
| 66 | ||||
| 67 | td = &tif->tif_dir; | |||
| 68 | /* | |||
| 69 | * Extend image length if needed | |||
| 70 | * (but only for PlanarConfig=1). | |||
| 71 | */ | |||
| 72 | if (row >= td->td_imagelength) { /* extend image */ | |||
| 73 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE2) { | |||
| 74 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 75 | "Can not change \"ImageLength\" when using separate planes"); | |||
| 76 | return (-1); | |||
| 77 | } | |||
| 78 | td->td_imagelength = row+1; | |||
| 79 | imagegrew = 1; | |||
| 80 | } | |||
| 81 | /* | |||
| 82 | * Calculate strip and check for crossings. | |||
| 83 | */ | |||
| 84 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE2) { | |||
| 85 | if (sample >= td->td_samplesperpixel) { | |||
| 86 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 87 | "%lu: Sample out of range, max %lu", | |||
| 88 | (unsigned long) sample, (unsigned long) td->td_samplesperpixel); | |||
| 89 | return (-1); | |||
| 90 | } | |||
| 91 | strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; | |||
| 92 | } else | |||
| 93 | strip = row / td->td_rowsperstrip; | |||
| 94 | /* | |||
| 95 | * Check strip array to make sure there's space. We don't support | |||
| 96 | * dynamically growing files that have data organized in separate | |||
| 97 | * bitplanes because it's too painful. In that case we require that | |||
| 98 | * the imagelength be set properly before the first write (so that the | |||
| 99 | * strips array will be fully allocated above). | |||
| 100 | */ | |||
| 101 | if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) | |||
| 102 | return (-1); | |||
| 103 | if (strip != tif->tif_curstrip) { | |||
| 104 | /* | |||
| 105 | * Changing strips -- flush any data present. | |||
| 106 | */ | |||
| 107 | if (!TIFFFlushData(tif)) | |||
| 108 | return (-1); | |||
| 109 | tif->tif_curstrip = strip; | |||
| 110 | /* | |||
| 111 | * Watch out for a growing image. The value of strips/image | |||
| 112 | * will initially be 1 (since it can't be deduced until the | |||
| 113 | * imagelength is known). | |||
| 114 | */ | |||
| 115 | if (strip >= td->td_stripsperimage && imagegrew) | |||
| 116 | td->td_stripsperimage = | |||
| 117 | TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip)(((uint32)td->td_imagelength < (0xffffffff - (uint32)(td ->td_rowsperstrip-1))) ? ((((uint32)(td->td_imagelength ))+(((uint32)(td->td_rowsperstrip))-1))/((uint32)(td->td_rowsperstrip ))) : 0U); | |||
| 118 | tif->tif_row = | |||
| 119 | (strip % td->td_stripsperimage) * td->td_rowsperstrip; | |||
| 120 | if ((tif->tif_flags & TIFF_CODERSETUP0x00020) == 0) { | |||
| 121 | if (!(*tif->tif_setupencode)(tif)) | |||
| 122 | return (-1); | |||
| 123 | tif->tif_flags |= TIFF_CODERSETUP0x00020; | |||
| 124 | } | |||
| 125 | ||||
| 126 | tif->tif_rawcc = 0; | |||
| 127 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 128 | ||||
| 129 | if( td->td_stripbytecount[strip] > 0 ) | |||
| 130 | { | |||
| 131 | /* if we are writing over existing tiles, zero length */ | |||
| 132 | td->td_stripbytecount[strip] = 0; | |||
| 133 | ||||
| 134 | /* this forces TIFFAppendToStrip() to do a seek */ | |||
| 135 | tif->tif_curoff = 0; | |||
| 136 | } | |||
| 137 | ||||
| 138 | if (!(*tif->tif_preencode)(tif, sample)) | |||
| 139 | return (-1); | |||
| 140 | tif->tif_flags |= TIFF_POSTENCODE0x01000; | |||
| 141 | } | |||
| 142 | /* | |||
| 143 | * Ensure the write is either sequential or at the | |||
| 144 | * beginning of a strip (or that we can randomly | |||
| 145 | * access the data -- i.e. no encoding). | |||
| 146 | */ | |||
| 147 | if (row != tif->tif_row) { | |||
| 148 | if (row < tif->tif_row) { | |||
| 149 | /* | |||
| 150 | * Moving backwards within the same strip: | |||
| 151 | * backup to the start and then decode | |||
| 152 | * forward (below). | |||
| 153 | */ | |||
| 154 | tif->tif_row = (strip % td->td_stripsperimage) * | |||
| 155 | td->td_rowsperstrip; | |||
| 156 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 157 | } | |||
| 158 | /* | |||
| 159 | * Seek forward to the desired row. | |||
| 160 | */ | |||
| 161 | if (!(*tif->tif_seek)(tif, row - tif->tif_row)) | |||
| 162 | return (-1); | |||
| 163 | tif->tif_row = row; | |||
| 164 | } | |||
| 165 | ||||
| 166 | /* swab if needed - note that source buffer will be altered */ | |||
| 167 | tif->tif_postdecode( tif, (uint8*) buf, tif->tif_scanlinesize ); | |||
| 168 | ||||
| 169 | status = (*tif->tif_encoderow)(tif, (uint8*) buf, | |||
| 170 | tif->tif_scanlinesize, sample); | |||
| 171 | ||||
| 172 | /* we are now poised at the beginning of the next row */ | |||
| 173 | tif->tif_row = row + 1; | |||
| 174 | return (status); | |||
| 175 | } | |||
| 176 | ||||
| 177 | /* | |||
| 178 | * Encode the supplied data and write it to the | |||
| 179 | * specified strip. | |||
| 180 | * | |||
| 181 | * NB: Image length must be setup before writing. | |||
| 182 | */ | |||
| 183 | tmsize_t | |||
| 184 | TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) | |||
| 185 | { | |||
| 186 | static const char module[] = "TIFFWriteEncodedStrip"; | |||
| 187 | TIFFDirectory *td = &tif->tif_dir; | |||
| 188 | uint16 sample; | |||
| 189 | ||||
| 190 | if (!WRITECHECKSTRIPS(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),0, module))) | |||
| 191 | return ((tmsize_t) -1); | |||
| 192 | /* | |||
| 193 | * Check strip array to make sure there's space. | |||
| 194 | * We don't support dynamically growing files that | |||
| 195 | * have data organized in separate bitplanes because | |||
| 196 | * it's too painful. In that case we require that | |||
| 197 | * the imagelength be set properly before the first | |||
| 198 | * write (so that the strips array will be fully | |||
| 199 | * allocated above). | |||
| 200 | */ | |||
| 201 | if (strip >= td->td_nstrips) { | |||
| 202 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE2) { | |||
| 203 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 204 | "Can not grow image by strips when using separate planes"); | |||
| 205 | return ((tmsize_t) -1); | |||
| 206 | } | |||
| 207 | if (!TIFFGrowStrips(tif, 1, module)) | |||
| 208 | return ((tmsize_t) -1); | |||
| 209 | td->td_stripsperimage = | |||
| 210 | TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)(((uint32)td->td_imagelength < (0xffffffff - (uint32)(td ->td_rowsperstrip-1))) ? ((((uint32)(td->td_imagelength ))+(((uint32)(td->td_rowsperstrip))-1))/((uint32)(td->td_rowsperstrip ))) : 0U); | |||
| 211 | } | |||
| 212 | /* | |||
| 213 | * Handle delayed allocation of data buffer. This | |||
| 214 | * permits it to be sized according to the directory | |||
| 215 | * info. | |||
| 216 | */ | |||
| 217 | if (!BUFFERCHECK(tif)((((tif)->tif_flags & 0x00010) && tif->tif_rawdata ) || TIFFWriteBufferSetup((tif), ((void*)0), (tmsize_t) -1))) | |||
| 218 | return ((tmsize_t) -1); | |||
| 219 | ||||
| 220 | tif->tif_flags |= TIFF_BUF4WRITE0x100000; | |||
| 221 | tif->tif_curstrip = strip; | |||
| 222 | ||||
| 223 | tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; | |||
| 224 | if ((tif->tif_flags & TIFF_CODERSETUP0x00020) == 0) { | |||
| 225 | if (!(*tif->tif_setupencode)(tif)) | |||
| 226 | return ((tmsize_t) -1); | |||
| 227 | tif->tif_flags |= TIFF_CODERSETUP0x00020; | |||
| 228 | } | |||
| 229 | ||||
| 230 | tif->tif_rawcc = 0; | |||
| 231 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 232 | ||||
| 233 | if( td->td_stripbytecount[strip] > 0 ) | |||
| 234 | { | |||
| 235 | /* Force TIFFAppendToStrip() to consider placing data at end | |||
| 236 | of file. */ | |||
| 237 | tif->tif_curoff = 0; | |||
| 238 | } | |||
| 239 | ||||
| 240 | tif->tif_flags &= ~TIFF_POSTENCODE0x01000; | |||
| 241 | sample = (uint16)(strip / td->td_stripsperimage); | |||
| 242 | if (!(*tif->tif_preencode)(tif, sample)) | |||
| 243 | return ((tmsize_t) -1); | |||
| 244 | ||||
| 245 | /* swab if needed - note that source buffer will be altered */ | |||
| 246 | tif->tif_postdecode( tif, (uint8*) data, cc ); | |||
| 247 | ||||
| 248 | if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) | |||
| 249 | return (0); | |||
| 250 | if (!(*tif->tif_postencode)(tif)) | |||
| 251 | return ((tmsize_t) -1); | |||
| 252 | if (!isFillOrder(tif, td->td_fillorder)(((tif)->tif_flags & (td->td_fillorder)) != 0) && | |||
| 253 | (tif->tif_flags & TIFF_NOBITREV0x00100) == 0) | |||
| 254 | TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); | |||
| 255 | if (tif->tif_rawcc > 0 && | |||
| 256 | !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) | |||
| 257 | return ((tmsize_t) -1); | |||
| 258 | tif->tif_rawcc = 0; | |||
| 259 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 260 | return (cc); | |||
| 261 | } | |||
| 262 | ||||
| 263 | /* | |||
| 264 | * Write the supplied data to the specified strip. | |||
| 265 | * | |||
| 266 | * NB: Image length must be setup before writing. | |||
| 267 | */ | |||
| 268 | tmsize_t | |||
| 269 | TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) | |||
| 270 | { | |||
| 271 | static const char module[] = "TIFFWriteRawStrip"; | |||
| 272 | TIFFDirectory *td = &tif->tif_dir; | |||
| 273 | ||||
| 274 | if (!WRITECHECKSTRIPS(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),0, module))) | |||
| ||||
| 275 | return ((tmsize_t) -1); | |||
| 276 | /* | |||
| 277 | * Check strip array to make sure there's space. | |||
| 278 | * We don't support dynamically growing files that | |||
| 279 | * have data organized in separate bitplanes because | |||
| 280 | * it's too painful. In that case we require that | |||
| 281 | * the imagelength be set properly before the first | |||
| 282 | * write (so that the strips array will be fully | |||
| 283 | * allocated above). | |||
| 284 | */ | |||
| 285 | if (strip >= td->td_nstrips) { | |||
| 286 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE2) { | |||
| 287 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 288 | "Can not grow image by strips when using separate planes"); | |||
| 289 | return ((tmsize_t) -1); | |||
| 290 | } | |||
| 291 | /* | |||
| 292 | * Watch out for a growing image. The value of | |||
| 293 | * strips/image will initially be 1 (since it | |||
| 294 | * can't be deduced until the imagelength is known). | |||
| 295 | */ | |||
| 296 | if (strip >= td->td_stripsperimage) | |||
| 297 | td->td_stripsperimage = | |||
| 298 | TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip)(((uint32)td->td_imagelength < (0xffffffff - (uint32)(td ->td_rowsperstrip-1))) ? ((((uint32)(td->td_imagelength ))+(((uint32)(td->td_rowsperstrip))-1))/((uint32)(td->td_rowsperstrip ))) : 0U); | |||
| 299 | if (!TIFFGrowStrips(tif, 1, module)) | |||
| 300 | return ((tmsize_t) -1); | |||
| 301 | } | |||
| 302 | tif->tif_curstrip = strip; | |||
| 303 | tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; | |||
| ||||
| 304 | return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ? | |||
| 305 | cc : (tmsize_t) -1); | |||
| 306 | } | |||
| 307 | ||||
| 308 | /* | |||
| 309 | * Write and compress a tile of data. The | |||
| 310 | * tile is selected by the (x,y,z,s) coordinates. | |||
| 311 | */ | |||
| 312 | tmsize_t | |||
| 313 | TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s) | |||
| 314 | { | |||
| 315 | if (!TIFFCheckTile(tif, x, y, z, s)) | |||
| 316 | return ((tmsize_t)(-1)); | |||
| 317 | /* | |||
| 318 | * NB: A tile size of -1 is used instead of tif_tilesize knowing | |||
| 319 | * that TIFFWriteEncodedTile will clamp this to the tile size. | |||
| 320 | * This is done because the tile size may not be defined until | |||
| 321 | * after the output buffer is setup in TIFFWriteBufferSetup. | |||
| 322 | */ | |||
| 323 | return (TIFFWriteEncodedTile(tif, | |||
| 324 | TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1))); | |||
| 325 | } | |||
| 326 | ||||
| 327 | /* | |||
| 328 | * Encode the supplied data and write it to the | |||
| 329 | * specified tile. There must be space for the | |||
| 330 | * data. The function clamps individual writes | |||
| 331 | * to a tile to the tile size, but does not (and | |||
| 332 | * can not) check that multiple writes to the same | |||
| 333 | * tile do not write more than tile size data. | |||
| 334 | * | |||
| 335 | * NB: Image length must be setup before writing; this | |||
| 336 | * interface does not support automatically growing | |||
| 337 | * the image on each write (as TIFFWriteScanline does). | |||
| 338 | */ | |||
| 339 | tmsize_t | |||
| 340 | TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) | |||
| 341 | { | |||
| 342 | static const char module[] = "TIFFWriteEncodedTile"; | |||
| 343 | TIFFDirectory *td; | |||
| 344 | uint16 sample; | |||
| 345 | ||||
| 346 | if (!WRITECHECKTILES(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),1, module))) | |||
| 347 | return ((tmsize_t)(-1)); | |||
| 348 | td = &tif->tif_dir; | |||
| 349 | if (tile >= td->td_nstrips) { | |||
| 350 | TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", | |||
| 351 | (unsigned long) tile, (unsigned long) td->td_nstrips); | |||
| 352 | return ((tmsize_t)(-1)); | |||
| 353 | } | |||
| 354 | /* | |||
| 355 | * Handle delayed allocation of data buffer. This | |||
| 356 | * permits it to be sized more intelligently (using | |||
| 357 | * directory information). | |||
| 358 | */ | |||
| 359 | if (!BUFFERCHECK(tif)((((tif)->tif_flags & 0x00010) && tif->tif_rawdata ) || TIFFWriteBufferSetup((tif), ((void*)0), (tmsize_t) -1))) | |||
| 360 | return ((tmsize_t)(-1)); | |||
| 361 | ||||
| 362 | tif->tif_flags |= TIFF_BUF4WRITE0x100000; | |||
| 363 | tif->tif_curtile = tile; | |||
| 364 | ||||
| 365 | tif->tif_rawcc = 0; | |||
| 366 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 367 | ||||
| 368 | if( td->td_stripbytecount[tile] > 0 ) | |||
| 369 | { | |||
| 370 | /* Force TIFFAppendToStrip() to consider placing data at end | |||
| 371 | of file. */ | |||
| 372 | tif->tif_curoff = 0; | |||
| 373 | } | |||
| 374 | ||||
| 375 | /* | |||
| 376 | * Compute tiles per row & per column to compute | |||
| 377 | * current row and column | |||
| 378 | */ | |||
| 379 | tif->tif_row = (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength)(((uint32)td->td_imagelength < (0xffffffff - (uint32)(td ->td_tilelength-1))) ? ((((uint32)(td->td_imagelength)) +(((uint32)(td->td_tilelength))-1))/((uint32)(td->td_tilelength ))) : 0U)) | |||
| 380 | * td->td_tilelength; | |||
| 381 | tif->tif_col = (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth)(((uint32)td->td_imagewidth < (0xffffffff - (uint32)(td ->td_tilewidth-1))) ? ((((uint32)(td->td_imagewidth))+( ((uint32)(td->td_tilewidth))-1))/((uint32)(td->td_tilewidth ))) : 0U)) | |||
| 382 | * td->td_tilewidth; | |||
| 383 | ||||
| 384 | if ((tif->tif_flags & TIFF_CODERSETUP0x00020) == 0) { | |||
| 385 | if (!(*tif->tif_setupencode)(tif)) | |||
| 386 | return ((tmsize_t)(-1)); | |||
| 387 | tif->tif_flags |= TIFF_CODERSETUP0x00020; | |||
| 388 | } | |||
| 389 | tif->tif_flags &= ~TIFF_POSTENCODE0x01000; | |||
| 390 | sample = (uint16)(tile/td->td_stripsperimage); | |||
| 391 | if (!(*tif->tif_preencode)(tif, sample)) | |||
| 392 | return ((tmsize_t)(-1)); | |||
| 393 | /* | |||
| 394 | * Clamp write amount to the tile size. This is mostly | |||
| 395 | * done so that callers can pass in some large number | |||
| 396 | * (e.g. -1) and have the tile size used instead. | |||
| 397 | */ | |||
| 398 | if ( cc < 1 || cc > tif->tif_tilesize) | |||
| 399 | cc = tif->tif_tilesize; | |||
| 400 | ||||
| 401 | /* swab if needed - note that source buffer will be altered */ | |||
| 402 | tif->tif_postdecode( tif, (uint8*) data, cc ); | |||
| 403 | ||||
| 404 | if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) | |||
| 405 | return (0); | |||
| 406 | if (!(*tif->tif_postencode)(tif)) | |||
| 407 | return ((tmsize_t)(-1)); | |||
| 408 | if (!isFillOrder(tif, td->td_fillorder)(((tif)->tif_flags & (td->td_fillorder)) != 0) && | |||
| 409 | (tif->tif_flags & TIFF_NOBITREV0x00100) == 0) | |||
| 410 | TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); | |||
| 411 | if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, | |||
| 412 | tif->tif_rawdata, tif->tif_rawcc)) | |||
| 413 | return ((tmsize_t)(-1)); | |||
| 414 | tif->tif_rawcc = 0; | |||
| 415 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 416 | return (cc); | |||
| 417 | } | |||
| 418 | ||||
| 419 | /* | |||
| 420 | * Write the supplied data to the specified strip. | |||
| 421 | * There must be space for the data; we don't check | |||
| 422 | * if strips overlap! | |||
| 423 | * | |||
| 424 | * NB: Image length must be setup before writing; this | |||
| 425 | * interface does not support automatically growing | |||
| 426 | * the image on each write (as TIFFWriteScanline does). | |||
| 427 | */ | |||
| 428 | tmsize_t | |||
| 429 | TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) | |||
| 430 | { | |||
| 431 | static const char module[] = "TIFFWriteRawTile"; | |||
| 432 | ||||
| 433 | if (!WRITECHECKTILES(tif, module)(((tif)->tif_flags&0x00040) || TIFFWriteCheck((tif),1, module))) | |||
| 434 | return ((tmsize_t)(-1)); | |||
| 435 | if (tile >= tif->tif_dir.td_nstrips) { | |||
| 436 | TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", | |||
| 437 | (unsigned long) tile, | |||
| 438 | (unsigned long) tif->tif_dir.td_nstrips); | |||
| 439 | return ((tmsize_t)(-1)); | |||
| 440 | } | |||
| 441 | return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ? | |||
| 442 | cc : (tmsize_t)(-1)); | |||
| 443 | } | |||
| 444 | ||||
| 445 | #define isUnspecified(tif, f) \ | |||
| 446 | (TIFFFieldSet(tif,f)(((tif)->tif_dir.td_fieldsset[(f)/32]) & (((unsigned long )1L)<<((f)&0x1f))) && (tif)->tif_dir.td_imagelength == 0) | |||
| 447 | ||||
| 448 | int | |||
| 449 | TIFFSetupStrips(TIFF* tif) | |||
| 450 | { | |||
| 451 | TIFFDirectory* td = &tif->tif_dir; | |||
| 452 | ||||
| 453 | if (isTiled(tif)(((tif)->tif_flags & 0x00400) != 0)) | |||
| 454 | td->td_stripsperimage = | |||
| 455 | isUnspecified(tif, FIELD_TILEDIMENSIONS2) ? | |||
| 456 | td->td_samplesperpixel : TIFFNumberOfTiles(tif); | |||
| 457 | else | |||
| 458 | td->td_stripsperimage = | |||
| 459 | isUnspecified(tif, FIELD_ROWSPERSTRIP17) ? | |||
| 460 | td->td_samplesperpixel : TIFFNumberOfStrips(tif); | |||
| 461 | td->td_nstrips = td->td_stripsperimage; | |||
| 462 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE2) | |||
| 463 | td->td_stripsperimage /= td->td_samplesperpixel; | |||
| 464 | td->td_stripoffset = (uint64 *) | |||
| 465 | _TIFFmalloc(td->td_nstrips * sizeof (uint64)); | |||
| 466 | td->td_stripbytecount = (uint64 *) | |||
| 467 | _TIFFmalloc(td->td_nstrips * sizeof (uint64)); | |||
| 468 | if (td->td_stripoffset == NULL((void*)0) || td->td_stripbytecount == NULL((void*)0)) | |||
| 469 | return (0); | |||
| 470 | /* | |||
| 471 | * Place data at the end-of-file | |||
| 472 | * (by setting offsets to zero). | |||
| 473 | */ | |||
| 474 | _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); | |||
| 475 | _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); | |||
| 476 | TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS)(((tif)->tif_dir.td_fieldsset[(25)/32]) |= (((unsigned long )1L)<<((25)&0x1f))); | |||
| 477 | TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS)(((tif)->tif_dir.td_fieldsset[(24)/32]) |= (((unsigned long )1L)<<((24)&0x1f))); | |||
| 478 | return (1); | |||
| 479 | } | |||
| 480 | #undef isUnspecified | |||
| 481 | ||||
| 482 | /* | |||
| 483 | * Verify file is writable and that the directory | |||
| 484 | * information is setup properly. In doing the latter | |||
| 485 | * we also "freeze" the state of the directory so | |||
| 486 | * that important information is not changed. | |||
| 487 | */ | |||
| 488 | int | |||
| 489 | TIFFWriteCheck(TIFF* tif, int tiles, const char* module) | |||
| 490 | { | |||
| 491 | if (tif->tif_mode == O_RDONLY00) { | |||
| 492 | TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing"); | |||
| 493 | return (0); | |||
| 494 | } | |||
| 495 | if (tiles ^ isTiled(tif)(((tif)->tif_flags & 0x00400) != 0)) { | |||
| 496 | TIFFErrorExt(tif->tif_clientdata, module, tiles ? | |||
| 497 | "Can not write tiles to a stripped image" : | |||
| 498 | "Can not write scanlines to a tiled image"); | |||
| 499 | return (0); | |||
| 500 | } | |||
| 501 | ||||
| 502 | _TIFFFillStriles( tif ); | |||
| 503 | ||||
| 504 | /* | |||
| 505 | * On the first write verify all the required information | |||
| 506 | * has been setup and initialize any data structures that | |||
| 507 | * had to wait until directory information was set. | |||
| 508 | * Note that a lot of our work is assumed to remain valid | |||
| 509 | * because we disallow any of the important parameters | |||
| 510 | * from changing after we start writing (i.e. once | |||
| 511 | * TIFF_BEENWRITING is set, TIFFSetField will only allow | |||
| 512 | * the image's length to be changed). | |||
| 513 | */ | |||
| 514 | if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)(((tif)->tif_dir.td_fieldsset[(1)/32]) & (((unsigned long )1L)<<((1)&0x1f)))) { | |||
| 515 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 516 | "Must set \"ImageWidth\" before writing data"); | |||
| 517 | return (0); | |||
| 518 | } | |||
| 519 | if (tif->tif_dir.td_samplesperpixel == 1) { | |||
| 520 | /* | |||
| 521 | * Planarconfiguration is irrelevant in case of single band | |||
| 522 | * images and need not be included. We will set it anyway, | |||
| 523 | * because this field is used in other parts of library even | |||
| 524 | * in the single band case. | |||
| 525 | */ | |||
| 526 | if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)(((tif)->tif_dir.td_fieldsset[(20)/32]) & (((unsigned long )1L)<<((20)&0x1f)))) | |||
| 527 | tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG1; | |||
| 528 | } else { | |||
| 529 | if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)(((tif)->tif_dir.td_fieldsset[(20)/32]) & (((unsigned long )1L)<<((20)&0x1f)))) { | |||
| 530 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 531 | "Must set \"PlanarConfiguration\" before writing data"); | |||
| 532 | return (0); | |||
| 533 | } | |||
| 534 | } | |||
| 535 | if (tif->tif_dir.td_stripoffset == NULL((void*)0) && !TIFFSetupStrips(tif)) { | |||
| 536 | tif->tif_dir.td_nstrips = 0; | |||
| 537 | TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", | |||
| 538 | isTiled(tif)(((tif)->tif_flags & 0x00400) != 0) ? "tile" : "strip"); | |||
| 539 | return (0); | |||
| 540 | } | |||
| 541 | if (isTiled(tif)(((tif)->tif_flags & 0x00400) != 0)) | |||
| 542 | { | |||
| 543 | tif->tif_tilesize = TIFFTileSize(tif); | |||
| 544 | if (tif->tif_tilesize == 0) | |||
| 545 | return (0); | |||
| 546 | } | |||
| 547 | else | |||
| 548 | tif->tif_tilesize = (tmsize_t)(-1); | |||
| 549 | tif->tif_scanlinesize = TIFFScanlineSize(tif); | |||
| 550 | if (tif->tif_scanlinesize == 0) | |||
| 551 | return (0); | |||
| 552 | tif->tif_flags |= TIFF_BEENWRITING0x00040; | |||
| 553 | return (1); | |||
| 554 | } | |||
| 555 | ||||
| 556 | /* | |||
| 557 | * Setup the raw data buffer used for encoding. | |||
| 558 | */ | |||
| 559 | int | |||
| 560 | TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size) | |||
| 561 | { | |||
| 562 | static const char module[] = "TIFFWriteBufferSetup"; | |||
| 563 | ||||
| 564 | if (tif->tif_rawdata) { | |||
| 565 | if (tif->tif_flags & TIFF_MYBUFFER0x00200) { | |||
| 566 | _TIFFfree(tif->tif_rawdata); | |||
| 567 | tif->tif_flags &= ~TIFF_MYBUFFER0x00200; | |||
| 568 | } | |||
| 569 | tif->tif_rawdata = NULL((void*)0); | |||
| 570 | } | |||
| 571 | if (size == (tmsize_t)(-1)) { | |||
| 572 | size = (isTiled(tif)(((tif)->tif_flags & 0x00400) != 0) ? | |||
| 573 | tif->tif_tilesize : TIFFStripSize(tif)); | |||
| 574 | /* | |||
| 575 | * Make raw data buffer at least 8K | |||
| 576 | */ | |||
| 577 | if (size < 8*1024) | |||
| 578 | size = 8*1024; | |||
| 579 | bp = NULL((void*)0); /* NB: force malloc */ | |||
| 580 | } | |||
| 581 | if (bp == NULL((void*)0)) { | |||
| 582 | bp = _TIFFmalloc(size); | |||
| 583 | if (bp == NULL((void*)0)) { | |||
| 584 | TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer"); | |||
| 585 | return (0); | |||
| 586 | } | |||
| 587 | tif->tif_flags |= TIFF_MYBUFFER0x00200; | |||
| 588 | } else | |||
| 589 | tif->tif_flags &= ~TIFF_MYBUFFER0x00200; | |||
| 590 | tif->tif_rawdata = (uint8*) bp; | |||
| 591 | tif->tif_rawdatasize = size; | |||
| 592 | tif->tif_rawcc = 0; | |||
| 593 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 594 | tif->tif_flags |= TIFF_BUFFERSETUP0x00010; | |||
| 595 | return (1); | |||
| 596 | } | |||
| 597 | ||||
| 598 | /* | |||
| 599 | * Grow the strip data structures by delta strips. | |||
| 600 | */ | |||
| 601 | static int | |||
| 602 | TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module) | |||
| 603 | { | |||
| 604 | TIFFDirectory *td = &tif->tif_dir; | |||
| 605 | uint64* new_stripoffset; | |||
| 606 | uint64* new_stripbytecount; | |||
| 607 | ||||
| 608 | assert(td->td_planarconfig == PLANARCONFIG_CONTIG)((td->td_planarconfig == 1) ? (void) (0) : __assert_fail ( "td->td_planarconfig == 1", "tif_write.c", 608, __PRETTY_FUNCTION__ )); | |||
| 609 | new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset, | |||
| 610 | (td->td_nstrips + delta) * sizeof (uint64)); | |||
| 611 | new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount, | |||
| 612 | (td->td_nstrips + delta) * sizeof (uint64)); | |||
| 613 | if (new_stripoffset == NULL((void*)0) || new_stripbytecount == NULL((void*)0)) { | |||
| 614 | if (new_stripoffset) | |||
| 615 | _TIFFfree(new_stripoffset); | |||
| 616 | if (new_stripbytecount) | |||
| 617 | _TIFFfree(new_stripbytecount); | |||
| 618 | td->td_nstrips = 0; | |||
| 619 | TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays"); | |||
| 620 | return (0); | |||
| 621 | } | |||
| 622 | td->td_stripoffset = new_stripoffset; | |||
| 623 | td->td_stripbytecount = new_stripbytecount; | |||
| 624 | _TIFFmemset(td->td_stripoffset + td->td_nstrips, | |||
| 625 | 0, delta*sizeof (uint64)); | |||
| 626 | _TIFFmemset(td->td_stripbytecount + td->td_nstrips, | |||
| 627 | 0, delta*sizeof (uint64)); | |||
| 628 | td->td_nstrips += delta; | |||
| 629 | tif->tif_flags |= TIFF_DIRTYDIRECT0x00008; | |||
| 630 | ||||
| 631 | return (1); | |||
| 632 | } | |||
| 633 | ||||
| 634 | /* | |||
| 635 | * Append the data to the specified strip. | |||
| 636 | */ | |||
| 637 | static int | |||
| 638 | TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) | |||
| 639 | { | |||
| 640 | static const char module[] = "TIFFAppendToStrip"; | |||
| 641 | TIFFDirectory *td = &tif->tif_dir; | |||
| 642 | uint64 m; | |||
| 643 | int64 old_byte_count = -1; | |||
| 644 | ||||
| 645 | if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { | |||
| 646 | assert(td->td_nstrips > 0)((td->td_nstrips > 0) ? (void) (0) : __assert_fail ("td->td_nstrips > 0" , "tif_write.c", 646, __PRETTY_FUNCTION__)); | |||
| 647 | ||||
| 648 | if( td->td_stripbytecount[strip] != 0 | |||
| 649 | && td->td_stripoffset[strip] != 0 | |||
| 650 | && td->td_stripbytecount[strip] >= (uint64) cc ) | |||
| 651 | { | |||
| 652 | /* | |||
| 653 | * There is already tile data on disk, and the new tile | |||
| 654 | * data we have will fit in the same space. The only | |||
| 655 | * aspect of this that is risky is that there could be | |||
| 656 | * more data to append to this strip before we are done | |||
| 657 | * depending on how we are getting called. | |||
| 658 | */ | |||
| 659 | if (!SeekOK(tif, td->td_stripoffset[strip])(((*((tif))->tif_seekproc)(((tif))->tif_clientdata,((td ->td_stripoffset[strip])),(0)))==(td->td_stripoffset[strip ]))) { | |||
| 660 | TIFFErrorExt(tif->tif_clientdata, module, | |||
| 661 | "Seek error at scanline %lu", | |||
| 662 | (unsigned long)tif->tif_row); | |||
| 663 | return (0); | |||
| 664 | } | |||
| 665 | } | |||
| 666 | else | |||
| 667 | { | |||
| 668 | /* | |||
| 669 | * Seek to end of file, and set that as our location to | |||
| 670 | * write this strip. | |||
| 671 | */ | |||
| 672 | td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END)((*(tif)->tif_seekproc)((tif)->tif_clientdata,(0),(2))); | |||
| 673 | tif->tif_flags |= TIFF_DIRTYSTRIP0x200000; | |||
| 674 | } | |||
| 675 | ||||
| 676 | tif->tif_curoff = td->td_stripoffset[strip]; | |||
| 677 | ||||
| 678 | /* | |||
| 679 | * We are starting a fresh strip/tile, so set the size to zero. | |||
| 680 | */ | |||
| 681 | old_byte_count = td->td_stripbytecount[strip]; | |||
| 682 | td->td_stripbytecount[strip] = 0; | |||
| 683 | } | |||
| 684 | ||||
| 685 | m = tif->tif_curoff+cc; | |||
| 686 | if (!(tif->tif_flags&TIFF_BIGTIFF0x80000)) | |||
| 687 | m = (uint32)m; | |||
| 688 | if ((m<tif->tif_curoff)||(m<(uint64)cc)) | |||
| 689 | { | |||
| 690 | TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded"); | |||
| 691 | return (0); | |||
| 692 | } | |||
| 693 | if (!WriteOK(tif, data, cc)(((*((tif))->tif_writeproc)(((tif))->tif_clientdata,((data )),((cc))))==(cc))) { | |||
| 694 | TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", | |||
| 695 | (unsigned long) tif->tif_row); | |||
| 696 | return (0); | |||
| 697 | } | |||
| 698 | tif->tif_curoff = m; | |||
| 699 | td->td_stripbytecount[strip] += cc; | |||
| 700 | ||||
| 701 | if( (int64) td->td_stripbytecount[strip] != old_byte_count ) | |||
| 702 | tif->tif_flags |= TIFF_DIRTYSTRIP0x200000; | |||
| 703 | ||||
| 704 | return (1); | |||
| 705 | } | |||
| 706 | ||||
| 707 | /* | |||
| 708 | * Internal version of TIFFFlushData that can be | |||
| 709 | * called by ``encodestrip routines'' w/o concern | |||
| 710 | * for infinite recursion. | |||
| 711 | */ | |||
| 712 | int | |||
| 713 | TIFFFlushData1(TIFF* tif) | |||
| 714 | { | |||
| 715 | if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE0x100000 ) { | |||
| 716 | if (!isFillOrder(tif, tif->tif_dir.td_fillorder)(((tif)->tif_flags & (tif->tif_dir.td_fillorder)) != 0) && | |||
| 717 | (tif->tif_flags & TIFF_NOBITREV0x00100) == 0) | |||
| 718 | TIFFReverseBits((uint8*)tif->tif_rawdata, | |||
| 719 | tif->tif_rawcc); | |||
| 720 | if (!TIFFAppendToStrip(tif, | |||
| 721 | isTiled(tif)(((tif)->tif_flags & 0x00400) != 0) ? tif->tif_curtile : tif->tif_curstrip, | |||
| 722 | tif->tif_rawdata, tif->tif_rawcc)) | |||
| 723 | return (0); | |||
| 724 | tif->tif_rawcc = 0; | |||
| 725 | tif->tif_rawcp = tif->tif_rawdata; | |||
| 726 | } | |||
| 727 | return (1); | |||
| 728 | } | |||
| 729 | ||||
| 730 | /* | |||
| 731 | * Set the current write offset. This should only be | |||
| 732 | * used to set the offset to a known previous location | |||
| 733 | * (very carefully), or to 0 so that the next write gets | |||
| 734 | * appended to the end of the file. | |||
| 735 | */ | |||
| 736 | void | |||
| 737 | TIFFSetWriteOffset(TIFF* tif, toff_t off) | |||
| 738 | { | |||
| 739 | tif->tif_curoff = off; | |||
| 740 | } | |||
| 741 | ||||
| 742 | /* vim: set ts=8 sts=8 sw=8 noet: */ | |||
| 743 | /* | |||
| 744 | * Local Variables: | |||
| 745 | * mode: c | |||
| 746 | * c-basic-offset: 8 | |||
| 747 | * fill-column: 78 | |||
| 748 | * End: | |||
| 749 | */ |