C# 创建8位图像
我正在尝试创建一个带有纯色背景的8位图像。看起来应该很简单,但文件中的详细信息将其列为32位颜色深度。我错过了什么C# 创建8位图像,c#,image,C#,Image,我正在尝试创建一个带有纯色背景的8位图像。看起来应该很简单,但文件中的详细信息将其列为32位颜色深度。我错过了什么 public void CreateImage() { var bmpOut = new Bitmap(300, 300); var g = Graphics.FromImage(bmpOut); g.FillRectangle(new SolidBrush(Color.Gray), 0, 0, 300, 300);
public void CreateImage()
{
var bmpOut = new Bitmap(300, 300);
var g = Graphics.FromImage(bmpOut);
g.FillRectangle(new SolidBrush(Color.Gray), 0, 0, 300, 300);
var stream = new MemoryStream();
bmpOut.Save(stream, GetPngCodecInfo(), GetEncoderParameters());
bmpOut.Save(@"C:\image.png", GetPngCodecInfo(), GetEncoderParameters());
}
public EncoderParameters GetEncoderParameters()
{
var parameters = new EncoderParameters();
parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);
return parameters;
}
public ImageCodecInfo GetPngCodecInfo()
{
var encoders = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo codecInfo = null;
foreach (var imageCodecInfo in encoders)
{
if (imageCodecInfo.FormatID != ImageFormat.Png.Guid)
continue;
codecInfo = imageCodecInfo;
break;
}
return codecInfo;
}
- ImageExtensions.cs
using System.Runtime.InteropServices; using System.Linq; using System.Drawing.Imaging; using System.Drawing; using System; public static partial class ImageExtensions { public static ColorPalette ToGrayScale(this ColorPalette palette) { var entries=palette.Entries; for(var i=entries.Length; i-->0; entries[i]=entries[i].ToGrayScale()) ; return palette; } public static Color ToGrayScale(this Color color, double[] luminance=null) { var list=(luminance??new[] { 0.2989, 0.5870, 0.1140 }).ToList(); var channel=new[] { color.R, color.G, color.B }; var c=(byte)Math.Round(list.Sum(x => x*channel[list.IndexOf(x)])); return Color.FromArgb(c, c, c); } public static Bitmap To8bppIndexed(this Bitmap original) { var rect=new Rectangle(Point.Empty, original.Size); var pixelFormat=PixelFormat.Format8bppIndexed; var destination=new Bitmap(rect.Width, rect.Height, pixelFormat); using(var source=original.Clone(rect, PixelFormat.Format32bppArgb)) { var destinationData=destination.LockBits(rect, ImageLockMode.WriteOnly, pixelFormat); var sourceData=source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat); var destinationSize=destinationData.Stride*destinationData.Height; var destinationBuffer=new byte[destinationSize]; var sourceSize=sourceData.Stride*sourceData.Height; var sourceBuffer=new byte[sourceSize]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, sourceSize); source.UnlockBits(sourceData); destination.Palette=destination.Palette.ToGrayScale(); var list=destination.Palette.Entries.ToList(); for(var y=destination.Height; y-->0; ) { for(var x=destination.Width; x-->0; ) { var pixelIndex=y*destination.Width+x; var sourceIndex=4*pixelIndex; var color= Color.FromArgb( sourceBuffer[0+sourceIndex], sourceBuffer[1+sourceIndex], sourceBuffer[2+sourceIndex], sourceBuffer[3+sourceIndex] ).ToGrayScale(); destinationBuffer[pixelIndex]=(byte)list.IndexOf(color); } } Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, destinationSize); destination.UnlockBits(destinationData); } return destination; } }
调用
bmpOut=bmpOut.to8bpindexed()代码>保存到文件之前 使用此构造函数指定像素格式:
由于无法从索引像素格式创建图形,因此只能将原始像素写入8位图像
Bitmap bitmap = new Bitmap(32, 32, PixelFormat.Format8bppIndexed);
var bitmapData = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), ImageLockMode.ReadWrite, bitmap.PixelFormat);
Random random=new Random();
byte[] buffer=new byte[bitmap.Width*bitmap.Height];
random.NextBytes(buffer);
Marshal.Copy(buffer,0,bitmapData.Scan0,buffer.Length);
bitmap.UnlockBits(bitmapData);
bitmap.Save("test.bmp",ImageFormat.Bmp);
您可以在WinForms上使用以下代码:
或者,如果您可以从WPF引用此类,则会更容易:
您还可以以更高的比特率创建图像,然后在保存之前将其转换为8位。这将允许您在创建图像时使用图形上下文。有关如何转换为8位的建议,请参见此问题:“C:\image.png”
可能是无效路径。。。假设前面有@
(或者为了示例而只是随机字符串)。从我看到的情况来看,您缺少的是调色板…不过要小心。仅指定像素格式是不够的,因为创建8位索引图像将在下一行失败,即从图像创建<代码>图形
。从索引格式创建图形将引发异常:无法从具有索引像素格式的图像创建图形对象。这到底是什么Random
在那里做什么?@nyrguds被用来创建一个随机图像,我想是吧?事实上,我偶然发现了这个答案,我在寻找一种方法来可视化我的随机数据。顺便说一句,这个答案实际上并没有回答这个问题。这不允许用户以任何方式确定如何选择和绘制特定颜色。为此,您需要编辑调色板。据我所见,由此产生的随机图像仅使用8位图像创建的默认调色板的颜色。将调色板转换为新图像的灰度没有意义。只需使用从00,00,00到FF,FF,FF的颜色值填充调色板。使用这样的调色板,您可以100%确保拥有所有灰度值,并且最终像素上的8位值仅等于实际灰度像素颜色的三种颜色分量中的任何一种。不需要更多的查找。