您的位置:首页 > 移动开发 > Android开发

Android中将bitmap转换成单色的BMP图片

2015-06-26 18:46 525 查看
最近想把bitmap转成单色的BMP图片,没有找到现成的方法,经过一番努力最终成功转换.

首先找到一篇文章,把bitmap转换成BMP图片 /article/4076286.html

发现博主转换的BMP图片为24位色的,而我需要的单色的.我看到博主转换成24位色的BMP图片时,给bitmap增加了一些数据,这些数据貌似是BMP图片的一些信息,所以找到一篇了BMP文件结构的文章
/article/6972367.html。发现在位图信息头里面有一个表示BMP图像的色深的字段。前面博主使用的是0x18
0x00 0x18转换成十进制为24所以生成的图片为24位的,想要生成单色的图片话把0x18改成0x01,图片就成了单色。又看到BMP文件结构里面有句话“彩色表/调色板(color table)是单色、16色和256色图像文件所特有的,相对应的调色板大小是2、16和256,调色板以4字节为单位,每4个字节存放一个颜色值,图像 的数据是指向调色板的索引。“因为24位色的BMP图片不存在调色板。如果我要改成单色的话就得加上一个大小为2的调色板,每个调色板的大小为4字节。在24位色中每3个字节表示一个点,而在单色中每个bit表示一个点。所以循环取到bitmap中每个像素点,(ps:在bitmap中每4个字节表示点),将每个点用1bit来表示。由于我在使用bitmap之前先将bitmap变成黑白色的,所以我只需要判断哪些像素点为黑色就将那个bit置为1。如此转换就将24位色的BMP图片转成了单色的BMP图片.

PS:原博主转换成BMP图片有个bug,BMP文件头中3-6字节表示BMP图像文件的大小,而原博主使用的是BMP图像数据大小,而位图信息头中21-24表示BMP图像数据大小而博主给的是0。这种情况下WINDOWS显示没问题,但是android系统识别文件大小为0。

以下附上源码,但是我的代码存在一个问题,BMP图像的宽度只能为N*8*4,BMP文件结构说明有这么一句话"

BMP图像数据大小,必须是4的倍数,图像数据大小不是4的倍数时用0填充补足",但是我补0了转换出来的BMP文件还是有问题,如果有知道原因的,还请留言告知...

附源码:

/**将bitmap转换成bmp格式图片

* @param bitmap 要转换的bitmap

* @param fos bmp文件输出流

*/

private void FormatBMP(Bitmap bitmap,FileOutputStream fos)

