我是android
的新手,我对如何处理Bitmaps
感到困惑。
我想下载Bitmap
,它可能非常大,并将其保存到临时内部文件中。然后,我将稍后将此Bitmap
绘制到Canvas
。
我目前的方法是
1.下载输入流
2.复制流
3.使用一个流来使用bitmapFactory.options
计算边界
4.使用另一个流来解码具有样本大小的完整位图
但是,我需要landscape
和portrait
版本,所以现在我必须执行两次并保存两张图片。
或者 - 我看到人们使用bm.compress(Bitmap.CompressFormat.JPEG, 50, bos);
来保存文件。这使得解码具有样本大小,直接从流中保存。我想当我绘制到Canvas
时,我会使用矩阵来缩放。
基本上,我很困惑作为此任务的最佳方法,哪种方法不太可能遇到内存不足而且是更常用的方法?
干杯
答案 0 :(得分:0)
byte[] imagesByte = getLogoImage(Your url);
设置为imageview ...
imgView.setImageBitmap(BitmapFactory.decodeByteArray( imagesByte, 0, imagesByte.length));
下载方法
public static byte[] getLogoImage(String url){
try {
URL imageUrl = new URL(url);
URLConnection ucon = imageUrl.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(500);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
return baf.toByteArray();
} catch (Exception e) {
Log.d("ImageManager", "Error: " + e.toString());
}
return null;
}
答案 1 :(得分:0)
在Android中你必须意识到有限的内存,因此大图像不适合内存,你将有OutOfMemory异常。
关键是,在内部存储器中保存图像后,以显示分辨率
加载它首先下载te图像,这应该在UI线程之外完成,让_url
URL
使用图像地址和_file
包含目标文件的字符串:
URLConnection conn = _url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
boolean success = false; //track succesful operation
if( _file != null)
{
try
{
FileOutputStream fos = new FileOutputStream(_file);
byte data[] = new byte[4086]; //use 4086 bytes buffer
int count = 0;
while ((count = is.read(data)) != -1)
{
fos.write(data, 0, count);//write de data
}
is.close();
fos.flush();
fos.close();
int len = conn.getContentLength();
File f = new File( _file);//check fie length is correct
if( len== f.length())
{
success = true;
}
else
{
//error downloading, delete de file
File tmp = new File( _file);
if( tmp.exists())
{
tmp.delete();
}
}
}catch (Exception e )
{
try
{
e.printStackTrace();
//delete file with errors
File tmp = new File( _file);
if( tmp.exists())
{
tmp.delete();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
finally
{
is.close();//cleanup
}
然后当你必须以所需的分辨率加载图像时,这里的关键是使用BitmapFactory来读取位图信息并获得缩放的位图:
public static Bitmap bitmapFromFile(int width, int height, String file)
{
Bitmap bitmap = null;
final BitmapFactory.Options options = new BitmapFactory.Options();
if( height >0 && width > 0 ) {
options.inJustDecodeBounds = true;//only read bitmap metadata
BitmapFactory.decodeFile(file,options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
}
try
{
bitmap = BitmapFactory.decodeFile(file, options);//decode scaled bitmap
}catch (Throwable t)
{
if( bitmap != null)
{
bitmap.recycle();//cleanup memory, very important!
}
return null;
}
return bitmap
}
最后一步是计算比例因子:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height;
final int halfWidth = width;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((couldShrink(halfWidth, reqWidth, inSampleSize)&&
couldShrink(halfHeight,reqHeight, inSampleSize))
//&&(halfHeight*halfWidth)/inSampleSize > maxsize)
)
{
inSampleSize *= 2;
}
}
return inSampleSize;
}
private static boolean couldShrink ( int dimension, int req_dimension, int divider)
{
int actual = dimension / divider;
int next = dimension / (divider*2);
int next_error = Math.abs(next - req_dimension);
int actual_error = Math.abs(actual-req_dimension);
return next > req_dimension ||
(actual > req_dimension && (next_error < actual_error) )
;
}
如果您想手动完成,我建议您使用Picasso来处理图像的下载,磁盘缓存和内存缓存:
在下载时加载到名为image
的ImageView中显示背景(R.drawable.img_bg
):
Picasso.with(image.getContext())
.load(url).placeholder(R.drawable.img_bg).fit()
.into(image, new Callback.EmptyCallback()
{
@Override
public void onSuccess()
{
holder.progress.setVisibility(View.GONE); //hide progress bar
}
@Override
public void onError()
{
holder.progress.setVisibility(View.GONE); //hide progress bar
//do whatever you design to show error
}
});
自己处理一个位图:
//first declare a target
_target = new Target()
{
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
{
//handle your bitmap (store it and use it on you canvas
}
@Override
public void onBitmapFailed(Drawable errorDrawable)
{
//handle your fail state
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable)
{//for example for drawing a placeholder while downloading
}
};
现在您只需加载并调整图片大小:
Picasso.with(context).load(url).resize(192, 192).centerCrop().into(_target);
希望有所帮助。