0

I have a PNG file in which I want to set / change the background color in its header.

The picture itself should not be edited. I'm talking about the header here (https://www.metadata2go.com/file-info/background-color). I don't want to change the pixels.

Tried https://learn.microsoft.com/de-de/dotnet/api/system.drawing.image.setpropertyitem?view=dotnet-plat-ext-3.1 but don't know how to add a value that doesn't yet exist and how to match it ID is. Also, I'm not at all sure if it's the right approach.

I can't get any further, can you help me?

Joni
  • 72
  • 1
  • 11

1 Answers1

0

Thanks to Ahmed Abdelhameed the solution is https://www.codeproject.com/Articles/16424/Writing-a-Background-Color-bKGD-Chunk-to-a-PNG-Fil

Here the Code Source: codeproject !

public class BackgroundHeaderChanger
{
    /// <summary>
    /// Calculates a byte array containing the calculated CRC.
    /// </summary>
    /// <param name="buf">The raw data on which to calculate the CRC.</param>
    public static byte[] GetCrc(byte[] buffer)
    {
        uint data = 0xFFFFFFFF;
        int n;

        if (!IsTableCreated)
            CreateCrcTable();

        for (n = 0; n < buffer.Length; n++)
            data = CrcTable[(data ^ buffer[n]) & 0xff] ^ (data >> 8);

        data = data ^ 0xFFFFFFFF;

        byte b1 = Convert.ToByte(data >> 24);
        byte b2 = Convert.ToByte(b1 << 8 ^ data >> 16);
        byte b3 = Convert.ToByte(((data >> 16 << 16) ^ (data >> 8 << 8)) >> 8);
        byte b4 = Convert.ToByte((data >> 8 << 8) ^ data);

        return new byte[] { b1, b2, b3, b4 };
    }

    /// <summary>
    /// Creates the CRC table for calculating a 32-bit CRC.
    /// </summary>
    private static void CreateCrcTable()
    {
        uint c;
        int k;
        int n;

        for (n = 0; n < 256; n++)
        {
            c = (uint)n;

            for (k = 0; k < 8; k++)
            {
                if ((c & 1) == 1)
                {
                    c = 0xedb88320 ^ (c >> 1);
                }
                else
                {
                    c = c >> 1;
                }
            }
            CrcTable[n] = c;
        }
        IsTableCreated = true;
    }
    static uint[] CrcTable = new uint[256];
    static bool IsTableCreated = false;

    /// <summary>
    /// Writes a backup background color to the specified PNG file.
    /// </summary>
    /// <param name="fileName">The path and name of the PNG file to write to.</param>
    /// <param name="color">The <see cref="Color"/> to set as the backup background color.</param>
    public static void WriteBackupBackgroundColor(string fileName, Color color)
    {
        // Length: 6 bytes, bKGD, then the color
        byte[] lengthData = { 0, 0, 0, 6 };
        byte[] bkgdChunk = { 98, 75, 71, 68, 0, color.R, 0, color.G, 0, color.B };
        byte[] crcData = GetCrc(bkgdChunk);
        byte[] data;

        using (FileStream fs = new FileStream(fileName, FileMode.Open))
        using (BinaryReader binReader = new BinaryReader(fs))
        {
            data = binReader.ReadBytes((int)binReader.BaseStream.Length);
        }

        // 18 bytes is the size of a bKGD chunk
        byte[] newData = new byte[data.Length + 18];
        int dataIndex = 0;
        bool wroteChunk = false;

        for (int i = 0; i < data.Length; i++)
        {
            if (!wroteChunk && data[i + 4] == 'I' && data[i + 5] == 'D' && data[i + 6] == 'A' && data[i + 7] == 'T')
            {
                Array.Copy(lengthData, 0, newData, dataIndex, 4);
                dataIndex += 4;
                Array.Copy(bkgdChunk, 0, newData, dataIndex, bkgdChunk.Length);                 
                dataIndex += bkgdChunk.Length;
                Array.Copy(crcData, 0, newData, dataIndex, 4);
                dataIndex += 4;

                wroteChunk = true;
            }
            newData[dataIndex++] = data[i];
        }


        if (File.Exists(fileName))
            File.Delete(fileName);

        using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
        using (BinaryWriter binWriter = new BinaryWriter(fs))
        {
            binWriter.Write(newData);
        }
    }
}

Usage Example:

 BackgroundHeaderChanger.WriteBackupBackgroundColor(@"C:\TestImg\test.png", Color.Black);
Joni
  • 72
  • 1
  • 11