Bitmap bmp   = intent.getExtras().get("data");
  int size     = bmp.getRowBytes() * bmp.getHeight();
  ByteBuffer b = ByteBuffer.allocate(size);


  byte[] bytes = new byte[size];

  try {
     b.get(bytes, 0, bytes.length);
  } catch (BufferUnderflowException e) {
     // always happens
  // do something with byte[]

When I look at the buffer after the call to copyPixelsToBuffer the bytes are all 0... The bitmap returned from the camera is immutable... but that shouldn't matter since it's doing a copy.

What could be wrong with this code?

Solution 1

Try something like this:

Bitmap bmp = intent.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();

Solution 2

CompressFormat is too slow...

Try ByteBuffer.

Bitmap to byte

width = bitmap.getWidth();
height = bitmap.getHeight();

int size = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(size);
byteArray = byteBuffer.array();

byte to bitmap

Bitmap.Config configBmp = Bitmap.Config.valueOf(bitmap.getConfig().name());
Bitmap bitmap_tmp = Bitmap.createBitmap(width, height, configBmp);
ByteBuffer buffer = ByteBuffer.wrap(byteArray);

Solution 3

Here is bitmap extension .convertToByteArray wrote in Kotlin.

 * Convert bitmap to byte array using ByteBuffer.
fun Bitmap.convertToByteArray(): ByteArray {
    //minimum number of bytes that can be used to store this bitmap's pixels
    val size = this.byteCount

    //allocate new instances which will hold bitmap
    val buffer = ByteBuffer.allocate(size)
    val bytes = ByteArray(size)

    //copy the bitmap's pixels into the specified buffer

    //rewinds buffer (buffer position is set to zero and the mark is discarded)

    //transfer bytes from buffer into the given destination array

    //return bitmap's pixels
    return bytes

Solution 4

Do you need to rewind the buffer, perhaps?

Also, this might happen if the stride (in bytes) of the bitmap is greater than the row length in pixels * bytes/pixel. Make the length of bytes b.remaining() instead of size.

Solution 5

Use below functions to encode bitmap into byte[] and vice versa

public static String encodeTobase64(Bitmap image) {
    Bitmap immagex = image;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    immagex.compress(Bitmap.CompressFormat.PNG, 90, baos);
    byte[] b = baos.toByteArray();
    String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);
    return imageEncoded;

public static Bitmap decodeBase64(String input) {
    byte[] decodedByte = Base64.decode(input, 0);
    return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);

Solution 6

Your byte array is too small. Each pixel takes up 4 bytes, not just 1, so multiply your size * 4 so that the array is big enough.

Solution 7

Ted Hopp is correct, from the API Documentation :

public void copyPixelsToBuffer (Buffer dst)

"... After this method returns, the current position of the buffer is updated: the position is incremented by the number of elements written in the buffer. "


public ByteBuffer get (byte[] dst, int dstOffset, int byteCount)

"Reads bytes from the current position into the specified byte array, starting at the specified offset, and increases the position by the number of bytes read."

Solution 8

In order to avoid OutOfMemory error for bigger files, I would recommend to solve the task by splitting a bitmap into several parts and merging their parts' bytes.

private byte[] getBitmapBytes(Bitmap bitmap)
    int chunkNumbers = 10;
    int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();
    byte[] imageBytes = new byte[bitmapSize];
    int rows, cols;
    int chunkHeight, chunkWidth;
    rows = cols = (int) Math.sqrt(chunkNumbers);
    chunkHeight = bitmap.getHeight() / rows;
    chunkWidth = bitmap.getWidth() / cols;

    int yCoord = 0;
    int bitmapsSizes = 0;

    for (int x = 0; x < rows; x++)
        int xCoord = 0;
        for (int y = 0; y < cols; y++)
            Bitmap bitmapChunk = Bitmap.createBitmap(bitmap, xCoord, yCoord, chunkWidth, chunkHeight);
            byte[] bitmapArray = getBytesFromBitmapChunk(bitmapChunk);
            System.arraycopy(bitmapArray, 0, imageBytes, bitmapsSizes, bitmapArray.length);
            bitmapsSizes = bitmapsSizes + bitmapArray.length;
            xCoord += chunkWidth;

            bitmapChunk = null;
        yCoord += chunkHeight;
    return imageBytes;

private byte[] getBytesFromBitmapChunk(Bitmap bitmap)
    int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();
    ByteBuffer byteBuffer = ByteBuffer.allocate(bitmapSize);
    return byteBuffer.array();

Solution 9

I think this will do -

public static byte[] convertBitmapToByteArray(Bitmap bitmap){
        ByteBuffer byteBuffer = ByteBuffer.allocate(bitmap.getByteCount());
        return byteBuffer.array();

Solution 10

Try this to convert String-Bitmap or Bitmap-String

 * @param bitmap
 * @return converting bitmap and return a string
public static String BitMapToString(Bitmap bitmap){
    ByteArrayOutputStream baos=new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
    byte [] b=baos.toByteArray();
    String temp=Base64.encodeToString(b, Base64.DEFAULT);
    return temp;

 * @param encodedString
 * @return bitmap (from given string)
public static Bitmap StringToBitMap(String encodedString){
        byte [] encodeByte=Base64.decode(encodedString,Base64.DEFAULT);
        Bitmap bitmap= BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
        return bitmap;
    }catch(Exception e){
        return null;