mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-06 04:55:30 -04:00
- Minor clean-up in CMYKColorSpace, PSDColorData and PSDHeader
- Implemented raw type specifier to resemble file storage format - Implemented banded reading for raw type
This commit is contained in:
parent
a782bcfc3b
commit
370505b62f
2
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/CMYKColorSpace.java
Executable file → Normal file
2
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/CMYKColorSpace.java
Executable file → Normal file
@ -37,7 +37,7 @@ import java.awt.color.ColorSpace;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: CMYKColorSpace.java,v 1.0 Apr 30, 2008 1:38:13 PM haraldk Exp$
|
* @version $Id: CMYKColorSpace.java,v 1.0 Apr 30, 2008 1:38:13 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
// TODO: Move to com.twlevemonkeys.image?
|
// TODO: Move to com.twelvemonkeys.image?
|
||||||
// TODO: Read a ICC CMYK profile from classpath resource (from ECI)? ISO coated?
|
// TODO: Read a ICC CMYK profile from classpath resource (from ECI)? ISO coated?
|
||||||
final class CMYKColorSpace extends ColorSpace {
|
final class CMYKColorSpace extends ColorSpace {
|
||||||
|
|
||||||
|
3
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDColorData.java
Executable file → Normal file
3
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDColorData.java
Executable file → Normal file
@ -68,11 +68,13 @@ class PSDColorData {
|
|||||||
int[] rgb = toInterleavedRGB(mColors);
|
int[] rgb = toInterleavedRGB(mColors);
|
||||||
mColorModel = new InverseColorMapIndexColorModel(8, rgb.length, rgb, 0, false, -1, DataBuffer.TYPE_BYTE);
|
mColorModel = new InverseColorMapIndexColorModel(8, rgb.length, rgb, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mColorModel;
|
return mColorModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] toInterleavedRGB(byte[] pColors) {
|
private int[] toInterleavedRGB(byte[] pColors) {
|
||||||
int[] rgb = new int[pColors.length / 3];
|
int[] rgb = new int[pColors.length / 3];
|
||||||
|
|
||||||
for (int i = 0; i < rgb.length; i++) {
|
for (int i = 0; i < rgb.length; i++) {
|
||||||
// Pack the non-interleaved samples into interleaved form
|
// Pack the non-interleaved samples into interleaved form
|
||||||
int r = pColors[ i] & 0xff;
|
int r = pColors[ i] & 0xff;
|
||||||
@ -81,6 +83,7 @@ class PSDColorData {
|
|||||||
|
|
||||||
rgb[i] = (r << 16) | (g << 8) | b;
|
rgb[i] = (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rgb;
|
return rgb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDHeader.java
Executable file → Normal file
15
twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDHeader.java
Executable file → Normal file
@ -68,11 +68,14 @@ class PSDHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int version = pInput.readUnsignedShort();
|
int version = pInput.readUnsignedShort();
|
||||||
if (version != 1) {
|
|
||||||
if (version == 2) {
|
switch (version) {
|
||||||
throw new IIOException("Large Document Format (PSB) not supported yet.");
|
case 1:
|
||||||
}
|
break;
|
||||||
throw new IIOException("Unknown PSD version, expected 1 or 2: 0x" + Integer.toHexString(version));
|
case 2:
|
||||||
|
throw new IIOException("Photoshop Large Document Format (PSB) not supported yet.");
|
||||||
|
default:
|
||||||
|
throw new IIOException(String.format("Unknown PSD version, expected 1 or 2: 0x%08x", version));
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] reserved = new byte[6];
|
byte[] reserved = new byte[6];
|
||||||
@ -80,7 +83,7 @@ class PSDHeader {
|
|||||||
|
|
||||||
mChannels = pInput.readShort();
|
mChannels = pInput.readShort();
|
||||||
mHeight = pInput.readInt(); // Rows
|
mHeight = pInput.readInt(); // Rows
|
||||||
mWidth = pInput.readInt(); // Coloumns
|
mWidth = pInput.readInt(); // Columns
|
||||||
mBits = pInput.readShort();
|
mBits = pInput.readShort();
|
||||||
mMode = pInput.readShort();
|
mMode = pInput.readShort();
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,7 @@ 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.*;
|
import java.awt.*;
|
||||||
@ -59,7 +56,6 @@ import java.util.List;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: PSDImageReader.java,v 1.0 Apr 29, 2008 4:45:52 PM haraldk Exp$
|
* @version $Id: PSDImageReader.java,v 1.0 Apr 29, 2008 4:45:52 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
// TODO: Figure out why reading directly from a FileInputStream is so dead slow...
|
|
||||||
// TODO: Implement meta data reading
|
// TODO: Implement meta data reading
|
||||||
// TODO: Implement layer reading
|
// TODO: Implement layer reading
|
||||||
// TODO: Allow reading separate (or some?) layers
|
// TODO: Allow reading separate (or some?) layers
|
||||||
@ -98,49 +94,48 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
return mHeader.mHeight;
|
return mHeader.mHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int pIndex) throws IOException {
|
@Override
|
||||||
// TODO: Check out the custom ImageTypeIterator and ImageTypeProducer used in the Sun provided JPEGImageReader
|
public ImageTypeSpecifier getRawImageType(int pIndex) throws IOException {
|
||||||
// Could use similar concept to create lazily-created ImageTypeSpecifiers (util candidate, based on FilterIterator?)
|
|
||||||
|
|
||||||
checkBounds(pIndex);
|
checkBounds(pIndex);
|
||||||
readHeader();
|
readHeader();
|
||||||
|
|
||||||
ColorSpace cs;
|
ColorSpace cs;
|
||||||
List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>();
|
|
||||||
|
|
||||||
switch (mHeader.mMode) {
|
switch (mHeader.mMode) {
|
||||||
case PSD.COLOR_MODE_MONOCHROME:
|
case PSD.COLOR_MODE_MONOCHROME:
|
||||||
if (mHeader.mChannels == 1 && mHeader.mBits == 1) {
|
if (mHeader.mChannels == 1 && mHeader.mBits == 1) {
|
||||||
types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY));
|
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new IIOException("Unsupported channel count/bit depth for Monochrome PSD: " + mHeader.mChannels + " channels/" + mHeader.mBits + " bits");
|
throw new IIOException(
|
||||||
}
|
String.format("Unsupported channel count/bit depth for Monochrome PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
||||||
break;
|
);
|
||||||
|
|
||||||
case PSD.COLOR_MODE_INDEXED:
|
case PSD.COLOR_MODE_INDEXED:
|
||||||
// TODO: 16 bit indexed?!
|
// TODO: 16 bit indexed?!
|
||||||
if (mHeader.mChannels == 1 && mHeader.mBits == 8) {
|
if (mHeader.mChannels == 1 && mHeader.mBits == 8) {
|
||||||
types.add(IndexedImageTypeSpecifier.createFromIndexColorModel(mColorData.getIndexColorModel()));
|
return IndexedImageTypeSpecifier.createFromIndexColorModel(mColorData.getIndexColorModel());
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new IIOException("Unsupported channel count/bit depth for Indexed Color PSD: " + mHeader.mChannels + " channels/" + mHeader.mBits + " bits");
|
throw new IIOException(
|
||||||
}
|
String.format("Unsupported channel count/bit depth for Indexed Color PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
||||||
break;
|
);
|
||||||
|
|
||||||
case PSD.COLOR_MODE_DUOTONE:
|
case PSD.COLOR_MODE_DUOTONE:
|
||||||
// NOTE: Duotone (whatever that is) should be treated as gray scale, so fall-through
|
// NOTE: Duotone (whatever that is) should be treated as gray scale
|
||||||
|
// Fall-through
|
||||||
case PSD.COLOR_MODE_GRAYSCALE:
|
case PSD.COLOR_MODE_GRAYSCALE:
|
||||||
if (mHeader.mChannels == 1 && mHeader.mBits == 8) {
|
if (mHeader.mChannels == 1 && mHeader.mBits == 8) {
|
||||||
types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY));
|
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
|
||||||
}
|
}
|
||||||
else if (mHeader.mChannels == 1 && mHeader.mBits == 16) {
|
else if (mHeader.mChannels == 1 && mHeader.mBits == 16) {
|
||||||
types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY));
|
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new IIOException(
|
throw new IIOException(
|
||||||
String.format("Unsupported channel count/bit depth for Gray Scale PSD: %s channels/%s bits", mHeader.mChannels, mHeader.mBits)
|
String.format("Unsupported channel count/bit depth for Gray Scale PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PSD.COLOR_MODE_RGB:
|
case PSD.COLOR_MODE_RGB:
|
||||||
cs = getEmbeddedColorSpace();
|
cs = getEmbeddedColorSpace();
|
||||||
if (cs == null) {
|
if (cs == null) {
|
||||||
@ -148,11 +143,70 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mHeader.mChannels == 3 && mHeader.mBits == 8) {
|
if (mHeader.mChannels == 3 && mHeader.mBits == 8) {
|
||||||
// types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR));
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2}, new int[] {0, 0, 0}, DataBuffer.TYPE_BYTE, false, false);
|
||||||
|
}
|
||||||
|
else if (mHeader.mChannels >= 4 && mHeader.mBits == 8) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_BYTE, true, false);
|
||||||
|
}
|
||||||
|
else if (mHeader.mChannels == 3 && mHeader.mBits == 16) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2}, new int[] {0, 0, 0}, DataBuffer.TYPE_USHORT, false, false);
|
||||||
|
}
|
||||||
|
else if (mHeader.mChannels >= 4 && mHeader.mBits == 16) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_USHORT, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IIOException(
|
||||||
|
String.format("Unsupported channel count/bit depth for RGB PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
||||||
|
);
|
||||||
|
|
||||||
|
case PSD.COLOR_MODE_CMYK:
|
||||||
|
cs = getEmbeddedColorSpace();
|
||||||
|
if (cs == null) {
|
||||||
|
cs = CMYKColorSpace.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mHeader.mChannels == 4 && mHeader.mBits == 8) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_BYTE, false, false);
|
||||||
|
}
|
||||||
|
else if (mHeader.mChannels == 5 && mHeader.mBits == 8) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3, 4}, new int[] {0, 0, 0, 0, 0}, DataBuffer.TYPE_BYTE, true, false);
|
||||||
|
}
|
||||||
|
else if (mHeader.mChannels == 4 && mHeader.mBits == 16) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, DataBuffer.TYPE_USHORT, false, false);
|
||||||
|
}
|
||||||
|
else if (mHeader.mChannels == 5 && mHeader.mBits == 16) {
|
||||||
|
return ImageTypeSpecifier.createBanded(cs, new int[] {0, 1, 2, 3, 4}, new int[] {0, 0, 0, 0, 0}, DataBuffer.TYPE_USHORT, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IIOException(
|
||||||
|
String.format("Unsupported channel count/bit depth for CMYK PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new IIOException(
|
||||||
|
String.format("Unsupported PSD MODE: %s (%d channels/%d bits)", mHeader.mMode, mHeader.mChannels, mHeader.mBits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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?)
|
||||||
|
|
||||||
|
// Get the raw type. Will fail for unsupported types
|
||||||
|
ImageTypeSpecifier rawType = getRawImageType(pIndex);
|
||||||
|
|
||||||
|
ColorSpace cs = rawType.getColorModel().getColorSpace();
|
||||||
|
List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>();
|
||||||
|
|
||||||
|
switch (mHeader.mMode) {
|
||||||
|
case PSD.COLOR_MODE_RGB:
|
||||||
|
// Prefer interleaved versions as they are much faster to display
|
||||||
|
if (mHeader.mChannels == 3 && mHeader.mBits == 8) {
|
||||||
|
// Basically same as BufferedImage.TYPE_3BYTE_BGR
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
|
||||||
}
|
}
|
||||||
else if (mHeader.mChannels >= 4 && mHeader.mBits == 8) {
|
else if (mHeader.mChannels >= 4 && mHeader.mBits == 8) {
|
||||||
// types.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR));
|
// Basically same as BufferedImage.TYPE_4BYTE_ABGR
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
|
||||||
}
|
}
|
||||||
else if (mHeader.mChannels == 3 && mHeader.mBits == 16) {
|
else if (mHeader.mChannels == 3 && mHeader.mBits == 16) {
|
||||||
@ -161,44 +215,32 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
else if (mHeader.mChannels >= 4 && mHeader.mBits == 16) {
|
else if (mHeader.mChannels >= 4 && mHeader.mBits == 16) {
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw new IIOException(
|
|
||||||
String.format("Unsupported channel count/bit depth for RGB PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case PSD.COLOR_MODE_CMYK:
|
case PSD.COLOR_MODE_CMYK:
|
||||||
|
// Prefer interleaved versions as they are much faster to display
|
||||||
// TODO: We should convert these to their RGB equivalents while reading for the common-case,
|
// TODO: We should convert these to their RGB equivalents while reading for the common-case,
|
||||||
// as Java2D is extremely slow displaying custom images.
|
// as Java2D is extremely slow displaying custom images.
|
||||||
// Converting to RGB is also correct behaviour, according to the docs.
|
// Converting to RGB is also correct behaviour, according to the docs.
|
||||||
// The code below is, however, correct for raw type.
|
|
||||||
cs = getEmbeddedColorSpace();
|
|
||||||
if (cs == null) {
|
|
||||||
cs = CMYKColorSpace.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mHeader.mChannels == 4 && mHeader.mBits == 8) {
|
if (mHeader.mChannels == 4 && mHeader.mBits == 8) {
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{3, 2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, false, false));
|
||||||
}
|
}
|
||||||
else if (mHeader.mChannels == 5 && mHeader.mBits == 8) {
|
else if (mHeader.mChannels == 5 && mHeader.mBits == 8) {
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{4, 3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {4, 3, 2, 1, 0}, DataBuffer.TYPE_BYTE, true, false));
|
||||||
}
|
}
|
||||||
else if (mHeader.mChannels == 4 && mHeader.mBits == 16) {
|
else if (mHeader.mChannels == 4 && mHeader.mBits == 16) {
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{3, 2, 1, 0}, DataBuffer.TYPE_USHORT, false, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{3, 2, 1, 0}, DataBuffer.TYPE_USHORT, false, false));
|
||||||
}
|
}
|
||||||
else if (mHeader.mChannels == 5 && mHeader.mBits == 16) {
|
else if (mHeader.mChannels == 5 && mHeader.mBits == 16) {
|
||||||
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[]{4, 3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false));
|
types.add(ImageTypeSpecifier.createInterleaved(cs, new int[] {4, 3, 2, 1, 0}, DataBuffer.TYPE_USHORT, true, false));
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IIOException(
|
|
||||||
String.format("Unsupported channel count/bit depth for CMYK PSD: %d channels/%d bits", mHeader.mChannels, mHeader.mBits)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IIOException("Unsupported PSD MODE: " + mHeader.mMode);
|
// Just stick to the raw type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally add the
|
||||||
|
types.add(rawType);
|
||||||
|
|
||||||
return types.iterator();
|
return types.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +264,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
return mColorSpace;
|
return mColorSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement param handling
|
|
||||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||||
checkBounds(pIndex);
|
checkBounds(pIndex);
|
||||||
|
|
||||||
@ -249,6 +290,10 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
// Otherwise, copy "through" ColorMode?l
|
// Otherwise, copy "through" ColorMode?l
|
||||||
// Copy pixels from temp raster
|
// Copy pixels from temp raster
|
||||||
// If possible, leave the destination image "untouched" (accelerated)
|
// If possible, leave the destination image "untouched" (accelerated)
|
||||||
|
|
||||||
|
// TODO: Doing a per line color convert will be expensive, as data is channelled...
|
||||||
|
// Will need to either convert entire image, or skip back/forth between channels...
|
||||||
|
|
||||||
// TODO: Banding...
|
// TODO: Banding...
|
||||||
|
|
||||||
ImageTypeSpecifier spec = getRawImageType(pIndex);
|
ImageTypeSpecifier spec = getRawImageType(pIndex);
|
||||||
@ -260,9 +305,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Maybe a banded raster would be easier than interleaved? We could still convert to interleaved in CCOp
|
|
||||||
WritableRaster raster = image.getRaster();
|
|
||||||
|
|
||||||
final int xSub;
|
final int xSub;
|
||||||
final int ySub;
|
final int ySub;
|
||||||
|
|
||||||
@ -299,19 +341,18 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
switch (mHeader.mBits) {
|
switch (mHeader.mBits) {
|
||||||
case 1:
|
case 1:
|
||||||
read1bitData(raster, image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
|
read1bitData(image.getRaster(), image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
read8bitData(raster, image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
|
read8bitData(image.getRaster(), image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
read16bitData(raster, image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
|
read16bitData(image.getRaster(), image.getColorModel(), source, dest, xSub, ySub, offsets, compression == PSD.COMPRESSION_RLE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IIOException("Unknown bit depth: " + mHeader.mBits);
|
throw new IIOException("Unknown bit depth: " + mHeader.mBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
processReadAborted();
|
processReadAborted();
|
||||||
}
|
}
|
||||||
@ -328,7 +369,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
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();
|
||||||
final short[] data = ((DataBufferUShort) pRaster.getDataBuffer()).getData();
|
|
||||||
|
|
||||||
// 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
|
||||||
ColorModel sourceColorModel = pDestinationColorModel;
|
ColorModel sourceColorModel = pDestinationColorModel;
|
||||||
@ -339,9 +379,15 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
final boolean isCMYK = sourceColorModel.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
|
final boolean isCMYK = sourceColorModel.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
|
||||||
final int colorComponents = sourceColorModel.getColorSpace().getNumComponents();
|
final int colorComponents = sourceColorModel.getColorSpace().getNumComponents();
|
||||||
|
|
||||||
|
DataBufferUShort buffer = (DataBufferUShort) pRaster.getDataBuffer();
|
||||||
|
final boolean banded = buffer.getNumBanks() > 1;
|
||||||
|
|
||||||
|
short[] data = null;
|
||||||
int x = 0, y = 0, c = 0;
|
int x = 0, y = 0, c = 0;
|
||||||
try {
|
try {
|
||||||
for (c = 0; c < channels; c++) {
|
for (c = 0; c < channels; c++) {
|
||||||
|
data = banded ? buffer.getData(c) : buffer.getData();
|
||||||
|
|
||||||
for (y = 0; y < mHeader.mHeight; y++) {
|
for (y = 0; y < mHeader.mHeight; y++) {
|
||||||
// Length is in shorts!?
|
// Length is in shorts!?
|
||||||
int length = 2 * (pRLECompressed ? pRowOffsets[c * mHeader.mHeight + y] : mHeader.mWidth);
|
int length = 2 * (pRLECompressed ? pRowOffsets[c * mHeader.mHeight + y] : mHeader.mWidth);
|
||||||
@ -366,7 +412,9 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
// TODO: Destination offset...??
|
// TODO: Destination offset...??
|
||||||
// Copy line sub sampled into real data
|
// Copy line sub sampled into real data
|
||||||
int offset = (y - pSource.y) / pYSub * pDest.width * channels + (channels - 1 - c);
|
int offset = banded ?
|
||||||
|
(y - pSource.y) / pYSub * pDest.width :
|
||||||
|
(y - pSource.y) / pYSub * pDest.width * channels + (channels - 1 - c);
|
||||||
for (int i = 0; i < pDest.width; i++) {
|
for (int i = 0; i < pDest.width; i++) {
|
||||||
short value = row[pSource.x + i * pXSub];
|
short value = row[pSource.x + i * pXSub];
|
||||||
|
|
||||||
@ -375,7 +423,12 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
value = (short) (65535 - value & 0xffff);
|
value = (short) (65535 - value & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
data[offset + i * channels] = value;
|
if (banded) {
|
||||||
|
data[offset + i] = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data[offset + i * channels] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -419,7 +472,6 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
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();
|
||||||
final byte[] data = ((DataBufferByte) pRaster.getDataBuffer()).getData();
|
|
||||||
|
|
||||||
// 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
|
||||||
ColorModel sourceColorModel = pDestinationColorModel;
|
ColorModel sourceColorModel = pDestinationColorModel;
|
||||||
@ -430,9 +482,15 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
final boolean isCMYK = sourceColorModel.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
|
final boolean isCMYK = sourceColorModel.getColorSpace().getType() == ColorSpace.TYPE_CMYK;
|
||||||
final int colorComponents = sourceColorModel.getColorSpace().getNumComponents();
|
final int colorComponents = sourceColorModel.getColorSpace().getNumComponents();
|
||||||
|
|
||||||
|
DataBufferByte buffer = (DataBufferByte) pRaster.getDataBuffer();
|
||||||
|
final boolean banded = buffer.getNumBanks() > 1;
|
||||||
|
|
||||||
|
byte[] data = null;
|
||||||
int x = 0, y = 0, c = 0;
|
int x = 0, y = 0, c = 0;
|
||||||
try {
|
try {
|
||||||
for (c = 0; c < channels; c++) {
|
for (c = 0; c < channels; c++) {
|
||||||
|
data = banded ? buffer.getData(c) : buffer.getData();
|
||||||
|
|
||||||
for (y = 0; y < mHeader.mHeight; y++) {
|
for (y = 0; y < mHeader.mHeight; y++) {
|
||||||
int length = pRLECompressed ? pRowOffsets[c * mHeader.mHeight + y] : mHeader.mWidth;
|
int length = pRLECompressed ? pRowOffsets[c * mHeader.mHeight + y] : mHeader.mWidth;
|
||||||
|
|
||||||
@ -452,9 +510,13 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
mImageInput.readFully(row, 0, mHeader.mWidth);
|
mImageInput.readFully(row, 0, mHeader.mWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: If banded and not sub sampling/cmyk, we could just copy using System.arraycopy
|
||||||
// TODO: Destination offset...??
|
// TODO: Destination offset...??
|
||||||
// Copy line sub sampled into real data
|
// Copy line sub sampled into real data
|
||||||
int offset = (y - pSource.y) / pYSub * pDest.width * channels + (channels - 1 - c);
|
// int offset = (y - pSource.y) / pYSub * pDest.width * channels + (channels - 1 - c);
|
||||||
|
int offset = banded ?
|
||||||
|
(y - pSource.y) / pYSub * pDest.width :
|
||||||
|
(y - pSource.y) / pYSub * pDest.width * channels + (channels - 1 - c);
|
||||||
for (int i = 0; i < pDest.width; i++) {
|
for (int i = 0; i < pDest.width; i++) {
|
||||||
byte value = row[pSource.x + i * pXSub];
|
byte value = row[pSource.x + i * pXSub];
|
||||||
|
|
||||||
@ -463,7 +525,12 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
value = (byte) (255 - value & 0xff);
|
value = (byte) (255 - value & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
data[offset + i * channels] = value;
|
if (banded) {
|
||||||
|
data[offset + i] = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data[offset + i * channels] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -497,7 +564,7 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compose out the background of the semi-transparent pixels, as PS somehow has the background composed in
|
// Compose out the background of the semi-transparent pixels, as PS somehow has the background composed in
|
||||||
decomposeAlpha(sourceColorModel, data, pDest.width, pDest.height, channels);
|
decomposeAlpha(sourceColorModel, buffer, pDest.width, pDest.height, channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void read1bitData(final WritableRaster pRaster, final ColorModel pDestinationColorModel,
|
private void read1bitData(final WritableRaster pRaster, final ColorModel pDestinationColorModel,
|
||||||
@ -591,29 +658,57 @@ public class PSDImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decomposeAlpha(final ColorModel pModel, final byte[] pData,
|
private void decomposeAlpha(final ColorModel pModel, final DataBufferByte pBuffer,
|
||||||
final int pWidth, final int pHeight, final int pChannels) throws IOException
|
final int pWidth, final int pHeight, final int pChannels) {
|
||||||
{
|
// TODO: Is the document background always white!?
|
||||||
// TODO: What about CMYK + alpha?
|
// TODO: What about CMYK + alpha?
|
||||||
if (pModel.hasAlpha() && pModel.getColorSpace().getType() == ColorSpace.TYPE_RGB) {
|
if (pModel.hasAlpha() && pModel.getColorSpace().getType() == ColorSpace.TYPE_RGB) {
|
||||||
// TODO: Probably faster to do this in line..
|
|
||||||
for (int y = 0; y < pHeight; y++) {
|
|
||||||
for (int x = 0; x < pWidth; x++) {
|
|
||||||
int offset = (x + y * pWidth) * pChannels;
|
|
||||||
// TODO: Is the document background always white!?
|
|
||||||
// ABGR format
|
|
||||||
int alpha = pData[offset] & 0xff;
|
|
||||||
|
|
||||||
if (alpha != 0) {
|
|
||||||
double normalizedAlpha = alpha / 255.0;
|
|
||||||
|
|
||||||
for (int i = 1; i < pChannels; i++) {
|
// TODO: Probably faster to do this in line..
|
||||||
pData[offset + i] = decompose(pData[offset + i] & 0xff, normalizedAlpha);
|
if (pBuffer.getNumBanks() > 1) {
|
||||||
|
byte[][] data = pBuffer.getBankData();
|
||||||
|
|
||||||
|
for (int y = 0; y < pHeight; y++) {
|
||||||
|
for (int x = 0; x < pWidth; x++) {
|
||||||
|
int offset = (x + y * pWidth);
|
||||||
|
// ARGB format
|
||||||
|
int alpha = data[pChannels - 1][offset] & 0xff;
|
||||||
|
|
||||||
|
if (alpha != 0) {
|
||||||
|
double normalizedAlpha = alpha / 255.0;
|
||||||
|
|
||||||
|
for (int i = 0; i < pChannels - 1; i++) {
|
||||||
|
data[i][offset] = decompose(data[i][offset] & 0xff, normalizedAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < pChannels - 1; i++) {
|
||||||
|
data[i][offset] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
for (int i = 1; i < pChannels; i++) {
|
}
|
||||||
pData[offset + i] = 0;
|
else {
|
||||||
|
byte[] data = pBuffer.getData();
|
||||||
|
|
||||||
|
for (int y = 0; y < pHeight; y++) {
|
||||||
|
for (int x = 0; x < pWidth; x++) {
|
||||||
|
int offset = (x + y * pWidth) * pChannels;
|
||||||
|
// ABGR format
|
||||||
|
int alpha = data[offset] & 0xff;
|
||||||
|
|
||||||
|
if (alpha != 0) {
|
||||||
|
double normalizedAlpha = alpha / 255.0;
|
||||||
|
|
||||||
|
for (int i = 1; i < pChannels; i++) {
|
||||||
|
data[offset + i] = decompose(data[offset + i] & 0xff, normalizedAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 1; i < pChannels; i++) {
|
||||||
|
data[offset + i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user