Mert Sevinc
Mert Sevinc

Reputation: 1026

How can I create a 4-bit PNG with C#?

I am trying to create a 4-bit PNG file in C# but my code does not work.

Here is the code:

 Bitmap bmp = new Bitmap(200, 50, PixelFormat.Format4bppIndexed);
 string f = bmp.PixelFormat.ToString();
 Graphics gImage = Graphics.FromImage(bmp);
 gImage.FillRectangle(Brushes.Red, 0, 0, bmp.Width - 20, bmp.Height - 20);
 gImage.DrawRectangle(Pens.White, 0, 0, bmp.Width - 20, bmp.Height - 20);
 gImage.DrawString("Test", SystemFonts.DefaultFont, Brushes.White, 5, 8);
 bmp.Save("C:\\buttons_normal1.png",ImageFormat.Png);

The code throws an exception at Graphics gImage line due to PixelFormat set to Format4bppIndexed. I saw a solution here suggesting that the final bitmap can be converted to 4-bit, but that code never worked for me.

Any suggestions?

Upvotes: 2

Views: 1905

Answers (2)

mosheb
mosheb

Reputation: 704

Create a non-4bit, and then convert to 4bit using the System.Windows.Media.Imaging library:

    public void to4bit(Bitmap sourceBitmap, Stream outputStream)
    {
        BitmapImage myBitmapImage = ToBitmapImage(sourceBitmap);
        FormatConvertedBitmap fcb = new FormatConvertedBitmap();
        fcb.BeginInit();
        myBitmapImage.DecodePixelWidth = sourceBitmap.Width;
        fcb.Source = myBitmapImage;
        fcb.DestinationFormat = System.Windows.Media.PixelFormats.Gray4;
        fcb.EndInit();

        PngBitmapEncoder bme = new PngBitmapEncoder();
        bme.Frames.Add(BitmapFrame.Create(fcb));
        bme.Save(outputStream);

    }

    private BitmapImage ToBitmapImage(Bitmap sourceBitmap)
    {
        using (var memory = new MemoryStream())
        {
            sourceBitmap.Save(memory, ImageFormat.Png);
            memory.Position = 0;

            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memory;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();

            return bitmapImage;
        }
    }

Upvotes: 0

mbeckish
mbeckish

Reputation: 10579

The problem is that you aren't allowed to create a Graphics object with an indexed pixel format.

One solution would be to create a Graphics object in a different format to do your drawing, and create an empty Bitmap in PixelFormat.Format4bppIndexed format, and copy each pixel from one image to the other.

Upvotes: 1

Related Questions