Imagick的图像水印-程序员宅基地

技术标签: python  java  机器学习  深度学习  人工智能  

Imagine a friend of yours approaches you one day and would like you to build her a website so she can showcase her photography. She wants to be able to easily upload her photographs and have them watermarked so that people can’t easily steal them. “Don’t worry!” you tell her, because you know there are functions provided by the Imagick extension that makes watermarking images a breeze in PHP.

想象一下,您的一个朋友有一天会接近您,并希望您建立一个网站,以便她展示自己的摄影作品。 她希望能够轻松上传自己的照片并为照片加水印,以使人们无法轻易窃取它们。 “不用担心!” 您告诉她,是因为您知道Imagick扩展提供的功能使PHP中的水印图像变得轻而易举。

This article shares a few pointers on what makes an effective watermark, and then shows you how to use the Imagick functions to add a watermark to your image. Before you get started, make sure the Imagick extension is available on your host. It’s also advisable to find a few pictures you can test the watermark on to gauge it’s effectiveness.

本文分享了一些有关有效水印的内容,然后向您展示了如何使用Imagick函数向图像添加水印。 在开始之前,请确保主机上有Imagick扩展程序可用。 还建议您找到一些可以测试水印的图片,以评估其有效性。

什么造就了良好的水印 (What Makes a Good Watermark)

For a watermark to be effective, it needs to visible against a wide variety of backgrounds. I suggest that you try to find at least one test photo that is very light, and another that is very dark. For example, these two prairie dog pictures from Shutterstock make a good test pair:

为了使水印有效,它需要在多种背景下可见。 我建议您尝试找到至少一张非常亮的测试照片,以及另一张非常暗的照片。 例如,来自Shutterstock的这两张草原土拨鼠图片构成了很好的测试对:

2 prairie dog pictures

It’s important that the watermark is transparent enough for you to still be able to see the original image, but opaque enough so it’s difficult for an unscrupulous person to remove. A 40% opacity level is probably a good starting point, and you can increase it or decrease it depending on the situation.

重要的是,水印必须足够透明,以使您仍然能够看到原始图像,但又要足够透明,因此不道德的人很难将其删除。 不透明度40%的水平可能是一个不错的起点,您可以根据情况增加或减少它。

You also want the watermark to be large enough. If you simply put a small watermark in the lower right-hand corner, it’s a prime target for being cropped out. Watermarks that cover a large portion of the original image are more effective. See how iStockPhoto and Shutterstock watermark their work for an example.

您还希望水印足够大。 如果仅在右下角放置一个小水印,则这是裁剪的主要目标。 覆盖原始图像大部分的水印效果更好。 以iStockPhotoShutterstock为工作加水印为例。

Finally, the watermark should have contrast. Consider making the watermark dark with a light stroke or visa-versa. This is what iStockPhoto and Shutterstock do, and their mark is easily visible on all of their images whether the original image is light or dark.

最后,水印应具有对比度。 考虑通过轻击或反之使水印变黑。 这就是iStockPhoto和Shutterstock所做的,无论原始图像是浅色还是深色,它们的标记都可以在其所有图像上轻松看到。

For this article I’ll be using this as my watermark, a PNG file with about 40% opacity:

对于本文,我将使用它作为水印,这是一个约40%不透明的PNG文件:

watermark

添加水印 (Adding a Watermark)

Adding the watermark is a simple 4-step process: first you open the original image, next you open the watermark, then you overlay the watermark on top of the first image, and then either save or output the result. Here’s the code:

添加水印是一个简单的四步过程:首先打开原始图像,然后打开水印,然后将水印叠加在第一张图像的顶部,然后保存或输出结果。 这是代码:

<?php
// Open the original image
$image = new Imagick();
$image->readImage("/path/to/image.jpg");

// Open the watermark
$watermark = new Imagick();
$watermark->readImage("/path/to/watermark.png");

// Overlay the watermark on the original image
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, 0, 0);

// send the result to the browser
header("Content-Type: image/" . $image->getImageFormat());
echo $image;

You can open images from a path by creating a new instance of the Imagick class and using its readImage() method. One nice thing about Imagick is that it can open any time of file that ImageMagick was compiled to support, so you don’t need to explicitly tell it that the file is a JPEG or PNG; it’s smart enough to figure it out on its own.

