Problemy z wyświetlaniem obrazów w Swingu w Windows

0

Oglądam ten program:

http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

Jak się kliknie przycisk trzeci od lewej, to teoretycznie pojawia się kształt z gradientem.

Testowałem na komputerze z Windows XP 32bit i pojawiają się błyskające białe linie. Posiadam również Linux i MacOS w maszynach wirtualnych, tam wszystko pokazuje się prawidłowo.
Testowałem również na innym komputerze z Windows 7 i są te same błędy, jak z Windows XP.

Nieraz piszę programy wyświetlające bitmapy BufferedImage jako ikonę JLabel i czasem obrazki wyświetlają się z błędami takimi, że w losowym obszarze jest inny fragment tego samego obrazka, takich błędów nie ma w Linux i Mac OS. Jest to błąd podobny do tego, jak przy wyświetlaniu animacji w powyższym programie. Jeżeli po wyświetleniu obrazka wykonuje się na nim operacje wiążące się z odczytem pikseli (zapis do pliku, kopiowanie do innego obrazka, skalowanie, obracanie itp.), to te operacje wykonują się prawidłowo, tak, jakby obrazek był wyświetlony bezbłędnie.

Co jest przyczyną błędów i jak go rozwiązać?

0

Jestem laikiem w Javie, coś sobie w niej dłubie ale jak dla mnie brak tam podwójnego buforowania.
Windows nie wyrabia z odświeżaniem obrazka i takie są efekty.
Wejdź na stronę poniżej, tam jest Applet, poruszaj sobie szybko "rybą" a zobaczysz migotanie.
Prosty przykład odrysowywania obrazka i linii bez buforowania.
http://www.konstruktorbudowlany.republika.pl/

Pozdrawiam

0
tomasz79 napisał(a)

Jestem laikiem w Javie, coś sobie w niej dłubie ale jak dla mnie brak tam podwójnego buforowania.
Windows nie wyrabia z odświeżaniem obrazka i takie są efekty.
Wejdź na stronę poniżej, tam jest Applet, poruszaj sobie szybko "rybą" a zobaczysz migotanie.
Prosty przykład odrysowywania obrazka i linii bez buforowania.
http://www.konstruktorbudowlany.republika.pl/

Pozdrawiam

Tu o coś zupełnie innego chodzi, mój problem nie ma chyba nic wzpólnego z tym, co piszesz i jest w aplecie.

W oknie interfejsu (obiekt dziedziczący po javax.swing.JFrame) jest JLabel o nazwie ViewerScreen.

Ponadto jest w nim metoda do wyświetlania obrazu:

    public void SetPicture(BufferedImage Pic)
    {
        ViewerScreen.setIcon(new ImageIcon(Pic));
    }

Obraz wyświetla się w skali 1:1, więc przed wyświetleniem trzeba go przygotować. Samo generowanie obrazu przebiega prawidłowo, tylko przy wyświetlaniu są błędy. Obraz nie jest odświeżany w sposób ciągły, jak np. powyższy aplet z rybą, tylko jest raz wyświetlony i czeka na akcję użytkownika, której skutkiem może być wyświetlenie innego obrazu, ewentualnie tego samego przy innych parametrach generowania. W załączniku screenshoty przedstawiające okno wyświetlające anaglif z błędami. Prawidłowe obrazy są przedstawione na tej stronie:
http://www.fotopolis.pl/index.php?n=12626&p=7
Na tych screenach, żółte i niebieskie cienie to efekt zamierzony (anaglif w systemie ColorCode 3D), natomiast prostokąt wyświetlający fragment innego obszaru obrazu jest niepożądany.

Taki błąd zdarza się raz na kilka-kilkanaście wyświetleń (każde wyświetlenie to wywołanie metody SetPicture przedstawione powyżej). Jeżeli jest błąd, to ponowne wyświetlenie tego samego najczęściej wyświetla bez błędu.

Stwierdziłem, że błąd dotyczy tylko wyswietlania. Po wyświetleniu z błędem uzyskiwane kolory pikseli przy GetRGB są prawidłowe, po zapisaniu do plikuj przez ImageIO.write też nie ma błędu.

