Как мне обрезать изображение в Java? - PullRequest
65 голосов
/ 05 марта 2010

Я хочу обрезать изображение вручную с помощью мыши.
Предположим, на изображении есть текст, и я хочу выделить текст на изображении, затем для этого я хочу обрезать эту область с помощью мыши.

Ответы [ 7 ]

140 голосов
/ 27 января 2011

Решение, которое я нашел наиболее полезным для обрезки буферизованного изображения, использует getSubImage (x, y, w, h);

Моя процедура обрезки в итоге выглядела так:

  private BufferedImage cropImage(BufferedImage src, Rectangle rect) {
      BufferedImage dest = src.getSubimage(0, 0, rect.width, rect.height);
      return dest; 
   }
37 голосов
/ 11 мая 2014

Есть две потенциально серьезные проблемы с основным ответом на этот вопрос. Во-первых, согласно документам:

публичный BufferedImage getSubimage (int x, Int y, Int W, int h)

Возвращает подизображение, заданное указанной прямоугольной областью. Возвращенный BufferedImage использует тот же массив данных, что и исходный изображение.

По сути, это означает, что результат getSubimage действует как указатель, указывающий на подраздел исходного изображения.

Почему это важно? Что ж, если вы по какой-либо причине планируете редактировать подизображение, редактирование также произойдет с исходным изображением. Например, я столкнулся с этой проблемой, когда использовал маленькое изображение в отдельном окне, чтобы увеличить исходное изображение. (вроде как увеличительное стекло). Я сделал возможным инвертировать цвета, чтобы легче видеть определенные детали, но область, которая была «увеличена», также инвертировалась в исходном изображении! Таким образом, была небольшая часть исходного изображения, которая имела инвертированные цвета, в то время как остальная часть оставалась нормальной. Во многих случаях это не имеет значения, но если вы хотите отредактировать изображение или просто хотите получить копию обрезанного раздела, вы можете рассмотреть метод.

Что подводит нас ко второй проблеме. К счастью, это не такая большая проблема, как первая. getSubImage использует тот же массив данных, что и исходное изображение. Это означает, что все оригинальное изображение все еще сохраняется в памяти. Предполагая, что при «обрезании» изображения вам действительно нужно изображение меньшего размера, вам нужно будет перерисовать его как новое изображение, а не просто получить подизображение.

Попробуйте это:

BufferedImage img = image.getSubimage(startX, startY, endX, endY); //fill in the corners of the desired crop location here
BufferedImage copyOfImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = copyOfImage.createGraphics();
g.drawImage(img, 0, 0, null);
return copyOfImage; //or use it however you want

Этот метод сам даст вам обрезанное изображение, которое вы ищете, без ссылки на исходное изображение. Это сохранит целостность исходного изображения, а также сэкономит вам память на хранение большего изображения. (Если вы сделаете дамп исходного изображения позже)

14 голосов
/ 05 марта 2010

Это метод, который будет работать:

import java.awt.image.BufferedImage;
import java.awt.Rectangle;
import java.awt.Color;
import java.awt.Graphics;

public BufferedImage crop(BufferedImage src, Rectangle rect)
{
    BufferedImage dest = new BufferedImage(rect.getWidth(), rect.getHeight(), BufferedImage.TYPE_ARGB_PRE);
    Graphics g = dest.getGraphics();
    g.drawImage(src, 0, 0, rect.getWidth(), rect.getHeight(), rect.getX(), rect.getY(), rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight(), null);
    g.dispose();
    return dest;
}

Конечно, вы должны создать свой собственный JComponent:

import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.Rectangle;
import java.awt.Graphics;
import javax.swing.JComponent;

public class JImageCropComponent extends JComponent implements MouseListener, MouseMotionListener
{
   private BufferedImage img;
   private int x1, y1, x2, y2;

   public JImageCropComponent(BufferedImage img)
   {
       this.img = img;
       this.addMouseListener(this);
       this.addMouseMotionListener(this);
   }

   public void setImage(BufferedImage img)
   {
       this.img = img;
   }

   public BufferedImage getImage()
   {
       return this;
   }

   @Override
   public void paintComponent(Graphics g)
   {
      g.drawImage(img, 0, 0, this);
      if (cropping)
      {
          // Paint the area we are going to crop.
          g.setColor(Color.RED);
          g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2));
      }
   }

   @Override
   public void mousePressed(MouseEvent evt)
   {
       this.x1 = evt.getX();
       this.y1 = evt.getY();
   }

   @Override
   public void mouseReleased(MouseEvent evt)
   {
       this.cropping = false;
       // Now we crop the image;
       // This is the method a wrote in the other snipped
       BufferedImage cropped = crop(new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2));
       // Now you have the cropped image;
       // You have to choose what you want to do with it
       this.img = cropped;
   }

   @Override
   public void mouseDragged(MouseEvent evt)
   {
       cropping = true;
       this.x2 = evt.getX();
       this.y2 = evt.getY();
   }

   //TODO: Implement the other unused methods from Mouse(Motion)Listener

}

Я не проверял это. Возможно, есть некоторые ошибки (я не уверен насчет всего импорта).

Вы можете поместить метод crop(img, rect) в этот класс. Надеюсь, это поможет.

10 голосов
/ 18 января 2016
File fileToWrite = new File(filePath, "url");

BufferedImage bufferedImage = cropImage(fileToWrite, x, y, w, h);

private BufferedImage cropImage(File filePath, int x, int y, int w, int h){

    try {
        BufferedImage originalImgage = ImageIO.read(filePath);

        BufferedImage subImgage = originalImgage.getSubimage(x, y, w, h);



        return subImgage;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
6 голосов
/ 05 марта 2010

На этот вопрос недостаточно информации, чтобы ответить. Общее решение (в зависимости от вашей структуры GUI): добавьте обработчик событий мыши, который будет ловить щелчки и движения мыши. Это даст вам ваши (х, у) координаты. Затем используйте эти координаты, чтобы обрезать ваше изображение.

2 голосов
/ 05 марта 2010

Вам нужно прочитать о Java Image API и API, связанном с мышью, возможно, где-то под java.awt.event package.

Для начала вам нужно иметь возможность загружать и отображать изображение на экране, возможно, вы будете использовать JPanel.

Затем оттуда вы попытаетесь реализовать интерфейс слушателя движения мыши и другие связанные интерфейсы. Может быть, вы будете привязаны к mouseDragged методу ...

Для действия mousedragged вы получите координату прямоугольной формы путем перетаскивания ...

Затем из этих координат вы получите изображение с имеющегося у вас изображения, и вы как бы перерисовываете его заново ....

А затем покажите обрезанное изображение ... Я не знаю, сработает ли это, просто продукт моего воображения ... просто мысль!

0 голосов
/ 03 сентября 2018

Я привожу этот пример, потому что это действительно работает для моего варианта использования.

Я пытался использовать AWS Rekognition API . API возвращает объект BoundingBox:

BoundingBox boundingBox = faceDetail.getBoundingBox();

Код ниже использует его для обрезки изображения:

import com.amazonaws.services.rekognition.model.BoundingBox;

private BufferedImage cropImage(BufferedImage image, BoundingBox box) {
        Rectangle goal = new Rectangle(Math.round(box.getLeft()* image.getWidth()),Math.round(box.getTop()* image.getHeight()),Math.round(box.getWidth() * image.getWidth()), Math.round(box.getHeight() * image.getHeight()));

        Rectangle clip = goal.intersection(new Rectangle(image.getWidth(), image.getHeight()));

        BufferedImage clippedImg = image.getSubimage(clip.x, clip.y , clip.width, clip.height);

        return clippedImg;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...