通过java实现自动根据图片的格式类型给图片添加水印


博主的 Github 地址


0.前言

该程序要用到eclipse中的swt插件来实现可视化编程
插件的安装及使用操作可在我这一篇博客中获取
https://blog.csdn.net/leon9dragon/article/details/91864590

运行结果在本文最后放出

该程序仅支持jpg,png和bmp三种格式
有需要的朋友可自行魔改程序中获取图片格式部分的代码即可增加格式类型

图片格式类型的获取是通过文件流来进行获取的
通过判断对比文件头然后来给图片添加水印
下面列举了部分文件头

常用文件的文件头如下:(以前六位为准)
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D
CAD (dwg),文件头:41433130
Adobe Photoshop (psd),文件头:38425053
Rich Text Format (rtf),文件头:7B5C727466
XML (xml),文件头:3C3F786D6C
HTML (html),文件头:68746D6C3E
Email [thorough only] (eml),文件头:44656C69766572792D646174653A
Outlook Express (dbx),文件头:CFAD12FEC5FD746F
Outlook (pst),文件头:2142444E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0
MS Access (mdb),文件头:5374616E64617264204A
WordPerfect (wpd),文件头:FF575043
Postscript (eps.or.ps),文件头:252150532D41646F6265
Adobe Acrobat (pdf),文件头:255044462D312E
Quicken (qdf),文件头:AC9EBD8F
Windows Password (pwl),文件头:E3828596
ZIP Archive (zip),文件头:504B0304
RAR Archive (rar),文件头:52617221
Wave (wav),文件头:57415645
AVI (avi),文件头:41564920
Real Audio (ram),文件头:2E7261FD
Real Media (rm),文件头:2E524D46
MPEG (mpg),文件头:000001BA
MPEG (mpg),文件头:000001B3
Quicktime (mov),文件头:6D6F6F76
Windows Media (asf),文件头:3026B2758E66CF11
MIDI (mid),文件头:4D546864

1.代码实现

ps1:
这个程序本来是我毕设设计的系统的其中一个界面
是可以获取登录用户的名字然后打在水印上的
但这里我进行了删除了这部分内容,并不影响整个程序的运行
这里默认的图片作者名字是null
有需要的朋友可以根据自己设计的系统再重新嵌入这部分代码

ps2:
同时这部分代码中默认的图片输出格式是bmp格式
因为获取文件头的时候是取的前6位
然而bmp格式的文件头只有4位
为了省事,直接默认进行bmp格式的输出
有需要的朋友可以再在判断格式这部分通过字符串对比的方法进行修改

package com.blog.watermark;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;

public class testWatermark extends JFrame {