Jak przerobić okno interfejsu programu, żeby nie było błędów przy wyświetlaniu.

0

Mała sugestia. Od Javy 6 (lub 5) wszystkie obiekty BufferedImage mogą użyć buforowania w pamięci układu graficznego bez względu na to czy klient używający tych obiektów zamierza używać akceleracji sprzętowej czy nie.
A pamięć taka może zostać stracona lub uszkodzona (np. w taki sposób jak na tych obrazkach). I oczywiście służy ona wyłącznie do wyświetlania. Nadal głównym buforem do obróbki pozostaje bufor w pamięci JVM, więc wszystkie operacje graficzne działają właśnie na nim.
Nie wiem czy to pomoże, ale spróbuj użyć metody na takim obiekcie setAccelerationPriority(0f), co wyłączy używanie pamięci graficznej przez obiekt na którym wymuszono zakaz akceleracji i wymusi na nim klasyczne kopiowanie swojego bufora w celu wyświetlania.
Jest to tym bardziej prawdopodobne skoro występuje tylko na systemach Windows, a Java właśnie na nich intensywnie używa przyspieszenia sprzętowego.

0

Przerobiłem procedurę wyświetlającą obrazki:

    public void SetPicture(BufferedImage Pic)
    {
        Pic.setAccelerationPriority(0);
        ViewerScreen.setIcon(new ImageIcon(Pic));
        ViewerScreen.repaint();
    }

Teraz błędy zdarzają się rzadziej, ale zdarzają się.

Czy dobrze zrobiłem?
Czy da się tak zrobić, żeby cała maszyna wirtualna nie korzystała z akceleracji grafiki?

0

Jak chcesz w ogóle wyłączyć tę akcelerację:

<applet id="jakis_id" archive="applet.jar" code="costam.MojApplet.class">
	<PARAM name="java_arguments" value="-Dsun.java2d.translaccel=false">
</applet>

ale spróbuj najpierw zamiast tego dać tam -Dsun.java2d.opengl=true może to wina directx, że się tak psuje

0

http://www.falstad.com/circuit/

Zaraz po uruchomieniu apletu w większości przypadków błyskają niepożądane fragmenty obrazu. Na 99% jest to ten sam problem, z którym ja się borykam i jest tematem tego wątku. Jak się we właściwościach ekranu przejdzie do zaawansowanych i suwak "przyspieszenie sprzętowe" przesunie w lewo do końca, czyli całkowicie wyłącza przyspieszenie, to problemu nie ma.

Czy u Was też jest ten problem? Wcześniej szukałem w Googlach rozwiązania i nic ciekawego nie znalazłem, nawet opisu, że taki problem istnieje.

0

Czytałeś w ogóle co napisałem?

poza tym, upewnij się, że masz zainstalowane sterowniki do karty graficznej od wydawcy, a nie te od microsoftu...

Teraz mały test...

Sprawdź tutaj czy zostają takie artefakty:
http://dev.keraj.net/javaballs/java-volatile.html - tylko zaznacz "slowdown"

jeśli zostają, to sprawdź to - korzysta z opengl zamiast z dx
http://dev.keraj.net/javaballs/java-volatile-opengl.html - też zaznacz slowdown

Na koniec sprawdź jak tutaj:
http://dev.keraj.net/javaballs/java-volatile-noaccel.html

i powiedz jak wyszło wszędzie.

0
Kerai napisał(a)

Jak chcesz w ogóle wyłączyć tę akcelerację:

<applet id="jakis_id" archive="applet.jar" code="costam.MojApplet.class">
	<PARAM name="java_arguments" value="-Dsun.java2d.translaccel=false">
</applet>

ale spróbuj najpierw zamiast tego dać tam -Dsun.java2d.opengl=true może to wina directx, że się tak psuje

Ponieważ mój projekt to nie aplet, tylko samodzielna aplikacja java, proponowane przez Ciebie ustawienie ustawiłem we właściwościach, tak, jak na załączonym screenie.

Sprawdziłem obie możliwości

