]> git.saurik.com Git - wxWidgets.git/blobdiff - src/tiff/libtiff/tif_strip.c
Reflect changes in stc.cpp in stc.cpp.in from which it's generated.
[wxWidgets.git] / src / tiff / libtiff / tif_strip.c
index cc3bc3595e7cf27ae91fcec1eddce1ac24e6edaf..360a8d90790a8ed9240dc0eb010931632182f2d2 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id$ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
  */
 #include "tiffiop.h"
 
-static uint32
-summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where)
-{
-       /*
-        * XXX: We are using casting to uint32 here, bacause sizeof(size_t)
-        * may be larger than sizeof(uint32) on 64-bit architectures.
-        */
-       uint32  bytes = summand1 + summand2;
-
-       if (bytes - summand1 != summand2) {
-               TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where);
-               bytes = 0;
-       }
-
-       return (bytes);
-}
-
-static uint32
-multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where)
-{
-       uint32  bytes = nmemb * elem_size;
-
-       if (elem_size && bytes / elem_size != nmemb) {
-               TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where);
-               bytes = 0;
-       }
-
-       return (bytes);
-}
-
 /*
  * Compute which strip a (row,sample) value is in.
  */
-tstrip_t
-TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample)
+uint32
+TIFFComputeStrip(TIFF* tif, uint32 row, uint16 sample)
 {
+       static const char module[] = "TIFFComputeStrip";
        TIFFDirectory *td = &tif->tif_dir;
-       tstrip_t strip;
+       uint32 strip;
 
        strip = row / td->td_rowsperstrip;
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
                if (sample >= td->td_samplesperpixel) {
-                       TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+                       TIFFErrorExt(tif->tif_clientdata, module,
                            "%lu: Sample out of range, max %lu",
                            (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
-                       return ((tstrip_t) 0);
+                       return (0);
                }
-               strip += sample*td->td_stripsperimage;
+               strip += (uint32)sample*td->td_stripsperimage;
        }
        return (strip);
 }
@@ -86,33 +56,34 @@ TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample)
 /*
  * Compute how many strips are in an image.
  */
-tstrip_t
+uint32
 TIFFNumberOfStrips(TIFF* tif)
 {
        TIFFDirectory *td = &tif->tif_dir;
-       tstrip_t nstrips;
+       uint32 nstrips;
 
        nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 :
-            TIFFhowmany(td->td_imagelength, td->td_rowsperstrip));
+            TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip));
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
-               nstrips = multiply(tif, nstrips, td->td_samplesperpixel,
-                                  "TIFFNumberOfStrips");
+               nstrips = _TIFFMultiply32(tif, nstrips, (uint32)td->td_samplesperpixel,
+                   "TIFFNumberOfStrips");
        return (nstrips);
 }
 
 /*
  * Compute the # bytes in a variable height, row-aligned strip.
  */
-tsize_t
-TIFFVStripSize(TIFF* tif, uint32 nrows)
+uint64
+TIFFVStripSize64(TIFF* tif, uint32 nrows)
 {
+       static const char module[] = "TIFFVStripSize64";
        TIFFDirectory *td = &tif->tif_dir;
-
-       if (nrows == (uint32) -1)
-               nrows = td->td_imagelength;
-       if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
-           td->td_photometric == PHOTOMETRIC_YCBCR &&
-           !isUpSampled(tif)) {
+       if (nrows==(uint32)(-1))
+               nrows=td->td_imagelength;
+       if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&&
+           (td->td_photometric == PHOTOMETRIC_YCBCR)&&
+           (!isUpSampled(tif)))
+       {
                /*
                 * Packed YCbCr data contain one Cb+Cr for every
                 * HorizontalSampling*VerticalSampling Y values.
@@ -121,54 +92,103 @@ TIFFVStripSize(TIFF* tif, uint32 nrows)
                 * horizontal/vertical subsampling area include
                 * YCbCr data for the extended image.
                 */
-                uint16 ycbcrsubsampling[2];
-                tsize_t w, scanline, samplingarea;
-
-                TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, 
-                              ycbcrsubsampling + 0, 
-                              ycbcrsubsampling + 1 );
-
-               samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1];
-               if (samplingarea == 0) {
-                       TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
-                                    "Invalid YCbCr subsampling");
+               uint16 ycbcrsubsampling[2];
+               uint16 samplingblock_samples;
+               uint32 samplingblocks_hor;
+               uint32 samplingblocks_ver;
+               uint64 samplingrow_samples;
+               uint64 samplingrow_size;
+               if(td->td_samplesperpixel!=3)
+               {
+                       TIFFErrorExt(tif->tif_clientdata,module,
+                           "Invalid td_samplesperpixel value");
                        return 0;
                }
