C#: Create Indexed PNG Using System.Windows.Media.BitmapSource with Pre-defined Palettes in BitmapPalettes Class
Creating Indexed PNG in C#
In C#, there are mainly two namespaces to creating image...
- System.Drawing namespace
- System.Windows.Media namespace
So, in this post, I will show you how to create indexed png using classes under System.Windows.Media namespace.
Preparation for Using Classes Under System.Windows.Media
You need to add following dlls to your project reference in order to handle images using classes under System.Windows.Media.
- PresentationCore.dll
- Xaml.dll
- WindowsBase.dll
Creating Palette Based Indexed Image
If you would like to create indexed png, first of all, you should create color palette which can hold max 256 colors.
Creating color palette is trivial. Please see the below example code:
var colors = new List<Color>(); colors.Add(Color.FromRgb(255, 0, 0)); // 0 - red colors.Add(Color.FromRgb(0, 255, 0)); // 1 - green var palette = new BitmapPalette(colors);Then you should pass created BitmapPalette object to arguments of BitmapSource.Create method.
int width = 256; int height = 256; int stride = width; // set pixel values byte[] pixels = new byte[height * stride]; var image= BitmapSource.Create( width, height, 96, 96, PixelFormats.Indexed8, // should be indexed image palette, // <- your palette pixels, stride);
Save BitmapSource as PNG
private static void SaveAsPng(this BitmapSource image, string path) { var stream = new FileStream(path, FileMode.Create); var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(image)); encoder.Save(stream); }
Pre-defined Palletes in BitmapPalettes Class
System.Windows.Media.Imaging.BitmapPalettes has following predefined BitmapPalette objects as static fields.
- BlackAndWhite
- BlackAndWhiteTransparent
- Halftone8
- Halftone8Transparent
- Halftone27
- Halftone27Transparent
- Halftone64
- Halftone64Transparent
- Halftone125
- Halftone125Transparent
- Halftone216
- Halftone216Transparent
- Halftone252
- Halftone252Transparent
- Halftone256
- Halftone256Transparent
- Gray4
- Gray4Transparent
- Gray16
- Gray16Transparent
- Gray256
- Gray256Transparent
- WebPalette
- WebPaletteTransparent
I will show you the code and all images generated by the code. Actually this section might be a main part of this post :)
using System.IO; using System.Reflection; using System.Windows.Media; using System.Windows.Media.Imaging; namespace PngTest { public static class IndexedPngGenerateTest { public static void Create_Indexed_Png_For_Predefined_Palletes_In_BitmapPalettes_Class() { // using reflection for iterating predefined palette in BitmapPalettes class. var properties = typeof(BitmapPalettes).GetProperties(BindingFlags.Static | BindingFlags.Public); foreach (var property in properties) { var palette = property.GetValue(null, null) as BitmapPalette; if(palette == null) continue; SaveTestIndexedPng(palette, property.Name); } } public static void SaveTestIndexedPng(BitmapPalette palette, string name) { var image = CreateTestIndexedBitmapSource(palette); image.SaveAsPng("c:\\temp\\BitmapPalettes\\" + name + ".png"); } private static void SaveAsPng(this BitmapSource image, string path) { var stream = new FileStream(path, FileMode.Create); var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(image)); encoder.Save(stream); } private static BitmapSource CreateTestIndexedBitmapSource(BitmapPalette palette) { int width = 256; int height = 256; int stride = width; byte[] pixels = new byte[height * stride]; // set pixel values int colorNum = palette.Colors.Count; int widthPerColor = 256 / colorNum; for (int i = 0, len = pixels.Length; i < len; i++) { pixels[i] = (byte)((i % 256) / widthPerColor); } return BitmapSource.Create( width, height, 96, 96, PixelFormats.Indexed8, palette, pixels, stride); } } }
The indexed png images generated by above program are below.
The program try to allocate the largest width as much as possible for each color in the palette.
Black color bands which sometimes appear in the most right is simply blank space - no color allocated.
コメント