Frage

Während ich schwerwiegende Speicherprobleme in meiner App nachverfolgte, habe ich mir mehrere Heap-Dumps meiner App angesehen und meistens habe ich eine RIESIGE Bitmap, von der ich nichts weiß.

Es benötigt 9,4 MB oder 9.830.400 Bytes oder tatsächlich ein 1280 x 1920 großes Bild mit 4 Bytes pro Pixel.

Ich habe in Eclipse MAT nachgesehen, es ist tatsächlich ein Byte[9830400], das eine eingehende Referenz hat, nämlich a android.graphics.Bitmap.

Ich möchte dies in eine Datei kopieren und versuchen, es anzuzeigen.Ich kann nicht verstehen, woher es kommt.Mein größtes Bild in all meinen Drawables ist ein 640x960-PNG-Bild, das weniger als 3 MB benötigt.

Ich habe versucht, Eclipse zum „Kopieren von Werten in eine Datei“ zu verwenden, aber ich denke, es druckt einfach den Puffer in die Datei, und ich kenne keine Bildsoftware, die einen Bytestrom lesen und als 4 Byte pro Pixel anzeigen kann Bild.

Irgendeine Idee?

Folgendes habe ich versucht:Speichern Sie das Byte-Array in einer Datei, verschieben Sie es nach /sdcard/img und laden Sie eine Aktivität wie diese:

@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");
    }
}

Ich habe nichts gesehen.

Wissen Sie, wie das Bild kodiert ist?Angenommen, es wird darin gespeichert byte[] buffer. buffer[0] ist rot, buffer[1] ist grün usw.?

War es hilfreich?

Lösung 2

OK – Nach einigen erfolglosen Versuchen habe ich endlich etwas aus diesem Byte-Array herausgeholt.Ich habe dieses einfache C-Programm geschrieben, um das Byte-Array in eine Windows-Bitmap-Datei zu konvertieren.Ich lasse den Code fallen, falls jemand Interesse hat.
Ich habe dies mit VisualC 6.0 und gcc 3.4.4 kompiliert, es sollte auf jedem Betriebssystem funktionieren (getestet unter Windows, Linux und 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);
}

Mit diesem Tool konnte ich das Bild erkennen, das zur Erstellung dieser 1280x1920-Bitmap verwendet wurde.

Andere Tipps

Eine einfachere Antwort finden Sie hier: MAT (Eclipse Memory Analyzer) – So zeigen Sie Bitmaps aus dem Speicherauszug an

TL;DR – Installieren Sie GIMP und laden Sie das Bild als rohes RGB-Alpha

Ich habe festgestellt, dass Sie ab der neuesten Version von Android Studio (2.2.2 zum Zeitpunkt des Schreibens) die Bitmap-Datei direkt anzeigen können:

  1. Öffnen Sie die Registerkarte „Android Monitor“ (unten links) und dann die Registerkarte „Speicher“.
  2. Klicken Sie auf die Schaltfläche „Java-Heap sichern“.

  3. Wählen Sie den Klassennamen „Bitmap“ für den aktuellen Schnappschuss, wählen Sie jede Bitmap-Instanz aus und sehen Sie, welches Bild genau mehr Speicher verbraucht als erwartet.(Bildschirme 4 und 5)

  4. Wählen Sie das Bitmap Klassenname…

enter image description here

  1. Wählen Sie jede Bitmap-Instanz aus

enter image description here

und mit der rechten Maustaste darauf klicken, auswählen View Bitmap

enter image description here

Nehmen Sie einfach die Eingabe in das Bild und konvertieren Sie es mithilfe des Dateieingabe-Streams/Datenstreams in ein Bitmap-Objekt.Fügen Sie außerdem Protokolle hinzu, um Daten für jedes verwendete Bild anzuzeigen.

Sie könnten eine USB-Verbindung aktivieren und die Datei auf einen anderen Computer kopieren, auf dem weitere Tools zur Untersuchung vorhanden sind.

Einige Geräte können so konfiguriert werden, dass sie den aktuellen Bildschirm beim Drücken der Starttaste in das Dateisystem übertragen.Vielleicht passiert dir das.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top