Public feed #531311

Something

public text v1 · immutable
Raw Edit
·published 2007-06-02 13:06 UTC
rendered paste body

void write_pixel32(FILE *f, uint32_t pixel32, rgb_map_t map)
{
  unsigned char *pixels = (unsigned char *)&pixel32;
  if(!f) return;
  fputc(pixels[map.r], f);
  fputc(pixels[map.g], f);
  fputc(pixels[map.b], f);
}


uint32_t yuv2rgb(int y, int u, int v)
{
   uint32_t pixel32;
   unsigned char *pixel = (unsigned char *)&pixel32;
   int r, g, b;
   
   /*
     Another formula I found:  (seems to work)
     
     R = Y + 1.370705 (V-128)
     G = Y - 0.698001 (V-128) - 0.337633 (U-128)
     B = Y + 1.732446 (U-128)
   */
   
   r = (int) y + (1.370705 * (v-128));
   g = (int)  y - (0.698001 * (v-128)) - (0.337633 * (u-128));
   b = (int)  y + (1.732446 * (u-128));

   /* Even with proper conversion, some values still need clipping. */
   if (r > 255) r = 255;
   if (g > 255) g = 255;
   if (b > 255) b = 255;
   if (r < 0) r = 0;
   if (g < 0) g = 0;
   if (b < 0) b = 0;

   /* Values only go from 0-220..  Why? */
   pixel[0] = r * 220 / 256;
   pixel[1] = g * 220 / 256;
   pixel[2] = b * 220 / 256;
   pixel[3] = 0;

   /* Debug
   printf("yuv2rgb(%i, %i, %i) -> %i, %i, %i  (0x%x)\n",
	  y, u, v,
	  pixel[0], pixel[1], pixel[2],
	  pixel32);
   */
   
   return pixel32;
}


void yuv420p_to_ppm(FILE * fpin, FILE * fpout)
{
	uint32_t pixel32;
	unsigned char *buffer, *src;
	int depth = 24;
	int y=0, u=0, v=0;
	int i=0;
	rgb_map_t rgb_map = { 0, 1, 2 };
	rewind(fpout);
	struct timeval tvstart;
	struct timeval tvfinish;
  
	gettimeofday(&tvstart, NULL); 
	
	buffer = (unsigned char *) malloc((g_win.width * g_win.height * depth));

	// This should go into another function
	i = 0;
	size_t bytesread;
	
	read(g_fdin, buffer, g_win.width * g_win.height * depth);
        gettimeofday(&tvfinish, NULL); 
        fprintf(stderr, "capture in:%ld ms\n", (tvfinish.tv_usec - tvstart.tv_usec)/1000);
	
	
	src = buffer;
	
	fprintf(fpout, "P6\n%d %d 255\n", g_win.width, g_win.height);
	
	for (i = 0; i < g_win.width * g_win.height; i++) 
	{
		if(i == 0) 
		{
			src = buffer + (g_win.width*g_win.height);

		}
		y = buffer[i];
		u = src[(i/2)%(g_win.width/2)];
		v = src[(g_win.width*g_win.height)/4 + (i/2)%(g_win.width/2)];
		if(i && (i%(g_win.width*4)) == 0) 
		{
			src += g_win.width;

		}
		pixel32 = yuv2rgb(y, u, v);
		write_pixel32(fpout, pixel32, rgb_map);
	}

	free(buffer);
	rewind(fpout);
        gettimeofday(&tvfinish, NULL); 
        //fprintf(stderr, "conversion in:%ld ms\n", (tvfinish.tv_usec - tvstart.tv_usec)/1000);
	
	
}