Merge pull request #1518 from dg0yt/static-windows
[openjpeg.git] / thirdparty / libtiff / tif_getimage.c
index 6a09b4d254f9c1a3301d6cf1a468d8e753e9de37..f49b73fd474fca270d18e20ab0b5806b0a6ebc47 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: tif_getimage.c,v 1.78 2011-02-23 21:46:09 fwarmerdam Exp $ */
+/* $Id: tif_getimage.c,v 1.90 2015-06-17 01:34:08 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -182,8 +182,23 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
                                    "Planarconfiguration", td->td_planarconfig);
                                return (0);
                        }
+                       if( td->td_samplesperpixel != 3 )
+            {
+                sprintf(emsg,
+                        "Sorry, can not handle image with %s=%d",
+                        "Samples/pixel", td->td_samplesperpixel);
+                return 0;
+            }
                        break;
                case PHOTOMETRIC_CIELAB:
+            if( td->td_samplesperpixel != 3 || td->td_bitspersample != 8 )
+            {
+                sprintf(emsg,
+                        "Sorry, can not handle image with %s=%d and %s=%d",
+                        "Samples/pixel", td->td_samplesperpixel,
+                        "Bits/sample", td->td_bitspersample);
+                return 0;
+            }
                        break;
                default:
                        sprintf(emsg, "Sorry, can not handle image with %s=%d",
@@ -597,6 +612,10 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
     int32 fromskew, toskew;
     uint32 nrow;
     int ret = 1, flip;
+    uint32 this_tw, tocol;
+    int32 this_toskew, leftmost_toskew;
+    int32 leftmost_fromskew;
+    uint32 leftmost_tw;
 
     buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif));
     if (buf == 0) {
@@ -617,37 +636,50 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
            toskew = -(int32)(tw - w);
     }
      
+    /*
+     * Leftmost tile is clipped on left side if col_offset > 0.
+     */
+    leftmost_fromskew = img->col_offset % tw;
+    leftmost_tw = tw - leftmost_fromskew;
+    leftmost_toskew = toskew + leftmost_fromskew;
     for (row = 0; row < h; row += nrow)
     {
         rowstoread = th - (row + img->row_offset) % th;
        nrow = (row + rowstoread > h ? h - row : rowstoread);
-       for (col = 0; col < w; col += tw) 
+       fromskew = leftmost_fromskew;
+       this_tw = leftmost_tw;
+       this_toskew = leftmost_toskew;
+       tocol = 0;
+       col = img->col_offset;
+       while (tocol < w)
         {
-           if (TIFFReadTile(tif, buf, col+img->col_offset,  
+           if (TIFFReadTile(tif, buf, col,  
                             row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr)
             {
                 ret = 0;
                 break;
             }
-           
-           pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);  
-
-           if (col + tw > w) 
-            {
-                /*
-                 * Tile is clipped horizontally.  Calculate
-                 * visible portion and skewing factors.
-                 */
-                uint32 npix = w - col;
-                fromskew = tw - npix;
-                (*put)(img, raster+y*w+col, col, y,
-                       npix, nrow, fromskew, toskew + fromskew, buf + pos);
-            }
-            else 
-            {
-                (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos);
-            }
-        }
+            pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \
+                  ((tmsize_t) fromskew * img->samplesperpixel);
+           if (tocol + this_tw > w) 
+           {
+               /*
+                * Rightmost tile is clipped on right side.
+                */
+               fromskew = tw - (w - tocol);
+               this_tw = tw - fromskew;
+               this_toskew = toskew + fromskew;
+           }
+           (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos);
+           tocol += this_tw;
+           col += this_tw;
+           /*
+            * After the leftmost tile, tiles are no longer clipped on left side.
+            */
+           fromskew = 0;
+           this_tw = tw;
+           this_toskew = toskew;
+       }
 
         y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
     }
@@ -692,19 +724,29 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        unsigned char* p2;
        unsigned char* pa;
        tmsize_t tilesize;
+       tmsize_t bufsize;
        int32 fromskew, toskew;
        int alpha = img->alpha;
        uint32 nrow;
        int ret = 1, flip;
         int colorchannels;
+       uint32 this_tw, tocol;
+       int32 this_toskew, leftmost_toskew;
+       int32 leftmost_fromskew;
+       uint32 leftmost_tw;
 
        tilesize = TIFFTileSize(tif);  
-       buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize);
+       bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize);
+       if (bufsize == 0) {
+               TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate");
+               return (0);
+       }
+       buf = (unsigned char*) _TIFFmalloc(bufsize);
        if (buf == 0) {
                TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer");
                return (0);
        }
