在C#中为图片添加数字水印的几种办法

news2024/10/1 12:53:08

最近在写个人项目时,有遇到需要将图片加上水印防止被盗取的需求。这里找了几种实现方式,可供有需要的朋友参考。

本身我不是搞算法这块的,所以这里只是找了一些实现,也没有继续深究下去。

以前在学校的时候从书上了解过可以将一些信息嵌入到图片中的技术,这次顺便也在网上找到了这种实现方式。

方式一,直接使用GDI+绘制水印到图片上

这种方式的话存在几个问题

1、水印很容易被清除,用ps的内容识别一下就干掉了

2、水印的文字大小不好控制(理论是可以根据图片的大小动态计算字符的大小的,以前见过这种实现,但这里我也没去仔细找实现了,就大概写了个根据图片大小调整字符大小的逻辑。)

实现逻辑如下:

 1     public static void DrawWatermark(string imageFilePath,string watermark)
 2         {
 3             using (MemoryStream ms = new MemoryStream(System.IO.File.ReadAllBytes(imageFilePath)))
 4             {
 5                 Bitmap bitmap = (Bitmap)Image.FromStream(ms);
 6 
 7                 using (Graphics graphics = Graphics.FromImage(bitmap))
 8                 {
 9                     var size = (float)(bitmap.Height * 0.02);
10                     if (size < 10)
11                         size = 10f;
12                     using (Font arialFont = new Font("Arial", size, GraphicsUnit.Pixel))
13                     {
14                         var location = new Point(0, 0);
15                         graphics.DrawString(watermark, arialFont, new SolidBrush(Color.FromArgb(120, Color.Silver)), location);
16                     }
17                 }
18 
19                 bitmap.Save(imageFilePath);
20             }
21         }

绘制出来大概效果如下:

方式二、将图片信息嵌入到图片中

这是我在github上找到一种实现方式,项目地址:GitHub - mchall/HiddenWatermark: Embeds a hidden watermark in an image using a blind DWT-DCT approach

项目描述:

使用盲DWT-DCT方法在图像中嵌入隐藏水印。与隐写方法不同,这种隐藏水印能够抵抗各种形式的攻击。仅限于黑白32x32水印图像。

项目里有示例,可以根据示例进行调用。 

使用这种方法,可以将一个32x32的黑白图像嵌入到图片中。

经过我实际 测试,发现如果图片太小,是不支持这种嵌入方式 的。个人推断应该是如果图片太小,还未达到写入32x32图片的空间大小。具体最小支持到什么尺寸的图片,我也没有仔细去计算了。

效果如下:

我这里弄了一张写了zti三个字的灰度图,然后嵌入到图片中去。

 +    

 嵌入 后,图片看起来跟原始图像没有区别,但是能再次把嵌入的图片提取出来

方式三、将文字信息嵌入到图片中

这是我在CodeProject上找到的一种实现方式。可以在下面的链接中下载到实现的源码和示例程序,直接参考集成即可。

项目地址:Steganography: Simple Implementation in C# - CodeProject

使用这种方式,可以将文字嵌入到图片中,然后再次提取出来。

注意:注意:不要以有损格式(如 JPEG)保存结果图像;推荐是保存为PNG。

效果如下:

我这里嵌入了HelloWorld到图片中,可以再次从图片中提取出来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1979600.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cmake常用命令学习

1.include https://blog.csdn.net/qq_38410730/article/details/102677143 CmakeLists.txt才是cmake的正统文件&#xff0c;而.cmake文件是一个模块文件&#xff0c;可以被include到CMakeLists.txt中。 include指令一般用于语句的复用&#xff0c;也就是说&#xff0c;如果有…

OBS Studio:如何打造专业级的视频直播体验

1.简介 OBS&#xff08;Open Broadcaster Software&#xff09;是一款开源的视频录制和直播软件&#xff0c;广泛用于视频制作、游戏直播和网络直播。它支持多种操作系统&#xff0c;包括Windows、macOS和Linux。OBS提供了丰富的功能&#xff0c;包括但不限于&#xff1a; **…

聊聊跨境电商平台与固定IP的那些事

IP地址网络地址&#xff08;网络号&#xff09;主机地址&#xff08;地址号&#xff09;&#xff0c;IP地址是一台电脑在网络中的唯一标识&#xff0c;可分为固定IP与动态IP。那么IP地址的分类有哪些&#xff1f;什么IP适合亚马逊/eBay/速卖通等平台运营时使用&#xff1f; A类…

Spring5 的日志学习

我们在使用 Spring5 的过程中会出现这样的现像&#xff0c;就是 Spring5 内部代码打印的日志和我们自己的业务代码打印日志使用的不是统一日志实现&#xff0c;尤其是在项目启动的时候&#xff0c;Spring5 的内部日志使用的是 log4j2&#xff0c;但是业务代码打印使用的可能是 …

DNS安全概述

一、DNS的解析过程 1.递归解析 递归解析是一种由DNS客户端&#xff08;通常是用户的应用程序&#xff0c;如一个浏览器&#xff09;向本地DNS解析器发出解析请求&#xff0c;然后本地DNS解析器负责查询最终结果并将结果返回给客户端&#xff0c;而中间的所有查询请求都由本地D…

每日OJ_牛客HJ62 查找输入整数二进制中1的个数

目录 牛客HJ62 查找输入整数二进制中1的个数 解析代码 牛客HJ62 查找输入整数二进制中1的个数 查找输入整数二进制中1的个数_牛客题霸_牛客网 解析代码 本题是计算一个数二进制表示中1的个数&#xff0c;通过&#xff08;n >> i) & 1可以获取第i位的二进制值&…

