문제

내 앱의 심각한 메모리 문제를 추적하는 과정에서 내 앱의 여러 힙 덤프를 살펴보았는데 대부분의 경우 내가 알지 못하는 거대한 비트맵이 있습니다.

9.4MB, 즉 9,830,400바이트 또는 실제로는 픽셀당 4바이트의 1280x1920 이미지가 필요합니다.

Eclipse MAT를 확인해 보니 실제로는 바이트[9830400]이고, 하나의 수신 참조가 있습니다. android.graphics.Bitmap.

이 내용을 파일로 저장해서 확인해 보고 싶습니다.나는 그것이 어디서 오는지 이해할 수 없습니다.내 모든 드로어블 중 가장 큰 이미지는 640x960 PNG이며 크기는 3MB 미만입니다.

"값을 파일에 복사"하기 위해 Eclipse를 사용하려고 시도했지만 단순히 버퍼를 파일에 인쇄하는 것 뿐이라고 생각하고 바이트 스트림을 읽고 픽셀당 4바이트로 표시할 수 있는 이미지 소프트웨어를 모릅니다. 영상.

어떤 아이디어?

내가 시도한 것은 다음과 같습니다.바이트 배열을 파일로 덤프하고 /sdcard/img에 푸시한 후 다음과 같은 활동을 로드합니다.

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

나는 아무것도 보지 못했다.

이미지가 어떻게 인코딩되는지 알고 있나요?에 저장되어 있다고 하세요. byte[] buffer. buffer[0] 빨간색이고, buffer[1] 녹색인가요?

도움이 되었습니까?

해결책 2

확인 - 꽤 오래 실패한 후에는 마침내이 바이트 배열에서 뭔가를 얻었습니다.Byte Array를 Windows 비트 맵 파일로 변환하는이 간단한 C 프로그램을 썼습니다.누군가가 관심이있는 경우 코드를 삭제하고 있습니다.
VisualC 6.0 및 GCC 3.4.4에 대해이를 컴파일하므로 모든 OS에서 작동해야합니다 (Windows, Linux 및 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);
}
.

이 도구를 사용 하여이 1280x1920 비트 맵을 생성하는 데 사용 된 그림을 인식 할 수있었습니다.

다른 팁

여기를 쉽게 참조하십시오 : MAT (Eclipse 메모리 분석기) - 메모리 덤프에서 비트 맵을 보는 방법

tl; DR - 김프를 설치하고 원시 RGB 알파 로 이미지를로드하십시오.

최신 버전의 Android Studio(작성 당시 2.2.2)부터 비트맵 파일을 직접 볼 수 있다는 것을 알았습니다.

  1. 'Android 모니터' 탭(왼쪽 하단)을 연 다음 메모리 탭을 엽니다.
  2. 'Java 힙 덤프' 버튼을 누르세요.

  3. 현재 스냅샷에 대한 'Bitmap' 클래스 이름을 선택하고, 비트맵의 각 인스턴스를 선택한 다음 정확히 어떤 이미지가 예상보다 더 많은 메모리를 소비하는지 확인하세요.(화면 4와 5)

  4. 다음을 선택하세요. Bitmap 수업 이름…

enter image description here

  1. 비트맵의 각 인스턴스 선택

enter image description here

그리고 마우스 오른쪽 버튼을 클릭하고 선택하세요. View Bitmap

enter image description here

이미지를 이미지로 가져 와서 FileInput Stream / DataStream을 사용하여 비트 맵 객체로 변환합니다.또한 사용되는 각 이미지에 대한 데이터를 볼 수 있도록 로그를 추가하십시오.

USB 연결을 활성화하고 조사 할 수있는 더 많은 도구가있는 다른 컴퓨터로 파일을 복사 할 수 있습니다.

일부 장치는 시작 버튼을 누르면 현재 화면을 파일 시스템에 덤프하도록 구성 할 수 있습니다.어쩌면 이것은 당신에게 일어날 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top