Autor Wątek: [J2ME] / Wczytanie przezroczystego zdjęcia i powiązanie go z Graphics  (Przeczytany 5460 razy)

Offline Adam B

  • Użytkownik

# Marzec 10, 2009, 23:37:07
Witam.

Mam problem następującej postaci: Chce utworzyć Image img, w taki sposób by nowopowstały obraz miał przeźroczyste tło. I tutaj mam problem, ponieważ:

Image img = Image.createImage(x,y);
Graphics g = img.getGraphics();
// po takim wykonaniu tło jest automatycznie białe, a ja chce przeżroczyste

Próbowałem tez tak:
Image img = Image.createImage("/przezroczysty.png");
Graphics g = img.getGraphics(); // <- jednak w takim przypadku po uruchomieniu aplikacji wyskakuje blad :(

Nie wiem jak to rozwiązać - a chce mieć przeźroczysty obiekt, po którym będe mogł malować i nanosić na niego inne obrazy..

Pozdrawiam Adam :)

//EDIT: Bardzo też by mi zależało na tym żeby dalo to sie wlączyć na MidP1
« Ostatnia zmiana: Marzec 10, 2009, 23:40:36 wysłana przez Adam B »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Troll

  • Użytkownik
    • Oficjalna strona gry Gizarma

# Marzec 10, 2009, 23:43:21
Ja to robie tak:

BufferedImage bufferedImage = new BufferedImage( width,height,BufferedImage.TYPE_4BYTE_ABGR_PRE );
Graphics gc=bufferedImage.createGraphics();

Offline Adam B

  • Użytkownik

# Marzec 10, 2009, 23:54:37
Ja to robie tak:

BufferedImage bufferedImage = new BufferedImage( width,height,BufferedImage.TYPE_4BYTE_ABGR_PRE );
Graphics gc=bufferedImage.createGraphics();

Niestety NetBeans 6.5 nawet mi nie rozpoznaje czegoś takiego jak BufferedImage :/

Offline Yarek

  • Użytkownik

# Marzec 11, 2009, 00:19:44
Image AddAlpha(Image img, int keyColor)
   {
    int size = img.getHeight()*img.getWidth();
    int tab[] = new int[size];
    img.getRGB(tab, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());
   
    for(int i=0; i<size; i++)
    if(tab[i]==keyColor)
    tab[i]&=0x00FFFFFF;
   
    return Image.createRGBImage(tab, img.getWidth(), img.getHeight(), true) ;
   }

Offline Solgar

  • Użytkownik

# Marzec 11, 2009, 10:01:05
Mutualbe image tworzony jest tylko przez statyczna metode Image.createImage(int,int), a tylko z mutuable image mozna otrzymac jego Graphics. Tak tworzony obrazek ma kazdy piksel bialy (zgodnie zreszta ze specyfikacja). Nie da sie dodac przezroczystosci do obrazka mutuable.
Kod: (java) [Zaznacz]
Image AddAlpha(Image img, int keyColor)
{
    int size = img.getHeight()*img.getWidth();
    int tab[] = new int[size];
    img.getRGB(tab, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());

    for(int i=0; i<size; i++)
        if(tab[i]==keyColor)
            tab[i]&=0x00FFFFFF;

    return Image.createRGBImage(tab, img.getWidth(), img.getHeight(), true) ;
}
To nie jest do konca rozwiazanie, ktore by odpowiadalo wymaganiom Adama. Zwracany Image jest typu immutuable, czyli nie mozna pobrac jego graphics i rysowac na nim. Poza tym nie bylo by to mozliwe pod MIDP 1.0. Musisz wymyslec jakis inny sposob renderowania i odswiezania ekranu. :)

// edit: nie ma czegos takiego jak BufferedImage w MIDP
« Ostatnia zmiana: Marzec 11, 2009, 10:03:42 wysłana przez Solgar »

Offline Adam B

  • Użytkownik

# Marzec 11, 2009, 10:36:44
Mhh zastanawiam sie jeszcze nad inna opcja:

1. Tworze Graphics tlo; <- Graphics domyslnie jest pusty (przezroczysty) ?
2. tlo.drawImage(img, x, y); <- Img jest wczytane z pliku wiec moze byc przezroczyste ;)
3. Rysuje sobie po "tlo" ile chce ;)
4. Kopiuje z "tlo" w odpowiednie miejsce "g", a "g" wyswietlam ;) (ale nie wiem jak to zrobic)

Nie wiem czy taka metoda ma sens i pozwoli rozwiazac moj problem ;)

//EDIT: Jest możliwe stworzenie Image.createImage(x,y) i ustawienie kanalu alpha ale dla MidP1?
« Ostatnia zmiana: Marzec 11, 2009, 10:48:24 wysłana przez Adam B »

Offline Solgar

  • Użytkownik

# Marzec 11, 2009, 10:45:00
I leci null pointer exception ;).

Offline Adam B

  • Użytkownik

# Marzec 11, 2009, 11:08:03
I leci null pointer exception ;).

