Как поставить водяной знак на изображение в Java?

Как я могу создать водяной знак на изображении с помощью Java? Мне нужно, чтобы введенный пользователем текст был добавлен в указанную позицию над изображением. Любой пример кода/предложения поможет.


person Pit Digger    schedule 28.03.2011    source источник


Ответы (7)


Вы можете ознакомиться с разделом «Нанесение водяного знака» на странице http://web.archive.org/web/20080324030029/http://blog.codebeach.com/2008/02/watermarking-images.-in-java-servlet.html

Или вы можете использовать библиотеку GIF4J http://www.gif4j.com/java-gif4j-pro-gif-image-watermark.htm#gifimagewatermarkapply

person Wavyx    schedule 28.03.2011
comment
Я использовал этот blog.codebeach.com/2008/ 02/ - person Pit Digger; 29.03.2011

В 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.

person coobird    schedule 28.03.2011
comment
Я пробовал это, но это делает изображение с некоторыми проводными цветами. Есть ли что-то, что мне нужно сделать с созданием линий изображения? BufferedImage originalImage = ...; BufferedImage WatermarkImage = ...; - person Pit Digger; 14.05.2011
comment
@ user608576: Вы случайно не отправили отчет по этой проблеме на странице проекта Thumbnailator? (code.google.com/p/thumbnailator/issues/detail?id =10) Если да, предоставьте дополнительную информацию о проблеме, с которой вы столкнулись. Спасибо! - person coobird; 14.05.2011

Недавно у меня была похожая потребность, и я нашел этот пост довольно полезным: 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/ за хороший образец.

person Reigo    schedule 14.07.2014

Я использовал для своих проектов библиотеку IM4Java - обёртку imagemagick для java. Пример водяного знака см. на странице http://www.imagemagick.org/Usage/annotating/.

person Eugene Burtsev    schedule 28.03.2011
comment
@user608576 user608576 Да, но на сервере должен быть установлен imagemagick - person Eugene Burtsev; 28.03.2011

используйте этот код, он работает .. здесь изображение используется в качестве водяного знака и размещается в месте 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();
    }
  }
}
person amithgc    schedule 16.09.2013

Ниже приведен код для добавления водяного знака на любое изображение.

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

  }

}

person Nirbhay Rana    schedule 01.03.2016

Сначала установите Imagemagick в папку C:\Imagemagick в Windows, используя

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

}

person prem30488    schedule 03.03.2014