-
-               w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]);
-               scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
-                                                "TIFFVStripSize"));
-               nrows = TIFFroundup(nrows, ycbcrsubsampling[1]);
-               /* NB: don't need TIFFhowmany here 'cuz everything is rounded */
-               scanline = multiply(tif, nrows, scanline, "TIFFVStripSize");
-               return ((tsize_t)
-                   summarize(tif, scanline,
-                             multiply(tif, 2, scanline / samplingarea,
-                                      "TIFFVStripSize"), "TIFFVStripSize"));
-       } else
-               return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif),
-                                          "TIFFVStripSize"));
+               TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0,
+                   ycbcrsubsampling+1);
+               if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4)
+                   ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4))
+               {
+                       TIFFErrorExt(tif->tif_clientdata,module,
+                                    "Invalid YCbCr subsampling (%dx%d)", 
+                                    ycbcrsubsampling[0], 
+                                    ycbcrsubsampling[1] );
+                       return 0;
+               }
+               samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2;
+               samplingblocks_hor=TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]);
+               samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]);
+               samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module);
+               samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module));
+               return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module));
+       }
+       else
+               return(_TIFFMultiply64(tif,nrows,TIFFScanlineSize64(tif),module));
+}
+tmsize_t
+TIFFVStripSize(TIFF* tif, uint32 nrows)
+{
+       static const char module[] = "TIFFVStripSize";
+       uint64 m;
+       tmsize_t n;
+       m=TIFFVStripSize64(tif,nrows);
+       n=(tmsize_t)m;
+       if ((uint64)n!=m)
+       {
+               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
+               n=0;
+       }
+       return(n);
 }
-
 
 /*
  * Compute the # bytes in a raw strip.
  */
-tsize_t
-TIFFRawStripSize(TIFF* tif, tstrip_t strip)
+uint64
+TIFFRawStripSize64(TIFF* tif, uint32 strip)
 {
+       static const char module[] = "TIFFRawStripSize64";
        TIFFDirectory* td = &tif->tif_dir;
-       tsize_t bytecount = td->td_stripbytecount[strip];
+       uint64 bytecount = td->td_stripbytecount[strip];
 
-       if (bytecount <= 0) {
-               TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
-                         "%lu: Invalid strip byte count, strip %lu",
-                         (unsigned long) bytecount, (unsigned long) strip);
-               bytecount = (tsize_t) -1;
+       if (bytecount == 0)
+       {
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
+               TIFFErrorExt(tif->tif_clientdata, module,
+                            "%I64u: Invalid strip byte count, strip %lu",
+                            (unsigned __int64) bytecount,
+                            (unsigned long) strip);
+#else
+               TIFFErrorExt(tif->tif_clientdata, module,
+                            "%llu: Invalid strip byte count, strip %lu",
+                            (unsigned long long) bytecount,
+                            (unsigned long) strip);
+#endif
+               bytecount = (uint64) -1;
        }
 
        return bytecount;
 }
+tmsize_t
+TIFFRawStripSize(TIFF* tif, uint32 strip)
+{
+       static const char module[] = "TIFFRawStripSize";
+       uint64 m;
+       tmsize_t n;
+       m=TIFFRawStripSize64(tif,strip);
+       if (m==(uint64)(-1))
+               n=(tmsize_t)(-1);
+       else
+       {
+               n=(tmsize_t)m;
+               if ((uint64)n!=m)
+               {
+                       TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
+                       n=0;
+               }
+       }
+       return(n);
+}
 
 /*
  * Compute the # bytes in a (row-aligned) strip.
@@ -178,14 +198,29 @@ TIFFRawStripSize(TIFF* tif, tstrip_t strip)
  * truncated to reflect the actual space required
  * to hold the strip.
  */
