Support for compressing from/decompressing to a BufferedImage in the Java wrapper

This commit is contained in:
DRC
2011-02-23 12:09:56 +00:00
parent 4802041125
commit a311c1cd21
7 changed files with 441 additions and 54 deletions

View File

@@ -32,6 +32,8 @@
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.awt.image.*;
import javax.imageio.*;
import org.libjpegturbo.turbojpeg.*; import org.libjpegturbo.turbojpeg.*;
public class TJUnitTest { public class TJUnitTest {
@@ -42,6 +44,7 @@ public class TJUnitTest {
System.out.println("\nUSAGE: java "+classname+" [options]\n"); System.out.println("\nUSAGE: java "+classname+" [options]\n");
System.out.println("Options:\n"); System.out.println("Options:\n");
System.out.println("-yuv = test YUV encoding/decoding support\n"); System.out.println("-yuv = test YUV encoding/decoding support\n");
System.out.println("-bi = test BufferedImage support\n");
System.exit(1); System.exit(1);
} }
@@ -60,11 +63,18 @@ public class TJUnitTest {
{1, 1, 1, 1, 2, 2, 0}; {1, 1, 1, 1, 2, 2, 0};
private final static int _boffset[]= private final static int _boffset[]=
{2, 0, 2, 0, 1, 3, 0}; {2, 0, 2, 0, 1, 3, 0};
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 _3byteFormats[]= private final static int _3byteFormats[]=
{TJ.PF_RGB, TJ.PF_BGR}; {TJ.PF_RGB, TJ.PF_BGR};
private final static int _3byteFormatsBI[]=
{TJ.PF_BGR};
private final static int _4byteFormats[]= private final static int _4byteFormats[]=
{TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB}; {TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB};
private final static int _4byteFormatsBI[]=
{TJ.PF_RGBX, TJ.PF_BGRX};
private final static int _onlyGray[]= private final static int _onlyGray[]=
{TJ.PF_GRAY}; {TJ.PF_GRAY};
private final static int _onlyRGB[]= private final static int _onlyRGB[]=
@@ -72,6 +82,7 @@ public class TJUnitTest {
private final static int YUVENCODE=1, YUVDECODE=2; private final static int YUVENCODE=1, YUVDECODE=2;
private static int yuv=0; private static int yuv=0;
private static boolean bi=false;
private static int exitstatus=0; private static int exitstatus=0;
@@ -149,6 +160,56 @@ public class TJUnitTest {
} }
} }
private static void initimg(BufferedImage img, int pf, int flags)
{
int i, _i, j, w=img.getWidth(), h=img.getHeight(), pixel;
if(pf==TJ.PF_GRAY)
{
for(_i=0; _i<16; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
if(((_i/8)+(j/8))%2==0) pixel=0xFFFFFFFF;
else pixel=0xFF4C4C4C;
img.setRGB(j, i, pixel);
}
}
for(_i=16; _i<h; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
if(((_i/8)+(j/8))%2==0) pixel=0xFF000000;
else pixel=0xFFE2E2E2;
img.setRGB(j, i, pixel);
}
}
return;
}
for(_i=0; _i<16; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
pixel=0xFFFF0000;
if(((_i/8)+(j/8))%2==0) pixel|=0x0000FFFF;
img.setRGB(j, i, pixel);
}
}
for(_i=16; _i<h; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
pixel=0;
if(((_i/8)+(j/8))%2!=0) pixel=0xFFFFFF00;
img.setRGB(j, i, pixel);
}
}
}
private static void dumpbuf(byte [] buf, int w, int h, int pf, private static void dumpbuf(byte [] buf, int w, int h, int pf,
int scalefactor, int flags) int scalefactor, int flags)
{ {
@@ -171,33 +232,33 @@ public class TJUnitTest {
} }
} }
private static void checkval(int i, int j, byte v, String vname, int cvi) private static void checkval(int i, int j, int v, String vname, int cv)
throws Exception throws Exception
{ {
int vi=(v<0)? v+256:v; v=(v<0)? v+256:v;
if(vi<cvi-1 || vi>cvi+1) if(v<cv-1 || v>cv+1)
{ {
throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be "+cvi throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be "+cv
+", not "+v+"\n"); +", not "+v+"\n");
} }
} }
private static void checkval0(int i, int j, byte v, String vname) private static void checkval0(int i, int j, int v, String vname)
throws Exception throws Exception
{ {
int vi=(v<0)? v+256:v; v=(v<0)? v+256:v;
if(vi>1) if(v>1)
{ {
throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 0, not " throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 0, not "
+v+"\n"); +v+"\n");
} }
} }
private static void checkval255(int i, int j, byte v, String vname) private static void checkval255(int i, int j, int v, String vname)
throws Exception throws Exception
{ {
int vi=(v<0)? v+256:v; v=(v<0)? v+256:v;
if(vi<254 && !(vi==217 && i==0 && j==21)) if(v<254 && !(v==217 && i==0 && j==21))
{ {
throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 255, not " throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 255, not "
+v+"\n"); +v+"\n");
@@ -309,6 +370,115 @@ public class TJUnitTest {
return retval; return retval;
} }
private static int checkimg(BufferedImage img, int pf,
int subsamp, int scalefactor, int flags) throws Exception
{
int i, _i, j, retval=1, w=img.getWidth(), h=img.getHeight();
int halfway=16/scalefactor, blocksize=8/scalefactor;
try
{
if(subsamp==TJ.SAMP_GRAY)
{
for(_i=0; _i<halfway; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
int r=(img.getRGB(j, i)>>16) & 0xFF;
int g=(img.getRGB(j, i)>>8) & 0xFF;
int b=img.getRGB(j, i) & 0xFF;
if(((_i/blocksize)+(j/blocksize))%2==0)
{
checkval255(_i, j, r, "R");
checkval255(_i, j, g, "G");
checkval255(_i, j, b, "B");
}
else
{
checkval(_i, j, r, "R", 76);
checkval(_i, j, g, "G", 76);
checkval(_i, j, b, "B", 76);
}
}
}
for(_i=halfway; _i<h; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
int r=(img.getRGB(j, i)>>16) & 0xFF;
int g=(img.getRGB(j, i)>>8) & 0xFF;
int b=img.getRGB(j, i) & 0xFF;
if(((_i/blocksize)+(j/blocksize))%2==0)
{
checkval0(_i, j, r, "R");
checkval0(_i, j, g, "G");
checkval0(_i, j, b, "B");
}
else
{
checkval(_i, j, r, "R", 226);
checkval(_i, j, g, "G", 226);
checkval(_i, j, b, "B", 226);
}
}
}
}
else
{
for(_i=0; _i<halfway; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
int r=(img.getRGB(j, i)>>16) & 0xFF;
int g=(img.getRGB(j, i)>>8) & 0xFF;
int b=img.getRGB(j, i) & 0xFF;
checkval255(_i, j, r, "R");
if(((_i/blocksize)+(j/blocksize))%2==0)
{
checkval255(_i, j, g, "G");
checkval255(_i, j, b, "B");
}
else
{
checkval0(_i, j, g, "G");
checkval0(_i, j, b, "B");
}
}
}
for(_i=halfway; _i<h; _i++)
{
if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
for(j=0; j<w; j++)
{
int r=(img.getRGB(j, i)>>16) & 0xFF;
int g=(img.getRGB(j, i)>>8) & 0xFF;
int b=img.getRGB(j, i) & 0xFF;
checkval0(_i, j, b, "B");
if(((_i/blocksize)+(j/blocksize))%2==0)
{
checkval0(_i, j, r, "R");
checkval0(_i, j, g, "G");
}
else
{
checkval255(_i, j, r, "R");
checkval255(_i, j, g, "G");
}
}
}
}
}
catch(Exception e)
{
System.out.println(e);
retval=0;
}
return retval;
}
private static int PAD(int v, int p) private static int PAD(int v, int p)
{ {
return ((v+(p)-1)&(~((p)-1))); return ((v+(p)-1)&(~((p)-1)));
@@ -444,9 +614,9 @@ public class TJUnitTest {
int h, int pf, String basefilename, int subsamp, int qual, int h, int pf, String basefilename, int subsamp, int qual,
int flags) throws Exception int flags) throws Exception
{ {
String tempstr; byte [] bmpbuf; String tempstr; byte [] bmpbuf=null; BufferedImage img=null;
String pixformat; double t; String pixformat; double t;
int size=0; int size=0, ps=TJ.pixelSize[pf];
if(yuv==YUVENCODE) flags|=TJ.YUV; if(yuv==YUVENCODE) flags|=TJ.YUV;
@@ -459,13 +629,31 @@ public class TJUnitTest {
if(yuv==YUVENCODE) System.out.print("YUV ... "); if(yuv==YUVENCODE) System.out.print("YUV ... ");
else System.out.print("Q"+qual+" ... "); else System.out.print("Q"+qual+" ... ");
bmpbuf=new byte[w*h*TJ.pixelSize[pf]+1]; if(bi)
{
img=new BufferedImage(w, h, biType[pf]);
initimg(img, pf, flags);
tempstr=basefilename+"_enc_"+pixformat+"_"
+(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
+"_Q"+qual+".png";
File file=new File(tempstr);
ImageIO.write(img, "png", file);
}
else
{
bmpbuf=new byte[w*h*ps+1];
initbuf(bmpbuf, w, h, pf, flags); initbuf(bmpbuf, w, h, pf, flags);
}
Arrays.fill(jpegbuf, (byte)0); Arrays.fill(jpegbuf, (byte)0);
t=gettime(); t=gettime();
if(bi)
size=tjc.compress(img, jpegbuf, subsamp, qual, flags);
else
{
tjc.setBitmapBuffer(bmpbuf, w, 0, h, pf); tjc.setBitmapBuffer(bmpbuf, w, 0, h, pf);
size=tjc.compress(jpegbuf, subsamp, qual, flags); size=tjc.compress(jpegbuf, subsamp, qual, flags);
}
t=gettime()-t; t=gettime()-t;
if(yuv==YUVENCODE) if(yuv==YUVENCODE)
@@ -476,6 +664,7 @@ public class TJUnitTest {
+(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp] +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
+"_Q"+qual+".jpg"; +"_Q"+qual+".jpg";
writejpeg(jpegbuf, size, tempstr); writejpeg(jpegbuf, size, tempstr);
if(yuv==YUVENCODE) if(yuv==YUVENCODE)
{ {
if(checkbufyuv(jpegbuf, size, w, h, subsamp)==1) if(checkbufyuv(jpegbuf, size, w, h, subsamp)==1)
@@ -493,10 +682,12 @@ public class TJUnitTest {
int jpegsize, int w, int h, int pf, String basefilename, int subsamp, int jpegsize, int w, int h, int pf, String basefilename, int subsamp,
int flags, int scalefactor) throws Exception int flags, int scalefactor) throws Exception
{ {
String pixformat; int _hdrw=0, _hdrh=0, _hdrsubsamp=-1; double t; String pixformat, tempstr; int _hdrw=0, _hdrh=0, _hdrsubsamp=-1;
double t;
int scaledw=(w+scalefactor-1)/scalefactor; int scaledw=(w+scalefactor-1)/scalefactor;
int scaledh=(h+scalefactor-1)/scalefactor; int scaledh=(h+scalefactor-1)/scalefactor;
int temp1, temp2; int temp1, temp2;
BufferedImage img=null; byte [] bmpbuf=null;
if(yuv==YUVDECODE) flags|=TJ.YUV; if(yuv==YUVDECODE) flags|=TJ.YUV;
else if(yuv==YUVENCODE) return; else if(yuv==YUVENCODE) return;
@@ -525,9 +716,24 @@ public class TJUnitTest {
if(temp1!=scaledw || temp2!=scaledh) if(temp1!=scaledw || temp2!=scaledh)
throw new Exception("Scaled size mismatch"); throw new Exception("Scaled size mismatch");
byte [] bmpbuf=tjd.decompress(scaledw, 0, scaledh, pf, flags); if(bi)
{
img=new BufferedImage(scaledw, scaledh, biType[pf]);
tjd.decompress(img, flags);
}
else
bmpbuf=tjd.decompress(scaledw, 0, scaledh, pf, flags);
t=gettime()-t; t=gettime()-t;
if(bi)
{
tempstr=basefilename+"_dec_"+pixformat+"_"
+(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
+"_"+scalefactor+"x"+".png";
File file=new File(tempstr);
ImageIO.write(img, "png", file);
}
if(yuv==YUVDECODE) if(yuv==YUVDECODE)
{ {
if(checkbufyuv(bmpbuf, bmpbuf.length, w, h, subsamp)==1) if(checkbufyuv(bmpbuf, bmpbuf.length, w, h, subsamp)==1)
@@ -536,12 +742,14 @@ public class TJUnitTest {
} }
else else
{ {
if(checkbuf(bmpbuf, scaledw, scaledh, pf, subsamp, scalefactor, flags) if((bi && checkimg(img, pf, subsamp, scalefactor, flags)==1)
==1) || (!bi && checkbuf(bmpbuf, scaledw, scaledh, pf, subsamp, scalefactor,
flags)==1))
System.out.print("Passed."); System.out.print("Passed.");
else else
{ {
System.out.print("FAILED!"); exitstatus=-1; System.out.print("FAILED!"); exitstatus=-1;
if(bmpbuf!=null)
dumpbuf(bmpbuf, scaledw, scaledh, pf, scalefactor, flags); dumpbuf(bmpbuf, scaledw, scaledh, pf, scalefactor, flags);
} }
} }
@@ -669,10 +877,13 @@ public class TJUnitTest {
if(argv[i].substring(0, 1).equalsIgnoreCase("-h") if(argv[i].substring(0, 1).equalsIgnoreCase("-h")
|| argv[i].equalsIgnoreCase("-?")) || argv[i].equalsIgnoreCase("-?"))
usage(); usage();
if(argv[i].equalsIgnoreCase("-bi")) bi=true;
} }
if(bi && doyuv)
throw new Exception("-bi and -yuv cannot be used together.");
if(doyuv) yuv=YUVENCODE; if(doyuv) yuv=YUVENCODE;
dotest(35, 39, _3byteFormats, TJ.SAMP_444, "test"); dotest(35, 39, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_444, "test");
dotest(39, 41, _4byteFormats, TJ.SAMP_444, "test"); dotest(39, 41, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_444, "test");
if(doyuv) if(doyuv)
{ {
dotest(41, 35, _3byteFormats, TJ.SAMP_422, "test"); dotest(41, 35, _3byteFormats, TJ.SAMP_422, "test");
@@ -681,9 +892,9 @@ public class TJUnitTest {
dotest(41, 35, _4byteFormats, TJ.SAMP_420, "test"); dotest(41, 35, _4byteFormats, TJ.SAMP_420, "test");
} }
dotest(35, 39, _onlyGray, TJ.SAMP_GRAY, "test"); dotest(35, 39, _onlyGray, TJ.SAMP_GRAY, "test");
dotest(39, 41, _3byteFormats, TJ.SAMP_GRAY, "test"); dotest(39, 41, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_GRAY, "test");
dotest(41, 35, _4byteFormats, TJ.SAMP_GRAY, "test"); dotest(41, 35, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_GRAY, "test");
if(!doyuv) dotest1(); if(!doyuv && !bi) dotest1();
if(doyuv) if(doyuv)
{ {
yuv=YUVDECODE; yuv=YUVDECODE;
@@ -700,6 +911,7 @@ public class TJUnitTest {
catch(Exception e) catch(Exception e)
{ {
System.out.println(e); System.out.println(e);
exitstatus=-1;
} }
System.exit(exitstatus); System.exit(exitstatus);
} }

View File

@@ -28,6 +28,8 @@
package org.libjpegturbo.turbojpeg; package org.libjpegturbo.turbojpeg;
import java.awt.image.*;
public class TJCompressor { public class TJCompressor {
public TJCompressor() throws Exception { public TJCompressor() throws Exception {
@@ -60,6 +62,50 @@ public class TJCompressor {
flags | TJ.getFlags(bitmapPixelFormat)); flags | TJ.getFlags(bitmapPixelFormat));
} }
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);
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(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));
}
else {
ComponentSampleModel sm =
(ComponentSampleModel)srcImage.getSampleModel();
int pixelSize = sm.getPixelStride();
if(pixelSize != TJ.pixelSize[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));
}
}
public void close() throws Exception { public void close() throws Exception {
destroy(); destroy();
} }
@@ -83,6 +129,10 @@ public class TJCompressor {
int height, int pixelSize, byte [] dstbuf, int jpegSubsamp, int jpegQual, int height, int pixelSize, byte [] dstbuf, int jpegSubsamp, int jpegQual,
int flags) throws Exception; int flags) throws Exception;
private native int compress(int [] srcBuf, int width, int pitch,
int height, byte [] dstbuf, int jpegSubsamp, int jpegQual, int flags)
throws Exception;
static { static {
System.loadLibrary("turbojpeg"); System.loadLibrary("turbojpeg");
} }

View File

@@ -28,6 +28,8 @@
package org.libjpegturbo.turbojpeg; package org.libjpegturbo.turbojpeg;
import java.awt.image.*;
public class TJDecompressor { public class TJDecompressor {
public TJDecompressor() throws Exception { public TJDecompressor() throws Exception {
@@ -66,49 +68,96 @@ public class TJDecompressor {
return jpegSubsamp; return jpegSubsamp;
} }
public int getScaledWidth(int desired_width, int desired_height) public int getScaledWidth(int desiredWidth, int desiredHeight)
throws Exception { throws Exception {
if(jpegWidth < 1 || jpegHeight < 1) if(jpegWidth < 1 || jpegHeight < 1)
throw new Exception("JPEG buffer not initialized"); throw new Exception("JPEG buffer not initialized");
return getScaledWidth(jpegWidth, jpegHeight, desired_width, return getScaledWidth(jpegWidth, jpegHeight, desiredWidth,
desired_height); desiredHeight);
} }
public int getScaledHeight(int output_width, int output_height) public int getScaledHeight(int desiredWidth, int desiredHeight)
throws Exception { throws Exception {
if(jpegWidth < 1 || jpegHeight < 1) if(jpegWidth < 1 || jpegHeight < 1)
throw new Exception("JPEG buffer not initialized"); throw new Exception("JPEG buffer not initialized");
return getScaledHeight(jpegWidth, jpegHeight, output_width, return getScaledHeight(jpegWidth, jpegHeight, desiredWidth,
output_height); desiredHeight);
} }
public void decompress(byte [] dstBuf, int width, int pitch, public void decompress(byte [] dstBuf, int desiredWidth, int pitch,
int height, int pixelFormat, int flags) throws Exception { int desiredHeight, int pixelFormat, int flags) throws Exception {
if(jpegBuf == null) throw new Exception("JPEG buffer not initialized"); if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
decompress(jpegBuf, jpegBufSize, dstBuf, width, pitch, height, decompress(jpegBuf, jpegBufSize, dstBuf, desiredWidth, pitch,
TJ.getPixelSize(pixelFormat), flags | TJ.getFlags(pixelFormat)); desiredHeight, TJ.getPixelSize(pixelFormat),
flags | TJ.getFlags(pixelFormat));
} }
public byte [] decompress(int width, int pitch, int height, public byte [] decompress(int desiredWidth, int pitch, int desiredHeight,
int pixelFormat, int flags) throws Exception { int pixelFormat, int flags) throws Exception {
if(width < 0 || height < 0 || pitch < 0 || pixelFormat < 0 if(desiredWidth < 0 || desiredHeight < 0 || pitch < 0 || pixelFormat < 0
|| pixelFormat >= TJ.NUMPFOPT) || pixelFormat >= TJ.NUMPFOPT || flags < 0)
throw new Exception("Invalid argument in decompress()"); throw new Exception("Invalid argument in decompress()");
int pixelSize = TJ.getPixelSize(pixelFormat); int pixelSize = TJ.getPixelSize(pixelFormat);
int scaledWidth = getScaledWidth(width, height); int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
int scaledHeight = getScaledHeight(width, height); int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
if(pitch == 0) pitch = scaledWidth * pixelSize; if(pitch == 0) pitch = scaledWidth * pixelSize;
int bufSize; int bufSize;
if((flags&TJ.YUV)!=0) if((flags&TJ.YUV)!=0)
bufSize = TJ.bufSizeYUV(width, height, jpegSubsamp); bufSize = TJ.bufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp);
else bufSize = pitch * scaledHeight; else bufSize = pitch * scaledHeight;
byte [] buf = new byte[bufSize]; byte [] buf = new byte[bufSize];
if(jpegBuf == null) throw new Exception("JPEG buffer not initialized"); if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
decompress(jpegBuf, jpegBufSize, buf, width, pitch, height, decompress(jpegBuf, jpegBufSize, buf, desiredWidth, pitch, desiredHeight,
TJ.getPixelSize(pixelFormat), flags | TJ.getFlags(pixelFormat)); TJ.getPixelSize(pixelFormat), flags | TJ.getFlags(pixelFormat));
return buf; 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);
int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
if(scaledWidth != desiredWidth || scaledHeight != desiredHeight)
throw new Exception("BufferedImage dimensions do not match a scaled image size that TurboJPEG is capable of generating.");
int pixelFormat; boolean intPixels=false;
switch(dstImage.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 = dstImage.getRaster();
if(intPixels) {
SinglePixelPackedSampleModel sm =
(SinglePixelPackedSampleModel)dstImage.getSampleModel();
int pitch = sm.getScanlineStride();
DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
int [] buf = db.getData();
decompress(jpegBuf, jpegBufSize, buf, scaledWidth, pitch, scaledHeight,
flags | TJ.getFlags(pixelFormat));
}
else {
ComponentSampleModel sm =
(ComponentSampleModel)dstImage.getSampleModel();
int pixelSize = sm.getPixelStride();
if(pixelSize != TJ.pixelSize[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();
decompress(buf, scaledWidth, pitch, scaledHeight, pixelFormat, flags);
}
}
public void close() throws Exception { public void close() throws Exception {
destroy(); destroy();
} }
@@ -131,14 +180,18 @@ public class TJDecompressor {
throws Exception; throws Exception;
private native void decompress(byte [] srcBuf, int size, byte [] dstBuf, private native void decompress(byte [] srcBuf, int size, byte [] dstBuf,
int width, int pitch, int height, int pixelSize, int flags) int desiredWidth, int pitch, int desiredHeight, int pixelSize, int flags)
throws Exception; throws Exception;
private native int getScaledWidth(int input_width, int input_height, private native void decompress(byte [] srcBuf, int size, int [] dstBuf,
int output_width, int output_height) throws Exception; int desiredWidth, int pitch, int desiredHeight, int flags)
throws Exception;
private native int getScaledHeight(int input_width, int input_height, private native int getScaledWidth(int jpegWidth, int jpegHeight,
int output_width, int output_height) throws Exception; int desiredWidth, int desiredHeight) throws Exception;
private native int getScaledHeight(int jpegWidth, int jpegHeight,
int desiredWidth, int desiredHeight) throws Exception;
static { static {
System.loadLibrary("turbojpeg"); System.loadLibrary("turbojpeg");

View File

@@ -28,9 +28,17 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
* Method: compress * Method: compress
* Signature: ([BIIII[BIII)I * Signature: ([BIIII[BIII)I
*/ */
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
(JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jbyteArray, jint, jint, jint); (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jbyteArray, jint, jint, jint);
/*
* Class: org_libjpegturbo_turbojpeg_TJCompressor
* Method: compress
* Signature: ([IIII[BIII)I
*/
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIII_3BIII
(JNIEnv *, jobject, jintArray, jint, jint, jint, jbyteArray, jint, jint, jint);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -36,9 +36,17 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
* Method: decompress * Method: decompress
* Signature: ([BI[BIIIII)V * Signature: ([BI[BIIIII)V
*/ */
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
(JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint, jint, jint, jint, jint); (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint, jint, jint, jint, jint);
/*
* Class: org_libjpegturbo_turbojpeg_TJDecompressor
* Method: decompress
* Signature: ([BI[IIIII)V
*/
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIII
(JNIEnv *, jobject, jbyteArray, jint, jintArray, jint, jint, jint, jint);
/* /*
* Class: org_libjpegturbo_turbojpeg_TJDecompressor * Class: org_libjpegturbo_turbojpeg_TJDecompressor
* Method: getScaledWidth * Method: getScaledWidth

View File

@@ -86,7 +86,7 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
return; return;
} }
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
(JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch, (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
jint height, jint pixelsize, jbyteArray dst, jint jpegsubsamp, jint height, jint pixelsize, jbyteArray dst, jint jpegsubsamp,
jint jpegqual, jint flags) jint jpegqual, jint flags)
@@ -114,6 +114,33 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress
return (jint)size; return (jint)size;
} }
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIII_3BIII
(JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch,
jint height, jbyteArray dst, jint jpegsubsamp, jint jpegqual, jint flags)
{
tjhandle handle=0;
unsigned long size=0;
unsigned char *srcbuf=NULL, *dstbuf=NULL;
gethandle();
bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
if(tjCompress(handle, srcbuf, width, pitch*sizeof(jint), height,
sizeof(jint), dstbuf, &size, jpegsubsamp, jpegqual, flags)==-1)
{
(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
_throw(tjGetErrorStr());
}
bailout:
if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
return (jint)size;
}
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
(JNIEnv *env, jobject obj) (JNIEnv *env, jobject obj)
{ {
@@ -199,7 +226,7 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
return; return;
} }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
(JNIEnv *env, jobject obj, jbyteArray src, jint size, jbyteArray dst, (JNIEnv *env, jobject obj, jbyteArray src, jint size, jbyteArray dst,
jint width, jint pitch, jint height, jint pixelsize, jint flags) jint width, jint pitch, jint height, jint pixelsize, jint flags)
{ {
@@ -225,6 +252,33 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress
return; return;
} }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIII
(JNIEnv *env, jobject obj, jbyteArray src, jint size, jintArray dst,
jint width, jint pitch, jint height, jint flags)
{
tjhandle handle=0;
unsigned char *srcbuf=NULL, *dstbuf=NULL;
gethandle();
bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
if(tjDecompress(handle, srcbuf, (unsigned long)size, dstbuf, width,
pitch*sizeof(jint), height, sizeof(jint), flags)==-1)
{
(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
_throw(tjGetErrorStr());
}
bailout:
if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
return;
}
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
(JNIEnv *env, jobject obj) (JNIEnv *env, jobject obj)
{ {

View File

@@ -14,11 +14,13 @@
Java_org_libjpegturbo_turbojpeg_TJ_bufSize; Java_org_libjpegturbo_turbojpeg_TJ_bufSize;
Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV; Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV;
Java_org_libjpegturbo_turbojpeg_TJCompressor_init; Java_org_libjpegturbo_turbojpeg_TJCompressor_init;
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress; Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII;
Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIII_3BIII;
Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy; Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_init; Java_org_libjpegturbo_turbojpeg_TJDecompressor_init;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader; Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress; Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIII;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy; Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledHeight; Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledHeight;
Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledWidth; Java_org_libjpegturbo_turbojpeg_TJDecompressor_getScaledWidth;