TJDecompressor.java revision 4f1580cc0e7c33385e88bca7fe08602b87d29aeb
1/* 2 * Copyright (C)2011 D. R. Commander. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * - Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * - Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * - Neither the name of the libjpeg-turbo Project nor the names of its 13 * contributors may be used to endorse or promote products derived from this 14 * software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29package org.libjpegturbo.turbojpeg; 30 31import java.awt.image.*; 32 33public class TJDecompressor { 34 35 public TJDecompressor() throws Exception { 36 init(); 37 } 38 39 public TJDecompressor(byte [] buf) throws Exception { 40 setJPEGBuffer(buf, buf.length); 41 } 42 43 public TJDecompressor(byte [] buf, int bufSize) throws Exception { 44 setJPEGBuffer(buf, bufSize); 45 } 46 47 public void setJPEGBuffer(byte [] buf, int bufSize) throws Exception { 48 if(handle == 0) init(); 49 if(buf == null || bufSize < 1) 50 throw new Exception("Invalid argument in setJPEGBuffer()"); 51 jpegBuf = buf; 52 jpegBufSize = bufSize; 53 decompressHeader(jpegBuf, jpegBufSize); 54 } 55 56 public int getWidth() throws Exception { 57 if(jpegWidth < 1) throw new Exception("JPEG buffer not initialized"); 58 return jpegWidth; 59 } 60 61 public int getHeight() throws Exception { 62 if(jpegHeight < 1) throw new Exception("JPEG buffer not initialized"); 63 return jpegHeight; 64 } 65 66 public int getSubsamp() throws Exception { 67 if(jpegSubsamp < 0) throw new Exception("JPEG buffer not initialized"); 68 if(jpegSubsamp >= TJ.NUMSAMPOPT) 69 throw new Exception("JPEG header information is invalid"); 70 return jpegSubsamp; 71 } 72 73 public int getScaledWidth(int desiredWidth, int desiredHeight) 74 throws Exception { 75 if(jpegWidth < 1 || jpegHeight < 1) 76 throw new Exception("JPEG buffer not initialized"); 77 if(desiredWidth < 0 || desiredHeight < 0) 78 throw new Exception("Invalid argument in getScaledWidth()"); 79 return getScaledWidth(jpegWidth, jpegHeight, desiredWidth, 80 desiredHeight); 81 } 82 83 public int getScaledHeight(int desiredWidth, int desiredHeight) 84 throws Exception { 85 if(jpegWidth < 1 || jpegHeight < 1) 86 throw new Exception("JPEG buffer not initialized"); 87 if(desiredWidth < 0 || desiredHeight < 0) 88 throw new Exception("Invalid argument in getScaledHeight()"); 89 return getScaledHeight(jpegWidth, jpegHeight, desiredWidth, 90 desiredHeight); 91 } 92 93 public void decompress(byte [] dstBuf, int desiredWidth, int pitch, 94 int desiredHeight, int pixelFormat, int flags) throws Exception { 95 if(jpegBuf == null) throw new Exception("JPEG buffer not initialized"); 96 if(dstBuf == null || desiredWidth < 0 || pitch < 0 || desiredHeight < 0 97 || pixelFormat < 0 || pixelFormat >= TJ.NUMPFOPT || flags < 0) 98 throw new Exception("Invalid argument in decompress()"); 99 decompress(jpegBuf, jpegBufSize, dstBuf, desiredWidth, pitch, 100 desiredHeight, pixelFormat, flags); 101 } 102 103 public byte [] decompress(int desiredWidth, int pitch, int desiredHeight, 104 int pixelFormat, int flags) throws Exception { 105 if(desiredWidth < 0 || pitch < 0 || desiredHeight < 0 106 || pixelFormat < 0 || pixelFormat >= TJ.NUMPFOPT || flags < 0) 107 throw new Exception("Invalid argument in decompress()"); 108 int pixelSize = TJ.getPixelSize(pixelFormat); 109 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight); 110 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight); 111 if(pitch == 0) pitch = scaledWidth * pixelSize; 112 byte [] buf = new byte[pitch * scaledHeight]; 113 decompress(buf, desiredWidth, pitch, desiredHeight, pixelFormat, flags); 114 return buf; 115 } 116 117 public void decompressToYUV(byte [] dstBuf, int flags) throws Exception { 118 if(jpegBuf == null) throw new Exception("JPEG buffer not initialized"); 119 if(dstBuf == null || flags < 0) 120 throw new Exception("Invalid argument in decompressToYUV()"); 121 decompressToYUV(jpegBuf, jpegBufSize, dstBuf, flags); 122 } 123 124 public byte [] decompressToYUV(int flags) throws Exception { 125 if(flags < 0) 126 throw new Exception("Invalid argument in decompressToYUV()"); 127 if(jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0) 128 throw new Exception("JPEG buffer not initialized"); 129 if(jpegSubsamp >= TJ.NUMSAMPOPT) 130 throw new Exception("JPEG header information is invalid"); 131 byte [] buf = new byte[TJ.bufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp)]; 132 decompressToYUV(buf, flags); 133 return buf; 134 } 135 136 public void decompress(BufferedImage dstImage, int flags) throws Exception { 137 if(dstImage == null || flags < 0) 138 throw new Exception("Invalid argument in decompress()"); 139 int desiredWidth = dstImage.getWidth(); 140 int desiredHeight = dstImage.getHeight(); 141 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight); 142 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight); 143 if(scaledWidth != desiredWidth || scaledHeight != desiredHeight) 144 throw new Exception("BufferedImage dimensions do not match a scaled image size that TurboJPEG is capable of generating."); 145 int pixelFormat; boolean intPixels=false; 146 switch(dstImage.getType()) { 147 case BufferedImage.TYPE_3BYTE_BGR: 148 pixelFormat=TJ.PF_BGR; break; 149 case BufferedImage.TYPE_BYTE_GRAY: 150 pixelFormat=TJ.PF_GRAY; break; 151 case BufferedImage.TYPE_INT_BGR: 152 pixelFormat=TJ.PF_RGBX; intPixels=true; break; 153 case BufferedImage.TYPE_INT_RGB: 154 pixelFormat=TJ.PF_BGRX; intPixels=true; break; 155 default: 156 throw new Exception("Unsupported BufferedImage format"); 157 } 158 WritableRaster wr = dstImage.getRaster(); 159 if(intPixels) { 160 SinglePixelPackedSampleModel sm = 161 (SinglePixelPackedSampleModel)dstImage.getSampleModel(); 162 int pitch = sm.getScanlineStride(); 163 DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); 164 int [] buf = db.getData(); 165 if(jpegBuf == null) throw new Exception("JPEG buffer not initialized"); 166 decompress(jpegBuf, jpegBufSize, buf, scaledWidth, pitch, scaledHeight, 167 pixelFormat, flags); 168 } 169 else { 170 ComponentSampleModel sm = 171 (ComponentSampleModel)dstImage.getSampleModel(); 172 int pixelSize = sm.getPixelStride(); 173 if(pixelSize != TJ.getPixelSize(pixelFormat)) 174 throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage"); 175 int pitch = sm.getScanlineStride(); 176 DataBufferByte db = (DataBufferByte)wr.getDataBuffer(); 177 byte [] buf = db.getData(); 178 decompress(buf, scaledWidth, pitch, scaledHeight, pixelFormat, flags); 179 } 180 } 181 182 public BufferedImage decompress(int desiredWidth, int desiredHeight, 183 int bufferedImageType, int flags) throws Exception { 184 if(desiredWidth < 0 || desiredHeight < 0 || flags < 0) 185 throw new Exception("Invalid argument in decompress()"); 186 int scaledWidth = getScaledWidth(desiredWidth, desiredHeight); 187 int scaledHeight = getScaledHeight(desiredWidth, desiredHeight); 188 BufferedImage img = new BufferedImage(scaledWidth, scaledHeight, 189 bufferedImageType); 190 decompress(img, flags); 191 return img; 192 } 193 194 public void close() throws Exception { 195 destroy(); 196 } 197 198 protected void finalize() throws Throwable { 199 try { 200 close(); 201 } catch(Exception e) { 202 } 203 finally { 204 super.finalize(); 205 } 206 }; 207 208 private native void init() throws Exception; 209 210 private native void destroy() throws Exception; 211 212 private native void decompressHeader(byte [] srcBuf, int size) 213 throws Exception; 214 215 private native void decompress(byte [] srcBuf, int size, byte [] dstBuf, 216 int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags) 217 throws Exception; 218 219 private native void decompress(byte [] srcBuf, int size, int [] dstBuf, 220 int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags) 221 throws Exception; 222 223 private native void decompressToYUV(byte [] srcBuf, int size, byte [] dstBuf, 224 int flags) 225 throws Exception; 226 227 private native int getScaledWidth(int jpegWidth, int jpegHeight, 228 int desiredWidth, int desiredHeight) throws Exception; 229 230 private native int getScaledHeight(int jpegWidth, int jpegHeight, 231 int desiredWidth, int desiredHeight) throws Exception; 232 233 static { 234 System.loadLibrary("turbojpeg"); 235 } 236 237 private long handle = 0; 238 private byte [] jpegBuf = null; 239 private int jpegBufSize = 0; 240 private int jpegWidth = 0; 241 private int jpegHeight = 0; 242 private int jpegSubsamp = -1; 243}; 244