voltear voltea rotar programa para pantalla las invertir imagenes imagen girar fotos espejo como celular automaticamente app java transform transformation interpolation bufferedimage

java - voltea - ¿Cómo se pueden producir resultados de pintura nítidos al rotar una imagen almacenada?



rotar imagen java 2d (3)

Al rotar una imagen rasterizada (como BufferedImage), se pierden datos. La mejor solución es guardar las imágenes más grandes de lo que las necesitará y reducirlas al vuelo cuando las pinte. He encontrado que 1.5 veces el tamaño que necesitas es un buen punto de partida.

Luego, cuando estés pintando la imagen, cambia el tamaño sobre la marcha:

g.drawImage(bufferedImage, x, y, desiredWidth, desiredHeight, observer);

Se recomiendan rotaciones mediante interpolación bilineal .

El crédito para la sugerencia va a guido.

Un intento de acercamiento fue usar TexturePaint y g.fillRect() para pintar la imagen. Sin embargo, esto requiere que cree un nuevo objeto TexturePaint y Rectangle2D cada vez que pinte una imagen, lo que no es ideal, y no ayuda de todos modos.

Cuando uso g.drawImage(BufferedImage,...) , las imágenes rotadas parecen ser borrosas / suaves.

Estoy familiarizado con RenderingHints y el doble búfer (que es lo que estoy haciendo, creo), me resulta difícil creer que no se puede rotar una imagen en Java de manera fácil y eficiente que produce resultados nítidos.

El código para usar TexturePaint ve así.

Grahics2D g2d = (Graphics2D)g; g2d.setPaint(new TexturePaint(bufferedImage, new Rectangle2D.Float(0,0,50,50))); g2d.fillRect(0,0,50,50);

Estoy usando AffineTransform para rotar una mano de cartas en un abanico. ¿Cuál sería el mejor enfoque para pintar imágenes atractivas rápidamente?

Aquí hay una captura de pantalla:

El 9 es nítido pero el resto de las cartas definitivamente no son tan afiladas.

Podría ser posible que el problema radique en cuando creo cada imagen de tarjeta y la almaceno en una matriz.
Así es como lo estoy haciendo en este momento:

// i from 0 to 52, card codes. ... GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gs.getDefaultConfiguration(); BufferedImage img = gc.createCompatibleImage(86, 126, Transparency.TRANSLUCENT); Graphics2D g = img.createGraphics(); setRenderingHints(g); g.drawImage(shadow, 0, 0, 86, 126, null); g.drawImage(white, 3, 3, 80, 120, null); g.drawImage(suit, 3, 3, 80, 120, null); g.drawImage(value, 3, 3, 80, 120, null); g.dispose(); cardImages[i] = img; } private void setRenderingHints(Graphics2D g){ g.setRenderingHint(KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.setRenderingHint(KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); }

¿Cómo debo enfocar esto de manera diferente? Gracias.

Editar:

Sin RenderingHints

Establecer consejos de AA no hizo ninguna diferencia. Además, configurar RenderingHints al crear las imágenes tampoco hace ninguna diferencia. Es solo cuando se rotan con AffineTransform y se pintan con g.drawImage(...) que parecen g.drawImage(...) .
La imagen de arriba muestra la diferencia entre el valor predeterminado (vecino más cercano) y la interpolación bilineal.

Aquí es cómo los estoy pintando actualmente (mucho más rápido que TexturePaint):

// GamePanel.java private void paintCard(Graphics2D g, int code, int x, int y){ g.drawImage(imageLoader.getCard(code), x, y, 86, 126, null); } // ImageLoader.java public BufferedImage getCard(int code){ return cardImages[code]; }

Todas mis tarjetas son 80x120 y la sombra .png es 86x126, para dejar una sombra semitransparente de 3px alrededor de la tarjeta. No es una sombra realista que conozco, pero se ve bien.

Y así, la pregunta se convierte en ... ¿Cómo se pueden producir resultados de pintura nítidos al rotar una imagen almacenada?

Referencia a una pregunta anterior también con respecto a una mano de carta avivada:
¿Cómo se puede detectar un evento de clic del mouse en un objeto de imagen en Java?

Edición de recompensas: De acuerdo, después de mucha discusión, hice algunas tarjetas de prueba .svg para ver cómo SVG Salamander se las tomaría. Desafortunadamente, el rendimiento es terrible. Mi implementación es lo suficientemente limpia, ya que con la imagen de BufferedImage con doble búfer la pintura fue increíblemente rápida. Lo que significa que he completado el círculo y he vuelto a mi problema original.

Daré la recompensa de 50 a quien me pueda dar una solución para obtener rotaciones nítidas de BufferedImage. Se han sugerido hacer las imágenes más grandes de lo necesario y reducirlas antes de pintar, y usar la interpolación bicúbica. Si estas son las únicas soluciones posibles, entonces realmente no sé a dónde ir a partir de aquí y quizás tenga que lidiar con las rotaciones borrosas, ya que ambas imponen retrocesos en el rendimiento.

Puedo terminar mi juego si puedo encontrar una manera de hacerlo bien. Gracias a todos. :)


Configurar el tipo de interpolación, así como el valor de suavizado, en un AffineTransformOp puede ofrecer alguna mejora. El tipo TYPE_BICUBIC , aunque más lento, suele ser la mejor calidad; un ejemplo se resume here . Tenga en cuenta que puede proporcionar varios RenderingHints . Otro error surge de no aplicar las sugerencias cada vez que se representa la imagen. Es posible que también deba ajustar la transparencia del fondo, como se sugiere here . Finalmente, considera crear un sscce que incluya una de tus imágenes reales.


Este consejo es probablemente un poco tarde en su diseño, pero vale la pena mencionarlo.

Las imágenes rasterizadas es probablemente la tecnología incorrecta que se debe utilizar si muchas de las rotaciones y animaciones forman parte de su interfaz de usuario; Especialmente con imágenes complicadas con muchas curvas. Solo espera hasta que intentes y escales tu lienzo. Podría sugerir mirar una biblioteca gráfica basada en vectores. Representarán los tipos de efectos que desee con menos potencial para artefactos.

http://xmlgraphics.apache.org/batik/using/swing.htm