手把手教你如何给图像加水印

d_hero
发布于 2022-9-14 10:44
浏览
0收藏

阅读完本文大约需要3分钟

一、介绍
在实际的系统开发中,某些业务场景下,我们经常需要给原始图片添加水印,以防止图片信息在互联网上随意传播!

也有的基于当下的业务需求,需要给相机照片加水印、地理位置、时间等信息,以方便记录自己的生活!

例如下图!

手把手教你如何给图像加水印-鸿蒙开发者社区

有的人可能很容易想到,通过 PS 技术就可以很轻松的完成!

的确,对于单个图像而言很容易,但是对于成千上万的图像,采用人工处理,显然不可取!

问题来了,面对大批量的图像加水印需求,我们应当如何处理呢?

试想一下,如果我们采用人工方式来给图像添加水印,大概的步骤离不开以下几步:

 ● 1、先获取需要处理的图像
 ● 2、然后将图像摆放整齐,用尺子计算出我们需要加水印的位置
 ● 3、采用画笔准确无误的在对应的位置上画上水印
 ● 4、最后,水印添加之后!
如果采用程序来实现,思路也是一样的,废话也不多说了,代码直接撸上!

 

二、程序实践
下面我们以java程序为例,给以下图添加一段复印无效的文字水印,并居中!

手把手教你如何给图像加水印-鸿蒙开发者社区

程序实践如下:

import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

/**
 * 给图像添加水印
 * @author pzblog
 * @since 2021-10-29
 */
public class ImageWaterMarkUtil {



    /**
     * 给图像添加文字水印
     * @param srcImgPath     原始文件地址
     * @param targetImgPath  目标文件地址
     * @param text           水印内容
     * @param color          水印文字颜色
     * @param font           水印文字字体
     * @param alpha          水印透明度
     * @param positionWidth  水印横向位置
     * @param positionHeight 水印纵向位置
     * @param degree         水印图片旋转角度
     * @param location       水印的位置,左上角、右上角、左下角、右下角、居中
     */
    public static void markImage(String srcImgPath,
                                 String targetImgPath,
                                 String text,
                                 Color color,
                                 Font font,
                                 float alpha,
                                 int positionWidth,
                                 int positionHeight,
                                 Integer degree,
                                 String location) {
        try {
            // 1、读取源图片
            Image srcImg = ImageIO.read(new File(srcImgPath));
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            BufferedImage buffImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);

            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg.getScaledInstance(srcImgWidth, srcImgHeight, Image.SCALE_SMOOTH), 0, 0, null);
            // 4、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
            }
            // 5、设置水印文字颜色
            g.setColor(color);
            // 6、设置水印文字Font
            g.setFont(font);
            // 7、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            // 8、水印图片的位置
            int x = 0, y = 0;
            if (StringUtils.equals(location, "left-top")) {
                x = 30;
                y = font.getSize();
            } else if (StringUtils.equals(location, "right-top")) {
                x = srcImgWidth - getWatermarkLength(text, g) - 30;
                y = font.getSize();
            } else if (StringUtils.equals(location, "left-bottom")) {
                x += 30;
                y = buffImg.getHeight() - font.getSize();
            } else if (StringUtils.equals(location, "right-bottom")) {
                x = srcImgWidth - getWatermarkLength(text, g) - 30;
                y = srcImgHeight - font.getSize();
            } else if (StringUtils.equals(location, "center")) {
                x = (srcImgWidth - getWatermarkLength(text, g)) / 2;
                y = srcImgHeight / 2;
            } else {
                //自定义位置
                x = positionWidth;
                y = positionHeight;
            }
            // 9、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
            g.drawString(text, x, y);
            // 10、释放资源
            g.dispose();
            // 11、生成图片
            ImageIO.write(buffImg, "png", new File(targetImgPath));
            System.out.println("图片完成添加水印文字");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算填充的水印长度
     * @param text
     * @param g
     * @return
     */
    private static int getWatermarkLength(String text, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(text.toCharArray(), 0, text.length());
    }

    public static void main(String[] args) {
        String srcImgPath = "/Users/pzblog/Desktop/Jietu.jpg"; //原始文件地址
        String targetImgPath = "/Users/pzblog/Desktop/Jietu-copy.jpg"; //目标文件地址
        String text = "复 印 无 效"; //水印文字内容
        Color color = Color.red; //水印文字颜色
        Font font = new Font("宋体", Font.BOLD, 60); //水印文字字体
        float alpha = 0.4f; //水印透明度
        int positionWidth = 320; //水印横向位置坐标
        int positionHeight = 450; //水印纵向位置坐标
        Integer degree = -30; //水印旋转角度
        String location = "center"; //水印的位置
        //给图片添加文字水印
        markImage(srcImgPath, targetImgPath, text, color, font, alpha, positionWidth, positionHeight, degree, location);
    }
}

