1111#define WIDTH 640
1212#define HEIGHT 480
1313#define NUM_BUFFERS 4
14+ #define OUTPUT_WIDTH 240
15+ #define OUTPUT_HEIGHT 240
1416
1517// Global variables
1618int fd = -1 ;
1719struct v4l2_buffer buf ;
1820void * buffers [NUM_BUFFERS ];
1921size_t buffer_length ;
2022
21- // Convert YUYV to RGB for PPM output
22- void yuyv_to_rgb (unsigned char * yuyv , unsigned char * rgb , int width , int height ) {
23- for (int i = 0 ; i < width * height ; i ++ ) {
24- int index = i * 2 ;
25- int y = yuyv [index ];
26- int u = yuyv [index + 1 ];
27- int v = yuyv [index + 3 ];
28-
29- int r = y + (1.402 * (v - 128 ));
30- int g = y - (0.344 * (u - 128 )) - (0.714 * (v - 128 ));
31- int b = y + (1.772 * (u - 128 ));
32-
33- r = r < 0 ? 0 : (r > 255 ? 255 : r );
34- g = g < 0 ? 0 : (g > 255 ? 255 : g );
35- b = b < 0 ? 0 : (b > 255 ? 255 : b );
36-
37- rgb [i * 3 + 0 ] = r ;
38- rgb [i * 3 + 1 ] = g ;
39- rgb [i * 3 + 2 ] = b ;
23+ // Convert YUYV to grayscale and downscale to 240x240
24+ void yuyv_to_grayscale_240x240 (unsigned char * yuyv , unsigned char * gray , int in_width , int in_height ) {
25+ // Downscale factors
26+ float x_ratio = (float )in_width / OUTPUT_WIDTH ;
27+ float y_ratio = (float )in_height / OUTPUT_HEIGHT ;
28+
29+ for (int y = 0 ; y < OUTPUT_HEIGHT ; y ++ ) {
30+ for (int x = 0 ; x < OUTPUT_WIDTH ; x ++ ) {
31+ // Nearest-neighbor interpolation
32+ int src_x = (int )(x * x_ratio );
33+ int src_y = (int )(y * y_ratio );
34+ int src_index = (src_y * in_width + src_x ) * 2 ; // YUYV: 2 bytes per pixel
35+ gray [y * OUTPUT_WIDTH + x ] = yuyv [src_index ]; // Use Y component for grayscale
36+ }
4037 }
4138}
4239
43- // Save frame as PPM
44- void save_ppm (const char * filename , unsigned char * data , int width , int height ) {
40+ // Save grayscale frame as .raw
41+ void save_raw (const char * filename , unsigned char * data , int width , int height ) {
4542 FILE * fp = fopen (filename , "wb" );
4643 if (!fp ) {
4744 perror ("Cannot open file" );
4845 return ;
4946 }
50- fprintf (fp , "P6\n%d %d\n255\n" , width , height );
51- unsigned char * rgb = malloc (width * height * 3 );
52- yuyv_to_rgb (data , rgb , width , height );
53- fwrite (rgb , 1 , width * height * 3 , fp );
47+ fwrite (data , 1 , width * height , fp ); // Write raw grayscale data
5448 fclose (fp );
55- free (rgb );
5649}
5750
5851int init_webcam (const char * device ) {
@@ -158,8 +151,11 @@ int capture_frame(char *filename) {
158151 return -1 ;
159152 }
160153
161- // Save frame
162- save_ppm (filename , buffers [buf .index ], WIDTH , HEIGHT );
154+ // Convert and save frame
155+ unsigned char * gray = malloc (OUTPUT_WIDTH * OUTPUT_HEIGHT );
156+ yuyv_to_grayscale_240x240 (buffers [buf .index ], gray , WIDTH , HEIGHT );
157+ save_raw (filename , gray , OUTPUT_WIDTH , OUTPUT_HEIGHT );
158+ free (gray );
163159
164160 // Requeue buffer
165161 if (ioctl (fd , VIDIOC_QBUF , & buf ) < 0 ) {
@@ -173,7 +169,7 @@ int capture_frame(char *filename) {
173169int capture_frames (int n ) {
174170 for (int i = 0 ; i < n ; i ++ ) {
175171 char filename [32 ];
176- snprintf (filename , sizeof (filename ), "frame_%03d.ppm " , i );
172+ snprintf (filename , sizeof (filename ), "frame_%03d.raw " , i );
177173 if (capture_frame (filename ) < 0 ) {
178174 printf ("Failed to capture frame %d\n" , i );
179175 return -1 ;
0 commit comments