我写了一个从YUV_420_888到Bitmap的转换,考虑到以下逻辑(据我所知):
总结该方法:内核的坐标x和y与Y平面(2d分配)的非填充部分的x和y以及输出位图的x和y都是一致的.然而,U平面和V平面具有与Y平面不同的结构,因为它们使用1个字节覆盖4个像素,此外,可能具有多于一个的PixelStride,此外它们可能也有一个可以与Y平面不同的填充.因此,为了通过内核有效地访问U和V,我将它们放入1-d分配并创建索引"uvIndex",该索引给出了在给定的1-d分配中相应的U-和V的位置( x,y)坐标(非填充)Y平面(以及输出位图).
为了保持rs-Kernel的精简,我通过LaunchOptions限制x范围来排除yPlane中的填充区域(这反映了y平面的RowStride,因此可以在内核中忽略).所以我们只需要考虑uvIndex中的uvPixelStride和uvRowStride,即用于访问u值和v值的索引.
这是我的代码:
Renderscript内核,名为yuv420888.rs
#pragma version(1)
#pragma rs java_package_name(com.xxxyyy.testcamera2);
#pragma rs_fp_relaxed
int32_t width;
int32_t height;
uint picWidth, uvPixelStride, uvRowStride ;
rs_allocation ypsIn,uIn,vIn;
// The LaunchOptions ensure that the Kernel does not enter the padding zone of Y, so yRowStride can be ignored WITHIN the Kernel.
uchar4 __attribute__((kernel)) doConvert(uint32_t x, uint32_t y) {
// index for accessing the uIn's and vIn's
uint uvIndex= uvPixelStride * (x/2) + uvRowStride*(y/2);
// get the y,u,v values
uchar yps= rsGetElementAt_uchar(ypsIn, x, y);
uchar …Run Code Online (Sandbox Code Playgroud) 我正在编写一个应用摄像头的应用程序,将其转换为rgb,以便进行一些处理.
它适用于使用NV21 Yuv格式的旧相机实现.我遇到的问题是使用新的Yuv格式YUV_420_888.在新的Camera2 Api中,图像不再正确转换为RGB,后者发送YUV_420_888 yuv格式而不是NV21(YUV_420_SP)格式.
有人可以告诉我如何将YUV_420_888转换为RGB?
谢谢
我正在尝试使用这里提出的camera2 api实现相机预览图像数据处理:使用Android L和Camera2 API进行相机预览图像数据处理.
我使用onImageAvailableListener成功接收回调,但是为了将来的处理,我需要从YUV_420_888 android.media.Image获取位图.我搜索了类似的问题,但没有一个帮助.
你能否建议我如何将android.media.Image(YUV_420_888)转换为Bitmap,或者有更好的方法来监听预览帧?
我尝试将图像从YUV_420_888转换为rgb,我对输出图像有些麻烦.在ImageReader中,我以YUV_420_888格式获取图像(使用相机2 api获取此图像预览).
imageReader = ImageReader.newInstance(1920,1080,ImageFormat.YUV_420_888,10);
Run Code Online (Sandbox Code Playgroud)
在android sdk中为YuvImage类编写,即YuvImage仅使用NV21,YUY2.
因为我们可以看到N21和yuv420之间的差异不大,我尝试将数据转换为N21
在onImageAvailable中我单独获得每个Planes并将它们放在正确的位置(如图像所示)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteBuffer bufferY = image.getPlanes()[0].getBuffer();
byte[] data0 = new byte[bufferY.remaining()];
bufferY.get(data0);
ByteBuffer bufferU = image.getPlanes()[1].getBuffer();
byte[] data1 = new byte[bufferU.remaining()];
bufferU.get(data1);
ByteBuffer bufferV = image.getPlanes()[2].getBuffer();
byte[] data2 = new byte[bufferV.remaining()];
bufferV.get(data2);
...
outputStream.write(data0);
for (int i=0;i<bufferV.remaining();i++) {
outputStream.write(data1[i]);
outputStream.write(data2[i]);
}
Run Code Online (Sandbox Code Playgroud)
创建YuvImage后,转换为Bitmap,查看并保存
final YuvImage yuvImage = new YuvImage(outputStream.toByteArray(), ImageFormat.NV21, 1920,1080, null);
ByteArrayOutputStream outBitmap = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0,1920, 1080), 95, outBitmap);
byte[] …Run Code Online (Sandbox Code Playgroud) 对于视频图像处理项目,我必须旋转传入的 YUV 图像数据,以便数据不是水平显示而是垂直显示。我使用了这个项目,它让我深入了解了如何将 YUV 图像数据转换为 ARGB 以实时处理它们。该项目的唯一缺点是它仅在景观中。没有纵向模式选项(我不知道为什么 Google 的人提供了一个仅处理横向的示例示例)。我想改变这一点。
因此,我决定使用自定义的 YUV 转 RGB 脚本来旋转数据,使其以纵向模式显示。以下 GIF 演示了应用程序如何在我应用任何旋转之前显示数据。
你必须知道,在 Android 中,即使设备处于纵向模式,YUV 图像数据也会以横向呈现(我在开始这个项目之前不知道。同样,我不明白为什么没有可用的方法可用于通过一次调用来旋转帧)。这意味着即使设备处于纵向模式,起点也在左下角。但是在纵向模式下,每一帧的起点应该在左上角。我对字段使用矩阵表示法(例如 (0,0)、(0,1) 等)。注意:我从这里拿了草图:

要旋转横向框架,我们必须重新组织字段。这是我对草图(见上文)所做的映射,它显示了yuv_420横向模式下的单个帧。映射应将框架旋转 90 度:
first column starting from the bottom-left corner and going upwards:
(0,0) -> (0,5) // (0,0) should be at (0,5)
(0,1) -> (1,5) // (0,1) should be at (1,5)
(0,2) -> (2,5) // and so on ..
(0,3) -> (3,5)
(0,4) -> (4,5)
(0,5) -> (5,5)
2nd column starting at …Run Code Online (Sandbox Code Playgroud)