如何从ImageProxy创建BinaryBitmap?CameraX转ZXing遇数组越界
解决CameraX ImageProxy转ZXing BinaryBitmap的数组越界问题
你当前代码的核心错误是把JPEG压缩后的字节数组传给了需要原始YUV数据的PlanarYUVLuminanceSource,两者数据格式和长度不匹配,直接触发数组越界异常。以下是正确的转换方案:
错误原因拆解
PlanarYUVLuminanceSource要求输入的是未压缩的YUV格式中Y通道的原始字节数据,而你通过ImageUtil.yuvImageToJpegByteArray得到的是压缩后的JPEG数据,数据长度、结构完全不符合要求,必然导致越界。
修正后的代码实现
第一步:提取并处理Y通道数据(处理stride步长)
CameraX返回的ImageProxy的Y平面存在stride(行字节数)可能大于图像宽度的情况,需要提取每行的有效数据:
private fun getYPlaneData(imageProxy: ImageProxy): ByteArray { val yPlane = imageProxy.planes[0] val yBuffer = yPlane.buffer val ySize = yBuffer.remaining() val yData = ByteArray(ySize) yBuffer.get(yData) val stride = yPlane.rowStride val width = imageProxy.width val height = imageProxy.height // 步长等于宽度时直接返回,否则提取有效数据 if (stride == width) { return yData } val correctedData = ByteArray(width * height) var inputIndex = 0 var outputIndex = 0 for (i in 0 until height) { System.arraycopy(yData, inputIndex, correctedData, outputIndex, width) inputIndex += stride outputIndex += width } return correctedData }
第二步:创建正确的BinaryBitmap
同时处理图像旋转(CameraX预览时常见的方向问题):
private fun createBinaryBitmap(imageProxy: ImageProxy): BinaryBitmap { val yData = getYPlaneData(imageProxy) val rotationDegrees = imageProxy.imageInfo.rotationDegrees // 根据旋转角度调整宽高 val (targetWidth, targetHeight) = if (rotationDegrees == 90 || rotationDegrees == 270) { imageProxy.height to imageProxy.width } else { imageProxy.width to imageProxy.height } val source = PlanarYUVLuminanceSource( yData, targetWidth, targetHeight, 0, 0, targetWidth, targetHeight, false ) return BinaryBitmap(HybridBinarizer(source)) }
额外注意事项
- 用完ImageProxy后必须调用
imageProxy.close(),避免内存泄漏 - 如果需要指定扫描区域,调整
PlanarYUVLuminanceSource的裁剪参数(x、y起点和宽高),确保参数不超出图像范围 - 若解码仍有问题,可以尝试调整Binarizer类型(比如替换为
GlobalHistogramBinarizer)
内容的提问来源于stack exchange,提问作者Elyes Mansour
相关产品推荐
相关产品推荐

