2012-03-08 14 views
6

Podczas śledzenia poważnych problemów z pamięcią w mojej aplikacji, sprawdziłem kilka zrzutów sterty z mojej aplikacji, a przez większość czasu mam OGROMNĄ bitmapę, którą daję nie wiem.Jak faktycznie wyświetlić bitmapę pobraną ze zrzutu sterty Androida?

Zajmuje 9,4 MB lub 9 830,400 bajtów, a właściwie obraz 1280 x 1920 przy 4 bajtach na piksel.

Sprawdziłem Eclipse MAT, to jest rzeczywiście bajt [9830400], który ma jeden przychodzący numer referencyjny, który jest android.graphics.Bitmap.

Chciałbym zrzucić to do pliku i spróbować go zobaczyć. Nie mogę zrozumieć, skąd się bierze. Mój największy obraz we wszystkich moich rysunkach to 640x960 png, który zajmuje mniej niż 3 MB.

Próbowałem użyć Eclipse do "kopiowania wartości do pliku", ale myślę, że po prostu drukuje bufor do pliku, i nie znam żadnego oprogramowania obrazującego, które może odczytać strumień bajtów i wyświetlić go jako 4 bajty na piksel obrazu.

Każdy pomysł?

Oto, co starałem: zrzucić tablicę bajtów do pliku, wciśnij go do/sdcard/img i załadować działalność tak:

@Override 
public void onCreate(final Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    try { 
     final File inputFile = new File("/sdcard/img"); 
     final FileInputStream isr = new FileInputStream(inputFile); 
     final Bitmap bmp = BitmapFactory.decodeStream(isr); 
     ImageView iv = new ImageView(this); 
     iv.setImageBitmap(bmp); 
     setContentView(iv); 
     Log.d("ImageTest", "Image was inflated"); 
    } catch (final FileNotFoundException e) { 
     Log.d("ImageTest", "Image was not inflated"); 
    } 
} 

nie widzę nic.

Czy wiesz, jak jest zakodowany obraz? Powiedzmy, że jest przechowywany w byte[] buffer. buffer[0] jest czerwony, buffer[1] jest zielony itp.?

+0

Czy to nie jest po prostu rodzimy cache renderowania? Czy używasz akceleracji sprzętowej? – Peterdk

+0

Tak, mam przyspieszenie HW. Ale to nie wyjaśnia, dlaczego moja bitmapa została zwiększona o 200% i dlaczego ta ogromna bitmapa jest przydzielana w stercie, IMHO. –

+0

Czy miałeś szczęście, aby dowiedzieć się, jaki to był obraz? Ja też mam taki nieuczciwy obraz, który zajmuje 1,1 MB i wydaje się pochodzić z fabrycznie załadowanych zasobów Androida. Kiedy patrzę na podgląd bufora bajtów za pomocą GIMP, widzę niebieski gradient radialny o rozmiarze 1044x270. – c05mic

Odpowiedz

2

OK - Po dość nieudanych próbach, w końcu udało mi się coś z tej tablicy bajtów. Napisałem ten prosty program C, aby przekonwertować tablicę bajtów na plik bitmapy Windows. Zrzucam kod na wypadek, gdyby ktoś był zainteresowany.
I skompilowałem to przeciwko VisualC 6.0 i gcc 3.4.4, powinien działać na każdym systemie operacyjnym (testowane na Windows, Linux i MacOS X).

#include <stdio.h> 
#include <math.h> 
#include <string.h> 
#include <stdlib.h> 

/* Types */ 
typedef unsigned char byte; 
typedef unsigned short uint16_t; 
typedef unsigned int uint32_t; 
typedef int int32_t; 

/* Constants */ 
#define RMASK 0x00ff0000 
#define GMASK 0x0000ff00 
#define BMASK 0x000000ff 
#define AMASK 0xff000000 

/* Structures */ 
struct bmpfile_magic { 
    unsigned char magic[2]; 
}; 

struct bmpfile_header { 
    uint32_t filesz; 
    uint16_t creator1; 
    uint16_t creator2; 
    uint32_t bmp_offset; 
}; 

struct bmpfile_dibheader { 
    uint32_t header_sz; 
    uint32_t width; 
    uint32_t height; 
    uint16_t nplanes; 
    uint16_t bitspp; 
    uint32_t compress_type; 
    uint32_t bmp_bytesz; 
    int32_t hres; 
    int32_t vres; 
    uint32_t ncolors; 
    uint32_t nimpcolors; 

    uint32_t rmask, gmask, bmask, amask; 
    uint32_t colorspace_type; 
    byte colorspace[0x24]; 
    uint32_t rgamma, ggamma, bgamma; 
}; 

/* Displays usage info and exits */ 
void usage(char *cmd) { 
    printf("Usage:\t%s <img_src> <img_dest.bmp> <width> <height>\n" 
     "\timg_src:\timage byte buffer obtained from Eclipse MAT, using 'copy > save value to file' while selecting the byte[] buffer corresponding to an android.graphics.Bitmap\n" 
     "\timg_dest:\tpath to target *.bmp file\n" 
     "\twidth:\t\tpicture width, obtained in Eclipse MAT, selecting the android.graphics.Bitmap object and seeing the object member values\n" 
     "\theight:\t\tpicture height\n\n", cmd); 
    exit(1); 
} 