运行结果如下:

手把手教你如何给图像加水印-鸿蒙开发者社区

水印添加成功!

 

2.1、给图像添加多处文字
有的需求会要求给图像添加多处文字水印,例如下图!

手把手教你如何给图像加水印-鸿蒙开发者社区

处理过程也很简单!

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

/**
 * 给图像添加水印
 * @author pzblog
 * @since 2021-10-29
 */
public class ImageFullWaterMarkUtil {



    /**
     * 给图像添加多处文字水印
     * @param srcImgPath     原始文件地址
     * @param targetImgPath  目标文件地址
     * @param text           水印内容
     * @param color          水印文字颜色
     * @param font           水印文字字体
     * @param alpha          水印透明度
     * @param startWidth     水印横向起始位置
     * @param degree         水印图片旋转角度
     * @param interval       高度间隔
     */
    public static void fullMarkImage(String srcImgPath,
                                 String targetImgPath,
                                 String text,
                                 Color color,
                                 Font font,
                                 float alpha,
                                 int startWidth,
                                 Integer degree,
                                 Integer interval) {
        try {
            // 1、读取源图片
            Image srcImg = ImageIO.read(new File(srcImgPath));
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            BufferedImage buffImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);

            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg.getScaledInstance(srcImgWidth, srcImgHeight, Image.SCALE_SMOOTH), 0, 0, null);
            // 4、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
            }
            // 5、设置水印文字颜色
            g.setColor(color);
            // 6、设置水印文字Font
            g.setFont(font);
            // 7、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            // 8、水印图片的位置
            int x = startWidth;
            int y = font.getSize();
            int space = srcImgHeight / interval;
            for (int i = 0; i < space; i++) {
                //如果最后一个坐标的y轴比height高,直接退出
                if (((y + font.getSize()) > srcImgHeight) || ((x + getWatermarkLength(text,g))  > srcImgWidth)) {
                    break;
                }
                //9、进行绘制
                g.drawString(text, x, y);
                x += getWatermarkLength(text,g);
                y += font.getSize() + interval;
            }
            // 10、释放资源
            g.dispose();
            // 11、生成图片
            ImageIO.write(buffImg, "png", new File(targetImgPath));
            System.out.println("图片完成添加水印文字");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算填充的水印长度
     * @param text
     * @param g
     * @return
     */
    private static int getWatermarkLength(String text, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(text.toCharArray(), 0, text.length());
    }

    public static void main(String[] args) {
        String srcImgPath = "/Users/pzblog/Desktop/Jietu.jpg"; //原始文件地址
        String targetImgPath = "/Users/pzblog/Desktop/Jietu-copy-full.jpg"; //目标文件地址
        String text = "复 印 无 效"; //水印文字内容
        Color color = Color.red; //水印文字颜色
        Font font = new Font("宋体", Font.BOLD, 30); //水印文字字体
        float alpha = 0.4f; //水印透明度
        int startWidth = 30; //水印横向位置坐标
        Integer degree = -0; //水印旋转角度
        Integer interval = 100; //水印的位置
        //给图片添加文字水印
        fullMarkImage(srcImgPath, targetImgPath, text, color, font, alpha, startWidth, degree, interval);
    }
}

2.2、给图像添加图片水印
某些情况下,我们还需要给图像添加图片水印,例如下图效果!

手把手教你如何给图像加水印-鸿蒙开发者社区

处理过程也很简单!

import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

/**
 * 给图像添加水印
 * @author pzblog
 * @since 2021-10-29
 */
public class ImageIconWaterMarkUtil {



