Maison  >  Article  >  Java  >  Exemple d'analyse de la façon d'ajouter un filigrane aux images en Java

Exemple d'analyse de la façon d'ajouter un filigrane aux images en Java

黄舟
黄舟original
2017-07-18 09:34:041578parcourir

Le développement de filigranes est une fonction relativement courante dans le développement Web, et le code implémenté est très simple. Cet article présente principalement des cas de développement de filigranes d'images JAVA, qui ont une certaine valeur de référence.

Écrivez-le au début

La semaine dernière, j'ai passé une semaine à faire des recherches fragmentaires sur le développement des filigranes, et maintenant j'ai enfin écrit une démo d'entrée de gamme et pris des notes. référence.

La démo est construite sur le cadre d'importation et d'exportation de fichiers (méthode POI) du cas pratique JAVA que j'ai écrit la dernière fois, basé sur Spring+SpringMVC. Merci de me corriger s'il y a des erreurs.

Une brève introduction

Le développement de filigranes est une fonction courante dans le développement Web. Le code implémenté est très simple. Je suivrai également les étapes de mise en œuvre spécifiques. Description détaillée basée sur le code. En fait, sur la base de ma compréhension personnelle, je divise les types et les processus de développement des filigranes dans les catégories suivantes.

Types de filigranes :

Filigrane de texte unique
Filigrane d'image unique
Filigranes de texte multiples
Filigranes d'image multiples

Processus de développement du filigrane :

  • Créer un objet de cache d'image

  • Créer un objet outil de dessin Java

  • Utilisez l'objet outil de dessin pour dessiner l'image originale sur l'objet image du cache

  • Utilisez le dessin objet outil pour dessiner l'image originale sur l'objet image du cache Dessiner des filigranes (texte/images) sur les images mises en cache

  • Créer une classe d'outils d'encodage d'image

  • Utilisez la classe d'outils d'encodage d'image pour afficher l'image mise en cache dans le fichier cible

Rendu :

Page de téléchargement :

Image originale :

Filigrane de texte unique :

Filigrane d'image unique :

Filigranes de texte multiples :

Filigranes d'image multiples :

Développement d'un filigrane de texte unique

Le soi-disant filigrane de texte consiste à ajouter un filigrane de texte à une image. Notre processus principal consiste à décoder l'image correspondante via la classe d'outils ImageIO, puis à créer un objet BufferImage et à créer un objet Graphics2D via BufferImage object , puis dessinez l'image originale sur l'objet BufferImage via l'objet Graphics2D. Ensuite, nous pouvons également utiliser l'objet Graphics2D pour définir des informations relatives au filigrane, telles que le contenu du filigrane, la taille de la police, le style de police, etc.
Ce qui doit être expliqué ici, c'est que nous devons calculer la largeur du texte en filigrane. La longueur chinoise est la largeur du texte et la longueur anglaise est la moitié de la largeur du texte. Pour plus de détails, veuillez vous référer au contenu pertinent dans mon code source.


 //计算水印文本长度
 //1、中文长度即文本长度 2、英文长度为文本长度二分之一
 public int getTextLength(String text){
  //水印文字长度
  int length = text.length();

  for (int i = 0; i < text.length(); i++) {
   String s =String.valueOf(text.charAt(i));
   if (s.getBytes().length>1) {
    length++;
   }
  }
  length = length%2==0?length/2:length/2+1;
  return length;
 }


//添加单条文字水印方法
public String textWaterMark(MultipartFile myFile,String imageFileName) {
InputStream is =null;
OutputStream os =null;
int X = 636;
int Y = 700;

  try {
   //使用ImageIO解码图片
   Image image = ImageIO.read(myFile.getInputStream());
   //计算原始图片宽度长度
   int width = image.getWidth(null);
   int height = image.getHeight(null);
   //创建图片缓存对象
   BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
   //创建java绘图工具对象
   Graphics2D graphics2d = bufferedImage.createGraphics();
   //参数主要是,原图,坐标,宽高
   graphics2d.drawImage(image, 0, 0, width, height, null);
   graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
   graphics2d.setColor(FONT_COLOR);

   //使用绘图工具将水印绘制到图片上
   //计算文字水印宽高值
   int waterWidth = FONT_SIZE*getTextLength(MARK_TEXT);
   int waterHeight = FONT_SIZE;
   //计算水印与原图高宽差
   int widthDiff = width-waterWidth;
   int heightDiff = height-waterHeight;
   //水印坐标设置
   if (X > widthDiff) {
    X = widthDiff;
   }
   if (Y > heightDiff) {
    Y = heightDiff;
   }
   //水印透明设置
   graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
   //纵坐标在下方,不增加字体高度会靠上
   graphics2d.drawString(MARK_TEXT, X, Y+FONT_SIZE);

   graphics2d.dispose();
   os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);
   //创建图像编码工具类
   JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);
   //使用图像编码工具类,输出缓存图像到目标文件
   en.encode(bufferedImage);
   if(is!=null){  
    is.close();
   }
   if(os!=null){
    os.close();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
  return "success";
 }

