Zastanawiam się jak można obrócić obrazek rastrowy.
Mam JPanel na którym wyświetlony w pewnym miejscu jest obrazek rastrowy.
Jeśli chodzi o jego translację, czy skalowanie, to raczej dam radę. Żeby dostać się do każdego piksela wystarczy dwa razy użyć pętli for od jednego wierzchołka do drugiego.
Ale co z obrotem? Wtedy obrazek już nie jest prostokątem, tylko równoległobokiem i nie da się tak łatwo przejść po jego wszystkich pikselach.
A może po prostu trzeba jako obrazek traktować cały ekran malowania i tło tez od nowa malować? Choć to wydaje mi się trochę bez sensu :P
Mam nadzieje, że rozumiecie o co mi chodzi. Jak nie, to napiszcie co słabo wytłuamczyłem, to postaram się opisać to konkretniej :P
Z góry dzięki za pomoc.
Żeby było jaśniej :P
Mam zrobic program, który wczytany obrazek rastrowy może przeskalować, obrócić i przesunąć oraz wykonać dowolne złożenie tych operacji.
Do skalowania mam uzyć interpolacji dwuliniowej, więc do tych operacji muszę dla każdego poksela w obrazie wynikowym wyznaczyć odpowiadający mu piksel w obrazie startowym - przy użyciu macierzy odwrotnej do tej, która przekształcamy obraz.
Pierwsze pytanie: żeby wiedzieć gdzie znajduje się wynikowy obraz, najpierw musimy przemnożyć wierzchołki obrazu startowego przez macierz operacji, aby wiedzieć gdzie rozciąga się obraz końcowy?
Drugie pytanie: jeśli obraz wynikowy nie jest prostopadły/równoległy do osi, tylko przekrzywiony, to jak można przejść po ejgo wszystkich pikselach? Bo dwie pętle for w tym wypadku raczej odpadają...
http://download.oracle.com/javase/tutorial/2d/images/index.html
Wszystko jest już zaimplementowane. Masz nawet dostęp do dowolnych przekształceń afinicznych.
Poza tym jest BufferedImage.getWritableTile().setPixels(...)
Wszystkie macierze i przekształcenia muszę miec napisane samodzielnie.
Podstawy klasy BufferedImage znam ;)
Weźmy taki przykład, że dostaję jakąś macierz - nie wiem co to za przekształcenie. I co po kolei robię z obrazkiem startowym?
- Najpierw wyliczam gdzie znajduje się obraz wynikowy? Czyli przez tą macierz mnożę wierzchołki obrazka. Tak?
- Wiem gdzie jest obraz wynikowy. Muszę go teraz stworzyć. Dla każdego piksela z tej przestrzeni muszę znaleźć odpowiadający mu piksel z obrazu startowego. Wykorzystuję tu polaryzację dwuliniową. Problem w tym jak przejść po wszystkich pikselach obrazu wynikowego (czyli od wierzchołka A do wierzchołka B i w tym od wierzchołka A do wierzchołka C, jeśli obrazek jest prostokątem ABCD), żeby ustawić im odpowiednie kolory? Zwłaszcza jeśli obraz jest przekrzywiony, czyli przejście dwoma pętlami for odpada.
Jak już napisałem wyżej - znam metody pobierania piksela, ustawiania koloru piksela itp.
Z góry dzięki za pomoc.
"polaryzację dwuliniową"
Chyba interpolację.
Wydaje mi się że obrazek jest zawsze prostokątem. Przy rysowaniu robisz te dwie pętle i rysujesz po kolejnym prostokątnym obrazku z uwzględnieniem transformacji.
W przekształceniu afinicznym mamy współrzędne jednorodne uwzględniające skalowania, obroty, rotacje itp, a więc po prostu pozycję każdego piksela wejściowego mnożymy przez macierz i dostajemy miejsce gdzie go powinniśmy namalować.
Nikt ci też nie broni czytać źródeł JDK. Ja pewnie bym tak zrobił.
donkey7 napisał(a)
"polaryzację dwuliniową"
Chyba interpolację.
Oczywiście, moja pomyłka. Jestem świezakiem w tym temacie i stąd ta pomyłka :P
Wydaje mi się że obrazek jest zawsze prostokątem. Przy rysowaniu robisz te dwie pętle i rysujesz po kolejnym prostokątnym obrazku z uwzględnieniem transformacji.
W przekształceniu afinicznym mamy współrzędne jednorodne uwzględniające skalowania, obroty, rotacje itp, a więc po prostu pozycję każdego piksela wejściowego mnożymy przez macierz i dostajemy miejsce gdzie go powinniśmy namalować.
No tak, ale jak obrazek powiększamy to musimy dla każdego piksela wyjściowego, szukać piksel wejściowy. Czyli musimy iść po każdym pikselu obrazu wyjściowego. A co jeśli był on jednocześnie obrócony?
Obrazki są tylko prostokątne.
Jeśli zrobiłeś jakąś transformację za pomocą macierzy to możesz ją odwrócić (ale zwykle z utratą części informacji) poprzez znalezienie odwrotności dla tamtej macierzy.
Jaki ty masz problem z tymi obrotami? Obrócony obrazek jest dalej prostokątny, niektóre piksele mogą być obcięte, inne wypełnione domyślną wartością, choćbyś nie wiem co robił nie zrobisz obrazka który nie jest prostokątny.
PS:
Jeśli chcesz robić milion transformacji w ciągu to nie transformuj cały czas na bieżąco, tylko działaj na macierzy przekształceń i dopiero na końcu dokonaj przekształcenia.
Czyli po obrocie mam mieć obrazek prostokątny, który ma w sobie obrócony obrazek wejściowy, a te zostające trójkąty mam wypełnić tłem?
I to jest poprawne rozwiązanie?
Bo jeśli tak, to problem mam juz rozwiązany :P
Jeśli chodzi o PS, to wiem.
Najpierw mnożę te wszystkie macierze, a potem dopiero przekształcam obrazek przez jedną macierz :P
No ja na razie nie znam sposobu żeby zrobić nieprostokątny obrazek. Wypełniaj tłem, albo co najwyżej ustaw przezroczystość w pustych miejscach. W każdym programie czy systemie obrazki są kwadratowe, nie widzę powodu żeby w Javie kombinować inaczej.
W takim razie bardzo dziękuję za pomoc :) Myślę, że z sama implementacją tych pomysłów już sobie poradzę :)
Po obrocie obrazka jego krawędzie nie są gładkie. Są takie postrzępione.
Tutaj przykład: http://www.fotosik.pl/pokaz_obrazek/93f03afad599bdb5.html
Da się z tym coś zrobić? Czy po prostu tak juz zostawić?