Implement YUV encode/decode methods at the Java level; Remove some of the arguments from the Java API and replace with get/set methods; General API cleanup; Fix BufferedImage grayscale tests in TJUnitTest
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@451 632fc199-4ca6-4c93-a231-07263d6284db
This commit is contained in:
@@ -49,7 +49,7 @@ final public class TJ {
|
||||
PF_XRGB = 5,
|
||||
PF_GRAY = 6;
|
||||
|
||||
final public static int pixelSize[] = {
|
||||
final private static int pixelSize[] = {
|
||||
3, 3, 4, 4, 4, 4, 1
|
||||
};
|
||||
|
||||
@@ -59,6 +59,36 @@ final public class TJ {
|
||||
return pixelSize[pixelFormat];
|
||||
}
|
||||
|
||||
final private static int redShift[] = {
|
||||
0, 16, 0, 16, 24, 8, 0
|
||||
};
|
||||
|
||||
final public static int getRedShift(int pixelFormat) throws Exception {
|
||||
if(pixelFormat < 0 || pixelFormat >= NUMPFOPT)
|
||||
throw new Exception("Invalid pixel format");
|
||||
return redShift[pixelFormat];
|
||||
}
|
||||
|
||||
final private static int greenShift[] = {
|
||||
8, 8, 8, 8, 16, 16, 0
|
||||
};
|
||||
|
||||
final public static int getGreenShift(int pixelFormat) throws Exception {
|
||||
if(pixelFormat < 0 || pixelFormat >= NUMPFOPT)
|
||||
throw new Exception("Invalid pixel format");
|
||||
return greenShift[pixelFormat];
|
||||
}
|
||||
|
||||
final private static int blueShift[] = {
|
||||
16, 0, 16, 0, 8, 24, 0
|
||||
};
|
||||
|
||||
final public static int getBlueShift(int pixelFormat) throws Exception {
|
||||
if(pixelFormat < 0 || pixelFormat >= NUMPFOPT)
|
||||
throw new Exception("Invalid pixel format");
|
||||
return blueShift[pixelFormat];
|
||||
}
|
||||
|
||||
// Flags
|
||||
final public static int
|
||||
BOTTOMUP = 2,
|
||||
@@ -66,22 +96,7 @@ final public class TJ {
|
||||
FORCESSE = 16,
|
||||
FORCESSE2 = 32,
|
||||
FORCESSE3 = 128,
|
||||
FASTUPSAMPLE = 256,
|
||||
YUV = 512;
|
||||
|
||||
final private static int
|
||||
TJ_BGR = 1,
|
||||
TJ_ALPHAFIRST = 64;
|
||||
|
||||
final private static int flags[] = {
|
||||
0, TJ_BGR, 0, TJ_BGR, TJ_BGR|TJ_ALPHAFIRST, TJ_ALPHAFIRST, 0
|
||||
};
|
||||
|
||||
final public static int getFlags(int pixelFormat) throws Exception {
|
||||
if(pixelFormat < 0 || pixelFormat >= NUMPFOPT)
|
||||
throw new Exception("Invalid pixel format");
|
||||
return flags[pixelFormat];
|
||||
}
|
||||
FASTUPSAMPLE = 256;
|
||||
|
||||
public native final static int bufSize(int width, int height)
|
||||
throws Exception;
|
||||
|
||||
@@ -55,18 +55,40 @@ public class TJCompressor {
|
||||
bitmapPixelFormat = pixelFormat;
|
||||
}
|
||||
|
||||
public int compress(byte [] dstBuf, int jpegSubsamp, int jpegQual,
|
||||
int flags) throws Exception {
|
||||
return compress(bitmapBuf, bitmapWidth, bitmapPitch, bitmapHeight,
|
||||
TJ.getPixelSize(bitmapPixelFormat), dstBuf, jpegSubsamp, jpegQual,
|
||||
flags | TJ.getFlags(bitmapPixelFormat));
|
||||
public void setSubsamp(int newSubsamp) throws Exception {
|
||||
if(newSubsamp < 0 || newSubsamp >= TJ.NUMSAMPOPT)
|
||||
throw new Exception ("Invalid argument in setSubsamp()");
|
||||
subsamp = newSubsamp;
|
||||
}
|
||||
|
||||
public int compress(BufferedImage srcImage, byte [] dstBuf, int jpegSubsamp,
|
||||
int jpegQual, int flags) throws Exception {
|
||||
if(srcImage == null || flags < 0)
|
||||
throw new Exception("Invalid argument in decompress()");
|
||||
flags &= ~(TJ.YUV);
|
||||
public void setJPEGQuality(int quality) throws Exception {
|
||||
if(quality < 1 || quality > 100)
|
||||
throw new Exception ("Invalid argument in setJPEGQuality()");
|
||||
jpegQuality = quality;
|
||||
}
|
||||
|
||||
public void compress(byte [] dstBuf, int flags) throws Exception {
|
||||
if(dstBuf == null || flags < 0)
|
||||
throw new Exception("Invalid argument in compress()");
|
||||
if(bitmapBuf == null) throw new Exception("Bitmap buffer not initialized");
|
||||
if(jpegQuality < 0) throw new Exception("JPEG Quality not set");
|
||||
if(subsamp < 0) throw new Exception("Subsampling level not set");
|
||||
compressedSize = compress(bitmapBuf, bitmapWidth, bitmapPitch,
|
||||
bitmapHeight, bitmapPixelFormat, dstBuf, subsamp, jpegQuality, flags);
|
||||
}
|
||||
|
||||
public byte [] compress(int flags) throws Exception {
|
||||
if(bitmapWidth < 1 || bitmapHeight < 1)
|
||||
throw new Exception("Bitmap buffer not initialized");
|
||||
byte [] buf = new byte[TJ.bufSize(bitmapWidth, bitmapHeight)];
|
||||
compress(buf, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public void compress(BufferedImage srcImage, byte [] dstBuf, int flags)
|
||||
throws Exception {
|
||||
if(srcImage == null || dstBuf == null || flags < 0)
|
||||
throw new Exception("Invalid argument in compress()");
|
||||
int width = srcImage.getWidth();
|
||||
int height = srcImage.getHeight();
|
||||
int pixelFormat; boolean intPixels=false;
|
||||
@@ -83,29 +105,117 @@ public class TJCompressor {
|
||||
throw new Exception("Unsupported BufferedImage format");
|
||||
}
|
||||
WritableRaster wr = srcImage.getRaster();
|
||||
if(jpegQuality < 0) throw new Exception("JPEG Quality not set");
|
||||
if(subsamp < 0) throw new Exception("Subsampling level not set");
|
||||
if(intPixels) {
|
||||
SinglePixelPackedSampleModel sm =
|
||||
(SinglePixelPackedSampleModel)srcImage.getSampleModel();
|
||||
int pitch = sm.getScanlineStride();
|
||||
DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
|
||||
int [] buf = db.getData();
|
||||
return compress(buf, width, pitch, height, dstBuf, jpegSubsamp, jpegQual,
|
||||
flags | TJ.getFlags(pixelFormat));
|
||||
compressedSize = compress(buf, width, pitch, height, pixelFormat, dstBuf,
|
||||
subsamp, jpegQuality, flags);
|
||||
}
|
||||
else {
|
||||
ComponentSampleModel sm =
|
||||
(ComponentSampleModel)srcImage.getSampleModel();
|
||||
int pixelSize = sm.getPixelStride();
|
||||
if(pixelSize != TJ.pixelSize[pixelFormat])
|
||||
if(pixelSize != TJ.getPixelSize(pixelFormat))
|
||||
throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
|
||||
int pitch = sm.getScanlineStride();
|
||||
DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
|
||||
byte [] buf = db.getData();
|
||||
return compress(buf, width, pitch, height, TJ.getPixelSize(pixelFormat),
|
||||
dstBuf, jpegSubsamp, jpegQual, flags | TJ.getFlags(pixelFormat));
|
||||
compressedSize = compress(buf, width, pitch, height, pixelFormat, dstBuf,
|
||||
subsamp, jpegQuality, flags);
|
||||
}
|
||||
}
|
||||
|
||||
public byte [] compress(BufferedImage srcImage, int flags) throws Exception {
|
||||
int width = srcImage.getWidth();
|
||||
int height = srcImage.getHeight();
|
||||
byte [] buf = new byte[TJ.bufSize(width, height)];
|
||||
compress(srcImage, buf, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public void encodeYUV(byte [] dstBuf, int flags) throws Exception {
|
||||
if(dstBuf == null || flags < 0)
|
||||
throw new Exception("Invalid argument in compress()");
|
||||
if(bitmapBuf == null) throw new Exception("Bitmap buffer not initialized");
|
||||
if(subsamp < 0) throw new Exception("Subsampling level not set");
|
||||
encodeYUV(bitmapBuf, bitmapWidth, bitmapPitch, bitmapHeight,
|
||||
bitmapPixelFormat, dstBuf, subsamp, flags);
|
||||
compressedSize = TJ.bufSizeYUV(bitmapWidth, bitmapHeight, subsamp);
|
||||
}
|
||||
|
||||
public byte [] encodeYUV(int flags) throws Exception {
|
||||
if(bitmapWidth < 1 || bitmapHeight < 1)
|
||||
throw new Exception("Bitmap buffer not initialized");
|
||||
if(subsamp < 0) throw new Exception("Subsampling level not set");
|
||||
byte [] buf = new byte[TJ.bufSizeYUV(bitmapWidth, bitmapHeight, subsamp)];
|
||||
encodeYUV(buf, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public void encodeYUV(BufferedImage srcImage, byte [] dstBuf, int flags)
|
||||
throws Exception {
|
||||
if(srcImage == null || dstBuf == null || flags < 0)
|
||||
throw new Exception("Invalid argument in encodeYUV()");
|
||||
int width = srcImage.getWidth();
|
||||
int height = srcImage.getHeight();
|
||||
int pixelFormat; boolean intPixels=false;
|
||||
switch(srcImage.getType()) {
|
||||
case BufferedImage.TYPE_3BYTE_BGR:
|
||||
pixelFormat=TJ.PF_BGR; break;
|
||||
case BufferedImage.TYPE_BYTE_GRAY:
|
||||
pixelFormat=TJ.PF_GRAY; break;
|
||||
case BufferedImage.TYPE_INT_BGR:
|
||||
pixelFormat=TJ.PF_RGBX; intPixels=true; break;
|
||||
case BufferedImage.TYPE_INT_RGB:
|
||||
pixelFormat=TJ.PF_BGRX; intPixels=true; break;
|
||||
default:
|
||||
throw new Exception("Unsupported BufferedImage format");
|
||||
}
|
||||
WritableRaster wr = srcImage.getRaster();
|
||||
if(subsamp < 0) throw new Exception("Subsampling level not set");
|
||||
if(intPixels) {
|
||||
SinglePixelPackedSampleModel sm =
|
||||
(SinglePixelPackedSampleModel)srcImage.getSampleModel();
|
||||
int pitch = sm.getScanlineStride();
|
||||
DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
|
||||
int [] buf = db.getData();
|
||||
encodeYUV(buf, width, pitch, height, pixelFormat, dstBuf, subsamp,
|
||||
flags);
|
||||
}
|
||||
else {
|
||||
ComponentSampleModel sm =
|
||||
(ComponentSampleModel)srcImage.getSampleModel();
|
||||
int pixelSize = sm.getPixelStride();
|
||||
if(pixelSize != TJ.getPixelSize(pixelFormat))
|
||||
throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
|
||||
int pitch = sm.getScanlineStride();
|
||||
DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
|
||||
byte [] buf = db.getData();
|
||||
encodeYUV(buf, width, pitch, height, pixelFormat, dstBuf, subsamp,
|
||||
flags);
|
||||
}
|
||||
compressedSize = TJ.bufSizeYUV(width, height, subsamp);
|
||||
}
|
||||
|
||||
public byte [] encodeYUV(BufferedImage srcImage, int flags)
|
||||
throws Exception {
|
||||
if(subsamp < 0) throw new Exception("Subsampling level not set");
|
||||
int width = srcImage.getWidth();
|
||||
int height = srcImage.getHeight();
|
||||
byte [] buf = new byte[TJ.bufSizeYUV(width, height, subsamp)];
|
||||
encodeYUV(srcImage, buf, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public int getCompressedSize() {
|
||||
return compressedSize;
|
||||
}
|
||||
|
||||
public void close() throws Exception {
|
||||
destroy();
|
||||
}
|
||||
@@ -126,11 +236,19 @@ public class TJCompressor {
|
||||
|
||||
// JPEG size in bytes is returned
|
||||
private native int compress(byte [] srcBuf, int width, int pitch,
|
||||
int height, int pixelSize, byte [] dstbuf, int jpegSubsamp, int jpegQual,
|
||||
int height, int pixelFormat, byte [] dstbuf, int jpegSubsamp, int jpegQual,
|
||||
int flags) throws Exception;
|
||||
|
||||
private native int compress(int [] srcBuf, int width, int pitch,
|
||||
int height, byte [] dstbuf, int jpegSubsamp, int jpegQual, int flags)
|
||||
int height, int pixelFormat, byte [] dstbuf, int jpegSubsamp, int jpegQual,
|
||||
int flags) throws Exception;
|
||||
|
||||
private native void encodeYUV(byte [] srcBuf, int width, int pitch,
|
||||
int height, int pixelFormat, byte [] dstbuf, int subsamp, int flags)
|
||||
throws Exception;
|
||||
|
||||
private native void encodeYUV(int [] srcBuf, int width, int pitch,
|
||||
int height, int pixelFormat, byte [] dstbuf, int subsamp, int flags)
|
||||
throws Exception;
|
||||
|
||||
static {
|
||||
@@ -143,4 +261,7 @@ public class TJCompressor {
|
||||
private int bitmapHeight = 0;
|
||||
private int bitmapPitch = 0;
|
||||
private int bitmapPixelFormat = -1;
|
||||
private int subsamp = -1;
|
||||
private int jpegQuality = -1;
|
||||
private int compressedSize = 0;
|
||||
};
|
||||
|
||||
@@ -74,6 +74,8 @@ public class TJDecompressor {
|
||||
throws Exception {
|
||||
if(jpegWidth < 1 || jpegHeight < 1)
|
||||
throw new Exception("JPEG buffer not initialized");
|
||||
if(desiredWidth < 0 || desiredHeight < 0)
|
||||
throw new Exception("Invalid argument in getScaledWidth()");
|
||||
return getScaledWidth(jpegWidth, jpegHeight, desiredWidth,
|
||||
desiredHeight);
|
||||
}
|
||||
@@ -82,6 +84,8 @@ public class TJDecompressor {
|
||||
throws Exception {
|
||||
if(jpegWidth < 1 || jpegHeight < 1)
|
||||
throw new Exception("JPEG buffer not initialized");
|
||||
if(desiredWidth < 0 || desiredHeight < 0)
|
||||
throw new Exception("Invalid argument in getScaledHeight()");
|
||||
return getScaledHeight(jpegWidth, jpegHeight, desiredWidth,
|
||||
desiredHeight);
|
||||
}
|
||||
@@ -89,35 +93,49 @@ public class TJDecompressor {
|
||||
public void decompress(byte [] dstBuf, int desiredWidth, int pitch,
|
||||
int desiredHeight, int pixelFormat, int flags) throws Exception {
|
||||
if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
|
||||
if(dstBuf == null || desiredWidth < 0 || pitch < 0 || desiredHeight < 0
|
||||
|| pixelFormat < 0 || pixelFormat >= TJ.NUMPFOPT || flags < 0)
|
||||
throw new Exception("Invalid argument in decompress()");
|
||||
decompress(jpegBuf, jpegBufSize, dstBuf, desiredWidth, pitch,
|
||||
desiredHeight, TJ.getPixelSize(pixelFormat),
|
||||
flags | TJ.getFlags(pixelFormat));
|
||||
desiredHeight, pixelFormat, flags);
|
||||
}
|
||||
|
||||
public byte [] decompress(int desiredWidth, int pitch, int desiredHeight,
|
||||
int pixelFormat, int flags) throws Exception {
|
||||
if(desiredWidth < 0 || desiredHeight < 0 || pitch < 0 || pixelFormat < 0
|
||||
|| pixelFormat >= TJ.NUMPFOPT || flags < 0)
|
||||
if(desiredWidth < 0 || pitch < 0 || desiredHeight < 0
|
||||
|| pixelFormat < 0 || pixelFormat >= TJ.NUMPFOPT || flags < 0)
|
||||
throw new Exception("Invalid argument in decompress()");
|
||||
int pixelSize = TJ.getPixelSize(pixelFormat);
|
||||
int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
|
||||
int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
|
||||
if(pitch == 0) pitch = scaledWidth * pixelSize;
|
||||
int bufSize;
|
||||
if((flags&TJ.YUV)!=0)
|
||||
bufSize = TJ.bufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp);
|
||||
else bufSize = pitch * scaledHeight;
|
||||
byte [] buf = new byte[bufSize];
|
||||
byte [] buf = new byte[pitch * scaledHeight];
|
||||
decompress(buf, desiredWidth, pitch, desiredHeight, pixelFormat, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public void decompressToYUV(byte [] dstBuf, int flags) throws Exception {
|
||||
if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
|
||||
decompress(jpegBuf, jpegBufSize, buf, desiredWidth, pitch, desiredHeight,
|
||||
TJ.getPixelSize(pixelFormat), flags | TJ.getFlags(pixelFormat));
|
||||
if(dstBuf == null || flags < 0)
|
||||
throw new Exception("Invalid argument in decompressToYUV()");
|
||||
decompressToYUV(jpegBuf, jpegBufSize, dstBuf, flags);
|
||||
}
|
||||
|
||||
public byte [] decompressToYUV(int flags) throws Exception {
|
||||
if(flags < 0)
|
||||
throw new Exception("Invalid argument in decompressToYUV()");
|
||||
if(jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0)
|
||||
throw new Exception("JPEG buffer not initialized");
|
||||
if(jpegSubsamp >= TJ.NUMSAMPOPT)
|
||||
throw new Exception("JPEG header information is invalid");
|
||||
byte [] buf = new byte[TJ.bufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp)];
|
||||
decompressToYUV(buf, flags);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public void decompress(BufferedImage dstImage, int flags) throws Exception {
|
||||
if(dstImage == null || flags < 0)
|
||||
throw new Exception("Invalid argument in decompress()");
|
||||
flags &= ~(TJ.YUV);
|
||||
int desiredWidth = dstImage.getWidth();
|
||||
int desiredHeight = dstImage.getHeight();
|
||||
int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
|
||||
@@ -144,14 +162,15 @@ public class TJDecompressor {
|
||||
int pitch = sm.getScanlineStride();
|
||||
DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
|
||||
int [] buf = db.getData();
|
||||
if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
|
||||
decompress(jpegBuf, jpegBufSize, buf, scaledWidth, pitch, scaledHeight,
|
||||
flags | TJ.getFlags(pixelFormat));
|
||||
pixelFormat, flags);
|
||||
}
|
||||
else {
|
||||
ComponentSampleModel sm =
|
||||
(ComponentSampleModel)dstImage.getSampleModel();
|
||||
int pixelSize = sm.getPixelStride();
|
||||
if(pixelSize != TJ.pixelSize[pixelFormat])
|
||||
if(pixelSize != TJ.getPixelSize(pixelFormat))
|
||||
throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
|
||||
int pitch = sm.getScanlineStride();
|
||||
DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
|
||||
@@ -160,6 +179,18 @@ public class TJDecompressor {
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage decompress(int desiredWidth, int desiredHeight,
|
||||
int bufferedImageType, int flags) throws Exception {
|
||||
if(desiredWidth < 0 || desiredHeight < 0 || flags < 0)
|
||||
throw new Exception("Invalid argument in decompress()");
|
||||
int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
|
||||
int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
|
||||
BufferedImage img = new BufferedImage(scaledWidth, scaledHeight,
|
||||
bufferedImageType);
|
||||
decompress(img, flags);
|
||||
return img;
|
||||
}
|
||||
|
||||
public void close() throws Exception {
|
||||
destroy();
|
||||
}
|
||||
@@ -182,11 +213,15 @@ public class TJDecompressor {
|
||||
throws Exception;
|
||||
|
||||
private native void decompress(byte [] srcBuf, int size, byte [] dstBuf,
|
||||
int desiredWidth, int pitch, int desiredHeight, int pixelSize, int flags)
|
||||
int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags)
|
||||
throws Exception;
|
||||
|
||||
private native void decompress(byte [] srcBuf, int size, int [] dstBuf,
|
||||
int desiredWidth, int pitch, int desiredHeight, int flags)
|
||||
int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags)
|
||||
throws Exception;
|
||||
|
||||
private native void decompressToYUV(byte [] srcBuf, int size, byte [] dstBuf,
|
||||
int flags)
|
||||
throws Exception;
|
||||
|
||||
private native int getScaledWidth(int jpegWidth, int jpegHeight,
|
||||
|
||||
Reference in New Issue
Block a user