Eclipse Memory Analyzer并不提供从一个bitmap buffer直接观察图片内容的功能,下面的步骤教你从bitmap buffer中导出一个我们能够直接浏览的图片:
1. 存储要浏览的bitmap buffer
2. 将bitmap buffer存到本地电脑中
3. 在Eclipse中打开inspector视图
当你要将存好的bitmap buffer转换成普通图片时,需要知道bitmap所对应图片的宽高,从inspector视图中可以得到。
4. 从inspector视图中找到bitmap的宽高
5. 将bitmap buffer文件转换为bmp图片文件
import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; public class MATBitmap { /* Constants */ public static final int RMASK = 0x00ff0000; public static final int GMASK = 0x0000ff00; public static final int BMASK = 0x000000ff; public static final int AMASK = 0xff000000; private static final int SIZE_OF_HEADER = 12; private static final int SIZE_OF_DIB_HEADER = 108; private static final int SIZE_OF_MAGIC = 2; /* Structures */ class bmpfile_magic { byte magic[]; }; static class BMPFile_header { int filesz; short creator1; short creator2; int bmp_offset; public byte[] getBytes() { try { ByteBuffer out = ByteBuffer.allocate(SIZE_OF_HEADER); out.order(ByteOrder.LITTLE_ENDIAN); // ByteArrayOutputStream bout = new ByteArrayOutputStream(); // DataOutputStream out = new DataOutputStream(bout); out.putInt(filesz); out.putShort(creator1); out.putShort(creator2); out.putInt(bmp_offset); return out.array(); } catch (Exception e) { } return null; } }; static class BMPFile_dibheader { int header_sz; int width; int height; short nplanes; short bitspp; int compress_type; int bmp_bytesz; int hres; int vres; int ncolors; int nimpcolors; int rmask, gmask, bmask, amask; int colorspace_type; byte[] colorspace = new byte[0x24]; int rgamma, ggamma, bgamma; public byte[] getBytes() { try { ByteBuffer out = ByteBuffer.allocate(SIZE_OF_DIB_HEADER); out.order(ByteOrder.LITTLE_ENDIAN); out.putInt(header_sz); out.putInt(width); out.putInt(height); out.putShort(nplanes); out.putShort(bitspp); out.putInt(compress_type); out.putInt(bmp_bytesz); out.putInt(hres); out.putInt(vres); out.putInt(ncolors); out.putInt(nimpcolors); out.putInt(rmask); out.putInt(gmask); out.putInt(bmask); out.putInt(amask); out.putInt(colorspace_type); out.put(colorspace); out.putInt(rgamma); out.putInt(ggamma); out.putInt(bgamma); return out.array(); } catch(Exception e) { e.printStackTrace(); } return null; } }; /* Displays usage info and exits */ private static void usage() { System.out .println("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"); System.exit(0); } /* C entry point */ public static void main(String[] args) { // args = new String[4]; // args[0] = "c:/0x100.png"; // args[1] = "c:/conv1.bmp"; // args[2] = "512"; // args[3] = "512"; try { FileInputStream in; FileOutputStream out; String file_in, file_out; int w, h, W, H; byte r, g, b, a, image[]; byte[] magic = new byte[2]; BMPFile_header header = new BMPFile_header(); BMPFile_dibheader dibheader = new BMPFile_dibheader(); /* Parse command line */ if (args.length != 4) { usage(); } file_in = args[0]; file_out = args[1]; W = Integer.parseInt(args[2]); H = Integer.parseInt(args[3]); in = new FileInputStream(file_in); out = new FileOutputStream(file_out); /* Check parameters */ if (in == null || out == null || W == 0 || H == 0) { usage(); } /* Init BMP headers */ magic[0] = 'B'; magic[1] = 'M'; header.filesz = W * H * 4 + magic.length + SIZE_OF_HEADER + SIZE_OF_DIB_HEADER; header.creator1 = 0; header.creator2 = 0; header.bmp_offset = SIZE_OF_MAGIC + SIZE_OF_HEADER + SIZE_OF_DIB_HEADER; dibheader.header_sz = SIZE_OF_DIB_HEADER; 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; Arrays.fill(dibheader.colorspace, (byte)0); dibheader.rgamma = dibheader.bgamma = dibheader.ggamma = 0; /* Read picture data */ image = new byte[4 * W * H]; if (image == null) { System.out.println("Could not allocate a %d-byte buffer. : " + (4 * W * H)); System.exit(0); } in.read(image); in.close(); /* Write header */ out.write(magic); out.write(header.getBytes()); out.write(dibheader.getBytes()); System.out.println("Started writing"); /* Convert the byte array to BMP format */ ByteArrayOutputStream bout = new ByteArrayOutputStream(); 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]; bout.write(b); bout.write(g); bout.write(r); bout.write(a); } } out.write(bout.toByteArray()); bout.close(); System.out.println("Finishe writing"); image = null; out.close(); } catch (Exception e) { e.printStackTrace(); } } }
将上面java代码存为MATBitmap.java
,然后将该java文件与本地存储的buffer文件存到同一目录下,随后在该目录中调起命令行采用下列格式执行命令:
1 |
Java MATBitmap.java <input.bmp> <output.bmp> <bitmap width> <bitmap height> |
Example
1 |
java MATBitmap debug.bmp converted.bmp 800 800 |
然后就可以用普通图片浏览器观察定位该bitmap文件了,从而可以定位内存中未释放的资源