简体   繁体   English

如何在 Java 中为图像加水印?

[英]How can I watermark an image in Java?

How can I create a watermark over an image using Java?如何使用 Java 在图像上创建水印? I need user-entered text to be added to a provided position over an image.我需要将用户输入的文本添加到图像上提供的位置。 Any sample code/suggestions will help.任何示例代码/建议都会有所帮助。

In Thumbnailator , one can add a text caption to an existing image by using the Caption image filter:Thumbnailator 中,可以使用Caption图像过滤器向现有图像添加文本标题:

// Image to add a text caption to.
BufferedImage originalImage = ...;

// Set up the caption properties
String caption = "Hello World";
Font font = new Font("Monospaced", Font.PLAIN, 14);
Color c = Color.black;
Position position = Positions.CENTER;
int insetPixels = 0;

// Apply caption to the image
Caption filter = new Caption(caption, font, c, position, insetPixels);
BufferedImage captionedImage = filter.apply(originalImage);

In the above code, the text Hello World will be drawn on centered on the originalImage with a Monospaced font, with a black foreground color, at 14 pt.在上面的代码中,文本Hello World将绘制在originalImage中心,使用 Monospaced 字体,前景色为黑色,14 pt。

Alternatively, if a watermark image is to be applied to an existing image, one can use the Watermark image filter:或者,如果要将水印图像应用于现有图像,则可以使用Watermark图像过滤器:

BufferedImage originalImage = ...;
BufferedImage watermarkImage = ...;

Watermark filter = new Watermark(Positions.CENTER, watermarkImage, 0.5f);
BufferedImage watermarkedImage = filter.apply(originalImage);

The above code will superimpose the watermarkImage on top of the originalImage , centered with an opacity of 50%.上面的代码将watermarkImage叠加在originalImage之上,居中,不透明度为 50%。

Thumbnailator will run on plain old Java SE -- one does not have to install any third party libraries. Thumbnailator 将在普通的旧 Java SE 上运行——无需安装任何第三方库。 (However, using the Sun Java runtime is required.) (但是,需要使用 Sun Java 运行时。)

Full disclosure: I am the developer for Thumbnailator.完全披露:我是 Thumbnailator 的开发人员。

I had a similar need recently and found this post rather useful: http://www.codeyouneed.com/java-watermark-image/我最近有类似的需求,发现这篇文章很有用: http : //www.codeyouneed.com/java-watermark-image/

The watermark method there uses ImgScalr for resizing the watermark when needed and supports placing text in the bottom / top of the image + the watermark image.那里的水印方法在需要时使用 ImgScalr 调整水印的大小,并支持在图像的底部/顶部 + 水印图像中放置文本。

For choosing the correct placement it uses a simple ENUM为了选择正确的位置,它使用一个简单的 ENUM

public enum PlacementPosition {
    TOPLEFT, TOPCENTER, TOPRIGHT, MIDDLELEFT, MIDDLECENTER, MIDDLERIGHT, BOTTOMLEFT, BOTTOMCENTER, BOTTOMRIGHT
}

And the whole watermarking logic is in this method:整个水印逻辑都在这个方法中:

/**
 * Generate a watermarked image.
 * 
 * @param originalImage
 * @param watermarkImage
 * @param position
 * @param watermarkSizeMaxPercentage
 * @return image with watermark
 * @throws IOException
 */