-tsize_t
-TIFFStripSize(TIFF* tif)
+uint64
+TIFFStripSize64(TIFF* tif)
 {
        TIFFDirectory* td = &tif->tif_dir;
        uint32 rps = td->td_rowsperstrip;
        if (rps > td->td_imagelength)
                rps = td->td_imagelength;
-       return (TIFFVStripSize(tif, rps));
+       return (TIFFVStripSize64(tif, rps));
+}
+tmsize_t
+TIFFStripSize(TIFF* tif)
+{
+       static const char module[] = "TIFFStripSize";
+       uint64 m;
+       tmsize_t n;
+       m=TIFFStripSize64(tif);
+       n=(tmsize_t)m;
+       if ((uint64)n!=m)
+       {
+               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
+               n=0;
+       }
+       return(n);
 }
 
 /*
@@ -209,10 +244,17 @@ _TIFFDefaultStripSize(TIFF* tif, uint32 s)
                 * image up into strips that are approximately
                 * STRIP_SIZE_DEFAULT bytes long.
                 */
-               tsize_t scanline = TIFFScanlineSize(tif);
-               s = (uint32)STRIP_SIZE_DEFAULT / (scanline == 0 ? 1 : scanline);
-               if (s == 0)             /* very wide images */
-                       s = 1;
+               uint64 scanlinesize;
+               uint64 rows;
+               scanlinesize=TIFFScanlineSize64(tif);
+               if (scanlinesize==0)
+                       scanlinesize=1;
+               rows=(uint64)STRIP_SIZE_DEFAULT/scanlinesize;
+               if (rows==0)
+                       rows=1;
+               else if (rows>0xFFFFFFFF)
+                       rows=0xFFFFFFFF;
+               s=(uint32)rows;
        }
        return (s);
 }
@@ -222,49 +264,75 @@ _TIFFDefaultStripSize(TIFF* tif, uint32 s)
  * one of the scanline-oriented i/o routines.  Note that
  * this number may be 1/samples-per-pixel if data is
  * stored as separate planes.
+ * The ScanlineSize in case of YCbCrSubsampling is defined as the
+ * strip size divided by the strip height, i.e. the size of a pack of vertical
+ * subsampling lines divided by vertical subsampling. It should thus make
+ * sense when multiplied by a multiple of vertical subsampling.
  */
-tsize_t
-TIFFScanlineSize(TIFF* tif)
+uint64
+TIFFScanlineSize64(TIFF* tif)
 {
+       static const char module[] = "TIFFScanlineSize64";
        TIFFDirectory *td = &tif->tif_dir;
-       tsize_t scanline;
-       
-       if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
-               if (td->td_photometric == PHOTOMETRIC_YCBCR
-                   && !isUpSampled(tif)) {
+       uint64 scanline_size;
+       if (td->td_planarconfig==PLANARCONFIG_CONTIG)
+       {
+               if ((td->td_photometric==PHOTOMETRIC_YCBCR)&&
+                   (td->td_samplesperpixel==3)&&
+                   (!isUpSampled(tif)))
+               {
                        uint16 ycbcrsubsampling[2];
-
-                       TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, 
-                                    ycbcrsubsampling + 0,
-                                    ycbcrsubsampling + 1);
-
-                       if (ycbcrsubsampling[0] == 0) {
-                               TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
-                                            "Invalid YCbCr subsampling");
-                               return 0;
+                       uint16 samplingblock_samples;
+                       uint32 samplingblocks_hor;
+                       uint64 samplingrow_samples;
+                       uint64 samplingrow_size;
+                       if(td->td_samplesperpixel!=3)
+                       {
+                            TIFFErrorExt(tif->tif_clientdata,module,
+                                         "Invalid td_samplesperpixel value");
+                            return 0;
                        }
-
-                       scanline = TIFFroundup(td->td_imagewidth,
-                                              ycbcrsubsampling[0]);
-                       scanline = TIFFhowmany8(multiply(tif, scanline,
-                                                        td->td_bitspersample,
-                                                        "TIFFScanlineSize"));
-                       return ((tsize_t)
-                               summarize(tif, scanline,
-                                         multiply(tif, 2,
-                                               scanline / ycbcrsubsampling[0],
-                                               "TIFFVStripSize"),
-                                         "TIFFVStripSize"));
-               } else {
-                       scanline = multiply(tif, td->td_imagewidth,
-                                           td->td_samplesperpixel,
-                                           "TIFFScanlineSize");
+                       TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,
+                                              ycbcrsubsampling+0,
+                                              ycbcrsubsampling+1);
+                       if (((ycbcrsubsampling[0]!=1)&&(ycbcrsubsampling[0]!=2)&&(ycbcrsubsampling[0]!=4)) ||
+                           ((ycbcrsubsampling[1]!=1)&&(ycbcrsubsampling[1]!=2)&&(ycbcrsubsampling[1]!=4)))
+                       {
+                            TIFFErrorExt(tif->tif_clientdata,module,
+                                         "Invalid YCbCr subsampling");
+                            return 0;
+                       }
+                       samplingblock_samples = ycbcrsubsampling[0]*ycbcrsubsampling[1]+2;
+                       samplingblocks_hor = TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]);
+                       samplingrow_samples = _TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module);
+                       samplingrow_size = TIFFhowmany_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module),8);
+                       scanline_size = (samplingrow_size/ycbcrsubsampling[1]);
                }
