/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.jpeg; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import javax.imageio.IIOException; import javax.imageio.ImageReadParam; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.weasis.image.jni.InputStreamAdapter; import org.weasis.image.jni.NativeCodec; import org.weasis.image.jni.NativeImage; import org.weasis.image.jni.NativeImageReader; import org.weasis.image.jni.StreamSegment; import org.weasis.jpeg.internal.JpegCodec; import com.sun.media.imageioimpl.common.SignedDataImageParam; import com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGMetadata; class NativeJPEGImageReader extends NativeImageReader { private static final Logger LOGGER = LoggerFactory.getLogger(NativeJPEGImageReader.class); private IIOMetadata imageMetadata = null; private int imageMetadataIndex = -1; NativeJPEGImageReader(ImageReaderSpi originatingProvider) { super(originatingProvider); } @Override protected NativeCodec getCodec() { return new JpegCodec(); } @Override protected final synchronized NativeImage nativeDecode(InputStream stream, ImageReadParam param, int imageIndex) throws IOException { ImageInputStream iis = null; if (stream instanceof InputStreamAdapter) { iis = ((InputStreamAdapter) stream).getWrappedStream(); } NativeImage mlImage = nativeImages.get(imageIndex); try { NativeCodec decoder = getCodec(); if (mlImage == null) { mlImage = decoder.buildImage(iis); } if (param instanceof SignedDataImageParam) { mlImage.getImageParameters().setSignedData(((SignedDataImageParam) param).isSignedData()); } StreamSegment.adaptParametersFromStream(iis, mlImage); long start = System.currentTimeMillis(); String error = decoder.decompress(mlImage, param); // TODO Get the ICC profile data. if (error != null) { throw new IIOException("Native JPEG codec error: " + error); } long stop = System.currentTimeMillis(); LOGGER.debug("Reading image time (native codec): {} ms", (stop - start)); //$NON-NLS-1$ // Free native resources. decoder.dispose(); } catch (Throwable t) { if (LOGGER.isDebugEnabled()) { LOGGER.error("Native JPEG codec error", t); //$NON-NLS-1$ } throw new IIOException("Native JPEG codec error", t); } LOGGER.debug("Parameters => {}", mlImage.getImageParameters().toString()); return mlImage; } @Override protected boolean skipImage(int index) throws IOException { boolean retval = false; if (input == null) { throw new IllegalStateException("input cannot be null"); } InputStream stream = null; if (input instanceof ImageInputStream) { stream = new InputStreamAdapter((ImageInputStream) input); } else { throw new IllegalArgumentException("input is not an ImageInputStream!"); } retval = nativeDecode(stream, null, index) != null; if (retval) { long pos = ((ImageInputStream) input).getStreamPosition(); if (pos > highMark) { highMark = pos; } } return retval; } @Override public synchronized IIOMetadata getImageMetadata(int imageIndex) throws IOException { if (input == null) { throw new IllegalStateException("input cannot be null"); } if (imageMetadata == null || imageIndex != imageMetadataIndex) { seekToImage(imageIndex); ImageInputStream stream = (ImageInputStream) input; long pos = stream.getStreamPosition(); try { imageMetadata = new CLibJPEGMetadata(stream); imageMetadataIndex = imageIndex; } catch (IIOException e) { throw e; } finally { stream.seek(pos); } } return imageMetadata; } @Override public boolean readerSupportsThumbnails() { return true; } @Override public int getNumThumbnails(int imageIndex) throws IOException { CLibJPEGMetadata metadata = (CLibJPEGMetadata) getImageMetadata(imageIndex); return metadata.getNumThumbnails(); } @Override public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) throws IOException { CLibJPEGMetadata metadata = (CLibJPEGMetadata) getImageMetadata(imageIndex); return metadata.getThumbnail(thumbnailIndex); } @Override protected void resetLocal() { imageMetadata = null; imageMetadataIndex = -1; super.resetLocal(); } }