如何使用Glide将图片下载到位图中?

193

使用Glide将URL下载到ImageView中非常容易:

Glide
   .with(context)
   .load(getIntent().getData())
   .placeholder(R.drawable.ic_loading)
   .centerCrop()
   .into(imageView);

我想知道是否可以将其下载到Bitmap中? 我想下载到一个原始位图中,然后可以使用其他工具进行操作。 我已经查看了代码,但没有看到如何实现。

15个回答

269

请确保您正在使用最新版本

implementation 'com.github.bumptech.glide:glide:4.10.0'

Kotlin:

Glide.with(this)
        .asBitmap()
        .load(imagePath)
        .into(object : CustomTarget<Bitmap>(){
            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                imageView.setImageBitmap(resource)
            }
            override fun onLoadCleared(placeholder: Drawable?) {
                // this is called when imageView is cleared on lifecycle call or for
                // some other reason.
                // if you are referencing the bitmap somewhere else too other than this imageView
                // clear it here as you can no longer have the bitmap
            }
        })

位图大小:

如果您想使用图像的原始大小,请像上面一样使用默认构造函数,否则您可以为位图传递所需的大小

into(object : CustomTarget<Bitmap>(1980, 1080)

Java:

Glide.with(this)
        .asBitmap()
        .load(path)
        .into(new CustomTarget<Bitmap>() {
            @Override
            public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                imageView.setImageBitmap(resource);
            }

            @Override
            public void onLoadCleared(@Nullable Drawable placeholder) {
            }
        });

旧回答:

使用 compile 'com.github.bumptech.glide:glide:4.8.0' 及以下版本

New Answer:

compile 'com.github.bumptech.glide:glide:4.8.0' 及其以下版本中

Glide.with(this)
        .asBitmap()
        .load(path)
        .into(new SimpleTarget<Bitmap>() {
            @Override
            public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                imageView.setImageBitmap(resource);
            }
        });

对于compile 'com.github.bumptech.glide:glide:3.7.0'及其以下版本

Glide.with(this)
        .load(path)
        .asBitmap()
        .into(new SimpleTarget<Bitmap>() {
            @Override
            public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                imageView.setImageBitmap(resource);
            }
        });

现在你可能会看到一个警告信息:SimpleTarget已被弃用

原因:

弃用SimpleTarget的主要目的是为了警告您它诱使您违反Glide的API协议的方式。具体来说,一旦清除SimpleTarget,它并不会强制您停止使用任何已加载的资源,这可能导致崩溃和图像损坏。

SimpleTarget仍然可以使用,只要确保在imageView被清除后不再使用位图即可。


11
我使用 Glide 4.0,但似乎找不到 .asBitmap() 方法。 - Chris Nevill
11
要进行同步调用,请使用Glide.with(this).asBitmap().load(pictureUrl).submit(100, 100).get()。当您想通过 .setLargeIcon(bitmap) 在通知中添加图标时,它非常有用。 - Yazon2006
1
@Max,这个实现对我来说是有效的: implementation 'com.github.bumptech.glide:glide:3.6.1' - Bipin Bharti
2
@Nux请确保您使用的是最新版本4.9.0 - Atiq
4
如果.asBitmap()无法解决,应将其放在with(this)之后。 - Alston
显示剩余6条评论

208

我对Glide不太熟悉,但看起来如果您知道目标大小,可以使用类似以下的代码:

Bitmap theBitmap = Glide.
        with(this).
        load("http://....").
        asBitmap().
        into(100, 100). // Width and height
        get();

看起来您可以传递 -1,-1 ,并获取完整尺寸的图像(仅基于测试,未见文档记录)。

请注意,into(int,int) 返回一个 FutureTarget<Bitmap>,因此您必须将其包装在try-catch块中,涵盖 ExecutionExceptionInterruptedException。这里是一个更完整的示例实现,经过测试可行:

class SomeActivity extends Activity {

    private Bitmap theBitmap = null;
        
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // onCreate stuff ...
        final ImageView image = (ImageView) findViewById(R.id.imageView);

        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                Looper.prepare();
                try {
                    theBitmap = Glide.
                        with(SomeActivity.this).
                        load("https://www.google.es/images/srpr/logo11w.png").
                        asBitmap().
                        into(-1,-1).
                        get();
                 } catch (final ExecutionException e) {
                     Log.e(TAG, e.getMessage());
                 } catch (final InterruptedException e) {
                     Log.e(TAG, e.getMessage());
                 }
                 return null;
            }
            @Override
            protected void onPostExecute(Void dummy) {
                if (null != theBitmap) {
                    // The full bitmap should be available here
                    image.setImageBitmap(theBitmap);
                    Log.d(TAG, "Image loaded");
                };
            }
        }.execute();
    }
}

