RGBA位图存单像素需3×3数组原因及规避;Android 1×1图转Bitmap变3×3问题
嘿,这俩问题其实都是Android图形加载和OpenCV转换里的常见坑,我给你拆解清楚:
问题1:为什么会出现“RGBA位图用3×3数组存1个像素”的情况,怎么避免?
首先得澄清:这不是RGBA位图本身的要求,核心原因是Android的Drawable密度自动缩放机制。
背后的逻辑:
Android为了让低分辨率的图片在高DPI屏幕上显示清晰,会根据设备屏幕密度和图片所在资源目录的基准密度,自动缩放Drawable的尺寸。比如:
- 你把1×1的图片放在默认的
drawable目录(对应mdpi,基准密度160dpi) - 如果你的设备是xxhdpi(密度480dpi,是mdpi的3倍)
- 系统就会自动把这个Drawable放大3倍,变成3×3的Bitmap——看起来就像是“用3×3数组存了原本1个像素的内容”。
避免方法:
- 把图片放到
drawable-nodpi目录:这个目录下的图片不会被系统根据密度缩放,完全保持原始尺寸。 - 加载时手动禁用缩放:用
BitmapFactory.Options关闭自动缩放:BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; // 禁用密度缩放 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_image, options); - 指定密度加载:用
Resources.getDrawableForDensity(),传入和图片基准密度一致的参数,跳过缩放逻辑。
问题2:1×1红色JPG转Bitmap变成3×3,OpenCV矩阵异常的解决办法
这个问题其实就是上面说的密度缩放导致的,一步一步解决:
第一步:先拿到真正的1×1 Bitmap
按照问题1里的方法,比如把图片移到drawable-nodpi,或者用inScaled=false加载,这时候调用bitmap.getWidth()和getHeight()就会返回1、1了。
第二步:解决OpenCV矩阵的异常情况
你看到的Mat [ 1*1*CV_64FC1, ...和Mat [ 3*3*CV_8UC4, ...差异,是因为:
- 前者可能是你误把缩放前的原始尺寸(或者错误转换的单通道数据)当成了结果;
- 后者是缩放后的3×3 RGBA Bitmap转成的Mat(CV_8UC4对应8位4通道)。
正确的转换步骤:
- 把1×1的ARGB Bitmap转成OpenCV Mat:
Mat rgbaMat = new Mat(); Utils.bitmapToMat(bitmap, rgbaMat); // 此时Mat是1×1×CV_8UC4格式 - 灰度化处理:
这时候Mat grayMat = new Mat(); Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY);grayMat就是你预期的1×1×CV_8UC1格式,转字符串输出也会显示正确的尺寸。
额外注意点:
- JPG本身不支持透明通道,但Android加载后默认会转成ARGB_8888格式的Bitmap,所以转成OpenCV Mat是CV_8UC4是正常的;
- 如果你需要直接加载成单通道灰度图,可以在Bitmap加载后先转灰度,或者用OpenCV直接解码图片(跳过Android的Bitmap转换):
这样得到的就是1×1×CV_8UC1的Mat,一步到位。Mat mat = Imgcodecs.imread("/path/to/your/red_1x1.jpg", Imgcodecs.IMREAD_GRAYSCALE);
内容的提问来源于stack exchange,提问作者Lobstw
相关产品推荐
相关产品推荐