{

if (bitmap != null) {

int w = bitmap.getWidth(), h = bitmap.getHeight();

int[] pixels=new int[w*h];

bitmap.getPixels(pixels, 0, w, 0, 0, w, h);//取得BITMAP的所有像素点

byte[] rgb = addBMP_RGB_888(pixels,w,h);

byte[] header = addBMPImageHeader(62+rgb.length);

byte[] infos = addBMPImageInfosHeader(w, h,rgb.length);

byte[] colortable = addBMPImageColorTable();

byte[] buffer = new byte[62 + rgb.length];

System.arraycopy(header, 0, buffer, 0, header.length);

System.arraycopy(infos, 0, buffer, 14, infos.length);

System.arraycopy(colortable, 0, buffer, 54, colortable.length);

System.arraycopy(rgb, 0, buffer, 62, rgb.length);

try {

fos.write(buffer);

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

// BMP文件头

private byte[] addBMPImageHeader(int size) {

byte[] buffer = new byte[14];

buffer[0] = 0x42;

buffer[1] = 0x4D;

buffer[2] = (byte) (size >> 0);

buffer[3] = (byte) (size >> 8);

buffer[4] = (byte) (size >> 16);

buffer[5] = (byte) (size >> 24);

buffer[6] = 0x00;

buffer[7] = 0x00;

buffer[8] = 0x00;

buffer[9] = 0x00;

// buffer[10] = 0x36;

buffer[10] = 0x3E;

buffer[11] = 0x00;

buffer[12] = 0x00;

buffer[13] = 0x00;

return buffer;

}

// BMP文件信息头

private byte[] addBMPImageInfosHeader(int w, int h, int size) {

Log.i("_DETEST_", "size="+size);

byte[] buffer = new byte[40];

buffer[0] = 0x28;

buffer[1] = 0x00;

buffer[2] = 0x00;

buffer[3] = 0x00;

buffer[4] = (byte) (w >> 0);

buffer[5] = (byte) (w >> 8);

buffer[6] = (byte) (w >> 16);

buffer[7] = (byte) (w >> 24);

buffer[8] = (byte) (h >> 0);

buffer[9] = (byte) (h >> 8);

buffer[10] = (byte) (h >> 16);

buffer[11] = (byte) (h >> 24);

buffer[12] = 0x01;

buffer[13] = 0x00;

buffer[14] = 0x01;

buffer[15] = 0x00;

buffer[16] = 0x00;

buffer[17] = 0x00;

buffer[18] = 0x00;

buffer[19] = 0x00;

buffer[20] = (byte) (size >> 0);

buffer[21] = (byte) (size >> 8);

buffer[22] = (byte) (size >> 16);

buffer[23] = (byte) (size >> 24);

// buffer[24] = (byte) 0xE0;

// buffer[25] = 0x01;

buffer[24] = (byte) 0xC3;

buffer[25] = 0x0E;

buffer[26] = 0x00;

buffer[27] = 0x00;

// buffer[28] = 0x02;

// buffer[29] = 0x03;

buffer[28] = (byte) 0xC3;

buffer[29] = 0x0E;

buffer[30] = 0x00;

buffer[31] = 0x00;

buffer[32] = 0x00;

buffer[33] = 0x00;

buffer[34] = 0x00;

buffer[35] = 0x00;

buffer[36] = 0x00;

buffer[37] = 0x00;

buffer[38] = 0x00;

buffer[39] = 0x00;

return buffer;

}

private byte[] addBMPImageColorTable() {

byte[] buffer = new byte[8];

buffer[0] = (byte) 0xFF;

buffer[1] = (byte) 0xFF;

buffer[2] = (byte) 0xFF;

buffer[3] = 0x00;

buffer[4] = 0x00;

buffer[5] = 0x00;

buffer[6] = 0x00;

buffer[7] = 0x00;

return buffer;

}

private byte[] addBMP_RGB_888(int[] b, int w, int h) {

int len = w*h;

int bufflen = 0;

byte[] tmp = new byte[3];

int index = 0,bitindex = 1;

if (w*h % 8 != 0)//将8字节变成1个字节,不足补0

{

bufflen = w*h/ 8 + 1;

}

else

{

bufflen = w*h/ 8;

}

if (bufflen % 4 != 0)//BMP图像数据大小,必须是4的倍数,图像数据大小不是4的倍数时用0填充补足

{

bufflen = bufflen + bufflen%4;

}

byte[] buffer = new byte[bufflen];

for (int i = len - 1; i >= w; i -= w) {

// DIB文件格式最后一行为第一行,每行按从左到右顺序

int end = i, start = i - w + 1;

for (int j = start; j <= end; j++) {

tmp[0] = (byte) (b[j] >> 0);

tmp[1] = (byte) (b[j] >> 8);

tmp[2] = (byte) (b[j] >> 16);

String hex = "";

for (int g = 0; g < tmp.length; g++) {

String temp = Integer.toHexString(tmp[g] & 0xFF);

if (temp.length() == 1) {

temp = "0" + temp;

}

hex = hex + temp;

}

if (bitindex > 8)

{

index += 1;

bitindex = 1;

}

if (!hex.equals("ffffff"))

{

buffer[index] = (byte) (buffer[index] | (0x01 << 8-bitindex));

}

bitindex++;

}

}

return buffer;

}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: