Android中通过BitmapDrawable获取Bitmap

本文介绍了BitmapDrawable类的使用方法,包括如何从资源文件中获取BitmapDrawable对象、如何通过BitmapDrawable对象获取Bitmap对象以及如何对Bitmap对象进行缩放和裁剪操作。

一个BitmapDrawable就是封装了一个位图。直接以文件的方式,就是封装了一个原始的位图。要了解BitmapDrawable的使用,还需要明白Bitmap、BitmapFactory等类。Bitmap代表了一个原始的位图,并且可以对位图进行一系列的变换操作。BitmapFactory提供一系列的方法用于产生一个Bitmap对象。多用在Canvas中。下面贴一段BitmapDrawable获取Bitmap的代码片段,附带简单的图片裁剪和缩放:

/**
	 * 功能:显示缩略图,大小为40*40
	 * @param rsid
	 * @return
	 */
	public Bitmap getAdjustBitmap(int rsid){
		//通过openRawResource获取一个inputStream对象  
        InputStream inputStream = getResources().openRawResource(rsid);  
        //通过一个InputStream创建一个BitmapDrawable对象  
        BitmapDrawable drawable = new BitmapDrawable(inputStream);  
        //通过BitmapDrawable对象获得Bitmap对象  
        Bitmap bitmap = drawable.getBitmap();  
        //利用Bitmap对象创建缩略图  
        bitmap = ThumbnailUtils.extractThumbnail(bitmap, 40, 40); 
        return bitmap;
       
	}
/**
	 * 功能:image2从image1中截取120*120大小后显示,截取起始坐标为(x,y)
	 * @param img0
	 * @param img1
	 * @return
	 */
	public void setCutBitmap(ImageView img0,ImageView img1,int x,int y){
		BitmapDrawable bitmapDrawable = (BitmapDrawable) img0.getDrawable();
		//获取第一个图片显示框中的位图
		Bitmap bitmap= bitmapDrawable.getBitmap();
		//显示图片的指定区域
		img1.setImageBitmap(Bitmap.createBitmap(bitmap, x, y, 120, 120));
	}

源码下载请点击: 源码下载



