linux下把yuyv422格式的圖片轉換爲pnm格式的圖片

平臺: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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章