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; } }