<think>我们需要在Android中加载图片到ImageView,并在图片加载完成后获取Bitmap对象。这在使用Glide等第三方库时尤为常见,因为直接获取Bitmap需要一定的技巧。 下面我将介绍几种常用的方法: 方法1:使用Glide的SimpleTarget 方法2:使用Glide的into(Target)方法 方法3:使用Bitmap回调(结合Glide) 方法4:自定义ViewTarget 方法5:异步等待加载完成(不推荐,但提供思路) 下面重点介绍前两种方法,并给出完整代码。 </think># Android ImageView 加载完成后获取 Bitmap 的全面指南 在 Android 开发中,从 ImageView 获取加载完成的 Bitmap 是一个常见的需求,我将详细介绍多种实现方法及其最佳实践。 ## 核心解决方案 ### 方法1:使用 Glide 的 SimpleTarget(推荐) ```java Glide.with(context) .asBitmap() .load(imageUrl) .into(new CustomTarget<Bitmap>() { @Override public void onResourceReady( @NonNull Bitmap bitmap, @Nullable Transition<? super Bitmap> transition ) { // Bitmap 加载完成 processBitmap(bitmap); // 处理Bitmap // 可选:设置到ImageView imageView.setImageBitmap(bitmap); } @Override public void onLoadCleared(@Nullable Drawable placeholder) { // 清除资源时的处理 } @Override public void onLoadFailed(@Nullable Drawable errorDrawable) { // 加载失败处理 } }); // 处理Bitmap的方法 private void processBitmap(Bitmap bitmap) { // 示例:保存到文件 saveBitmapToFile(bitmap); // 示例:处理Bitmap Bitmap processed = applyEffects(bitmap); // 示例:分析Bitmap analyzeBitmap(bitmap); } // 使用Handler确保在主线程更新UI private void saveBitmapToFile(Bitmap bitmap) { new Thread(() -> { File file = new File(getExternalFilesDir(null), "image_" + System.currentTimeMillis() + ".jpg"); try (FileOutputStream out = new FileOutputStream(file)) { bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); runOnUiThread(() -> Toast.makeText(context, "Saved to " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show()); } catch (IOException e) { runOnUiThread(() -> Toast.makeText(context, "Save failed: " + e.getMessage(), Toast.LENGTH_SHORT).show()); } }).start(); } ``` ### 方法2:使用 ViewTarget 直接从 ImageView 获取 ```java Glide.with(context) .load(imageUrl) .into(imageView); // 在需要时获取ImageViewBitmap public void getBitmapFromImageView() { // 检查Drawable类型 Drawable drawable = imageView.getDrawable(); if (drawable instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); if (bitmap != null && !bitmap.isRecycled()) { processBitmap(bitmap); } else { Log.w(TAG, "Bitmap is null or recycled"); } } else if (drawable instanceof Animatable) { Log.w(TAG, "Cannot get bitmap from animated drawable"); } else { Log.w(TAG, "Unsupported drawable type: " + drawable.getClass().getSimpleName()); } } ``` ### 方法3:使用 Picasso 的回调 ```java Picasso.get() .load(imageUrl) .into(imageView, new Callback() { @Override public void onSuccess() { // 图片加载成功 Drawable drawable = imageView.getDrawable(); if (drawable instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); processBitmap(bitmap); } } @Override public void onError(Exception e) { // 加载失败处理 Log.e(TAG, "Image loading failed", e); } }); ``` ### 方法4:使用 Android 原生方法(不推荐) ```java // 设置Bitmap回调 imageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { imageView.getViewTreeObserver().removeOnPreDrawListener(this); // 尝试获取Bitmap Drawable drawable = imageView.getDrawable(); if (drawable instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); if (bitmap != null) { processBitmap(bitmap); } } return true; } }); ``` ## 高级实现:带生命周期的 Bitmap 获取助手 ```java public class BitmapLoaderHelper implements LifecycleObserver { private final WeakReference<Context> contextRef; private final WeakReference<ImageView> imageViewRef; private BitmapCallback callback; public interface BitmapCallback { void onBitmapReady(Bitmap bitmap); void onFailure(Exception e); } public BitmapLoaderHelper(Context context, ImageView imageView) { this.contextRef = new WeakReference<>(context); this.imageViewRef = new WeakReference<>(imageView); if (context instanceof LifecycleOwner) { ((LifecycleOwner) context).getLifecycle().addObserver(this); } } public void loadImage(Object imageSource, BitmapCallback callback) { this.callback = callback; Context context = contextRef.get(); ImageView imageView = imageViewRef.get(); if (context == null || imageView == null) return; Glide.with(context) .asBitmap() .load(imageSource) .addListener(new RequestListener<Bitmap>() { @Override public boolean onLoadFailed( @Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource ) { if (callback != null) { callback.onFailure(e != null ? e : new Exception("Unknown error")); } return false; } @Override public boolean onResourceReady( Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource ) { if (callback != null) { callback.onBitmapReady(resource); } return false; } }) .into(imageView); } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestroy() { contextRef.clear(); imageViewRef.clear(); callback = null; } public Bitmap getCurrentBitmap() { ImageView imageView = imageViewRef.get(); if (imageView == null) return null; Drawable drawable = imageView.getDrawable(); if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } return null; } } // 使用示例 public class MyActivity extends AppCompatActivity { private BitmapLoaderHelper bitmapLoader; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView imageView = findViewById(R.id.image_view); bitmapLoader = new BitmapLoaderHelper(this, imageView); bitmapLoader.loadImage("https://example.com/image.jpg", new BitmapLoaderHelper.BitmapCallback() { @Override public void onBitmapReady(Bitmap bitmap) { // 处理Bitmap saveBitmap(bitmap); } @Override public void onFailure(Exception e) { Toast.makeText(MyActivity.this, "Failed to load image", Toast.LENGTH_SHORT).show(); } }); } private void saveBitmap(Bitmap bitmap) { // 保存Bitmap的实现 } @Override protected void onDestroy() { super.onDestroy(); if (bitmapLoader != null) { getLifecycle().removeObserver(bitmapLoader); } } } ``` ## 常见问题解决方案 ### 问题1:Bitmap 被回收或为空 **解决方案**:使用强引用和有效性检查 ```java public void processBitmapSafely(Bitmap bitmap) { if (bitmap == null || bitmap.isRecycled()) { Log.w(TAG, "Bitmap is invalid"); return; } // 创建Bitmap的副本 Bitmap safeBitmap = bitmap.copy(bitmap.getConfig(), true); // 使用副本处理 // ... } ``` ### 问题2:内存泄漏 **解决方案**:使用弱引用和生命周期管理 ```java public class SafeBitmapProcessor { private final WeakReference<Context> contextRef; public SafeBitmapProcessor(Context context) { this.contextRef = new WeakReference<>(context); } public void process(Bitmap bitmap) { Context context = contextRef.get(); if (context == null) return; // 处理Bitmap new Thread(() -> { // 耗时操作 Bitmap processed = processBitmap(bitmap); // 更新UI new Handler(Looper.getMainLooper()).post(() -> { if (contextRef.get() != null) { ImageView imageView = ((Activity) context).findViewById(R.id.result_image); imageView.setImageBitmap(processed); } }); }).start(); } } ``` ### 问题3:大图处理导致 OOM **解决方案**:使用采样和内存优化 ```java public Bitmap loadAndProcessLargeImage(Context context, Uri imageUri) { // 获取图片尺寸 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; InputStream is = context.getContentResolver().openInputStream(imageUri); BitmapFactory.decodeStream(is, null, options); is.close(); // 计算采样率 int width = options.outWidth; int height = options.outHeight; int inSampleSize = Math.max(1, Math.min(width / 1024, height / 1024)); // 重新加载带采样 options.inJustDecodeBounds = false; options.inSampleSize = inSampleSize; options.inPreferredConfig = Bitmap.Config.RGB_565; is = context.getContentResolver().openInputStream(imageUri); Bitmap bitmap = BitmapFactory.decodeStream(is, null, options); is.close(); return bitmap; } ``` ## 性能优化策略 ### 1. 使用高效的内存缓存 ```java public class BitmapMemoryCache { private static final LruCache<String, Bitmap> memoryCache; static { // 使用最大内存的 1/8 作为缓存 final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; memoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // 以KB为单位返回Bitmap大小 return bitmap.getByteCount() / 1024; } }; } public static void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null && bitmap != null) { memoryCache.put(key, bitmap); } } public static Bitmap getBitmapFromMemCache(String key) { return memoryCache.get(key); } } // 使用示例 String imageKey = "image_" + imageUrl.hashCode(); Bitmap cachedBitmap = BitmapMemoryCache.getBitmapFromMemCache(imageKey); if (cachedBitmap != null && !cachedBitmap.isRecycled()) { imageView.setImageBitmap(cachedBitmap); processBitmap(cachedBitmap); } else { Glide.with(context) .asBitmap() .load(imageUrl) .into(new CustomTarget<Bitmap>() { @Override public void onResourceReady(@NonNull Bitmap bitmap, Transition<? super Bitmap> transition) { // 缓存Bitmap BitmapMemoryCache.addBitmapToMemoryCache(imageKey, bitmap); // 设置到ImageView imageView.setImageBitmap(bitmap); // 处理Bitmap processBitmap(bitmap); } @Override public void onLoadCleared(@Nullable Drawable placeholder) {} }); } ``` ### 2. 使用磁盘缓存策略 ```java public class BitmapDiskCache { private static DiskLruCache diskLruCache; public static synchronized DiskLruCache getInstance(Context context) throws IOException { if (diskLruCache == null || diskLruCache.isClosed()) { File cacheDir = new File(context.getCacheDir(), "bitmap_cache"); if (!cacheDir.exists()) cacheDir.mkdirs(); int appVersion = context.getPackageManager() .getPackageInfo(context.getPackageName(), 0).versionCode; diskLruCache = DiskLruCache.open( cacheDir, appVersion, 1, // 每个key对应一个文件 10 * 1024 * 1024 // 10MB缓存 ); } return diskLruCache; } public static void putBitmap(Context context, String key, Bitmap bitmap) { try { DiskLruCache cache = getInstance(context); DiskLruCache.Editor editor = cache.edit(key); if (editor != null) { OutputStream os = editor.newOutputStream(0); bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); os.close(); editor.commit(); } } catch (Exception e) { Log.e(TAG, "Failed to cache bitmap", e); } } public static Bitmap getBitmap(Context context, String key) { try { DiskLruCache cache = getInstance(context); DiskLruCache.Snapshot snapshot = cache.get(key); if (snapshot != null) { InputStream is = snapshot.getInputStream(0); return BitmapFactory.decodeStream(is); } } catch (Exception e) { Log.e(TAG, "Failed to get cached bitmap", e); } return null; } } ``` ### 3. 异步处理与线程管理 ```java public class BitmapProcessor { private static final ExecutorService executor = Executors.newFixedThreadPool( Math.max(1, Runtime.getRuntime().availableProcessors() - 1) ); public interface BitmapProcessingCallback { void onProcessingComplete(Bitmap result); void onProcessingFailed(Exception e); } public static void processAsync(Bitmap source, ProcessingTask task, BitmapProcessingCallback callback) { executor.execute(() -> { try { Bitmap result = task.process(source); new Handler(Looper.getMainLooper()).post(() -> { if (callback != null) callback.onProcessingComplete(result); }); } catch (Exception e) { new Handler(Looper.getMainLooper()).post(() -> { if (callback != null) callback.onProcessingFailed(e); }); } }); } public interface ProcessingTask { Bitmap process(Bitmap bitmap) throws Exception; } } // 使用示例 BitmapLoaderHelper loader = new BitmapLoaderHelper(context, imageView); loader.loadImage(imageUrl, new BitmapLoaderHelper.BitmapCallback() { @Override public void onBitmapReady(Bitmap bitmap) { BitmapProcessor.processAsync(bitmap, new BitmapProcessor.ProcessingTask() { @Override public Bitmap process(Bitmap bitmap) throws Exception { // 耗时处理 - 例如高斯模糊 return applyBlurEffect(bitmap, 25); } }, new BitmapProcessor.BitmapProcessingCallback() { @Override public void onProcessingComplete(Bitmap result) { resultImageView.setImageBitmap(result); } @Override public void onProcessingFailed(Exception e) { Toast.makeText(context, "Processing failed", Toast.LENGTH_SHORT).show(); } }); } @Override public void onFailure(Exception e) { // 处理加载失败 } }); ``` ## 实际应用场景 ### 场景1:图像上传前处理 ```java public void uploadImageWithProcessing() { BitmapLoaderHelper loader = new BitmapLoaderHelper(this, imageView); loader.loadImage(imageUri, new BitmapLoaderHelper.BitmapCallback() { @Override public void onBitmapReady(Bitmap original) { // 应用压缩和调整大小 Bitmap processed = resizeAndCompress(original, 1024, 768, 80); // 上传处理后的图片 uploadBitmap(processed); } @Override public void onFailure(Exception e) { showError("Failed to load image"); } }); } private Bitmap resizeAndCompress(Bitmap source, int maxWidth, int maxHeight, int quality) { // 计算缩放比例 float aspectRatio = (float) source.getWidth() / source.getHeight(); int width, height; if (source.getWidth() > source.getHeight()) { width = maxWidth; height = Math.round(width / aspectRatio); } else { height = maxHeight; width = Math.round(height * aspectRatio); } // 创建新Bitmap Bitmap result = Bitmap.createScaledBitmap(source, width, height, true); // 压缩到ByteArray ByteArrayOutputStream stream = new ByteArrayOutputStream(); result.compress(Bitmap.CompressFormat.JPEG, quality, stream); byte[] byteArray = stream.toByteArray(); // 返回新Bitmap return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); } ``` ### 场景2:实时图像分析 ```java public void analyzeImageContent() { BitmapLoaderHelper loader = new BitmapLoaderHelper(this, imageView); loader.loadImage(imageUrl, new BitmapLoaderHelper.BitmapCallback() { @Override public void onBitmapReady(Bitmap bitmap) { // 使用ML Kit进行图像分析 FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap); FirebaseVisionImageLabeler labeler = FirebaseVision.getInstance() .getOnDeviceImageLabeler(); labeler.processImage(image) .addOnSuccessListener(labels -> { // 处理标签结果 List<String> labelTexts = new ArrayList<>(); for (FirebaseVisionImageLabel label : labels) { labelTexts.add(label.getText() + ": " + label.getConfidence()); } showLabels(labelText
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值