将Java位图转换为字节数组

Tom*_*ear 279 java serialization android bytebuffer bitmap

  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[]
Run Code Online (Sandbox Code Playgroud)

当我在调用copyPixelsToBuffer字节后查看缓冲区全部为0 ...从摄像机返回的位图是不可变的......但这应该无关紧要,因为它正在进行复制.

这段代码有什么问题?

小智 628

尝试这样的事情:

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

  • 根据我的经验,在Android等低内存系统上,必须注意添加bitmap.recycle(); 刚压缩后,关闭流以避免内存泄漏异常. (35认同)
  • 这种方法真的浪费了分配.你```ByteArrayOutputStream```将分配一个```字节[]``大小等于```为byte []````你的备份```Bitmap```,然后```ByteArrayOutputStream. toByteArray()```将再次分配另一个相同大小的```byte []```. (10认同)
  • 如果图像不是PNG类型,这不会导致问题吗? (7认同)
  • 不会因为Bitmap是一个解码图像而不管它是什么,就像像素阵列一样.它将压缩为PNG,在压缩时不会失去质量 (5认同)
  • 更好的是@Ted Hopp的倒带选项 - 压缩它是浪费CPU,除非你的目标是编码图像.... (5认同)
  • 此方法会破坏给定图像的 exif 数据。 (2认同)

朱西西*_*朱西西 58

CompressFormat太慢了......

试试ByteBuffer.

※※※字节※※※的位图

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

int size = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(size);
bitmap.copyPixelsToBuffer(byteBuffer);
byteArray = byteBuffer.array();
Run Code Online (Sandbox Code Playgroud)

※※※字节到位图※※※

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);
Run Code Online (Sandbox Code Playgroud)

  • 由于这个问题带有Android标签,因此也可以使用单线将字节转换回位图:`Bitmap bmp = BitmapFactory.decodeByteArray(bytes,0,bytes.length)`其中`bytes'是您的字节数组 (4认同)

Ted*_*opp 17

你需要回放缓冲区吗?

此外,如果位图的步幅(以字节为单位)大于以像素为单位的行长度*字节/像素,则可能会发生这种情况.使字节长度为b.remaining()而不是size.

  • `rewind()`是关键.我得到了相同的`BufferUnderflowException`并在填充后重新缓冲缓冲区解决了这个问题. (6认同)

Tom*_*van 11

这是.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
}
Run Code Online (Sandbox Code Playgroud)


Amo*_*shi 8

使用以下函数将位图编码为byte [],反之亦然

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);
 }
Run Code Online (Sandbox Code Playgroud)


Min*_*ice 6

你的字节数组太小了.每个像素占用4个字节,而不仅仅是1个,因此将您的大小*4相乘,以便阵列足够大.

  • 他的字节数组足够大.`getRowBytes()`占用每个像素4个字节. (4认同)