mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-02 19:15:29 -04:00
Added multi-palette support to IFFImageReader + minor clean-up.
This commit is contained in:
parent
926359d9d2
commit
4463a00667
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name "TwelveMonkeys" nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Parts of this code is based on ilbmtoppm.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989 by Jef Poskanzer.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation. This software is provided "as is" without express or
|
||||||
|
* implied warranty.
|
||||||
|
*
|
||||||
|
* Multipalette-support by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbstractMultiPaletteChunk
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: AbstractMultiPaletteChunk.java,v 1.0 30.03.12 15:57 haraldk Exp$
|
||||||
|
*/
|
||||||
|
abstract class AbstractMultiPaletteChunk extends IFFChunk implements MultiPalette {
|
||||||
|
/* scale factor maxval 15 -> maxval 255 */
|
||||||
|
static final int FACTOR_4BIT = 17;
|
||||||
|
|
||||||
|
protected MutableIndexColorModel.PaletteChange[] initialChanges;
|
||||||
|
protected MutableIndexColorModel.PaletteChange[][] changes;
|
||||||
|
|
||||||
|
protected WeakReference<IndexColorModel> originalPalette;
|
||||||
|
protected MutableIndexColorModel mutablePalette;
|
||||||
|
|
||||||
|
public AbstractMultiPaletteChunk(int pChunkId, int pChunkLength) {
|
||||||
|
super(pChunkId, pChunkLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void readChunk(final DataInput pInput) throws IOException {
|
||||||
|
if (chunkId == IFF.CHUNK_SHAM) {
|
||||||
|
pInput.readUnsignedShort(); // Version, typically 0, skipped
|
||||||
|
}
|
||||||
|
|
||||||
|
int rows = chunkLength / 32; /* sizeof(word) * 16 */
|
||||||
|
|
||||||
|
changes = new MutableIndexColorModel.PaletteChange[rows][];
|
||||||
|
|
||||||
|
for (int row = 0; row < rows; row++) {
|
||||||
|
changes[row] = new MutableIndexColorModel.PaletteChange[16];
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
changes[row][i] = new MutableIndexColorModel.PaletteChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++ ) {
|
||||||
|
int data = pInput.readUnsignedShort();
|
||||||
|
|
||||||
|
changes[row][i].index = i;
|
||||||
|
changes[row][i].r = (byte) (((data & 0x0f00) >> 8) * FACTOR_4BIT);
|
||||||
|
changes[row][i].g = (byte) (((data & 0x00f0) >> 4) * FACTOR_4BIT);
|
||||||
|
changes[row][i].b = (byte) (((data & 0x000f) ) * FACTOR_4BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void writeChunk(DataOutput pOutput) throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Method writeChunk not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ColorModel getColorModel(final IndexColorModel colorModel, final int rowIndex, final boolean laced) {
|
||||||
|
if (mutablePalette == null || originalPalette != null && originalPalette.get() != colorModel) {
|
||||||
|
originalPalette = new WeakReference<IndexColorModel>(colorModel);
|
||||||
|
mutablePalette = new MutableIndexColorModel(colorModel);
|
||||||
|
|
||||||
|
if (initialChanges != null) {
|
||||||
|
mutablePalette.adjustColorMap(initialChanges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int row = laced && skipLaced() ? rowIndex / 2 : rowIndex;
|
||||||
|
if (row < changes.length && changes[row] != null) {
|
||||||
|
mutablePalette.adjustColorMap(changes[row]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutablePalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean skipLaced() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,7 @@ import java.io.IOException;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: BMHDChunk.java,v 1.0 28.feb.2006 00:04:32 haku Exp$
|
* @version $Id: BMHDChunk.java,v 1.0 28.feb.2006 00:04:32 haku Exp$
|
||||||
*/
|
*/
|
||||||
class BMHDChunk extends IFFChunk {
|
final class BMHDChunk extends IFFChunk {
|
||||||
//
|
//
|
||||||
// typedef UBYTE Masking; /* Choice of masking technique. */
|
// typedef UBYTE Masking; /* Choice of masking technique. */
|
||||||
//
|
//
|
||||||
|
@ -39,7 +39,7 @@ import java.io.DataOutput;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: BODYChunk.java,v 1.0 28.feb.2006 01:25:49 haku Exp$
|
* @version $Id: BODYChunk.java,v 1.0 28.feb.2006 01:25:49 haku Exp$
|
||||||
*/
|
*/
|
||||||
class BODYChunk extends IFFChunk {
|
final class BODYChunk extends IFFChunk {
|
||||||
protected BODYChunk(int pChunkLength) {
|
protected BODYChunk(int pChunkLength) {
|
||||||
super(IFF.CHUNK_BODY, pChunkLength);
|
super(IFF.CHUNK_BODY, pChunkLength);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import java.io.IOException;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: CAMGChunk.java,v 1.0 28.feb.2006 02:10:07 haku Exp$
|
* @version $Id: CAMGChunk.java,v 1.0 28.feb.2006 02:10:07 haku Exp$
|
||||||
*/
|
*/
|
||||||
class CAMGChunk extends IFFChunk {
|
final class CAMGChunk extends IFFChunk {
|
||||||
// HIRES=0x8000, LACE=0x4
|
// HIRES=0x8000, LACE=0x4
|
||||||
// #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 */
|
||||||
@ -55,6 +55,7 @@ class CAMGChunk extends IFFChunk {
|
|||||||
if (chunkLength != 4) {
|
if (chunkLength != 4) {
|
||||||
throw new IIOException("Unknown CAMG chunk length: " + chunkLength);
|
throw new IIOException("Unknown CAMG chunk length: " + chunkLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
camg = pInput.readInt();
|
camg = pInput.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +63,14 @@ class CAMGChunk extends IFFChunk {
|
|||||||
throw new InternalError("Not implemented: writeChunk()");
|
throw new InternalError("Not implemented: writeChunk()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isHires() {
|
||||||
|
return (camg & 0x8000) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLaced() {
|
||||||
|
return (camg & 0x4) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isHAM() {
|
boolean isHAM() {
|
||||||
return (camg & 0x800) != 0;
|
return (camg & 0x800) != 0;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ import java.io.IOException;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: CMAPChunk.java,v 1.0 28.feb.2006 00:38:05 haku Exp$
|
* @version $Id: CMAPChunk.java,v 1.0 28.feb.2006 00:38:05 haku Exp$
|
||||||
*/
|
*/
|
||||||
class CMAPChunk extends IFFChunk {
|
final class CMAPChunk extends IFFChunk {
|
||||||
|
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
// UBYTE red, green, blue; /* color intensities 0..255 */
|
// UBYTE red, green, blue; /* color intensities 0..255 */
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name "TwelveMonkeys" nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CTBLChunk
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: CTBLChunk.java,v 1.0 30.03.12 14:53 haraldk Exp$
|
||||||
|
*/
|
||||||
|
final class CTBLChunk extends AbstractMultiPaletteChunk {
|
||||||
|
protected CTBLChunk(int pChunkLength) {
|
||||||
|
super(IFF.CHUNK_CTBL, pChunkLength);
|
||||||
|
}
|
||||||
|
}
|
@ -42,7 +42,7 @@ import java.io.IOException;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: GRABChunk.java,v 1.0 28.feb.2006 01:55:05 haku Exp$
|
* @version $Id: GRABChunk.java,v 1.0 28.feb.2006 01:55:05 haku Exp$
|
||||||
*/
|
*/
|
||||||
class GRABChunk extends IFFChunk {
|
final class GRABChunk extends IFFChunk {
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
// WORD x, y; /* relative coordinates (pixels) */
|
// WORD x, y; /* relative coordinates (pixels) */
|
||||||
// } Point2D;
|
// } Point2D;
|
||||||
|
@ -39,7 +39,7 @@ import java.io.DataOutput;
|
|||||||
* @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: UnknownChunk.java,v 1.0 28.feb.2006 00:53:47 haku Exp$
|
||||||
*/
|
*/
|
||||||
class GenericChunk extends IFFChunk {
|
final class GenericChunk extends IFFChunk {
|
||||||
|
|
||||||
byte[] data;
|
byte[] data;
|
||||||
|
|
||||||
@ -56,15 +56,7 @@ class GenericChunk extends IFFChunk {
|
|||||||
void readChunk(DataInput pInput) throws IOException {
|
void readChunk(DataInput pInput) throws IOException {
|
||||||
pInput.readFully(data, 0, data.length);
|
pInput.readFully(data, 0, data.length);
|
||||||
|
|
||||||
int toSkip = chunkLength - data.length;
|
skipData(pInput, chunkLength, data.length);
|
||||||
while (toSkip > 0) {
|
|
||||||
toSkip -= pInput.skipBytes(toSkip);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read pad
|
|
||||||
if (chunkLength % 2 != 0) {
|
|
||||||
pInput.readByte();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChunk(DataOutput pOutput) throws IOException {
|
void writeChunk(DataOutput pOutput) throws IOException {
|
||||||
|
@ -39,12 +39,22 @@ interface IFF {
|
|||||||
/** IFF FORM group chunk */
|
/** IFF FORM group chunk */
|
||||||
int CHUNK_FORM = ('F' << 24) + ('O' << 16) + ('R' << 8) + 'M';
|
int CHUNK_FORM = ('F' << 24) + ('O' << 16) + ('R' << 8) + 'M';
|
||||||
|
|
||||||
/** IFF ILBM form type */
|
/** IFF ILBM form type (Interleaved bitmap) */
|
||||||
int TYPE_ILBM = ('I' << 24) + ('L' << 16) + ('B' << 8) + 'M';
|
int TYPE_ILBM = ('I' << 24) + ('L' << 16) + ('B' << 8) + 'M';
|
||||||
|
|
||||||
/** IFF PBM form type */
|
/** IFF PBM form type (Packed bitmap) */
|
||||||
int TYPE_PBM = ('P' << 24) + ('B' << 16) + ('M' << 8) + ' ';
|
int TYPE_PBM = ('P' << 24) + ('B' << 16) + ('M' << 8) + ' ';
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
/** IFF DEEP form type (TVPaint) */
|
||||||
|
int TYPE_DEEP = ('D' << 24) + ('E' << 16) + ('E' << 8) + 'P';
|
||||||
|
/** IFF RGB8 form type (TurboSilver) */
|
||||||
|
int TYPE_RGB8 = ('R' << 24) + ('G' << 16) + ('B' << 8) + '8';
|
||||||
|
/** IFF RGBN form type (TurboSilver) */
|
||||||
|
int TYPE_RGBN = ('R' << 24) + ('G' << 16) + ('B' << 8) + 'N';
|
||||||
|
/** IFF ACBM form type (Amiga Basic) */
|
||||||
|
int TYPE_ACBM = ('A' << 24) + ('C' << 16) + ('B' << 8) + 'M';
|
||||||
|
|
||||||
/** Bitmap Header chunk */
|
/** Bitmap Header chunk */
|
||||||
int CHUNK_BMHD = ('B' << 24) + ('M' << 16) + ('H' << 8) + 'D';
|
int CHUNK_BMHD = ('B' << 24) + ('M' << 16) + ('H' << 8) + 'D';
|
||||||
|
|
||||||
@ -65,4 +75,53 @@ interface IFF {
|
|||||||
|
|
||||||
/** Main data (body) chunk */
|
/** Main data (body) chunk */
|
||||||
int CHUNK_BODY = ('B' << 24) + ('O' << 16) + ('D' << 8) + 'Y';
|
int CHUNK_BODY = ('B' << 24) + ('O' << 16) + ('D' << 8) + 'Y';
|
||||||
|
|
||||||
|
/** Junk (to allow garbage data in files, without re-writing the entire file) */
|
||||||
|
int CHUNK_JUNK = ('J' << 24) + ('U' << 16) + ('N' << 8) + 'K';
|
||||||
|
|
||||||
|
/** EA IFF 85 Generic Author chunk */
|
||||||
|
int CHUNK_AUTH = ('A' << 24) + ('U' << 16) + ('T' << 8) + 'H';
|
||||||
|
/** EA IFF 85 Generic character string chunk */
|
||||||
|
int CHUNK_CHRS = ('C' << 24) + ('H' << 16) + ('R' << 8) + 'S';
|
||||||
|
/** EA IFF 85 Generic Name of art, music, etc. chunk */
|
||||||
|
int CHUNK_NAME = ('N' << 24) + ('A' << 16) + ('M' << 8) + 'E';
|
||||||
|
/** EA IFF 85 Generic unformatted ASCII text chunk */
|
||||||
|
int CHUNK_TEXT = ('T' << 24) + ('E' << 16) + ('X' << 8) + 'T';
|
||||||
|
/** EA IFF 85 Generic Copyright text chunk */
|
||||||
|
int CHUNK_COPY = ('(' << 24) + ('c' << 16) + (')' << 8) + ' ';
|
||||||
|
|
||||||
|
/** color cycling */
|
||||||
|
int CHUNK_CRNG = ('C' << 24) + ('R' << 16) + ('N' << 8) + 'G';
|
||||||
|
/** color cycling */
|
||||||
|
int CHUNK_CCRT = ('C' << 24) + ('C' << 16) + ('R' << 8) + 'T';
|
||||||
|
/** Color Lookup Table chunk */
|
||||||
|
int CHUNK_CLUT = ('C' << 24) + ('L' << 16) + ('U' << 8) + 'T';
|
||||||
|
/** Dots per inch chunk */
|
||||||
|
int CHUNK_DPI = ('D' << 24) + ('P' << 16) + ('I' << 8) + ' ';
|
||||||
|
/** DPaint perspective chunk (EA) */
|
||||||
|
int CHUNK_DPPV = ('D' << 24) + ('P' << 16) + ('P' << 8) + 'V';
|
||||||
|
/** DPaint IV enhanced color cycle chunk (EA) */
|
||||||
|
int CHUNK_DRNG = ('D' << 24) + ('R' << 16) + ('N' << 8) + 'G';
|
||||||
|
/** Encapsulated Postscript chunk */
|
||||||
|
int CHUNK_EPSF = ('E' << 24) + ('P' << 16) + ('S' << 8) + 'F';
|
||||||
|
/** Cyan, Magenta, Yellow, & Black color map (Soft-Logik) */
|
||||||
|
int CHUNK_CMYK = ('C' << 24) + ('M' << 16) + ('Y' << 8) + 'K';
|
||||||
|
/** Color naming chunk (Soft-Logik) */
|
||||||
|
int CHUNK_CNAM = ('C' << 24) + ('N' << 16) + ('A' << 8) + 'M';
|
||||||
|
/** Line by line palette control information (Sebastiano Vigna) */
|
||||||
|
int CHUNK_PCHG = ('P' << 24) + ('C' << 16) + ('H' << 8) + 'G';
|
||||||
|
/** A mini duplicate ILBM used for preview (Gary Bonham) */
|
||||||
|
int CHUNK_PRVW = ('P' << 24) + ('R' << 16) + ('V' << 8) + 'W';
|
||||||
|
/** eXtended BitMap Information (Soft-Logik) */
|
||||||
|
int CHUNK_XBMI = ('X' << 24) + ('B' << 16) + ('M' << 8) + 'I';
|
||||||
|
/** Newtek Dynamic Ham color chunk */
|
||||||
|
int CHUNK_CTBL = ('C' << 24) + ('T' << 16) + ('B' << 8) + 'L';
|
||||||
|
/** Newtek Dynamic Ham chunk */
|
||||||
|
int CHUNK_DYCP = ('D' << 24) + ('Y' << 16) + ('C' << 8) + 'P';
|
||||||
|
/** Sliced HAM color chunk */
|
||||||
|
int CHUNK_SHAM = ('S' << 24) + ('H' << 16) + ('A' << 8) + 'M';
|
||||||
|
/** ACBM body chunk */
|
||||||
|
int CHUNK_ABIT = ('A' << 24) + ('B' << 16) + ('I' << 8) + 'T';
|
||||||
|
/** unofficial direct color */
|
||||||
|
int CHUNK_DCOL = ('D' << 24) + ('C' << 16) + ('O' << 8) + 'L';
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,19 @@ abstract class IFFChunk {
|
|||||||
|
|
||||||
abstract void writeChunk(DataOutput pOutput) throws IOException;
|
abstract void writeChunk(DataOutput pOutput) throws IOException;
|
||||||
|
|
||||||
|
protected static void skipData(final DataInput pInput, final int chunkLength, final int dataReadSoFar) throws IOException {
|
||||||
|
int toSkip = chunkLength - dataReadSoFar;
|
||||||
|
|
||||||
|
while (toSkip > 0) {
|
||||||
|
toSkip -= pInput.skipBytes(toSkip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read pad
|
||||||
|
if (chunkLength % 2 != 0) {
|
||||||
|
pInput.readByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return IFFUtil.toChunkStr(chunkId) + " chunk (" + chunkLength + " bytes)";
|
return IFFUtil.toChunkStr(chunkId) + " chunk (" + chunkLength + " bytes)";
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
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;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
@ -94,7 +95,9 @@ public 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
|
||||||
// http://amigan.1emu.net/reg/iff.html
|
// http://amigan.1emu.net/index/iff.html
|
||||||
|
|
||||||
|
// TODO: Allow reading rasters for HAM6/HAM8 and multipalette images that are expanded to RGB (24 bit) during read.
|
||||||
|
|
||||||
private BMHDChunk header;
|
private BMHDChunk header;
|
||||||
private CMAPChunk colorMap;
|
private CMAPChunk colorMap;
|
||||||
@ -102,6 +105,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
@SuppressWarnings({"FieldCanBeLocal"})
|
@SuppressWarnings({"FieldCanBeLocal"})
|
||||||
private GRABChunk grab;
|
private GRABChunk grab;
|
||||||
private CAMGChunk viewPort;
|
private CAMGChunk viewPort;
|
||||||
|
private MultiPalette paletteChange;
|
||||||
private int formType;
|
private int formType;
|
||||||
private long bodyStart;
|
private long bodyStart;
|
||||||
|
|
||||||
@ -127,6 +131,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
header = null;
|
header = null;
|
||||||
colorMap = null;
|
colorMap = null;
|
||||||
|
paletteChange = null;
|
||||||
body = null;
|
body = null;
|
||||||
viewPort = null;
|
viewPort = null;
|
||||||
formType = 0;
|
formType = 0;
|
||||||
@ -144,7 +149,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
formType = imageInput.readInt();
|
formType = imageInput.readInt();
|
||||||
if (formType != IFF.TYPE_ILBM && formType != IFF.TYPE_PBM) {
|
if (formType != IFF.TYPE_ILBM && formType != IFF.TYPE_PBM) {
|
||||||
throw new IIOException("Only IFF (FORM) type ILBM and PBM supported: " + IFFUtil.toChunkStr(formType));
|
throw new IIOException("Only IFF FORM types ILBM and PBM supported: " + IFFUtil.toChunkStr(formType));
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println("IFF type FORM " + toChunkStr(type));
|
//System.out.println("IFF type FORM " + toChunkStr(type));
|
||||||
@ -200,6 +205,57 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
//System.out.println(viewPort);
|
//System.out.println(viewPort);
|
||||||
break;
|
break;
|
||||||
|
case IFF.CHUNK_PCHG:
|
||||||
|
if (paletteChange instanceof PCHGChunk) {
|
||||||
|
throw new IIOException("Multiple PCHG chunks not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
PCHGChunk pchg = new PCHGChunk(length);
|
||||||
|
pchg.readChunk(imageInput);
|
||||||
|
|
||||||
|
// Always prefer PCHG style palette changes
|
||||||
|
paletteChange = pchg;
|
||||||
|
|
||||||
|
// System.out.println(paletteChange);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IFF.CHUNK_SHAM:
|
||||||
|
if (paletteChange instanceof SHAMChunk) {
|
||||||
|
throw new IIOException("Multiple SHAM chunks not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
SHAMChunk sham = new SHAMChunk(length);
|
||||||
|
sham.readChunk(imageInput);
|
||||||
|
|
||||||
|
// NOTE: We prefer PHCG to SHAM style palette changes, if both are present
|
||||||
|
if (paletteChange == null) {
|
||||||
|
paletteChange = sham;
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println(paletteChange);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IFF.CHUNK_CTBL:
|
||||||
|
if (paletteChange instanceof CTBLChunk) {
|
||||||
|
throw new IIOException("Multiple CTBL chunks not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
CTBLChunk ctbl = new CTBLChunk(length);
|
||||||
|
ctbl.readChunk(imageInput);
|
||||||
|
|
||||||
|
// NOTE: We prefer PHCG to ctbl style palette changes, if both are present
|
||||||
|
if (paletteChange == null) {
|
||||||
|
paletteChange = ctbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.out.println(paletteChange);
|
||||||
|
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");
|
||||||
@ -209,16 +265,15 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
bodyStart = imageInput.getStreamPosition();
|
bodyStart = imageInput.getStreamPosition();
|
||||||
|
|
||||||
// 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:
|
default:
|
||||||
// TODO: We probably want to store anno chunks as Metadata
|
// TODO: We probably want to store ANNO, TEXT, AUTH, COPY etc chunks as Metadata
|
||||||
// ANNO, DEST, SPRT and more
|
// SHAM, ANNO, DEST, SPRT and more
|
||||||
IFFChunk generic = new GenericChunk(chunkId, length);
|
IFFChunk generic = new GenericChunk(chunkId, length);
|
||||||
generic.readChunk(imageInput);
|
generic.readChunk(imageInput);
|
||||||
|
|
||||||
//System.out.println(generic);
|
// System.out.println(generic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,7 +352,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
case 8:
|
case 8:
|
||||||
// 8 bit
|
// 8 bit
|
||||||
// May be HAM8
|
// May be HAM8
|
||||||
if (!isHAM()) {
|
if (!isConvertToRGB()) {
|
||||||
if (colorMap != null) {
|
if (colorMap != null) {
|
||||||
IndexColorModel cm = colorMap.getIndexColorModel();
|
IndexColorModel cm = colorMap.getIndexColorModel();
|
||||||
specifier = IndexedImageTypeSpecifier.createFromIndexColorModel(cm);
|
specifier = IndexedImageTypeSpecifier.createFromIndexColorModel(cm);
|
||||||
@ -323,6 +378,10 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
return specifier;
|
return specifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isConvertToRGB() {
|
||||||
|
return isHAM() || isPCHG() || isSHAM();
|
||||||
|
}
|
||||||
|
|
||||||
private void readBody(final ImageReadParam pParam) throws IOException {
|
private void readBody(final ImageReadParam pParam) throws IOException {
|
||||||
imageInput.seek(bodyStart);
|
imageInput.seek(bodyStart);
|
||||||
byteRunStream = null;
|
byteRunStream = null;
|
||||||
@ -361,7 +420,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure band settings from param are compatible with images
|
// Ensure band settings from param are compatible with images
|
||||||
checkReadParamBandSettings(pParam, isHAM() ? 3 : 1, image.getSampleModel().getNumBands());
|
checkReadParamBandSettings(pParam, isConvertToRGB() ? 3 : 1, image.getSampleModel().getNumBands());
|
||||||
|
|
||||||
WritableRaster destination = image.getRaster();
|
WritableRaster destination = image.getRaster();
|
||||||
if (destinationBands != null || offset.x != 0 || offset.y != 0) {
|
if (destinationBands != null || offset.x != 0 || offset.y != 0) {
|
||||||
@ -376,7 +435,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
ColorModel cm;
|
ColorModel cm;
|
||||||
WritableRaster raster;
|
WritableRaster raster;
|
||||||
|
|
||||||
if (isHAM()) {
|
if (isConvertToRGB()) {
|
||||||
// TODO: If HAM6, use type USHORT_444_RGB or 2BYTE_444_RGB?
|
// TODO: If HAM6, use type USHORT_444_RGB or 2BYTE_444_RGB?
|
||||||
// Or create a HAMColorModel, if at all possible?
|
// Or create a HAMColorModel, if at all possible?
|
||||||
// TYPE_3BYTE_BGR
|
// TYPE_3BYTE_BGR
|
||||||
@ -398,9 +457,8 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
final byte[] row = new byte[width * 8];
|
final byte[] row = new byte[width * 8];
|
||||||
|
|
||||||
//System.out.println("Data length: " + data.length);
|
// System.out.println("PlaneData length: " + planeData.length);
|
||||||
//System.out.println("PlaneData length: " + planeData.length * planeData[0].length);
|
// System.out.println("Row length: " + row.length);
|
||||||
//System.out.println("Row length: " + row.length);
|
|
||||||
|
|
||||||
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
||||||
|
|
||||||
@ -433,6 +491,12 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
if (isHAM()) {
|
if (isHAM()) {
|
||||||
hamToRGB(row, pModel, data, 0);
|
hamToRGB(row, pModel, data, 0);
|
||||||
}
|
}
|
||||||
|
else if (isConvertToRGB()) {
|
||||||
|
multiPaletteToRGB(srcY, row, pModel, data, 0);
|
||||||
|
}
|
||||||
|
else if (isSHAM()) {
|
||||||
|
throw new UnsupportedOperationException("SHAM not supported (yet)");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
raster.setDataElements(0, 0, width, 1, row);
|
raster.setDataElements(0, 0, width, 1, row);
|
||||||
}
|
}
|
||||||
@ -449,7 +513,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
int dstY = (srcY - aoi.y) / sourceYSubsampling;
|
int dstY = (srcY - aoi.y) / sourceYSubsampling;
|
||||||
// Handle non-converting raster as special case for performance
|
// Handle non-converting raster as special case for performance
|
||||||
if (cm.isCompatibleRaster(destination)) {
|
if (cm.isCompatibleRaster(destination)) {
|
||||||
// Rasters are compatible, just write to destinaiton
|
// Rasters are compatible, just write to destination
|
||||||
if (sourceXSubsampling == 1) {
|
if (sourceXSubsampling == 1) {
|
||||||
destination.setRect(offset.x, dstY, sourceRow);
|
destination.setRect(offset.x, dstY, sourceRow);
|
||||||
// dataElements = raster.getDataElements(aoi.x, 0, aoi.width, 1, dataElements);
|
// dataElements = raster.getDataElements(aoi.x, 0, aoi.width, 1, dataElements);
|
||||||
@ -609,10 +673,12 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
switch (header.compressionType) {
|
switch (header.compressionType) {
|
||||||
case BMHDChunk.COMPRESSION_NONE:
|
case BMHDChunk.COMPRESSION_NONE:
|
||||||
pInput.readFully(pData, pOffset, pPlaneWidth);
|
pInput.readFully(pData, pOffset, pPlaneWidth);
|
||||||
|
|
||||||
// Uncompressed rows must have even number of bytes
|
// Uncompressed rows must have even number of bytes
|
||||||
if ((header.bitplanes * pPlaneWidth) % 2 != 0) {
|
if ((header.bitplanes * pPlaneWidth) % 2 != 0) {
|
||||||
pInput.readByte();
|
pInput.readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BMHDChunk.COMPRESSION_BYTE_RUN:
|
case BMHDChunk.COMPRESSION_BYTE_RUN:
|
||||||
@ -630,6 +696,7 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
byteRunStream.readFully(pData, pOffset, pPlaneWidth);
|
byteRunStream.readFully(pData, pOffset, pPlaneWidth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -638,8 +705,25 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hamToRGB(final byte[] pIndexed, final IndexColorModel pModel,
|
private void multiPaletteToRGB(final int srcY, final byte[] indexed, final IndexColorModel colorModel, final byte[] dest, final int destOffset) {
|
||||||
final byte[] pDest, final int pDestOffset) {
|
final int width = header.width;
|
||||||
|
|
||||||
|
// TODO: Assure we have applied color change for all rows up until rowIndex, in case of source region/subsampling
|
||||||
|
ColorModel palette = paletteChange.getColorModel(colorModel, srcY, isLaced());
|
||||||
|
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
int pixel = indexed[x] & 0xff;
|
||||||
|
|
||||||
|
int rgb = palette.getRGB(pixel);
|
||||||
|
|
||||||
|
int offset = (x * 3) + destOffset;
|
||||||
|
dest[2 + offset] = (byte) ((rgb >> 16) & 0xff);
|
||||||
|
dest[1 + offset] = (byte) ((rgb >> 8) & 0xff);
|
||||||
|
dest[ offset] = (byte) ( rgb & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hamToRGB(final byte[] indexed, final IndexColorModel colorModel, final byte[] dest, final int destOffset) {
|
||||||
final int bits = header.bitplanes;
|
final int bits = header.bitplanes;
|
||||||
final int width = header.width;
|
final int width = header.width;
|
||||||
int lastRed = 0;
|
int lastRed = 0;
|
||||||
@ -647,20 +731,18 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
int lastBlue = 0;
|
int lastBlue = 0;
|
||||||
|
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
int pixel = pIndexed[x] & 0xff;
|
int pixel = indexed[x] & 0xff;
|
||||||
|
|
||||||
//System.out.println("--> ham" + bits);
|
|
||||||
int paletteIndex = bits == 6 ? pixel & 0x0f : pixel & 0x3f;
|
int paletteIndex = bits == 6 ? pixel & 0x0f : pixel & 0x3f;
|
||||||
int indexShift = bits == 6 ? 4 : 2;
|
int indexShift = bits == 6 ? 4 : 2;
|
||||||
int colorMask = bits == 6 ? 0x0f : 0x03;
|
int colorMask = bits == 6 ? 0x0f : 0x03;
|
||||||
//System.out.println("palette index=" + paletteIndex);
|
|
||||||
|
|
||||||
// Get Hold and Modify bits
|
// Get Hold and Modify bits
|
||||||
switch ((pixel >> (8 - indexShift)) & 0x03) {
|
switch ((pixel >> (8 - indexShift)) & 0x03) {
|
||||||
case 0x00:// HOLD
|
case 0x00:// HOLD
|
||||||
lastRed = pModel.getRed(paletteIndex);
|
lastRed = colorModel.getRed(paletteIndex);
|
||||||
lastGreen = pModel.getGreen(paletteIndex);
|
lastGreen = colorModel.getGreen(paletteIndex);
|
||||||
lastBlue = pModel.getBlue(paletteIndex);
|
lastBlue = colorModel.getBlue(paletteIndex);
|
||||||
break;
|
break;
|
||||||
case 0x01:// MODIFY BLUE
|
case 0x01:// MODIFY BLUE
|
||||||
lastBlue = (lastBlue & colorMask) | (paletteIndex << indexShift);
|
lastBlue = (lastBlue & colorMask) | (paletteIndex << indexShift);
|
||||||
@ -672,29 +754,48 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
lastGreen = (lastGreen & colorMask) | (paletteIndex << indexShift);
|
lastGreen = (lastGreen & colorMask) | (paletteIndex << indexShift);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int offset = (x * 3) + pDestOffset;
|
|
||||||
pDest[2 + offset] = (byte) lastRed;
|
int offset = (x * 3) + destOffset;
|
||||||
pDest[1 + offset] = (byte) lastGreen;
|
dest[2 + offset] = (byte) lastRed;
|
||||||
pDest[offset] = (byte) lastBlue;
|
dest[1 + offset] = (byte) lastGreen;
|
||||||
|
dest[ offset] = (byte) lastBlue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSHAM() {
|
||||||
|
// TODO:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPCHG() {
|
||||||
|
return paletteChange != null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isHAM() {
|
private boolean isHAM() {
|
||||||
return viewPort != null && viewPort.isHAM();
|
return viewPort != null && viewPort.isHAM();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLaced() {
|
||||||
|
return viewPort != null && viewPort.isLaced();
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] pArgs) throws IOException {
|
public static void main(String[] pArgs) throws IOException {
|
||||||
ImageReader reader = new IFFImageReader();
|
ImageReader reader = new IFFImageReader();
|
||||||
|
|
||||||
// ImageInputStream input = ImageIO.createImageInputStream(new File(pArgs[0]));
|
boolean scale = false;
|
||||||
ImageInputStream input = new BufferedImageInputStream(ImageIO.createImageInputStream(new File(pArgs[0])));
|
for (String arg : pArgs) {
|
||||||
boolean canRead = reader.getOriginatingProvider().canDecodeInput(input);
|
if (arg.startsWith("-")) {
|
||||||
|
scale = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ImageInputStream input = new BufferedImageInputStream(ImageIO.createImageInputStream(new File(arg)));
|
||||||
|
boolean canRead = reader.getOriginatingProvider().canDecodeInput(input);
|
||||||
|
|
||||||
System.out.println("Can read: " + canRead);
|
System.out.println("Can read: " + canRead);
|
||||||
|
|
||||||
if (canRead) {
|
if (canRead) {
|
||||||
reader.setInput(input);
|
reader.setInput(input);
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
// param.setSourceRegion(new Rectangle(0, 0, 160, 200));
|
// param.setSourceRegion(new Rectangle(0, 0, 160, 200));
|
||||||
// param.setSourceRegion(new Rectangle(160, 200, 160, 200));
|
// param.setSourceRegion(new Rectangle(160, 200, 160, 200));
|
||||||
// param.setSourceRegion(new Rectangle(80, 100, 160, 200));
|
// param.setSourceRegion(new Rectangle(80, 100, 160, 200));
|
||||||
@ -702,10 +803,17 @@ public class IFFImageReader extends ImageReaderBase {
|
|||||||
// param.setSourceSubsampling(3, 3, 0, 0);
|
// param.setSourceSubsampling(3, 3, 0, 0);
|
||||||
// param.setSourceBands(new int[]{0, 1, 2});
|
// param.setSourceBands(new int[]{0, 1, 2});
|
||||||
// param.setDestinationBands(new int[]{1, 0, 2});
|
// param.setDestinationBands(new int[]{1, 0, 2});
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
System.out.println("image = " + image);
|
System.out.println("image = " + image);
|
||||||
|
|
||||||
|
if (scale) {
|
||||||
|
image = new ResampleOp(image.getWidth() / 2, image.getHeight(), ResampleOp.FILTER_LANCZOS).filter(image, null);
|
||||||
|
// image = ImageUtil.createResampled(image, image.getWidth(), image.getHeight() * 2, Image.SCALE_FAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
showIt(image, arg);
|
||||||
|
}
|
||||||
|
|
||||||
showIt(image, pArgs[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name "TwelveMonkeys" nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MultiPalette
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: MultiPalette.java,v 1.0 30.03.12 15:22 haraldk Exp$
|
||||||
|
*/
|
||||||
|
interface MultiPalette {
|
||||||
|
ColorModel getColorModel(IndexColorModel colorModel, int rowIndex, boolean laced);
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name "TwelveMonkeys" nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Parts of this code is based on ilbmtoppm.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989 by Jef Poskanzer.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation. This software is provided "as is" without express or
|
||||||
|
* implied warranty.
|
||||||
|
*
|
||||||
|
* Multipalette-support by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mutable indexed color model.
|
||||||
|
* For use with images that exploits Amiga hardware to change the color
|
||||||
|
* lookup table between scan lines.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: MutableIndexColorModel.java,v 1.0 29.03.12 15:00 haraldk Exp$
|
||||||
|
*/
|
||||||
|
final class MutableIndexColorModel extends ColorModel {
|
||||||
|
final static int MP_REG_IGNORE = -1;
|
||||||
|
|
||||||
|
final int[] rgbs;
|
||||||
|
|
||||||
|
public MutableIndexColorModel(final IndexColorModel base) {
|
||||||
|
super(base.getPixelSize(), base.getComponentSize(), base.getColorSpace(), base.hasAlpha(), base.isAlphaPremultiplied(), base.getTransparency(), base.getTransferType());
|
||||||
|
|
||||||
|
this.rgbs = getRGBs(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] getRGBs(final IndexColorModel colorModel) {
|
||||||
|
int[] rgbs = new int[colorModel.getMapSize()];
|
||||||
|
colorModel.getRGBs(rgbs);
|
||||||
|
return rgbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void adjustColorMap(final PaletteChange[] changes) {
|
||||||
|
for (int i = 0; i < changes.length; i++) {
|
||||||
|
int index = changes[i].index;
|
||||||
|
|
||||||
|
if (index >= rgbs.length) {
|
||||||
|
// TODO: Issue IIO warning
|
||||||
|
System.err.printf("warning - palette change register out of range\n");
|
||||||
|
System.err.printf(" change structure %d index=%d (max %d)\n", i, index, getMapSize() - 1);
|
||||||
|
System.err.printf(" ignoring it... colors might get messed up from here\n");
|
||||||
|
}
|
||||||
|
else if (index != MP_REG_IGNORE) {
|
||||||
|
updateRGB(index, ((changes[i].r & 0xff) << 16) | ((changes[i].g & 0xff) << 8) | (changes[i].b & 0xff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRGB(int pixel) {
|
||||||
|
return rgbs[pixel];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRed(int pixel) {
|
||||||
|
return (rgbs[pixel] >> 16) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGreen(int pixel) {
|
||||||
|
return (rgbs[pixel] >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlue(int pixel) {
|
||||||
|
return rgbs[pixel] & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAlpha(int pixel) {
|
||||||
|
return (rgbs[pixel] >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRGB(int index, int rgb) {
|
||||||
|
rgbs[index] = rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMapSize() {
|
||||||
|
return rgbs.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PaletteChange {
|
||||||
|
/* palette index to change */
|
||||||
|
public int index;
|
||||||
|
/* new colors for index */
|
||||||
|
public byte r;
|
||||||
|
public byte g;
|
||||||
|
public byte b;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name "TwelveMonkeys" nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Parts of this code is based on ilbmtoppm.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989 by Jef Poskanzer.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation. This software is provided "as is" without express or
|
||||||
|
* implied warranty.
|
||||||
|
*
|
||||||
|
* Multipalette-support by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
||||||
|
*/
|
||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PCHGChunk
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: PCHGChunk.java,v 1.0 27.03.12 13:02 haraldk Exp$
|
||||||
|
*/
|
||||||
|
final class PCHGChunk extends AbstractMultiPaletteChunk {
|
||||||
|
// NOTE: Values from ilbm2ppm.
|
||||||
|
final static int PCHG_COMP_NONE = 0;
|
||||||
|
final static int PCHG_COMP_HUFFMAN = 1;
|
||||||
|
|
||||||
|
/** Use SmallLineChanges */
|
||||||
|
final static int PCHGF_12BIT = 1; // NOTE: The beta spec refers to this as PHCGF_4BIT
|
||||||
|
/** Use BigLineChanges */
|
||||||
|
final static int PCHGF_32BIT = 2;
|
||||||
|
/** meaningful only if PCHG_32BIT is on: use the Alpha channel info */
|
||||||
|
final static int PCHGF_USE_ALPHA = 4;
|
||||||
|
|
||||||
|
private int startLine;
|
||||||
|
private int changedLines;
|
||||||
|
private int lineCount;
|
||||||
|
private int totalChanges;
|
||||||
|
private int minReg;
|
||||||
|
|
||||||
|
public PCHGChunk(int pChunkLength) {
|
||||||
|
super(IFF.CHUNK_PCHG, pChunkLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void readChunk(final DataInput pInput) throws IOException {
|
||||||
|
int compression = pInput.readUnsignedShort();
|
||||||
|
int flags = pInput.readUnsignedShort();
|
||||||
|
startLine = pInput.readShort();
|
||||||
|
lineCount = pInput.readUnsignedShort();
|
||||||
|
changedLines = pInput.readUnsignedShort();
|
||||||
|
minReg = pInput.readUnsignedShort();
|
||||||
|
int maxReg = pInput.readUnsignedShort();
|
||||||
|
int maxChanges = pInput.readUnsignedShort(); // We don't really care, as we're not limited by the Amiga display hardware
|
||||||
|
totalChanges = pInput.readInt();
|
||||||
|
|
||||||
|
// System.err.println("compression: " + compression);
|
||||||
|
// System.err.println("flags: " + Integer.toBinaryString(flags));
|
||||||
|
// System.err.println("startLine: " + startLine);
|
||||||
|
// System.err.println("lineCount: " + lineCount);
|
||||||
|
// System.err.println("changedLines: " + changedLines);
|
||||||
|
// System.err.println("minReg: " + minReg);
|
||||||
|
// System.err.println("maxReg: " + maxReg);
|
||||||
|
// System.err.println("maxChanges: " + maxChanges);
|
||||||
|
// System.err.println("totalChanges: " + totalChanges);
|
||||||
|
|
||||||
|
switch (compression) {
|
||||||
|
case PCHG_COMP_NONE:
|
||||||
|
byte[] data = new byte[chunkLength - 20];
|
||||||
|
pInput.readFully(data);
|
||||||
|
|
||||||
|
changes = new MutableIndexColorModel.PaletteChange[startLine + lineCount][];
|
||||||
|
|
||||||
|
if (startLine < 0) {
|
||||||
|
int numChanges = maxReg - minReg + 1;
|
||||||
|
|
||||||
|
initialChanges = new MutableIndexColorModel.PaletteChange[numChanges];
|
||||||
|
for (int i = 0; i < initialChanges.length; i++) {
|
||||||
|
initialChanges[i] = new MutableIndexColorModel.PaletteChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < numChanges; i++) {
|
||||||
|
initialChanges[i].index = MutableIndexColorModel.MP_REG_IGNORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Postpone conversion to actually needed
|
||||||
|
if ((flags & PCHGF_12BIT) != 0) {
|
||||||
|
convertSmallChanges(data);
|
||||||
|
}
|
||||||
|
else if ((flags & PCHGF_32BIT) != 0) {
|
||||||
|
System.err.println("BigLineChanges");
|
||||||
|
|
||||||
|
if ((flags & PCHGF_USE_ALPHA) != 0) {
|
||||||
|
System.err.println("Alpha should be used...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement 32 bit/alpha support
|
||||||
|
throw new UnsupportedOperationException("BigLineChanges not supported (yet)");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case PCHG_COMP_HUFFMAN:
|
||||||
|
// TODO: Implement Huffman decoding
|
||||||
|
throw new IIOException("Huffman PCHG compression not supported");
|
||||||
|
default:
|
||||||
|
throw new IIOException("Unknown PCHG compression: " + compression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void convertSmallChanges(byte[] data) throws IIOException {
|
||||||
|
int thismask = 0;
|
||||||
|
int changeCount, reg;
|
||||||
|
int changeCount16, changeCount32;
|
||||||
|
int smallChange;
|
||||||
|
int totalchanges = 0;
|
||||||
|
int changedlines = changedLines;
|
||||||
|
|
||||||
|
int maskBytesLeft = 4 * ((lineCount + 31) / 32);
|
||||||
|
|
||||||
|
int maskIdx = 0;
|
||||||
|
int dataIdx = maskBytesLeft;
|
||||||
|
int dataBytesLeft = data.length - maskBytesLeft;
|
||||||
|
|
||||||
|
int bits = 0;
|
||||||
|
for (int row = startLine; changedlines != 0 && row < 0; row++) {
|
||||||
|
if (bits == 0) {
|
||||||
|
if (maskBytesLeft == 0) {
|
||||||
|
throw new IIOException("insufficient data in line mask");
|
||||||
|
}
|
||||||
|
|
||||||
|
thismask = data[maskIdx++];
|
||||||
|
--maskBytesLeft;
|
||||||
|
bits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((thismask & (1 << 7)) != 0) {
|
||||||
|
if (dataBytesLeft < 2) {
|
||||||
|
throw new IIOException("insufficient data in SmallLineChanges structures: " + dataBytesLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeCount16 = data[dataIdx++];
|
||||||
|
changeCount32 = data[dataIdx++];
|
||||||
|
dataBytesLeft -= 2;
|
||||||
|
|
||||||
|
changeCount = changeCount16 + changeCount32;
|
||||||
|
|
||||||
|
for (int i = 0; i < changeCount; i++) {
|
||||||
|
if (totalchanges >= this.totalChanges) {
|
||||||
|
throw new IIOException("insufficient data in SmallLineChanges structures (changeCount): " + totalchanges);
|
||||||
|
}
|
||||||
|
if (dataBytesLeft < 2) {
|
||||||
|
throw new IIOException("insufficient data in SmallLineChanges structures: " + dataBytesLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
smallChange = toShort(data, dataIdx);
|
||||||
|
dataIdx += 2;
|
||||||
|
dataBytesLeft -= 2;
|
||||||
|
reg = ((smallChange & 0xf000) >> 12) + (i >= changeCount16 ? 16 : 0);
|
||||||
|
initialChanges[reg - minReg].index = reg;
|
||||||
|
initialChanges[reg - minReg].r = (byte) (((smallChange & 0x0f00) >> 8) * FACTOR_4BIT);
|
||||||
|
initialChanges[reg - minReg].g = (byte) (((smallChange & 0x00f0) >> 4) * FACTOR_4BIT);
|
||||||
|
initialChanges[reg - minReg].b = (byte) (((smallChange & 0x000f) ) * FACTOR_4BIT);
|
||||||
|
++totalchanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
--changedlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
thismask <<= 1;
|
||||||
|
bits--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = startLine; changedlines != 0 && row < this.changes.length; row++) {
|
||||||
|
if (bits == 0) {
|
||||||
|
if (maskBytesLeft == 0) {
|
||||||
|
throw new IIOException("insufficient data in line mask");
|
||||||
|
}
|
||||||
|
|
||||||
|
thismask = data[maskIdx++];
|
||||||
|
--maskBytesLeft;
|
||||||
|
bits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((thismask & (1 << 7)) != 0) {
|
||||||
|
if (dataBytesLeft < 2) {
|
||||||
|
throw new IIOException("insufficient data in SmallLineChanges structures: " + dataBytesLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeCount16 = data[dataIdx++];
|
||||||
|
changeCount32 = data[dataIdx++];
|
||||||
|
dataBytesLeft -= 2;
|
||||||
|
|
||||||
|
changeCount = changeCount16 + changeCount32;
|
||||||
|
|
||||||
|
changes[row] = new MutableIndexColorModel.PaletteChange[changeCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < changeCount; i++) {
|
||||||
|
changes[row][i] = new MutableIndexColorModel.PaletteChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < changeCount; i++) {
|
||||||
|
if (totalchanges >= this.totalChanges) {
|
||||||
|
throw new IIOException("insufficient data in SmallLineChanges structures");
|
||||||
|
}
|
||||||
|
if (dataBytesLeft < 2) {
|
||||||
|
throw new IIOException("insufficient data in SmallLineChanges structures");
|
||||||
|
}
|
||||||
|
|
||||||
|
smallChange = toShort(data, dataIdx);
|
||||||
|
dataIdx += 2;
|
||||||
|
dataBytesLeft -= 2;
|
||||||
|
reg = ((smallChange & 0xf000) >> 12) + (i >= changeCount16 ? 16 : 0);
|
||||||
|
changes[row][i].index = reg;
|
||||||
|
changes[row][i].r = (byte) (((smallChange & 0x0f00) >> 8) * FACTOR_4BIT);
|
||||||
|
changes[row][i].g = (byte) (((smallChange & 0x00f0) >> 4) * FACTOR_4BIT);
|
||||||
|
changes[row][i].b = (byte) (((smallChange & 0x000f) ) * FACTOR_4BIT);
|
||||||
|
++totalchanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
--changedlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
thismask <<= 1;
|
||||||
|
bits--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalchanges != this.totalChanges) {
|
||||||
|
// TODO: Issue IIO warning
|
||||||
|
System.err.printf("warning - got %d change structures, chunk header reports %d", totalchanges, this.totalChanges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Util method
|
||||||
|
private static short toShort(byte[] bytes, int idx) {
|
||||||
|
return (short) ((bytes[idx] & 0xff) << 8 | (bytes[idx + 1] & 0xff));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name "TwelveMonkeys" nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHAMChunk
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: SHAMChunk.java,v 1.0 30.03.12 14:53 haraldk Exp$
|
||||||
|
*/
|
||||||
|
final class SHAMChunk extends AbstractMultiPaletteChunk {
|
||||||
|
protected SHAMChunk(int pChunkLength) {
|
||||||
|
super(IFF.CHUNK_SHAM, pChunkLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean skipLaced() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -52,14 +52,18 @@ public class IFFImageReaderTest extends ImageReaderAbstractTestCase<IFFImageRead
|
|||||||
new TestData(getClassLoaderResource("/iff/survivor.iff"), new Dimension(800, 600)), // 24 bit
|
new TestData(getClassLoaderResource("/iff/survivor.iff"), new Dimension(800, 600)), // 24 bit
|
||||||
// HAM6 - Ok (a lot of visual "fringe", would be interesting to see on a real HAM display)
|
// HAM6 - Ok (a lot of visual "fringe", would be interesting to see on a real HAM display)
|
||||||
new TestData(getClassLoaderResource("/iff/A4000T_HAM6.IFF"), new Dimension(320, 512)), // ham6
|
new TestData(getClassLoaderResource("/iff/A4000T_HAM6.IFF"), new Dimension(320, 512)), // ham6
|
||||||
// HAM8 - Ok (PackBits decoder chokes on padding byte)
|
// HAM8 - Ok
|
||||||
new TestData(getClassLoaderResource("/iff/A4000T_HAM8.IFF"), new Dimension(628, 512)), // ham8
|
new TestData(getClassLoaderResource("/iff/A4000T_HAM8.IFF"), new Dimension(628, 512)), // ham8
|
||||||
// 8 color indexed - Ok
|
// 8 color indexed - Ok
|
||||||
new TestData(getClassLoaderResource("/iff/AmigaBig.iff"), new Dimension(300, 200)), // 8 color
|
|
||||||
// 8 color indexed - Ok
|
|
||||||
new TestData(getClassLoaderResource("/iff/AmigaAmiga.iff"), new Dimension(200, 150)), // 8 color
|
new TestData(getClassLoaderResource("/iff/AmigaAmiga.iff"), new Dimension(200, 150)), // 8 color
|
||||||
// Ok (PackBits decoder chokes on padding byte)
|
// HAM6 - Ok
|
||||||
new TestData(getClassLoaderResource("/iff/Abyss.iff"), new Dimension(320, 400))
|
new TestData(getClassLoaderResource("/iff/Abyss.iff"), new Dimension(320, 400)),
|
||||||
|
// 256 color indexed - Ok
|
||||||
|
new TestData(getClassLoaderResource("/iff/IKKEGOD.iff"), new Dimension(640, 256)),
|
||||||
|
// 16 color indexed, multi palette (PCHG) - Ok
|
||||||
|
new TestData(getClassLoaderResource("/iff/Manhattan.PCHG"), new Dimension(704, 440)),
|
||||||
|
// 16 color indexed, multi palette (PCHG + SHAM) - Ok
|
||||||
|
new TestData(getClassLoaderResource("/iff/Manhattan.PCHG"), new Dimension(704, 440))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
imageio/imageio-iff/src/test/resources/iff/IKKEGOD.iff
Normal file
BIN
imageio/imageio-iff/src/test/resources/iff/IKKEGOD.iff
Normal file
Binary file not shown.
BIN
imageio/imageio-iff/src/test/resources/iff/Manhattan.PCHG
Normal file
BIN
imageio/imageio-iff/src/test/resources/iff/Manhattan.PCHG
Normal file
Binary file not shown.
BIN
imageio/imageio-iff/src/test/resources/iff/Somnambulist-2.SHAM
Normal file
BIN
imageio/imageio-iff/src/test/resources/iff/Somnambulist-2.SHAM
Normal file
Binary file not shown.
5
imageio/imageio-iff/src/test/resources/iff/fair-use.txt
Normal file
5
imageio/imageio-iff/src/test/resources/iff/fair-use.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
The image files in this folder may contain copyrighted artwork. However, I believe that using them for test purposes
|
||||||
|
(without actually displaying the artwork) must be considered fair use.
|
||||||
|
If you disagree for any reason, please send me a note, and I will remove your image from the distribution.
|
||||||
|
|
||||||
|
-- harald.kuhr@gmail.com
|
Loading…
x
Reference in New Issue
Block a user