可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am working on an application in which I need to capture an Image from camera. After capture, I have to convert the Bitmap to Base64. After converting to Base64, I have to send that String to SERVER. I am using below code for this task:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] b = baos.toByteArray(); base64Image = Base64.encodeToString(b,Base64.DEFAULT);
Problem : When I convert that Base64 to image, I am getting INCOMPLETE IMAGE. The same result is happening over server where my image is not perfectly re-constructed from Base64 String.
Please suggest me the solution. I have already search a-lot and getting same code which I am using right now.
Edited: please see the below incomplete Image

Code use to capture the Image:
intent = new Intent("android.media.action.IMAGE_CAPTURE"); startActivityForResult(intent, TAKE_PHOTO);
回答1:
Create your own Base64 class and use this :
public class Base64 { private Base64() { super(); } /** * Encode some data and return a String. */ public final static String encode(byte[] d) { if (d == null) return null; byte data[] = new byte[d.length+2]; System.arraycopy(d, 0, data, 0, d.length); byte dest[] = new byte[(data.length/3)*4]; // 3-byte to 4-byte conversion for (int sidx = 0, didx=0; sidx < d.length; sidx += 3, didx += 4) { dest[didx] = (byte) ((data[sidx] >>> 2) & 077); dest[didx+1] = (byte) ((data[sidx+1] >>> 4) & 017 | (data[sidx] << 4) & 077); dest[didx+2] = (byte) ((data[sidx+2] >>> 6) & 003 | (data[sidx+1] << 2) & 077); dest[didx+3] = (byte) (data[sidx+2] & 077); } // 0-63 to ascii printable conversion for (int idx = 0; idx <dest.length; idx++) { if (dest[idx] < 26) dest[idx] = (byte)(dest[idx] + 'A'); else if (dest[idx] < 52) dest[idx] = (byte)(dest[idx] + 'a' - 26); else if (dest[idx] < 62) dest[idx] = (byte)(dest[idx] + '0' - 52); else if (dest[idx] < 63) dest[idx] = (byte)'+'; else dest[idx] = (byte)'/'; } // add padding for (int idx = dest.length-1; idx > (d.length*4)/3; idx--) { dest[idx] = (byte)'='; } return new String(dest); } /** * Encode a String using Base64 using the default platform encoding **/ public final static String encode(String s) { return encode(s.getBytes()); } /** * Decode data and return bytes. */ public final static byte[] decode(String str) { if (str == null) return null; byte data[] = str.getBytes(); return decode(data); } /** * Decode data and return bytes. Assumes that the data passed * in is ASCII text. */ public final static byte[] decode(byte[] data) { int tail = data.length; while (data[tail-1] == '=') tail--; byte dest[] = new byte[tail - data.length/4]; // ascii printable to 0-63 conversion for (int idx = 0; idx <data.length; idx++) { if (data[idx] == '=') data[idx] = 0; else if (data[idx] == '/') data[idx] = 63; else if (data[idx] == '+') data[idx] = 62; else if (data[idx] >= '0' && data[idx] <= '9') data[idx] = (byte)(data[idx] - ('0' - 52)); else if (data[idx] >= 'a' && data[idx] <= 'z') data[idx] = (byte)(data[idx] - ('a' - 26)); else if (data[idx] >= 'A' && data[idx] <= 'Z') data[idx] = (byte)(data[idx] - 'A'); } // 4-byte to 3-byte conversion int sidx, didx; for (sidx = 0, didx=0; didx < dest.length-2; sidx += 4, didx += 3) { dest[didx] = (byte) ( ((data[sidx] << 2) & 255) | ((data[sidx+1] >>> 4) & 3) ); dest[didx+1] = (byte) ( ((data[sidx+1] << 4) & 255) | ((data[sidx+2] >>> 2) & 017) ); dest[didx+2] = (byte) ( ((data[sidx+2] << 6) & 255) | (data[sidx+3] & 077) ); } if (didx < dest.length) { dest[didx] = (byte) ( ((data[sidx] << 2) & 255) | ((data[sidx+1] >>> 4) & 3) ); } if (++didx < dest.length) { dest[didx] = (byte) ( ((data[sidx+1] << 4) & 255) | ((data[sidx+2] >>> 2) & 017) ); } return dest; } /** * A simple test that encodes and decodes the first commandline argument. */ public static final void main(String[] args) { if (args.length != 1) { System.out.println("Usage: Base64 string"); System.exit(0); } try { String e = Base64.encode(args[0].getBytes()); String d = new String(Base64.decode(e)); System.out.println("Input = '" + args[0] + "'"); System.out.println("Encoded = '" + e + "'"); System.out.println("Decoded = '" + d + "'"); } catch (Exception x) { x.printStackTrace(); } } }
First Convert your bitmap to byteArray by following code :
ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] b = baos.toByteArray();
To use this call pass byte[] of your bitmap image:
base64Image = Base64.encode(b));
You can check it by hitting following line in your browser, you will see image.
data:image/jpeg;base64,base64Image
回答2:
Ok, i solved it. the problem was in the storing of the base64 string on the database. my column was declare as "TEXT" and it cuts the other picture's parts because the lenght of the string. so i changes it to "LONGTEXT" and now it's work perfectly!
回答3:
When I convert that Base64 to image, I am getting INCOMPLETE IMAGE
Try to do this with your image Bitmap and check if something is not as expected:
Bitmap originalBitmap = (Bitmap) data.getExtras().get("data"); //or whatever image you want Log.d(TAG, "original bitmap byte count: " + originalBitmap.getByteCount()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); originalBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); Log.d(TAG, "byte array output stream size: " + baos.size()); byte[] outputByteArray = baos.toByteArray(); Log.d(TAG, "output byte array length: " + outputByteArray.length); String base64EncodedString = Base64.encodeToString(outputByteArray, Base64.DEFAULT); Log.d(TAG, "base64 encoded string length: " + base64EncodedString.length()); byte[] inputByteArray = Base64.decode(base64EncodedString, Base64.DEFAULT); Log.d(TAG, "input byte array length: " + inputByteArray.length); ByteArrayInputStream bais = new ByteArrayInputStream(inputByteArray); Log.d(TAG, "byte array input stream size: " + bais.available()); Bitmap decodedBitmap = BitmapFactory.decodeStream(bais); Log.d(TAG, "decoded bitmap byte count: " + decodedBitmap.getByteCount()); Log.d(TAG, "decoded bitmap same as original bitmap? " + decodedBitmap.sameAs(originalBitmap));
If all is ok then the problem is not the base64 encoding. Let me know!