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文件了,從而可以定位內存中未釋放的資源