	private JPanel contentPane;
	private JTextField pathField;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					testWatermark frame = new testWatermark();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public testWatermark() {
		setTitle("\u6DFB\u52A0\u6C34\u5370\u754C\u9762");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		pathField = new JTextField();
		pathField.setBounds(52, 99, 240, 21);
		contentPane.add(pathField);
		pathField.setColumns(10);
		
		JButton cpathBton = new JButton("\u9009\u62E9\u56FE\u7247");
		cpathBton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				cpathaction(arg0);
			}
		});
		cpathBton.setBounds(297, 98, 93, 23);
		contentPane.add(cpathBton);
		
		markBton = new JButton("\u6DFB\u52A0\u6C34\u5370");
		markBton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					markaction(arg0);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		});
		markBton.setBounds(155, 130, 93, 23);
		contentPane.add(markBton);
		
		JLabel lbljpg = new JLabel("\u652F\u6301jpg/png/bmp\u683C\u5F0F\u7684\u56FE\u7247");
		lbljpg.setFont(new Font("黑体", Font.BOLD, 15));
		lbljpg.setForeground(Color.RED);
		lbljpg.setBounds(52, 74, 240, 15);
		contentPane.add(lbljpg);
	}
	
	public String imgname = null;//文件名称,包括了后缀
	public String imgpath = null;//文件所在的文件夹路径
	private JButton markBton;
	//选择图片路径事件
	public void cpathaction(ActionEvent arg0){
		JFileChooser fileChooser=new JFileChooser("C:/Users/Administrator/Desktop/");//默认首先搜寻路径,可根据自己的需要进行修改
		if(fileChooser.showOpenDialog(null)==JFileChooser.APPROVE_OPTION){
			pathField.setText(fileChooser.getSelectedFile().getPath());//文本框给出路径
			imgname = fileChooser.getSelectedFile().getName();//获取加密文件名
			imgpath = pathField.getText() ;
			imgpath = imgpath.substring(0,imgpath.length()-imgname.length());//获取加密的文件所在的文件夹
		}
	}
	
	
	//添加水印按钮事件
	public void markaction(ActionEvent arg0) throws Exception{
		
		String path = pathField.getText();//获取图片路径
		String markimg = imgpath   + "(watermark)" + imgname;
		String authorname = null;
		/**
		  这部分本来是获取数据库中用户名的代码
		  删除掉并不影响程序的实现
		  若有需要可自行编写
		*/
		// 原图位置, 输出图片位置, 水印文字颜色, 水印文字+作者名字
        new testWatermark().addmark(path, markimg,Color.red, "图片作者:" + authorname);
	}
	
    //添加水印的功能实现,同时通过文件流来检测图片的类型,仅支持jpg和png和bmp格式
    public void addmark(String srcImgPath, String outImgPath, Color markColor, String waterMarkContent) {
        try {//参数分别是(要添加水印的图片的路径,添加水印后图片输出路径,水印文字的颜色,水印的文字)       	            
            File srcImgFile = new File(srcImgPath);
            //检测图片文件是否存在
            if(!srcImgFile.exists()) {	        	 
	            JOptionPane.showMessageDialog(null, "请先选择图片");
	            throw  new NullPointerException("Watermark file is empty");
	         }            
            // 读取原图片
            Image srcImg = ImageIO.read(srcImgFile);
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);           
            // 加水印
            BufferedImage buffImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = buffImg.createGraphics();//得到画笔对象
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);            
            Font font = new Font("黑体", Font.PLAIN, 25);//设置水印的字体
            g.setFont(font);            
            g.setColor(markColor); // 设置水印颜色            
            int x = srcImgWidth - getWatermarkLength(waterMarkContent, g) - 3;//设置水印的坐标(x,y)
            int y = srcImgHeight - 3;       
            g.drawString(waterMarkContent, x, y);//waterMarkContent是设置的内容,后面两个参数是文字在图片上的坐标位置(x,y)
            g.dispose();
            //获取图片类型后缀,用文件流进行判断
            FileInputStream filetype = new FileInputStream(srcImgPath);
            byte[] b = new byte[3];
            filetype.read(b, 0, b.length);
            String prefix = bytesToHexString(b);
            prefix = prefix.toUpperCase();
            String suffix = checkType(prefix);
            System.out.println("后缀名是:" + suffix);
            
            // 输出图片,因为获取了图片的后缀,png和bmp也可以输出
            FileOutputStream outImgStream = new FileOutputStream(outImgPath);
            ImageIO.write(buffImg, suffix, outImgStream);
            outImgStream.flush();
            outImgStream.close();
            JOptionPane.showMessageDialog(null, "添加水印成功");
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "添加水印失败");
        }
    }

    //获取水印文字总长度
    public int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }
    //返回文件格式后缀
    //由于bmp文件的文件头只有4位,而文件流获取的是6位,因此无法比较,所以默认输出格式是bmp
    //有想法的朋友可以给我留言给出修改意见,谢谢
    public static String checkType(String xxxx) {
        switch (xxxx) {
        case "FFD8FF": return "jpg";
        case "89504E": return "png";
        
        default: return "bmp";
        }
    }
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

}

2.运行效果

1)选择图片
选择图片
2)添加水印,控制台也会输出图片后缀名,不需要的话可以删除这部分代码
添加水印
3)图片效果
没添加水印的原图
这是笔者花了3秒钟画的,很好看吧~
原图
添加水印后的图片
水印图片
如图右下角出现了红色水印(被csdn的白色水印盖住了一点…)
水印的颜色,字体,大小等都可以在代码中进行调整
作者名字如开头所说,可以通过连接数据库获取
也可直接设定变量authorname=你所需要的名字

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Java中为图片添加固定大小的水印,您可以使用Java的Graphics2D类来实现。以下是一个简单的示例代码: ```java import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class AddWatermark { public static void main(String[] args) { try { // 读取原始图片 BufferedImage originalImage = ImageIO.read(new File("original.jpg")); // 创建一个带透明度的图片 BufferedImage watermarkedImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_INT_ARGB); // 获取Graphics2D对象 Graphics2D g2d = (Graphics2D) watermarkedImage.getGraphics(); // 将原始图片绘制到带透明度的图片中 g2d.drawImage(originalImage, 0, 0, null); // 设置水印字体 Font font = new Font("Arial", Font.BOLD, 36); g2d.setFont(font); // 设置水印颜色 g2d.setColor(Color.RED); // 设置水印透明度 AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); g2d.setComposite(alphaChannel); // 绘制水印 String watermark = "My Watermark"; FontMetrics fontMetrics = g2d.getFontMetrics(); Rectangle2D rect = fontMetrics.getStringBounds(watermark, g2d); int centerX = (originalImage.getWidth() - (int) rect.getWidth()) / 2; int centerY = (originalImage.getHeight() - (int) rect.getHeight()) / 2; g2d.drawString(watermark, centerX, centerY); // 保存带水印图片 ImageIO.write(watermarkedImage, "png", new File("watermarked.png")); // 释放资源 g2d.dispose(); System.out.println("Watermark added successfully."); } catch (IOException ex) { System.err.println(ex); } } } ``` 在这个示例代码中,我们首先读取原始图片,并创建一个新的带透明度的BufferedImage对象。然后,我们获取Graphics2D对象,并将原始图片绘制到带透明度的图片中。接下来,我们设置水印的字体、颜色和透明度,并在图片中央绘制水印。最后,我们保存带水印图片,并释放资源。 请注意,在本示例中,水印的大小是根据水印文本自动计算的,以使其居中。如果您希望水印的大小是固定的,请根据需要调整绘制水印的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值