Implemted thumbnail support.

This commit is contained in:
Harald Kuhr 2009-10-02 18:53:45 +02:00
parent 1a67e1721e
commit a86cf5bf15
2 changed files with 113 additions and 20 deletions

View File

@ -95,7 +95,11 @@ public class PSDImageReader extends ImageReaderBase {
} }
@Override @Override
public ImageTypeSpecifier getRawImageType(int pIndex) throws IOException { public ImageTypeSpecifier getRawImageType(final int pIndex) throws IOException {
return getRawImageTypeInternal(pIndex);
}
private ImageTypeSpecifier getRawImageTypeInternal(final int pIndex) throws IOException {
checkBounds(pIndex); checkBounds(pIndex);
readHeader(); readHeader();
@ -193,7 +197,7 @@ public class PSDImageReader extends ImageReaderBase {
// Could use similar concept to create lazily-created ImageTypeSpecifiers (util candidate, based on FilterIterator?) // Could use similar concept to create lazily-created ImageTypeSpecifiers (util candidate, based on FilterIterator?)
// Get the raw type. Will fail for unsupported types // Get the raw type. Will fail for unsupported types
ImageTypeSpecifier rawType = getRawImageType(pIndex); ImageTypeSpecifier rawType = getRawImageTypeInternal(pIndex);
ColorSpace cs = rawType.getColorModel().getColorSpace(); ColorSpace cs = rawType.getColorModel().getColorSpace();
List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>(); List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>();
@ -264,18 +268,19 @@ public class PSDImageReader extends ImageReaderBase {
return mColorSpace; return mColorSpace;
} }
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException { public BufferedImage read(final int pIndex, final ImageReadParam pParam) throws IOException {
checkBounds(pIndex); checkBounds(pIndex);
readHeader(); readHeader();
processImageStarted(pIndex);
readImageResources(false); readImageResources(false);
readLayerAndMaskInfo(false); readLayerAndMaskInfo(false);
// TODO: Test if explicit destination is compatible or throw IllegalArgumentException
BufferedImage image = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight); BufferedImage image = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight);
processImageStarted(pIndex);
final Rectangle source = new Rectangle(); final Rectangle source = new Rectangle();
final Rectangle dest = new Rectangle(); final Rectangle dest = new Rectangle();
computeRegions(pParam, mHeader.mWidth, mHeader.mHeight, image, source, dest); computeRegions(pParam, mHeader.mWidth, mHeader.mHeight, image, source, dest);
@ -339,19 +344,7 @@ public class PSDImageReader extends ImageReaderBase {
throw new IIOException("Unknown compression type: " + compression); throw new IIOException("Unknown compression type: " + compression);
} }
switch (mHeader.mBits) { readImageData(image, source, dest, xSub, ySub, offsets, compression);
case 1:
read1bitData(image.getRaster(), image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
break;
case 8:
read8bitData(image.getRaster(), image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
break;
case 16:
read16bitData(image.getRaster(), image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
break;
default:
throw new IIOException("Unknown bit depth: " + mHeader.mBits);
}
if (abortRequested()) { if (abortRequested()) {
processReadAborted(); processReadAborted();
@ -363,11 +356,31 @@ public class PSDImageReader extends ImageReaderBase {
return image; return image;
} }
private void readImageData(final BufferedImage pImage,
final Rectangle pSource, final Rectangle pDest,
final int pXSub, final int pYSub,
final int[] pOffsets, final int pCompression) throws IOException {
// TODO: Refactor so that we loop through channels here, and read one channel in each of the methods below
switch (mHeader.mBits) {
case 1:
read1bitData(pImage.getRaster(), pImage.getColorModel(), pSource, pDest, pXSub, pYSub, pOffsets, pCompression == PSD.COMPRESSION_RLE);
break;
case 8:
read8bitData(pImage.getRaster(), pImage.getColorModel(), pSource, pDest, pXSub, pYSub, pOffsets, pCompression == PSD.COMPRESSION_RLE);
break;
case 16:
read16bitData(pImage.getRaster(), pImage.getColorModel(), pSource, pDest, pXSub, pYSub, pOffsets, pCompression == PSD.COMPRESSION_RLE);
break;
default:
throw new IIOException("Unknown bit depth: " + mHeader.mBits);
}
}
private void read16bitData(final WritableRaster pRaster, final ColorModel pDestinationColorModel, private void read16bitData(final WritableRaster pRaster, final ColorModel pDestinationColorModel,
final Rectangle pSource, final Rectangle pDest, final Rectangle pSource, final Rectangle pDest,
final int pXSub, final int pYSub, final int pXSub, final int pYSub,
final int[] pRowOffsets, final boolean pRLECompressed) throws IOException final int[] pRowOffsets, final boolean pRLECompressed) throws IOException {
{
final int channels = pRaster.getNumBands(); final int channels = pRaster.getNumBands();
// TODO: FixMe: Use real source color model from native (raw) image type, and convert if needed // TODO: FixMe: Use real source color model from native (raw) image type, and convert if needed
@ -872,6 +885,78 @@ public class PSDImageReader extends ImageReaderBase {
} }
} }
/// Thumbnail support
@Override
public boolean readerSupportsThumbnails() {
return true;
}
private List<PSDThumbnail> getThumbnailResources(final int pIndex) throws IOException {
checkBounds(pIndex);
readHeader();
List<PSDThumbnail> thumbnails = null;
if (mImageResources != null) {
// TODO: Need flag here, to specify what resources to read...
readImageResources(true);
// TODO: Skip this, requires storing some stream offsets
readLayerAndMaskInfo(false);
for (PSDImageResource resource : mImageResources) {
if (resource instanceof PSDThumbnail) {
if (thumbnails == null) {
thumbnails = new ArrayList<PSDThumbnail>();
}
thumbnails.add((PSDThumbnail) resource);
}
}
}
return thumbnails;
}
@Override
public int getNumThumbnails(int pIndex) throws IOException {
List<PSDThumbnail> thumbnails = getThumbnailResources(pIndex);
if (thumbnails == null) {
return 0;
}
return thumbnails.size();
}
@Override
public int getThumbnailWidth(int imageIndex, int thumbnailIndex) throws IOException {
// TODO: We could get this without decoding the thumbnail first
return super.getThumbnailWidth(imageIndex, thumbnailIndex);
}
@Override
public int getThumbnailHeight(int imageIndex, int thumbnailIndex) throws IOException {
// TODO: We could get this without decoding the thumbnail first
return super.getThumbnailHeight(imageIndex, thumbnailIndex);
}
@Override
public BufferedImage readThumbnail(int pImageIndex, int pThumbnailIndex) throws IOException {
// TODO: Thumbnail listeners...
List<PSDThumbnail> thumbnails = getThumbnailResources(pImageIndex);
if (thumbnails == null) {
throw new IndexOutOfBoundsException(String.format("%d > 0", pThumbnailIndex));
}
// TODO: Defer decoding
// TODO: It's possible to attach listeners to the ImageIO reader delegate... But do we really care?
processThumbnailStarted(pImageIndex, pThumbnailIndex);
processThumbnailComplete();
return thumbnails.get(pThumbnailIndex).getThumbnail();
}
/// Functional testing
public static void main(final String[] pArgs) throws IOException { public static void main(final String[] pArgs) throws IOException {
int subsampleFactor = 1; int subsampleFactor = 1;
Rectangle sourceRegion = null; Rectangle sourceRegion = null;
@ -924,6 +1009,13 @@ public class PSDImageReader extends ImageReaderBase {
System.out.println("imageReader.mLayerInfo: " + imageReader.mLayerInfo); System.out.println("imageReader.mLayerInfo: " + imageReader.mLayerInfo);
System.out.println("imageReader.mGlobalLayerMask: " + imageReader.mGlobalLayerMask); System.out.println("imageReader.mGlobalLayerMask: " + imageReader.mGlobalLayerMask);
if (imageReader.hasThumbnails(0)) {
int thumbnails = imageReader.getNumThumbnails(0);
for (int i = 0; i < thumbnails; i++) {
showIt(imageReader.readThumbnail(0, i), String.format("Thumbnail %d", i));
}
}
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
ImageReadParam param = imageReader.getDefaultReadParam(); ImageReadParam param = imageReader.getDefaultReadParam();

View File

@ -65,6 +65,7 @@ class PSDThumbnail extends PSDImageResource {
// TODO: Warning/Exception // TODO: Warning/Exception
} }
// TODO: Defer decoding until getThumbnail?
// TODO: Support BGR if id == RES_THUMBNAIL_PS4? Or is that already supported in the JPEG? // TODO: Support BGR if id == RES_THUMBNAIL_PS4? Or is that already supported in the JPEG?
mThumbnail = ImageIO.read(IIOUtil.createStreamAdapter(pInput, sizeCompressed)); mThumbnail = ImageIO.read(IIOUtil.createStreamAdapter(pInput, sizeCompressed));
} }