在使用Graphics.FromImage方法的时候,如果传入的System.Drawing.Image图像是索引像素格式,那么将会引发异常并提示以下消息:“无法从带有索引像素格式的图像创建 Graphics 对象。”。
先说下本人遇到的具体情况:由于网站需要添加一个上传图片自动打水印的功能,所以需要使用System.Drawing.Graphics类对图像重新绘制,将水印图片绘制到图片上。但在实际测试中,发现上传图片后,有的图片可以打水印成功,有的则会抛出异常,出现错误信息:A Graphics object cannot be created from an image that has an indexed pixel format。
后来断点调试,发现主要出错的地方是在Graphics.FromImage方法那,查阅了MSDN才发现这是由于索引像素格式的图片造成的(一般大多数的GIF格式图片都是这种类型):
官方文档:https://msdn.microsoft.com/zh-cn/library/system.drawing.graphics.fromimage.aspx
这里说下解决的思路,既然问题出在索引像素格式的图像上,那么只要对其进行处理即可。
根据官方文档所描述,一共有这8种像素格式会出现带有索引像素格式的图像无法创建 Graphics 对象的错误:Format1bppIndexed、Format4bppIndexed、Format8bppIndexed、Undefined、DontCare、Format16bppArgb1555、Format16bppGrayScale。
我们使用下面的方法来判断图像的像素格式是否会引发异常:
/// <summary>
/// 判断图片是否索引像素格式,是否是引发异常的像素格式
/// </summary>
/// <param name="imagePixelFormat">图片的像素格式</param>
/// <returns></returns>
private bool IsIndexedPixelFormat(System.Drawing.Imaging.PixelFormat imagePixelFormat)
{
PixelFormat[] pixelFormatArray = {
PixelFormat.Format1bppIndexed
,PixelFormat.Format4bppIndexed
,PixelFormat.Format8bppIndexed
,PixelFormat.Undefined
,PixelFormat.DontCare
,PixelFormat.Format16bppArgb1555
,PixelFormat.Format16bppGrayScale
};
foreach (PixelFormat pf in pixelFormatArray)
{
if (imagePixelFormat == pf)
{
return true;
}
}
return false;
}
我们只要传入当前Image对象的PixelFormat属性,就可以判断当前图像是否会抛出异常。那么接下来就可以根据自己的业务需求进行操作。
这里有多种方法,比如官方文档上所说的使用Image.Save(String, ImageFormat) 方法将索引的图像保存为另一种格式,然后为此新图像检索 Graphics 对象。
也可以使用Graphics.DrawImage方法将图像重新绘制到一个Bitmap对象中,并指定像素格式,从而去除索引,简单的范例:
using (System.Drawing.Image img = System.Drawing.Image.FromFile("要打水印的图片的路径"))
{
if (IsIndexedPixelFormat(img.PixelFormat))
{
Bitmap bmp = new Bitmap(img.Width, img.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(img, 0, 0);
}
}
}
当然也可以直接禁止对索引像素格式的图片进行操作,如果想要偷懒,还可以直接使用try catch将异常捕获处理。无论使用什么方法,就是一定要注意带有索引像素格式的图片不能使用FromImage方法Graphics对象。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/98678.html