Не можете да конвертирате Bitmap в перфектен Base64 String в Android?

Работя върху приложение, в което трябва да заснема изображение от камера. След заснемането трябва да преобразувам Bitmap в Base64. След преобразуване в Base64, трябва да изпратя този низ на СЪРВЪР. Използвам кода по-долу за тази задача:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
base64Image = Base64.encodeToString(b,Base64.DEFAULT);

Проблем: Когато конвертирам този Base64 в изображение, получавам НЕПЪЛНО ИЗОБРАЖЕНИЕ. Същият резултат се случва на сървър, където моето изображение не е перфектно реконструирано от Base64 String.

Моля, предложете ми решението. Вече търсих много и получавам същия код, който използвам в момента.

Редактирано: моля, вижте непълното изображение по-долу

въведете описание на изображението тук

Използване на код за заснемане на изображението:

intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, TAKE_PHOTO);

person Sam-In-TechValens    schedule 01.08.2013    source източник
comment
получавате НЕПЪЛНО ИЗОБРАЖЕНИЕ като какво?   -  person Muhammad Babar    schedule 01.08.2013
comment
проблемът възниква за всички изображения или за някои конкретни?   -  person Muhammad Babar    schedule 01.08.2013
comment
От низа base64 се генерира само 25% изображение...и това се случва с всички изображения   -  person Sam-In-TechValens    schedule 01.08.2013
comment
Вижте, публикувах и изображението...Размерът на изображението е точен спрямо оригинала...но само 25% от горната част се генерират.. останалото не е завършено   -  person Sam-In-TechValens    schedule 01.08.2013
comment
@Sam-In-TechValens пробвахте ли моя код в отговора по-долу?   -  person The Holy Coder    schedule 01.08.2013
comment
променяте ли размера на изображението с BitmapFactoty.Options options.inSampleSize?   -  person Muhammad Babar    schedule 02.08.2013
comment
Решихте ли вече проблема? Имам същия проблем.   -  person emen    schedule 20.09.2013
comment
същия проблем, някакви решения?   -  person Yakov    schedule 02.09.2015


Отговори (3)


Създайте свой собствен Base64 клас и използвайте това:

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();
    }
  }
}

Първо конвертирайте вашето растерно изображение в byteArray чрез следния код:

 ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();

За да използвате този байт за преминаване на повикване [] от вашето растерно изображение:

base64Image = Base64.encode(b));

Можете да го проверите, като натиснете следващия ред в браузъра си, ще видите изображение.

data:image/jpeg;base64,base64Image
person The Holy Coder    schedule 01.08.2013
comment
Да... Опитах вашия код... и изображението по-горе, което публикувах, е само от този код... Получавам същите резултати - person Sam-In-TechValens; 01.08.2013

Добре, реших го. проблемът беше в съхраняването на низа base64 в базата данни. моята колона беше декларирана като "ТЕКСТ" и тя отрязва частите на другата картина, защото дължината на низа. така че го променям на "LONGTEXT" и сега работи перфектно!

person Yakov    schedule 02.09.2015
comment
Много ви благодаря, господине, оправихте деня ми. Аз също бях изправен пред същия проблем, така че преобразувах моя тип данни BLOB в LONGBLOB. - person Priya Jagtap; 17.04.2018

Когато конвертирам този Base64 в изображение, получавам НЕПЪЛНО ИЗОБРАЖЕНИЕ

Опитайте да направите това с вашето изображение Bitmap и проверете дали нещо не е според очакванията:

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));

Ако всичко е наред, тогава проблемът не е кодирането base64. Кажи ми!

person Francesco Vadicamo    schedule 02.08.2013