0

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;
    }
Ramesh
  • 11
  • 4
  • so what problemas do you have with `Base64` ? – pskink Dec 28 '15 at 08:32
  • No problem with base64 as such. Problem is with converting the base64 encoded BufferedImage into a image/Bitmap on the android side. – Ramesh Dec 28 '15 at 09:46
  • so `BitmapFactory` is not working? – pskink Dec 28 '15 at 09:59
  • Yes, doesn't seem to. I get a null bitmap after that call. – Ramesh Dec 28 '15 at 10:02
  • so what is the input data? is it a byte array? is it an `InputStream`? did you try to save it and hex dump? – pskink Dec 28 '15 at 10:08
  • The input data is a BufferedImage written out as a Base64 encoded string using ImageIO. So, when it comes to android, it is a Base64 encoded string. I hope I am clear. – Ramesh Dec 28 '15 at 11:07
  • what is an input to `BitmapFactory`? is it a byte array? is it an `InputStream`? did you try to save it and hex dump? – pskink Dec 28 '15 at 11:15
  • Your Base64 string seems to be missing padding. This is non-standard, and might make the Android decoder choke. Alternatively, try passing `Base64.NO_PADDING` to the `decode` method, to instruct that the input isn't padded. – Harald K Dec 29 '15 at 11:34

2 Answers2

1

@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.

Ramesh
  • 11
  • 4
0

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

Community
  • 1
  • 1
  • I already tried a similar code and didn't seem to work. I have given the sample code above with the base64 encoded image string. – Ramesh Dec 28 '15 at 09:55
  • Use "InputStream" instead of "ByteArrayInputStream" and pass it to "BitmapFactory.decodeStream(InputStream is)",It will not accept "ByteArrayInputStream" as far i know,I updated the same in my answer as well – krishnakumar sekar Dec 28 '15 at 12:17