最近在做录像的项目,通过bitmap.copyPixelsToBuffer老是出现java.lang.RuntimeException: Buffer not large enough for pixels的错误。查找了一下原因。
Android Bitmap's format and IplImage's format matching is very important.
JavaCV处理图像格式多为IplImage格式,而Android程序里的ImageView组件无法直接显示IplImage格式图像,所以需要转化格式。通过将图片像素载入buffer的方式,实现将Bitmap格式图片转换为IplImage格式图片。建立4通道IplImage图像对应Bitmap数据格式为ARGB_8888;建立2通道IplImage图像对应Bitmap数据格式为RGB_565。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout layout = (LinearLayout)findViewById(R.id.root);
ImageView image = new ImageView(this);
layout.addView(image);
Bitmap bitmapIn = BitmapFactory.decodeResource(getResources(), R.drawable.abc);
IplImage newin = IplImage.create(bitmapIn.getWidth(), bitmapIn.getHeight(), IPL_DEPTH_8U, 4);
bitmapIn.copyPixelsToBuffer(newin.getByteBuffer());
cvFlip(newin, newout, 0);//图像旋转
IplImage newout = IplImage.create(bitmapIn.getWidth(), bitmapIn.getHeight(),IPL_DEPTH_8U, 4);
Bitmap bitmapOut = Bitmap.createBitmap(bitmapIn.getWidth(), bitmapIn.getHeight(), Bitmap.Config.ARGB_8888);
bitmapOut.copyPixelsFromBuffer(newout.getByteBuffer());
image.setImageBitmap(bitmapOut);
}
IplImage image = IplImage.create(width, height, IPL_DEPTH_8U, 4);IplImage _3image = IplImage.create(width, height, IPL_DEPTH_8U, 3);IplImage _1image = IplImage.create(width, height, IPL_DEPTH_8U, 1);Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);1. iplimage -> bitmapbitmap.copyPixelsFromBuffer(image.getByteBuffer());2. bitmap -> iplimagebitmap.copyPixelsToBuffer(image.getByteBuffer());3. iplimage(4channel) -> iplimage(3channel or 1channel)cvCvtColor(image, _3image, CV_BGRA2BGR);cvCvtColor(_3image, _1image, CV_RGB2GRAY);-----------------------------------------------------------------------------------Create iplimage from Android's camera byte[] dataprivate IplImage _4iplToBitmap;_4iplToBitmap = IplImage.create(width, height, IPL_DEPTH_8U, 4);int [] _temp = new int[width*height];if(_4iplToBitmap!= null){ decodeYUV420SP(_temp, data, width, height); _4iplToBitmap.getIntBuffer().put(_temp);}protected void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { int frameSize = width * height; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; rgb[yp] = 0xff000000 | ((b << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((r >> 10) & 0xff); } }}