public static BufferedImage watermark(BufferedImage originalImage,
        BufferedImage watermarkImage, PlacementPosition position,
        double watermarkSizeMaxPercentage) throws IOException {

    int imageWidth = originalImage.getWidth();
    int imageHeight = originalImage.getHeight();

    int watermarkWidth = getWatermarkWidth(originalImage, watermarkImage,
            watermarkSizeMaxPercentage);
    int watermarkHeight = getWatermarkHeight(originalImage, watermarkImage,
            watermarkSizeMaxPercentage);

    // We create a new image because we want to keep the originalImage
    // object intact and not modify it.
    BufferedImage bufferedImage = new BufferedImage(imageWidth,
            imageHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
    g2d.drawImage(originalImage, 0, 0, null);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

    int x = 0;
    int y = 0;
    if (position != null) {
        switch (position) {
        case TOPLEFT:
            x = 0;
            y = 0;
            break;
        case TOPCENTER:
            x = (imageWidth / 2) - (watermarkWidth / 2);
            y = 0;
            break;
        case TOPRIGHT:
            x = imageWidth - watermarkWidth;
            y = 0;
            break;

        case MIDDLELEFT:
            x = 0;
            y = (imageHeight / 2) - (watermarkHeight / 2);
            break;
        case MIDDLECENTER:
            x = (imageWidth / 2) - (watermarkWidth / 2);
            y = (imageHeight / 2) - (watermarkHeight / 2);
            break;
        case MIDDLERIGHT:
            x = imageWidth - watermarkWidth;
            y = (imageHeight / 2) - (watermarkHeight / 2);
            break;

        case BOTTOMLEFT:
            x = 0;
            y = imageHeight - watermarkHeight;
            break;
        case BOTTOMCENTER:
            x = (imageWidth / 2) - (watermarkWidth / 2);
            y = imageHeight - watermarkHeight;
            break;
        case BOTTOMRIGHT:
            x = imageWidth - watermarkWidth;
            y = imageHeight - watermarkHeight;
            break;

        default:
            break;
        }
    }

    g2d.drawImage(Scalr.resize(watermarkImage, Method.ULTRA_QUALITY,
            watermarkWidth, watermarkHeight), x, y, null);

    return bufferedImage;

}

And the corresponding methods for calculating the watermark size is:而相应的计算水印大小的方法是:

/**
 * 
 * @param originalImage
 * @param watermarkImage
 * @param maxPercentage
 * @return
 */
private static Pair<Double, Double> calculateWatermarkDimensions(
        BufferedImage originalImage, BufferedImage watermarkImage,
        double maxPercentage) {

    double imageWidth = originalImage.getWidth();
    double imageHeight = originalImage.getHeight();

    double maxWatermarkWidth = imageWidth / 100.0 * maxPercentage;
    double maxWatermarkHeight = imageHeight / 100.0 * maxPercentage;

    double watermarkWidth = watermarkImage.getWidth();
    double watermarkHeight = watermarkImage.getHeight();

    if (watermarkWidth > maxWatermarkWidth) {
        double aspectRatio = watermarkWidth / watermarkHeight;
        watermarkWidth = maxWatermarkWidth;
        watermarkHeight = watermarkWidth / aspectRatio;
    }

    if (watermarkHeight > maxWatermarkHeight) {
        double aspectRatio = watermarkWidth / watermarkHeight;
        watermarkHeight = maxWatermarkHeight;
        watermarkWidth = watermarkHeight / aspectRatio;
    }

    return Pair.of(watermarkWidth, watermarkHeight);
}

/**
 * 
 * @param originalImage
 * @param watermarkImage
 * @param maxPercentage
 * @return
 */
public static int getWatermarkWidth(BufferedImage originalImage,
        BufferedImage watermarkImage, double maxPercentage) {

    return calculateWatermarkDimensions(originalImage, watermarkImage,
            maxPercentage).getLeft().intValue();

}

/**
 * 
 * @param originalImage
 * @param watermarkImage
 * @param maxPercentage
 * @return
 */
public static int getWatermarkHeight(BufferedImage originalImage,
        BufferedImage watermarkImage, double maxPercentage) {

    return calculateWatermarkDimensions(originalImage, watermarkImage,
            maxPercentage).getRight().intValue();

}

Again, all credits to http://www.codeyouneed.com/java-watermark-image/ for a nice sample.同样,所有功劳都归功于http://www.codeyouneed.com/java-watermark-image/一个不错的示例。

use this code, it works.. here, an image is used as a watermark and is place at location 10,10使用此代码,它可以工作..在这里,图像用作水印并位于位置 10,10

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

public class WatermarkImage {

  public static void addWatermark(String localImagePath) {

    try {
        BufferedImage image = ImageIO.read(new File(localImagePath));
        BufferedImage overlay = ImageIO.read(new File(".\\data\\watermark\\watermark.png"));

        // create the new image, canvas size is the max. of both image sizes
        int w = Math.max(image.getWidth(), overlay.getWidth());
        int h = Math.max(image.getHeight(), overlay.getHeight());
        BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

        // paint both images, preserving the alpha channels
        Graphics g = combined.getGraphics();
        g.drawImage(image, 0, 0, null);
        g.drawImage(overlay, 10, 0, null);

        ImageIO.write(combined, "PNG", new File(localImagePath));
    } catch (IOException e) {
        e.printStackTrace();
    }
  }
}

Below is the code to add water mark on any image下面是在任何图像上添加水印的代码

import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

public class WatermarkImage {

  public static void main(String[] args) {

        File origFile = new File("C:/OrignalImage.jpg");
        ImageIcon icon = new ImageIcon(origFile.getPath());

        // create BufferedImage object of same width and height as of original image
        BufferedImage bufferedImage = new BufferedImage(icon.getIconWidth(),
                    icon.getIconHeight(), BufferedImage.TYPE_INT_RGB);

        // create graphics object and add original image to it
        Graphics graphics = bufferedImage.getGraphics();
        graphics.drawImage(icon.getImage(), 0, 0, null);

        // set font for the watermark text
        graphics.setFont(new Font("Arial", Font.BOLD, 30));

        //unicode characters for (c) is \u00a9
        String watermark = "\u00a9 JavaXp.com";

        // add the watermark text
        graphics.drawString(watermark, 0, icon.getIconHeight() / 2);
        graphics.dispose();

        File newFile = new File("C:/WatermarkedImage.jpg");
        try {
              ImageIO.write(bufferedImage, "jpg", newFile);
        } catch (IOException e) {
              e.printStackTrace();
        }

        System.out.println(newFile.getPath() + " created successfully!");

  }

} }