您可以通过创建Imagick类的新实例并使用其readImage()方法从路径打开图像。 关于Imagick的一件好事是,它可以在ImageMagick被编译为支持的文件的任何时间打开,因此您无需明确告诉它文件是JPEG还是PNG。 它足够聪明,可以自行解决。

To overlay the watermark image, you use the compositeImage() method. In this example, the method accepts four parameters: the first is the image that will be overlaid, the second is a predefined constant representing which type of composition operation Imagick should perform (there’s a whole slew to choose from to achieve different effects), and the third and fourth parameters are the X and Y coordinates at which to place the watermark measured in pixels from the top-left corner.

要覆盖水印图像,请使用compositeImage()方法。 在此示例中,该方法接受四个参数:第一个是将要覆盖的图像,第二个是预定义的常量,表示Imagick应该执行哪种类型的构图操作( 可以选择一个整体来实现不同的效果),以​​及第三个和第四个参数是在左上角以像素为单位放置的水印的X和Y坐标。

By default, PHP assumes your script’s output is HTML and sends a text/html Content-Type header automatically. If you output the image, the browser won’t handle it properly since the headers tell it you’re sending text. To avoid your visitors being greeted with a page of gibberish, you need to instruct PHP to send a more appropriate header using header() before sending the image. Instead of just hard-coding the Content-Type header’s value, the example accesses the image’s type using Imagick itself which is then used to construct an appropriate MIME type on the fly.

默认情况下,PHP假定脚本的输出为HTML,并自动发送text / html Content-Type标头。 如果输出图像,则浏览器将无法正确处理图像,因为标题会告诉您您正在发送文本。 为了避免访问者看到乱码页面,您需要指示PHP在发送图像之前使用header()发送更合适的标header() 。 该示例不仅仅是使用硬编码Content-Type标头的值,还使用Imagick本身访问了图像的类型,该图像随后用于动态构造适当的MIME类型。

Here’s the end result, a watermarked image:

这是最终结果,带有水印的图像:

alt

缩放水印 (Scaling the Watermark)

The previous example positioned the watermark at the top-left of the original image. While this approach is fine if you know the size of the original images beforehand since you can create the watermark with the appropriate dimensions, you might want a more robust approach in case the sizes of the original images vary. Such an approach might be to place the watermark in the center of the image, and scaling the watermark beforehand if it is larger than the original image.

前面的示例将水印放置在原始图像的左上角。 如果您可以事先以适当的尺寸创建水印,但如果您事先知道原始图像的大小,则此方法很好,但是,如果原始图像的大小有所变化,则可能需要一种更可靠的方法。 这样的方法可能是将水印放置在图像的中心,如果水印大于原始图像,则预先缩放水印。

<?php
$image = new Imagick();
$image->readImage("/path/to/image.jpg");

$watermark = new Imagick();
$watermark->readImage("/path/to/watermark.png");

// how big are the images?
$iWidth = $image->getImageWidth();
$iHeight = $image->getImageHeight();
$wWidth = $watermark->getImageWidth();
$wHeight = $watermark->getImageHeight();

if ($iHeight < $wHeight || $iWidth < $wWidth) {
    // resize the watermark
    $watermark->scaleImage($iWidth, $iHeight);

    // get new size
    $wWidth = $watermark->getImageWidth();
    $wHeight = $watermark->getImageHeight();
}

// calculate the position
$x = ($iWidth - $wWidth) / 2;
$y = ($iHeight - $wHeight) / 2;

$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $x, $y);

header("Content-Type: image/" . $image->getImageFormat());
echo $image;

The getImageWidth() and getImageHeight() methods return the width and height of an image respectively, measured in pixels. By comparing the width and height of the watermark image to the those of the the original image, you can determine whether or not it is necessary to resize the watermark so it will fit on smaller images.

getImageWidth()getImageHeight()方法分别返回图像的宽度和高度,以像素为单位。 通过将水印图像的宽度和高度与原始图像的宽度和高度进行比较,可以确定是否需要调整水印的大小,以使其适合较小的图像。

Resizing the watermark is accomplished by calling the scaleImage() method which takes an allowed width and height. The method will scale the image down so that the maximum width is no larger than the allowed width, and the maximum height is no larger than the allowed height, while maintaining the image’s aspect ratio.

