1

私は初めてでandroid、対処方法について混乱していBitmapsます。

をダウンロードしたいのですがBitmap、かなり大きくなる可能性があり、一時的な内部ファイルに保存します。次に、これBitmapCanvas後で描画します。

私の現在の方法は次のとおりです。1。入力ストリームをダウンロードします2.ストリームをコピーします3.1つのストリームを使用して境界を計算しますbitmapFactory.options 4.他のストリームを使用してサンプルサイズで完全なビットマップをデコードします

ただし、バージョンが必要なlandscapeのでportrait、これを2回実行して、2つの画像を保存する必要があります。

または-私は人々がbm.compress(Bitmap.CompressFormat.JPEG, 50, bos);代わりにファイルを保存するために使用するのを見ました。これは、ストリームから直接保存されたサンプルサイズでのデコードをバイパスします。に描画するときは、マトリックスを使用してスケーリングすると思いCanvasます。

基本的に、私はこのタスクの最良のアプローチとして混乱しています。どの方法がメモリ不足になる可能性が低く、より一般的に使用されるアプローチですか?

乾杯

4

2 に答える 2

0

Android ではメモリの制限に注意する必要があるため、大きな画像はメモリに収まらず、OutOfMemory 例外が発生します。

重要なのは、画像を内部ストレージに保存した後、ディスプレイ解像度でロードすることです。

最初に画像をダウンロードします。これは 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);

それが役立つことを願っています。

于 2016-07-22T11:25:33.450 に答える
0
  byte[] imagesByte = getLogoImage(Your url);

イメージビューに設定...

 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;
        }
于 2012-08-28T09:39:40.363 に答える