在.NET中组合多个PNG8图像的最简单方法
问题描述:
我试图在C#中将一组8位PNG图像组合成更大的PNG图像。奇怪的是,这似乎特别困难。在.NET中组合多个PNG8图像的最简单方法
因为Graphics不支持索引颜色,所以我不能使用它,所以我尝试构建一个非索引位图(使用图形)并将其转换为索引颜色位图。转换很好,但我无法弄清楚如何设置输出图像的调色板。它默认使用一些预定义的调色板,这与我正在寻找的内容无关。
所以:
有没有办法来控制位图调色板?还是有另一种方法(例如System.Windows.Media.Imaging.WriteableBitmap)可以支持这个?
Re:WriteableBitmap:我似乎无法在网上找到任何关于如何将PNG合并到此上下文中的示例,或者即使它尝试使用它也没有任何意义。
答
事实证明,我能够打造出一个非索引位图和使用转换PngBitmapEncoder像这样:
byte[] ConvertTo8bpp(Bitmap sourceBitmap)
{
// generate a custom palette for the bitmap (I already had a list of colors
// from a previous operation
Dictionary<System.Drawing.Color, byte> colorDict = new Dictionary<System.Drawing.Color, byte>(); // lookup table for conversion to indexed color
List<System.Windows.Media.Color> colorList = new List<System.Windows.Media.Color>(); // list for palette creation
byte index = 0;
unchecked
{
foreach (var cc in ColorsFromPreviousOperation)
{
colorDict[cc] = index++;
colorList.Add(cc.ToMediaColor());
}
}
System.Windows.Media.Imaging.BitmapPalette bmpPal = new System.Windows.Media.Imaging.BitmapPalette(colorList);
// create the byte array of raw image data
int width = sourceBitmap.Width;
int height = sourceBitmap.Height;
int stride = sourceBitmap.Width;
byte[] imageData = new byte[width * height];
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
var pixelColor = sourceBitmap.GetPixel(x, y);
imageData[x + (stride * y)] = colorDict[pixelColor];
}
// generate the image source
var bsource = BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed8, bmpPal, imageData, stride);
// encode the image
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Interlace = PngInterlaceOption.Off;
encoder.Frames.Add(BitmapFrame.Create(bsource));
MemoryStream outputStream = new MemoryStream();
encoder.Save(outputStream);
return outputStream.ToArray();
}
加上辅助扩展方法:
public static System.Windows.Media.Color ToMediaColor(this System.Drawing.Color color)
{
return new System.Windows.Media.Color()
{
A = color.A,
R = color.R,
G = color.G,
B = color.B
};
}
注意的警惕:PngBitmapEncoder实际上似乎可以将bpp计数从8减少到4。例如,当我使用6种颜色进行测试时,输出PNG只有4位。当我使用更色彩丰富的图像时,它是8位的。看起来像一个功能到目前为止...虽然它会很好,如果我有明确的控制权。
答
声明,我为Atalasoft工作。
我们的产品DotImage Photo是免费的,可以做到这一点。
要读取PNG
AtalaImage img = new AtalaImage("image.png");
要转换为24 BPP
img = img.GetChangedPixelFormat(newPixelFormat);
创建大小的图像,你要
AtalaImage img2 = new AtalaImage(width, height, color);
使用OverlayCommand叠加的img到IMG2
OverlayCommand cmd = new OverlayCommand(img);
cmd.Apply(img2, point);
为了节省
img2.Save("new.png", new PngEncoder(), null);
如果您需要帮助这个答案无论是评论还是一个论坛条目。
尽管专门提到GIF,但相同的颜色表主要可能适用于... http://support.microsoft.com/kb/319061只有在做一些非常相似的事情时才会尝试使用代码。 – 2010-12-05 03:08:05