    /**
     * 给图像添加多处文字水印
     * @param srcImgPath     原始文件地址
     * @param targetImgPath  目标文件地址
     * @param iconImgPath    水印icon
     * @param alpha          水印透明度
     * @param positionWidth  水印横向位置
     * @param positionHeight 水印纵向位置
     * @param degree         水印图片旋转角度
     * @param location       水印的位置,左上角、右上角、左下角、右下角、居中
     */
    public static void fullMarkImage(String srcImgPath,
                                 String targetImgPath,
                                 String iconImgPath,
                                 float alpha,
                                 int positionWidth,
                                 int positionHeight,
                                 Integer degree,
                                 String location) {
        try {
            // 1、读取源图片
            Image srcImg = ImageIO.read(new File(srcImgPath));
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            BufferedImage buffImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);

            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg.getScaledInstance(srcImgWidth, srcImgHeight, Image.SCALE_SMOOTH), 0, 0, null);
            // 4、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
            }
            // 5、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

            // 6、水印图片的路径 水印图片一般为gif或者png的,这样可设置透明度
            ImageIcon imgIcon = new ImageIcon(iconImgPath);
            // 7、得到Image对象。
            Image iconImg = imgIcon.getImage();
            int iconImgWidth = iconImg.getWidth(null);
            int iconImgHeight = iconImg.getHeight(null);

            int x = 0, y = 0;
            if (StringUtils.equals(location, "left-top")) {
                x = iconImgWidth;
                y = iconImgHeight;
            } else if (StringUtils.equals(location, "right-top")) {
                x = srcImgWidth - iconImgWidth - 30;
                y = iconImgHeight;
            } else if (StringUtils.equals(location, "left-bottom")) {
                x += iconImgWidth;
                y = buffImg.getHeight() - iconImgHeight;
            } else if (StringUtils.equals(location, "right-bottom")) {
                x = srcImgWidth - iconImgWidth - 30;
                y = srcImgHeight - iconImgHeight;
            } else if (StringUtils.equals(location, "center")) {
                x = (srcImgWidth - iconImgWidth) / 2;
                y = (srcImgHeight - iconImgHeight) / 2;
            } else {
                //自定义位置
                x = positionWidth;
                y = positionHeight;
            }
            g.drawImage(iconImg, x, y, null);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
            // 10、释放资源
            g.dispose();
            // 11、生成图片
            ImageIO.write(buffImg, "jpg", new File(targetImgPath));
            System.out.println("图片完成添加图片水印文字");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算填充的水印长度
     * @param text
     * @param g
     * @return
     */
    private static int getWatermarkLength(String text, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(text.toCharArray(), 0, text.length());
    }

    public static void main(String[] args) {
        String srcImgPath = "/Users/pzblog/Desktop/Jietu.jpg"; //原始文件地址
        String targetImgPath = "/Users/pzblog/Desktop/Jietu-copy-img.jpg"; //目标文件地址
        String iconImgPath = "/Users/pzblog/Desktop/1.png"; //图片水印地址
        float alpha = 0.6f; //水印透明度
        int positionWidth = 320; //水印横向位置坐标
        int positionHeight = 450; //水印纵向位置坐标
        Integer degree = 0; //水印旋转角度
        String location = "center"; //水印的位置
        //给图片添加文字水印
        fullMarkImage(srcImgPath, targetImgPath, iconImgPath, alpha, positionWidth, positionHeight, degree, location);
    }
}

三、踩坑点
以上实现都很简单,但是在实际的实现过程中,却发现了一个巨大的坑,如果你用的iphone手机拍摄的,按照以上代码进行添加水印,会发现图像突然变横了!

例如下图是原图:

手把手教你如何给图像加水印-鸿蒙开发者社区按照上面添加水印的处理,得到的图像结果如下:

手把手教你如何给图像加水印-鸿蒙开发者社区

很明显,图像旋转了90度!

通过不同拍摄角度的反复测试,发现拍摄角度正常,但是经过程序处理之后,有些是需要旋转 90/180/270 度才能回正。

如果想要在正确的位置加上水印,就必须先对图像进行旋转回到原有的角度,然后再添加水印!

 

那问题来了,我们如何获取其旋转的角度呢?

经过查阅资料,对于图像的拍摄角度信息,有一个专业的名词:EXIF,EXIF是 Exchangeable Image File的缩写,这是一种专门为数码相机照片设定的格式。

这种格式可以用来记录数字照片的属性信息,例如相机的品牌及型号、相片的拍摄时间、拍摄时所设置的光圈大小、快门速度、ISO等等信息。除此之外它还能够记录拍摄数据,以及照片格式化方式。

通过它,我们可以得知图像的旋转角度信息!