-       _TIFFmemset(buf, 0, (alpha?4:3)*tilesize);
+       _TIFFmemset(buf, 0, bufsize);
        p0 = buf;
        p1 = p0 + tilesize;
        p2 = p1 + tilesize;
@@ -736,20 +778,31 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
             break;
         }
 
+       /*
+        *      Leftmost tile is clipped on left side if col_offset > 0.
+        */
+       leftmost_fromskew = img->col_offset % tw;
+       leftmost_tw = tw - leftmost_fromskew;
+       leftmost_toskew = toskew + leftmost_fromskew;
        for (row = 0; row < h; row += nrow)
        {
                rowstoread = th - (row + img->row_offset) % th;
                nrow = (row + rowstoread > h ? h - row : rowstoread);
-               for (col = 0; col < w; col += tw)
+               fromskew = leftmost_fromskew;
+               this_tw = leftmost_tw;
+               this_toskew = leftmost_toskew;
+               tocol = 0;
+               col = img->col_offset;
+               while (tocol < w)
                {
-                       if (TIFFReadTile(tif, p0, col+img->col_offset,  
+                       if (TIFFReadTile(tif, p0, col,  
                            row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr)
                        {
                                ret = 0;
                                break;
                        }
                        if (colorchannels > 1 
-                            && TIFFReadTile(tif, p1, col+img->col_offset,  
+                            && TIFFReadTile(tif, p1, col,  
                                             row+img->row_offset,0,1) == (tmsize_t)(-1) 
                             && img->stoponerr)
                        {
@@ -757,7 +810,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                                break;
                        }
                        if (colorchannels > 1 
-                            && TIFFReadTile(tif, p2, col+img->col_offset,  
+                            && TIFFReadTile(tif, p2, col,  
                                             row+img->row_offset,0,2) == (tmsize_t)(-1) 
                             && img->stoponerr)
                        {
@@ -765,7 +818,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                                break;
                        }
                        if (alpha
-                            && TIFFReadTile(tif,pa,col+img->col_offset,  
+                            && TIFFReadTile(tif,pa,col,  
                                             row+img->row_offset,0,colorchannels) == (tmsize_t)(-1) 
                             && img->stoponerr)
                         {
@@ -773,23 +826,27 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                             break;
                        }
 
-                       pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);  
-
-                       if (col + tw > w)
+                       pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \
+                          ((tmsize_t) fromskew * img->samplesperpixel);
+                       if (tocol + this_tw > w) 
                        {
                                /*
-                                * Tile is clipped horizontally.  Calculate
-                                * visible portion and skewing factors.
+                                * Rightmost tile is clipped on right side.
                                 */
-                               uint32 npix = w - col;
-                               fromskew = tw - npix;
-                               (*put)(img, raster+y*w+col, col, y,
-                                   npix, nrow, fromskew, toskew + fromskew,
-                                   p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
-                       } else {
-                               (*put)(img, raster+y*w+col, col, y,
-                                   tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
+                               fromskew = tw - (w - tocol);
+                               this_tw = tw - fromskew;
+                               this_toskew = toskew + fromskew;
                        }
+                       (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, \
+                               p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
+                       tocol += this_tw;
+                       col += this_tw;
+                       /*
+                       * After the leftmost tile, tiles are no longer clipped on left side.
+                       */
+                       fromskew = 0;
+                       this_tw = tw;
+                       this_toskew = toskew;
                }
 
                y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow);
@@ -836,6 +893,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        int32 fromskew, toskew;
        int ret = 1, flip;
 
+       TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver);
+       if( subsamplingver == 0 ) {
+               TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Invalid vertical YCbCr subsampling");
+               return (0);
+       }
+
        buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif));
        if (buf == 0) {
                TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
@@ -853,7 +916,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        }
 
        TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
-       TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver);
+
        scanline = TIFFScanlineSize(tif);
        fromskew = (w < imagewidth ? imagewidth - w : 0);
        for (row = 0; row < h; row += nrow)
@@ -873,7 +936,8 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                        break;
                }
 
-               pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+               pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
+                       ((tmsize_t) img->col_offset * img->samplesperpixel);
                (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
                y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
        }
@@ -917,17 +981,23 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        uint32 rowsperstrip, offset_row;
        uint32 imagewidth = img->width;
        tmsize_t stripsize;
+       tmsize_t bufsize;
        int32 fromskew, toskew;
        int alpha = img->alpha;
        int ret = 1, flip, colorchannels;
 
        stripsize = TIFFStripSize(tif);  
-       p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize);
+       bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize);
+       if (bufsize == 0) {
+               TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate");
+               return (0);
+       }
+       p0 = buf = (unsigned char *)_TIFFmalloc(bufsize);
        if (buf == 0) {
                TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
                return (0);
        }
-       _TIFFmemset(buf, 0, (alpha?4:3)*stripsize);
+       _TIFFmemset(buf, 0, bufsize);
        p1 = p0 + stripsize;
        p2 = p1 + stripsize;
        pa = (alpha?(p2+stripsize):NULL);
@@ -998,7 +1068,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                        }
                }
 
