Как обрезать изображение на Java?

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

Ответ 1

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

Моя процедура обрезки закончилась следующим образом:

  private BufferedImage cropImage(BufferedImage src, Rectangle rect) {
      BufferedImage dest = src.getSubimage(0, 0, rect.width, rect.height);
      return dest; 
   }

Ответ 2

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

public 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

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

Ответ 3

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

import javax.image.BufferedImage; // I think
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 javax.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) в этот класс. Надеюсь, это поможет.

Ответ 4

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

Ответ 5

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

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

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

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

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

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

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