You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Canvas绘制后Bitmap被裁剪/缩小的问题求助

问题原因分析

你遇到的图片缩小/裁剪问题,核心原因是:从customView.getDrawable()中获取的Bitmap并非原始图片的尺寸。ZoomageView(继承自ImageView)会根据自身布局尺寸对Drawable进行缩放、适配,此时getDrawable()返回的是经过视图适配后的Bitmap,以此为基础创建新Bitmap并设置回视图,相当于把已经缩放压缩后的图当成了“原图”,最终就会出现视觉上的缩小效果,且无法再继续缩小(因为它已经是当前视图适配后的最小尺寸)。

解决方案

方案1:直接加载原始资源Bitmap(适用于本地图片)

如果你的图片是本地drawable/mipmap资源,直接从资源加载原始尺寸的Bitmap,跳过从View的Drawable中获取的步骤:

public void onBtnClick(View view){
    ZoomageView customView = findViewById(R.id.myZoomageView);
    
    // 加载原始尺寸的Bitmap(替换R.drawable.your_original_image为你的资源ID)
    Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_original_image);
    // 创建可编辑的副本(避免原始Bitmap不可修改的问题)
    Bitmap tempBitmap = originalBitmap.copy(Bitmap.Config.RGB_565, true);
    Canvas tempCanvas = new Canvas(tempBitmap);
    
    // 绘制线条(这里用原始图的尺寸作为终点,避免超出范围)
    Paint p = new Paint();
    p.setStrokeWidth(50);
    p.setColor(Color.RED);
    tempCanvas.drawLine(0, 0, originalBitmap.getWidth(), originalBitmap.getHeight(), p);
    
    customView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));
    
    // 回收原始Bitmap,避免内存泄漏
    if (!originalBitmap.isRecycled()) {
        originalBitmap.recycle();
    }
}

方案2:提前保存原始Bitmap引用(适用于动态加载的图片,如网络图)

如果图片是网络加载或动态生成的,在首次设置到ZoomageView时,就保存原始Bitmap的全局引用:

// 全局变量保存原始Bitmap
private Bitmap mOriginalBitmap;

// 初始化ZoomageView时保存原始Bitmap
public void initZoomageView(Bitmap bitmap) {
    mOriginalBitmap = bitmap;
    ZoomageView customView = findViewById(R.id.myZoomageView);
    customView.setImageBitmap(bitmap);
}

// 点击按钮绘制时使用保存的原始Bitmap
public void onBtnClick(View view){
    if (mOriginalBitmap == null) return;
    
    ZoomageView customView = findViewById(R.id.myZoomageView);
    Bitmap tempBitmap = mOriginalBitmap.copy(Bitmap.Config.RGB_565, true);
    Canvas tempCanvas = new Canvas(tempBitmap);
    
    Paint p = new Paint();
    p.setStrokeWidth(50);
    p.setColor(Color.RED);
    tempCanvas.drawLine(0, 0, mOriginalBitmap.getWidth(), mOriginalBitmap.getHeight(), p);
    
    customView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));
}
额外注意事项
  • 若需要根据屏幕上的触摸位置绘制线条,需要将ZoomageView的屏幕坐标转换为原始Bitmap的坐标:利用ZoomageView的变换矩阵,调用Matrix.invert()计算逆矩阵,将屏幕点映射到原始Bitmap的坐标系中。
  • 操作Bitmap后及时回收不再使用的实例,避免OOM问题。

内容的提问来源于stack exchange,提问作者Yaman Saran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:47:34