Android : save a Bitmap to bmp file format

后端 未结 4 892
盖世英雄少女心
盖世英雄少女心 2020-12-01 19:28

I have a Bitmap in memory and I need to save it in a bmp file (using the bmp file format).

Is there any way to do it on Android ?

(I read a lot of post sugg

4条回答
  •  渐次进展
    2020-12-01 20:07

    Code to convert android Bitmap object to 8bit bmp file. It is derived from this C# project : https://www.codeproject.com/articles/70442/c-rgb-to-palette-based-bit-greyscale-bitmap-clas

    import android.graphics.Bitmap;
    import android.graphics.Color;
    
    
    public class BitmapConvertor {
    
        private  byte[] Color_palette = new byte[1024]; //a palette containing 256 colors
       private   byte[] BMP_File_Header = new byte[14];
       private  byte[] DIB_header = new byte[40];
      private   byte[] Bitmap_Data = null;
    
    
        //returns a byte array of a grey scale bitmap image
        public    byte[] CreateGrayBitmapArray(Bitmap Image) {
            try {
                create_parts(Image);
                //Create the array
                byte[] bitmap_array = new byte[BMP_File_Header.length + DIB_header.length
                        + Color_palette.length + Bitmap_Data.length];
                Copy_to_Index(bitmap_array, BMP_File_Header, 0);
                Copy_to_Index(bitmap_array, DIB_header, BMP_File_Header.length);
                Copy_to_Index(bitmap_array, Color_palette, BMP_File_Header.length + DIB_header.length);
                Copy_to_Index(bitmap_array, Bitmap_Data, BMP_File_Header.length + DIB_header.length + Color_palette.length);
    
                return bitmap_array;
            } catch (Exception e) {
                return null; //return a null single byte array if fails
            }
        }
    
    
        //creates byte array of 256 color grayscale palette
        private   byte[] create_palette() {
            byte[] color_palette = new byte[1024];
            for (int i = 0; i < 256; i++) {
                color_palette[i * 4 + 0] = (byte) (i); //bule
                color_palette[i * 4 + 1] = (byte) (i); //green
                color_palette[i * 4 + 2] = (byte) (i); //red
                color_palette[i * 4 + 3] = (byte) 0; //padding
            }
            return color_palette;
        }
    
    
        //adds dtata of Source array to Destinition array at the Index
       private   boolean Copy_to_Index(byte[] destination, byte[] source, int index) {
            try {
                for (int i = 0; i < source.length; i++) {
                    destination[i + index] = source[i];
                }
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    
    
        //create different part of a bitmap file
      private    void create_parts(Bitmap img) {
            //Create Bitmap Data
            Bitmap_Data = ConvertToGrayscale(img);
            //Create Bitmap File Header (populate BMP_File_Header array)
            Copy_to_Index(BMP_File_Header, new byte[]{(byte) 'B', (byte) 'M'}, 0); //magic number
            Copy_to_Index(BMP_File_Header, writeInt(BMP_File_Header.length
                    + DIB_header.length + Color_palette.length + Bitmap_Data.length), 2); //file size
            Copy_to_Index(BMP_File_Header, new byte[]{(byte) 'M', (byte) 'C', (byte) 'A', (byte) 'T'}, 6); //reserved for application generating the bitmap file (not imprtant)
            Copy_to_Index(BMP_File_Header, writeInt(BMP_File_Header.length
                    + DIB_header.length + Color_palette.length), 10); //bitmap raw data offset
            //Create DIB Header (populate DIB_header array)
            Copy_to_Index(DIB_header, writeInt(DIB_header.length), 0); //DIB header length
            Copy_to_Index(DIB_header, writeInt(((Bitmap) img).getWidth()), 4); //image width
            Copy_to_Index(DIB_header, writeInt(((Bitmap) img).getHeight()), 8); //image height
            Copy_to_Index(DIB_header, new byte[]{(byte) 1, (byte) 0}, 12); //color planes. N.B. Must be set to 1
            Copy_to_Index(DIB_header, new byte[]{(byte) 8, (byte) 0}, 14); //bits per pixel
            Copy_to_Index(DIB_header, writeInt(0), 16); //compression method N.B. BI_RGB = 0
            Copy_to_Index(DIB_header, writeInt(Bitmap_Data.length), 20); //lenght of raw bitmap data
            Copy_to_Index(DIB_header, writeInt(1000), 24); //horizontal reselution N.B. not important
            Copy_to_Index(DIB_header, writeInt(1000), 28); //vertical reselution N.B. not important
            Copy_to_Index(DIB_header, writeInt(256), 32); //number of colors in the palette
            Copy_to_Index(DIB_header, writeInt(0), 36); //number of important colors used N.B. 0 = all colors are imprtant
            //Create Color palett
            Color_palette = create_palette();
        }
    
    
        //convert the color pixels of Source image into a grayscale bitmap (raw data)
      private    byte[] ConvertToGrayscale(Bitmap Source) {
            Bitmap source = (Bitmap) Source;
            int padding = (source.getWidth() % 4) != 0 ? 4 - (source.getWidth() % 4) : 0; //determine padding needed for bitmap file
            byte[] bytes = new byte[source.getWidth() * source.getHeight() + padding * source.getHeight()]; //create array to contain bitmap data with paddin
            for (int y = 0; y < source.getHeight(); y++) {
                for (int x = 0; x < source.getWidth(); x++) {
                    int pixel = source.getPixel(x, y);
                    int g = (int) (0.3 * Color.red(pixel) + 0.59 * Color.green(pixel) + 0.11 * Color.blue(pixel)); //grayscale shade corresponding to rgb
                    bytes[(source.getHeight() - 1 - y) * source.getWidth() + (source.getHeight() - 1 - y) * padding + x] = (byte) g;
                }
                //add the padding
                for (int i = 0; i < padding; i++) {
                    bytes[(source.getHeight() - y) * source.getWidth() + (source.getHeight() - 1 - y) * padding + i] = (byte) 0;
                }
            }
            return bytes;
        }
    
    
        /**
         * Write integer to little-endian
         *
         * @param value
         * @return
         * @throws IOException
         */
        private  byte[] writeInt(int value) {
            byte[] b = new byte[4];
    
            b[0] = (byte) (value & 0x000000FF);
            b[1] = (byte) ((value & 0x0000FF00) >> 8);
            b[2] = (byte) ((value & 0x00FF0000) >> 16);
            b[3] = (byte) ((value & 0xFF000000) >> 24);
    
            return b;
        }
    }
    

提交回复
热议问题