Created
July 23, 2018 09:06
-
-
Save DavidOndrus/43b6968fad956b45d2d22d4732fd47fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.nio.ByteBuffer; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
public class AndroidBmpUtil { | |
private static final int BMP_WIDTH_OF_TIMES = 4; | |
private static final int BYTE_PER_PIXEL = 3; | |
public static byte[] convertToBmp24bit(byte[] imageData) { | |
Bitmap orgBitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); | |
if(orgBitmap == null){ | |
return null; | |
} | |
//image size | |
int width = orgBitmap.getWidth(); | |
int height = orgBitmap.getHeight(); | |
//image dummy data size | |
//reason : the amount of bytes per image row must be a multiple of 4 (requirements of bmp format) | |
byte[] dummyBytesPerRow = null; | |
boolean hasDummy = false; | |
int rowWidthInBytes = BYTE_PER_PIXEL * width; //source image width * number of bytes to encode one pixel. | |
if(rowWidthInBytes%BMP_WIDTH_OF_TIMES>0){ | |
hasDummy=true; | |
//the number of dummy bytes we need to add on each row | |
dummyBytesPerRow = new byte[(BMP_WIDTH_OF_TIMES-(rowWidthInBytes%BMP_WIDTH_OF_TIMES))]; | |
//just fill an array with the dummy bytes we need to append at the end of each row | |
for(int i = 0; i < dummyBytesPerRow.length; i++){ | |
dummyBytesPerRow[i] = (byte)0xFF; | |
} | |
} | |
//an array to receive the pixels from the source image | |
int[] pixels = new int[width * height]; | |
//the number of bytes used in the file to store raw image data (excluding file headers) | |
int imageSize = (rowWidthInBytes+(hasDummy?dummyBytesPerRow.length:0)) * height; | |
//file headers size | |
int imageDataOffset = 0x36; | |
//final size of the file | |
int fileSize = imageSize + imageDataOffset; | |
//Android Bitmap Image Data | |
orgBitmap.getPixels(pixels, 0, width, 0, 0, width, height); | |
//ByteArrayOutputStream baos = new ByteArrayOutputStream(fileSize); | |
ByteBuffer buffer = ByteBuffer.allocate(fileSize); | |
try { | |
/* | |
BITMAP FILE HEADER Write Start | |
*/ | |
buffer.put((byte)0x42); | |
buffer.put((byte)0x4D); | |
//size | |
buffer.put(writeInt(fileSize)); | |
//reserved | |
buffer.put(writeShort((short)0)); | |
buffer.put(writeShort((short)0)); | |
//image data start offset | |
buffer.put(writeInt(imageDataOffset)); | |
/* BITMAP FILE HEADER Write End */ | |
//******************************************* | |
/* BITMAP INFO HEADER Write Start */ | |
//size | |
buffer.put(writeInt(0x28)); | |
//width, height | |
//if we add 3 dummy bytes per row : it means we add a pixel (and the image width is modified. | |
buffer.put(writeInt(width+(hasDummy?(dummyBytesPerRow.length==3?1:0):0))); | |
buffer.put(writeInt(height)); | |
//planes | |
buffer.put(writeShort((short)1)); | |
//bit count | |
buffer.put(writeShort((short)24)); | |
//bit compression | |
buffer.put(writeInt(0)); | |
//image data size | |
buffer.put(writeInt(imageSize)); | |
//horizontal resolution in pixels per meter | |
buffer.put(writeInt(0)); | |
//vertical resolution in pixels per meter (unreliable) | |
buffer.put(writeInt(0)); | |
buffer.put(writeInt(0)); | |
buffer.put(writeInt(0)); | |
/* BITMAP INFO HEADER Write End */ | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return null; | |
} | |
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; | |
} | |
return buffer.array(); | |
} | |
/** | |
* 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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment