ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tif_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.