2010-12-06 33 views
5

Quiero copiar parte de una imagen en otra más pequeña: en otras palabras, copie un subrectangle.¿Cómo copio parte de una imagen a otra?

Tengo un objetoGraphics2D para la fuente, puedo hacer uno para el objetivo, y sé quién es targetGraphics2D.drawImage (img Imagen, ....), pero ¿cómo puedo conseguir que img del sourceGraphics2D?


respuesta (por aioobe): La fuente debe ser un imagen en lugar de un Graphics2D.

Image.subImage() es el método para obtener la parte relevante de la fuente.

+2

Tenga en cuenta que la sub-imagen() no copia el subyacente datos de imagen, al menos con BufferedImage. Entonces, si dibujas sobre la Imagen obtenida por subimagen() también modificas el original, mientras que con target.createGraphics(). DrawImage (Img de Imagen, ...) realmente haces una copia. – Trilarion

Respuesta

0

En primer lugar, algunas notas sobre Andreas_D respuesta a continuación:

  • Su código se basa en sun.java2d.SunGraphics2D que es una clase de OpenJDK interna y no documentada. Esto significa que, si bien podría compilarse y ejecutarse en su computadora, es posible que se rompa si distribuye el código a otras personas. Para una discusión detallada, vea el official statement con respecto a esto.

  • El código se basa en la reflexión para abrir la clase interna abierta, que es un olor de código en sí mismo.

  • Con todo, su enfoque es un ejemplo de excepcionalmente malas prácticas (tanto cuando se trata de estilo de programación y cuando se trata de ayudar compañeros programadores utilizar la API correctamente)


¿cómo obtengo ese img del sourceGraphics2D?

Sospecho que usted no entendió la responsabilidad de la clase Graphics2D.

Utiliza la clase Graphics2D para dibujar en algo. Es capaz de dibujar en un BufferedImage (si tiene el objeto gráfico de una imagen almacenada en el búfer), la pantalla (si lo tiene como argumento para su método paintComponent) o incluso una impresora. En otras palabras, dado un objeto Graphics2D, ¡puede que ni siquiera exista una imagen!

Por lo tanto, como probablemente entiendas, la API Graphics2D no proporciona métodos para obtener la imagen subyacente. (¡Este método no tendría sentido, el objeto gráfico podría estar pasando líneas y texto que se dibuja en una impresora!)

Para sujetar una subimagen, necesita obtener la imagen subyacente que el objeto gráfico dado se inspira.

+0

OK, entiendo. La fuente debe ser una Imagen en lugar de un Graphics2D. Luego, Image.subImage() es el método para obtener el clip. –

+0

Sí. Algo así :-) – aioobe

+2

¡Ah, vamos, siempre hay una manera! (Y en este caso: el "lápiz" recuerda lo que ha dibujado ;-)) –

3

Como dijo Aioobe, no obtendrá la imagen solo de Graphics2D.Pero si su SourceGraphics2D proviene de un componente Swing, puede intentar invocar sus métodos de pintura con su propia instancia de Graphics2D. Desde allí puedes copiar la interesante subregión.

Esto es como un truco, pero debería funcionar suponiendo que está utilizando objetos Swing.

class CopySwingPaintingSubRegion extends TheSourceType 
{ 
     private BufferedImage bufImg; 

     public CopySwingPaintingSubRegion() 
     { 
      bufImg = new BufferedImage(...); 

      //Draw the original image into our bufImg for copying 
      super.paintComponent(bufImg.createGraphics()); 
     } 

     public BufferedImage getSubImage(int x, int y, int w, int h) 
     { 
      return bufImg.getSubImage(x,y,w,h); 
     } 
} 
3

Respuesta corta: Sí, se puede

Un objeto Graphics2D que se ha creado en una imagen tamponada sabe la imagen, pero no está dispuesto a entregar de nuevo a usted. Si no te importa usar el reflejo, puedes robar atrás (reflejo). El código siguiente muestra el enfoque:

public class Graphics2DReflector { 

    public static void main(String[] args) { 
    // prepare the Graphics2D - note, we don't keep a ref to the image! 
    final Graphics2D g2d = 
      new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB).createGraphics(); 
    g2d.drawString("Reflected", 10, 50); 


    JFrame frame = new JFrame("Reflected Image"); 
    // one Panel to show the image only known by g2d 
    frame.getContentPane().add(new Panel() { 
     @Overwrite 
     public void paint(Graphics g) { 
     try { 
      SurfaceData data = ((SunGraphics2D) g2d).surfaceData; 
      Field bufImg = BufImgSurfaceData.class.getDeclaredField("bufImg"); 
      bufImg.setAccessible(true); 
      BufferedImage image = (BufferedImage) bufImg.get(data); 
      g.drawImage(image,0,0,null); 
     } catch (Exception oops) { 
      oops.printStackTrace(); 
     } 
     } 
    }); 
    frame.setSize(200,200); 
    frame.setVisible(); 
    } 
} 

Nota: esto depende de algunas clases de Sun/Oracle y podría no funcionar con todas las máquinas virtuales de Java. Al menos muestra un enfoque y es posible que deba inspeccionar las clases reales para obtener los campos.

+1

confiando tanto en el paquete 'sun. *' Como en la misma respuesta ... jeje;) Probablemente deberías al menos enumerar las circunstancias bajo que el objeto 'Graphics2D' realmente * es * a' SunGraphics2D' Lea [Por qué los desarrolladores no deben escribir programas That Call 'sun' Packages] (http://java.sun.com/products/jdk/faq/faq-sun-packages.html). – aioobe

+1

@aiobe - Oye, es un truco y ya agregué una nota general para esas limitaciones. Dijiste que no funciona y yo solo respondí: es posible. No es portátil en absoluto, pero no imposible. –

1

Si lo entiendo bien, W3Schools tiene un código para obtener parte de una imagen para poner en un lienzo. Si lo necesita como otra imagen, puede obtenerlo de ese lienzo.

tengo una imagen PNG 20 de alto por 200 de ancho que tiene 10 "células o marcos" - que utilizo para la animación y el uso el método siguiente:

context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height); 
Cuestiones relacionadas