/* C entry point */ 
int main(int argc, char **argv) { 
    FILE *in, *out; 
    char *file_in, *file_out; 
    int w, h, W, H; 
    byte r, g, b, a, *image; 
    struct bmpfile_magic magic; 
    struct bmpfile_header header; 
    struct bmpfile_dibheader dibheader; 

    /* Parse command line */ 
    if (argc < 5) { 
     usage(argv[0]); 
    } 
    file_in = argv[1]; 
    file_out = argv[2]; 
    W = atoi(argv[3]); 
    H = atoi(argv[4]); 
    in = fopen(file_in, "rb"); 
    out = fopen(file_out, "wb"); 

    /* Check parameters */ 
    if (in == NULL || out == NULL || W == 0 || H == 0) { 
     usage(argv[0]); 
    } 

    /* Init BMP headers */ 
    magic.magic[0] = 'B'; 
    magic.magic[1] = 'M'; 

    header.filesz = W * H * 4 + sizeof(magic) + sizeof(header) + sizeof(dibheader); 
    header.creator1 = 0; 
    header.creator2 = 0; 
    header.bmp_offset = sizeof(magic) + sizeof(header) + sizeof(dibheader); 

    dibheader.header_sz = sizeof(dibheader); 
    dibheader.width = W; 
    dibheader.height = H; 
    dibheader.nplanes = 1; 
    dibheader.bitspp = 32; 
    dibheader.compress_type = 3; 
    dibheader.bmp_bytesz = W * H * 4; 
    dibheader.hres = 2835; 
    dibheader.vres = 2835; 
    dibheader.ncolors = 0; 
    dibheader.nimpcolors = 0; 
    dibheader.rmask = RMASK; 
    dibheader.gmask = BMASK; 
    dibheader.bmask = GMASK; 
    dibheader.amask = AMASK; 
    dibheader.colorspace_type = 0x57696e20; 
    memset(&dibheader.colorspace, 0, sizeof(dibheader.colorspace)); 
    dibheader.rgamma = dibheader.bgamma = dibheader.ggamma = 0; 

    /* Read picture data */ 
    image = (byte*) malloc(4*W*H); 
    if (image == NULL) { 
     printf("Could not allocate a %d-byte buffer.\n", 4*W*H); 
     exit(1); 
    } 
    fread(image, 4*W*H, sizeof(byte), in); 
    fclose(in); 

    /* Write header */ 
    fwrite(&magic, sizeof(magic), 1, out); 
    fwrite(&header, sizeof(header), 1, out); 
    fwrite(&dibheader, sizeof(dibheader), 1, out); 

    /* Convert the byte array to BMP format */ 
    for (h = H-1; h >= 0; h--) { 
     for (w = 0; w < W; w++) { 
      r = *(image + w*4 + 4 * W * h); 
      b = *(image + w*4 + 4 * W * h + 1); 
      g = *(image + w*4 + 4 * W * h + 2); 
      a = *(image + w*4 + 4 * W * h + 3); 

      fwrite(&b, 1, 1, out); 
      fwrite(&g, 1, 1, out); 
      fwrite(&r, 1, 1, out); 
      fwrite(&a, 1, 1, out); 
     } 
    } 

    free(image); 
    fclose(out); 
} 

Dzięki temu narzędziu udało mi się rozpoznać zdjęcie użyte do wygenerowania tej mapy bitowej 1280x1920.

+0

Zastanawiam się, czy zapisałeś zawartość tablicy bajtów w jakiś specjalny sposób na Mac OSX? Udało mi się skompilować twój kod i uruchomić go w stosunku do zawartości pliku, który zapisałem z MAT, ale wynikowy BMP nie może być odczytany przez przeglądarkę podglądu podglądu komputera Mac (zakładając, że coś jest nie tak z plikiem źródłowym, ponieważ kod nie powoduje błędu) –

+0

Nie pamiętam dokładnie, po prostu użyłem "wartości kopiowania do pliku" Eclipse z MAT i uruchomiłem program C przeciwko temu plikowi. –

0

Po prostu wprowadź dane wejściowe do obrazu i przekonwertuj je na obiekt bitmapowy, używając strumienia danych/strumienia danych. Dodaj również dzienniki, aby zobaczyć dane dla każdego używanego obrazu.

+0

Próbowałem, ale nic nie wyświetla ... Zobacz moją edycję. –

0

Można włączyć połączenie USB i skopiować plik na inny komputer z większą ilością narzędzi do zbadania.

Niektóre urządzenia można skonfigurować tak, aby zrzuciły bieżący ekran do systemu plików po naciśnięciu przycisku start. Może ci się to przydarza.

+0

Dziękuję bardzo, ale nie widzę, w jaki sposób jest to związane z moim problemem oraz w jaki sposób pomogło mi przekonwertować tablicę bajtów pobraną ze zrzutu sterty na format obrazu widocznego. –

0

Okazało się, że począwszy od najnowszej wersji Androida Studio (2.2.2 dzień pisanie), można bezpośrednio wyświetlić plik bitmapy:

  1. Otwórz zakładkę "Android Monitor" (w lewym dolnym rogu), a następnie kartę Pamięć.
  2. Naciśnij „Dump Java heap” przycisk

  3. Wybierz „Bitmap” Class Nazwa bieżącego snapshot wybierz każdej instancji bitmapy i zobaczyć co dokładnie obraz zużywają więcej pamięci niż oczekiwano. (ekrany 4 i 5)

  4. Wybierz nazwę Bitmap klasy ...

enter image description here

  1. Wybierz każdej instancji bitmapy

enter image description here

i kliknij prawym przyciskiem myszy Wybierz View Bitmap

enter image description here