-       } else
-               scanline = td->td_imagewidth;
-       return ((tsize_t) TIFFhowmany8(multiply(tif, scanline,
-                                               td->td_bitspersample,
-                                               "TIFFScanlineSize")));
+               else
+               {
+                       uint64 scanline_samples;
+                       scanline_samples=_TIFFMultiply64(tif,td->td_imagewidth,td->td_samplesperpixel,module);
+                       scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,scanline_samples,td->td_bitspersample,module),8);
+               }
+       }
+       else
+               scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewidth,td->td_bitspersample,module),8);
+       return(scanline_size);
+}
+tmsize_t
+TIFFScanlineSize(TIFF* tif)
+{
+       static const char module[] = "TIFFScanlineSize";
+       uint64 m;
+       tmsize_t n;
+       m=TIFFScanlineSize64(tif);
+       n=(tmsize_t)m;
+       if ((uint64)n!=m)
+       {
+               TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
+               n=0;
+       }
+       return(n);
 }
 
 /*
@@ -273,22 +341,42 @@ TIFFScanlineSize(TIFF* tif)
  * I/O size returned by TIFFScanlineSize which may be less
  * if data is store as separate planes).
  */
-tsize_t
-TIFFRasterScanlineSize(TIFF* tif)
+uint64
+TIFFRasterScanlineSize64(TIFF* tif)
 {
+       static const char module[] = "TIFFRasterScanlineSize64";
        TIFFDirectory *td = &tif->tif_dir;
-       tsize_t scanline;
-       
-       scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
-                            "TIFFRasterScanlineSize");
+       uint64 scanline;
+
+       scanline = _TIFFMultiply64(tif, td->td_bitspersample, td->td_imagewidth, module);
        if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
-               scanline = multiply (tif, scanline, td->td_samplesperpixel,
-                                    "TIFFRasterScanlineSize");
-               return ((tsize_t) TIFFhowmany8(scanline));
+               scanline = _TIFFMultiply64(tif, scanline, td->td_samplesperpixel, module);
+               return (TIFFhowmany8_64(scanline));
        } else
-               return ((tsize_t) multiply (tif, TIFFhowmany8(scanline),
-                                           td->td_samplesperpixel,
-                                           "TIFFRasterScanlineSize"));
+               return (_TIFFMultiply64(tif, TIFFhowmany8_64(scanline),
+                   td->td_samplesperpixel, module));
+}
+tmsize_t
+TIFFRasterScanlineSize(TIFF* tif)
+{
+       static const char module[] = "TIFFRasterScanlineSize";
+       uint64 m;
+       tmsize_t n;
+       m=TIFFRasterScanlineSize64(tif);
+       n=(tmsize_t)m;
+       if ((uint64)n!=m)
+       {
+               TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
+               n=0;
+       }
+       return(n);
 }
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */