PNGのパレット変換

PNGのパレット変換は、PLTEチャンクが固定された位置にないので検索しなければならないのと、CRCの計算をしなくてはならないので、ちょっと複雑になります。

private int[] crc_table = null;

/**
 * @brief PNG 画像のパレット変更を行います。
 * 
 * @param buf PNG 画像のデータが入ったバッファ
 * @param pal パレット画像のデータが入ったバッファ
 *            (PNG のパレットデータの形式に準ずる)
 * 
 * @return @a buf をコピーしてパレットデータを書き換えたバッファを返します。
 */
private byte[] changePalette(byte[] buf, byte[] pal)
{
    byte[] buf2;

    buf2 = new byte[buf.length];
    System.arraycopy(buf, 0, buf2, 0, buf.length);

    int length;
    int signature;
    int seek;

    // PNG signature + IHDR Chunk
    seek = 8 + 25;

    while (true)
    {
        length      =   ((buf[seek + 0] & 0xff) << 24) |
                        ((buf[seek + 1] & 0xff) << 16) |
                        ((buf[seek + 2] & 0xff) << 8)  |
                        ((buf[seek + 3] & 0xff) << 0);
        seek += 4;
        signature   =   ((buf[seek + 0] & 0xff) << 24) |
                        ((buf[seek + 1] & 0xff) << 16) |
                        ((buf[seek + 2] & 0xff) << 8)  |
                        ((buf[seek + 3] & 0xff) << 0);
        seek += 4;
        if (signature == 0x504C5445)       // PLTE
        {
            int size, crc;
            size = (length < pal.length) ? length : pal.length;

            // copy palette
            System.arraycopy(pal, 0, buf2, seek, size);

            if (crc_table == null)
            {
                // make CRC table
                int c,n,k;
                crc_table = new crc_table[256];
                for (n = 0; n < 256; n++)
                {
                    c = n;
                    for (k = 0; k < 8; k++)
                    {
                        if ((c & 1) != 0)   c = (c >>> 1) ^ 0xedb88320;
                        else                c = (c >>> 1);
                    }
                    crc_table[n] = c;
                }
            }

            // calculate CRC
            crc = 0xffffffff;
            int last = seek + size;
            seek -= 4;
            for (; seek < last; seek++)
            {
                crc = crc_table[(crc ^ (int)buf2[seek]) & 0xff] ^ (crc >>> 8);
            }
            crc ^= 0xffffffff;

            // write CRC
            buf2[seek++] = (crc >>> 24) & 0xff;
            buf2[seek++] = (crc >>> 16) & 0xff;
            buf2[seek++] = (crc >>> 8)  & 0xff;
            buf2[seek++] = (crc >>> 0)  & 0xff;
            
            break;
        }
        seek += length + 4;
    }
    return buf2;
}

めんどい(;´Д`)