基于Spring boot + Vue的校园论坛

作者的B站地址&#xff1a;程序员云翼的个人空间-程序员云翼个人主页-哔哩哔哩视频 csdn地址&#xff1a;程序员云翼-CSDN博客 1.项目技术栈&#xff1a; 前后端分离的项目 后端&#xff1a;Springboot MybatisPlus 前端&#xff1a;Vue ElementUI 数据库&#xff1a; …

聚星文社 聚星3高级推理创作

聚星文社 聚星3高级推理创作 Docshttps://qvfbz6lhqnd.feishu.cn/wiki/D3YLwmIzmivZ7BkDij6coVcbn7W

CAS5.3自定义登录校验规则

前一篇文章介绍过CAS自定义用户信息, 这个用户信息实在登录成功后加到session中的, 今天来介绍一下CAS5.3怎么自定义登录校验逻辑 思路 有了前一篇文章的铺垫这一次自定义登录校验其实就很简单了, 因为想要把用户信息放入到session中是一定要在登陆的时候完成的,因此这次我们…

Codeforces Round 960 (Div. 2) A~E

A. Submission Bait &#xff08;思维&#xff09; 题意&#xff1a; A l i c e Alice Alice 和 B o b Bob Bob 正在玩一个数组 a a a 中大小为 n n n 的游戏。 他们轮流进行操作&#xff0c; A l i c e Alice Alice先开始。无法操作的玩家将输掉。首先&#xff0c;将变量…

常用控件之 QWidget

目录 一、控件概述 1.关于控件体系的发展&#xff1a; 二、QWidget 核心属性 1.核心属性概览 2.enabled 3.geometry &#x1f335;window frame&#xff08;窗口框架&#xff09; 的影响 4.windowTitle 5.windowIcon &#x1f335;使用 qrc 文件管理资源 6.windowOpa…

微信公众号上线12周年了,12年前的公众号历史文章怎么找?抓取了公众号历史文章同步到博客,找起来方便了

为了方便看看12年来这些号发过的文章 2023 批量下载公众号文章内容/话题/图片/封面/视频/音频&#xff0c;导出文章pdf和抓取文章数据包含阅读数/点赞数/在看数/留言数&#xff0c;我抓取了其中一些号的所有历史文章同步到博客 : 比如深圳卫健委从2014年更新&#xff0c;到2023…

Reqable:跨平台HTTP开发与调试工具

在当今快速发展的互联网时代&#xff0c;HTTP协议作为网络通信的基础&#xff0c;其开发和调试工具的选择对开发效率有着重要影响。本文将详细介绍一款新型的跨平台HTTP开发和调试工具——Reqable&#xff0c;它支持HTTP1、HTTP2以及最新的HTTP3(QUIC)协议&#xff0c;为开发、…

超秒集物:助力品牌商腾飞,共筑强国梦想

在当今竞争激烈的商业世界中&#xff0c;每一个小微企业都怀揣着成为世界 500 强的梦想。它们虽然微小&#xff0c;但都在努力绽放出属于自己的光芒。而超秒集物&#xff0c;以其独特的平台力量&#xff0c;为众多小微企业照亮了前行的道路&#xff0c;助力它们追逐梦想&#x…

贝叶斯之光:照亮机器学习领域的算法瑰宝

一、贝叶斯算法概述 贝叶斯算法起源于英国数学家托马斯贝叶斯&#xff08;Thomas Bayes&#xff09;在18世纪提出的贝叶斯定理。该定理是概率论中的一个重要定理&#xff0c;描述了条件概率之间的关系。其基本形式可以表示为&#xff1a; P(A∣B)P(B)P(B∣A)P(A)​ 其中&…

C++进阶:C++11新增语法(1)

文章目录 1. 统一的列表初始化1.1 &#xff5b;&#xff5d;初始化 1.2 std::initializer_list2. 声明2.1 auto2.2 decltype3.3 nullptr 4 范围for循环5 STL中一些变化6 右值引用和移动语义6.1 左值引用和右值引用6.2 左值引用与右值引用特性6.3 左值引用和右值引用使用场景和意…

图的应用--最小生成树

一. 前言 生成树的概念&#xff1a; 生成树是图的极小连通子图&#xff0c;也就是去掉一条边就非连通的图&#xff0c;并且这个图的所有顶点都由边连接在一起&#xff0c;但不存在回路。 生成树的特点&#xff1a;一个图可以有很多个不同的生成树。生成树的顶点个数和图的顶点个…

另一棵树的子树 - 力扣(LeetCode)C语言

572. 另一棵树的子树 - 力扣&#xff08;LeetCode&#xff09;&#xff08;点击前面链接即可查看题目&#xff09; 一、题目 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在&#xff0c;返回 true &#xff1b;否则&…

反转链表 II(LeetCode)

题目 给你单链表的头指针 和两个整数 和 &#xff0c;其中 。请你反转从位置 到位置 的链表节点&#xff0c;返回 反转后的链表 。 解题 class ListNode:def __init__(self, value0, nextNone):self.value valueself.next nextdef reverseBetween(head: ListNode, lef…

即使是 Linux 用户也应该看看这篇文章。

关注公众号网络研究观获取更多内容。 安全启动至少从 Windows 8 开始就成为一项标准功能。 顾名思义&#xff0c;该功能可保护启动过程。 通过对启动过程中使用的任何软件&#xff08;“固件”&#xff09;进行数字签名&#xff0c;可确保启动过程的完整性。 与任何数字签名…