Autor Wątek: Wczytywanie obraz do Tablicy byte[] //[J2ME]  (Przeczytany 2304 razy)

Offline Adam B

  • Użytkownik

# Czerwiec 16, 2009, 18:56:54
Witam,
Chciałem upiększyć mój jar i w związku z tym zabrałem się za pakowanie plików PNG do jednego binarnego (to teoretycznie może też przyśpieszyć wczytywanie, jednak nie o to mi chodzi). Pokombinowałem i wymyśliłem coś takiego (kod jest eksperymentalny więc i brzydki):

int x=0;
int y=0;

// ŻEBY ZOBACZYć ILE WCZYTUJE ZNAKÓW
try{
    InputStreamReader in = new InputStreamReader(getClass().getResourceAsStream("/x.png"));
            while ((in.read())!=-1) {
                x++;
            }
}catch(IOException ioe){
    System.out.println("ale gdzie plik?");
    ioe.printStackTrace();
}

// TABLICA Z BYTAMI :)
byte tab[] = new byte[x]; // Tablica dokładnie jakiej potrzeba ;)

try{
    InputStreamReader in = new InputStreamReader(getClass().getResourceAsStream("/x.png"));
            int cos=0;
            while ((cos = in.read())!=-1) {
                tab[y]=(byte)cos; // Wpisanie do tablicy kolorku
                y++;
            }
}catch(IOException ioe){
    System.out.println("ale gdzie plik?");
    ioe.printStackTrace();
}
       
        Image img;
        img = Image.createImage(tab, 0, x);  // Tutaj pojawia się błąd związany ze złym argumentem - dwoje się i troje i nic nie umiem wymyślić :/
        g.drawImage(img, 50, 50, 0);

Teoretycznie wszytko jest ok ale emulator mi się burzy !
Pozdrawiam :)

Offline Mr. Spam

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

Offline grrr

  • Użytkownik

# Czerwiec 17, 2009, 09:57:08
Wiesz, jak zawsze... Zdania typu: "tutaj pojawia się błąd związany ze złym argumentem" i "emulator mi się burzy" prawdopodobnie nic nikomu nie powiedzą, więc i ciężko będzie pomóc.

Offline Adam B

  • Użytkownik

# Czerwiec 17, 2009, 10:11:39
Wiesz, jak zawsze... Zdania typu: "tutaj pojawia się błąd związany ze złym argumentem" i "emulator mi się burzy" prawdopodobnie nic nikomu nie powiedzą, więc i ciężko będzie pomóc.

Nie z kodu wynika wszystko co i jak. Jak ktoś kiedyś robił wczytywanie png w podobny sposób to wie na czym polega problem.

Wymaga jest tablica typu byte (do funkcji tworzącej Image), a problem polega na tym ze InsputStreamReader.read zwraca int - nie ma innej metody tej klasy żeby zwracała co innego i to jest chyba jedyna opcja odczytu zawartości JARa. Natomiast pierwsza liczba odczytana z pliku PNG to 8200 czy jakoś tak - także znacznie wykracza po za zakres byte:/ Dlatego dane wejściowe są złe i nie mam pojęcia jak rozwiązać ten problem. Na pewno da się to jakoś zrobić bo w wielu gra widziałem, że był ogólny plik binarny zawierający wszystkie grafiki z gry+miejsce ich położenia + grafike czcionki + teksty...

//EDIT: pobawie się może dataInputStream - może to coś pomoże..
« Ostatnia zmiana: Czerwiec 17, 2009, 10:22:11 wysłana przez Adam B »

Offline MadMax

  • Użytkownik
    • http://mobiledeveloper.cba.pl/

# Czerwiec 17, 2009, 10:34:00
Witam

to nie lepiej pakowac do binarki szerokosc, wysokosc kazdego obrazka, indeksy kolorow, oraz oddzielna wspolna dla obrazkow palete jako dodatkowy plik, lub na poczatku binarki ?.

Nie wiem czy programisci wrzucaja do binarnego pliku obrazki w formacie png - to wydaje mi sie ze tak powiem malo optymalne.

btw. jesli chcesz wczytac np. liczbe typu int, to najprosciej bajty przerzucic:

int len = (is.read() & 0xFF) << 24;
 len |= (is.read() & 0xFF) << 16;
 len |= (is.read() & 0xFF) << 8;
 len |= (is.read() & 0xFF);

Jesli masz np. w danej pozycji pliku naglowek o rozmiarze obrazka, to (klasyczna) bezpieczna i szybsza wersja funkcji wczytujacej wyglada tak :

    public final byte[] loadFile(String f, int apos) {
        byte buffer[], tmp[];

        int len, p = 0;

        try {
            InputStream is = _class.getResourceAsStream(f);
            if (is == null) {
                throw new Exception("File Does Not Exist");
            }

            if (apos > 0) {
                is.skip(apos);
            }

            len = (is.read() & 0xFF) << 24;
            len |= (is.read() & 0xFF) << 16;
            len |= (is.read() & 0xFF) << 8;
            len |= (is.read() & 0xFF);
            buffer = new byte[len];
            tmp = new byte[len];

            while ((len = is.read(tmp, 0, tmp.length)) > 0) {
                System.arraycopy(tmp, 0, buffer, p, len);
                p += len;
                if (p >= buffer.length) {
                    break;
                }
            }
            tmp = null;
            is.close();
            is = null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            buffer = null;
            tmp = null;
        }
        return buffer;
    }

mozna to zoptymalizowac, ale nevermind :).

Pozdrawiam,
madmax

Offline grrr

  • Użytkownik

# Czerwiec 17, 2009, 10:48:51
InputStrem udostępnia metodę read(byte[]), wystarczy połączyć to z ByteArrayOutputStream - wtedy nie musisz wiedzieć, jaki długi jest plik, czytasz z inputStream i piszesz to ByteArrayOutputStream (póki inputStream wciąż coś zwraca), a potem robisz toByteArray()  - piszę z głowy. Ani nie musisz modyfikować pliku, ani wczytywać go dwukrotnie.

Offline Adam B

  • Użytkownik

# Czerwiec 17, 2009, 10:58:29
Żeby z wysokości, szerokości, palety i indeksu odczytać obrazki trzeba użyć CreateRGBImagen pomysł dobry i łatwy ;) Tylko jedynym problem jest stworzenie narzędzia, które będzie taki plik tworzyło ale to też jest kilka godz. roboty. Mi natomiast chodziło o coś troszke innego:

Oto rozwiązanie tego co chciałem osiągnąć.
int x=155;  // WIEM ZE OBRAZEK MA 155 BAJTÓW
byte tab[] = new byte[x];

try{
    DataInputStream in = new DataInputStream(getClass().getResourceAsStream("/x.png"));
    while ((in.read(tab, 0, x))!=-1) {}
}catch(IOException ioe){}

        Image img;
        img = Image.createImage(tab, 0, x); //  elegancko się tworzy obrazek.
        g.drawImage(img, 50, 50, 0);


Podejrzewam, że tworząc swój format to i tak skorzystam z createRGBImage. Ze względu na większą prostote wykonania.