• asp.net图片添加水印以及GDI+ 中发生一般性错误的解决方法


    前台代码:

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <title>Asp.net上传图片并添加水印</title>
    </head>
    <body>
    <form id="form1" runat="server">
    <div id="top">
    Asp.Net上传并添加水印
    </div>
    <div id="content">
    选择上传图片:<asp:FileUpload ID="upFileTest" runat="server" /><br />
    <br />
    <br />
    <asp:RequiredFieldValidator ID="vUpFile" runat="server" ControlToValidate="upFileTest"
    ErrorMessage
    ="请选择要上传的文件!"></asp:RequiredFieldValidator><br />
    <br />
    <br />
    <br />
    <asp:Button ID="btnText" runat="server" OnClick="btnText_Click" Text="上传并添加文字水印" />
    &nbsp;&nbsp;&nbsp;
    <br />
    <br />
    <br />
    <br />
    <asp:Label ID="lblStatus" runat="server"></asp:Label></div>
    </form>
    </body>
    </html>

    后台cs代码:

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;

    namespace 图片添加水印
    {
    public partial class WaterMarkTest : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    lblStatus.Visible = false;
    }
    }

    private void Show(string str)
    {
    Response.Write("<script language='javascript'>alert('" + str + "')</script>");
    }
    private void upLoad()
    {
    string fullName = upFileTest.PostedFile.FileName;
    string fileName = fullName.Substring(fullName.LastIndexOf("\\") + 1);
    string marks = fullName.Substring(fullName.LastIndexOf(".") + 1); //图片格式
    if (marks.ToLower() != "jpg" && marks.ToLower() != "gif")
    {
    Show("上传的文件格式不正确,请重新选择!");
    }
    else
    {
    string upFileName = Server.MapPath("upLoadFiles") + "\\" + System.DateTime.Now.ToString("yyyyMMddhhmmss") + "." + marks;
    Session["filePath"] = upFileName;
    Session["marks"] = marks;
    upFileTest.PostedFile.SaveAs(upFileName);
    }
    }

    protected void btnText_Click(object sender, EventArgs e)
    {
    upLoad();
    //开始加文字水印
    System.Drawing.Image img = System.Drawing.Image.FromFile(Session["filePath"].ToString());
    Graphics g = Graphics.FromImage(img);
    g.DrawImage(img, 0, 0, img.Width, img.Height);
    Font f = new Font("黑体", 10); //字体的型号大小
    Brush b = new SolidBrush(Color.FromArgb(70, Color.WhiteSmoke));//画笔的颜色
    string str = "水印名称";
    g.DrawString(str, f, b, img.Width/2, img.Height*9/10);//水印的位置
    g.Dispose();
    string newFilePath = Server.MapPath("upLoadFiles") + "\\" + System.DateTime.Now.ToString("yyyyMMddhhmmss") + "."
                       + Session["marks"].ToString();
    img.Save(newFilePath);
    img.Dispose();
    if (File.Exists(Session["filePath"].ToString()))
    {
    File.Delete(Session["filePath"].ToString());
    }
    lblStatus.Visible = true;
    lblStatus.Text = "水印绘制成功!";

    }
    }
    }

    在编辑的过程中。出现过 GDI+ 中发生一般性错误。网上查了资料后发现,原因可能是:Bitmap 对象创建后没有释放。

    Bitmap 对象或一个 图像 对象从一个文件, 构造时该文件仍保留锁定对于对象的生存期。 因此, 无法更改图像并将其保存回它产生相同的文件。

    替代方法
    •    创建非索引映像。
    •    创建索引映像。
    这两种情况下, 原始 位图 上调用 Bitmap.Dispose() 方法删除该文件上锁或删除要求, 流或内存保持活动。

    创建非索引图像
    即使原始映像被索引格式中该方法要求新图像位于每像素 (超过 8 位 -) -, 非索引像素格式。 此变通方法使用 Graphics.DrawImage() 方法来将映像复制到新 位图 对象:
    1.    构造从流、 从内存, 或从文件原始 位图 。
    2.    创建新 位图 的相同大小, 带有是超过 8 位 - - 像素 (BPP) 每像素格式。
    3.    使用 Graphics.FromImage() 方法以获取有关二 位图 Graphics 对象。
    4.    用于 Graphics.DrawImage() 绘制首 位图 到二 位图 。
    5.    用于 Graphics.Dispose() 处置是 图形 。
    6.    用于 Bitmap.Dispose() 是首 位图 处置。

    创建索引映像
    此解决办法在索引格式创建一个 Bitmap 对象:
    1.    构造从流、 从内存, 或从文件原始 位图 。
    2.    创建新 位图 具有相同的大小和像素格式作为首 位图 。
    3.    使用 Bitmap.LockBits() 方法来锁定整个图像对于两 Bitmap 对象以其本机像素格式。
    4.    使用 Marshal.Copy 函数或其他内存复制函数来从首 位图 复制到二 位图 图像位。
    5.    使用 Bitmap.UnlockBits() 方法可以解锁两 Bitmap 对象。
    6.    用于 Bitmap.Dispose() 是首 位图 处置。

    由于外国人的思维和我们不一样,我重新用实例解释一下,我这里使用的是创建非索引图像。

    private void ToolStripMenuItem_Click(object sender, EventArgs e)
            {
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    //创建一个bitmap类型的bmp变量来读取文件。
                    Bitmap bmp = new Bitmap(openFileDialog1 .FileName );
                    //新建第二个bitmap类型的bmp2变量,我这里是根据我的程序需要设置的。
                    Bitmap bmp2 = new Bitmap(1024, 768, PixelFormat.Format16bppRgb555);
                    //将第一个bmp拷贝到bmp2中
                    Graphics draw = Graphics.FromImage(bmp2);
                    draw.DrawImage(bmp,0,0);
                    pictureBox1.Image = (Image)bmp2 ;//读取bmp2到picturebox
                    FILE = openFileDialog1.FileName;
                    openFileDialog1.Dispose();
                    draw.Dispose();
                    bmp.Dispose();//释放bmp文件资源
                }
            }

    通过以上的读取文件,在保存的时候就不会出现错误了。                         

     但是也不是这个问题,最后发现,问题其实出在。图片在加水印前和加水印后保存的文件夹是同一个,导致错误。
    解决的方法是新建一个保存加水印后的图片的文件夹。及: 
    将代码:

    string newFilePath = Server.MapPath("upLoadFiles") + "\\" + System.DateTime.Now.ToString("yyyyMMddhhmmss") + "." + Session["marks"].ToString(); 

    改为:string newFilePath = Server.MapPath("newMarkFiles") + "\\" + System.DateTime.Now.ToString("yyyyMMddhhmmss") + "."+ Session["marks"].ToString();

    新建文件夹的名称是:newMarkFiles

  • 相关阅读:
    synchronized 到底该不该用?
    线上Java程序占用 CPU 过高,请说一下排查方法?
    『JVM』我不想知道我是怎么来滴,我就想知道我是怎么没滴
    Golang 实现 Redis(8): TCC分布式事务
    Golang 实现 Redis(7): 集群与一致性 Hash
    Golang 实现 Redis(6): 实现 pipeline 模式的 redis 客户端
    LSM 树详解
    uni-app subNVue 原生子窗体简单使用案例(app端)
    日计不足涓滴成河-自定义响应结果格式化器
    RTT之软件包
  • 原文地址:https://www.cnblogs.com/jianglan/p/2372451.html
Copyright © 2020-2023  润新知