a
554325746@qq.com
2020-01-10 ce0902f1721b9de6c0a2e8b16cdb6be2c6bca2b3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package com.basic.security.utils;
 
import android.graphics.Bitmap;
import android.util.Log;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
 
public class AndroidBmpUtil {
    private static final int BMP_WIDTH_OF_TIMES = 4;
    private static final int BYTE_PER_PIXEL = 3;
 
    /**
     * Android Bitmap Object to Window's v3 24bit Bmp Format File
     *
     * @param orgBitmap
     * @param filePath
     * @return file saved result
     */
    public static boolean save(Bitmap orgBitmap, String filePath) throws IOException {
        long start = System.currentTimeMillis();
        if (orgBitmap == null) {
            return false;
        }
        if (filePath == null) {
            return false;
        }
        boolean isSaveSuccess = true;
 
        int width = orgBitmap.getWidth();
        int height = orgBitmap.getHeight();
 
 
        byte[] dummyBytesPerRow = null;
        boolean hasDummy = false;
        int rowWidthInBytes = BYTE_PER_PIXEL * width;
        if (rowWidthInBytes % BMP_WIDTH_OF_TIMES > 0) {
            hasDummy = true;
 
            dummyBytesPerRow = new byte[(BMP_WIDTH_OF_TIMES - (rowWidthInBytes % BMP_WIDTH_OF_TIMES))];
 
            for (int i = 0; i < dummyBytesPerRow.length; i++) {
                dummyBytesPerRow[i] = (byte) 0xFF;
            }
        }
 
        int[] pixels = new int[width * height];
 
        int imageSize = (rowWidthInBytes + (hasDummy ? dummyBytesPerRow.length : 0)) * height;
 
        int imageDataOffset = 0x36;
 
        int fileSize = imageSize + imageDataOffset;
 
        orgBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
 
        ByteBuffer buffer = ByteBuffer.allocate(fileSize);
        /**
         * BITMAP FILE HEADER Write Start
         **/
        buffer.put((byte) 0x42);
        buffer.put((byte) 0x4D);
 
        buffer.put(writeInt(fileSize));
 
        buffer.put(writeShort((short) 0));
        buffer.put(writeShort((short) 0));
 
        buffer.put(writeInt(imageDataOffset));
        /** BITMAP FILE HEADER Write End */
 
        /** BITMAP INFO HEADER Write Start */
 
        buffer.put(writeInt(0x28));
 
 
        buffer.put(writeInt(width + (hasDummy ? (dummyBytesPerRow.length == 3 ? 1 : 0) : 0)));
        buffer.put(writeInt(height));
 
        buffer.put(writeShort((short) 1));
 
        buffer.put(writeShort((short) 24));
 
        buffer.put(writeInt(0));
 
        buffer.put(writeInt(imageSize));
 
        buffer.put(writeInt(0));
 
        buffer.put(writeInt(0));
        buffer.put(writeInt(0));
        buffer.put(writeInt(0));
        /** BITMAP INFO HEADER Write End */
        int row = height;
        int col = width;
        int startPosition = (row - 1) * col;
        int endPosition = row * col;
        while (row > 0) {
            for (int i = startPosition; i < endPosition; i++) {
                buffer.put((byte) (pixels[i] & 0x000000FF));
                buffer.put((byte) ((pixels[i] & 0x0000FF00) >> 8));
                buffer.put((byte) ((pixels[i] & 0x00FF0000) >> 16));
            }
            if (hasDummy) {
                buffer.put(dummyBytesPerRow);
            }
            row--;
            endPosition = startPosition;
            startPosition = startPosition - col;
        }
        FileOutputStream fos = new FileOutputStream(filePath);
        fos.write(buffer.array());
        fos.close();
        Log.v("AndroidBmpUtil", System.currentTimeMillis() - start + " ms");
        return isSaveSuccess;
    }
 
    /**
     * Write integer to little-endian
     *
     * @param value
     * @return
     * @throws IOException
     */
    private static byte[] writeInt(int value) throws IOException {
        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;
    }
 
    /**
     * Write short to little-endian byte array
     *
     * @param value
     * @return
     * @throws IOException
     */
    private static byte[] writeShort(short value) throws IOException {
        byte[] b = new byte[2];
        b[0] = (byte) (value & 0x00FF);
        b[1] = (byte) ((value & 0xFF00) >> 8);
        return b;
    }
}