안녕하세요 V4L를 가지고 머좀 만들어볼려는 학생입니다.
이렇게 처음으로 질문을 드리네요 ^^

EZ-X5보드와 로직텍 퀵캠 4000에 장비를 가지고
V4L로 "file.bmp"란 파일을 생성하는 프로그램을 만들었습니다.
그런데 사진이 이상하게 깨져서 나오더군요.(아마설정을 잘못해준거 같은데...)

QT를 이용한 camstream을 이용하면 영상이 깨끗하게 나옵니다.
밑에는 재가 코딩한 프로그램입니다.

또 한가지만 더 물어볼께요
프레임버퍼로 그림을 출력시키는 방법을 잘모르겠습니다.
인터넷에서 많은 자료를 찻았는데
저의 머리가 돌머리인지 이해가 잘 안되더라고요 -_ㅜ

도와주세요ㅡㅜ

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/ioctl.h>
                                                                                
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <getopt.h>

#include <linux/types.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/mman.h>
#include <linux/videodev.h>

#define SERVO_LEFT        1
#define SERVO_RIGHT        2
#define SERVO_MIDDLE        3

#define Dev_Name        "dev/Cam_Stream_Module"

static int Timer = 0;
static int Servo = 0;
static int frames2 = 0;
static int frame_number = 0;

//extern int frame_number2;

struct picbuf
{
        char *data;
};

typedef struct camera
{
        int dev;
        int x;
        int y;
        int dither;
        int contrast, brightness, colour, hug;
        struct video_capability         vid_cap;
        struct video_picture                vid_pic;
        struct video_channel                vid_chnl;
        struct video_window                vid_win;
        struct video_mbuf                vid_buf;
        struct video_mmap                vid_map[2];
        char video_dev[256];
        char *pic;
        char *image;
        char *ppmfile;
        struct picbuf pic_buf[2];
}cam;

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

typedef struct lcd_frmae_buffer
{
        int dev;
        char lcd_dev[256];
        struct fb_var_screeninfo        fbvar;
        struct bgrpixel                 pixel;
        int x;
        int y;
        int bp;
        int byte_total;
        unsigned short *vbase;
}lcd;

int video_open(lcd *lcd)
{
        if(ioctl(lcd->dev, FBIOGET_VSCREENINFO, &lcd->fbvar) < 0)
        {
                printf("fbvar open failn");
                return 0;
        }
        if(lcd -> fbvar.bits_per_pixel != 16)
        {
                printf("bpp is not 16n");
                exit(0);
        }
        lcd -> x = lcd -> fbvar.xres;
        lcd -> y = lcd -> fbvar.yres;
        lcd -> bp = lcd -> fbvar.bits_per_pixel;
        lcd -> byte_total = (lcd->x * lcd->y * (lcd->bp/8));
        lcd -> vbase = (unsigned short *) mmap(0, lcd->byte_total, PROT_READ | PROT_WRITE, MAP_SHARED, lcd->dev, 0);
        if((unsigned)lcd->vbase == (unsigned)-1)
        {
                printf("Lcd MMAP FAILn");
                exit(0);
        }

        return 0;
}

static unsigned short makepixel(lcd *lcd, unsigned char r, unsigned char g, unsigned char b)
{
        unsigned short rnew, gnew, bnew;
        
        rnew = r >> (8 - (lcd->fbvar.red.length));
        gnew = g >> (8 - (lcd->fbvar.green.length));
        bnew = b >> (8 - (lcd->fbvar.blue.length));
        
        return (unsigned short) ((rnew << lcd->fbvar.red.offset)
                | (gnew << lcd->fbvar.green.offset)
                | (bnew << lcd->fbvar.blue.offset));
}

void screen(lcd *lcd,cam *cam)
{
        int x, y;
        
        for(x = 0; x <= cam->x ; x ++)
        {
                for(y = 0; y <= cam->y ; y++)
                {
                        lcd->pixel.r = 10;
                        lcd->pixel.g = 10;
                        lcd->pixel.b = 10;
                        *(lcd->vbase + x *lcd->fbvar.xres+y) = makepixel(&lcd->fbvar, lcd->pixel.r, lcd->pixel.g, lcd->pixel.b);
                }
        }
}

void draw(int x, int y, unsigned short color,lcd *lcd)
{
        unsigned short *ptr;
        ptr = lcd->vbase + ((y * lcd->x) + x);
        *ptr = color;
}

int ppm_save(cam *cam)
{
        FILE *fp;
        int fc;
        
        printf("Capturing...n");
        fp = fopen(cam->ppmfile, "w");
        if(fp == NULL)
        {
                printf("OPEN FAIL FOR WIRTING...n");
                return -1;
        }
        fprintf(fp, "P6n%d %dn%dn",cam->x,cam->y,255);
        fc = fwrite(cam->pic_buf[frame_number].data, 1, cam->vid_buf.size, fp);
        fclose(fp);
        return 0;
}        

void camera_cap(cam *cam)
{
        if(ioctl(cam->dev, VIDIOCGCAP, &cam->vid_cap) == -1)
        {
                printf("Camera Capabilities OPEN FAIL, EXIT...n");
                exit(0);
        }
        if(cam -> vid_cap.maxwidth < cam -> x)
        {
                cam->x = cam->vid_cap.maxwidth;
        }
        if(cam -> vid_cap.minwidth > cam -> x)
        {
                cam->x = cam->vid_cap.minwidth;
        }
        if(cam -> vid_cap.maxheight < cam -> y)
        {
                cam->y = cam->vid_cap.maxheight;
        }
        if(cam -> vid_cap.minheight > cam -> y)
        {
                cam->y = cam->vid_cap.minheight;
        }
}

