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:
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:
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. :)
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.
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.
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ęć.
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