जावा बिटमैप को बाइट सरणी में परिवर्तित करना


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 से रिवाइंड विकल्प है - इसे संपीड़ित करना जब तक सीपीयू की बर्बादी नहीं होती है जब तक कि आपका लक्ष्य एक एन्कोडेड छवि नहीं है ...
Kaolin Fire

38
मेरे अनुभव में, एंड्रॉइड जैसे कम-मेमोरी सिस्टम पर, बिटमैप को जोड़ने पर ध्यान देना होगा। साइकिल (); संपीड़न के बाद, और मेमोरी रिसाव अपवाद से बचने के लिए स्ट्रीम को बंद करें।
बेटा हुई टीआरएन

10
यह दृष्टिकोण वास्तव में आवंटन का अपव्यय है। आपका ByteArrayOutputStreamआवंटित करेगा एक byte[]आकार के के बराबर byte[]अपने समर्थन Bitmapहै, तो ByteArrayOutputStream.toByteArray()अभी तक एक और फिर से आवंटित करेगा byte[]एक ही आकार के।
zyamys

70

CompFormorm बहुत धीमी है ...

बाइटबफ़र आज़माएँ।

※※※ बिटमैप को बाइट के लिए by

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

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

※※※ बाइट टू बिटमैप bit

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है
automaton

शायद बड़े / छोटे एंडियन को माना जाना चाहिए?
नियोवांग

यदि आप स्थानीय DB (Sqlite, Room) में बाइट सरणी को सहेजना चाहते हैं, तो आपको ऊपरी उत्तर की तरह संपीड़ित करना चाहिए!
जे। विक्रॉन

ध्यान दें, हालांकि, संपीड़न के बिना आकार का अंतर नाटकीय है। सिद्धांत के लिए आप विकिपीडिया पढ़ सकते हैं, लेकिन उदाहरण के लिए मेरे मामले में संपीड़ित परिणाम (1 उत्तर के अनुसार) 20 एमबी है, अन्य एक (यह उत्तर) 48 एमबी है
किरिल स्टैरस्टिन

19

यहाँ बिटमैप विस्तार .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
}

18

क्या आपको बफर को रिवाइंड करने की जरूरत है, शायद?

इसके अलावा, यह हो सकता है यदि बिटमैप के स्ट्राइड (बाइट्स) पिक्सेल * बाइट्स / पिक्सेल में पंक्ति की लंबाई से अधिक है। आकार के बजाय बाइट्स b.remaining () की लंबाई बनाएं।


6
rewind()क्या चाबी है। मैं वही हो रहा था BufferUnderflowExceptionऔर इसे हल करने के बाद बफर को फिर से खोल रहा था ।
tstuts 16

9

बिटमैप को बाइट में संलग्न करने के लिए नीचे दिए गए कार्यों का उपयोग करें] और इसके विपरीत

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

आपकी बाइट सरणी बहुत छोटी है। प्रत्येक पिक्सेल 4 बाइट्स लेता है, न कि केवल 1, इसलिए अपने आकार को 4 * गुणा करें ताकि सरणी काफी बड़ा हो।


4
उसकी बाइट सरणी काफी बड़ी है। getRowBytes()खाते में प्रति पिक्सेल 4 बाइट्स लेता है।
tstuts

3

टेड हॉप सही है, एपीआई प्रलेखन से:

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

स्ट्रिंग-बिटमैप या बिटमैप-स्ट्रिंग को कनवर्ट करने के लिए इसे आज़माएं

/**
 * @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;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.