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

最近想把bitmap转成单色的BMP图片,没有找到现成的方法,经过一番努力最终成功转换.

首先找到一篇文章,把bitmap转换成BMP图片 http://coderlxl201209164551.iteye.com/blog/1765740

发现博主转换的BMP图片为24位色的,而我需要的单色的.我看到博主转换成24位色的BMP图片时,给bitmap增加了一些数据,这些数据貌似是BMP图片的一些信息,所以找到一篇了BMP文件结构的文章  http://www.cnblogs.com/kingmoon/archive/2011/04/18/2020097.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;
 }



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值