基于C#实现数字水印工具

基于C#实现数字水印工具
摘要
基于C#提供的Image类,实现数字水印比较容易;这里强调的是如何做可release的一个工具。
照片添加
利用C#的FolderBrowserDialog类,可以方便地的读取图像文件。本文是基于目录添加照片,所以需要进行目录遍历。如果打开的是目录,还需要打开子目录读取照片;在本文实现中,只读取JPG文件,并且在添加前试着读一下,避免一些图片不能读取,影响后续操作的有效性。
另外,从FolderBrowserDialog类得到路径后,不要忘记读取该目录下的文件,这是一个容易忽略的小问题,即 get_file(fbdlg.SelectedPath) 后再调用get_dir(fbdlg.SelectedPath)。

private void get_dir(string parent)
        {
            DirectoryInfo di = new DirectoryInfo(parent);
            foreach (DirectoryInfo subdir in di.GetDirectories())
            {
                get_file(subdir.FullName);
            }
        }
        private void get_file(string parent)
        {
            DirectoryInfo di = new DirectoryInfo(parent);
            foreach (FileInfo fi in di.GetFiles())
            {
                if (fi.Extension.ToUpper() == ".JPG")
                {
                    try
                    {
                        Image test = Image.FromFile(fi.FullName);
                        if (test != null)
                        {
                            insertPhoto(fi);
                            test.Dispose();
                        }
                    }
                    catch (OutOfMemoryException ome)
                    {
                        MessageBox.Show(fi.FullName + " can not be added into album" + Environment.NewLine + "reason[" + ome.Message + "]");
                    }
                    catch (FileNotFoundException fnfe)
                    {
                        MessageBox.Show(fi.FullName + " can not be added into album" + Environment.NewLine + "reason[" + fnfe.Message + "]");
                    }
                    catch (ExternalException)
                    {
                        continue;
                    }
                }
            }              
       }

接下来的问题是:读入的照片,如何显示?考虑到本工具不是图片处理,需求Scope比较容易确定;缩略图是个最佳选择。想到缩略图,就想到了利用ListView来显示添加的图片:LargeImageList刚好满足要求;另外,ListViewItem的CheckBox正好用来选定图片。

this .listView1.LargeImageList = il;
                for (int i = 0; i < il.Images.Count; i++)
                {
                    ListViewItem lvi = new ListViewItem();
                    lvi.Name = new FileInfo(img_files[i]).Name;
                    lvi.ImageIndex = i;                    
                    this.listView1.Items.Add(lvi);
                }

图片选取
ListView的ListViewItem有个名为 Checked 的属性,只要改变这个属性,就能全部选择和全部取消选择。

private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in this.listView1.Items)
            {
                if (!lvi.Checked)
                {
                    lvi.Checked = true;
                }
            }
        }
 
        private void unselectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in this.listView1.Items)
            {
                if (lvi.Checked)
                {
                    lvi.Checked = false;
                }
            }
        }

水印定制
字符水印可以改变字体的大小、颜色、字体名和水印内容;这里提供定制模态对话框。在该对话框中有个RichTextBox来显示定制的实际效果;当然会使用FontDialog类。

FontDialog fdlg = new FontDialog();
            fdlg.Font = m_font;
            fdlg.ShowColor = true;
           fdlg.ShowEffects = true;
            if (DialogResult.OK == fdlg.ShowDialog())
            {
                this.richTextBox1.Font = fdlg.Font;               
                this.richTextBox1.ForeColor = fdlg.Color;               
            }
            fdlg.Dispose();

当对话框按确定按钮时,需要将定制信息保存下来,并持久化;本文使用注册表(关于注册表操作请参见《基于C#操作注册表》一文)。

Tips:关于模态对话框的实现。
在C#中,只有Form类;通过调用ShowDialog时指定parent,来实现模态。另外,还需要在对话框的确定和取消按钮的DialogResult属性,指定相应的返回值。
 

水印添加
添加水印的过程有点类似photoshop的图层:
1) 一个同样大小的Bitmap;new
2)复制图片属性,如分辨率信息,日期等;
3)先将该图层涂白;
4)再把原图画在上面;
5)然后把文字写在上面;
6)保存。

private void watermarkphoto(string filename, Image img)
        {           
            Bitmap b = new Bitmap(img.Width, img.Height, PixelFormat.Format32bppRgb);
            b.SetResolution(img.HorizontalResolution, img.VerticalResolution);
            foreach (PropertyItem item in img.PropertyItems)
            {
                b.SetPropertyItem(item);
            }
            Graphics g = Graphics.FromImage(b);
            g.Clear(Color.White);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            g.DrawImage(img, 0, 0, img.Width, img.Height);
            SolidBrush brush = new SolidBrush(m_default_color);           
            StringFormat format = new StringFormat(StringFormatFlags.NoClip);
            format.LineAlignment = StringAlignment.Near;
            format.Alignment = StringAlignment.Near;        
            SizeF stringSize = g.MeasureString(m_defalut_watermark, m_default_font);
            g.DrawString(m_defalut_watermark, m_default_font, brush, new PointF((img.Width - stringSize.Width) / 2, img.Height *2 /3), format);
            try
            {
                b.Save(filename, ImageFormat.Jpeg);
            }
            catch (ExternalException ee)
            {
                MessageBox.Show("fail to handle " + filename + " because " + ee.Message);
            }
          b .Dispose();
            brush.Dispose();
            g.Dispose();           
        }

当然,改变字体后要计算一下水印宽度。
 

SizeF stringSize = g.MeasureString(m_defalut_watermark, m_default_font);

结束语
基于上述思想,实现的数字水印工具已经发布给几个朋友使用,反映良好。拥有自己的水印工具后,展示照片就不担心侵权了。 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值