I used for my projects IM4Java library - imagemagick wrapper for java.我在我的项目中使用了IM4Java 库- java 的 imagemagick 包装器。 For watermarking example see http://www.imagemagick.org/Usage/annotating/有关水印示例,请参阅http://www.imagemagick.org/Usage/annotating/

First intall Imagemagick in C:\\Imagemagick folder in windows using首先在 Windows 中的 C:\\Imagemagick 文件夹中安装 Imagemagick 使用

http://www.imagemagick.org/download/binaries/ImageMagick-6.8.8-7-Q16-x86-dll.exe http://www.imagemagick.org/download/binaries/ImageMagick-6.8.8-7-Q16-x86-dll.exe

while installation add C:\\ImageMagick;安装时添加 C:\\ImageMagick; in PATH enviornment variable在 PATH 环境变量中

and use below code并使用下面的代码

    package UploadServlet;

    import java.io.*;
    import java.util.*;

    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;        
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.commons.io.output.*;

    /**
     * Servlet implementation class UploadServlet
     */
    public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
 * @see HttpServlet#HttpServlet()
 */
 private boolean isMultipart;
 private String filePath;
 private int maxFileSize = 50 * 1024;
 private int maxMemSize = 4 * 1024;
 private File file ;

public UploadServlet() {
    super();
    // TODO Auto-generated constructor stub
}

public void init(){
    // Get the file location where it would be stored.
    filePath = getServletContext().getInitParameter("file-upload"); 
 }
/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
     throw new ServletException("GET method used with " +
                getClass( ).getName( )+": POST method required.");
}

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    // Check that we have a file upload request
      isMultipart = ServletFileUpload.isMultipartContent(request);
      response.setContentType("text/html");
      java.io.PrintWriter out = response.getWriter( );
      if( !isMultipart ){
         out.println("<html>");
         out.println("<head>");
         out.println("<title>Servlet upload</title>");  
         out.println("</head>");
         out.println("<body>");
         out.println("<p>No file uploaded</p>"); 
         out.println("</body>");
         out.println("</html>");
         return;
      }
      DiskFileItemFactory factory = new DiskFileItemFactory();
      // maximum size that will be stored in memory
      factory.setSizeThreshold(maxMemSize);
      // Location to save data that is larger than maxMemSize.
      factory.setRepository(new File("c:\\temp"));

      // Create a new file upload handler
      ServletFileUpload upload = new ServletFileUpload(factory);
      // maximum file size to be uploaded.
      upload.setSizeMax( maxFileSize );

      try{ 
      // Parse the request to get file items.
      List fileItems = upload.parseRequest(request);

      // Process the uploaded file items
      Iterator i = fileItems.iterator();

      out.println("<html>");
      out.println("<head>");
      out.println("<title>Servlet upload</title>");  
      out.println("</head>");
      out.println("<body>");
      out.println("<h3>Watermark :</h3>");
      out.println("Select a file to upload: <br />");
      out.println("<form action=\"UploadServlet\" method=\"post\" enctype=\"multipart/form-data\">");
      out.println("<input type=\"file\" name=\"file\" size=\"50\" /><br/>");
      out.println("<input type=\"submit\" value=\"Upload File\" />");
      out.println("</form><br/>");
      while ( i.hasNext () ) 
      {
         FileItem fi = (FileItem)i.next();
         if ( !fi.isFormField () )  
         {
            // Get the uploaded file parameters
            String fieldName = fi.getFieldName();
            String fileName = fi.getName();
            //System.out.println("Filename:" + fileName);
            String contentType = fi.getContentType();
            boolean isInMemory = fi.isInMemory();
            long sizeInBytes = fi.getSize();
            // get application path
            String webAppPath = getServletContext().getRealPath("/");
            //System.out.println("Web Application Path :" + webAppPath);

            // Write the file

            file = new File( webAppPath + "ImageTest.jpeg") ;

            fi.write( file ) ;


            out.println("<br/><h3>Uploaded File :</h3><img src=\"ImageTest.jpeg\" height='300px' width='300px' />");

            String command = "";
            command = "convert.exe -draw \"gravity south fill black text 0,0 'Watermark' \" \"" + webAppPath + "ImageTest.jpeg \" \""+ webAppPath +"imageTest_result.jpg \"";
            ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);
            Process p = pb.start();
            try {
                Thread.sleep(1000);
            } catch(InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
             out.println("<br/><h3>Watermarked File :</h3><img src=\"imageTest_result.jpg\" height='300px' width='300px' />");

         }

      }
      out.println("</body>");
      out.println("</html>");
   }catch(Exception ex) {
       System.out.println(ex);
       out.println("<br/><font color='red'><b>"+ex.getMessage()+"</b></font><br/>");
   }
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM