Jak uzyskać ostre rezultaty malowania podczas obracania obrazu bufora?

Jedną z prób było użycie TexturePaint i g.fillRect() do namalowania obrazu. Wymaga to jednak utworzenia nowego obiektu Textturepaint i Rectangle2D za każdym razem, gdy malujesz obraz, co nie jest idealne - i tak nie pomaga.

Kiedy używam g.drawImage(BufferedImage,...), obrócone obrazy wydają się być niewyraźne/miękkie.

Jestem zaznajomiony z RenderingHints i podwójnym buforowaniem (co chyba robię), po prostu trudno mi uwierzyć, że nie można łatwo i skutecznie obróć obraz w języku Java, który daje ostre wyniki.

Kod do użycia TexturePaint wygląda mniej więcej tak.

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

Używam AffineTransform aby obrócić rękę z kart do wachlarza. Jakie byłoby najlepsze podejście do szybkiego malowania dobrze wyglądających obrazów?

Oto zrzut ekranu:
Przykład rozmytych obrotów
9 jest ostry, ale reszta kart zdecydowanie nie są tak ostre.

Możliwe, że problem tkwi w tym, kiedy tworzę każdy obraz karty i przechowuję go w tablica.
Oto Jak to robię w tej chwili:

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

Jak mam podejść do tego inaczej? Dzięki.

Edytuj:
Przykład ręki bez renderowania
Bez Renderingu

Ustawienie podpowiedzi AA nie miało znaczenia. Również ustawienie RenderingHints podczas tworzenia obrazów również nie ma znaczenia. Tylko wtedy, gdy są obracane za pomocą AffineTransform i malowane za pomocą g.drawImage(...), wydają się rozmywać.
powyższy obrazek pokazuje różnicę między domyślna (najbliższa Sąsiadka) i Dwuliniowa interpolacja.

Oto jak je obecnie maluję (znacznie szybciej niż Textturepaint):

// 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];
  }
Wszystkie moje karty to 80x120 i cień .png to 86x126, tak aby pozostawić półprzezroczysty Cień 3px wokół karty. Wiem, że to nie jest realistyczny cień, ale wygląda dobrze.

I tak powstaje pytanie... jak można uzyskać ostre efekty malowania podczas obracania obrazu bufora?

Odniesienie do poprzedniego pytanie również dotyczące rozdania kart:
W Jaki Sposób można wykryć Zdarzenie kliknięcia myszką na obiekcie obrazu w Javie?

Bounty-Edit: OK, więc po wielu dyskusjach zrobiłem kilka testów .karty svg, aby zobaczyć, jak SVG będzie je renderować. Niestety, wykonanie jest fatalne. Moja realizacja jest wystarczająco czysta, ponieważ w przypadku buforowanego BufferedImage obraz był niewiarygodnie szybki. Co oznacza, że zatoczyłem pełne koło i wróciłem do mojego oryginalny problem.

Dam 50 bounty każdemu, kto może dać mi rozwiązanie, aby uzyskać ostre obroty BufferedImage. Zasugerowano, aby obrazy były większe niż muszą być i zmniejszone przed malowaniem, a także użycie interpolacji dwubiegunowej. Jeśli są to jedyne możliwe rozwiązania, to naprawdę Nie wiem, dokąd się udać i być może będę musiał po prostu poradzić sobie z niewyraźnymi obrotami - ponieważ oba te rozwiązania narzucają problemy z wydajnością.

I can finish my game if I może znaleźć sposób, aby to zrobić dobrze. Dziękuję wszystkim. :)

Author: rtheunissen, 2011-07-17

3 answers

Po obróceniu rasteryzowanego obrazu (np. obrazu buforowanego) tracisz dane. Najlepszym rozwiązaniem jest zapisywanie obrazów większych niż będą potrzebne i zmniejszanie ich w locie podczas malowania. Odkryłem, że 1,5 x Rozmiar, którego potrzebujesz, to dobry punkt wyjścia.

Następnie, gdy malujesz obraz, Zmień rozmiar w locie:

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

Zaleca się rotację za pomocą interpolacji dwuliniowej.

uznanie za sugestię należy się guido.

 9
Author: paranoid-android,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-16 16:44:15

Ta rada jest prawdopodobnie trochę za późno w Twoim projekcie, ale może warto wspomnieć.

Rasteryzowane obrazy są prawdopodobnie niewłaściwą technologią, jeśli wiele obrotów i animacji jest częścią interfejsu użytkownika; szczególnie w przypadku skomplikowanych obrazów z dużą ilością krzywych. Poczekaj, aż spróbujesz przeskalować swoje płótna. Proponuję spojrzeć na bibliotekę graficzną opartą na wektorach. Będą renderować pożądane efekty z mniejszym potencjałem dla artefakty.

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

 5
Author: mbarnes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-17 19:41:20

Ustawianie typu interpolacji, a także wartości antyaliasingu, w AffineTransformOp może zaoferować pewną poprawę. Typ TYPE_BICUBIC, choć wolniejszy, jest zazwyczaj najlepszą jakością; przykład przedstawiono tutaj . Należy pamiętać, że można dostarczyć wiele RenderingHints. Kolejna pułapka wynika z braku zastosowania podpowiedzi za każdym razem, gdy obraz jest renderowany. Może być również konieczne dostosowanie przezroczystości tła, zgodnie z sugestią tutaj . Na koniec rozważ utworzenie sscce w tym jeden z Twoich rzeczywistych zdjęć.

 4
Author: trashgod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:29:45