void set_pic_info(cam *cam)
{
        if(ioctl(cam->dev, VIDIOCSPICT, &cam->vid_pic) == -1)
        {
                printf("VIDEO PICTURE OPEN FILE EXIT.....n");
                exit(0);        
        }
}

void get_pic_info(cam *cam)
{
        if(ioctl(cam->dev, VIDIOCSPICT, &cam->vid_pic) == -1)
        {
                printf("VIDEO GET PICTURE OPEN FAIL EXIT.....n");
                exit(0);
        }
}

void get_win_info(cam *cam)
{
        if(ioctl(cam->dev, VIDIOCSWIN, &cam->vid_win) == -1)
        {
                printf("VIDEO GET WINDOW OPEN FAIL EXIT.....n");
                exit(0);
        }
}

void set_win_info(cam *cam)
{
        if(ioctl(cam->dev, VIDIOCSWIN, &cam->vid_win) == -1)
        {
                printf("VIDEO SET WINDOW OPEN FAIL EXIT.....n");
                exit(0);
        }
}

void set_buffer(cam *cam)
{
        if(ioctl(cam->dev, VIDIOCGMBUF, &cam->vid_buf) == -1)
        {
                printf("BUFFER SET FAIL EXIT.....n");
                exit(0);
        }
}


void dev_open(void)
{
        Servo = open(Dev_Name, O_RDWR | O_NOCTTY);        
        Timer = open("dev_timer", O_RDWR | O_NOCTTY);
        
        if(Servo < 0)
        {
                printf("%s OPEN FAIL.....n",Dev_Name);
                exit(0);
        }
        printf("Servo OPEN SUCCESS.....n");
        if(Timer < 0)
        {
                printf("Timer OPEN Fail [dev/timer]nn");
                exit(1);
        }
        printf("Timer OPENn");
}

void init_cam(cam *cam)
{
        cam->pic = mmap(0,cam->vid_buf.size,PROT_READ | PROT_WRITE,MAP_SHARED, cam->dev,0);
        cam->vid_map[0].height = cam->y;
        cam->vid_map[0].width = cam->x;
        cam->vid_map[0].frame = 0;
        cam->vid_map[0].format = cam->vid_pic.palette;
        cam->pic_buf[0].data = cam->pic;
        cam->vid_map[1].height = cam->y;
        cam->vid_map[1].width = cam->x;
        cam->vid_map[1].frame = 1;
        cam->vid_map[1].format = cam->vid_pic.palette;
        cam->pic_buf[1].data = cam->pic + cam->vid_buf.offsets[1];
        
        if((unsigned char*) -1 == (unsigned char *) cam->pic)
        {
                printf("MMAP FAILEDn");
                exit(-1);
        }
        if(ioctl(cam->dev, VIDIOCMCAPTURE, cam->vid_map) == -1)
        {
                printf("100n");
        }
        if(ioctl(cam->dev, VIDIOCSYNC, cam->vid_map) == -1)
        {
                printf("1000n");
        }
}

void frameloop(cam *cam)
{
        int ctl = 0;
        ctl = ioctl(cam->dev, VIDIOCMCAPTURE, cam->vid_map + frame_number);

        if(ctl == -1)
        {
                printf("CAPTURE FROM DEVICE OPEN FAIL.....n");
                exit(-1);
        }
        frames2++;
        ctl = ioctl(cam->dev, VIDIOCSYNC, cam->vid_map + frame_number);

        if(ctl == -1)
        {
                printf("VIDIOCSYNC FAILED.....n");
                munmap(cam->vid_map, cam->vid_buf.size);
                exit(-1);
        }
}

int main(int argc,char **argv)
{
        //int one = 1;
        //int done = 0;
        
        cam cam;
        lcd lcd;
        
        cam.x = 320;
        cam.y = 240;

        strcpy(lcd.lcd_dev, "/dev/fb0");
        strcpy(cam.video_dev, "/dev/video0");

        cam.dither = 128;
        
        lcd.dev = open(lcd.lcd_dev, O_RDWR);
        cam.dev = open(cam.video_dev, O_RDWR);
        
        cam.image = malloc(cam.x * cam.y * 3);
//        cam.vid_buf.size = cam.x * cam.y * 3;

        video_open(&lcd);
        camera_cap(&cam);

        if(ioctl(cam.dev, VIDIOCSCHAN, cam.vid_chnl) == -1);

        cam.vid_pic.palette = VIDEO_PALETTE_RGB24;
        cam.vid_win.x = 0;
        cam.vid_win.y = 0;
        cam.vid_win.width = cam.x;
        cam.vid_win.height = cam.y;

        cam.ppmfile = "file.bmp";
                
        set_pic_info(&cam);

        cam.contrast = cam.vid_pic.contrast * 256;
        cam.brightness = cam.vid_pic.brightness * 256;
        cam.colour = cam.vid_pic.colour * 256;
        cam.hug = cam.vid_pic.hue * 256;

        set_win_info(&cam);
        
        set_buffer(&cam);
        init_cam(&cam);
        //dev_open();

        while(1)
        {
                frameloop(&cam);
                ppm_save(&cam);
        }
        return 0;
}