Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to convert Bitmap to perfect Base64 String in Android?

Tags:

android

base64

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

enter image description here

Code use to capture the Image:

intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, TAKE_PHOTO);
like image 318
Sam-In-TechValens Avatar asked Aug 01 '13 10:08

Sam-In-TechValens


2 Answers

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
like image 61
The Holy Coder Avatar answered Oct 16 '22 13:10

The Holy Coder


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!

like image 21
Yakov Avatar answered Oct 16 '22 16:10

Yakov