Skip to content

Instantly share code, notes, and snippets.

@DavidOndrus
Created July 23, 2018 09:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save DavidOndrus/43b6968fad956b45d2d22d4732fd47fa to your computer and use it in GitHub Desktop.
Save DavidOndrus/43b6968fad956b45d2d22d4732fd47fa to your computer and use it in GitHub Desktop.
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