-               pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+               pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
+                       ((tmsize_t) img->col_offset * img->samplesperpixel);
                (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos,
                    p2 + pos, (alpha?(pa+pos):NULL));
                y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
@@ -1196,6 +1267,26 @@ DECLAREContigPutFunc(putgreytile)
     }
 }
 
+/*
+ * 8-bit greyscale with associated alpha => colormap/RGBA
+ */
+DECLAREContigPutFunc(putagreytile)
+{
+    int samplesperpixel = img->samplesperpixel;
+    uint32** BWmap = img->BWmap;
+
+    (void) y;
+    while (h-- > 0) {
+       for (x = w; x-- > 0;)
+        {
+            *cp++ = BWmap[*pp][0] & (*(pp+1) << 24 | ~A1);
+            pp += samplesperpixel;
+        }
+       cp += toskew;
+       pp += fromskew;
+    }
+}
+
 /*
  * 16-bit greyscale => colormap/RGB
  */
@@ -1494,6 +1585,26 @@ DECLARESepPutFunc(putRGBAAseparate8bittile)
        }
 }
 
+/*
+ * 8-bit unpacked CMYK samples => RGBA
+ */
+DECLARESepPutFunc(putCMYKseparate8bittile)
+{
+       (void) img; (void) y;
+       while (h-- > 0) {
+               uint32 rv, gv, bv, kv;
+               for (x = w; x-- > 0;) {
+                       kv = 255 - *a++;
+                       rv = (kv*(255-*r++))/255;
+                       gv = (kv*(255-*g++))/255;
+                       bv = (kv*(255-*b++))/255;
+                       *cp++ = PACK4(rv,gv,bv,255);
+               }
+               SKEW4(r, g, b, a, fromskew);
+               cp += toskew;
+       }
+}
+
 /*
  * 8-bit unpacked samples => RGBA w/ unassociated alpha
  */
@@ -1800,7 +1911,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
 
     (void) y;
     fromskew = (fromskew * 10) / 4;
