【问题标题】:How can I watermark an image in Java?如何在 Java 中为图像添加水印?
【发布时间】:2011-03-28 13:30:24
【问题描述】:

如何使用 Java 在图像上创建水印?我需要将用户输入的文本添加到图像上提供的位置。任何示例代码/建议都会有所帮助。

【问题讨论】:

    标签: java image watermark


    【解决方案1】:

    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);
    

    在上面的代码中,文本Hello World 将绘制在originalImage 的中心,使用等宽字体,黑色前景色,14 pt。

    或者,如果要将水印图像应用于现有图像,可以使用Watermark 图像过滤器:

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

    以上代码会将watermarkImage 叠加在originalImage 之上,居中,不透明度为50%。

    Thumbnailator 将在普通的旧 Java SE 上运行——无需安装任何第三方库。 (但是,需要使用 Sun Java 运行时。)

    全面披露:我是 Thumbnailator 的开发者。

    【讨论】:

    • 我试过这个,但它用一些有线颜色制作图像。创建图像线我需要做些什么吗? BufferedImage originalImage = ...; BufferedImage watermarkImage = ...;
    • @user608576:您是否偶然在 Thumbnailator 项目页面上提交了有关此问题的报告? (code.google.com/p/thumbnailator/issues/detail?id=10) 如果您这样做了,请提供有关您遇到的问题的更多信息。谢谢!
    【解决方案2】:
    【解决方案3】:

    我最近也有类似的需求,发现这篇文章很有用: http://www.codeyouneed.com/java-watermark-image/

    那里的水印方法使用ImgScalr在需要时调整水印的大小,并支持将文本放置在图像的底部/顶部+水印图像。

    为了选择正确的位置,它使用一个简单的 ENUM

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

    而整个水印逻辑都在这个方法中:

    /**
     * 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;
    
    }
    

    而相应的计算水印大小的方法是:

    /**
     * 
     * @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();
    
    }
    

    再次感谢 http://www.codeyouneed.com/java-watermark-image/ 提供一个不错的示例。

    【讨论】:

      【解决方案4】:

      我用于我的项目 IM4Java library - java 的 imagemagick 包装器。水印示例见http://www.imagemagick.org/Usage/annotating/

      【讨论】:

      • @user608576 是的,但需要在服务器上安装 imagemagick
      • +1 然后尝试使用像selonen.org/arto/netbsd/watermarks.html 这样的技术。但是还没有这样做,所以不确定它是否会起作用......
      【解决方案5】:

      使用此代码,它可以工作.. 此处,图像用作水印,并放置在位置 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();
          }
        }
      }
      

      【讨论】:

        【解决方案6】:

        以下是在任何图像上添加水印的代码

        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!");
        
          }
        

        }

        【讨论】:

          【解决方案7】:

          首先在 Windows 的 C:\Imagemagick 文件夹中安装 Imagemagick

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

          安装时添加 C:\ImageMagick;在PATH环境变量中

          并使用下面的代码

              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/>");
             }
          }
          

          }

          【讨论】:

            猜你喜欢
            • 2016-07-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-05-27
            • 2017-07-24
            • 2016-10-11
            • 1970-01-01
            相关资源
            最近更新 更多