将Java位图转换为字节数组。

时间:2022-09-27 08:59:27
  Bitmap bmp   = intent.getExtras().get("data");
  int size     = bmp.getRowBytes() * bmp.getHeight();
  ByteBuffer b = ByteBuffer.allocate(size);

  bmp.copyPixelsToBuffer(b);

  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.

当我在调用copyPixelsToBuffer之后查看缓冲区时,字节都是0…从相机返回的位图是不可变的…但这并不重要,因为它在复制。

What could be wrong with this code?

这段代码有什么问题?

9 个解决方案

#1


550  

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();
bmp.recycle();

#2


25  

Use CompressFormat is too slow...

使用压缩格式太慢…

Try use ByteBuffer.

尝试使用ByteBuffer。

※※※Bitmap to byte※※※

※※※※※※。、、、位图到字节、、

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

            int size = bitmap.getRowBytes() * bitmap.getHeight();
            ByteBuffer byteBuffer = ByteBuffer.allocate(size);
            bitmap.copyPixelsToBuffer(byteBuffer);
            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);
        bitmap_tmp.copyPixelsFromBuffer(buffer);

#3


16  

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.

此外,如果位图的步幅(以字节为单位)大于行长度(以像素为单位),则可能发生这种情况。将字节的长度改为b.剩下的()而不是大小。

#4


5  

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.

您的字节数组太小。每个像素占用4个字节,而不是1个字节,所以要乘以大小* 4,这样数组就足够大了。

#5


3  

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

#6


2  

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

为了避免大文件的OutOfMemory错误,我将通过将位图分割成几个部分并合并它们的部分字节来解决这个任务。

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.recycle();
            bitmapChunk = null;
        }
        yCoord += chunkHeight;
    }

    return imageBytes;
}


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

#7


2  

Here is bitmap extension .convertToByteArray wrote in Kotlin.

这里是位图扩展。converttobytearray在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
    this.copyPixelsToBuffer(buffer)

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

    //transfer bytes from buffer into the given destination array
    buffer.get(bytes)

    //return bitmap's pixels
    return bytes
}

#8


1  

Ted Hopp is correct, from the API Documentation :

Ted Hopp是正确的,从API文档:

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. "

“…在此方法返回后,缓冲区的当前位置将被更新:该位置将被缓冲区中写入的元素的数量递增。”

and

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."

“从当前位置读取字节到指定的字节数组,从指定的偏移量开始,并通过读取的字节数增加位置。”

#9


0  

Try this to convert String-Bitmap or Bitmap-String

请尝试将此转换为String-Bitmap或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){
    try{
        byte [] encodeByte=Base64.decode(encodedString,Base64.DEFAULT);
        Bitmap bitmap= BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
        return bitmap;
    }catch(Exception e){
        e.getMessage();
        return null;
    }
}

#1


550  

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();
bmp.recycle();

#2


25  

Use CompressFormat is too slow...

使用压缩格式太慢…

Try use ByteBuffer.

尝试使用ByteBuffer。

※※※Bitmap to byte※※※

※※※※※※。、、、位图到字节、、

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

            int size = bitmap.getRowBytes() * bitmap.getHeight();
            ByteBuffer byteBuffer = ByteBuffer.allocate(size);
            bitmap.copyPixelsToBuffer(byteBuffer);
            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);
        bitmap_tmp.copyPixelsFromBuffer(buffer);

#3


16  

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.

此外,如果位图的步幅(以字节为单位)大于行长度(以像素为单位),则可能发生这种情况。将字节的长度改为b.剩下的()而不是大小。

#4


5  

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.

您的字节数组太小。每个像素占用4个字节,而不是1个字节,所以要乘以大小* 4,这样数组就足够大了。

#5


3  

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

#6


2  

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

为了避免大文件的OutOfMemory错误,我将通过将位图分割成几个部分并合并它们的部分字节来解决这个任务。

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.recycle();
            bitmapChunk = null;
        }
        yCoord += chunkHeight;
    }

    return imageBytes;
}


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

#7


2  

Here is bitmap extension .convertToByteArray wrote in Kotlin.

这里是位图扩展。converttobytearray在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
    this.copyPixelsToBuffer(buffer)

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

    //transfer bytes from buffer into the given destination array
    buffer.get(bytes)

    //return bitmap's pixels
    return bytes
}

#8


1  

Ted Hopp is correct, from the API Documentation :

Ted Hopp是正确的,从API文档:

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. "

“…在此方法返回后,缓冲区的当前位置将被更新:该位置将被缓冲区中写入的元素的数量递增。”

and

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."

“从当前位置读取字节到指定的字节数组,从指定的偏移量开始,并通过读取的字节数增加位置。”

#9


0  

Try this to convert String-Bitmap or Bitmap-String

请尝试将此转换为String-Bitmap或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){
    try{
        byte [] encodeByte=Base64.decode(encodedString,Base64.DEFAULT);
        Bitmap bitmap= BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
        return bitmap;
    }catch(Exception e){
        e.getMessage();
        return null;
    }
}