-Dsun.java2d.opengl=false ==> błędy, jak były, tak są

-Dsun.java2d.opengl=true ==> brak jakichkolwiek błędów

Kerai napisał(a)

poza tym, upewnij się, że masz zainstalowane sterowniki do karty graficznej od wydawcy, a nie te od microsoftu...

Tak, są oryginalne sterowniki z płyty dołączonej do grafiki.

Kerai napisał(a)

Teraz mały test...

Sprawdź tutaj czy zostają takie artefakty:
http://dev.keraj.net/javaballs/java-volatile.html - tylko zaznacz "slowdown"

jeśli zostają, to sprawdź to - korzysta z opengl zamiast z dx
http://dev.keraj.net/javaballs/java-volatile-opengl.html - też zaznacz slowdown

Na koniec sprawdź jak tutaj:
http://dev.keraj.net/javaballs/java-volatile-noaccel.html

i powiedz jak wyszło wszędzie.

W żadnej wersji nie ma artefaktów

0

No, to sprawa rozwiązana, Java u Ciebie ma problemy z DirectX'em... cholera wie dlaczego.
Czy to błąd w Javie? Może, chociaż wszędzie indziej działa...
Może to Twój błąd? inny aplet, który pokazałeś, zostawia artefakty... ale mój nie. (chociaż ja nie korzystam z BufferedImage) może łączysz komponenty swinga z komponentami awt?
Może to błąd DirectX? na tyle na ile miałem do czynienia z dx, to stawiałbym, że to wina dx... lub sterowników

Tak czy siak masz rozwiązanie...
Możesz kazać Javie korzystać z OpenGL (w apletach może się to kłócić z managerem okien, w stand-alone aplikacji jest okej)
Możesz kazać Javie nie korzystać z przyspieszenia sprzętowego w ogóle:
-Dsun.java2d.noddraw=true
taką opcją, to najlepiej działa w apletach, jeśli dx sprawia problemy.

0

Testowałem parametr -Dsun.java2d.translaccel i zarówno dla false, jak i dla true sa błędy.

Testowałem inny program, w którym również jest wyświetlanie obrazków, przy czym wyswietlany obraz zmienia się przy przeciąganiu myszką, więc wszystkie problemy od razu wyłażą na wierzch objawiając błyskaniem niepożądanych fragmentów.

Po uruchomieniu z parametrem "-Dsun.java2d.opengl=true" lub "-Dsun.java2d.noddraw=true" (jeden z nich) działa idealnie, nic nie błyska, nie ma żadnych problemów.

Nie podkręcałem karty graficznej, w żadnej grze ani programie korzystającym z DirectX, a nie napisanym w Java nie mam żadnych błędów.

W załączonym screenie są niby właściwości projektu i tam ustawiam parametry, to jednak jest mały problem.
Jak uruchomię z NetBreans, to parametry działają i mam oczekiwany rezultad.
Natomiast, jak zrobię "clean and build" i uruchomię plik JAR z katalogu "dist" to nie widzi tych parametrów, oczywiście uruchomienie z linii poleceń z parametrami daje oczekiwany rezultat.

Jak ustawić projekt w NetBeans, żeby dwukrotne kliknięcie pliku Jar powodowało przyjęcie określonych wartości, żeby nie trzeba było ich podawać w linii poleceń? Ewentualnie, jak zmodyfikować plik Jar po kompilacji?

0

żeby dwukrotne kliknięcie pliku Jar powodowało przyjęcie określonych wartości, żeby nie trzeba było ich podawać w linii poleceń

Nie da się...

w takich przypadkach dodaje się własny skrypt wsadowy lub program rozruchowy...

http://winrun4j.sourceforge.net/ - tu jest dobry i prosty lanczer...

0
andrzejlisek napisał(a)

Tak, są oryginalne sterowniki z płyty dołączonej do grafiki.

