mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 03:25:28 -04:00
IFF format clean-up + standard metadata support
This commit is contained in:
parent
78af95d747
commit
64fb421b38
@ -28,7 +28,7 @@ The goal is to create a set of efficient and robust ImageIO plug-ins, that can b
|
|||||||
| | ICO | MS Windows Icon Format | ✔ | ✔ | - |
|
| | ICO | MS Windows Icon Format | ✔ | ✔ | - |
|
||||||
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | ✔ | - | Standard |
|
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | ✔ | - | Standard |
|
||||||
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | ✔ | ✔ | - |
|
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | ✔ | ✔ | - |
|
||||||
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | ✔ | ✔ | - |
|
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | ✔ | ✔ | Standard |
|
||||||
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | Native & Standard |
|
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | Native & Standard |
|
||||||
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | Standard |
|
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | Standard |
|
||||||
| | DCX | Multi-page PCX fax document | ✔ | - | Standard |
|
| | DCX | Multi-page PCX fax document | ✔ | - | Standard |
|
||||||
|
@ -102,14 +102,15 @@ abstract class AbstractMultiPaletteChunk extends IFFChunk implements MultiPalett
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void writeChunk(DataOutput pOutput) throws IOException {
|
void writeChunk(DataOutput pOutput) {
|
||||||
throw new UnsupportedOperationException("Method writeChunk not implemented");
|
throw new UnsupportedOperationException("Method writeChunk not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public ColorModel getColorModel(final IndexColorModel colorModel, final int rowIndex, final boolean laced) {
|
public ColorModel getColorModel(final IndexColorModel colorModel, final int rowIndex, final boolean laced) {
|
||||||
if (rowIndex < lastRow || mutablePalette == null || originalPalette != null && originalPalette.get() != colorModel) {
|
if (rowIndex < lastRow || mutablePalette == null || originalPalette != null && originalPalette.get() != colorModel) {
|
||||||
originalPalette = new WeakReference<IndexColorModel>(colorModel);
|
originalPalette = new WeakReference<>(colorModel);
|
||||||
mutablePalette = new MutableIndexColorModel(colorModel);
|
mutablePalette = new MutableIndexColorModel(colorModel);
|
||||||
|
|
||||||
if (initialChanges != null) {
|
if (initialChanges != null) {
|
||||||
|
@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BMHDChunk
|
* BMHDChunk
|
||||||
*
|
*
|
||||||
@ -129,7 +130,8 @@ final class BMHDChunk extends IFFChunk {
|
|||||||
pageHeight = Math.min(pHeight, Short.MAX_VALUE);
|
pageHeight = Math.min(pHeight, Short.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readChunk(DataInput pInput) throws IOException {
|
@Override
|
||||||
|
void readChunk(final DataInput pInput) throws IOException {
|
||||||
if (chunkLength != 20) {
|
if (chunkLength != 20) {
|
||||||
throw new IIOException("Unknown BMHD chunk length: " + chunkLength);
|
throw new IIOException("Unknown BMHD chunk length: " + chunkLength);
|
||||||
}
|
}
|
||||||
@ -148,7 +150,8 @@ final class BMHDChunk extends IFFChunk {
|
|||||||
pageHeight = pInput.readShort();
|
pageHeight = pInput.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChunk(DataOutput pOutput) throws IOException {
|
@Override
|
||||||
|
void writeChunk(final DataOutput pOutput) throws IOException {
|
||||||
pOutput.writeInt(chunkId);
|
pOutput.writeInt(chunkId);
|
||||||
pOutput.writeInt(chunkLength);
|
pOutput.writeInt(chunkLength);
|
||||||
|
|
||||||
@ -167,6 +170,7 @@ final class BMHDChunk extends IFFChunk {
|
|||||||
pOutput.writeShort(pageHeight);
|
pOutput.writeShort(pageHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString()
|
return super.toString()
|
||||||
+ " {w=" + width + ", h=" + height
|
+ " {w=" + width + ", h=" + height
|
||||||
|
@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.iff;
|
|||||||
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BODYChunk
|
* BODYChunk
|
||||||
@ -45,11 +44,13 @@ final class BODYChunk extends IFFChunk {
|
|||||||
super(IFF.CHUNK_BODY, pChunkLength);
|
super(IFF.CHUNK_BODY, pChunkLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readChunk(DataInput pInput) throws IOException {
|
@Override
|
||||||
|
void readChunk(final DataInput pInput) {
|
||||||
throw new InternalError("BODY chunk should only be read from IFFImageReader");
|
throw new InternalError("BODY chunk should only be read from IFFImageReader");
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChunk(DataOutput pOutput) throws IOException {
|
@Override
|
||||||
|
void writeChunk(final DataOutput pOutput) {
|
||||||
throw new InternalError("BODY chunk should only be written from IFFImageWriter");
|
throw new InternalError("BODY chunk should only be written from IFFImageWriter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CAMGChunk
|
* CAMGChunk
|
||||||
*
|
*
|
||||||
@ -46,13 +47,14 @@ final class CAMGChunk extends IFFChunk {
|
|||||||
// #define CAMG_HAM 0x800 /* hold and modify */
|
// #define CAMG_HAM 0x800 /* hold and modify */
|
||||||
// #define CAMG_EHB 0x80 /* extra halfbrite */
|
// #define CAMG_EHB 0x80 /* extra halfbrite */
|
||||||
|
|
||||||
private int camg;
|
int camg;
|
||||||
|
|
||||||
public CAMGChunk(int pLength) {
|
public CAMGChunk(int pLength) {
|
||||||
super(IFF.CHUNK_CAMG, pLength);
|
super(IFF.CHUNK_CAMG, pLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readChunk(DataInput pInput) throws IOException {
|
@Override
|
||||||
|
void readChunk(final DataInput pInput) throws IOException {
|
||||||
if (chunkLength != 4) {
|
if (chunkLength != 4) {
|
||||||
throw new IIOException("Unknown CAMG chunk length: " + chunkLength);
|
throw new IIOException("Unknown CAMG chunk length: " + chunkLength);
|
||||||
}
|
}
|
||||||
@ -60,7 +62,8 @@ final class CAMGChunk extends IFFChunk {
|
|||||||
camg = pInput.readInt();
|
camg = pInput.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChunk(DataOutput pOutput) throws IOException {
|
@Override
|
||||||
|
void writeChunk(final DataOutput pOutput) {
|
||||||
throw new InternalError("Not implemented: writeChunk()");
|
throw new InternalError("Not implemented: writeChunk()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +83,7 @@ final class CAMGChunk extends IFFChunk {
|
|||||||
return (camg & 0x80) != 0;
|
return (camg & 0x80) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString() + " {mode=" + (isHAM() ? "HAM" : isEHB() ? "EHB" : "Normal") + "}";
|
return super.toString() + " {mode=" + (isHAM() ? "HAM" : isEHB() ? "EHB" : "Normal") + "}";
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.IndexColorModel;
|
import java.awt.image.IndexColorModel;
|
||||||
import java.awt.image.WritableRaster;
|
import java.awt.image.WritableRaster;
|
||||||
@ -39,6 +38,8 @@ import java.io.DataOutput;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CMAPChunk
|
* CMAPChunk
|
||||||
*
|
*
|
||||||
@ -68,6 +69,7 @@ final class CMAPChunk extends IFFChunk {
|
|||||||
model = pModel;
|
model = pModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
void readChunk(final DataInput pInput) throws IOException {
|
void readChunk(final DataInput pInput) throws IOException {
|
||||||
int numColors = chunkLength / 3;
|
int numColors = chunkLength / 3;
|
||||||
|
|
||||||
@ -95,6 +97,7 @@ final class CMAPChunk extends IFFChunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
void writeChunk(final DataOutput pOutput) throws IOException {
|
void writeChunk(final DataOutput pOutput) throws IOException {
|
||||||
pOutput.writeInt(chunkId);
|
pOutput.writeInt(chunkId);
|
||||||
pOutput.writeInt(chunkLength);
|
pOutput.writeInt(chunkLength);
|
||||||
@ -112,6 +115,7 @@ final class CMAPChunk extends IFFChunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString() + " {colorMap=" + model + "}";
|
return super.toString() + " {colorMap=" + model + "}";
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,10 @@ import java.io.DataOutput;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UnknownChunk
|
* GenericChunk
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: UnknownChunk.java,v 1.0 28.feb.2006 00:53:47 haku Exp$
|
* @version $Id: GenericChunk.java,v 1.0 28.feb.2006 00:53:47 haku Exp$
|
||||||
*/
|
*/
|
||||||
final class GenericChunk extends IFFChunk {
|
final class GenericChunk extends IFFChunk {
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ final class GenericChunk extends IFFChunk {
|
|||||||
|
|
||||||
protected GenericChunk(int pChunkId, int pChunkLength) {
|
protected GenericChunk(int pChunkId, int pChunkLength) {
|
||||||
super(pChunkId, pChunkLength);
|
super(pChunkId, pChunkLength);
|
||||||
data = new byte[pChunkLength <= 50 ? pChunkLength : 47];
|
data = new byte[chunkLength];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GenericChunk(int pChunkId, byte[] pChunkData) {
|
protected GenericChunk(int pChunkId, byte[] pChunkData) {
|
||||||
@ -54,13 +54,15 @@ final class GenericChunk extends IFFChunk {
|
|||||||
data = pChunkData;
|
data = pChunkData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readChunk(DataInput pInput) throws IOException {
|
@Override
|
||||||
|
void readChunk(final DataInput pInput) throws IOException {
|
||||||
pInput.readFully(data, 0, data.length);
|
pInput.readFully(data, 0, data.length);
|
||||||
|
|
||||||
skipData(pInput, chunkLength, data.length);
|
skipData(pInput, chunkLength, data.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChunk(DataOutput pOutput) throws IOException {
|
@Override
|
||||||
|
void writeChunk(final DataOutput pOutput) throws IOException {
|
||||||
pOutput.writeInt(chunkId);
|
pOutput.writeInt(chunkId);
|
||||||
pOutput.writeInt(chunkLength);
|
pOutput.writeInt(chunkLength);
|
||||||
pOutput.write(data, 0, data.length);
|
pOutput.write(data, 0, data.length);
|
||||||
@ -70,6 +72,7 @@ final class GenericChunk extends IFFChunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString() + " {value=\""
|
return super.toString() + " {value=\""
|
||||||
+ new String(data, 0, data.length <= 50 ? data.length : 47)
|
+ new String(data, 0, data.length <= 50 ? data.length : 47)
|
||||||
|
@ -91,6 +91,12 @@ interface IFF {
|
|||||||
/** EA IFF 85 Generic Copyright text chunk */
|
/** EA IFF 85 Generic Copyright text chunk */
|
||||||
int CHUNK_COPY = ('(' << 24) + ('c' << 16) + (')' << 8) + ' ';
|
int CHUNK_COPY = ('(' << 24) + ('c' << 16) + (')' << 8) + ' ';
|
||||||
|
|
||||||
|
/** EA IFF 85 Generic annotation chunk (usually used for Software) */
|
||||||
|
int CHUNK_ANNO = ('A' << 24) + ('N' << 16) + ('N' << 8) + 'O';;
|
||||||
|
|
||||||
|
/** Third-party defined UTF-8 text. */
|
||||||
|
int CHUNK_UTF8 = ('U' << 24) + ('T' << 16) + ('F' << 8) + '8';
|
||||||
|
|
||||||
/** color cycling */
|
/** color cycling */
|
||||||
int CHUNK_CRNG = ('C' << 24) + ('R' << 16) + ('N' << 8) + 'G';
|
int CHUNK_CRNG = ('C' << 24) + ('R' << 16) + ('N' << 8) + 'G';
|
||||||
/** color cycling */
|
/** color cycling */
|
||||||
|
@ -0,0 +1,252 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.AbstractMetadata;
|
||||||
|
|
||||||
|
final class IFFImageMetadata extends AbstractMetadata {
|
||||||
|
private final int formType;
|
||||||
|
private final BMHDChunk header;
|
||||||
|
private final IndexColorModel colorMap;
|
||||||
|
private final CAMGChunk viewPort;
|
||||||
|
private final List<GenericChunk> meta;
|
||||||
|
|
||||||
|
IFFImageMetadata(int formType, BMHDChunk header, IndexColorModel colorMap, CAMGChunk viewPort, List<GenericChunk> meta) {
|
||||||
|
this.formType = formType;
|
||||||
|
this.header = header;
|
||||||
|
this.colorMap = colorMap;
|
||||||
|
this.viewPort = viewPort;
|
||||||
|
this.meta = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardChromaNode() {
|
||||||
|
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
||||||
|
|
||||||
|
IIOMetadataNode csType = new IIOMetadataNode("ColorSpaceType");
|
||||||
|
chroma.appendChild(csType);
|
||||||
|
|
||||||
|
switch (header.bitplanes) {
|
||||||
|
case 8:
|
||||||
|
if (colorMap == null) {
|
||||||
|
csType.setAttribute("name", "GRAY");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 24:
|
||||||
|
case 32:
|
||||||
|
csType.setAttribute("name", "RGB");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
csType.setAttribute("name", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Channels in chroma node reflects channels in color model (see data node, for channels in data)
|
||||||
|
IIOMetadataNode numChannels = new IIOMetadataNode("NumChannels");
|
||||||
|
chroma.appendChild(numChannels);
|
||||||
|
if (colorMap == null && header.bitplanes == 8) {
|
||||||
|
numChannels.setAttribute("value", Integer.toString(1));
|
||||||
|
}
|
||||||
|
else if (header.bitplanes == 32) {
|
||||||
|
numChannels.setAttribute("value", Integer.toString(4));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numChannels.setAttribute("value", Integer.toString(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
IIOMetadataNode blackIsZero = new IIOMetadataNode("BlackIsZero");
|
||||||
|
chroma.appendChild(blackIsZero);
|
||||||
|
blackIsZero.setAttribute("value", "TRUE");
|
||||||
|
|
||||||
|
// NOTE: TGA files may contain a color map, even if true color...
|
||||||
|
// Not sure if this is a good idea to expose to the meta data,
|
||||||
|
// as it might be unexpected... Then again...
|
||||||
|
if (colorMap != null) {
|
||||||
|
IIOMetadataNode palette = new IIOMetadataNode("Palette");
|
||||||
|
chroma.appendChild(palette);
|
||||||
|
|
||||||
|
for (int i = 0; i < colorMap.getMapSize(); i++) {
|
||||||
|
IIOMetadataNode paletteEntry = new IIOMetadataNode("PaletteEntry");
|
||||||
|
palette.appendChild(paletteEntry);
|
||||||
|
paletteEntry.setAttribute("index", Integer.toString(i));
|
||||||
|
|
||||||
|
paletteEntry.setAttribute("red", Integer.toString(colorMap.getRed(i)));
|
||||||
|
paletteEntry.setAttribute("green", Integer.toString(colorMap.getGreen(i)));
|
||||||
|
paletteEntry.setAttribute("blue", Integer.toString(colorMap.getBlue(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Background color is the color of the transparent index in the color model?
|
||||||
|
// if (extensions != null && extensions.getBackgroundColor() != 0) {
|
||||||
|
// Color background = new Color(extensions.getBackgroundColor(), true);
|
||||||
|
//
|
||||||
|
// IIOMetadataNode backgroundColor = new IIOMetadataNode("BackgroundColor");
|
||||||
|
// chroma.appendChild(backgroundColor);
|
||||||
|
//
|
||||||
|
// backgroundColor.setAttribute("red", Integer.toString(background.getRed()));
|
||||||
|
// backgroundColor.setAttribute("green", Integer.toString(background.getGreen()));
|
||||||
|
// backgroundColor.setAttribute("blue", Integer.toString(background.getBlue()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
return chroma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardCompressionNode() {
|
||||||
|
if (header.compressionType == BMHDChunk.COMPRESSION_NONE) {
|
||||||
|
return null; // All defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
IIOMetadataNode node = new IIOMetadataNode("Compression");
|
||||||
|
|
||||||
|
IIOMetadataNode compressionTypeName = new IIOMetadataNode("CompressionTypeName");
|
||||||
|
compressionTypeName.setAttribute("value", "RLE");
|
||||||
|
node.appendChild(compressionTypeName);
|
||||||
|
|
||||||
|
IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
|
||||||
|
lossless.setAttribute("value", "TRUE");
|
||||||
|
node.appendChild(lossless);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardDataNode() {
|
||||||
|
IIOMetadataNode data = new IIOMetadataNode("Data");
|
||||||
|
|
||||||
|
// PlanarConfiguration
|
||||||
|
IIOMetadataNode planarConfiguration = new IIOMetadataNode("PlanarConfiguration");
|
||||||
|
switch (formType) {
|
||||||
|
case IFF.TYPE_PBM:
|
||||||
|
planarConfiguration.setAttribute("value", "PixelInterleaved");
|
||||||
|
break;
|
||||||
|
case IFF.TYPE_ILBM:
|
||||||
|
planarConfiguration.setAttribute("value", "PlaneInterleaved");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
planarConfiguration.setAttribute("value", "Unknown " + IFFUtil.toChunkStr(formType));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data.appendChild(planarConfiguration);
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFormat = new IIOMetadataNode("SampleFormat");
|
||||||
|
sampleFormat.setAttribute("value", colorMap != null ? "Index" : "UnsignedIntegral");
|
||||||
|
data.appendChild(sampleFormat);
|
||||||
|
|
||||||
|
// BitsPerSample
|
||||||
|
IIOMetadataNode bitsPerSample = new IIOMetadataNode("BitsPerSample");
|
||||||
|
String value = bitsPerSampleValue(header.bitplanes);
|
||||||
|
bitsPerSample.setAttribute("value", value);
|
||||||
|
data.appendChild(bitsPerSample);
|
||||||
|
|
||||||
|
// SignificantBitsPerSample not in format
|
||||||
|
// SampleMSB not in format
|
||||||
|
|
||||||
|
return data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String bitsPerSampleValue(int bitplanes) {
|
||||||
|
switch (bitplanes) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
return Integer.toString(bitplanes);
|
||||||
|
case 24:
|
||||||
|
return "8 8 8";
|
||||||
|
case 32:
|
||||||
|
return "8 8 8 8";
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Ubknown bit count: " + bitplanes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardDimensionNode() {
|
||||||
|
if (viewPort == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IIOMetadataNode dimension = new IIOMetadataNode("Dimension");
|
||||||
|
|
||||||
|
// PixelAspectRatio
|
||||||
|
IIOMetadataNode pixelAspectRatio = new IIOMetadataNode("PixelAspectRatio");
|
||||||
|
pixelAspectRatio.setAttribute("value", String.valueOf((viewPort.isHires() ? 2f : 1f) / (viewPort.isLaced() ? 2f : 1f)));
|
||||||
|
dimension.appendChild(pixelAspectRatio);
|
||||||
|
|
||||||
|
// TODO: HorizontalScreenSize?
|
||||||
|
// TODO: VerticalScreenSize?
|
||||||
|
|
||||||
|
return dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardDocumentNode() {
|
||||||
|
IIOMetadataNode document = new IIOMetadataNode("Document");
|
||||||
|
|
||||||
|
IIOMetadataNode formatVersion = new IIOMetadataNode("FormatVersion");
|
||||||
|
document.appendChild(formatVersion);
|
||||||
|
formatVersion.setAttribute("value", "1.0");
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardTextNode() {
|
||||||
|
if (meta.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IIOMetadataNode text = new IIOMetadataNode("Text");
|
||||||
|
|
||||||
|
// /Text/TextEntry@keyword = field name, /Text/TextEntry@value = field value.
|
||||||
|
for (GenericChunk chunk : meta) {
|
||||||
|
IIOMetadataNode node = new IIOMetadataNode("TextEntry");
|
||||||
|
node.setAttribute("keyword", IFFUtil.toChunkStr(chunk.chunkId));
|
||||||
|
node.setAttribute("value", new String(chunk.data, chunk.chunkId == IFF.CHUNK_UTF8 ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII));
|
||||||
|
text.appendChild(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardTransparencyNode() {
|
||||||
|
if ((colorMap == null || !colorMap.hasAlpha()) && header.bitplanes != 32) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IIOMetadataNode transparency = new IIOMetadataNode("Transparency");
|
||||||
|
|
||||||
|
if (header.bitplanes == 32) {
|
||||||
|
IIOMetadataNode alpha = new IIOMetadataNode("Alpha");
|
||||||
|
alpha.setAttribute("value", "nonpremultiplied");
|
||||||
|
transparency.appendChild(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorMap != null && colorMap.getTransparency() == Transparency.BITMASK) {
|
||||||
|
IIOMetadataNode transparentIndex = new IIOMetadataNode("TransparentIndex");
|
||||||
|
transparentIndex.setAttribute("value", Integer.toString(colorMap.getTransparentPixel()));
|
||||||
|
transparency.appendChild(transparentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transparency;
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,26 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.color.ColorSpace;
|
||||||
|
import java.awt.image.*;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
|
||||||
import com.twelvemonkeys.image.ResampleOp;
|
import com.twelvemonkeys.image.ResampleOp;
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.stream.BufferedImageInputStream;
|
import com.twelvemonkeys.imageio.stream.BufferedImageInputStream;
|
||||||
@ -38,19 +58,6 @@ import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|||||||
import com.twelvemonkeys.io.enc.DecoderStream;
|
import com.twelvemonkeys.io.enc.DecoderStream;
|
||||||
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
||||||
|
|
||||||
import javax.imageio.*;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.color.ColorSpace;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reader for Commodore Amiga (Electronic Arts) IFF ILBM (InterLeaved BitMap) and PBM
|
* Reader for Commodore Amiga (Electronic Arts) IFF ILBM (InterLeaved BitMap) and PBM
|
||||||
* format (Packed BitMap).
|
* format (Packed BitMap).
|
||||||
@ -96,7 +103,7 @@ import java.util.List;
|
|||||||
* @see <a href="http://en.wikipedia.org/wiki/Interchange_File_Format">Wikipedia: IFF</a>
|
* @see <a href="http://en.wikipedia.org/wiki/Interchange_File_Format">Wikipedia: IFF</a>
|
||||||
* @see <a href="http://en.wikipedia.org/wiki/ILBM">Wikipedia: IFF ILBM</a>
|
* @see <a href="http://en.wikipedia.org/wiki/ILBM">Wikipedia: IFF ILBM</a>
|
||||||
*/
|
*/
|
||||||
public class IFFImageReader extends ImageReaderBase {
|
public final class IFFImageReader extends ImageReaderBase {
|
||||||
// http://home.comcast.net/~erniew/lwsdk/docs/filefmts/ilbm.html
|
// http://home.comcast.net/~erniew/lwsdk/docs/filefmts/ilbm.html
|
||||||
// http://www.fileformat.info/format/iff/spec/7866a9f0e53c42309af667c5da3bd426/view.htm
|
// http://www.fileformat.info/format/iff/spec/7866a9f0e53c42309af667c5da3bd426/view.htm
|
||||||
// - Contains definitions of some "new" chunks, as well as alternative FORM types
|
// - Contains definitions of some "new" chunks, as well as alternative FORM types
|
||||||
@ -111,17 +118,14 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
private GRABChunk grab;
|
private GRABChunk grab;
|
||||||
private CAMGChunk viewPort;
|
private CAMGChunk viewPort;
|
||||||
private MultiPalette paletteChange;
|
private MultiPalette paletteChange;
|
||||||
|
private final List<GenericChunk> meta = new ArrayList<>();
|
||||||
private int formType;
|
private int formType;
|
||||||
private long bodyStart;
|
private long bodyStart;
|
||||||
|
|
||||||
private BufferedImage image;
|
private BufferedImage image;
|
||||||
private DataInputStream byteRunStream;
|
private DataInputStream byteRunStream;
|
||||||
|
|
||||||
public IFFImageReader() {
|
IFFImageReader(ImageReaderSpi pProvider) {
|
||||||
super(new IFFImageReaderSpi());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IFFImageReader(ImageReaderSpi pProvider) {
|
|
||||||
super(pProvider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +137,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
header = null;
|
header = null;
|
||||||
colorMap = null;
|
colorMap = null;
|
||||||
@ -140,6 +145,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
body = null;
|
body = null;
|
||||||
viewPort = null;
|
viewPort = null;
|
||||||
formType = 0;
|
formType = 0;
|
||||||
|
meta.clear();
|
||||||
|
|
||||||
image = null;
|
image = null;
|
||||||
byteRunStream = null;
|
byteRunStream = null;
|
||||||
@ -258,11 +264,6 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
// System.out.println(ctbl);
|
// System.out.println(ctbl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IFF.CHUNK_JUNK:
|
|
||||||
// Always skip junk chunks
|
|
||||||
IFFChunk.skipData(imageInput, length, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IFF.CHUNK_BODY:
|
case IFF.CHUNK_BODY:
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
throw new IIOException("Multiple BODY chunks not allowed");
|
throw new IIOException("Multiple BODY chunks not allowed");
|
||||||
@ -274,18 +275,32 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
// NOTE: We don't read the body here, it's done later in the read(int, ImageReadParam) method
|
// NOTE: We don't read the body here, it's done later in the read(int, ImageReadParam) method
|
||||||
// Done reading meta
|
// Done reading meta
|
||||||
return;
|
return;
|
||||||
default:
|
|
||||||
// TODO: We probably want to store ANNO, TEXT, AUTH, COPY etc chunks as Metadata
|
case IFF.CHUNK_ANNO:
|
||||||
// SHAM, ANNO, DEST, SPRT and more
|
case IFF.CHUNK_AUTH:
|
||||||
IFFChunk generic = new GenericChunk(chunkId, length);
|
case IFF.CHUNK_COPY:
|
||||||
|
case IFF.CHUNK_NAME:
|
||||||
|
case IFF.CHUNK_TEXT:
|
||||||
|
case IFF.CHUNK_UTF8:
|
||||||
|
GenericChunk generic = new GenericChunk(chunkId, length);
|
||||||
generic.readChunk(imageInput);
|
generic.readChunk(imageInput);
|
||||||
|
meta.add(generic);
|
||||||
|
|
||||||
// System.out.println(generic);
|
// System.out.println(generic);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IFF.CHUNK_JUNK:
|
||||||
|
// Always skip junk chunks
|
||||||
|
default:
|
||||||
|
// TODO: SHAM, DEST, SPRT and more
|
||||||
|
// Everything else, we'll just skip
|
||||||
|
IFFChunk.skipData(imageInput, length, 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||||
init(pIndex);
|
init(pIndex);
|
||||||
|
|
||||||
@ -314,16 +329,26 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getWidth(int pIndex) throws IOException {
|
public int getWidth(int pIndex) throws IOException {
|
||||||
init(pIndex);
|
init(pIndex);
|
||||||
return header.width;
|
return header.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getHeight(int pIndex) throws IOException {
|
public int getHeight(int pIndex) throws IOException {
|
||||||
init(pIndex);
|
init(pIndex);
|
||||||
return header.height;
|
return header.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
|
||||||
|
init(imageIndex);
|
||||||
|
|
||||||
|
return new IFFImageMetadata(formType, header, colorMap != null ? colorMap.getIndexColorModel(header, isEHB()) : null, viewPort, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
|
public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
|
||||||
init(pIndex);
|
init(pIndex);
|
||||||
|
|
||||||
@ -363,12 +388,11 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
if (colorMap != null) {
|
if (colorMap != null) {
|
||||||
IndexColorModel cm = colorMap.getIndexColorModel(header, isEHB());
|
IndexColorModel cm = colorMap.getIndexColorModel(header, isEHB());
|
||||||
specifier = ImageTypeSpecifiers.createFromIndexColorModel(cm);
|
specifier = ImageTypeSpecifiers.createFromIndexColorModel(cm);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
specifier = ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
|
specifier = ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// NOTE: HAM modes falls through, as they are converted to RGB
|
// NOTE: HAM modes falls through, as they are converted to RGB
|
||||||
case 24:
|
case 24:
|
||||||
@ -786,7 +810,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] pArgs) throws IOException {
|
public static void main(String[] pArgs) throws IOException {
|
||||||
ImageReader reader = new IFFImageReader();
|
ImageReader reader = new IFFImageReader(new IFFImageReaderSpi());
|
||||||
|
|
||||||
boolean scale = false;
|
boolean scale = false;
|
||||||
for (String arg : pArgs) {
|
for (String arg : pArgs) {
|
||||||
|
@ -30,12 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Locale;
|
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IFFImageReaderSpi
|
* IFFImageReaderSpi
|
||||||
@ -52,6 +53,7 @@ public final class IFFImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
super(new IFFProviderInfo());
|
super(new IFFProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean canDecodeInput(Object pSource) throws IOException {
|
public boolean canDecodeInput(Object pSource) throws IOException {
|
||||||
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
|
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
|
||||||
}
|
}
|
||||||
@ -80,10 +82,12 @@ public final class IFFImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ImageReader createReaderInstance(Object pExtension) throws IOException {
|
public ImageReader createReaderInstance(Object pExtension) throws IOException {
|
||||||
return new IFFImageReader(this);
|
return new IFFImageReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getDescription(Locale pLocale) {
|
public String getDescription(Locale pLocale) {
|
||||||
return "Commodore Amiga/Electronic Arts Image Interchange Format (IFF) image reader";
|
return "Commodore Amiga/Electronic Arts Image Interchange Format (IFF) image reader";
|
||||||
}
|
}
|
||||||
|
@ -30,22 +30,31 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import javax.imageio.IIOImage;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.ImageWriteParam;
|
||||||
|
import javax.imageio.ImageWriter;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageWriterBase;
|
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
||||||
import com.twelvemonkeys.io.enc.EncoderStream;
|
import com.twelvemonkeys.io.enc.EncoderStream;
|
||||||
import com.twelvemonkeys.io.enc.PackBitsEncoder;
|
import com.twelvemonkeys.io.enc.PackBitsEncoder;
|
||||||
|
|
||||||
import javax.imageio.*;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writer for Commodore Amiga (Electronic Arts) IFF ILBM (InterLeaved BitMap) format.
|
* Writer for Commodore Amiga (Electronic Arts) IFF ILBM (InterLeaved BitMap) format.
|
||||||
* The IFF format (Interchange File Format) is the standard file format
|
* The IFF format (Interchange File Format) is the standard file format
|
||||||
@ -57,24 +66,23 @@ import java.io.OutputStream;
|
|||||||
* @see <a href="http://en.wikipedia.org/wiki/Interchange_File_Format">Wikipedia: IFF</a>
|
* @see <a href="http://en.wikipedia.org/wiki/Interchange_File_Format">Wikipedia: IFF</a>
|
||||||
* @see <a href="http://en.wikipedia.org/wiki/ILBM">Wikipedia: IFF ILBM</a>
|
* @see <a href="http://en.wikipedia.org/wiki/ILBM">Wikipedia: IFF ILBM</a>
|
||||||
*/
|
*/
|
||||||
public class IFFImageWriter extends ImageWriterBase {
|
public final class IFFImageWriter extends ImageWriterBase {
|
||||||
|
|
||||||
public IFFImageWriter() {
|
IFFImageWriter(ImageWriterSpi pProvider) {
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IFFImageWriter(ImageWriterSpi pProvider) {
|
|
||||||
super(pProvider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) {
|
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) {
|
||||||
throw new UnsupportedOperationException("Method getDefaultImageMetadata not implemented");// TODO: Implement
|
throw new UnsupportedOperationException("Method getDefaultImageMetadata not implemented");// TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) {
|
public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) {
|
||||||
throw new UnsupportedOperationException("Method convertImageMetadata not implemented");// TODO: Implement
|
throw new UnsupportedOperationException("Method convertImageMetadata not implemented");// TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void write(IIOMetadata pStreamMetadata, IIOImage pImage, ImageWriteParam pParam) throws IOException {
|
public void write(IIOMetadata pStreamMetadata, IIOImage pImage, ImageWriteParam pParam) throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
|
||||||
@ -105,13 +113,9 @@ public class IFFImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
// NOTE: This is much faster than imageOutput.write(pImageData.toByteArray())
|
// NOTE: This is much faster than imageOutput.write(pImageData.toByteArray())
|
||||||
// as the data array is not duplicated
|
// as the data array is not duplicated
|
||||||
OutputStream adapter = IIOUtil.createStreamAdapter(imageOutput);
|
try (OutputStream adapter = IIOUtil.createStreamAdapter(imageOutput)) {
|
||||||
try {
|
|
||||||
pImageData.writeTo(adapter);
|
pImageData.writeTo(adapter);
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
adapter.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pImageData.size() % 2 == 0) {
|
if (pImageData.size() % 2 == 0) {
|
||||||
imageOutput.writeByte(0); // PAD
|
imageOutput.writeByte(0); // PAD
|
||||||
@ -180,7 +184,7 @@ public class IFFImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
private void writeMeta(RenderedImage pImage, int pBodyLength) throws IOException {
|
private void writeMeta(RenderedImage pImage, int pBodyLength) throws IOException {
|
||||||
// Annotation ANNO chunk, 8 + annoData.length bytes
|
// Annotation ANNO chunk, 8 + annoData.length bytes
|
||||||
String annotation = "Written by " + getOriginatingProvider().getDescription(null) + " by " + getOriginatingProvider().getVendorName();
|
String annotation = String.format("Written by %s IFFImageWriter %s", getOriginatingProvider().getVendorName(), getOriginatingProvider().getVersion());
|
||||||
GenericChunk anno = new GenericChunk(IFFUtil.toInt("ANNO".getBytes()), annotation.getBytes());
|
GenericChunk anno = new GenericChunk(IFFUtil.toInt("ANNO".getBytes()), annotation.getBytes());
|
||||||
|
|
||||||
ColorModel cm = pImage.getColorModel();
|
ColorModel cm = pImage.getColorModel();
|
||||||
|
@ -30,12 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Locale;
|
import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IFFImageWriterSpi
|
* IFFImageWriterSpi
|
||||||
@ -58,10 +59,12 @@ public class IFFImageWriterSpi extends ImageWriterSpiBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ImageWriter createWriterInstance(Object pExtension) throws IOException {
|
public ImageWriter createWriterInstance(Object pExtension) throws IOException {
|
||||||
return new IFFImageWriter(this);
|
return new IFFImageWriter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getDescription(Locale pLocale) {
|
public String getDescription(Locale pLocale) {
|
||||||
return "Commodore Amiga/Electronic Arts Image Interchange Format (IFF) image writer";
|
return "Commodore Amiga/Electronic Arts Image Interchange Format (IFF) image writer";
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ package com.twelvemonkeys.imageio.plugins.iff;
|
|||||||
* @author Harald Kuhr (Java port)
|
* @author Harald Kuhr (Java port)
|
||||||
* @version $Id: IFFUtil.java,v 1.0 06.mar.2006 13:31:35 haku Exp$
|
* @version $Id: IFFUtil.java,v 1.0 06.mar.2006 13:31:35 haku Exp$
|
||||||
*/
|
*/
|
||||||
class IFFUtil {
|
final class IFFUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a rotation table
|
* Creates a rotation table
|
||||||
|
@ -0,0 +1,511 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.function.ThrowingRunnable;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
public class IFFImageMetadataTest {
|
||||||
|
@Test
|
||||||
|
public void testStandardFeatures() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
final IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
// Standard metadata format
|
||||||
|
assertTrue(metadata.isStandardMetadataFormatSupported());
|
||||||
|
Node root = metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
assertNotNull(root);
|
||||||
|
assertTrue(root instanceof IIOMetadataNode);
|
||||||
|
|
||||||
|
// Other formats
|
||||||
|
assertNull(metadata.getNativeMetadataFormatName());
|
||||||
|
assertNull(metadata.getExtraMetadataFormatNames());
|
||||||
|
assertThrows(IllegalArgumentException.class, new ThrowingRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
metadata.getAsTree("com_foo_bar_1.0");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Read-only
|
||||||
|
assertTrue(metadata.isReadOnly());
|
||||||
|
assertThrows(IllegalStateException.class, new ThrowingRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() throws Throwable {
|
||||||
|
metadata.mergeTree(IIOMetadataFormatImpl.standardMetadataFormatName, new IIOMetadataNode(IIOMetadataFormatImpl.standardMetadataFormatName));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardChromaGray() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode chroma = metadata.getStandardChromaNode();
|
||||||
|
assertNotNull(chroma);
|
||||||
|
assertEquals("Chroma", chroma.getNodeName());
|
||||||
|
assertEquals(3, chroma.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode colorSpaceType = (IIOMetadataNode) chroma.getFirstChild();
|
||||||
|
assertEquals("ColorSpaceType", colorSpaceType.getNodeName());
|
||||||
|
assertEquals("GRAY", colorSpaceType.getAttribute("name"));
|
||||||
|
|
||||||
|
IIOMetadataNode numChannels = (IIOMetadataNode) colorSpaceType.getNextSibling();
|
||||||
|
assertEquals("NumChannels", numChannels.getNodeName());
|
||||||
|
assertEquals("1", numChannels.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode blackIsZero = (IIOMetadataNode) numChannels.getNextSibling();
|
||||||
|
assertEquals("BlackIsZero", blackIsZero.getNodeName());
|
||||||
|
assertEquals("TRUE", blackIsZero.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(blackIsZero.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardChromaRGB() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode chroma = metadata.getStandardChromaNode();
|
||||||
|
assertNotNull(chroma);
|
||||||
|
assertEquals("Chroma", chroma.getNodeName());
|
||||||
|
assertEquals(3, chroma.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode colorSpaceType = (IIOMetadataNode) chroma.getFirstChild();
|
||||||
|
assertEquals("ColorSpaceType", colorSpaceType.getNodeName());
|
||||||
|
assertEquals("RGB", colorSpaceType.getAttribute("name"));
|
||||||
|
|
||||||
|
IIOMetadataNode numChannels = (IIOMetadataNode) colorSpaceType.getNextSibling();
|
||||||
|
assertEquals("NumChannels", numChannels.getNodeName());
|
||||||
|
assertEquals("3", numChannels.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode blackIsZero = (IIOMetadataNode) numChannels.getNextSibling();
|
||||||
|
assertEquals("BlackIsZero", blackIsZero.getNodeName());
|
||||||
|
assertEquals("TRUE", blackIsZero.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(blackIsZero.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardChromaPalette() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 1, BMHDChunk.MASK_TRANSPARENT_COLOR, BMHDChunk.COMPRESSION_BYTE_RUN, 1);
|
||||||
|
|
||||||
|
byte[] bw = {0, (byte) 0xff};
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, new IndexColorModel(header.bitplanes, bw.length, bw, bw, bw, header.transparentIndex), null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode chroma = metadata.getStandardChromaNode();
|
||||||
|
assertNotNull(chroma);
|
||||||
|
assertEquals("Chroma", chroma.getNodeName());
|
||||||
|
assertEquals(4, chroma.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode colorSpaceType = (IIOMetadataNode) chroma.getFirstChild();
|
||||||
|
assertEquals("ColorSpaceType", colorSpaceType.getNodeName());
|
||||||
|
assertEquals("RGB", colorSpaceType.getAttribute("name"));
|
||||||
|
|
||||||
|
IIOMetadataNode numChannels = (IIOMetadataNode) colorSpaceType.getNextSibling();
|
||||||
|
assertEquals("NumChannels", numChannels.getNodeName());
|
||||||
|
assertEquals("3", numChannels.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode blackIsZero = (IIOMetadataNode) numChannels.getNextSibling();
|
||||||
|
assertEquals("BlackIsZero", blackIsZero.getNodeName());
|
||||||
|
assertEquals("TRUE", blackIsZero.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode palette = (IIOMetadataNode) blackIsZero.getNextSibling();
|
||||||
|
assertEquals("Palette", palette.getNodeName());
|
||||||
|
assertEquals(bw.length, palette.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < palette.getLength(); i++) {
|
||||||
|
IIOMetadataNode item0 = (IIOMetadataNode) palette.item(i);
|
||||||
|
assertEquals("PaletteEntry", item0.getNodeName());
|
||||||
|
assertEquals(String.valueOf(i), item0.getAttribute("index"));
|
||||||
|
String rgb = String.valueOf(bw[i] & 0xff);
|
||||||
|
assertEquals(rgb, item0.getAttribute("red"));
|
||||||
|
assertEquals(rgb, item0.getAttribute("green"));
|
||||||
|
assertEquals(rgb, item0.getAttribute("blue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: BackgroundIndex == 1??
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardCompressionRLE() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode compression = metadata.getStandardCompressionNode();
|
||||||
|
assertNotNull(compression);
|
||||||
|
assertEquals("Compression", compression.getNodeName());
|
||||||
|
assertEquals(2, compression.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode compressionTypeName = (IIOMetadataNode) compression.getFirstChild();
|
||||||
|
assertEquals("CompressionTypeName", compressionTypeName.getNodeName());
|
||||||
|
assertEquals("RLE", compressionTypeName.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode lossless = (IIOMetadataNode) compressionTypeName.getNextSibling();
|
||||||
|
assertEquals("Lossless", lossless.getNodeName());
|
||||||
|
assertEquals("TRUE", lossless.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(lossless.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardCompressionNone() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_NONE, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
assertNull(metadata.getStandardCompressionNode()); // No compression, all default...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDataILBM_Gray() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode data = metadata.getStandardDataNode();
|
||||||
|
assertNotNull(data);
|
||||||
|
assertEquals("Data", data.getNodeName());
|
||||||
|
assertEquals(3, data.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode planarConfiguration = (IIOMetadataNode) data.getFirstChild();
|
||||||
|
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
|
||||||
|
assertEquals("PlaneInterleaved", planarConfiguration.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFomat = (IIOMetadataNode) planarConfiguration.getNextSibling();
|
||||||
|
assertEquals("SampleFormat", sampleFomat.getNodeName());
|
||||||
|
assertEquals("UnsignedIntegral", sampleFomat.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode bitsPerSample = (IIOMetadataNode) sampleFomat.getNextSibling();
|
||||||
|
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
|
||||||
|
assertEquals("8", bitsPerSample.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(bitsPerSample.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDataILBM_RGB() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode data = metadata.getStandardDataNode();
|
||||||
|
assertNotNull(data);
|
||||||
|
assertEquals("Data", data.getNodeName());
|
||||||
|
assertEquals(3, data.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode planarConfiguration = (IIOMetadataNode) data.getFirstChild();
|
||||||
|
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
|
||||||
|
assertEquals("PlaneInterleaved", planarConfiguration.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFomat = (IIOMetadataNode) planarConfiguration.getNextSibling();
|
||||||
|
assertEquals("SampleFormat", sampleFomat.getNodeName());
|
||||||
|
assertEquals("UnsignedIntegral", sampleFomat.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode bitsPerSample = (IIOMetadataNode) sampleFomat.getNextSibling();
|
||||||
|
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
|
||||||
|
assertEquals("8 8 8", bitsPerSample.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(bitsPerSample.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDataILBM_RGBA() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 32, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode data = metadata.getStandardDataNode();
|
||||||
|
assertNotNull(data);
|
||||||
|
assertEquals("Data", data.getNodeName());
|
||||||
|
assertEquals(3, data.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode planarConfiguration = (IIOMetadataNode) data.getFirstChild();
|
||||||
|
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
|
||||||
|
assertEquals("PlaneInterleaved", planarConfiguration.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFomat = (IIOMetadataNode) planarConfiguration.getNextSibling();
|
||||||
|
assertEquals("SampleFormat", sampleFomat.getNodeName());
|
||||||
|
assertEquals("UnsignedIntegral", sampleFomat.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode bitsPerSample = (IIOMetadataNode) sampleFomat.getNextSibling();
|
||||||
|
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
|
||||||
|
assertEquals("8 8 8 8", bitsPerSample.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(bitsPerSample.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDataILBM_Palette() {
|
||||||
|
for (int i = 1; i <= 8; i++) {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, i, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
byte[] rgb = new byte[2 << i]; // Colors doesn't really matter here
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, new IndexColorModel(header.bitplanes, rgb.length, rgb, rgb, rgb, 0), null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode data = metadata.getStandardDataNode();
|
||||||
|
assertNotNull(data);
|
||||||
|
assertEquals("Data", data.getNodeName());
|
||||||
|
assertEquals(3, data.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode planarConfiguration = (IIOMetadataNode) data.getFirstChild();
|
||||||
|
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
|
||||||
|
assertEquals("PlaneInterleaved", planarConfiguration.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFomat = (IIOMetadataNode) planarConfiguration.getNextSibling();
|
||||||
|
assertEquals("SampleFormat", sampleFomat.getNodeName());
|
||||||
|
assertEquals("Index", sampleFomat.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode bitsPerSample = (IIOMetadataNode) sampleFomat.getNextSibling();
|
||||||
|
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
|
||||||
|
assertEquals(String.valueOf(i), bitsPerSample.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(bitsPerSample.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDataPBM_Gray() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_PBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode data = metadata.getStandardDataNode();
|
||||||
|
assertNotNull(data);
|
||||||
|
assertEquals("Data", data.getNodeName());
|
||||||
|
assertEquals(3, data.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode planarConfiguration = (IIOMetadataNode) data.getFirstChild();
|
||||||
|
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
|
||||||
|
assertEquals("PixelInterleaved", planarConfiguration.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFomat = (IIOMetadataNode) planarConfiguration.getNextSibling();
|
||||||
|
assertEquals("SampleFormat", sampleFomat.getNodeName());
|
||||||
|
assertEquals("UnsignedIntegral", sampleFomat.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode bitsPerSample = (IIOMetadataNode) sampleFomat.getNextSibling();
|
||||||
|
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
|
||||||
|
assertEquals("8", bitsPerSample.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(bitsPerSample.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDataPBM_RGB() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_PBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode data = metadata.getStandardDataNode();
|
||||||
|
assertNotNull(data);
|
||||||
|
assertEquals("Data", data.getNodeName());
|
||||||
|
assertEquals(3, data.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode planarConfiguration = (IIOMetadataNode) data.getFirstChild();
|
||||||
|
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
|
||||||
|
assertEquals("PixelInterleaved", planarConfiguration.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode sampleFomat = (IIOMetadataNode) planarConfiguration.getNextSibling();
|
||||||
|
assertEquals("SampleFormat", sampleFomat.getNodeName());
|
||||||
|
assertEquals("UnsignedIntegral", sampleFomat.getAttribute("value"));
|
||||||
|
|
||||||
|
IIOMetadataNode bitsPerSample = (IIOMetadataNode) sampleFomat.getNextSibling();
|
||||||
|
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
|
||||||
|
assertEquals("8 8 8", bitsPerSample.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(bitsPerSample.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDimensionNoViewport() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode dimension = metadata.getStandardDimensionNode();
|
||||||
|
assertNull(dimension);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDimensionNormal() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, new CAMGChunk(4), Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode dimension = metadata.getStandardDimensionNode();
|
||||||
|
assertNotNull(dimension);
|
||||||
|
assertEquals("Dimension", dimension.getNodeName());
|
||||||
|
assertEquals(1, dimension.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) dimension.getFirstChild();
|
||||||
|
assertEquals("PixelAspectRatio", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("1.0", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDimensionHires() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
CAMGChunk viewPort = new CAMGChunk(4);
|
||||||
|
viewPort.camg = 0x8000;
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, viewPort, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode dimension = metadata.getStandardDimensionNode();
|
||||||
|
assertNotNull(dimension);
|
||||||
|
assertEquals("Dimension", dimension.getNodeName());
|
||||||
|
assertEquals(1, dimension.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) dimension.getFirstChild();
|
||||||
|
assertEquals("PixelAspectRatio", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("2.0", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDimensionInterlaced() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
CAMGChunk viewPort = new CAMGChunk(4);
|
||||||
|
viewPort.camg = 0x4;
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, viewPort, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode dimension = metadata.getStandardDimensionNode();
|
||||||
|
assertNotNull(dimension);
|
||||||
|
assertEquals("Dimension", dimension.getNodeName());
|
||||||
|
assertEquals(1, dimension.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) dimension.getFirstChild();
|
||||||
|
assertEquals("PixelAspectRatio", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("0.5", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDimensionHiresInterlaced() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
CAMGChunk viewPort = new CAMGChunk(4);
|
||||||
|
viewPort.camg = 0x8004;
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, viewPort, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode dimension = metadata.getStandardDimensionNode();
|
||||||
|
assertNotNull(dimension);
|
||||||
|
assertEquals("Dimension", dimension.getNodeName());
|
||||||
|
assertEquals(1, dimension.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) dimension.getFirstChild();
|
||||||
|
assertEquals("PixelAspectRatio", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("1.0", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardDocument() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode document = metadata.getStandardDocumentNode();
|
||||||
|
assertNotNull(document);
|
||||||
|
assertEquals("Document", document.getNodeName());
|
||||||
|
assertEquals(1, document.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) document.getFirstChild();
|
||||||
|
assertEquals("FormatVersion", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("1.0", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardText() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 8, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
String[] texts = {"annotation", "äñnótâtïøñ"};
|
||||||
|
List<GenericChunk> meta = Arrays.asList(new GenericChunk(IFF.CHUNK_ANNO, texts[0].getBytes(StandardCharsets.US_ASCII)),
|
||||||
|
new GenericChunk(IFF.CHUNK_UTF8, texts[1].getBytes(StandardCharsets.UTF_8)));
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, meta);
|
||||||
|
|
||||||
|
IIOMetadataNode text = metadata.getStandardTextNode();
|
||||||
|
assertNotNull(text);
|
||||||
|
assertEquals("Text", text.getNodeName());
|
||||||
|
assertEquals(texts.length, text.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < texts.length; i++) {
|
||||||
|
IIOMetadataNode textEntry = (IIOMetadataNode) text.item(i);
|
||||||
|
assertEquals("TextEntry", textEntry.getNodeName());
|
||||||
|
assertEquals(IFFUtil.toChunkStr(meta.get(i).chunkId), textEntry.getAttribute("keyword"));
|
||||||
|
assertEquals(texts[i], textEntry.getAttribute("value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardTransparencyRGB() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 24, BMHDChunk.MASK_NONE, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode transparency = metadata.getStandardTransparencyNode();
|
||||||
|
assertNull(transparency); // No transparency, just defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardTransparencyRGBA() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 32, BMHDChunk.MASK_HAS_MASK, BMHDChunk.COMPRESSION_BYTE_RUN, 0);
|
||||||
|
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, null, null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode transparency = metadata.getStandardTransparencyNode();
|
||||||
|
assertNotNull(transparency);
|
||||||
|
assertEquals("Transparency", transparency.getNodeName());
|
||||||
|
assertEquals(1, transparency.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) transparency.getFirstChild();
|
||||||
|
assertEquals("Alpha", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("nonpremultiplied", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStandardTransparencyPalette() {
|
||||||
|
BMHDChunk header = new BMHDChunk(300, 200, 1, BMHDChunk.MASK_TRANSPARENT_COLOR, BMHDChunk.COMPRESSION_BYTE_RUN, 1);
|
||||||
|
|
||||||
|
byte[] bw = {0, (byte) 0xff};
|
||||||
|
IFFImageMetadata metadata = new IFFImageMetadata(IFF.TYPE_ILBM, header, new IndexColorModel(header.bitplanes, bw.length, bw, bw, bw, header.transparentIndex), null, Collections.<GenericChunk>emptyList());
|
||||||
|
|
||||||
|
IIOMetadataNode transparency = metadata.getStandardTransparencyNode();
|
||||||
|
assertNotNull(transparency);
|
||||||
|
assertEquals("Transparency", transparency.getNodeName());
|
||||||
|
assertEquals(1, transparency.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = (IIOMetadataNode) transparency.getFirstChild();
|
||||||
|
assertEquals("TransparentIndex", pixelAspectRatio.getNodeName());
|
||||||
|
assertEquals("1", pixelAspectRatio.getAttribute("value"));
|
||||||
|
|
||||||
|
assertNull(pixelAspectRatio.getNextSibling()); // No more children
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user