Java 비트 맵을 바이트 배열로 변환


292
  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[]

copyPixelsToBuffer바이트 호출 이 모두 0 인 후 버퍼를 보면 카메라에서 반환 된 비트 맵은 변경할 수 없지만 복사를 수행하기 때문에 중요하지 않습니다.

이 코드에 어떤 문제가있을 수 있습니까?

답변:


652

다음과 같이 해보십시오 :

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

9
이미지가 PNG 유형이 아닌 경우 이것이 문제가되지 않습니까?
pgsandstrom

7
비트 맵은 픽셀 배열과 같은 것이 무엇이든 상관없이 디코딩 된 이미지이기 때문에 아닙니다. 압축시 품질을 잃지 않는 PNG로 압축됩니다

5
@Ted Hopp의 되감기 옵션이 더 좋습니다. 압축하면 목표가 인코딩 된 이미지가 아닌 한 CPU를 낭비하는 것입니다 ....
Kaolin Fire

38
내 경험에 따르면 Android와 같은 메모리가 부족한 시스템에서 bitmap.recycle (); 압축 직후에 메모리 누수 예외를 피하기 위해 스트림을 닫으십시오.
Son Huy TRAN

10
이 접근 방식은 실제로 할당이 낭비됩니다. 귀하 의 백업 과 동일한 크기 의 ByteArrayOutputStream를 할당 한 다음 다시 동일한 크기의 다른 할당 합니다. byte[]byte[]BitmapByteArrayOutputStream.toByteArray()byte[]
zyamys

70

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

※※※ 바이트에서 비트 맵으로 ※※※

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

5
:이 질문은 비트 맵에 다시 바이트 변환 안드로이드 태그를 가지고 있기 때문에 또한 한 줄 수행 할 수 있습니다 귀하의 바이트 배열Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length)bytes
기계적

아마도 큰 / 작은 엔디안을 고려해야합니까?
NeoWang 2016 년

바이트 배열을 로컬 DB (Sqlite, Room)에 저장하려면 위 답변과 같이 압축해야합니다!
J.Dragon

그러나 압축이 없으면 크기 차이가 극적입니다. 이론은 위키 피 디아를 읽을 수 있지만, (1 답에 따라) 내 경우 압축 된 결과의 예를 20 MB, 다른 하나 (이 대답)는 48 개의 MB입니다
키릴 Starostin

19

다음은 .convertToByteArrayKotlin에서 작성된 비트 맵 확장 입니다.

/**
 * 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
}

18

아마도 버퍼를 되 감아 야합니까?

또한 비트 맵의 ​​보폭 (바이트)이 행 길이보다 픽셀 * 바이트 / 픽셀보다 큰 경우에 발생할 수 있습니다. 크기 대신 바이트 길이 b.remaining ()을 만드십시오.


6
rewind()열쇠입니다. 나는 BufferUnderflowException이것을 얻었고 이것을 채운 후에 버퍼를 되 감았습니다.
tstuts

9

아래 함수를 사용하여 비트 맵을 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);
}

6

바이트 배열이 너무 작습니다. 각 픽셀은 1이 아닌 4 바이트를 차지하므로 크기가 4보다 곱하여 배열이 충분히 큽니다.


4
그의 바이트 배열은 충분히 큽니다. getRowBytes()픽셀 당 4 바이트를 고려합니다.
tstuts

3

API 문서에서 Ted Hopp가 정확합니다.

public void copyPixelsToBuffer (Buffer dst)

"...이 메소드가 리턴되면 버퍼 의 현재 위치 가 업데이트됩니다. 위치는 버퍼에 기록 된 요소 수만큼 증가합니다."

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

" 지정된 오프셋에서 시작 하여 현재 위치 에서 지정된 바이트 배열로 바이트를 읽고 읽은 바이트 수만큼 위치를 증가시킵니다."


2

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

0

이것을 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;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.