-    if ((h & 3) == 0 && (w & 1) == 0) {
+    if ((w & 3) == 0 && (h & 1) == 0) {
         for (; h >= 2; h -= 2) {
             x = w>>2;
             do {
@@ -1877,7 +1988,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
     /* XXX adjust fromskew */
     do {
        x = w>>2;
-       do {
+       while(x>0) {
            int32 Cb = pp[4];
            int32 Cr = pp[5];
 
@@ -1888,7 +1999,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
 
            cp += 4;
            pp += 6;
-       } while (--x);
+               x--;
+       }
 
         if( (w&3) != 0 )
         {
@@ -1979,7 +2091,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
        fromskew = (fromskew * 4) / 2;
        do {
                x = w>>1;
-               do {
+               while(x>0) {
                        int32 Cb = pp[2];
                        int32 Cr = pp[3];
 
@@ -1988,7 +2100,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
 
                        cp += 2;
                        pp += 4;
-               } while (--x);
+                       x --;
+               }
 
                if( (w&1) != 0 )
                {
@@ -2461,7 +2574,10 @@ PickContigCase(TIFFRGBAImage* img)
                                                img->put.contig = put16bitbwtile;
                                                break;
                                        case 8:
-                                               img->put.contig = putgreytile;
+                                               if (img->alpha && img->samplesperpixel == 2)
+                                                       img->put.contig = putagreytile;
+                                               else
+                                                       img->put.contig = putgreytile;
                                                break;
                                        case 4:
                                                img->put.contig = put4bitbwtile;
@@ -2486,7 +2602,7 @@ PickContigCase(TIFFRGBAImage* img)
                                         * must always be <= horizontal subsampling; so
                                         * there are only a few possibilities and we just
                                         * enumerate the cases.
-                                        * Joris: added support for the [1,2] case, nonetheless, to accomodate
+                                        * Joris: added support for the [1,2] case, nonetheless, to accommodate
                                         * some OJPEG files
                                         */
                                        uint16 SubsamplingHor;
@@ -2540,58 +2656,65 @@ PickSeparateCase(TIFFRGBAImage* img)
        img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
        img->put.separate = NULL;
        switch (img->photometric) {
-               case PHOTOMETRIC_MINISWHITE:
-               case PHOTOMETRIC_MINISBLACK:
-                  /* greyscale images processed pretty much as RGB by gtTileSeparate */
-               case PHOTOMETRIC_RGB:
-                       switch (img->bitspersample) {
-                               case 8:
-                                       if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
-                                               img->put.separate = putRGBAAseparate8bittile;
-                                       else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
-                                       {
-                                               if (BuildMapUaToAa(img))
-                                                       img->put.separate = putRGBUAseparate8bittile;
-                                       }
-                                       else
-                                               img->put.separate = putRGBseparate8bittile;
-                                       break;
-                               case 16:
-                                       if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
-                                       {
-                                               if (BuildMapBitdepth16To8(img))
-                                                       img->put.separate = putRGBAAseparate16bittile;
-                                       }
-                                       else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
-                                       {
-                                               if (BuildMapBitdepth16To8(img) &&
-                                                   BuildMapUaToAa(img))
-                                                       img->put.separate = putRGBUAseparate16bittile;
-                                       }
-                                       else
-                                       {
-                                               if (BuildMapBitdepth16To8(img))
-                                                       img->put.separate = putRGBseparate16bittile;
-                                       }
-                                       break;
+       case PHOTOMETRIC_MINISWHITE:
+       case PHOTOMETRIC_MINISBLACK:
+               /* greyscale images processed pretty much as RGB by gtTileSeparate */
+       case PHOTOMETRIC_RGB:
+               switch (img->bitspersample) {
+               case 8:
+                       if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+                               img->put.separate = putRGBAAseparate8bittile;
+                       else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+                       {
+                               if (BuildMapUaToAa(img))
+                                       img->put.separate = putRGBUAseparate8bittile;
                        }
+                       else
+                               img->put.separate = putRGBseparate8bittile;
                        break;
-               case PHOTOMETRIC_YCBCR:
-                       if ((img->bitspersample==8) && (img->samplesperpixel==3))
+               case 16:
+                       if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
                        {
-                               if (initYCbCrConversion(img)!=0)
-                               {
-                                       uint16 hs, vs;
-                                       TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
-                                       switch ((hs<<4)|vs) {
-                                               case 0x11:
-                                                       img->put.separate = putseparate8bitYCbCr11tile;
-                                                       break;
-                                               /* TODO: add other cases here */
-                                       }
-                               }
+                               if (BuildMapBitdepth16To8(img))
+                                       img->put.separate = putRGBAAseparate16bittile;
+                       }
+                       else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+                       {
+                               if (BuildMapBitdepth16To8(img) &&
+                                   BuildMapUaToAa(img))
+                                       img->put.separate = putRGBUAseparate16bittile;
+                       }
+                       else
+                       {
+                               if (BuildMapBitdepth16To8(img))
+                                       img->put.separate = putRGBseparate16bittile;
                        }
                        break;
+               }
+               break;
+       case PHOTOMETRIC_SEPARATED:
+               if (img->bitspersample == 8 && img->samplesperpixel == 4)
+               {
+                       img->alpha = 1; // Not alpha, but seems like the only way to get 4th band
+                       img->put.separate = putCMYKseparate8bittile;
+               }
+               break;
+       case PHOTOMETRIC_YCBCR:
+               if ((img->bitspersample==8) && (img->samplesperpixel==3))
+               {
+                       if (initYCbCrConversion(img)!=0)
+                       {
+                               uint16 hs, vs;
+                               TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
+                               switch ((hs<<4)|vs) {
+                               case 0x11:
+                                       img->put.separate = putseparate8bitYCbCr11tile;
+                                       break;
+                                       /* TODO: add other cases here */
+                               }
+                       }
+               }
+               break;
        }
        return ((img->get!=NULL) && (img->put.separate!=NULL));
 }