14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.javafx.iio.jpeg;
27
28 import com.sun.javafx.iio.ImageFrame;
29 import com.sun.javafx.iio.ImageMetadata;
30 import com.sun.javafx.iio.ImageStorage.ImageType;
31 import com.sun.glass.utils.NativeLibLoader;
32 import com.sun.javafx.iio.common.ImageLoaderImpl;
33 import com.sun.javafx.iio.common.ImageTools;
34 import com.sun.javafx.iio.common.PushbroomScaler;
35 import com.sun.javafx.iio.common.ScalerFactory;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.nio.ByteBuffer;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41
42 public class JPEGImageLoader extends ImageLoaderImpl {
43
44 // IJG Color codes.
45 public static final int JCS_UNKNOWN = 0; // error/unspecified
46 public static final int JCS_GRAYSCALE = 1; // monochrome
47 public static final int JCS_RGB = 2; // red/green/blue
48 public static final int JCS_YCbCr = 3; // Y/Cb/Cr (also known as YUV)
49 public static final int JCS_CMYK = 4; // C/M/Y/K
50 public static final int JCS_YCC = 5; // PhotoYCC
51 public static final int JCS_RGBA = 6; // RGB-Alpha
52 public static final int JCS_YCbCrA = 7; // Y/Cb/Cr/Alpha
53 // 8 and 9 were old "Legacy" codes which the old code never identified
54 // on reading anyway. Support for writing them is being dropped, too.
55 public static final int JCS_YCCA = 10; // PhotoYCC-Alpha
206 }
207
208 protected void finalize() {
209 dispose();
210 }
211
212 public ImageFrame load(int imageIndex, int width, int height, boolean preserveAspectRatio, boolean smooth) throws IOException {
213 if (imageIndex != 0) {
214 return null;
215 }
216
217 accessLock.lock();
218
219 // Determine output image dimensions.
220 int[] widthHeight = ImageTools.computeDimensions(inWidth, inHeight, width, height, preserveAspectRatio);
221 width = widthHeight[0];
222 height = widthHeight[1];
223
224 ImageMetadata md = new ImageMetadata(null, true,
225 null, null, null, null, null,
226 inWidth, inHeight, null, null, null);
227
228 updateImageMetadata(md);
229
230 ByteBuffer buffer = null;
231
232 int outNumComponents;
233 try {
234 outNumComponents = startDecompression(structPointer,
235 outColorSpaceCode, width, height);
236
237 // Uncomment next line for direct ByteBuffer.
238 //buffer = decompressDirect(structPointer, listeners != null && !listeners.isEmpty());
239 // Comment out next three lines to suppress indirect ByteBuffers.
240 byte[] array = new byte[outWidth*outHeight*outNumComponents];
241 buffer = ByteBuffer.wrap(array);
242 decompressIndirect(structPointer, listeners != null && !listeners.isEmpty(), buffer.array());
243 } catch (IOException e) {
244 throw e;
245 } finally {
246 accessLock.unlock();
247 dispose();
248 }
249
250 if (buffer == null) {
251 throw new IOException("Error decompressing JPEG stream!");
252 }
253
254 ImageFrame frame = null;
255
256 // Check whether the decompressed image has been scaled to the correct
257 // dimensions. If not, downscalte it here. Note outData, outHeight, and
258 // outWidth refer to the image as returned by the decompressor. This
259 // image might have been downscaled from the original source by a factor
260 // of N/8 where 1 <= N <=8.
261 if (outWidth != width || outHeight != height) {
262 // Get the decompressed data array. Note that the code really should
263 // be moidified to use direct buffers if and only if this post-
264 // decompression scaling will NOT occur.
265 byte[] outData;
266 if (buffer.hasArray()) {
267 outData = buffer.array();
268 } else {
269 outData = new byte[buffer.capacity()];
270 buffer.get(outData);
271 }
272
273 PushbroomScaler scaler = ScalerFactory.createScaler(outWidth, outHeight,
274 outNumComponents, width, height, smooth);
275 int stride = outWidth * outNumComponents;
276 int off = 0;
277 for (int y = 0; y < outHeight; y++) {
278 if (scaler.putSourceScanline(outData, off)) {
279 break;
280 }
281 off += stride;
282 }
283 buffer = scaler.getDestination();
284 frame = new ImageFrame(outImageType, buffer,
285 width, height, width * outNumComponents, null, md);
286 }
287 else {
288 frame = new ImageFrame(outImageType, buffer,
289 outWidth, outHeight, outWidth * outNumComponents, null, md);
290 }
291
292 return frame;
293 }
294
295 private static class Lock {
296 private boolean locked;
297
298 public Lock() {
299 locked = false;
300 }
301
302 public synchronized boolean isLocked() {
303 return locked;
304 }
305
306 public synchronized void lock() {
307 if (locked) {
308 throw new IllegalStateException("Recursive loading is not allowed.");
309 }
310 locked = true;
311 }
312
|
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.javafx.iio.jpeg;
27
28 import com.sun.javafx.iio.ImageFrame;
29 import com.sun.javafx.iio.ImageMetadata;
30 import com.sun.javafx.iio.ImageStorage.ImageType;
31 import com.sun.glass.utils.NativeLibLoader;
32 import com.sun.javafx.iio.common.ImageLoaderImpl;
33 import com.sun.javafx.iio.common.ImageTools;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.nio.ByteBuffer;
37 import java.security.AccessController;
38 import java.security.PrivilegedAction;
39
40 public class JPEGImageLoader extends ImageLoaderImpl {
41
42 // IJG Color codes.
43 public static final int JCS_UNKNOWN = 0; // error/unspecified
44 public static final int JCS_GRAYSCALE = 1; // monochrome
45 public static final int JCS_RGB = 2; // red/green/blue
46 public static final int JCS_YCbCr = 3; // Y/Cb/Cr (also known as YUV)
47 public static final int JCS_CMYK = 4; // C/M/Y/K
48 public static final int JCS_YCC = 5; // PhotoYCC
49 public static final int JCS_RGBA = 6; // RGB-Alpha
50 public static final int JCS_YCbCrA = 7; // Y/Cb/Cr/Alpha
51 // 8 and 9 were old "Legacy" codes which the old code never identified
52 // on reading anyway. Support for writing them is being dropped, too.
53 public static final int JCS_YCCA = 10; // PhotoYCC-Alpha
204 }
205
206 protected void finalize() {
207 dispose();
208 }
209
210 public ImageFrame load(int imageIndex, int width, int height, boolean preserveAspectRatio, boolean smooth) throws IOException {
211 if (imageIndex != 0) {
212 return null;
213 }
214
215 accessLock.lock();
216
217 // Determine output image dimensions.
218 int[] widthHeight = ImageTools.computeDimensions(inWidth, inHeight, width, height, preserveAspectRatio);
219 width = widthHeight[0];
220 height = widthHeight[1];
221
222 ImageMetadata md = new ImageMetadata(null, true,
223 null, null, null, null, null,
224 width, height, null, null, null);
225
226 updateImageMetadata(md);
227
228 ByteBuffer buffer = null;
229
230 int outNumComponents;
231 try {
232 outNumComponents = startDecompression(structPointer,
233 outColorSpaceCode, width, height);
234
235 // Uncomment next line for direct ByteBuffer.
236 //buffer = decompressDirect(structPointer, listeners != null && !listeners.isEmpty());
237 // Comment out next three lines to suppress indirect ByteBuffers.
238 byte[] array = new byte[outWidth*outHeight*outNumComponents];
239 buffer = ByteBuffer.wrap(array);
240 decompressIndirect(structPointer, listeners != null && !listeners.isEmpty(), buffer.array());
241 } catch (IOException e) {
242 throw e;
243 } finally {
244 accessLock.unlock();
245 dispose();
246 }
247
248 if (buffer == null) {
249 throw new IOException("Error decompressing JPEG stream!");
250 }
251
252 // Check whether the decompressed image has been scaled to the correct
253 // dimensions. If not, downscale it here. Note outData, outHeight, and
254 // outWidth refer to the image as returned by the decompressor. This
255 // image might have been downscaled from the original source by a factor
256 // of N/8 where 1 <= N <=8.
257 if (outWidth != width || outHeight != height) {
258 buffer = ImageTools.scaleImage(buffer,
259 outWidth, outHeight, outNumComponents, width, height, smooth);
260 }
261
262 return new ImageFrame(outImageType, buffer,
263 width, height, width * outNumComponents, null, md);
264 }
265
266 private static class Lock {
267 private boolean locked;
268
269 public Lock() {
270 locked = false;
271 }
272
273 public synchronized boolean isLocked() {
274 return locked;
275 }
276
277 public synchronized void lock() {
278 if (locked) {
279 throw new IllegalStateException("Recursive loading is not allowed.");
280 }
281 locked = true;
282 }
283
|