185 lines
4.4 KiB
Java
185 lines
4.4 KiB
Java
package ar.com.hjg.pngj.chunks;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
import ar.com.hjg.pngj.ImageInfo;
|
|
import ar.com.hjg.pngj.PngHelperInternal;
|
|
import ar.com.hjg.pngj.PngjException;
|
|
import ar.com.hjg.pngj.PngjInputException;
|
|
|
|
/**
|
|
* IHDR chunk.
|
|
* <p>
|
|
* see http://www.w3.org/TR/PNG/#11IHDR
|
|
* <p>
|
|
* This is a special critical Chunk.
|
|
*/
|
|
public class PngChunkIHDR extends PngChunkSingle {
|
|
public final static String ID = ChunkHelper.IHDR;
|
|
|
|
private int cols;
|
|
private int rows;
|
|
private int bitspc;
|
|
private int colormodel;
|
|
private int compmeth;
|
|
private int filmeth;
|
|
private int interlaced;
|
|
|
|
// http://www.w3.org/TR/PNG/#11IHDR
|
|
//
|
|
public PngChunkIHDR(ImageInfo info) { // argument is normally null here, if not null is used to fill the fields
|
|
super(ID, info);
|
|
if (info != null)
|
|
fillFromInfo(info);
|
|
}
|
|
|
|
@Override
|
|
public ChunkOrderingConstraint getOrderingConstraint() {
|
|
return ChunkOrderingConstraint.NA;
|
|
}
|
|
|
|
@Override
|
|
public ChunkRaw createRawChunk() {
|
|
ChunkRaw c = new ChunkRaw(13, ChunkHelper.b_IHDR, true);
|
|
int offset = 0;
|
|
PngHelperInternal.writeInt4tobytes(cols, c.data, offset);
|
|
offset += 4;
|
|
PngHelperInternal.writeInt4tobytes(rows, c.data, offset);
|
|
offset += 4;
|
|
c.data[offset++] = (byte) bitspc;
|
|
c.data[offset++] = (byte) colormodel;
|
|
c.data[offset++] = (byte) compmeth;
|
|
c.data[offset++] = (byte) filmeth;
|
|
c.data[offset++] = (byte) interlaced;
|
|
return c;
|
|
}
|
|
|
|
@Override
|
|
public void parseFromRaw(ChunkRaw c) {
|
|
if (c.len != 13)
|
|
throw new PngjException("Bad IDHR len " + c.len);
|
|
ByteArrayInputStream st = c.getAsByteStream();
|
|
cols = PngHelperInternal.readInt4(st);
|
|
rows = PngHelperInternal.readInt4(st);
|
|
// bit depth: number of bits per channel
|
|
bitspc = PngHelperInternal.readByte(st);
|
|
colormodel = PngHelperInternal.readByte(st);
|
|
compmeth = PngHelperInternal.readByte(st);
|
|
filmeth = PngHelperInternal.readByte(st);
|
|
interlaced = PngHelperInternal.readByte(st);
|
|
}
|
|
|
|
public int getCols() {
|
|
return cols;
|
|
}
|
|
|
|
public void setCols(int cols) {
|
|
this.cols = cols;
|
|
}
|
|
|
|
public int getRows() {
|
|
return rows;
|
|
}
|
|
|
|
public void setRows(int rows) {
|
|
this.rows = rows;
|
|
}
|
|
|
|
public int getBitspc() {
|
|
return bitspc;
|
|
}
|
|
|
|
public void setBitspc(int bitspc) {
|
|
this.bitspc = bitspc;
|
|
}
|
|
|
|
public int getColormodel() {
|
|
return colormodel;
|
|
}
|
|
|
|
public void setColormodel(int colormodel) {
|
|
this.colormodel = colormodel;
|
|
}
|
|
|
|
public int getCompmeth() {
|
|
return compmeth;
|
|
}
|
|
|
|
public void setCompmeth(int compmeth) {
|
|
this.compmeth = compmeth;
|
|
}
|
|
|
|
public int getFilmeth() {
|
|
return filmeth;
|
|
}
|
|
|
|
public void setFilmeth(int filmeth) {
|
|
this.filmeth = filmeth;
|
|
}
|
|
|
|
public int getInterlaced() {
|
|
return interlaced;
|
|
}
|
|
|
|
public void setInterlaced(int interlaced) {
|
|
this.interlaced = interlaced;
|
|
}
|
|
|
|
public boolean isInterlaced() {
|
|
return getInterlaced() == 1;
|
|
}
|
|
|
|
public void fillFromInfo(ImageInfo info) {
|
|
setCols(imgInfo.cols);
|
|
setRows(imgInfo.rows);
|
|
setBitspc(imgInfo.bitDepth);
|
|
int colormodel = 0;
|
|
if (imgInfo.alpha)
|
|
colormodel += 0x04;
|
|
if (imgInfo.indexed)
|
|
colormodel += 0x01;
|
|
if (!imgInfo.greyscale)
|
|
colormodel += 0x02;
|
|
setColormodel(colormodel);
|
|
setCompmeth(0); // compression method 0=deflate
|
|
setFilmeth(0); // filter method (0)
|
|
setInterlaced(0); // we never interlace
|
|
}
|
|
|
|
/** throws PngInputException if unexpected values */
|
|
public ImageInfo createImageInfo() {
|
|
check();
|
|
boolean alpha = (getColormodel() & 0x04) != 0;
|
|
boolean palette = (getColormodel() & 0x01) != 0;
|
|
boolean grayscale = (getColormodel() == 0 || getColormodel() == 4);
|
|
// creates ImgInfo and imgLine, and allocates buffers
|
|
return new ImageInfo(getCols(), getRows(), getBitspc(), alpha, grayscale, palette);
|
|
}
|
|
|
|
public void check() {
|
|
if (cols < 1 || rows < 1 || compmeth != 0 || filmeth != 0)
|
|
throw new PngjInputException("bad IHDR: col/row/compmethod/filmethod invalid");
|
|
if (bitspc != 1 && bitspc != 2 && bitspc != 4 && bitspc != 8 && bitspc != 16)
|
|
throw new PngjInputException("bad IHDR: bitdepth invalid");
|
|
if (interlaced < 0 || interlaced > 1)
|
|
throw new PngjInputException("bad IHDR: interlace invalid");
|
|
switch (colormodel) {
|
|
case 0:
|
|
break;
|
|
case 3:
|
|
if (bitspc == 16)
|
|
throw new PngjInputException("bad IHDR: bitdepth invalid");
|
|
break;
|
|
case 2:
|
|
case 4:
|
|
case 6:
|
|
if (bitspc != 8 && bitspc != 16)
|
|
throw new PngjInputException("bad IHDR: bitdepth invalid");
|
|
break;
|
|
default:
|
|
throw new PngjInputException("bad IHDR: invalid colormodel");
|
|
}
|
|
}
|
|
|
|
}
|