下面,我们就一起来了解下采用 Java 语言如何读取图像的 EXIF 信息,包括如何根据 EXIF 信息对图像进行调整以适合用户浏览。

 ● 首先添加 EXIF 依赖包

<dependency>
    <groupId>com.drewnoakes</groupId>
    <artifactId>metadata-extractor</artifactId>
    <version>2.16.0</version>
</dependency>

 ● 然后读取图像的 EXIF 信息

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;

import java.io.File;
import java.io.IOException;

/**
 * @author pzblog
 * @since 2021-10-29
 */
public class EXIFTest {

    public static void main(String[] args) throws ImageProcessingException, IOException {
        Metadata metadata = ImageMetadataReader.readMetadata(new File("/Users/pzblog/Desktop/11.jpeg"));

        for (Directory directory : metadata.getDirectories()) {
            for (Tag tag : directory.getTags()) {
                System.out.println(String.format("[%s] - %s = %s",
                        directory.getName(), tag.getTagName(), tag.getDescription()));
            }
            if (directory.hasErrors()) {
                for (String error : directory.getErrors()) {
                    System.err.format("ERROR: %s", error);
                }
            }
        }
    }
}

输入结果:

[JPEG] - Compression Type = Baseline
[JPEG] - Data Precision = 8 bits
[JPEG] - Image Height = 1080 pixels
[JPEG] - Image Width = 1440 pixels
[JPEG] - Number of Components = 3
[JPEG] - Component 1 = Y component: Quantization table 0, Sampling factors 2 horiz/2 vert
[JPEG] - Component 2 = Cb component: Quantization table 1, Sampling factors 1 horiz/1 vert
[JPEG] - Component 3 = Cr component: Quantization table 1, Sampling factors 1 horiz/1 vert
[JFIF] - Version = 1.1
[JFIF] - Resolution Units = none
[JFIF] - X Resolution = 72 dots
[JFIF] - Y Resolution = 72 dots
[JFIF] - Thumbnail Width Pixels = 0
[JFIF] - Thumbnail Height Pixels = 0
[Exif IFD0] - Orientation = Right side, top (Rotate 90 CW)
[Exif SubIFD] - Exif Image Width = 1440 pixels
[Exif SubIFD] - Exif Image Height = 1080 pixels
[ICC Profile] - Profile Size = 548
[ICC Profile] - CMM Type = appl
[ICC Profile] - Version = 4.0.0
[ICC Profile] - Class = Display Device
[ICC Profile] - Color space = RGB 
[ICC Profile] - Profile Connection Space = XYZ 
[ICC Profile] - Profile Date/Time = 2017:07:07 13:22:32
[ICC Profile] - Signature = acsp
[ICC Profile] - Primary Platform = Apple Computer, Inc.
[ICC Profile] - Device manufacturer = APPL
[ICC Profile] - XYZ values = 0.964 1 0.825
[ICC Profile] - Tag Count = 10
[ICC Profile] - Profile Description = Display P3
[ICC Profile] - Profile Copyright = Copyright Apple Inc., 2017
[ICC Profile] - Media White Point = (0.9505, 1, 1.0891)
[ICC Profile] - Red Colorant = (0.5151, 0.2412, 65536)
[ICC Profile] - Green Colorant = (0.292, 0.6922, 0.0419)
[ICC Profile] - Blue Colorant = (0.1571, 0.0666, 0.7841)
[ICC Profile] - Red TRC = para (0x70617261): 32 bytes
[ICC Profile] - Chromatic Adaptation = sf32 (0x73663332): 44 bytes
[ICC Profile] - Blue TRC = para (0x70617261): 32 bytes
[ICC Profile] - Green TRC = para (0x70617261): 32 bytes
[Photoshop] - Caption Digest = 212 29 140 217 143 0 178 4 233 128 9 152 236 248 66 126
[Huffman] - Number of Tables = 4 Huffman tables
[File Type] - Detected File Type Name = JPEG
[File Type] - Detected File Type Long Name = Joint Photographic Experts Group
[File Type] - Detected MIME Type = image/jpeg
[File Type] - Expected File Name Extension = jpg
[File] - File Name = 11.jpeg
[File] - File Size = 234344 bytes
[File] - File Modified Date = 星期日 十一月 07 20:05:52 +08:00 2021

其中Orientation标签描述的就是图像旋转的角度。

