]> granicus.if.org Git - libjpeg-turbo/commitdiff
When decompressing to a 4-byte RGB buffer, set the unused byte to 0xFF so it can...
authorDRC <dcommander@users.sourceforge.net>
Thu, 8 Sep 2011 23:54:40 +0000 (23:54 +0000)
committerDRC <dcommander@users.sourceforge.net>
Thu, 8 Sep 2011 23:54:40 +0000 (23:54 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@699 632fc199-4ca6-4c93-a231-07263d6284db

ChangeLog.txt
java/TJUnitTest.java
java/org/libjpegturbo/turbojpeg/TJCompressor.java
java/org/libjpegturbo/turbojpeg/TJDecompressor.java
jdcolext.c
simd/jsimdcfg.inc.h
tjunittest.c

index b202309268eeac670c4a33476760e70f18ad79ee..e5dd127a12323e53417f3516850162cb835daeb7 100644 (file)
@@ -60,6 +60,11 @@ worst-case JPEG size based on the level of chrominance subsampling.
 [16] Fixed 32-bit supplementary package for amd64 Debian systems which was
 broken by enhancements to the packaging system in 1.1.
 
+[17] When decompressing a JPEG image using an output colorspace of
+JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, or JCS_EXT_XRGB, libjpeg-turbo will
+now set the unused byte to 0xFF, which allows applications to interpret that
+byte as an alpha channel (0xFF = opaque).
+
 
 1.1.1
 =====
index 37e08312f0a2f61e14fb96e39b2fc54b0ba6706e..b732930ae197150730132faaa5aa2107769f3a5c 100644 (file)
@@ -34,6 +34,7 @@ import java.io.*;
 import java.util.*;
 import java.awt.image.*;
 import javax.imageio.*;
+import java.nio.*;
 import org.libjpegturbo.turbojpeg.*;
 
 public class TJUnitTest {
@@ -59,26 +60,31 @@ public class TJUnitTest {
   private final static String pixFormatStr[] = {
     "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"
   };
-  private final static int biType[] = {
-    0, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_INT_BGR,
-    BufferedImage.TYPE_INT_RGB, 0, 0, BufferedImage.TYPE_BYTE_GRAY
+
+  private final static int alphaOffset[] = {
+    -1, -1, 3, 3, 0, 0, -1
   };
 
   private final static int _3byteFormats[] = {
     TJ.PF_RGB, TJ.PF_BGR
   };
   private final static int _3byteFormatsBI[] = {
-    TJ.PF_BGR
+    BufferedImage.TYPE_3BYTE_BGR
   };
   private final static int _4byteFormats[] = {
     TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB
   };
   private final static int _4byteFormatsBI[] = {
-    TJ.PF_RGBX, TJ.PF_BGRX
+    BufferedImage.TYPE_INT_BGR, BufferedImage.TYPE_INT_RGB,
+    BufferedImage.TYPE_4BYTE_ABGR, BufferedImage.TYPE_4BYTE_ABGR_PRE,
+    BufferedImage.TYPE_INT_ARGB, BufferedImage.TYPE_INT_ARGB_PRE
   };
   private final static int onlyGray[] = {
     TJ.PF_GRAY
   };
+  private final static int onlyGrayBI[] = {
+    BufferedImage.TYPE_BYTE_GRAY
+  };
   private final static int onlyRGB[] = {
     TJ.PF_RGB
   };
@@ -90,6 +96,55 @@ public class TJUnitTest {
 
   private static int exitStatus = 0;
 
+  private static int biTypePF(int biType) {
+    ByteOrder byteOrder = ByteOrder.nativeOrder();
+    switch(biType) {
+      case BufferedImage.TYPE_3BYTE_BGR:
+        return TJ.PF_BGR;
+      case BufferedImage.TYPE_4BYTE_ABGR:
+      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+        return TJ.PF_XBGR;
+      case BufferedImage.TYPE_BYTE_GRAY:
+        return TJ.PF_GRAY;
+      case BufferedImage.TYPE_INT_BGR:
+        if(byteOrder == ByteOrder.BIG_ENDIAN)
+          return TJ.PF_XBGR;
+        else
+          return TJ.PF_RGBX;
+      case BufferedImage.TYPE_INT_RGB:
+      case BufferedImage.TYPE_INT_ARGB:
+      case BufferedImage.TYPE_INT_ARGB_PRE:
+        if(byteOrder == ByteOrder.BIG_ENDIAN)
+          return TJ.PF_XRGB;
+        else
+          return TJ.PF_BGRX;
+    }
+    return 0;
+  }
+
+  private static String biTypeStr(int biType) {
+    switch(biType) {
+      case BufferedImage.TYPE_3BYTE_BGR:
+        return "3BYTE_BGR";
+      case BufferedImage.TYPE_4BYTE_ABGR:
+        return "4BYTE_ABGR";
+      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+        return "4BYTE_ABGR_PRE";
+      case BufferedImage.TYPE_BYTE_GRAY:
+        return "BYTE_GRAY";
+      case BufferedImage.TYPE_INT_BGR:
+        return "INT_BGR";
+      case BufferedImage.TYPE_INT_RGB:
+        return "INT_RGB";
+      case BufferedImage.TYPE_INT_ARGB:
+        return "INT_ARGB";
+      case BufferedImage.TYPE_INT_ARGB_PRE:
+        return "INT_ARGB_PRE";
+    }
+    return "Unknown";
+  }
+  
+
   private static double getTime() {
     return (double)System.nanoTime() / 1.0e9;
   }
@@ -99,6 +154,7 @@ public class TJUnitTest {
     int roffset = TJ.getRedOffset(pf);
     int goffset = TJ.getGreenOffset(pf);
     int boffset = TJ.getBlueOffset(pf);
+    int aoffset = alphaOffset[pf];
     int ps = TJ.getPixelSize(pf);
     int index, row, col, halfway = 16;
 
@@ -132,6 +188,7 @@ public class TJUnitTest {
           buf[index + roffset] = (byte)255;
           if(row >= halfway) buf[index + goffset] = (byte)255;
         }
+        if (aoffset >= 0) buf[index + aoffset] = (byte)255;
       }
     }
   }
@@ -141,6 +198,7 @@ public class TJUnitTest {
     int rshift = TJ.getRedOffset(pf) * 8;
     int gshift = TJ.getGreenOffset(pf) * 8;
     int bshift = TJ.getBlueOffset(pf) * 8;
+    int ashift = alphaOffset[pf] * 8;
     int index, row, col, halfway = 16;
 
     Arrays.fill(buf, 0);
@@ -160,6 +218,7 @@ public class TJUnitTest {
           buf[index] |= (255 << rshift);
           if(row >= halfway) buf[index] |= (255 << gshift);
         }
+        if (ashift >= 0) buf[index] |= (255 << ashift);
       }
     }
   }
@@ -167,9 +226,11 @@ public class TJUnitTest {
   private static void initImg(BufferedImage img, int pf, int flags)
     throws Exception {
     WritableRaster wr = img.getRaster();
-    int imgtype = img.getType();
-    if(imgtype == BufferedImage.TYPE_INT_RGB
-      || imgtype == BufferedImage.TYPE_INT_BGR) {
+    int imgType = img.getType();
+    if(imgType == BufferedImage.TYPE_INT_RGB
+      || imgType == BufferedImage.TYPE_INT_BGR
+      || imgType == BufferedImage.TYPE_INT_ARGB
+      || imgType == BufferedImage.TYPE_INT_ARGB_PRE) {
       SinglePixelPackedSampleModel sm =
         (SinglePixelPackedSampleModel)img.getSampleModel();
       int pitch = sm.getScanlineStride();
@@ -218,6 +279,7 @@ public class TJUnitTest {
     int roffset = TJ.getRedOffset(pf);
     int goffset = TJ.getGreenOffset(pf);
     int boffset = TJ.getBlueOffset(pf);
+    int aoffset = alphaOffset[pf];
     int ps = TJ.getPixelSize(pf);
     int index, row, col, retval = 1;
     int halfway = 16 * sf.getNum() / sf.getDenom();
@@ -232,6 +294,7 @@ public class TJUnitTest {
           byte r = buf[index + roffset];
           byte g = buf[index + goffset];
           byte b = buf[index + boffset];
+          byte a = aoffset >= 0 ? buf[index + aoffset] : (byte)255;
           if(((row / blockSize) + (col / blockSize)) % 2 == 0) {
             if(row < halfway) {
               checkVal255(row, col, r, "R");
@@ -268,6 +331,7 @@ public class TJUnitTest {
               checkVal0(row, col, b, "B");                                                     
             }
           }
+          checkVal255(row, col, a, "A");
         }
       }
     }
@@ -297,6 +361,7 @@ public class TJUnitTest {
     int rshift = TJ.getRedOffset(pf) * 8;
     int gshift = TJ.getGreenOffset(pf) * 8;
     int bshift = TJ.getBlueOffset(pf) * 8;
+    int ashift = alphaOffset[pf] * 8;
     int index, row, col, retval = 1;
     int halfway = 16 * sf.getNum() / sf.getDenom();
     int blockSize = 8 * sf.getNum() / sf.getDenom();
@@ -310,6 +375,7 @@ public class TJUnitTest {
           int r = (buf[index] >> rshift) & 0xFF;
           int g = (buf[index] >> gshift) & 0xFF;
           int b = (buf[index] >> bshift) & 0xFF;
+          int a = ashift >= 0 ? (buf[index] >> ashift) & 0xFF : 255;
           if(((row / blockSize) + (col / blockSize)) % 2 == 0) {
             if(row < halfway) {
               checkVal255(row, col, r, "R");
@@ -346,6 +412,7 @@ public class TJUnitTest {
               checkVal0(row, col, b, "B");
             }
           }
+          checkVal255(row, col, a, "A");
         }
       }
     }
@@ -373,10 +440,12 @@ public class TJUnitTest {
   private static int checkImg(BufferedImage img, int pf,
     int subsamp, TJScalingFactor sf, int flags) throws Exception {
     WritableRaster wr = img.getRaster();
-    int imgtype = img.getType();
-    if(imgtype == BufferedImage.TYPE_INT_RGB
-      || imgtype == BufferedImage.TYPE_INT_BGR) {
-      SinglePixelPackedSampleModel sm =
+    int imgType = img.getType();
+    if(imgType == BufferedImage.TYPE_INT_RGB
+      || imgType == BufferedImage.TYPE_INT_BGR
+      || imgType == BufferedImage.TYPE_INT_ARGB
+      || imgType == BufferedImage.TYPE_INT_ARGB_PRE) {
+       SinglePixelPackedSampleModel sm =
         (SinglePixelPackedSampleModel)img.getSampleModel();
       int pitch = sm.getScanlineStride();
       DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
@@ -506,11 +575,17 @@ public class TJUnitTest {
     BufferedImage img = null;
     String pfStr;
     double t;
-    int size = 0, ps = TJ.getPixelSize(pf);
+    int size = 0, ps, imgType = pf;
 
-    pfStr = pixFormatStr[pf];
+    if (bi) {
+      pf = biTypePF(imgType);
+      pfStr = biTypeStr(imgType);
+    }
+    else pfStr = pixFormatStr[pf];
+    ps =  TJ.getPixelSize(pf);
 
     System.out.print(pfStr + " ");
+    if(bi) System.out.print("(" + pixFormatStr[pf] + ") ");
     if((flags & TJ.FLAG_BOTTOMUP) != 0) System.out.print("Bottom-Up");
     else System.out.print("Top-Down ");
     System.out.print(" -> " + subNameLong[subsamp] + " ");
@@ -518,7 +593,7 @@ public class TJUnitTest {
     else System.out.print("Q" + jpegQual + " ... ");
 
     if(bi) {
-      img = new BufferedImage(w, h, biType[pf]);
+      img = new BufferedImage(w, h, imgType);
       initImg(img, pf, flags);
       tempstr = baseName + "_enc_" + pfStr + "_"
         + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_"
@@ -578,18 +653,24 @@ public class TJUnitTest {
     double t;
     int scaledWidth = sf.getScaled(w);
     int scaledHeight = sf.getScaled(h);
-    int temp1, temp2;
+    int temp1, temp2, imgType = pf;
     BufferedImage img = null;
     byte[] dstBuf = null;
 
     if(yuv == YUVENCODE) return;
 
-    pfStr = pixFormatStr[pf];
+    if (bi) {
+      pf = biTypePF(imgType);
+      pfStr = biTypeStr(imgType);
+    }
+    else pfStr = pixFormatStr[pf];
+
     System.out.print("JPEG -> ");
     if(yuv == YUVDECODE)
       System.out.print("YUV " + subName[subsamp] + " ... ");
     else {
       System.out.print(pfStr + " ");
+      if(bi) System.out.print("(" + pixFormatStr[pf] + ") ");
       if((flags & TJ.FLAG_BOTTOMUP) != 0) System.out.print("Bottom-Up ");
       else System.out.print("Top-Down  ");
       if(!sf.isOne())
@@ -613,7 +694,7 @@ public class TJUnitTest {
     if(yuv == YUVDECODE) dstBuf = tjd.decompressToYUV(flags);
     else {
       if(bi)
-        img = tjd.decompress(scaledWidth, scaledHeight, biType[pf], flags);
+        img = tjd.decompress(scaledWidth, scaledHeight, imgType, flags);
       else dstBuf = tjd.decompress(scaledWidth, 0, scaledHeight, pf, flags);
     }
     t = getTime() - t;
@@ -775,7 +856,7 @@ public class TJUnitTest {
         doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_440,
           testName);
       }
-      doTest(35, 39, onlyGray, TJ.SAMP_GRAY, testName);
+      doTest(35, 39, bi ? onlyGrayBI : onlyGray, TJ.SAMP_GRAY, testName);
       doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_GRAY,
         testName);
       doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY,
index 102913922355694547416ece1ca8d80b8516441a..8c6a608e1d3082e35ee39decbc8010a8e04d753e 100644 (file)
@@ -190,6 +190,9 @@ public class TJCompressor {
     switch(srcImage.getType()) {
       case BufferedImage.TYPE_3BYTE_BGR:
         pixelFormat = TJ.PF_BGR;  break;
+      case BufferedImage.TYPE_4BYTE_ABGR:
+      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+        pixelFormat = TJ.PF_XBGR;  break;
       case BufferedImage.TYPE_BYTE_GRAY:
         pixelFormat = TJ.PF_GRAY;  break;
       case BufferedImage.TYPE_INT_BGR:
@@ -199,6 +202,8 @@ public class TJCompressor {
           pixelFormat = TJ.PF_RGBX;
         intPixels = true;  break;
       case BufferedImage.TYPE_INT_RGB:
+      case BufferedImage.TYPE_INT_ARGB:
+      case BufferedImage.TYPE_INT_ARGB_PRE:
         if(byteOrder == ByteOrder.BIG_ENDIAN)
           pixelFormat = TJ.PF_XRGB;
         else
@@ -329,6 +334,9 @@ public class TJCompressor {
     switch(srcImage.getType()) {
       case BufferedImage.TYPE_3BYTE_BGR:
         pixelFormat = TJ.PF_BGR;  break;
+      case BufferedImage.TYPE_4BYTE_ABGR:
+      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+        pixelFormat = TJ.PF_XBGR;  break;
       case BufferedImage.TYPE_BYTE_GRAY:
         pixelFormat = TJ.PF_GRAY;  break;
       case BufferedImage.TYPE_INT_BGR:
@@ -338,6 +346,8 @@ public class TJCompressor {
           pixelFormat = TJ.PF_RGBX;
         intPixels = true;  break;
       case BufferedImage.TYPE_INT_RGB:
+      case BufferedImage.TYPE_INT_ARGB:
+      case BufferedImage.TYPE_INT_ARGB_PRE:
         if(byteOrder == ByteOrder.BIG_ENDIAN)
           pixelFormat = TJ.PF_XRGB;
         else
index b247847157784ae8aca3059dead4238c43d8dae1..4be5494cc3dbadb81bf39e02398402e3c948a5ad 100644 (file)
@@ -387,6 +387,9 @@ public class TJDecompressor {
     switch(dstImage.getType()) {
       case BufferedImage.TYPE_3BYTE_BGR:
         pixelFormat = TJ.PF_BGR;  break;
+      case BufferedImage.TYPE_4BYTE_ABGR:
+      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+        pixelFormat = TJ.PF_XBGR;  break;
       case BufferedImage.TYPE_BYTE_GRAY:
         pixelFormat = TJ.PF_GRAY;  break;
       case BufferedImage.TYPE_INT_BGR:
@@ -396,6 +399,8 @@ public class TJDecompressor {
           pixelFormat = TJ.PF_RGBX;
         intPixels = true;  break;
       case BufferedImage.TYPE_INT_RGB:
+      case BufferedImage.TYPE_INT_ARGB:
+      case BufferedImage.TYPE_INT_ARGB_PRE:
         if(byteOrder == ByteOrder.BIG_ENDIAN)
           pixelFormat = TJ.PF_XRGB;
         else
index d0ccca360246a3d7eec71965a359b25a76c96e18..af7ea7e81fc7afaa151e4a20e91d626427d114c4 100644 (file)
@@ -54,6 +54,10 @@ ycc_rgb_convert_internal (j_decompress_ptr cinfo,
       y  = GETJSAMPLE(inptr0[col]);
       cb = GETJSAMPLE(inptr1[col]);
       cr = GETJSAMPLE(inptr2[col]);
+      /* Initialize 4-byte pixels so the alpha channel will be opaque */
+#if RGB_PIXELSIZE == 4
+      *(unsigned int *)outptr = 0xFFFFFFFF;
+#endif
       /* Range-limiting is essential due to noise introduced by DCT losses. */
       outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
       outptr[RGB_GREEN] = range_limit[y +
@@ -86,6 +90,10 @@ gray_rgb_convert_internal (j_decompress_ptr cinfo,
     inptr = input_buf[0][input_row++];
     outptr = *output_buf++;
     for (col = 0; col < num_cols; col++) {
+      /* Initialize 4-byte pixels so the alpha channel will be opaque */
+#if RGB_PIXELSIZE == 4
+      *(unsigned int *)outptr = 0xFFFFFFFF;
+#endif
       /* We can dispense with GETJSAMPLE() here */
       outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
       outptr += RGB_PIXELSIZE;
index 13cff0305d130a8779f8e5fa27666b3ebbcd746a..0dacd0656e2b60b6efcb17929f966656f589987f 100644 (file)
@@ -64,6 +64,8 @@ definev(EXT_XRGB_GREEN)
 definev(EXT_XRGB_BLUE)
 definev(EXT_XRGB_PIXELSIZE)
 
+%define RGBX_FILLER_0XFF        1
+
 ; Representation of a single sample (pixel element value).
 ; On this SIMD implementation, this must be 'unsigned char'.
 ;
index 08d8fe217a9ca4f29eb6cea285a13c45b9c21dd3..3a573479155a39d9dea489f1fd79fe90d76f284d 100644 (file)
@@ -68,6 +68,8 @@ const char *pixFormatStr[TJ_NUMPF]=
        "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"
 };
 
+const int alphaOffset[TJ_NUMPF] = {-1, -1, 3, 3, 0, 0, -1};
+
 const int _3byteFormats[]={TJPF_RGB, TJPF_BGR};
 const int _4byteFormats[]={TJPF_RGBX, TJPF_BGRX, TJPF_XBGR, TJPF_XRGB};
 const int _onlyGray[]={TJPF_GRAY};
@@ -156,6 +158,7 @@ int checkBuf(unsigned char *buf, int w, int h, int pf, int subsamp,
        int roffset=tjRedOffset[pf];
        int goffset=tjGreenOffset[pf];
        int boffset=tjBlueOffset[pf];
+       int aoffset=alphaOffset[pf];
        int ps=tjPixelSize[pf];
        int index, row, col, retval=1;
        int halfway=16*sf.num/sf.denom;
@@ -165,12 +168,13 @@ int checkBuf(unsigned char *buf, int w, int h, int pf, int subsamp,
        {
                for(col=0; col<w; col++)
                {
-                       unsigned char r, g, b;
+                       unsigned char r, g, b, a;
                        if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col;
                        else index=row*w+col;
                        r=buf[index*ps+roffset];
                        g=buf[index*ps+goffset];
                        b=buf[index*ps+boffset];
+                       a=aoffset>=0? buf[index*ps+aoffset]:0xFF;
                        if(((row/blocksize)+(col/blocksize))%2==0)
                        {
                                if(row<halfway)
@@ -207,6 +211,7 @@ int checkBuf(unsigned char *buf, int w, int h, int pf, int subsamp,
                                        }
                                }
                        }
+                       checkval255(a);
                }
        }