二、YUV420图像的水平拼接

概述

为了更加理解yuv,下面以YUV420图像作为例子,记录一下进行水平拼接的思路和实现

YUV420

YUV是一种原始图像格式,没有经过编码,比较方便软件处理。本文处理的图像格式为YUV420,图像数据中的亮度Y和色度UV分离,并在内存中连续存储,按照YUYV的方式进行存储。比如一张 4 × 2 图像,以YUV420sp的格式存储就是:Y1Y2Y3Y4Y5Y6Y7Y8U1V1U2V2,所占的内存空间为:width * height * 3 / 2(同理,YUV422所占的内存空间为:width * height * 2)

水平拼接

相较于垂直拼接,水平拼接稍微复杂一些,需要对图像的每一行进行处理。需要将两幅图对应行的Y连接在一起组成新的Y行,对应行的UV连接在一起组成新的UV行,再把新的UV连接到Y后面。用图片描述如下:
水平拼接YUV

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	FILE *file = NULL;
	FILE *yuv1 = NULL;
	FILE *yuv2 = NULL;

	int imgWidth = 1920;
	int imgHeight = 1080;
	int i = 0;

	char filename[64] = {0};
	snprintf(filename, sizeof(filename), "/out.yuv");

	//拼接后的yuv文件
	file = fopen(filename, "w+");
	if (NULL == file)
		return -1;
	
	//拼接前的yuv图像1
	yuv1 = fopen("/yuv001.yuv", "r");
	if (NULL == yuv1)
		return -1;
	
	//拼接前的yuv图像2
	yuv2 = fopen("/yuv002.yuv", "r");
	if (NULL == yuv1)
		return -1;

	char *imgY1, *imgY2;

	//开辟内存
	imgY1 = (char *)malloc(imgWidth * imgHeight * 3 / 2);		//yuv420
	if(NULL == imgY1)
		return -1;
	
	imgY2 = (char *)malloc(imgWidth * imgHeight * 3 /2);		//yuv420
	if(NULL == imgY1)
		return -1;

	//读取拼接前的两张yuv图像数据
	if((imgWidth * imgHeight *3 / 2) != fread(imgY1, 1, imgWidth * imgHeight * 3 / 2, yuv1))
		return -1;
	
	if((imgWidth * imgHeight *3 / 2) != fread(imgY2, 1, imgWidth * imgHeight * 3 / 2, yuv2))
		return -1;

	//水平拼接yuv420
	for (i = 0; i < imgHeight; i++)
	{
		fwrite(imgY1, 1, imgWidth*3/2, file);
		fwrite(imgY2, 1, imgWidth*3/2, file);
		imgY1 += imgWidth*3/2;
		imgY2 += imgWidth*3/2;
	}

	return 0;
}

结果

使用两张1920 * 1080 的YUV图像进行了测试,可以实现水平拼接,也可以多次拼接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript中使用Canvas绘制YUV420图像是一个相对复杂的任务,因为Canvas默认使用RGB颜色模式而不是YUV。你需要进行一些额外的步骤来将YUV420数据转换为RGB,并将其绘制到Canvas上。 下面是一个基本的示例代码,用于展示如何使用Canvas绘制YUV420图像: ```html <!DOCTYPE html> <html> <head> <title>Canvas YUV420</title> </head> <body> <canvas id="myCanvas" width="400" height="300"></canvas> <script> // 获取Canvas元素 var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); // 获取YUV420图像的Y、U、V分量数据(假设已经获取到了) // 假设Y分量数据为yData,U分量数据为uData,V分量数据为vData // 创建一个ImageData对象用于存储RGB数据 var imageData = ctx.createImageData(canvas.width, canvas.height); var data = imageData.data; // YUV420转RGB函数 function yuv420ToRgb(y, u, v) { var r, g, b; // YUV到RGB转换公式 r = y + 1.402 * (v - 128); g = y - 0.344136 * (u - 128) - 0.714136 * (v - 128); b = y + 1.772 * (u - 128); // 将RGB值限制在0到255之间 r = Math.max(0, Math.min(255, r)); g = Math.max(0, Math.min(255, g)); b = Math.max(0, Math.min(255, b)); return [r, g, b]; } // 遍历每个像素 for (var i = 0; i < canvas.width * canvas.height; i++) { var y = yData[i]; var u = uData[Math.floor(i / 4)]; var v = vData[Math.floor(i / 4)]; // 转换YUV到RGB var rgb = yuv420ToRgb(y, u, v); // 填充RGB值到ImageData var dataIndex = i * 4; data[dataIndex] = rgb[0]; // 红色通道 data[dataIndex + 1] = rgb[1]; // 绿色通道 data[dataIndex + 2] = rgb[2]; // 蓝色通道 data[dataIndex + 3] = 255; // 不透明度 } // 将ImageData对象绘制到Canvas上 ctx.putImageData(imageData, 0, 0); </script> </body> </html> ``` 在上面的示例中,我们假设已经获取到了YUV420图像的Y、U、V分量数据,并创建了一个ImageData对象来存储RGB数据。然后,我们使用一个yuv420ToRgb函数将YUV数据转换为RGB,并将转换后的RGB值填充到ImageData对象中。最后,我们使用putImageData方法将ImageData对象绘制到Canvas上。 请注意,上述示例是一个简化的版本,并未考虑YUV420图像的具体格式和数据排列。在实际应用中,你可能需要根据实际情况进行适当的解析和处理。此外,由于JavaScript是单线程的,处理大量像素数据可能会导致性能问题,你可能需要考虑使用Web Worker或其他优化技术来提高性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值