DUnno what you are doing wrong then, perhaps writing the CRC in the wrong byte order.
Heres a chunk of code that most definitely works.
The actual purpose of this code is rather irrelevant - its the crc generation and writing thats important in your situation.
(For the record, this was a little chunk of code I wrote to fix the palette chunk due to a bug in a particular phones png decoder.)
import java.util.*;
import java.io.*;
public class PNGColorFixer {
public static void main(String [] args) throws Exception
{
File srcImage = new File(args[0]);
byte [] data = new byte[(int)srcImage.length()];
FileInputStream fis = new FileInputStream(srcImage);
fis.read(data);
fis.close();
System.out.println(" ******* PAL FIX *******");
data = fixPal(data);
FileOutputStream fos = new FileOutputStream(args[0]);
fos.write(data);
fos.flush();
fos.close();
}
static final int PNGHEADER_LENGTH = 8;
static final int CHUNKLENGTH_LENGTH = 4;
static final int CHUNKNAME_LENGTH = 4;
static final int CHUNKCRC_LENGTH = 4;
static final int CHUNKNAME_IHDR = ((byte)'I' <<24) | ((byte)'H' <<16) | ((byte)'D' <<8) | ((byte)'R');
static final int CHUNKNAME_IDAT = ((byte)'I' <<24) | ((byte)'D' <<16) | ((byte)'A' <<8) | ((byte)'T');
static final int CHUNKNAME_PLTE = ((byte)'P' <<24) | ((byte)'L' <<16) | ((byte)'T' <<8) | ((byte)'E');
static final int CHUNKNAME_tRNS = ((byte)'t' <<24) | ((byte)'R' <<16) | ((byte)'N' <<8) | ((byte)'S');
static int [] CRC_TABLE;
//changes the 1st color in the palette to pink (fix for the SHITE E710)
// index 0 will almost always be occupied by the transparent color for palettized PNGs
public static byte [] fixPal(byte [] srcData)
{
System.out.println(" ******* srcData length = " + srcData.length + " *******");
/* lazy creation of the CRC_TABLE */
int [] crcTable = CRC_TABLE;
if(crcTable==null)
{
crcTable = new int [256];
int c;
for (int n = 0; n < 256; n++)
{
c = n;
for (int k = 0; k < 8; k++)
{
if ((c & 1) != 0)
{
c = ((int) 0xedb88320) ^ (c >>> 1);
}
else
{
c >>>= 1;
}
}
crcTable[n] = c;
}
CRC_TABLE = crcTable;
}
int palChunkStart =0; //start of the data section of the chunk
int palChunkLength =0;
boolean hasAlpha = false;
// This code assumes the PLTE chunk will appear before the tRNS chunk
out:
for(int i = PNGHEADER_LENGTH;;)
{
int chunkLength = MSB.readInt(srcData,i);
System.out.println("chunkLength=" + chunkLength);
i+=CHUNKLENGTH_LENGTH;
int chunkType = MSB.readInt(srcData,i);
System.out.println("srcChunkType=" + chunkType);
i+=CHUNKNAME_LENGTH;
switch(chunkType)
{
case CHUNKNAME_IDAT:
break out;
case CHUNKNAME_tRNS:
hasAlpha = true;
break;
case CHUNKNAME_PLTE:
palChunkStart = i;
palChunkLength = chunkLength;
break;
}
i+=chunkLength+CHUNKCRC_LENGTH;
}
//if there is no alpha, return with no changes
if(!hasAlpha) return srcData;
MSB.writeByte(255, srcData,palChunkStart);
MSB.writeByte(0, srcData,palChunkStart+1);
MSB.writeByte(255, srcData,palChunkStart+2);
int crc = -1;
//regenerate the CRC for the palette chunk
for(int i = palChunkStart-CHUNKNAME_LENGTH;i < (palChunkStart+palChunkLength);i++)
{
crc = crcTable[(crc ^ srcData[i]) & 0x00ff] ^ (crc >>> 8);
}
crc ^= -1;
MSB.writeInt(crc, srcData, palChunkStart+palChunkLength);
return srcData;
}
public static class LSB
{
public static int readInt(byte [] src, int index)
{
int retValue = ((src[index]&0xFF)) |
((src[index+1]&0xFF) << 8) |
((src[index+2]&0xFF) << 16) |
((src[index+3]&0xFF) << 24);
System.out.println("LSB.readInt @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + retValue + "; " + Integer.toHexString(retValue));
return retValue;
}
public static int readShort(byte [] src, int index)
{
int retValue = (
(src[index]&0xFF) |
((src[index+1]&0xFF) << 8)
)&0xFFFF;
System.out.println("LSB.readShort @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + retValue + "; " + Integer.toHexString(retValue));
return retValue;
}
public static int readByte(byte [] src, int index)
{
int retValue = src[index]&0xFF;
System.out.println("LSB.readByte @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + retValue + "; " + Integer.toHexString(retValue));
return retValue;
}
public static void writeInt(int val, byte [] dst, int index)
{
System.out.println("LSB.writeInt @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + val + "; " + Integer.toHexString(val));
for(int k = 0;k<4;k++)
{
dst[index+k] = (byte)val;
val >>=8;
}
}
public static void writeShort(int val, byte [] dst, int index)
{
System.out.println("LSB.writeShort @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + val + "; " + Integer.toHexString(val));
for(int k = 0;k<2;k++)
{
dst[index+k] = (byte)val;
val >>=8;
}
}
public static void writeByte(int val, byte [] dst, int index)
{
System.out.println("LSB.writeByte @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + val + "; " + Integer.toHexString(val));
dst[index] = (byte)val;
}
public static boolean sanityCheck()
{
byte [] testData = new byte[4];
int testValue = 1;
writeInt(testValue,testData,0);
int testValue2 = readInt(testData,0);
return (testValue==testValue2);
}
}
public static class MSB
{
public static int readInt(byte [] src, int index)
{
int retValue = ((src[index]&0xFF) << 24) | ((src[index+1]&0xFF) << 16) | ((src[index+2]&0xFF) << 8) | ((src[index+3]&0xFF));
System.out.println("MSB.readInt @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + retValue + "; " + Integer.toHexString(retValue));
return retValue;
}
public static int readShort(byte [] src, int index)
{
int retValue = (((src[index]&0xFF) << 8) | ((src[index+1]&0xFF)))&0xFFFF;
System.out.println("MSB.readShort @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + retValue + "; " + Integer.toHexString(retValue));
return retValue;
}
public static int readByte(byte [] src, int index)
{
int retValue = src[index]&0xFF;
System.out.println("MSB.readByte @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + retValue + "; " + Integer.toHexString(retValue));
return retValue;
}
public static void writeInt(int val, byte [] dst, int index)
{
System.out.println("MSB.writeInt @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + val + "; " + Integer.toHexString(val));
for(int k = 3;k>=0;k--)
{
dst[index+k] = (byte)val;
val >>=8;
}
}
public static void writeShort(int val, byte [] dst, int index)
{
System.out.println("MSB.writeShort @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + val + "; " + Integer.toHexString(val));
for(int k = 1;k>=0;k--)
{
dst[index+k] = (byte)val;
val >>=8;
}
}
public static void writeByte(int val, byte [] dst, int index)
{
System.out.println("MSB.writeByte @" + index +" ; " + Integer.toHexString(index));
System.out.println("value = " + val + "; " + Integer.toHexString(val));
dst[index] = (byte)val;
}
public static boolean sanityCheck()
{
byte [] testData = new byte[4];
int testValue = 1;
writeInt(testValue,testData,0);
int testValue2 = readInt(testData,0);
return (testValue==testValue2);
}
}
}