Buscamos por todo el mundo on line para traerte la solución para tu inquietud, en caso de alguna duda puedes dejarnos la duda y respondemos sin falta.
Solución:
Al mostrar Bitmap
en ImageView
de un archivo primero decodifíquelo con la ayuda de BitmapHelper.decodeFile(picturePath, 200, 200, true)
esto volverá comprimido Bitmap
de modo que mientras codifica este mapa de bits puede manejar imágenes de alta resolución, así como imágenes de gran tamaño de hasta 100 MB de archivo.
Después de decodificar el archivo, configúrelo en su ImageView
y conseguir Base64
Forma de cadena sobre la imagen comprimida usando BitmapHelper
clase; obtener Bitmap
de tu ImageView
(es decir, ya ha sido comprimido) y use ImageBase64.encodeTobase64(bitmap)
esto volverá a comprimir el archivo y hará que se maneje OutOfMemory
excepción mientras Encoding
a Bitmap
.
Para decoding
primero escribe tu Base64String
para archivar en la memoria de su dispositivo. Entonces lee Bytes
en trozos y decodificar eso ByteArray
con esto tendrás tu mapa de bits en tu memoria. Después de esto, reduzca este mapa de bits usando decodeFile()
método entonces habrás comprimido Bitmap
de Base64String
He buscado en varios blogs y publicaciones y de ellos he tomado el mejor código adecuado y los he combinado en uno para hacerlo más confiable. Pruebe el siguiente código para hacer encoding
y decoding
más rápido con la gestión de la memoria.
Para decodificar Base64String
Bitmap bitmap = ImageBase64.decodeBase64(base64ImageStr,MainActivity.this);
imageView.setImageBitmap(bitmap);
bitmap = null;
System.gc();
Para codificar Bitmap
Prueba esto:
imageView.setImageBitmap(BitmapHelper.decodeFile(picturePath, 200, 200, true));
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
base64ImageStr = ImageBase64.encodeTobase64(bitmap);
Prueba este código para ImageBase64
public class ImageBase64
private ImageBase64()
super();
private static Context appContext;
public static String encodeTobase64(Bitmap image)
ByteArrayOutputStream baos=new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,100, baos);
byte [] b=baos.toByteArray();
String temp=null;
try
System.gc();
temp=Base64.encodeToString(b, Base64.DEFAULT);
catch(Exception e)
e.printStackTrace();
catch(OutOfMemoryError e)
baos=new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,50, baos);
b=baos.toByteArray();
temp=Base64.encodeToString(b, Base64.DEFAULT);
Log.e("EWN", "Out of memory error catched");
return temp;
public static Bitmap decodeBase64(String input,Context context)
byte[] decodedByte = Base64.decode(input, 0);
appContext = context;
Boolean isSDPresent = android.os.Environment
.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
File sdCardDirectory;
if (isSDPresent)
// yes SD-card is present
sdCardDirectory = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"IMG");
if (!sdCardDirectory.exists())
if (!sdCardDirectory.mkdirs())
Log.d("MySnaps", "failed to create directory");
else
// Sorry
sdCardDirectory = new File(context.getCacheDir(),"");
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((1000 - 0) + 1) + 0;
String nw = "IMG_" + timeStamp + randomNum+".txt";
File image = new File(sdCardDirectory, nw);
// Encode the file as a PNG image.
FileOutputStream outStream;
try
outStream = new FileOutputStream(image);
outStream.write(input.getBytes());
outStream.flush();
outStream.close();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
Log.i("Compress bitmap path", image.getPath());
Bitmap bitmap;
try
bitmap = BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
catch(OutOfMemoryError e)
e.printStackTrace();
InputStream is = context.getResources().openRawResource(R.drawable.default_profile_pic);
bitmap = BitmapFactory.decodeStream(is);
catch (Exception e)
// TODO: handle exception
e.printStackTrace();
bitmap=null;
return bitmap;//BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
//return decodeFile(image);
private static Bitmap decodeFile(File f)
try
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale>=REQUIRED_SIZE && o.outHeight/scale>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
Boolean isSDPresent = android.os.Environment
.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
File sdCardDirectory;
if (isSDPresent)
// yes SD-card is present
sdCardDirectory = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"IMG");
if (!sdCardDirectory.exists())
if (!sdCardDirectory.mkdirs())
Log.d("MySnaps", "failed to create directory");
else
// Sorry
sdCardDirectory = new File(appContext.getCacheDir(),"");
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((1000 - 0) + 1) + 0;
String nw = "IMG_" + timeStamp + randomNum+".png";
File image = new File(sdCardDirectory, nw);
FileOutputStream out = null;
try
out = new FileOutputStream(image);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
catch (Exception e)
e.printStackTrace();
finally
try
if (out != null)
out.close();
catch (IOException e)
e.printStackTrace();
String pathNew =compressImage(image.getAbsolutePath());
Uri uri = Uri.parse(pathNew);
Bitmap bitmap=null ;
try
bitmap = MediaStore.Images.Media.getBitmap(appContext.getContentResolver(),uri);
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
return bitmap;
catch (FileNotFoundException e)
return null;
public static String compressImage(String imageUri) actualWidth > maxWidth)
if (imgRatio < maxRatio) imgRatio = maxHeight / actualHeight; actualWidth = (int) (imgRatio * actualWidth); actualHeight = (int) maxHeight; else if (imgRatio > maxRatio)
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
else
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
// setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
// inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
// this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try
// load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
catch (OutOfMemoryError exception)
exception.printStackTrace();
try
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight,Bitmap.Config.ARGB_8888);
catch (OutOfMemoryError exception)
exception.printStackTrace();
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6)
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
else if (orientation == 3)
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
else if (orientation == 8)
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
catch (IOException e)
e.printStackTrace();
FileOutputStream out = null;
String filename = getFilename();
try
out = new FileOutputStream(filename);
// write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
catch (FileNotFoundException e)
e.printStackTrace();
return filename;
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
public static String getFilename()
/*File file = new File(Environment.getExternalStorageDirectory().getPath(), "IMG/Images");
if (!file.exists())
file.mkdirs();
String uriSting = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + ".jpg");
*/
Boolean isSDPresent = android.os.Environment
.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
File sdCardDirectory;
if (isSDPresent)
// yes SD-card is present
sdCardDirectory = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath(),
"IMG/Images");
if (!sdCardDirectory.exists())
if (!sdCardDirectory.mkdirs())
Log.d("MySnaps", "failed to create directory");
else
// Sorry
sdCardDirectory = new File(appContext.getCacheDir(),"");
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((1000 - 0) + 1) + 0;
String nw = "img_" + timeStamp + randomNum+".jpg";
File image = new File(sdCardDirectory, nw);
String uriSting1 = (sdCardDirectory.getAbsolutePath() + "/" + nw);//System.currentTimeMillis() + ".jpg");
return uriSting1;
Agregue esta clase para manejar imágenes pesadas
public class BitmapHelper
//decodes image and scales it to reduce memory consumption
public static Bitmap decodeFile(String bitmapFile, int requiredWidth, int requiredHeight, boolean quickAndDirty)
try
//Decode image size
BitmapFactory.Options bitmapSizeOptions = new BitmapFactory.Options();
bitmapSizeOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, bitmapSizeOptions);
// load image using inSampleSize adapted to required image size
BitmapFactory.Options bitmapDecodeOptions = new BitmapFactory.Options();
bitmapDecodeOptions.inTempStorage = new byte[16 * 1024];
bitmapDecodeOptions.inSampleSize = computeInSampleSize(bitmapSizeOptions, requiredWidth, requiredHeight, false);
bitmapDecodeOptions.inPurgeable = true;
bitmapDecodeOptions.inDither = !quickAndDirty;
bitmapDecodeOptions.inPreferredConfig = quickAndDirty ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888;
Bitmap decodedBitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, bitmapDecodeOptions);
// scale bitmap to mathc required size (and keep aspect ratio)
float srcWidth = (float) bitmapDecodeOptions.outWidth;
float srcHeight = (float) bitmapDecodeOptions.outHeight;
float dstWidth = (float) requiredWidth;
float dstHeight = (float) requiredHeight;
float srcAspectRatio = srcWidth / srcHeight;
float dstAspectRatio = dstWidth / dstHeight;
// recycleDecodedBitmap is used to know if we must recycle intermediary 'decodedBitmap'
// (DO NOT recycle it right away: wait for end of bitmap manipulation process to avoid
// java.lang.RuntimeException: Canvas: trying to use a recycled bitmap [email protected]
// I do not excatly understand why, but this way it's OK
boolean recycleDecodedBitmap = false;
Bitmap scaledBitmap = decodedBitmap;
if (srcAspectRatio < dstAspectRatio)
scaledBitmap = getScaledBitmap(decodedBitmap, (int) dstWidth, (int) (srcHeight * (dstWidth / srcWidth)));
// will recycle recycleDecodedBitmap
recycleDecodedBitmap = true;
else if (srcAspectRatio > dstAspectRatio)
scaledBitmap = getScaledBitmap(decodedBitmap, (int) (srcWidth * (dstHeight / srcHeight)), (int) dstHeight);
recycleDecodedBitmap = true;
// crop image to match required image size
int scaledBitmapWidth = scaledBitmap.getWidth();
int scaledBitmapHeight = scaledBitmap.getHeight();
Bitmap croppedBitmap = scaledBitmap;
if (scaledBitmapWidth > requiredWidth)
int xOffset = (scaledBitmapWidth - requiredWidth) / 2;
croppedBitmap = Bitmap.createBitmap(scaledBitmap, xOffset, 0, requiredWidth, requiredHeight);
scaledBitmap.recycle();
else if (scaledBitmapHeight > requiredHeight)
int yOffset = (scaledBitmapHeight - requiredHeight) / 2;
croppedBitmap = Bitmap.createBitmap(scaledBitmap, 0, yOffset, requiredWidth, requiredHeight);
scaledBitmap.recycle();
if (recycleDecodedBitmap)
decodedBitmap.recycle();
decodedBitmap = null;
scaledBitmap = null;
return croppedBitmap;
catch (Exception ex)
ex.printStackTrace();
return null;
/**
* compute powerOf2 or exact scale to be used as @link BitmapFactory.Options#inSampleSize value (for subSampling)
*
* @param requiredWidth
* @param requiredHeight
* @param powerOf2
* weither we want a power of 2 sclae or not
* @return
*/
public static int computeInSampleSize(BitmapFactory.Options options, int dstWidth, int dstHeight, boolean powerOf2)
int inSampleSize = 1;
// Raw height and width of image
final int srcHeight = options.outHeight;
final int srcWidth = options.outWidth;
if (powerOf2)
//Find the correct scale value. It should be the power of 2.
int tmpWidth = srcWidth, tmpHeight = srcHeight;
while (true)
else
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) srcHeight / (float) dstHeight);
final int widthRatio = Math.round((float) srcWidth / (float) dstWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
return inSampleSize;
public static Bitmap drawableToBitmap(Drawable drawable)
if (drawable instanceof BitmapDrawable)
return ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
public static Bitmap getScaledBitmap(Bitmap bitmap, int newWidth, int newHeight)
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
return resizedBitmap;
Te sugiero que:
-
Si recibe datos de un servidor que utiliza un protocolo basado en xml, utilice SAXÓFONO analizador en lugar de DOM.
-
No cargue toda la cadena base64 en la memoria. Usar
InputStream
para cargar parte de los datos en elbyte[]
matriz, decodificar Base64 de la matriz y agregar el resultado a un archivo de caché a través deFileOutputStream
. -
Utilice la opción options.inJustDecodeBounds para evitar que un archivo de mapa de bits a gran escala se cargue en la memoria. Puede evaluar la cantidad total de memoria necesaria y tomar la decisión de reducirla, por ejemplo. UPD. Noté que ya lo estás usando.
-
Tenga en cuenta las referencias de objetos que está sosteniendo y pasando a través del flujo de sus métodos. Las referencias sólidas evitan que GC recupere la memoria.
Siguiendo su código: método decodeBase64
sostiene String input
parámetro de argumento en la pila, byte[] decodedByte
referencia y devolución BitmapFactory.decodeStream(new FileInputStream(f), null, o2)
al final. Mantener todos estos objetos en la memoria al mismo tiempo significa una gran presión sobre el GC y la asignación de memoria en general. Como solución más simple, puede null
referencias justo después de que se usaron los objetos correspondientes (cadena y matriz de bytes), por lo que GC podrá liberarlos.
Pruebe con este pseudocódigo: avíseme si tiene alguna pregunta
Bitmap bmp = (Bitmap) data.getExtras().get("data");
img.setImageBitmap(bmp);
btnadd.requestFocus();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
encodedImageString = Base64.encodeToString(b, Base64.DEFAULT);
byte[] bytarray = Base64.decode(encodedImageString, Base64.DEFAULT);
Bitmap bmimage = BitmapFactory.decodeByteArray(bytarray, 0,
bytarray.length);
Eres capaz de añadir valor a nuestro contenido participando con tu veteranía en las interpretaciones.