调整水印的大小可通过调用scaleImage()方法来实现,该方法采用允许的宽度和高度。 该方法将按比例缩小图像,以使最大宽度不大于允许的宽度,并且最大高度不大于允许的高度,同时保持图像的长宽比。

And here’s the watermarked image that results from this example:

这是此示例产生的带有水印的图像:

another watermarked prairie dog image

摘要 (Summary)

The Imagick library provides a comprehensive image processing API. Indeed, you’ve seen how easy it is to open images files, determine their dimensions and image format, scale them, and overlay one on top of another to watermark them.

Imagick库提供了全面的图像处理API。 确实,您已经看到了打开图像文件,确定其尺寸和图像格式,对其进行缩放以及将一个文件叠加在另一个文件上以对其进行水印处理是多么容易。

Usually I suggest the documentation on php.net if you want to learn more about about the capabilities of an extension, but in the case of Imagick the documentation is spotty. Many methods have just their parameter list given. So if you want to learn more, php.net is still a good place to start but you may have to look for more information for the methods in some other form (the command line application, for example) on the ImageMagick site itself and Google.

通常,如果您想了解有关扩展功能的更多信息,那么我建议您使用php.net上的文档,但是对于Imagick而言,该文档不可靠。 许多方法只给出了其参数列表。 因此,如果您想了解更多信息,php.net仍然是一个不错的起点,但是您可能不得不在ImageMagick网站本身和Google上以其他某种形式(例如,命令行应用程序)寻找有关方法的更多信息。 。

翻译自: https://www.sitepoint.com/watermarking-images/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/culi3118/article/details/108387012

智能推荐