Pierwsza zasada pracy w Windows:
"Sterowniki z płyty dołączonej do karty graficznej są zawsze przestarzałe."
W praktyce są niewiele więcej warte od sterowników certyfikowanych przez MS i oferowanych przez Windows Update. Czyli zazwyczaj są to kiepskie sterowniki jeżeli karta ma więcej niż rok. Pamiętaj, że kolejne edycje Javy są testowane zawsze z najnowszymi sterownikami producenta w momencie wypuszczania nowej Javy. Nigdy z przestarzałymi sterownikami z płyt lub pozbawionych akceleracji sprzętowej sterowników z zasobów Microsoftu (np. do wersji dla Visty i DirectX 10 firma ta w ogóle olewała kwestię akceleracji sprzętowej, szczególnie tej 3D, której Windows XP w ogóle nie używał).

Z Twoich wypowiedzi wychodzi mi, że Twoja aplikacja jest w jakimś miejscu źle napisana. Nie na tyle źle, żeby wyszło to przy poprzednich wersjach javy i bez akceleracji, ale na tyle źle, że założenia projektantów nowszych wersji JVM nie są dla Twojej aplikacji spełnione. Często może chodzić o złą kolejność dwóch instrukcji graficznych AWT lub czegoś korzystającego z AWT.

Jeżeli aplet Keraia chodzi poprawnie z akceleracją i bez, a Twoja aplikacja tylko bez, to jedyny wniosek może być taki, że albo w nowszej Javie jest błąd, albo jest on w Twoim kodzie. Obstawiam więc raczej Twój kod - jeżeli w wersji Javy, którą używasz nie ma tego problemu na liście "known issues".

Na Twoim miejscu sprawdziłbym więc na jakiej ostatniej wersji JVM program chodzi dobrze, a potem poczytał szczegółową listę zmian między tą, a kolejną wersją, w której Twój program przestaje dobrze w Windows działać. Wiedząc co się zmieniło będzie łatwiej namierzyć słabe miejsce w swoim kodzie.

0

Załączem jeden z prostych, niedokończonych projektów NetBeans, w którym również występuje problem z wyświetlaniem.

AppCore - główne jądro programu, w nim jest generowany obraz
http://pastebin.pl/56656

MainForm - fłówny i jedyny formularz interfejsu, na nim jest wyświetlany obraz
http://pastebin.pl/56657

PictureObject - obiekt odpowiadający za przetwarzanie obrazu, nie ma znaczenia w rozważanym problemie
http://pastebin.pl/56658

ScreenMerge - plik uruchamiany przy starcie programu
http://pastebin.pl/56660

Ja nic szczególnego odnośnie Swinga i AWT nie pisałem, cały kod bezpośrednio związany z formularzem jest generowany przez NetBeans.

Czy widzisz w nim coś niepokojącego lub nieprawidłowego?

0

U mnie się dobrze wyświetla... ale kodowi się nie przyglądałem za bardzo... czemu nazywasz wszystko z dużej litery? to nie pasuje.

Skoro problem występuje tylko pod directx i tylko u Ciebie... to może powiedz jaki to system, jaka wersja directX, jaka karta graficzna.

0
Kerai napisał(a)

U mnie się dobrze wyświetla... ale kodowi się nie przyglądałem za bardzo... czemu nazywasz wszystko z dużej litery? to nie pasuje.

Równolegle posługuję się C# i Javą (najpierw poznałem C#, później Javę), w obu przyzwyczaiłem się do nazywania zmiennych i metod z wielkiej litery.

Kerai napisał(a)

Skoro problem występuje tylko pod directx i tylko u Ciebie... to może powiedz jaki to system, jaka wersja directX, jaka karta graficzna.

Sprawdzałem na innym komputerze (laptop Dell, Windows 7 Pro) i tam nie stwierdziłem żadnych błędów.

U mnie:
System: Windows XP Pro + SP2
DirectX: wersja 9.0C
Grafika: NVidia GEForce GTS 250
Sterownik do grafiki: Wersja 6.14.11.9038 z dnia 2009-07-14

0

Problem rozwiązany!

Zainstalowałem sterownik grafiki 32bit w wersji 6.14.12.9573 z dnia 2012-02-09 i nie widzę żadnych błędów z działaniem.

Czyli była wada w sterowniku karty graficznej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1