android图片转1位bmp

来源:互联网 发布:photoshop mac版破解 编辑:程序博客网 时间:2024/05/22 02:16
最近在做一个项目,要一张png图片转换成1位bmp位图,再上传。在网上找了很多资料,都没有一个统一的答案。转成相应的位图比较好转(24png位转24bmp),可转成一位的,那是比较头疼了。下面介绍,如何将一位32位的png转成bmp。在android中,并没有保存bmp格式的现成api。32位的png,一个像素有32位,即ARGB,A表示alpha通道,1位的位图呢,一个字节表示8个像素,也就是说转换的时候,要用8个像素拼成一个byte(因为数据流每次至少写一个byte,没有只写一位的),每一个32位的像素要转成一位的。此文中,转成一位的只取alpha通道,即ARGB中的A位。如果说要将24位(没有alpha通道)的转成一位的,看各个需求了。
    public static void saveBmp(Bitmap bitmap, String desPath) {        try {            int png_width = bitmap.getWidth(), png_height = bitmap.getHeight();            int[] pixels = new int[png_width * png_height];            bitmap.getPixels(pixels, 0, png_width, 0, 0, png_width, png_height);            DataOutputStream bmpout = new DataOutputStream(                    new FileOutputStream(desPath));            Log.e("", png_height + ",with:" + png_width);            int a = png_width % 32;            a = (a == 0 ? 32 : a);            int with = png_width + 32 - a;            int arg[][] = new int[png_height][with];            int length = (png_width + 32 - a) * png_height / 8;            writeShort(0x424d, bmpout); // 文件头 2个字节,“BM”            writeInt(62 + length, bmpout);// 整个文件大小,4个字节            writeShort(0, bmpout);            writeShort(0, bmpout); // 保留,必须设置为0 ,4个字节            writeInt(62, bmpout); // 从文件开始到位图数据开始之间的数据(bitmap data)之间的偏移量 ,4个字节            writeInt(40, bmpout); // 位图信息头(Bitmap Info Header)的长度,用来描述                                    // 位图的颜色、压缩方法等            writeInt(png_width, bmpout); // 位图的宽度,以象素为单位            writeInt(png_height, bmpout); // 位图的高度,以象素为单位            writeInShort(1, bmpout); // 位图的位面数(注:该值将总是1)            writeInShort(1, bmpout);// 每个象素的位数。位深            writeInt(0, bmpout); // 压缩说明: 0 - 不压缩 (使用BI_RGB表示)            // 1 - RLE 8-使用8位RLE压缩方式(用BI_RLE8表示)            // 2 - RLE 4-使用4位RLE压缩方式(用BI_RLE4表示)            // 3 - Bitfields-位域存放方式(用BI_BITFIELDS表示),4个字节            writeInt(length, bmpout);            // 用字节数表示的位图数据的大小。该数必须是4 的倍数            writeInt(3780, bmpout); // 用象素/米表示的水平分辨率            writeInt(3780, bmpout); // 用象素/米表示的垂直分辨率            writeInt(0, bmpout); // 位图使用的颜色数。如8-比特/象素表示为100h或 者 256            writeInt(0, bmpout); // 指定重要的颜色数。当该域的值等于颜色数时(或 者等于0时),表示所有颜色都一样重要            writeInt(0, bmpout);            writeShort(0xFFFF, bmpout);//调色板的2种颜色            writeShort(0xFF00, bmpout);            String data = "";            for (int i = arg.length - 1; i >= 0; i--) {                for (int j = 0; j < arg[i].length; j++) {                    int color = 0x00000000;                    if (j > png_width - 1) {                    } else {                        color = pixels[png_width * i + j];                    }                    int alpha = (color & 0xff000000) >> 24;                    int temp = (alpha == 0 ? 1 : 0);                    data = data + temp;                    if (data.length() == 8) {                        bmpout.writeByte(Integer.parseInt(data, 2));                        data = "";                    }                }            }        } catch (Exception e) {        }    }    private static void writeInt(int n, DataOutputStream bmpout) {        try {            bmpout.writeByte(n);            bmpout.writeByte(n >> 8);            bmpout.writeByte(n >> 16);            bmpout.writeByte(n >> 24);        } catch (IOException ex) {        }    }    private static void writeShort(int n, DataOutputStream bmpout) {        try {            bmpout.writeByte(n >> 8);            bmpout.writeByte(n);        } catch (IOException ex) {        }    }    private static void writeInShort(int n, DataOutputStream bmpout) {        try {            bmpout.writeByte(n);            bmpout.writeByte(n >> 8);        } catch (IOException ex) {        }    }
 上面代码代码都有注释,注意,这里是生成一位的位图,一位的位图是有调色板的,如果说32位或者是24位,就没有调色板,也就是文件偏移少8个byte,前面的整个文件头,文件大小要减8,即62-8。这里位图颜色数据使用字符串处理的。int temp = (alpha == 0 ? 1 : 0); 当alpha通道是0,就给它赋值1,否则为0,没有alpha通道时,图片全是黑色的。最重要的是,当图片的宽度,不能够被32整除时,要按32位补齐,例如,图片652*233px,652%32=12,后面要补20个0,图片的大小就得增加20*233。最后测试代码:

@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Bitmap bitmap =
BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+File.separator+”sign.png”);
saveBmp(bitmap,
Environment.getExternalStorageDirectory()+File.separator+”sign.bmp”);
}
生成的位图,在pc端用UE打开,用pc自带的画图工具转成一位的位图对比一下(主要看头62位)。

0 0
原创粉丝点击