Czyli to jest złe rozwiązanie :( Zaczyna brakować mi pomysłów...

Offline hubo

  • Użytkownik

# Marzec 11, 2009, 11:18:33
Ale to co chcesz osiagnac ma pozniej do czegos posluzyc (np nieregularne ludziki na tle?)? Czy jest to sztuka dla sztuki, i chcesz miec poprostu przezroczysty obrazek? BO jak chcesz rysowac cos co ma tlo tak zeby tlo pominac mozesz np uzyc clippingu. Lata tego midpa nie uzywalem, ale chyba byla jakas funkcja setClip przy rysowaniu.

Offline Adam B

  • Użytkownik

# Marzec 11, 2009, 11:35:48
Ale to co chcesz osiagnac ma pozniej do czegos posluzyc (np nieregularne ludziki na tle?)? Czy jest to sztuka dla sztuki, i chcesz miec poprostu przezroczysty obrazek? BO jak chcesz rysowac cos co ma tlo tak zeby tlo pominac mozesz np uzyc clippingu. Lata tego midpa nie uzywalem, ale chyba byla jakas funkcja setClip przy rysowaniu.

setClip owszem ogranicza rysowany obszar ale tylko do kwadratu.
Złóżmy coś takigo:

Cytuj
Mam mapę (jest to obraz np 240x320) przedstawia ona ścieżkę w parku. Teraz na tej ścieżce chce narysować "dywan z liści" (jednak ma on być generowany losowo). W jarze mam 5 grafik różnych rodzajów wspomnianych liści. No to biorę sobie te liści rysuje sobie je w jednym obrazku i na koniec utworzony "dywan" rysuje na mapie.
A rysowanie każdego liścia oddzielnie strasznie wpłynęło by na wydajność :/ 

Np. może być taki przykład użycia tego co chce osiągnąć ;)

Offline hubo

  • Użytkownik

# Marzec 11, 2009, 12:05:14
setClip ogranicza kwadrat dlatego ksztalty trzeba na kilka kwadratow rysowac, nie znam innej techniki, ale ja uzywalem midp w czasach gdy pojawila sie motorola t720 ;).

[z przezroczystoscia]
Czy dywan lisci bedzie ciagle odrysowywany na mapie w calosci? Bo rozumiem ze masz zbuforowany rysunek z dywanem lisci (ktory musisz narysowac lisc po lisciu, skoro masz 5 rodzajow pojedynczych lisci), masz tez mape. Rysujesz jedno na drugim. Masz mape z liscmi. Teraz ktos tam lazi i zostawia slad na lisciach. Musisz odrysowac zniszczone fragmenty sciezki (dirty rectangle). To przeciez nie bedziesz rysowal calej sciezki, a tylko ten fragment zniszczony, czyli odrysujesz fragmencik rysunku "lisciastego" uzywajac setClip.

[bez przezroczystosci]
A teraz nie majac przezroczystosci. Mozesz narysowac liscie bezposrednio na mapie (kazdy lisc rysuje sie dluzej przez to ze fragmentami go rysujesz, i to cala roznica, bo przeceiz ten rysunek bazowy z dywanem lisci tez musiales zrobic), ale robisz to raz. Potem robisz kopie mapy, zeby na jej podstawie odrysowywac zniszczona sciezke. Zajmie troche wiecej pamieci, inicjalizuje sie wolniej - bo rysowanie wolniejsze, (mozna nie buforowac mapy, tylko trzeba by narysowac dwa dywany lisci - na mape i do bufora), z tym ze jezeli w calosci jest to rysowane jeden raz to da rade.

Wszystko kwesia jak sie ten dywan lisci mialby zmieniac, czy bedzie je wiatr rozwiewal ;).

Dobra tyle moich wywodow, poddaje sie ;).

Offline Adam B

  • Użytkownik

# Marzec 11, 2009, 12:19:36
Właśnie chce stworzyć taki rysunek z dywanem ;) I potem go rysować po ścieżce... I cały problem polega na tym jak stworzyć ten rysunek z dywanem? 

Offline Yarek

  • Użytkownik

# Marzec 11, 2009, 12:24:21
To może trzymać całą grafikę jako tablicę punktów byte[], napisać własną funkcje blitującą jedną grafikę na drugą i na końcu konwertować to co wyszło na Image'a po czym wrzucić na ekran??
Pewno z prędkością może być problem ale powinno działać.

Offline Adam B

  • Użytkownik

# Marzec 11, 2009, 14:58:33
To może trzymać całą grafikę jako tablicę punktów byte[], napisać własną funkcje blitującą jedną grafikę na drugą i na końcu konwertować to co wyszło na Image'a po czym wrzucić na ekran??
Pewno z prędkością może być problem ale powinno działać.

No tak ale gdybym co klatkę miał tworzyć w ten sposób obrazek to telefon by się spalił :P Wiec chyba jedynym rozwiązaniem jest MidP2 ;) I wcześniej podany algorytm:

Image AddAlpha(Image img, int keyColor)
{
    int size = img.getHeight()*img.getWidth();
    int tab[] = new int[size];
    img.getRGB(tab, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());
 
    for(int i=0; i<size; i++)
        if(tab[i]==keyColor)
            tab[i]&=0x00FFFFFF;
 
    return Image.createRGBImage(tab, img.getWidth(), img.getHeight(), true) ;
}

//EDIT: A wracając do tego co Yarek napisał:

To może trzymać całą grafikę jako tablicę punktów byte[], napisać własną funkcje blitującą jedną grafikę na drugą i na końcu konwertować to co wyszło na Image'a po czym wrzucić na ekran??
Pewno z prędkością może być problem ale powinno działać.

public static Image createImage(byte[] imageData, int imageOffset, int imageLength) // W takiej tablicy da się trzymać przeźroczyste pixele?
Jeżeli tak to problem wydaje sie częściowo rozwiązany - jednak cały czas pozostaje kwestia wpisania  obrazu do tablicy byte[]. (getRGB - jest ale w MidP2)
Jedyne co można zrobić to napisać własną klasę, która dekoduje PNG? 


« Ostatnia zmiana: Marzec 11, 2009, 15:56:30 wysłana przez Adam B »

Offline Yarek

  • Użytkownik

# Marzec 11, 2009, 16:09:15
Zajrzałem do dokumentacji MIDP1.0 i chyba createImage odpada ("The data must be in a self-identifying image file format supported by the implementation").
Chyba lepiej przesiądź się na MIDP2.0 jak możesz ;)