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

智能推荐

详解@JsonProperty、@JsonFormat 和 @DateTimeFormat 注解用法-程序员宅基地

文章浏览阅读1.4w次,点赞6次,收藏37次。详细解释 @JsonProperty、@JsonFormat 和 @DateTimeFormat 注解的用法_@jsonproperty

Linux使用docker搭建Mysql主从复制_linux 实现docker的mysql主从复制-程序员宅基地

文章浏览阅读326次。Linux使用docker搭建Mysql主从复制_linux 实现docker的mysql主从复制

C++ :error C3872: '0x3000': this character is not allowed in an identifier 包含中文全角空格错误【已解决】_character <u+ff08> not allowed in an identifier-程序员宅基地

文章浏览阅读870次。error C3872: ‘0x3000’: this character is not allowed in an identifier写的serialdll.cpp文件中报错如下,一大堆错误,但是反复查看了那几行代码,甚至重新写了一遍,还是报错。在网上帖子说可能是代码中有中文的全角空格,导致报错。但使用Ctrl + H查找当前的cpp文件,完全没有找到中文全角空格;继续排查原因,发现..._character not allowed in an identifier

解决Mac下MX4手机无法连接adb问题之解决方案-程序员宅基地

文章浏览阅读46次。一般的android连接mac 很方便不用安装驱动就可以啦,可是不知道为什么特殊情况下有的android手机(小米2,华为等)就是连接不上,下来就说说特殊情况下如何连接。使用USB连接安卓手机后可以做2件事情:1.关于本机-->更多信息->概系统览->系统报告->usb->你所连接的device-->供应商ID(Vendor ID)2..打开终端,输..._macpro adb连接mix4

老花眼:男女的“更年期”-程序员宅基地

文章浏览阅读671次。What do you think, how many operations can be done on one eye? A clinical case of one of my patients confirms that more than 20 operations of various kinds are not the limit. Although, no doubt, thi..._更年期 眼压高

MongoDB索引详解_mongodb索引的数据结构-程序员宅基地

文章浏览阅读1.2k次,点赞15次,收藏9次。MongoDB索引详解_mongodb索引的数据结构

随便推点

医学图像分割模型:U-Net详解及实战-程序员宅基地

文章浏览阅读6k次,点赞11次,收藏122次。2015年U-Net的出现使得原先需要数千个带注释的数据才能进行训练的深度学习神经网络大大减少了训练所需要的数据量,并且其针对神经网络在图像分割上的应用开创了先河。当时神经网络在图像分类任务上已经有了较好的成果,但在很多视觉的任务中由于输出需要进行定位,也就是每个像素需要分配一个类标签,这导致成千上万的训练图像在生物医学任务中通常难以获得,从而急需要一个神经网络,它不需要那么多的数据来进行训练却依旧有较好的效果,这就导致了U-Net的诞生。U-Net几乎是当前segmentation项目中应用最广的模型。_医学图像分割

qt 实现RTSP&RTMP拉流,实时显示视频流_qt rtsp拉流-程序员宅基地

文章浏览阅读2.5w次,点赞22次,收藏202次。最近项目需求,要实现一个rtsp视频流,经过一番了解之后,最后选择两种方式进行测试对比,一个是基于ffmpeg编码实现rtsp拉流,另外一个则是基于VLC开源的qt第三方库,实在github上搜索到的 key: qt vlc。首先粗略讲下ffmpeg编码怎么实现rtsp拉流呢?没有接触之前,感觉很高深的样子,其实并不然,ffmpeg内部基本都帮你实现了,类似打开摄像头一样的流程,使用avfor..._qt rtsp拉流

Java操作本地windows系统的cmd命令-程序员宅基地

文章浏览阅读10w+次,点赞2次,收藏11次。人工智能,零基础入门!http://www.captainbed.net/inner一、windows系统下运行cmd命令,直接打开cmd窗口输入对应命令执行就可以了,步骤:【1】输入快捷键:windows + R,如何输入cmd,按回车【2】然后会进入cmd命令的窗口界面:【3】执行一些cmd命令,看效果如下显示:二、但是在Java程序中如何执行本地windo...

使用WPUSH实现每日60s早报新闻的推送-程序员宅基地

文章浏览阅读403次,点赞6次,收藏7次。ALAPI:是一个免费的API接口平台,里面集成了上百个免费API接口WPUSH: 一个聚合消息推送平台,可以推送微信、短信、邮件、飞书、钉钉等消息Github Actions: 自动化CI工具,可以用这个实现自动化构建、定时任务等。_每日60s

基于Python所写的火车票分析助手设计_基于python的火车票助手分析的总体结构设计图-程序员宅基地

文章浏览阅读139次。(2)单击主界面“卧铺售票分析”的选项卡,然后输入需要查询的“出发地”与“目的地”,然后单击“查询”按钮将显示如图3所示的卧铺售票分析数据。(1)在主界面“车票查询”选项卡中依次输入,出发地、目的地以及出发时间,然后单击“查询”按钮,将显示如图2所示的车票信息。(3)单击主界面“车票起售时间”的选项卡,然后输入起售车站,再单击“查询”按钮将显示如图4所示的车票起售时间。在PyCharm中运行《火车票分析助手》即可进入如图1所示的系统主界面。图2 车票查询区域的数据显示。图4 显示查询车票起售时间。_基于python的火车票助手分析的总体结构设计图

Nginx重启报错: [error] open() “/usr/local/nginx/logs/nginx.pid“ failed (2: No such file or directory)_nginx: [error] open() "/usr/local/nginx/logs/nginx-程序员宅基地

文章浏览阅读5.3k次,点赞8次,收藏22次。Nginx reload重启报错: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory)_nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: no such f

推荐文章

热门文章

相关标签