按照 Monkeyless 在下面的评论中提到的建议(也是官方推荐的 方法),您可以使用 SimpleTarget,可选地与 override(int,int) 联合使用来大大简化代码。但是,在这种情况下必须提供精确的大小(小于1的任何值都不被接受):

Glide
    .with(getApplicationContext())
    .load("https://www.google.es/images/srpr/logo11w.png")
    .asBitmap()
    .into(new SimpleTarget<Bitmap>(100,100) {
        @Override
        public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
            image.setImageBitmap(resource); // Possibly runOnUiThread()
        }
    });

根据 @hennry 的建议,如果你需要同样的图像,则使用 new SimpleTarget<Bitmap>()

更新

 bitmap = Glide.with(c).asBitmap().load( "url").submit().get();

4
为了后代,您不需要异步任务,只需使用.override(int,int)和/或SimpleTarget即可。 - Sam Judd
35
要想获得原始尺寸的位图,最好将位图的宽和高都设置为Target.SIZE_ORIGINAL,而不是-1。 - Alex Bonel
2
@AlexBonel的建议是正确的。-1在我的程序中崩溃了。使用TARGET_SIZE_ORIGINAL获取原始大小。 - SIr Codealot
6
如果在SimpleTarget中不提供任何参数,就会获得完整尺寸的位图,代码如下:new SimpleTarget<Bitmap>(){...} - Henry
4
在 Glide 4.0.0+ 版本中,在 .load() 前使用 .asBitmap(),并且使用 .submit(100, 100) 代替 .into(100, 100)。 - Yazon2006
显示剩余9条评论

17

看起来覆盖Target类或其实现之一,如BitmapImageViewTarget,并覆盖setResource方法以捕获位图可能是可行的方式...

这未经测试。 :-)

    Glide.with(context)
         .load("http://goo.gl/h8qOq7")
         .asBitmap()
         .into(new BitmapImageViewTarget(imageView) {
                     @Override
                     protected void setResource(Bitmap resource) {
                         // Do bitmap magic here
                         super.setResource(resource);
                     }
         });

3
位图不会采用imageView的宽度/高度吗?我希望得到原始未经修改的位图。 - JohnnyLambada
2
对于 Glide 4.0.0+ 版本,请在 .load() 前使用 .asBitmap()。 - Saeed

11

更新

现在我们需要使用自定义目标

示例代码

    Glide.with(mContext)
            .asBitmap()
            .load("url")
            .into(new CustomTarget<Bitmap>() {
                @Override
                public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {

                }

                @Override
                public void onLoadCleared(@Nullable Drawable placeholder) {
                }
            });
如何使用 Glide 下载图像到 Bitmap? 上面的所有答案都是正确的,但已经过时了,因为在新版本的 Glide 中implementation 'com.github.bumptech.glide: glide: 4.8.0 ',
你会在代码中发现下面的错误:
  • .asBitmap()glide: 4.8.0中不可用
enter image description here
  • SimpleTarget<Bitmap> 已弃用
enter image description here 以下是解决方案。
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;



public class MainActivity extends AppCompatActivity {

    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.imageView);

        Glide.with(this)
                .load("")
                .apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
                .into(new Target<Drawable>() {
                    @Override
                    public void onLoadStarted(@Nullable Drawable placeholder) {

                    }

                    @Override
                    public void onLoadFailed(@Nullable Drawable errorDrawable) {

                    }

                    @Override
                    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {

                        Bitmap bitmap = drawableToBitmap(resource);
                        imageView.setImageBitmap(bitmap);
                        // now you can use bitmap as per your requirement
                    }

                    @Override
                    public void onLoadCleared(@Nullable Drawable placeholder) {

                    }

                    @Override
                    public void getSize(@NonNull SizeReadyCallback cb) {

                    }

                    @Override
                    public void removeCallback(@NonNull SizeReadyCallback cb) {

                    }

                    @Override
                    public void setRequest(@Nullable Request request) {

                    }

                    @Nullable
                    @Override
                    public Request getRequest() {
                        return null;
                    }

                    @Override
                    public void onStart() {

                    }

                    @Override
                    public void onStop() {

                    }

                    @Override
                    public void onDestroy() {

                    }
                });

    }

    public static Bitmap drawableToBitmap(Drawable drawable) {

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        int width = drawable.getIntrinsicWidth();
        width = width > 0 ? width : 1;
        int height = drawable.getIntrinsicHeight();
        height = height > 0 ? height : 1;

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}

如果您在.load之前尝试使用asBitmap,则不会出现任何错误。 - Vipul Chauhan
@Spritzig,你现在遇到了什么问题? - AskNilesh
@NileshRathod 它没有显示图标,也没有错误提示,只是不显示图标。 - TheCoderGuy
@NileshRathod 你找到这个问题了吗? - TheCoderGuy

