Context
I believe I have searched enough about this topic but haven't found an answer yet. If any of you have any answer please help out.
I am trying to send an image as an output to a service call from an android app.
I have used BufferedImage, ImageIO and a ByteArrayOutputStream to convert the image to a Base64 encoded string (from many of the examples I could find on stackoverflow).
This Base64 encoded string is received by the android app. Now, this needs to be converted back to an image and shown on an activity.
FYI. The image I am trying to send over is a QR code generated using zxing libraries.
Problem
This is where I am struggling. I am not sure how to do it. I haven't posted any sample code, since the server side code is pretty self explanatory and I don't yet have any code on the server side.
Sample code on the Android side
private Bitmap getBitmap() {
String base64String="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";
ByteArrayInputStream imageArr=new ByteArrayInputStream(Base64.decode(base64String, Base64.DEFAULT));
Bitmap bitmap = BitmapFactory.decodeStream(imageArr);
return bitmap;
}
#haraldK, thanks for giving me the right pointer. I was also wondering why I didn't see any padding, but didn't put enough focus on it to understand the issue. But, based on your hint, I finally figured out the issue. The issue was that I was not closing the OutputStream given by Base64 Encoder properly. In my code I had a the Base64 encoder stream as a wrapper of a ByteArrayOutputStream as below:
final ByteArrayOutputStream os = new ByteArrayOutputStream();
String qString = "";
try {
MatrixToImageWriter.writeToStream(matrix, formatName, Base64.getEncoder().wrap(os));
qString = os.toString("UTF-8");
os.close();
return qString;
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
In the above code, I was closing the ByteArrayOutputStream using os.close() which was not required. But what was required was closing of the OutputStream given out by the Base64 encoder. I changed the code as below to make it work:
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OutputStream base64Stream = Base64.getEncoder().wrap(os);
String qString = "";
try {
MatrixToImageWriter.writeToStream(matrix, formatName, base64Stream);
base64Stream.close();
qString = os.toString("UTF-8");
os.close();
return qString;
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
After the above change, the base64 encoded strings are properly padded and are properly getting decoded on the Android side. On the android side this is code I have to display the image:
byte[] imageArr=Base64.decode(base64String.getBytes(), Base64.NO_WRAP);
Bitmap bitmap=BitmapFactory.decodeByteArray(imageArr, 0, imageArr.length);
return bitmap;
I didn't know how to upvote your answer, so I have created this as a separate answer. Thanks for your help.
Can you please add your image Response string
As you are doing it in ByteArrayOutputStream you may missed the below item before decoding
String imageDataBytes = responseImageData.substring(responseImageData.indexOf(",")+1);
InputStream stream = new ByteArrayInputStream(Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT));
Bitmap bitmap = BitmapFactory.decodeStream(stream);
A good answer available for the same question here
Related
So in my app I have possibility to take photo. What I want to do later is to sent this photo to server using API as Base64 String. Here's my code to encode bitmap (photo) to String :
public static String convertPhotoToBase(Bitmap bmp) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
Log.e(TAG, Base64.encodeToString(byteArray, Base64.DEFAULT));
return Base64.encodeToString(byteArray, Base64.DEFAULT);
}
Looks ok, right ? Well, it's not and I don't why String I'm receiving is not encoded correctly. I add, that bitmap is ok , cuz I can display it in ImageView without any problems.
String I'm getting looks like this :
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 UHOSaACXt9dDDgZlJXClyxBszo4tmGKJp
It looks like correct Base64 string but if you check it - it's not. Do you have any idea why is that ? Is it bitmap issue ,or what ? Any help, please ?
use this method to encode the bitmap you want
public static String enBitmap64(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
bitmap.recycle();
byte[] array = stream.toByteArray();
return Base64.encodeToString(array, 0);
}
and this method to decode the string
public static Bitmap deBitmap64(String string) {
byte[] decodedString = Base64.decode(string, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
return decodedByte;
}
However, before using encode64 you need to know few things
Encode and decode bitmaps needs to be done in background (NOT IN THE MAIN THREAD) it hangs the UI specially if the bitmap was large, use Asynctask, Service or Runnable (Asynctask is best choice).
It's not recommended to encode large images and upload it as string to server, encode and decode only in two cases.
First, if all you images are small.
Second, if you have large images and somewhere you app you display it as thumbnail For exp; In friends search of Facebook you see small images(thumbnail) you click it becomes large(original image). so there is small image and large image, when you are in friends search page you only request(download) the small image (low resolution) from the server no need to request(download) such large image(high resolution), but the two images are stored in the server. the small one could be saved as encoded but NOT the large one, large images is to be upload to server though HttpClient, Volley or HttpURLConnection.. there are more
I have almost the same issue,
encoding and decoding were working perfectly on the java side.
But my Base64 string couldn't be decoded on the server side.
comparing different base64s helped me to see that my base64 break into lines so using following code helped to correct base64
base64string.replace("\n", ""));
I got a list of images and an input image, I want to output true if the image exist in my list.
Images will consider to be equal if they got the same raw data.
Is there an easy way of doing this in Android?
I saw this method:
boolean Bitmap.sameAs(Bitmap)
But it require to test binary data against each of my images in the list and this is kind of expensive. Is there a better way doing this?
And what if I change the definition of equal images to "similar", in such way that if the images got over 90% visual similarity they will consider to be equal.
Here is the solution for the first part where equal images are those who got the same raw data.
You can hash each image and compare it by hash, this way you will test the image raw data only once.
String toSHA1(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
try {
String sha1 = toSHA1(byteArray);
stream.close();
return sha1;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
String toSHA1(byte[] data) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
BigInteger bigInteger = new BigInteger(1, md.digest(data));
return bigInteger.toString(Character.MAX_RADIX);
}
I have the code below to decode a bitmap to a base64 string.
for(String e:paths)
{
String usepath=e.replace("%", "//");
Bitmap m=BitmapFactory.decodeFile(usepath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
m.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
String bb= Base64.encodeToString(b, Base64.NO_WRAP);
Log.e("Photo", bb);
String usepath prints like
/mnt/sdcard/DCIM/Camera/IMG_20140424_132023.jpg
I have saved the image on my pc and used an online tool to decode it to base64 and i got a long string of around 650kb(after uploading to google app engine) yet the string i get using the above code is like 10% of that and does not display the image .
But i can use the same image path to set an image view and it works like below
Bitmap bm= BitmapFactory.decodeFile(usepath);
holder.imageItem.setImageBitmap(bm);
Any reasons why the base64 encoding failing?
Ronald
Try adding the flag Base64.URL_SAFE to the encoding method.
Consider also that if the image is too large you may not get all the bytes you need in the String (you may try writing to a temp file previous to send the content).
I'm using the SpringFramework for Android to get my inputstreams.
#Override
public InputStream getImageStream(String url) {
InputStream is = new ByteArrayInputStream(template.getForObject(url, byte[].class));
return is;
}
For the first few inputstreams its going ok. No Problems at all, but then, I think it tries to get a very big inputstream. So then I get the outofmemory error.
I see a lot of posts using something like the following code:
public byte[] readBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
byte[] byteArray= byteBuffer.toByteArray();
return byteArray;
}
The idea of this code is to read the inputstream in chunks right?
But the outofmemory error I'm getting is before I can even start the readBytes method. I tried putting resets everywhere...I thought maybe I should clear the memory somewhere after readbytes or something. But I do not know how and I don't know if that is the right way?
I think I'm having the basics wrong? I'm very new to android and java... Is there a way of getting the InputStream another way? I also read something about BufferedInputStream but I just can't think up of a way to fit it in.
My goal is to store a blob of the image in the database. And my input is the imgurl via oauth.
I can also call less quality versions of the inputstream through another url. And then everything works...
But I wanted to try it with the original image url, because maybe later I want to have the ability to download an original for printing the photo.
You are getting OutOfMemory error because you reading whole data in memory when using ByteArrayInputStream. Also notice that when you write in ByteArrayOutputStream it keeps data in memory too (it just simple wrapper for byte array). Probably you should use FileOutputStream instead as cache.
I am new to iPhone development.Currently I am working on an application in which I need to send an image as well as text. So I thought of using json technology by sending the string as json data. Now I need to append this image to this string. Can anyone suggest a method to do this?
This application should also be able to bump with an android phone. Is there any method to do this?
I heard of converting the image to base64 and send as string. Is that the right method to do it?
converting image to base64 is the right method for this. please have look at following code snippet
public String convertToBase64(Bitmap bm){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] image = baos.toByteArray();
String encodedImage = Base64.encodeToString(image, Base64.DEFAULT);
return encodedImage;
}
You can use this string to send through JSON data
Edited Part
For iPhone Try this code
-(NSString *)getStringFromImage:(UIImage *)image{
if(image){
NSData *dataObj = UIImagePNGRepresentation(image);
return [dataObj base64Encoding];
} else {
return #"";
}
}
Hope this will solve your problem