获取大于等于一个整数的最小2次幂算法(HashMap#tableSizeFor)_整数 最小的2的几次方-程序员宅基地

文章浏览阅读2w次,点赞51次,收藏33次。一、需求给定一个整数,返回大于等于该整数的最小2次幂(2的乘方)。例: 输入 输出 -1 1 1 1 3 4 9 16 15 16二、分析当遇到这个需求的时候,我们可能会很容易想到一个"笨"办法:..._整数 最小的2的几次方

Linux 中 ss 命令的使用实例_ss@,,x,, 0-程序员宅基地

文章浏览阅读865次。选项,以防止命令将 IP 地址解析为主机名。如果只想在命令的输出中显示 unix套接字 连接,可以使用。不带任何选项,用来显示已建立连接的所有套接字的列表。如果只想在命令的输出中显示 tcp 连接,可以使用。如果只想在命令的输出中显示 udp 连接,可以使用。如果不想将ip地址解析为主机名称,可以使用。如果要取消命令输出中的标题行,可以使用。如果只想显示被侦听的套接字,可以使用。如果只想显示ipv4侦听的,可以使用。如果只想显示ipv6侦听的,可以使用。_ss@,,x,, 0

conda activate qiuqiu出现不存在activate_commandnotfounderror: 'activate-程序员宅基地

文章浏览阅读568次。CommandNotFoundError: 'activate'_commandnotfounderror: 'activate

Kafka 实战 - Windows10安装Kafka_win10安装部署kafka-程序员宅基地

文章浏览阅读426次,点赞10次,收藏19次。完成以上步骤后,您已在 Windows 10 上成功安装并验证了 Apache Kafka。在生产环境中,通常会将 Kafka 与外部 ZooKeeper 集群配合使用,并考虑配置安全、监控、持久化存储等高级特性。在生产者窗口中输入一些文本消息,然后按 Enter 发送。ZooKeeper 会在新窗口中运行。在另一个命令提示符窗口中,同样切换到 Kafka 的。Kafka 服务器将在新窗口中运行。在新的命令提示符窗口中,切换到 Kafka 的。,应显示已安装的 Java 版本信息。_win10安装部署kafka

【愚公系列】2023年12月 WEBGL专题-缓冲区对象_js 缓冲数据 new float32array-程序员宅基地

文章浏览阅读1.4w次。缓冲区对象(Buffer Object)是在OpenGL中用于存储和管理数据的一种机制。缓冲区对象可以存储各种类型的数据,例如顶点、纹理坐标、颜色等。在渲染过程中,缓冲区对象中存储的数据可以被复制到渲染管线的不同阶段中,例如顶点着色器、几何着色器和片段着色器等,以完成渲染操作。相比传统的CPU访问内存,缓冲区对象的数据存储和管理更加高效,能够提高OpenGL应用的性能表现。_js 缓冲数据 new float32array

四、数学建模之图与网络模型_图论与网络优化数学建模-程序员宅基地

文章浏览阅读912次。(1)图(Graph):图是数学和计算机科学中的一个抽象概念,它由一组节点(顶点)和连接这些节点的边组成。图可以是有向的(有方向的,边有箭头表示方向)或无向的(没有方向的,边没有箭头表示方向)。图用于表示各种关系,如社交网络、电路、地图、组织结构等。(2)网络(Network):网络是一个更广泛的概念,可以包括各种不同类型的连接元素,不仅仅是图中的节点和边。网络可以包括节点、边、连接线、路由器、服务器、通信协议等多种组成部分。网络的概念在各个领域都有应用,包括计算机网络、社交网络、电力网络、交通网络等。_图论与网络优化数学建模

随便推点

android 加载布局状态封装_adnroid加载数据转圈封装全屏转圈封装-程序员宅基地

文章浏览阅读1.5k次。我们经常会碰见 正在加载中,加载出错, “暂无商品”等一系列的相似的布局,因为我们有很多请求网络数据的页面,我们不可能每一个页面都写几个“正在加载中”等布局吧,这时候将这些状态的布局封装在一起就很有必要了。我们可以将这些封装为一个自定布局,然后每次操作该自定义类的方法就行了。 首先一般来说,从服务器拉去数据之前都是“正在加载”页面, 加载成功之后“正在加载”页面消失,展示数据;如果加载失败,就展示_adnroid加载数据转圈封装全屏转圈封装

阿里云服务器(Alibaba Cloud Linux 3)安装部署Mysql8-程序员宅基地

文章浏览阅读1.6k次,点赞23次,收藏29次。PS: 如果执行sudo grep 'temporary password' /var/log/mysqld.log 后没有报错,也没有任何结果显示,说明默认密码为空,可以直接进行下一步(后面设置密码时直接填写新密码就行)。3.(可选)当操作系统为Alibaba Cloud Linux 3时,执行如下命令,安装MySQL所需的库文件。下面示例中,将创建新的MySQL账号,用于远程访问MySQL。2.依次运行以下命令,创建远程登录MySQL的账号,并允许远程主机使用该账号访问MySQL。_alibaba cloud linux 3

excel离散度图表怎么算_excel离散数据表格-Excel 离散程度分析图表如何做-程序员宅基地

文章浏览阅读7.8k次。EXCEL中数据如何做离散性分析纠错。离散不是均值抄AVEDEV……=AVEDEV(A1:A100)算出来的是A1:A100的平均数。离散是指各项目间指标袭的离散均值(各数值的波动情况),数值较低表明项目间各指标波动幅百度小,数值高表明波动幅度较大。可以用excel中的离散公式为STDEV.P(即各指标平均离散)算出最终度离散度。excel表格函数求一组离散型数据,例如,几组C25的...用exc..._excel数据分析离散

学生时期学习资源同步-JavaSE理论知识-程序员宅基地

文章浏览阅读406次,点赞7次,收藏8次。i < 5){ //第3行。int count;System.out.println ("危险!System.out.println(”真”);System.out.println(”假”);System.out.print(“姓名:”);System.out.println("无匹配");System.out.println ("安全");

linux 性能测试磁盘状态监测:iostat监控学习,包含/proc/diskstats、/proc/stat简单了解-程序员宅基地

文章浏览阅读3.6k次。背景测试到性能、压力时,经常需要查看磁盘、网络、内存、cpu的性能值这里简单介绍下各个指标的含义一般磁盘比较关注的就是磁盘的iops,读写速度以及%util(看磁盘是否忙碌)CPU一般比较关注,idle 空闲,有时候也查看wait (如果wait特别大往往是io这边已经达到了瓶颈)iostatiostat uses the files below to create ..._/proc/diskstat

glReadPixels读取保存图片全黑_glreadpixels 全黑-程序员宅基地

文章浏览阅读2.4k次。问题:在Android上使用 glReadPixel 读取当前渲染数据,在若干机型(华为P9以及魅族某魅蓝手机)上读取数据失败,glGetError()没有抓到错误,但是获取到的数据有误,如果将获取到的数据保存成为图片,得到的图片为黑色。解决方法:glReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓..._glreadpixels 全黑