Développement de filigrane d'image unique

Filigrane d'image unique et Le flux de code du texte unique ci-dessus est à peu près le même, seules les différences sont expliquées ici.
Nous devons d'abord obtenir le chemin de l'image du filigrane, puis créer un objet fichier de filigrane, et également décoder l'image du filigrane via la classe d'outils ImageIO. En attendant, nous n'avons pas besoin de calculer la longueur et la largeur du filigrane. texte, car la longueur et la largeur d’un seul texte correspondent à notre image de filigrane.


   //水印图片路径
   //水印坐标设置
   String logoPath = "/img/logo.png";
   String realPath = request.getSession().getServletContext().getRealPath(logoPath);
   File logo = new File(realPath);
   Image imageLogo = ImageIO.read(logo);
   int widthLogo = imageLogo.getWidth(null);
   int heightLogo = imageLogo.getHeight(null);
   int widthDiff = width-widthLogo;
   int heightDiff = height-heightLogo;
   //水印坐标设置
   if (X > widthDiff) {
    X = widthDiff;
   }
   if (Y > heightDiff) {
    Y = heightDiff;
   }
   //水印透明设置
   graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
   graphics2d.drawImage(imageLogo, X, Y, null);

Développement de filigranes multi-textes

En fait, le développement de filigranes multi-textes est similaire au texte unique, le La principale différence est oui, nous devons faire pivoter l'objet BufferImage. Étant donné que le dessin de filigranes ne prend pas en charge la rotation des filigranes, nous devons faire pivoter l'image d'origine, puis, à travers des boucles, nous pouvons dessiner un filigrane de texte sur l'image d'origine plusieurs fois.


 //旋转原图,注意旋转角度为弧度制。后面两个参数为旋转的坐标中心
   graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);

   int x = -width/2;
   int y = -height/2;

   while(x < width*1.5){
    y = -height/2;
    while(y < height*1.5){
     graphics2d.drawString(MARK_TEXT, x, y);
     y+=waterHeight+100;
    }
    x+=waterWidth+100;
   }

Développement de filigrane multi-images

Comme ci-dessus, le filigrane multi-images doit d'abord lire l'image du filigrane , puis définissez la transparence du filigrane, faites pivoter l'image d'origine, puis grâce à une boucle, nous pouvons dessiner un filigrane d'image sur l'image d'origine plusieurs fois.


 //水印图片路径
   String logoPath = "/img/logo.png";
   String realPath = request.getSession().getServletContext().getRealPath(logoPath);
   File logo = new File(realPath);
   Image imageLogo = ImageIO.read(logo);
   int widthLogo = imageLogo.getWidth(null);
   int heightLogo = imageLogo.getHeight(null);
   
   //水印透明设置
   graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
   
   graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);
   
   int x = -width/2;
   int y = -height/2;

   while(x < width*1.5){
    y = -height/2;
    while(y < height*1.5){
     graphics2d.drawImage(imageLogo, x, y, null);
     y+=heightLogo+100;
    }
    x+=widthLogo+100;
   }

Code commercial complet :


import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.allan.service.WaterMarkService;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
@Service
public class WaterMarkServiceImpl implements WaterMarkService{
 //定义上传的文件夹
 private static final String UPLOAD_PATH = "E:/save";
 //定义水印文字样式
 private static final String MARK_TEXT = "小卖铺的老爷爷";
 private static final String FONT_NAME = "微软雅黑";
 private static final int FONT_STYLE = Font.BOLD;
 private static final int FONT_SIZE = 60;
 private static final Color FONT_COLOR = Color.black;


