平臺:Linux
/****************************************************************************
* 文件名:Yuyv422ToPnm.c
* 文件描述:把yuyv422格式的圖片轉換爲pnm格式的圖片,需要提供yuv422源文件名
* yuv圖片的寬,yuv圖片的高以及需要轉換的pnm圖片名稱
* 編寫人:王廷雲
* 編寫日期:2017-12-1
* 修改日期:2018-1-1
****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> // 下面四個頭文件是linux系統編程特有的
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <linux/videodev2.h> // 操作攝像頭設備
#define CLAMP(v) ((v<0?0:(v>255?255:v))) // 鉗制像素值的範圍
int main(int argc, char **argv)
{
int width; // yuv圖片的寬
int height; // yuv圖片的高
/* 參數檢查是否足夠*/
if (argc != 5)
{
/* yuv圖片名 yuv圖片的寬,yuv圖片的高,pnm圖片名稱 */
printf("Usage: [%s] [srcName] [width] [height] [destName]\n", argv[0]);
return -1;
}
/* 打開yuyv文件:用open是因爲後面的內存映射要的是文件描述符 */
int fin = open(argv[1], O_RDONLY);
if (-1 == fin)
{
perror("open");
return -2;
}
/* 獲取yuv圖片信息 */
struct stat st_buf;
fstat(fin, &st_buf); // 用於獲取圖片大小
sscanf(argv[2], "%d", &width); // 獲取圖片寬度
sscanf(argv[3], "%d", &height); // 獲取圖片高度
/* 把文件進行內存映射:加快操作速度(此步驟可以不用) */
unsigned char *yuyv;
yuyv = mmap(NULL, st_buf.st_size, PROT_READ, MAP_SHARED, fin, 0);
if (MAP_FAILED == yuyv)
{
perror("mmap");
return -2;
}
/* 進行數據轉換並保存到文件中去 */
FILE *fout = fopen(argv[4], "w");
if (NULL == fout)
{
perror("fopen");
return -3;
}
unsigned char *p = yuyv;
unsigned char y0, y1, u0, v1;
unsigned char rgb[3];
int x, y;
/* 寫pnm文件頭 */
fprintf(fout, "P6\n%d %d\n255\n", width, height);
/* 把yuv數據轉換爲rgb數據並寫入pnm文件中 */
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x += 2) // 兩個像素一起寫
{
/* 讀2個yuv422像素:共4個字節 yu yv */
y0 = *p++;
u0 = *p++;
y1 = *p++;
v1 = *p++;
/* 轉換爲2個rgb像素:共6個字節rgb rgb */
rgb[0] = CLAMP(y0 + 1.402 * (v1 - 128));
rgb[1] = CLAMP(y0 - 0.344 * (u0 - 128) - 0.714 * (v1 - 128));
rgb[2] = CLAMP(y0 + 1.772 * (u0 - 128));
fwrite(rgb, 1, 3, fout); // 寫第一個rgb像素
rgb[0] = CLAMP(y1 + 1.402 * (v1 - 128));
rgb[1] = CLAMP(y1 - 0.344 * (u0 - 128) - 0.714 * (v1 - 128));
rgb[2] = CLAMP(y1 + 1.772 * (u0 - 128));
fwrite(rgb, 1, 3, fout); // 寫第二個rgb像素
}
}
/* 尾部處理工作 */
munmap(yuyv, st_buf.st_size); // 解除內存映射
close(fin); // 關閉已打開的文件
fclose(fout);
return 0;
}