source

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

goodcode 2022. 8. 11. 22:17
반응형

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

  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...카메라에서 반환된 비트맵은 불변입니다...복사를 하고 있으니 그건 문제가 되지 않을 겁니다

이 코드에 어떤 문제가 있을까요?

다음과 같은 방법을 사용해 보십시오.

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

CompressFormat이 너무 느립니다...

Byte Buffer를 사용해 보세요.

※ ※ ※ 비트맵과 바이트 ※ ※ ※

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

비트맵 확장자는 다음과 같습니다..convertToByteArray코틀린어로 썼다.

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

버퍼를 되감아야 하나요?

또한 비트맵의 스트라이드(바이트 단위)가 행 길이(픽셀당 *바이트 수)보다 큰 경우에도 발생할 수 있습니다.크기 대신 b.remaining() 바이트 길이를 지정합니다.

다음 함수를 사용하여 비트맵을 바이트[]로 인코딩하거나 비트맵을 바이트[]로 인코딩합니다.

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

바이트 배열이 너무 작습니다.각 픽셀은 1바이트뿐만 아니라 4바이트를 차지하므로 어레이가 충분히 커지도록 크기 *4를 곱합니다.

API Documentation의 Ted Hopp은 다음과 같습니다.

public void copyPixelsToBuffer (Buffer dst)

"... 이 메서드가 반환되면 버퍼의 현재 위치가 갱신됩니다.이 위치는 버퍼에 입력된 요소의 수만큼 증가합니다."

그리고.

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

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

피하려면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();
}

이거면 될 것 같은데...

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

문자열 비트맵 또는 비트맵 문자열을 변환하려면 이 작업을 수행하십시오.

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

언급URL : https://stackoverflow.com/questions/4989182/converting-java-bitmap-to-byte-array

반응형