[Exif IFD0] - Orientation = Right side, top (Rotate 90 CW)

最后,我们可以通过Orientation信息计算出图像对应的旋转角度。

import com.alibaba.fastjson.JSON;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author pzblog
 * @since 2021-10-29
 */
public class TransferImage {

    public static void main(String[] args) throws IOException {
        String path = "/Users/pzblog/Desktop/11.jpeg";
        int result = getImgRotateAngle(new FileInputStream(path));
        System.out.println(result);
    }


    public static int getImgRotateAngle(InputStream inputStream) {
        int rotateAngle = 0;
        try {
            Metadata metadata = JpegMetadataReader.readMetadata(inputStream);
            Iterable<Directory> directories = metadata.getDirectories();
            for (Directory directory : directories) {
                for (Tag tag : directory.getTags()) {
                    System.out.println(JSON.toJSONString(tag));

                    int tagType = tag.getTagType();
                    //照片拍摄角度信息
                    if (274 == tagType) {
                        String description = tag.getDescription();
                        //Left side, bottom (Rotate 270 CW)
                        switch (description) {
                            //顺时针旋转90度
                            case "Right side, top (Rotate 90 CW)":
                                rotateAngle = 90;
                                break;
                            case "Left side, bottom (Rotate 270 CW)":
                                rotateAngle = 270;
                                break;
                            case "Bottom, right side (Rotate 180)":
                                rotateAngle = 180;
                                break;
                            default:
                                rotateAngle = 0;
                                break;
                        }
                    }

                }
            }
            return rotateAngle;
        } catch (Exception e) {
            return 0;
        }
    }
}

输出的旋转角度结果:

90

 ● 接着通过旋转角度参数,对图像进行回正

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * @author panzhi
 * @since 2021-10-29
 */
public class RotateImage {

    public static BufferedImage rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size
        Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);

        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = res.createGraphics();
        // transform
        g2.translate((rect_des.width - src_width) / 2,
                (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

        g2.drawImage(src, null, null);
        return res;
    }

    public static Rectangle calcRotatedSize(Rectangle src, int angel) {
        // if angel is greater than 90 degree, we need to do some conversion
        if (angel >= 90) {
            if(angel / 90 % 2 == 1){
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }

    public static void main(String[] args) throws IOException {
        BufferedImage src = ImageIO.read(new File("/Users/pzblog/Desktop/11.jpeg"));
        BufferedImage des = RotateImage.rotate(src, 90);
        ImageIO.write(des, "jpg", new File("/Users/pzblog/Desktop/11-rotate.jpeg"));
    }
}

 ● 最后给回正后的图像添加水印

public static void main(String[] args) {
    String srcImgPath = "/Users/pzblog/Desktop/11-rotate.jpeg"; //原始文件地址
    String targetImgPath = "/Users/pzblog/Desktop/1-rotate-copy.jpg"; //目标文件地址
    String text = "复 印 无 效"; //水印文字内容
    Color color = Color.red; //水印文字颜色
    Font font = new Font("宋体", Font.BOLD, 60); //水印文字字体
    float alpha = 0.4f; //水印透明度
    int positionWidth = 320; //水印横向位置坐标
    int positionHeight = 450; //水印纵向位置坐标
    Integer degree = -30; //水印旋转角度
    String location = "center"; //水印的位置
    //给图片添加文字水印
    markImage(srcImgPath, targetImgPath, text, color, font, alpha, positionWidth, positionHeight, degree, location);
}

输入结果:

手把手教你如何给图像加水印-鸿蒙开发者社区

添加水印的结果与预期一致!

 

四、小结
给图像添加水印最坑的地方就上面介绍的那个位置,如果是网络截图的照片,基本添加的结果与预期一致,但是采用手机拍摄的,很有可能会发生旋转,因此需要采用一些手法,先获取对应的图像旋转角度,然后进行回正,最后添加水印,保证与预期结果一致!

最后,想要获取源码的同学,可以在公众号留言【cccc01】,即可获取源代码!

 

五、参考
1、掘金 - 手机相机照片添加水印踩坑记录

2、开源博客 - Java实现图片内容无损任意角度旋转

3、csdn - Java 处理 iphone拍照后 图片EXIF属性翻转90度的方法

 

 

 

文章转载自公众号:Java极客技术

分类
标签
已于2022-9-14 10:44:20修改
收藏
回复
举报
回复
    相关推荐