2011-08-09 35 views
0

我試圖寫一個YUV422到RGB24轉換器,但轉換後的數據的結果似乎很奇怪。 結果是一個紫色觸摸灰度圖片與一些淺綠色的點... 有沒有人有想法?轉換YUV422到RGB24

inline void convert_yuv442_2_rgb24(const unsigned char* source, unsigned char* destination, unsigned long width, unsigned long height) 
{ 
    unsigned char data[3]; 
    for(unsigned long i = 0, c = 0; i < width * height * 2; i += 2, c += 3) 
    { 
     // 16Bit YUV422 -> 24Bit YUV 
     data[0] = source[i+0]; 
     data[1] = (source[i+1] & 0xF0) >> 4; 
     data[2] = (source[i+1] & 0X0F); 

// YUV-> RGB24 
//destination[c + 0] = (float) (1.164f*(data[0] - 16) + 1.596f*(data[2] - 128)); 
//destination[c + 1] = (float) (1.164f*(data[0] - 16) - 0.813f*(data[2] - 128) - 0.391f*(data[1] - 128)); 
//destination[c + 2] = (float) (1.164f*(data[0] - 16)       + 2.018f*(data[1] - 128)); 

     destination[c + 0] = (float) data[0] + (float) data[2]/0.877F; 
     destination[c + 2] = (float) data[0] + (float) data[1]/0.493f; 
     destination[c + 1] = (float) 1.7f * (float) data[0] - 0.509f * destination[c + 0] - 0.194f*(float)destination[c + 2]; 

    } 
} 

我試着用給定的提示成功oneone。 轉換器代碼來自這裏:http://paulbourke.net/dataformats/yuv/

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/ioctl.h> 
#include <libv4l1.h> 
#include <libv4l2.h> 
#include <linux/videodev.h> 

int init_webcam(int *fd, struct video_window *web_win, long *length); 

struct RGB 
{ 
    unsigned char r, g, b; 
}; 

RGB convert(int y, int u, int v) 
{ 
    RGB rgb; 
    u -= 128; 
    v -= 128; 

    rgb.r = y + 1.370705 * v; 
    rgb.g = y - 0.698001 * v - 0.337633 * u; 
    rgb.b = y + 1.732446 * u; 


    if (rgb.r < 0) rgb.r = 0; 
    if (rgb.g < 0) rgb.g = 0; 
    if (rgb.b < 0) rgb.b = 0; 
    if (rgb.r > 255) rgb.r = 255; 
    if (rgb.g > 255) rgb.g = 255; 
    if (rgb.b > 255) rgb.b = 255; 

    return rgb; 
} 

void YUV422_2_RGB24(unsigned char* yuv, RGB* p1, RGB* p2) 
{ 
// int u = yuv[0]; 
// int y1 = yuv[1]; 
// int v = yuv[2]; 
// int y2 = yuv[3]; 

    int y1 = yuv[0]; 
    int u = yuv[1]; 
    int y2 = yuv[2]; 
    int v = yuv[3]; 

    *p1 = convert(y1, u, v); 
    *p2 = convert(y2, u, v); 
} 


int main() 
{ 
    struct video_window web_win; 
    int fd; 
    long length; 

    if(!init_webcam(&fd, &web_win, &length)) 
     return 1; 


    // Bild aufnehmen 
    unsigned char* picture = new unsigned char[web_win.width * web_win.height * 2]; 
    unsigned char* image = new unsigned char[web_win.width * web_win.height * 3]; 

    if(v4l1_read(fd, picture, web_win.width * web_win.height * 2) == -1) 
    { 
     printf("Error while reading webcam\n"); 
     return 0; 
    } 

    // Bild speichern 
    FILE *imagefile; 

    if((imagefile = fopen("bild.ppm", "w+b")) == NULL) 
    { 
      printf("Couldn't open file for writing\n"); 
      return 0; 
    } 

    RGB p1, p2; 
    for(unsigned long i = 0, c = 0; i < web_win.width * web_win.height * 2; i += 4, c += 6) 
    { 
     YUV422_2_RGB24(&picture[i], &p1, &p2); 
     image[c + 0] = p1.r; 
     image[c + 1] = p1.g; 
     image[c + 2] = p1.b; 

     image[c + 3] = p2.r; 
     image[c + 4] = p2.g; 
     image[c + 5] = p2.b; 
    } 

    fprintf(imagefile, "P6\n%d %d\n255\n", web_win.width, web_win.height); 

    for(unsigned long i = 0; i < web_win.width * web_win.height; ++ i) 
    { 
      fwrite((unsigned char*) &image[i * 3], 1, 3, imagefile); 
    } 

    fclose(imagefile); 

    delete[] picture; 
    delete[] image; 



    v4l1_close(fd); 
    return 0; 
} 

int init_webcam(int *fd, struct video_window *web_win, long *length) 
{ 
    struct video_capability web_cap; 
    struct video_picture web_pict; 

    if((*fd = v4l1_open("/dev/video0", O_RDONLY)) == -1)/*Open webcam device*/ 
    { 
     printf("Unable to open webcam devide\n"); 
     return 0; 
    } 

    if(v4l1_ioctl(*fd, VIDIOCGPICT, &web_pict) == -1)/*This function call isn't necessary but otherwise you won't get a proper picture*/ 
    { 
     printf("Unable to get picture information\n"); 
     return 0; 
    } 

    if (ioctl (*fd, VIDIOCGPICT, &web_pict) != -1) 
    {  // successfully retrieved the default image properties 

      // the following values are for requesting 8bit grayscale 
      //web_pict.depth = 16; 
      web_pict.palette = VIDEO_PALETTE_YUV422; 
      if (ioctl (*fd, VIDIOCSPICT, &web_pict) == -1) 
      { 
       printf("failed to set the image properties\n"); 
       //return 0; 
      } 
    } 

    if(ioctl(*fd, VIDIOCGCAP, &web_cap) == -1)/*Get video capabilities*/ 
    { 
     printf("Unable to get capabilities\n"); 
     return 0; 
    } 

    if(v4l1_ioctl(*fd, VIDIOCGWIN, web_win) == -1)/*Get video information*/ 
    { 
     printf("Unable to get video information\n"); 
     return 0; 
    } 
    web_win->width = web_cap.maxwidth;/*Try to write max solution*/ 
    web_win->height = web_cap.maxheight; 
    if(v4l1_ioctl(*fd, VIDIOCSWIN, web_win) == -1)/*Write new(?!) video information*/ 
    { 
     printf("Unable to write video information\n"); 
     return -1; 
    } 
    if(v4l1_ioctl(*fd, VIDIOCGWIN, web_win) == -1)/*Read new(?!) video information*/ 
    { 
     printf("Unable to get video information\n"); 
     return 0; 
    } 

    *length = web_win->width * web_win->height * (web_pict.depth/8); 

    printf("bits per pixel: %d\n", web_pict.depth); 
    printf("palette:  %d\n", web_pict.palette); 

    return 1; 
} 
+0

422意味着8位正確嗎?你的代碼看起來像是試圖處理844個數據。此外,Y通道通常是有偏見的。你看過[維基百科](http://en.wikipedia.org/wiki/YUV#Y.27UV422)條目嗎? – user786653

+0

Y422使用宏像素來壓縮U和V,看起來並不像你正在處理的那樣。 –

回答