mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
Added subsampled reading to RLE encoded images. Still work to do.
This commit is contained in:
parent
7ef607815e
commit
cac1212944
@ -32,16 +32,14 @@ import com.twelvemonkeys.image.ImageUtil;
|
|||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.util.IndexedImageTypeSpecifier;
|
import com.twelvemonkeys.imageio.util.IndexedImageTypeSpecifier;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.*;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.color.ICC_ColorSpace;
|
import java.awt.color.ICC_ColorSpace;
|
||||||
import java.awt.color.ICC_Profile;
|
import java.awt.color.ICC_Profile;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
import java.awt.*;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -85,19 +83,22 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
mColorSpace = null;
|
mColorSpace = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth(int pIndex) throws IOException {
|
public int getWidth(final int pIndex) throws IOException {
|
||||||
checkBounds(pIndex);
|
checkBounds(pIndex);
|
||||||
readHeader();
|
readHeader();
|
||||||
return mHeader.mWidth;
|
return mHeader.mWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight(int pIndex) throws IOException {
|
public int getHeight(final int pIndex) throws IOException {
|
||||||
checkBounds(pIndex);
|
checkBounds(pIndex);
|
||||||
readHeader();
|
readHeader();
|
||||||
return mHeader.mHeight;
|
return mHeader.mHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
|
public Iterator<ImageTypeSpecifier> getImageTypes(final int pIndex) throws IOException {
|
||||||
|
// TODO: Check out the custom ImageTypeIterator and ImageTypeProducer used in the Sun provided JPEGImageReader
|
||||||
|
// Could use similar concept to create lazily-created ImageTypeSpecifiers (util candidate, based on FilterIterator?)
|
||||||
|
|
||||||
checkBounds(pIndex);
|
checkBounds(pIndex);
|
||||||
readHeader();
|
readHeader();
|
||||||
|
|
||||||
@ -205,6 +206,28 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
readLayerAndMaskInfo(false);
|
readLayerAndMaskInfo(false);
|
||||||
|
|
||||||
BufferedImage image = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight);
|
BufferedImage image = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight);
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: It seems safe to just leave this out for now. The only thing we need is to support sub sampling.
|
||||||
|
Sun's readers does not support arbitrary destination formats.
|
||||||
|
|
||||||
|
// TODO: Create temp raster in native format w * 1
|
||||||
|
// Read (sub-sampled) row into temp raster (skip other rows)
|
||||||
|
// If color model (color space) is not RGB, do color convert op
|
||||||
|
// Otherwise, copy "through" ColorMode?l
|
||||||
|
// Copy pixels from temp raster
|
||||||
|
// If possible, leave the destination image "untouched" (accelerated)
|
||||||
|
// TODO: Banding...
|
||||||
|
|
||||||
|
ImageTypeSpecifier spec = getRawImageType(pIndex);
|
||||||
|
BufferedImage temp = spec.createBufferedImage(getWidth(pIndex), 1);
|
||||||
|
temp.getRaster();
|
||||||
|
|
||||||
|
if (...)
|
||||||
|
ColorConvertOp convert = new ColorConvertOp(...);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// TODO: Should do color convert op for CMYK -> RGB
|
// TODO: Should do color convert op for CMYK -> RGB
|
||||||
ColorModel cm = image.getColorModel();
|
ColorModel cm = image.getColorModel();
|
||||||
final boolean isCMYK = cm.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
|
final boolean isCMYK = cm.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
|
||||||
@ -214,17 +237,38 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
if (!(raster.getDataBuffer() instanceof DataBufferByte)) {
|
if (!(raster.getDataBuffer() instanceof DataBufferByte)) {
|
||||||
throw new IIOException("Unsupported raster type: " + raster);
|
throw new IIOException("Unsupported raster type: " + raster);
|
||||||
}
|
}
|
||||||
byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
|
||||||
|
|
||||||
// TODO: Maybe a banded raster would be easier than interleaved?
|
// TODO: Maybe a banded raster would be easier than interleaved? We could still convert to interleaved in CCOp
|
||||||
final int channels = raster.getNumBands();
|
final int channels = raster.getNumBands();
|
||||||
|
|
||||||
|
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
||||||
|
final byte[] line = new byte[mHeader.mWidth];
|
||||||
|
|
||||||
// System.out.println("channels: " + channels);
|
// System.out.println("channels: " + channels);
|
||||||
// System.out.println("numColorComponents: " + numColorComponents);
|
// System.out.println("numColorComponents: " + numColorComponents);
|
||||||
// System.out.println("isCMYK: " + isCMYK);
|
// System.out.println("isCMYK: " + isCMYK);
|
||||||
|
|
||||||
short compression = mImageInput.readShort();
|
short compression = mImageInput.readShort();
|
||||||
|
|
||||||
|
// final Rectangle source = getSourceRegion(pParam, mHeader.mWidth, mHeader.mHeight);
|
||||||
|
final Rectangle source = new Rectangle();
|
||||||
|
final Rectangle dest = new Rectangle();
|
||||||
|
computeRegions(pParam, mHeader.mWidth, mHeader.mHeight, image, source, dest);
|
||||||
|
// System.out.println("image: " + new Rectangle(image.getWidth(), image.getHeight()));
|
||||||
|
// System.out.println("source: " + source);
|
||||||
|
// System.out.println("dest: " + dest);
|
||||||
|
|
||||||
|
final int xSub;
|
||||||
|
final int ySub;
|
||||||
|
|
||||||
|
if (pParam == null) {
|
||||||
|
xSub = ySub = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xSub = pParam.getSourceXSubsampling();
|
||||||
|
ySub = pParam.getSourceYSubsampling();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Bitmap (depth = 1) and 16 bit (depth = 16) must be read differently, obviously...
|
// TODO: Bitmap (depth = 1) and 16 bit (depth = 16) must be read differently, obviously...
|
||||||
// This code works fine for images with channel depth = 8
|
// This code works fine for images with channel depth = 8
|
||||||
switch (compression) {
|
switch (compression) {
|
||||||
@ -271,10 +315,13 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
for (y = 0; y < mHeader.mHeight; y++) {
|
for (y = 0; y < mHeader.mHeight; y++) {
|
||||||
int length = offsets[c * mHeader.mHeight + y];
|
int length = offsets[c * mHeader.mHeight + y];
|
||||||
// System.out.println("channel: " + c + " line: " + y + " length: " + length);
|
// System.out.println("channel: " + c + " line: " + y + " length: " + length);
|
||||||
|
// TODO: Skip rows without decoding
|
||||||
DataInputStream input = PSDUtil.createPackBitsStream(mImageInput, length);
|
DataInputStream input = PSDUtil.createPackBitsStream(mImageInput, length);
|
||||||
for (x = 0; x < mHeader.mWidth; x++) {
|
|
||||||
int offset = (x + y * mHeader.mWidth) * channels;
|
|
||||||
|
|
||||||
|
// TODO: Sometimes need to read the line y == source.y + source.height...
|
||||||
|
// Read entire line, if within source region and sampling
|
||||||
|
if (y >= source.y && y < source.y + source.height && y % ySub == 0) {
|
||||||
|
for (x = 0; x < mHeader.mWidth; x++) {
|
||||||
byte value = input.readByte();
|
byte value = input.readByte();
|
||||||
|
|
||||||
// if (c < numColorComponents) {
|
// if (c < numColorComponents) {
|
||||||
@ -287,8 +334,20 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// System.out.println("b: " + Integer.toHexString(b & 0xff));
|
// System.out.println("b: " + Integer.toHexString(b & 0xff));
|
||||||
data[offset + (channels - 1 - c)] = value;
|
line[x] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Destination offset...
|
||||||
|
// Copy line sub sampled into real data
|
||||||
|
int offset = (y - source.y) / ySub * dest.width * channels + (channels - 1 - c);
|
||||||
|
for (int i = 0; i < dest.width; i++) {
|
||||||
|
data[offset + i * channels] = line[source.x + i * xSub];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: (If not reading compressed) skip data
|
||||||
|
}
|
||||||
|
|
||||||
input.close();
|
input.close();
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
@ -372,7 +431,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// System.out.println("PSDImageReader.coerceData: " + cm.getClass());
|
// System.out.println("PSDImageReader.coerceData: " + cm.getClass());
|
||||||
// System.out.println("other.equals(cm): " + (other == cm));
|
// System.out.println("other.equals(cm): " + (other == cm));
|
||||||
@ -534,7 +592,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] pArgs) throws IOException {
|
public static void main(final String[] pArgs) throws IOException {
|
||||||
PSDImageReader imageReader = new PSDImageReader(null);
|
PSDImageReader imageReader = new PSDImageReader(null);
|
||||||
|
|
||||||
File file = new File(pArgs[0]);
|
File file = new File(pArgs[0]);
|
||||||
@ -552,7 +610,9 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
ImageReadParam param = new ImageReadParam();
|
ImageReadParam param = new ImageReadParam();
|
||||||
// param.setSourceRegion(new Rectangle(100, 100, 300, 200));
|
// param.setSourceRegion(new Rectangle(200, 200, 400, 400));
|
||||||
|
// param.setSourceRegion(new Rectangle(300, 200));
|
||||||
|
param.setSourceSubsampling(3, 3, 0, 0);
|
||||||
BufferedImage image = imageReader.read(0, param);
|
BufferedImage image = imageReader.read(0, param);
|
||||||
System.out.println("time: " + (System.currentTimeMillis() - start));
|
System.out.println("time: " + (System.currentTimeMillis() - start));
|
||||||
System.out.println("image: " + image);
|
System.out.println("image: " + image);
|
||||||
@ -572,5 +632,4 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
showIt(image, file.getName());
|
showIt(image, file.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user