Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentif_dirwrite.c
Go to the documentation of this file.
00001 /* $Id: tif_dirwrite.c,v 1.37.2.7 2010-06-08 18:50:42 bfriesen Exp $ */ 00002 00003 /* 00004 * Copyright (c) 1988-1997 Sam Leffler 00005 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 00006 * 00007 * Permission to use, copy, modify, distribute, and sell this software and 00008 * its documentation for any purpose is hereby granted without fee, provided 00009 * that (i) the above copyright notices and this permission notice appear in 00010 * all copies of the software and related documentation, and (ii) the names of 00011 * Sam Leffler and Silicon Graphics may not be used in any advertising or 00012 * publicity relating to the software without the specific, prior written 00013 * permission of Sam Leffler and Silicon Graphics. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 00016 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 00017 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 00018 * 00019 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 00020 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 00021 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00022 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 00023 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 00024 * OF THIS SOFTWARE. 00025 */ 00026 00027 /* 00028 * TIFF Library. 00029 * 00030 * Directory Write Support Routines. 00031 */ 00032 #include "tiffiop.h" 00033 00034 #ifdef HAVE_IEEEFP 00035 # define TIFFCvtNativeToIEEEFloat(tif, n, fp) 00036 # define TIFFCvtNativeToIEEEDouble(tif, n, dp) 00037 #else 00038 extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*); 00039 extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*); 00040 #endif 00041 00042 static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*); 00043 static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32); 00044 static void TIFFSetupShort(TIFF*, ttag_t, TIFFDirEntry*, uint16); 00045 static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*); 00046 static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*); 00047 static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*); 00048 static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**); 00049 static int TIFFWriteShortArray(TIFF*, TIFFDirEntry*, uint16*); 00050 static int TIFFWriteLongArray(TIFF *, TIFFDirEntry*, uint32*); 00051 static int TIFFWriteRationalArray(TIFF *, TIFFDirEntry*, float*); 00052 static int TIFFWriteFloatArray(TIFF *, TIFFDirEntry*, float*); 00053 static int TIFFWriteDoubleArray(TIFF *, TIFFDirEntry*, double*); 00054 static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*); 00055 static int TIFFWriteAnyArray(TIFF*, 00056 TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); 00057 static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*); 00058 static int TIFFWriteInkNames(TIFF*, TIFFDirEntry*); 00059 static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*); 00060 static int TIFFLinkDirectory(TIFF*); 00061 00062 #define WriteRationalPair(type, tag1, v1, tag2, v2) { \ 00063 TIFFWriteRational((tif), (type), (tag1), (dir), (v1)) \ 00064 TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2)) \ 00065 (dir)++; \ 00066 } 00067 #define TIFFWriteRational(tif, type, tag, dir, v) \ 00068 (dir)->tdir_tag = (tag); \ 00069 (dir)->tdir_type = (type); \ 00070 (dir)->tdir_count = 1; \ 00071 if (!TIFFWriteRationalArray((tif), (dir), &(v))) \ 00072 goto bad; 00073 00074 /* 00075 * Write the contents of the current directory 00076 * to the specified file. This routine doesn't 00077 * handle overwriting a directory with auxiliary 00078 * storage that's been changed. 00079 */ 00080 static int 00081 _TIFFWriteDirectory(TIFF* tif, int done) 00082 { 00083 uint16 dircount; 00084 toff_t diroff; 00085 ttag_t tag; 00086 uint32 nfields; 00087 tsize_t dirsize; 00088 char* data; 00089 TIFFDirEntry* dir; 00090 TIFFDirectory* td; 00091 unsigned long b, fields[FIELD_SETLONGS]; 00092 int fi, nfi; 00093 00094 if (tif->tif_mode == O_RDONLY) 00095 return (1); 00096 /* 00097 * Clear write state so that subsequent images with 00098 * different characteristics get the right buffers 00099 * setup for them. 00100 */ 00101 if (done) 00102 { 00103 if (tif->tif_flags & TIFF_POSTENCODE) { 00104 tif->tif_flags &= ~TIFF_POSTENCODE; 00105 if (!(*tif->tif_postencode)(tif)) { 00106 TIFFErrorExt(tif->tif_clientdata, 00107 tif->tif_name, 00108 "Error post-encoding before directory write"); 00109 return (0); 00110 } 00111 } 00112 (*tif->tif_close)(tif); /* shutdown encoder */ 00113 /* 00114 * Flush any data that might have been written 00115 * by the compression close+cleanup routines. 00116 */ 00117 if (tif->tif_rawcc > 0 00118 && (tif->tif_flags & TIFF_BEENWRITING) != 0 00119 && !TIFFFlushData1(tif)) { 00120 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00121 "Error flushing data before directory write"); 00122 return (0); 00123 } 00124 if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { 00125 _TIFFfree(tif->tif_rawdata); 00126 tif->tif_rawdata = NULL; 00127 tif->tif_rawcc = 0; 00128 tif->tif_rawdatasize = 0; 00129 } 00130 tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); 00131 } 00132 00133 td = &tif->tif_dir; 00134 /* 00135 * Size the directory so that we can calculate 00136 * offsets for the data items that aren't kept 00137 * in-place in each field. 00138 */ 00139 nfields = 0; 00140 for (b = 0; b <= FIELD_LAST; b++) 00141 if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM) 00142 nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); 00143 nfields += td->td_customValueCount; 00144 dirsize = nfields * sizeof (TIFFDirEntry); 00145 data = (char*) _TIFFmalloc(dirsize); 00146 if (data == NULL) { 00147 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00148 "Cannot write directory, out of space"); 00149 return (0); 00150 } 00151 /* 00152 * Directory hasn't been placed yet, put 00153 * it at the end of the file and link it 00154 * into the existing directory structure. 00155 */ 00156 if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) 00157 goto bad; 00158 tif->tif_dataoff = (toff_t)( 00159 tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); 00160 if (tif->tif_dataoff & 1) 00161 tif->tif_dataoff++; 00162 (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); 00163 tif->tif_curdir++; 00164 dir = (TIFFDirEntry*) data; 00165 /* 00166 * Setup external form of directory 00167 * entries and write data items. 00168 */ 00169 _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); 00170 /* 00171 * Write out ExtraSamples tag only if 00172 * extra samples are present in the data. 00173 */ 00174 if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) { 00175 ResetFieldBit(fields, FIELD_EXTRASAMPLES); 00176 nfields--; 00177 dirsize -= sizeof (TIFFDirEntry); 00178 } /*XXX*/ 00179 for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { 00180 const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; 00181 00182 /* 00183 * For custom fields, we test to see if the custom field 00184 * is set or not. For normal fields, we just use the 00185 * FieldSet test. 00186 */ 00187 if( fip->field_bit == FIELD_CUSTOM ) 00188 { 00189 int ci, is_set = FALSE; 00190 00191 for( ci = 0; ci < td->td_customValueCount; ci++ ) 00192 is_set |= (td->td_customValues[ci].info == fip); 00193 00194 if( !is_set ) 00195 continue; 00196 } 00197 else if (!FieldSet(fields, fip->field_bit)) 00198 continue; 00199 00200 /* 00201 * Handle other fields. 00202 */ 00203 switch (fip->field_bit) 00204 { 00205 case FIELD_STRIPOFFSETS: 00206 /* 00207 * We use one field bit for both strip and tile 00208 00209 * offsets, and so must be careful in selecting 00210 * the appropriate field descriptor (so that tags 00211 * are written in sorted order). 00212 */ 00213 tag = isTiled(tif) ? 00214 TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS; 00215 if (tag != fip->field_tag) 00216 continue; 00217 00218 dir->tdir_tag = (uint16) tag; 00219 dir->tdir_type = (uint16) TIFF_LONG; 00220 dir->tdir_count = (uint32) td->td_nstrips; 00221 if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset)) 00222 goto bad; 00223 break; 00224 case FIELD_STRIPBYTECOUNTS: 00225 /* 00226 * We use one field bit for both strip and tile 00227 * byte counts, and so must be careful in selecting 00228 * the appropriate field descriptor (so that tags 00229 * are written in sorted order). 00230 */ 00231 tag = isTiled(tif) ? 00232 TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS; 00233 if (tag != fip->field_tag) 00234 continue; 00235 00236 dir->tdir_tag = (uint16) tag; 00237 dir->tdir_type = (uint16) TIFF_LONG; 00238 dir->tdir_count = (uint32) td->td_nstrips; 00239 if (!TIFFWriteLongArray(tif, dir, td->td_stripbytecount)) 00240 goto bad; 00241 break; 00242 case FIELD_ROWSPERSTRIP: 00243 TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP, 00244 dir, td->td_rowsperstrip); 00245 break; 00246 case FIELD_COLORMAP: 00247 if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, 00248 3, td->td_colormap)) 00249 goto bad; 00250 break; 00251 case FIELD_IMAGEDIMENSIONS: 00252 TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, 00253 dir++, td->td_imagewidth); 00254 TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, 00255 dir, td->td_imagelength); 00256 break; 00257 case FIELD_TILEDIMENSIONS: 00258 TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, 00259 dir++, td->td_tilewidth); 00260 TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, 00261 dir, td->td_tilelength); 00262 break; 00263 case FIELD_COMPRESSION: 00264 TIFFSetupShort(tif, TIFFTAG_COMPRESSION, 00265 dir, td->td_compression); 00266 break; 00267 case FIELD_PHOTOMETRIC: 00268 TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC, 00269 dir, td->td_photometric); 00270 break; 00271 case FIELD_POSITION: 00272 WriteRationalPair(TIFF_RATIONAL, 00273 TIFFTAG_XPOSITION, td->td_xposition, 00274 TIFFTAG_YPOSITION, td->td_yposition); 00275 break; 00276 case FIELD_RESOLUTION: 00277 WriteRationalPair(TIFF_RATIONAL, 00278 TIFFTAG_XRESOLUTION, td->td_xresolution, 00279 TIFFTAG_YRESOLUTION, td->td_yresolution); 00280 break; 00281 case FIELD_BITSPERSAMPLE: 00282 case FIELD_MINSAMPLEVALUE: 00283 case FIELD_MAXSAMPLEVALUE: 00284 case FIELD_SAMPLEFORMAT: 00285 if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) 00286 goto bad; 00287 break; 00288 case FIELD_SMINSAMPLEVALUE: 00289 case FIELD_SMAXSAMPLEVALUE: 00290 if (!TIFFWritePerSampleAnys(tif, 00291 _TIFFSampleToTagType(tif), fip->field_tag, dir)) 00292 goto bad; 00293 break; 00294 case FIELD_PAGENUMBER: 00295 case FIELD_HALFTONEHINTS: 00296 case FIELD_YCBCRSUBSAMPLING: 00297 if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) 00298 goto bad; 00299 break; 00300 case FIELD_INKNAMES: 00301 if (!TIFFWriteInkNames(tif, dir)) 00302 goto bad; 00303 break; 00304 case FIELD_TRANSFERFUNCTION: 00305 if (!TIFFWriteTransferFunction(tif, dir)) 00306 goto bad; 00307 break; 00308 case FIELD_SUBIFD: 00309 /* 00310 * XXX: Always write this field using LONG type 00311 * for backward compatibility. 00312 */ 00313 dir->tdir_tag = (uint16) fip->field_tag; 00314 dir->tdir_type = (uint16) TIFF_LONG; 00315 dir->tdir_count = (uint32) td->td_nsubifd; 00316 if (!TIFFWriteLongArray(tif, dir, td->td_subifd)) 00317 goto bad; 00318 /* 00319 * Total hack: if this directory includes a SubIFD 00320 * tag then force the next <n> directories to be 00321 * written as ``sub directories'' of this one. This 00322 * is used to write things like thumbnails and 00323 * image masks that one wants to keep out of the 00324 * normal directory linkage access mechanism. 00325 */ 00326 if (dir->tdir_count > 0) { 00327 tif->tif_flags |= TIFF_INSUBIFD; 00328 tif->tif_nsubifd = (uint16) dir->tdir_count; 00329 if (dir->tdir_count > 1) 00330 tif->tif_subifdoff = dir->tdir_offset; 00331 else 00332 tif->tif_subifdoff = (uint32)( 00333 tif->tif_diroff 00334 + sizeof (uint16) 00335 + ((char*)&dir->tdir_offset-data)); 00336 } 00337 break; 00338 default: 00339 /* XXX: Should be fixed and removed. */ 00340 if (fip->field_tag == TIFFTAG_DOTRANGE) { 00341 if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) 00342 goto bad; 00343 } 00344 else if (!TIFFWriteNormalTag(tif, dir, fip)) 00345 goto bad; 00346 break; 00347 } 00348 dir++; 00349 00350 if( fip->field_bit != FIELD_CUSTOM ) 00351 ResetFieldBit(fields, fip->field_bit); 00352 } 00353 00354 /* 00355 * Write directory. 00356 */ 00357 dircount = (uint16) nfields; 00358 diroff = (uint32) tif->tif_nextdiroff; 00359 if (tif->tif_flags & TIFF_SWAB) { 00360 /* 00361 * The file's byte order is opposite to the 00362 * native machine architecture. We overwrite 00363 * the directory information with impunity 00364 * because it'll be released below after we 00365 * write it to the file. Note that all the 00366 * other tag construction routines assume that 00367 * we do this byte-swapping; i.e. they only 00368 * byte-swap indirect data. 00369 */ 00370 for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { 00371 TIFFSwabArrayOfShort(&dir->tdir_tag, 2); 00372 TIFFSwabArrayOfLong(&dir->tdir_count, 2); 00373 } 00374 dircount = (uint16) nfields; 00375 TIFFSwabShort(&dircount); 00376 TIFFSwabLong(&diroff); 00377 } 00378 (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); 00379 if (!WriteOK(tif, &dircount, sizeof (dircount))) { 00380 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00381 "Error writing directory count"); 00382 goto bad; 00383 } 00384 if (!WriteOK(tif, data, dirsize)) { 00385 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00386 "Error writing directory contents"); 00387 goto bad; 00388 } 00389 if (!WriteOK(tif, &diroff, sizeof (uint32))) { 00390 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00391 "Error writing directory link"); 00392 goto bad; 00393 } 00394 if (done) { 00395 TIFFFreeDirectory(tif); 00396 tif->tif_flags &= ~TIFF_DIRTYDIRECT; 00397 (*tif->tif_cleanup)(tif); 00398 00399 /* 00400 * Reset directory-related state for subsequent 00401 * directories. 00402 */ 00403 TIFFCreateDirectory(tif); 00404 } 00405 _TIFFfree(data); 00406 return (1); 00407 bad: 00408 _TIFFfree(data); 00409 return (0); 00410 } 00411 #undef WriteRationalPair 00412 00413 int 00414 TIFFWriteDirectory(TIFF* tif) 00415 { 00416 return _TIFFWriteDirectory(tif, TRUE); 00417 } 00418 00419 /* 00420 * Similar to TIFFWriteDirectory(), writes the directory out 00421 * but leaves all data structures in memory so that it can be 00422 * written again. This will make a partially written TIFF file 00423 * readable before it is successfully completed/closed. 00424 */ 00425 int 00426 TIFFCheckpointDirectory(TIFF* tif) 00427 { 00428 int rc; 00429 /* Setup the strips arrays, if they haven't already been. */ 00430 if (tif->tif_dir.td_stripoffset == NULL) 00431 (void) TIFFSetupStrips(tif); 00432 rc = _TIFFWriteDirectory(tif, FALSE); 00433 (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); 00434 return rc; 00435 } 00436 00437 static int 00438 _TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff) 00439 { 00440 uint16 dircount; 00441 uint32 nfields; 00442 tsize_t dirsize; 00443 char* data; 00444 TIFFDirEntry* dir; 00445 TIFFDirectory* td; 00446 unsigned long b, fields[FIELD_SETLONGS]; 00447 int fi, nfi; 00448 00449 if (tif->tif_mode == O_RDONLY) 00450 return (1); 00451 00452 td = &tif->tif_dir; 00453 /* 00454 * Size the directory so that we can calculate 00455 * offsets for the data items that aren't kept 00456 * in-place in each field. 00457 */ 00458 nfields = 0; 00459 for (b = 0; b <= FIELD_LAST; b++) 00460 if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM) 00461 nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); 00462 nfields += td->td_customValueCount; 00463 dirsize = nfields * sizeof (TIFFDirEntry); 00464 data = (char*) _TIFFmalloc(dirsize); 00465 if (data == NULL) { 00466 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00467 "Cannot write directory, out of space"); 00468 return (0); 00469 } 00470 /* 00471 * Put the directory at the end of the file. 00472 */ 00473 tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; 00474 tif->tif_dataoff = (toff_t)( 00475 tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); 00476 if (tif->tif_dataoff & 1) 00477 tif->tif_dataoff++; 00478 (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); 00479 dir = (TIFFDirEntry*) data; 00480 /* 00481 * Setup external form of directory 00482 * entries and write data items. 00483 */ 00484 _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); 00485 00486 for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { 00487 const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; 00488 00489 /* 00490 * For custom fields, we test to see if the custom field 00491 * is set or not. For normal fields, we just use the 00492 * FieldSet test. 00493 */ 00494 if( fip->field_bit == FIELD_CUSTOM ) 00495 { 00496 int ci, is_set = FALSE; 00497 00498 for( ci = 0; ci < td->td_customValueCount; ci++ ) 00499 is_set |= (td->td_customValues[ci].info == fip); 00500 00501 if( !is_set ) 00502 continue; 00503 } 00504 else if (!FieldSet(fields, fip->field_bit)) 00505 continue; 00506 00507 if( fip->field_bit != FIELD_CUSTOM ) 00508 ResetFieldBit(fields, fip->field_bit); 00509 } 00510 00511 /* 00512 * Write directory. 00513 */ 00514 dircount = (uint16) nfields; 00515 *pdiroff = (uint32) tif->tif_nextdiroff; 00516 if (tif->tif_flags & TIFF_SWAB) { 00517 /* 00518 * The file's byte order is opposite to the 00519 * native machine architecture. We overwrite 00520 * the directory information with impunity 00521 * because it'll be released below after we 00522 * write it to the file. Note that all the 00523 * other tag construction routines assume that 00524 * we do this byte-swapping; i.e. they only 00525 * byte-swap indirect data. 00526 */ 00527 for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { 00528 TIFFSwabArrayOfShort(&dir->tdir_tag, 2); 00529 TIFFSwabArrayOfLong(&dir->tdir_count, 2); 00530 } 00531 dircount = (uint16) nfields; 00532 TIFFSwabShort(&dircount); 00533 TIFFSwabLong(pdiroff); 00534 } 00535 (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); 00536 if (!WriteOK(tif, &dircount, sizeof (dircount))) { 00537 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00538 "Error writing directory count"); 00539 goto bad; 00540 } 00541 if (!WriteOK(tif, data, dirsize)) { 00542 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00543 "Error writing directory contents"); 00544 goto bad; 00545 } 00546 if (!WriteOK(tif, pdiroff, sizeof (uint32))) { 00547 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00548 "Error writing directory link"); 00549 goto bad; 00550 } 00551 _TIFFfree(data); 00552 return (1); 00553 bad: 00554 _TIFFfree(data); 00555 return (0); 00556 } 00557 00558 int 00559 TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff) 00560 { 00561 return _TIFFWriteCustomDirectory(tif, pdiroff); 00562 } 00563 00564 /* 00565 * Process tags that are not special cased. 00566 */ 00567 static int 00568 TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) 00569 { 00570 uint16 wc = (uint16) fip->field_writecount; 00571 uint32 wc2; 00572 00573 dir->tdir_tag = (uint16) fip->field_tag; 00574 dir->tdir_type = (uint16) fip->field_type; 00575 dir->tdir_count = wc; 00576 00577 switch (fip->field_type) { 00578 case TIFF_SHORT: 00579 case TIFF_SSHORT: 00580 if (fip->field_passcount) { 00581 uint16* wp; 00582 if (wc == (uint16) TIFF_VARIABLE2) { 00583 TIFFGetField(tif, fip->field_tag, &wc2, &wp); 00584 dir->tdir_count = wc2; 00585 } else { /* Assume TIFF_VARIABLE */ 00586 TIFFGetField(tif, fip->field_tag, &wc, &wp); 00587 dir->tdir_count = wc; 00588 } 00589 if (!TIFFWriteShortArray(tif, dir, wp)) 00590 return 0; 00591 } else { 00592 if (wc == 1) { 00593 uint16 sv; 00594 TIFFGetField(tif, fip->field_tag, &sv); 00595 dir->tdir_offset = 00596 TIFFInsertData(tif, dir->tdir_type, sv); 00597 } else { 00598 uint16* wp; 00599 TIFFGetField(tif, fip->field_tag, &wp); 00600 if (!TIFFWriteShortArray(tif, dir, wp)) 00601 return 0; 00602 } 00603 } 00604 break; 00605 case TIFF_LONG: 00606 case TIFF_SLONG: 00607 case TIFF_IFD: 00608 if (fip->field_passcount) { 00609 uint32* lp; 00610 if (wc == (uint16) TIFF_VARIABLE2) { 00611 TIFFGetField(tif, fip->field_tag, &wc2, &lp); 00612 dir->tdir_count = wc2; 00613 } else { /* Assume TIFF_VARIABLE */ 00614 TIFFGetField(tif, fip->field_tag, &wc, &lp); 00615 dir->tdir_count = wc; 00616 } 00617 if (!TIFFWriteLongArray(tif, dir, lp)) 00618 return 0; 00619 } else { 00620 if (wc == 1) { 00621 /* XXX handle LONG->SHORT conversion */ 00622 TIFFGetField(tif, fip->field_tag, 00623 &dir->tdir_offset); 00624 } else { 00625 uint32* lp; 00626 TIFFGetField(tif, fip->field_tag, &lp); 00627 if (!TIFFWriteLongArray(tif, dir, lp)) 00628 return 0; 00629 } 00630 } 00631 break; 00632 case TIFF_RATIONAL: 00633 case TIFF_SRATIONAL: 00634 if (fip->field_passcount) { 00635 float* fp; 00636 if (wc == (uint16) TIFF_VARIABLE2) { 00637 TIFFGetField(tif, fip->field_tag, &wc2, &fp); 00638 dir->tdir_count = wc2; 00639 } else { /* Assume TIFF_VARIABLE */ 00640 TIFFGetField(tif, fip->field_tag, &wc, &fp); 00641 dir->tdir_count = wc; 00642 } 00643 if (!TIFFWriteRationalArray(tif, dir, fp)) 00644 return 0; 00645 } else { 00646 if (wc == 1) { 00647 float fv; 00648 TIFFGetField(tif, fip->field_tag, &fv); 00649 if (!TIFFWriteRationalArray(tif, dir, &fv)) 00650 return 0; 00651 } else { 00652 float* fp; 00653 TIFFGetField(tif, fip->field_tag, &fp); 00654 if (!TIFFWriteRationalArray(tif, dir, fp)) 00655 return 0; 00656 } 00657 } 00658 break; 00659 case TIFF_FLOAT: 00660 if (fip->field_passcount) { 00661 float* fp; 00662 if (wc == (uint16) TIFF_VARIABLE2) { 00663 TIFFGetField(tif, fip->field_tag, &wc2, &fp); 00664 dir->tdir_count = wc2; 00665 } else { /* Assume TIFF_VARIABLE */ 00666 TIFFGetField(tif, fip->field_tag, &wc, &fp); 00667 dir->tdir_count = wc; 00668 } 00669 if (!TIFFWriteFloatArray(tif, dir, fp)) 00670 return 0; 00671 } else { 00672 if (wc == 1) { 00673 float fv; 00674 TIFFGetField(tif, fip->field_tag, &fv); 00675 if (!TIFFWriteFloatArray(tif, dir, &fv)) 00676 return 0; 00677 } else { 00678 float* fp; 00679 TIFFGetField(tif, fip->field_tag, &fp); 00680 if (!TIFFWriteFloatArray(tif, dir, fp)) 00681 return 0; 00682 } 00683 } 00684 break; 00685 case TIFF_DOUBLE: 00686 if (fip->field_passcount) { 00687 double* dp; 00688 if (wc == (uint16) TIFF_VARIABLE2) { 00689 TIFFGetField(tif, fip->field_tag, &wc2, &dp); 00690 dir->tdir_count = wc2; 00691 } else { /* Assume TIFF_VARIABLE */ 00692 TIFFGetField(tif, fip->field_tag, &wc, &dp); 00693 dir->tdir_count = wc; 00694 } 00695 if (!TIFFWriteDoubleArray(tif, dir, dp)) 00696 return 0; 00697 } else { 00698 if (wc == 1) { 00699 double dv; 00700 TIFFGetField(tif, fip->field_tag, &dv); 00701 if (!TIFFWriteDoubleArray(tif, dir, &dv)) 00702 return 0; 00703 } else { 00704 double* dp; 00705 TIFFGetField(tif, fip->field_tag, &dp); 00706 if (!TIFFWriteDoubleArray(tif, dir, dp)) 00707 return 0; 00708 } 00709 } 00710 break; 00711 case TIFF_ASCII: 00712 { 00713 char* cp; 00714 if (fip->field_passcount) 00715 { 00716 if( wc == (uint16) TIFF_VARIABLE2 ) 00717 TIFFGetField(tif, fip->field_tag, &wc2, &cp); 00718 else 00719 TIFFGetField(tif, fip->field_tag, &wc, &cp); 00720 } 00721 else 00722 TIFFGetField(tif, fip->field_tag, &cp); 00723 00724 dir->tdir_count = (uint32) (strlen(cp) + 1); 00725 if (!TIFFWriteByteArray(tif, dir, cp)) 00726 return (0); 00727 } 00728 break; 00729 00730 case TIFF_BYTE: 00731 case TIFF_SBYTE: 00732 if (fip->field_passcount) { 00733 char* cp; 00734 if (wc == (uint16) TIFF_VARIABLE2) { 00735 TIFFGetField(tif, fip->field_tag, &wc2, &cp); 00736 dir->tdir_count = wc2; 00737 } else { /* Assume TIFF_VARIABLE */ 00738 TIFFGetField(tif, fip->field_tag, &wc, &cp); 00739 dir->tdir_count = wc; 00740 } 00741 if (!TIFFWriteByteArray(tif, dir, cp)) 00742 return 0; 00743 } else { 00744 if (wc == 1) { 00745 char cv; 00746 TIFFGetField(tif, fip->field_tag, &cv); 00747 if (!TIFFWriteByteArray(tif, dir, &cv)) 00748 return 0; 00749 } else { 00750 char* cp; 00751 TIFFGetField(tif, fip->field_tag, &cp); 00752 if (!TIFFWriteByteArray(tif, dir, cp)) 00753 return 0; 00754 } 00755 } 00756 break; 00757 00758 case TIFF_UNDEFINED: 00759 { char* cp; 00760 if (wc == (unsigned short) TIFF_VARIABLE) { 00761 TIFFGetField(tif, fip->field_tag, &wc, &cp); 00762 dir->tdir_count = wc; 00763 } else if (wc == (unsigned short) TIFF_VARIABLE2) { 00764 TIFFGetField(tif, fip->field_tag, &wc2, &cp); 00765 dir->tdir_count = wc2; 00766 } else 00767 TIFFGetField(tif, fip->field_tag, &cp); 00768 if (!TIFFWriteByteArray(tif, dir, cp)) 00769 return (0); 00770 } 00771 break; 00772 00773 case TIFF_NOTYPE: 00774 break; 00775 } 00776 return (1); 00777 } 00778 00779 /* 00780 * Setup a directory entry with either a SHORT 00781 * or LONG type according to the value. 00782 */ 00783 static void 00784 TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) 00785 { 00786 dir->tdir_tag = (uint16) tag; 00787 dir->tdir_count = 1; 00788 if (v > 0xffffL) { 00789 dir->tdir_type = (short) TIFF_LONG; 00790 dir->tdir_offset = v; 00791 } else { 00792 dir->tdir_type = (short) TIFF_SHORT; 00793 dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); 00794 } 00795 } 00796 00797 /* 00798 * Setup a SHORT directory entry 00799 */ 00800 static void 00801 TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v) 00802 { 00803 dir->tdir_tag = (uint16) tag; 00804 dir->tdir_count = 1; 00805 dir->tdir_type = (short) TIFF_SHORT; 00806 dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); 00807 } 00808 #undef MakeShortDirent 00809 00810 #define NITEMS(x) (sizeof (x) / sizeof (x[0])) 00811 /* 00812 * Setup a directory entry that references a 00813 * samples/pixel array of SHORT values and 00814 * (potentially) write the associated indirect 00815 * values. 00816 */ 00817 static int 00818 TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) 00819 { 00820 uint16 buf[10], v; 00821 uint16* w = buf; 00822 uint16 i, samples = tif->tif_dir.td_samplesperpixel; 00823 int status; 00824 00825 if (samples > NITEMS(buf)) { 00826 w = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); 00827 if (w == NULL) { 00828 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00829 "No space to write per-sample shorts"); 00830 return (0); 00831 } 00832 } 00833 TIFFGetField(tif, tag, &v); 00834 for (i = 0; i < samples; i++) 00835 w[i] = v; 00836 00837 dir->tdir_tag = (uint16) tag; 00838 dir->tdir_type = (uint16) TIFF_SHORT; 00839 dir->tdir_count = samples; 00840 status = TIFFWriteShortArray(tif, dir, w); 00841 if (w != buf) 00842 _TIFFfree((char*) w); 00843 return (status); 00844 } 00845 00846 /* 00847 * Setup a directory entry that references a samples/pixel array of ``type'' 00848 * values and (potentially) write the associated indirect values. The source 00849 * data from TIFFGetField() for the specified tag must be returned as double. 00850 */ 00851 static int 00852 TIFFWritePerSampleAnys(TIFF* tif, 00853 TIFFDataType type, ttag_t tag, TIFFDirEntry* dir) 00854 { 00855 double buf[10], v; 00856 double* w = buf; 00857 uint16 i, samples = tif->tif_dir.td_samplesperpixel; 00858 int status; 00859 00860 if (samples > NITEMS(buf)) { 00861 w = (double*) _TIFFmalloc(samples * sizeof (double)); 00862 if (w == NULL) { 00863 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00864 "No space to write per-sample values"); 00865 return (0); 00866 } 00867 } 00868 TIFFGetField(tif, tag, &v); 00869 for (i = 0; i < samples; i++) 00870 w[i] = v; 00871 status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w); 00872 if (w != buf) 00873 _TIFFfree(w); 00874 return (status); 00875 } 00876 #undef NITEMS 00877 00878 /* 00879 * Setup a pair of shorts that are returned by 00880 * value, rather than as a reference to an array. 00881 */ 00882 static int 00883 TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) 00884 { 00885 uint16 v[2]; 00886 00887 TIFFGetField(tif, tag, &v[0], &v[1]); 00888 00889 dir->tdir_tag = (uint16) tag; 00890 dir->tdir_type = (uint16) TIFF_SHORT; 00891 dir->tdir_count = 2; 00892 return (TIFFWriteShortArray(tif, dir, v)); 00893 } 00894 00895 /* 00896 * Setup a directory entry for an NxM table of shorts, 00897 * where M is known to be 2**bitspersample, and write 00898 * the associated indirect data. 00899 */ 00900 static int 00901 TIFFWriteShortTable(TIFF* tif, 00902 ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table) 00903 { 00904 uint32 i, off; 00905 00906 dir->tdir_tag = (uint16) tag; 00907 dir->tdir_type = (short) TIFF_SHORT; 00908 /* XXX -- yech, fool TIFFWriteData */ 00909 dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample); 00910 off = tif->tif_dataoff; 00911 for (i = 0; i < n; i++) 00912 if (!TIFFWriteData(tif, dir, (char *)table[i])) 00913 return (0); 00914 dir->tdir_count *= n; 00915 dir->tdir_offset = off; 00916 return (1); 00917 } 00918 00919 /* 00920 * Write/copy data associated with an ASCII or opaque tag value. 00921 */ 00922 static int 00923 TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp) 00924 { 00925 if (dir->tdir_count <= 4) { 00926 if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { 00927 dir->tdir_offset = (uint32)cp[0] << 24; 00928 if (dir->tdir_count >= 2) 00929 dir->tdir_offset |= (uint32)cp[1] << 16; 00930 if (dir->tdir_count >= 3) 00931 dir->tdir_offset |= (uint32)cp[2] << 8; 00932 if (dir->tdir_count == 4) 00933 dir->tdir_offset |= cp[3]; 00934 } else { 00935 dir->tdir_offset = cp[0]; 00936 if (dir->tdir_count >= 2) 00937 dir->tdir_offset |= (uint32) cp[1] << 8; 00938 if (dir->tdir_count >= 3) 00939 dir->tdir_offset |= (uint32) cp[2] << 16; 00940 if (dir->tdir_count == 4) 00941 dir->tdir_offset |= (uint32) cp[3] << 24; 00942 } 00943 return 1; 00944 } else 00945 return TIFFWriteData(tif, dir, cp); 00946 } 00947 00948 /* 00949 * Setup a directory entry of an array of SHORT 00950 * or SSHORT and write the associated indirect values. 00951 */ 00952 static int 00953 TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) 00954 { 00955 if (dir->tdir_count <= 2) { 00956 if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { 00957 dir->tdir_offset = (uint32) v[0] << 16; 00958 if (dir->tdir_count == 2) 00959 dir->tdir_offset |= v[1] & 0xffff; 00960 } else { 00961 dir->tdir_offset = v[0] & 0xffff; 00962 if (dir->tdir_count == 2) 00963 dir->tdir_offset |= (uint32) v[1] << 16; 00964 } 00965 return (1); 00966 } else 00967 return (TIFFWriteData(tif, dir, (char*) v)); 00968 } 00969 00970 /* 00971 * Setup a directory entry of an array of LONG 00972 * or SLONG and write the associated indirect values. 00973 */ 00974 static int 00975 TIFFWriteLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v) 00976 { 00977 if (dir->tdir_count == 1) { 00978 dir->tdir_offset = v[0]; 00979 return (1); 00980 } else 00981 return (TIFFWriteData(tif, dir, (char*) v)); 00982 } 00983 00984 /* 00985 * Setup a directory entry of an array of RATIONAL 00986 * or SRATIONAL and write the associated indirect values. 00987 */ 00988 static int 00989 TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v) 00990 { 00991 uint32 i; 00992 uint32* t; 00993 int status; 00994 00995 t = (uint32*) _TIFFmalloc(2 * dir->tdir_count * sizeof (uint32)); 00996 if (t == NULL) { 00997 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00998 "No space to write RATIONAL array"); 00999 return (0); 01000 } 01001 for (i = 0; i < dir->tdir_count; i++) { 01002 float fv = v[i]; 01003 int sign = 1; 01004 uint32 den; 01005 01006 if (fv < 0) { 01007 if (dir->tdir_type == TIFF_RATIONAL) { 01008 TIFFWarningExt(tif->tif_clientdata, 01009 tif->tif_name, 01010 "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL", 01011 _TIFFFieldWithTag(tif,dir->tdir_tag)->field_name, 01012 fv); 01013 fv = 0; 01014 } else 01015 fv = -fv, sign = -1; 01016 } 01017 den = 1L; 01018 if (fv > 0) { 01019 while (fv < 1L<<(31-3) && den < 1L<<(31-3)) 01020 fv *= 1<<3, den *= 1L<<3; 01021 } 01022 t[2*i+0] = (uint32) (sign * (fv + 0.5)); 01023 t[2*i+1] = den; 01024 } 01025 status = TIFFWriteData(tif, dir, (char *)t); 01026 _TIFFfree((char*) t); 01027 return (status); 01028 } 01029 01030 static int 01031 TIFFWriteFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v) 01032 { 01033 TIFFCvtNativeToIEEEFloat(tif, dir->tdir_count, v); 01034 if (dir->tdir_count == 1) { 01035 dir->tdir_offset = *(uint32*) &v[0]; 01036 return (1); 01037 } else 01038 return (TIFFWriteData(tif, dir, (char*) v)); 01039 } 01040 01041 static int 01042 TIFFWriteDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v) 01043 { 01044 TIFFCvtNativeToIEEEDouble(tif, dir->tdir_count, v); 01045 return (TIFFWriteData(tif, dir, (char*) v)); 01046 } 01047 01048 /* 01049 * Write an array of ``type'' values for a specified tag (i.e. this is a tag 01050 * which is allowed to have different types, e.g. SMaxSampleType). 01051 * Internally the data values are represented as double since a double can 01052 * hold any of the TIFF tag types (yes, this should really be an abstract 01053 * type tany_t for portability). The data is converted into the specified 01054 * type in a temporary buffer and then handed off to the appropriate array 01055 * writer. 01056 */ 01057 static int 01058 TIFFWriteAnyArray(TIFF* tif, 01059 TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) 01060 { 01061 char buf[10 * sizeof(double)]; 01062 char* w = buf; 01063 int i, status = 0; 01064 01065 if (n * TIFFDataWidth(type) > sizeof buf) { 01066 w = (char*) _TIFFmalloc(n * TIFFDataWidth(type)); 01067 if (w == NULL) { 01068 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 01069 "No space to write array"); 01070 return (0); 01071 } 01072 } 01073 01074 dir->tdir_tag = (uint16) tag; 01075 dir->tdir_type = (uint16) type; 01076 dir->tdir_count = n; 01077 01078 switch (type) { 01079 case TIFF_BYTE: 01080 { 01081 uint8* bp = (uint8*) w; 01082 for (i = 0; i < (int) n; i++) 01083 bp[i] = (uint8) v[i]; 01084 if (!TIFFWriteByteArray(tif, dir, (char*) bp)) 01085 goto out; 01086 } 01087 break; 01088 case TIFF_SBYTE: 01089 { 01090 int8* bp = (int8*) w; 01091 for (i = 0; i < (int) n; i++) 01092 bp[i] = (int8) v[i]; 01093 if (!TIFFWriteByteArray(tif, dir, (char*) bp)) 01094 goto out; 01095 } 01096 break; 01097 case TIFF_SHORT: 01098 { 01099 uint16* bp = (uint16*) w; 01100 for (i = 0; i < (int) n; i++) 01101 bp[i] = (uint16) v[i]; 01102 if (!TIFFWriteShortArray(tif, dir, (uint16*)bp)) 01103 goto out; 01104 } 01105 break; 01106 case TIFF_SSHORT: 01107 { 01108 int16* bp = (int16*) w; 01109 for (i = 0; i < (int) n; i++) 01110 bp[i] = (int16) v[i]; 01111 if (!TIFFWriteShortArray(tif, dir, (uint16*)bp)) 01112 goto out; 01113 } 01114 break; 01115 case TIFF_LONG: 01116 { 01117 uint32* bp = (uint32*) w; 01118 for (i = 0; i < (int) n; i++) 01119 bp[i] = (uint32) v[i]; 01120 if (!TIFFWriteLongArray(tif, dir, bp)) 01121 goto out; 01122 } 01123 break; 01124 case TIFF_SLONG: 01125 { 01126 int32* bp = (int32*) w; 01127 for (i = 0; i < (int) n; i++) 01128 bp[i] = (int32) v[i]; 01129 if (!TIFFWriteLongArray(tif, dir, (uint32*) bp)) 01130 goto out; 01131 } 01132 break; 01133 case TIFF_FLOAT: 01134 { 01135 float* bp = (float*) w; 01136 for (i = 0; i < (int) n; i++) 01137 bp[i] = (float) v[i]; 01138 if (!TIFFWriteFloatArray(tif, dir, bp)) 01139 goto out; 01140 } 01141 break; 01142 case TIFF_DOUBLE: 01143 { 01144 if( !TIFFWriteDoubleArray(tif, dir, v)) 01145 goto out; 01146 } 01147 break; 01148 default: 01149 /* TIFF_NOTYPE */ 01150 /* TIFF_ASCII */ 01151 /* TIFF_UNDEFINED */ 01152 /* TIFF_RATIONAL */ 01153 /* TIFF_SRATIONAL */ 01154 goto out; 01155 } 01156 status = 1; 01157 out: 01158 if (w != buf) 01159 _TIFFfree(w); 01160 return (status); 01161 } 01162 01163 static int 01164 TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir) 01165 { 01166 TIFFDirectory* td = &tif->tif_dir; 01167 tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16); 01168 uint16** tf = td->td_transferfunction; 01169 int ncols; 01170 01171 /* 01172 * Check if the table can be written as a single column, 01173 * or if it must be written as 3 columns. Note that we 01174 * write a 3-column tag if there are 2 samples/pixel and 01175 * a single column of data won't suffice--hmm. 01176 */ 01177 switch (td->td_samplesperpixel - td->td_extrasamples) { 01178 default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; } 01179 case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; } 01180 case 1: case 0: ncols = 1; 01181 } 01182 return (TIFFWriteShortTable(tif, 01183 TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf)); 01184 } 01185 01186 static int 01187 TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir) 01188 { 01189 TIFFDirectory* td = &tif->tif_dir; 01190 01191 dir->tdir_tag = TIFFTAG_INKNAMES; 01192 dir->tdir_type = (short) TIFF_ASCII; 01193 dir->tdir_count = td->td_inknameslen; 01194 return (TIFFWriteByteArray(tif, dir, td->td_inknames)); 01195 } 01196 01197 /* 01198 * Write a contiguous directory item. 01199 */ 01200 static int 01201 TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) 01202 { 01203 tsize_t cc; 01204 01205 if (tif->tif_flags & TIFF_SWAB) { 01206 switch (dir->tdir_type) { 01207 case TIFF_SHORT: 01208 case TIFF_SSHORT: 01209 TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); 01210 break; 01211 case TIFF_LONG: 01212 case TIFF_SLONG: 01213 case TIFF_FLOAT: 01214 TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); 01215 break; 01216 case TIFF_RATIONAL: 01217 case TIFF_SRATIONAL: 01218 TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); 01219 break; 01220 case TIFF_DOUBLE: 01221 TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); 01222 break; 01223 } 01224 } 01225 dir->tdir_offset = tif->tif_dataoff; 01226 cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type); 01227 if (SeekOK(tif, dir->tdir_offset) && 01228 WriteOK(tif, cp, cc)) { 01229 tif->tif_dataoff += (cc + 1) & ~1; 01230 return (1); 01231 } 01232 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 01233 "Error writing data for field \"%s\"", 01234 _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); 01235 return (0); 01236 } 01237 01238 /* 01239 * Similar to TIFFWriteDirectory(), but if the directory has already 01240 * been written once, it is relocated to the end of the file, in case it 01241 * has changed in size. Note that this will result in the loss of the 01242 * previously used directory space. 01243 */ 01244 01245 int 01246 TIFFRewriteDirectory( TIFF *tif ) 01247 { 01248 static const char module[] = "TIFFRewriteDirectory"; 01249 01250 /* We don't need to do anything special if it hasn't been written. */ 01251 if( tif->tif_diroff == 0 ) 01252 return TIFFWriteDirectory( tif ); 01253 01254 /* 01255 ** Find and zero the pointer to this directory, so that TIFFLinkDirectory 01256 ** will cause it to be added after this directories current pre-link. 01257 */ 01258 01259 /* Is it the first directory in the file? */ 01260 if (tif->tif_header.tiff_diroff == tif->tif_diroff) 01261 { 01262 tif->tif_header.tiff_diroff = 0; 01263 tif->tif_diroff = 0; 01264 01265 TIFFSeekFile(tif, (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE), 01266 SEEK_SET); 01267 if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), 01268 sizeof (tif->tif_diroff))) 01269 { 01270 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 01271 "Error updating TIFF header"); 01272 return (0); 01273 } 01274 } 01275 else 01276 { 01277 toff_t nextdir, off; 01278 01279 nextdir = tif->tif_header.tiff_diroff; 01280 do { 01281 uint16 dircount; 01282 01283 if (!SeekOK(tif, nextdir) || 01284 !ReadOK(tif, &dircount, sizeof (dircount))) { 01285 TIFFErrorExt(tif->tif_clientdata, module, 01286 "Error fetching directory count"); 01287 return (0); 01288 } 01289 if (tif->tif_flags & TIFF_SWAB) 01290 TIFFSwabShort(&dircount); 01291 (void) TIFFSeekFile(tif, 01292 dircount * sizeof (TIFFDirEntry), SEEK_CUR); 01293 if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { 01294 TIFFErrorExt(tif->tif_clientdata, module, 01295 "Error fetching directory link"); 01296 return (0); 01297 } 01298 if (tif->tif_flags & TIFF_SWAB) 01299 TIFFSwabLong(&nextdir); 01300 } while (nextdir != tif->tif_diroff && nextdir != 0); 01301 off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ 01302 (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET); 01303 tif->tif_diroff = 0; 01304 if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) { 01305 TIFFErrorExt(tif->tif_clientdata, module, 01306 "Error writing directory link"); 01307 return (0); 01308 } 01309 } 01310 01311 /* 01312 ** Now use TIFFWriteDirectory() normally. 01313 */ 01314 01315 return TIFFWriteDirectory( tif ); 01316 } 01317 01318 01319 /* 01320 * Link the current directory into the directory chain for the file. 01321 */ 01322 static int 01323 TIFFLinkDirectory(TIFF* tif) 01324 { 01325 static const char module[] = "TIFFLinkDirectory"; 01326 toff_t nextdir; 01327 toff_t diroff, off; 01328 01329 tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; 01330 diroff = tif->tif_diroff; 01331 if (tif->tif_flags & TIFF_SWAB) 01332 TIFFSwabLong(&diroff); 01333 01334 /* 01335 * Handle SubIFDs 01336 */ 01337 if (tif->tif_flags & TIFF_INSUBIFD) { 01338 (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); 01339 if (!WriteOK(tif, &diroff, sizeof (diroff))) { 01340 TIFFErrorExt(tif->tif_clientdata, module, 01341 "%s: Error writing SubIFD directory link", 01342 tif->tif_name); 01343 return (0); 01344 } 01345 /* 01346 * Advance to the next SubIFD or, if this is 01347 * the last one configured, revert back to the 01348 * normal directory linkage. 01349 */ 01350 if (--tif->tif_nsubifd) 01351 tif->tif_subifdoff += sizeof (diroff); 01352 else 01353 tif->tif_flags &= ~TIFF_INSUBIFD; 01354 return (1); 01355 } 01356 01357 if (tif->tif_header.tiff_diroff == 0) { 01358 /* 01359 * First directory, overwrite offset in header. 01360 */ 01361 tif->tif_header.tiff_diroff = tif->tif_diroff; 01362 (void) TIFFSeekFile(tif, 01363 (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE), 01364 SEEK_SET); 01365 if (!WriteOK(tif, &diroff, sizeof (diroff))) { 01366 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 01367 "Error writing TIFF header"); 01368 return (0); 01369 } 01370 return (1); 01371 } 01372 /* 01373 * Not the first directory, search to the last and append. 01374 */ 01375 nextdir = tif->tif_header.tiff_diroff; 01376 do { 01377 uint16 dircount; 01378 01379 if (!SeekOK(tif, nextdir) || 01380 !ReadOK(tif, &dircount, sizeof (dircount))) { 01381 TIFFErrorExt(tif->tif_clientdata, module, 01382 "Error fetching directory count"); 01383 return (0); 01384 } 01385 if (tif->tif_flags & TIFF_SWAB) 01386 TIFFSwabShort(&dircount); 01387 (void) TIFFSeekFile(tif, 01388 dircount * sizeof (TIFFDirEntry), SEEK_CUR); 01389 if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { 01390 TIFFErrorExt(tif->tif_clientdata, module, 01391 "Error fetching directory link"); 01392 return (0); 01393 } 01394 if (tif->tif_flags & TIFF_SWAB) 01395 TIFFSwabLong(&nextdir); 01396 } while (nextdir != 0); 01397 off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ 01398 (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET); 01399 if (!WriteOK(tif, &diroff, sizeof (diroff))) { 01400 TIFFErrorExt(tif->tif_clientdata, module, 01401 "Error writing directory link"); 01402 return (0); 01403 } 01404 return (1); 01405 } 01406 01407 /* vim: set ts=8 sts=8 sw=8 noet: */ 01408 /* 01409 * Local Variables: 01410 * mode: c 01411 * c-basic-offset: 8 01412 * fill-column: 78 01413 * End: 01414 */ Generated on Fri May 25 2012 04:17:41 for ReactOS by
1.7.6.1
|