blob: 2ca8729b3d23df7ef2bb53424cbab56f6856ee9e [file] [edit]
/*
* Copyright (c) 2014-2021 by Wen Yu
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* or any later version.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
*/
package pixy.image.png;
import java.io.IOException;
import java.io.OutputStream;
import pixy.util.zip.CRC32;
import pixy.io.IOUtils;
import pixy.util.ArrayUtils;
import pixy.util.LangUtils;
/**
* Class for PNG chunks
*
* @author Wen Yu, yuwen_66@yahoo.com
* @version 1.0 11/07/2012
*/
public class Chunk implements Comparable<Chunk> {
private final long length;
private final ChunkType chunkType;
private final byte[] data;
private final long crc;
/**
* Compare different chunks according to their Attribute ranking.
*
* This is intended to be used for comparing chunks with different
* chunk types rather than chunks of the same chunkType which will always
* have the same ranking.
*/
public int compareTo(Chunk that) {
return this.chunkType.getRanking() - that.chunkType.getRanking();
}
public Chunk(ChunkType chunkType, long length, byte[] data, long crc) {
this.length = length;
this.chunkType = chunkType;
this.data = data;
this.crc = crc;
}
public ChunkType getChunkType() {
return chunkType;
}
public long getLength() {
return this.length;
}
public byte[] getData() {
return this.data.clone();
}
public long getCRC() {
return this.crc;
}
public boolean isValidCRC() {
return (calculateCRC(chunkType.getValue(), data) == crc);
}
public void write(OutputStream os) throws IOException {
IOUtils.writeIntMM(os, (int)length);
IOUtils.writeIntMM(os, chunkType.getValue());
IOUtils.write(os, data);
IOUtils.writeIntMM(os, (int)crc);
}
@Override public String toString() {
return this.chunkType.toString();
}
public boolean equals(Object that) {
if (! (that instanceof Chunk)) {
return false;
}
Chunk other = (Chunk)that;
long thisCRC = calculateCRC(this.getChunkType().getValue(), this.getData());
long otherCRC = calculateCRC(other.getChunkType().getValue(), other.getData());
return thisCRC == otherCRC;
}
public int hashCode() {
return LangUtils.longToIntHashCode(calculateCRC(this.getChunkType().getValue(), this.getData()));
}
public static long calculateCRC(int chunkValue, byte[] data)
{
CRC32 crc32 = new CRC32();
crc32.update(ArrayUtils.toByteArrayMM(chunkValue));
crc32.update(data);
return crc32.getValue();
}
public static long calculateCRC(int chunkValue, byte[] data, int offset, int length)
{
CRC32 crc32 = new CRC32();
crc32.update(ArrayUtils.toByteArrayMM(chunkValue));
crc32.update(data, offset, length);
return crc32.getValue();
}
}