10

以下是对我有效的解决方法:https://github.com/bumptech/glide/wiki/Custom-targets#overriding-default-behavior

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.request.target.BitmapImageViewTarget;

...

Glide.with(yourFragment)
  .load("yourUrl")
  .asBitmap()
  .into(new BitmapImageViewTarget(yourImageView) {
    @Override
    public void onResourceReady(Bitmap bitmap, Transition<? super Bitmap> anim) {
        super.onResourceReady(bitmap, anim);
        Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {  
            @Override
            public void onGenerated(Palette palette) {
                // Here's your generated palette
                Palette.Swatch swatch = palette.getDarkVibrantSwatch();
                int color = palette.getDarkVibrantColor(swatch.getTitleTextColor());
            }
        });
    }
});

9
如果您想将动态位图图像分配给位图变量 kotlin示例:
backgroundImage = Glide.with(applicationContext).asBitmap().load(PresignedUrl().getUrl(items!![position].img)).submit(100, 100).get();

上述答案对我没用。
应该先使用.asBitmap再使用.load("http://....")

5
"into(100, 100)"已经过时,请使用".submit(100, 100)"。 - Yazon2006
为什么Glide会废弃这样的东西?它的使用方式几乎是相同的... - Karan Harsh Wardhan
1
@KaranHarshWardhan 我同意。看起来Glide团队使用“已弃用”一词的含义是:不建议使用,因为我们认为这是一个坏主意。而在计算机领域中更常见的含义是:不建议使用,因为它将在未来版本中被删除。我更喜欢它仅作为未来删除的通知。 - timeSmith

6

新版本更新说明

Glide.with(context.applicationContext)
    .load(url)
    .listener(object : RequestListener<Drawable> {
        override fun onLoadFailed(
            e: GlideException?,
            model: Any?,
            target: Target<Drawable>?,
            isFirstResource: Boolean
        ): Boolean {
            listener?.onLoadFailed(e)
            return false
        }

        override fun onResourceReady(
            resource: Drawable?,
            model: Any?,
            target: com.bumptech.glide.request.target.Target<Drawable>?,
            dataSource: DataSource?,
            isFirstResource: Boolean
        ): Boolean {
            listener?.onLoadSuccess(resource)
            return false
        }

    })
    .into(this)

旧答案

@outlyer的答案是正确的,但新版Glide有一些变化

我的版本:4.7.1

代码:

 Glide.with(context.applicationContext)
                .asBitmap()
                .load(iconUrl)
                .into(object : SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
                    override fun onResourceReady(resource: Bitmap, transition: com.bumptech.glide.request.transition.Transition<in Bitmap>?) {
                        callback.onReady(createMarkerIcon(resource, iconId))
                    }
                })

注意:此代码在UI线程中运行,因此您可以使用AsyncTask、Executor或其他并发方式(如@outlyer的代码)。 如果您想获取原始大小,请将Target.SIZE_ORIGINAL作为我的代码。不要使用-1,-1。

4
SimpleTarget<Bitmap> 已经过时,请在新版本中使用其他替代方案。 - Nainal

3

Kotlin函数

inline fun getBitmap(imageUrl: String, block: (Bitmap?) -> Unit) {
        return try {
            val url = URL(imageUrl)
            val image = BitmapFactory.decodeStream(url.openConnection().getInputStream())
            block(image)
        } catch (e: IOException) {
            println(e)
            block(null)
        }
    }

3
对于Glide 4.10.0版本: Glide.with(context).download(mImageUrl).submit().get()

2
在 Kotlin 中,您可以使用以下代码:
CoroutineScope(Dispatchers.IO).launch {
      Glide.with(this@&YourActivity).asBitmap().load(imageUrl)                           
                        .listener(object : RequestListener<Bitmap> {
                            override fun onLoadFailed(
                                e: GlideException?,
                                model: Any?,
                                target: Target<Bitmap>?,
                                isFirstResource: Boolean
                            ): Boolean {
                                  Log.e("GlideException" ,"${e.message}")
                                return false
                            }

                            override fun onResourceReady(
                                resource: Bitmap?,
                                model: Any?,
                                target: Target<Bitmap>?,
                                dataSource: DataSource?,
                                isFirstResource: Boolean
                            ): Boolean {
                                resource?.let {bitmap->
                                    //here your bitmap is ready you can use it
                                }
                                return false
                            }

                        })
                        .submit().get()//by using this line glide lib behave as synchronously(block instructions until the task is completed) and by removing this line you can use it as a asynchronously(without blocking other operations)  
}

我正在使用

api 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接