 private static final float ALPHA = 0.3F;


 //1、上传图片
 public String uploadImage(MultipartFile myFile,String imageFileName) {
 InputStream is =null;
 OutputStream os =null;
 try{
  is = myFile.getInputStream();
  os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);
  byte[] buffer =new byte[1024];
  int len = 0;

  while ((len=is.read(buffer))>0){
  os.write(buffer);
  }

 }catch(Exception e){
  e.printStackTrace();
 }finally{
  if(is!=null){
  try {
   is.close();
  } catch (IOException e) {

   e.printStackTrace();
  }
  }
  if(os!=null){
  try {
   os.close();
  } catch (IOException e2) {
   e2.printStackTrace();
  }
  }
 }

 return "success";

 }
 //添加单条文字水印
 public String textWaterMark(MultipartFile myFile,String imageFileName) {
 InputStream is =null;
 OutputStream os =null;
 int X = 636;
 int Y = 700;

 try {
  Image image = ImageIO.read(myFile.getInputStream());
  //计算原始图片宽度长度
  int width = image.getWidth(null);
  int height = image.getHeight(null);
  //创建图片缓存对象
  BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
  //创建java绘图工具对象
  Graphics2D graphics2d = bufferedImage.createGraphics();
  //参数主要是,原图,坐标,宽高
  graphics2d.drawImage(image, 0, 0, width, height, null);
  graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
  graphics2d.setColor(FONT_COLOR);

  //使用绘图工具将水印绘制到图片上
  //计算文字水印宽高值
  int waterWidth = FONT_SIZE*getTextLength(MARK_TEXT);
  int waterHeight = FONT_SIZE;
  //计算水印与原图高宽差
  int widthDiff = width-waterWidth;
  int heightDiff = height-waterHeight;
  //水印坐标设置
  if (X > widthDiff) {
  X = widthDiff;
  }
  if (Y > heightDiff) {
  Y = heightDiff;
  }
  //水印透明设置
  graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
  graphics2d.drawString(MARK_TEXT, X, Y+FONT_SIZE);

  graphics2d.dispose();
  os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);
  //创建图像编码工具类
  JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);
  //使用图像编码工具类,输出缓存图像到目标文件
  en.encode(bufferedImage);
  if(is!=null){ 
  is.close();
  }
  if(os!=null){
  os.close();
  }
 } catch (IOException e) {
  e.printStackTrace();
 }
 return "success";
 }

 //添加单图片水印
 public String imageWaterMark(MultipartFile myFile,String imageFileName,HttpServletRequest request) {
 InputStream is =null;
 OutputStream os =null;
 int X = 636;
 int Y = 763;

 try {
  Image image = ImageIO.read(myFile.getInputStream());
  //计算原始图片宽度长度
  int width = image.getWidth(null);
  int height = image.getHeight(null);
  //创建图片缓存对象
  BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
  //创建java绘图工具对象
  Graphics2D graphics2d = bufferedImage.createGraphics();
  //参数主要是,原图,坐标,宽高
  graphics2d.drawImage(image, 0, 0, width, height, null);
  graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
  graphics2d.setColor(FONT_COLOR);

  //水印图片路径
  String logoPath = "/img/logo.png";
  String realPath = request.getSession().getServletContext().getRealPath(logoPath);
  File logo = new File(realPath);
  Image imageLogo = ImageIO.read(logo);
  int widthLogo = imageLogo.getWidth(null);
  int heightLogo = imageLogo.getHeight(null);
  int widthDiff = width-widthLogo;
  int heightDiff = height-heightLogo;
  //水印坐标设置
  if (X > widthDiff) {
  X = widthDiff;
  }
  if (Y > heightDiff) {
  Y = heightDiff;
  }
  //水印透明设置
  graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
  graphics2d.drawImage(imageLogo, X, Y, null);

  graphics2d.dispose();
  os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);
  //创建图像编码工具类
  JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);
  //使用图像编码工具类,输出缓存图像到目标文件
  en.encode(bufferedImage);
  if(is!=null){ 
  is.close();
  }
  if(os!=null){
  os.close();
  }
 } catch (IOException e) {
  e.printStackTrace();
 }
 return "success";
 }
 //添加多条文字水印
 public String moreTextWaterMark(MultipartFile myFile,String imageFileName) {
 InputStream is =null;
 OutputStream os =null;
 int X = 636;
 int Y = 763;

 try {
  Image image = ImageIO.read(myFile.getInputStream());
  //计算原始图片宽度长度
  int width = image.getWidth(null);
  int height = image.getHeight(null);
  //创建图片缓存对象
  BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
  //创建java绘图工具对象
  Graphics2D graphics2d = bufferedImage.createGraphics();
  //参数主要是,原图,坐标,宽高
  graphics2d.drawImage(image, 0, 0, width, height, null);
  graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
  graphics2d.setColor(FONT_COLOR);

  //使用绘图工具将水印绘制到图片上
  //计算文字水印宽高值
  int waterWidth = FONT_SIZE*getTextLength(MARK_TEXT);
  int waterHeight = FONT_SIZE;

  //水印透明设置
  graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
  graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);

  int x = -width/2;
  int y = -height/2;

  while(x < width*1.5){
  y = -height/2;
  while(y < height*1.5){
   graphics2d.drawString(MARK_TEXT, x, y);
   y+=waterHeight+100;
  }
  x+=waterWidth+100;
  }
  graphics2d.dispose();

  os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);
  //创建图像编码工具类
  JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);
  //使用图像编码工具类,输出缓存图像到目标文件
  en.encode(bufferedImage);
  if(is!=null){ 
  is.close();
  }
  if(os!=null){
  os.close();
  }
 } catch (IOException e) {
  e.printStackTrace();
 }
 return "success";
 }

 //多图片水印
 public String moreImageWaterMark(MultipartFile myFile,String imageFileName,HttpServletRequest request) {
 InputStream is =null;
 OutputStream os =null;
 int X = 636;
 int Y = 763;

 try {
  Image image = ImageIO.read(myFile.getInputStream());
  //计算原始图片宽度长度
  int width = image.getWidth(null);
  int height = image.getHeight(null);
  //创建图片缓存对象
  BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
  //创建java绘图工具对象
  Graphics2D graphics2d = bufferedImage.createGraphics();
  //参数主要是,原图,坐标,宽高
  graphics2d.drawImage(image, 0, 0, width, height, null);
  graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
  graphics2d.setColor(FONT_COLOR);

  //水印图片路径
  String logoPath = "/img/logo.png";
  String realPath = request.getSession().getServletContext().getRealPath(logoPath);
  File logo = new File(realPath);
  Image imageLogo = ImageIO.read(logo);
  int widthLogo = imageLogo.getWidth(null);
  int heightLogo = imageLogo.getHeight(null);
  
  //水印透明设置
  graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
  
  graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);
  
  int x = -width/2;
  int y = -height/2;

  while(x < width*1.5){
  y = -height/2;
  while(y < height*1.5){
   graphics2d.drawImage(imageLogo, x, y, null);
   y+=heightLogo+100;
  }
  x+=widthLogo+100;
  }
  graphics2d.dispose();
  os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);
  //创建图像编码工具类
  JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);
  //使用图像编码工具类,输出缓存图像到目标文件
  en.encode(bufferedImage);
  if(is!=null){ 
  is.close();
  }
  if(os!=null){
  os.close();
  }
 } catch (IOException e) {
  e.printStackTrace();
 }
 return "success";
 }

 //计算水印文本长度
 //1、中文长度即文本长度 2、英文长度为文本长度二分之一
 public int getTextLength(String text){
 //水印文字长度
 int length = text.length();

 for (int i = 0; i < text.length(); i++) {
  String s =String.valueOf(text.charAt(i));
  if (s.getBytes().length>1) {
  length++;
  }
 }
 length = length%2==0?length/2:length/2+1;
 return length;
 }
}

Enfin, cette démo a été écrite basé sur le dernier framework d'importation et d'exportation de fichiers. Il existe d'autres codes de démonstration dans le code source. Les principales classes utilisées sont WaterMarkController.java, WaterMarkService.java et WaterMarkServiceImpl.java, car j'ai codé en dur E dans le code : /save dossier Si vous souhaitez l'exécuter, veuillez d'abord créer un nouveau dossier ou le remplacer par un autre dossier.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn