水印之"indexed pixel format"
近日,需要做一个在图片上加水印的的程序。
比如页面上有个Banner,针对对不同的访问用户,需要在Banner上加上该用户所在公司的名称。
实现倒是简单,网上一搜一大把,但会遇到两个问题,未必能搜到解决方案:
其一:需要用到System.Drawing.Fr2omImage 静态方法,MSDN文档明确描述“If the image has an indexed pixel format, this method throws an exception with the message”,从美工处随意索来几个图片,都是所谓"indexed pixel format"的图片,看来这种格式还有普遍性;
Remarks
If the image has an indexed pixel format, this method throws an exception with the message, "A Graphics object cannot be created from an image that has an indexed pixel format." The indexed pixel formats are shown in the following list.
-
PixelFormat.Format1bppIndexed
-
PixelFormat.Format4bppIndexed
-
PixelFormat.Format8bppIndexed
This method also throws an exception if the image has any of the following pixel formats.
-
PixelFormat.Undefined
-
PixelFormat.DontCare
-
PixelFormat.Format16bppArgb1555
-
PixelFormat.Format16bppGrayScale
-
You should always call the Dispose method to release the Graphics object and related resources created by the FromImage method.
其二:你还会用到类似"bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);"的代码,结果发现网页上出现的图片效果色彩级差,到了不能忍受的地步。
问题一解决方案:在MSDN中有异常明确描述,我们只有绕过去。参见后附代码的棕色部分
思路:做一个同样尺寸的bitmap,将“indexed pixel format”格式的图片复制过来,变为一个非“indexed pixel format”的图片,然后按常规方法在图片上添加文字。
问题二解决方案:可以参考 Optimizing Color Quantization for ASP.NET Images ,太复杂,咱想简单点。
思路:直接输出位图。
实现代码:
MarkImg.aspx后台代码很简单,在Page_Load部分写加水印代码。
protected void Page_Load(object sender, EventArgs e)
{
if(Page.IsPostBack ==false)
{
string file = "mailbanner.gif";
string addText = "上海星移企业邮局";
try
{
addText = Request.QueryString["mark"].ToString();
}
catch(Exception)
{
}
//载入原始图片
Bitmap bmp = new Bitmap(Server.MapPath(file));
Graphics graphics;
try
{
//试图取得Graphics对象,用于添加文字
//对于indexed pixel format,此处会抛出异常
graphics = System.Drawing.Graphics.FromImage(bmp);
}
catch (Exception)
{
//对于indexed pixel format,抛出异常的特殊处理
Bitmap newBmp = new Bitmap(bmp.Width, bmp.Height);
graphics = System.Drawing.Graphics.FromImage(newBmp);
graphics.DrawImage(bmp,
new Rectangle(0, 0, newBmp.Width, newBmp.Height),
new Rectangle(0, 0, bmp.Width, bmp.Height),
GraphicsUnit.Pixel);
bmp = newBmp;
}
graphics.DrawString(addText,
new Font("Verdana", 14, FontStyle.Regular ),
new SolidBrush(Color.Gray), 181, 9);
graphics.DrawString(addText,
new Font("Verdana", 14, FontStyle.Regular),
new SolidBrush(Color.Goldenrod ), 180, 8);
graphics.Dispose();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
//网上的例程,通常是 bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg)
//色彩失真明显
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
bmp.Dispose();
Response.ClearContent();
Response.ContentType = "image/bmp";
Response.BinaryWrite(ms.ToArray());
}
}