test/testoverlay.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 20 Jan 2003 01:36:28 +0000
changeset 569 e8063c656626
parent 277 255c7ee077cb
child 603 2e726be3dc08
permissions -rw-r--r--
Date: Thu, 16 Jan 2003 13:48:31 +0200
From: "Mike Gorchak"

added help and options -mono to force monochrome RGB2YUB conversion and
-lum <percent> - luminance of image during conversion. Also rewritten code
which moves overlay into window. Now it depends on window size.
Also fully rewritten -scale option, image now scaling from 50% from center
of screen until border of window is reached - it really tests scaler, old
-scale test doesn't test downscale.
     1 
     2 /* Bring up a window and play with it */
     3 
     4 #include <stdlib.h>
     5 #include <stdio.h>
     6 #include <string.h>
     7 
     8 #define BENCHMARK_SDL
     9 
    10 #define NOTICE(X)	printf("%s", X);
    11 
    12 #define WINDOW_WIDTH  640
    13 #define WINDOW_HEIGHT 480
    14 
    15 #include "SDL.h"
    16 
    17 SDL_Surface *screen, *pic;
    18 SDL_Overlay *overlay;
    19 int scale;
    20 int monochrome;
    21 int luminance;
    22 int w, h;
    23 
    24 /* NOTE: These RGB conversion functions are not intended for speed,
    25          only as examples.
    26 */
    27 
    28 void RGBtoYUV(Uint8 *rgb, int *yuv, int monochrome, int luminance)
    29 {
    30     int i;
    31 
    32     if (monochrome)
    33     {
    34 #if 1 /* these are the two formulas that I found on the FourCC site... */
    35         yuv[0] = 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
    36         yuv[1] = 128;
    37         yuv[2] = 128;
    38 #else
    39         yuv[0] = (0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16;
    40         yuv[1] = 128;
    41         yuv[2] = 128;
    42 #endif
    43     }
    44     else
    45     {
    46 #if 1 /* these are the two formulas that I found on the FourCC site... */
    47         yuv[0] = 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
    48         yuv[1] = (rgb[2]-yuv[0])*0.565 + 128;
    49         yuv[2] = (rgb[0]-yuv[0])*0.713 + 128;
    50 #else
    51         yuv[0] = (0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16;
    52         yuv[1] = 128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2]);
    53         yuv[2] = 128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2]);
    54 #endif
    55     }
    56 
    57     if (luminance!=100)
    58     {
    59         yuv[0]=yuv[0]*luminance/100;
    60         if (yuv[0]>255)
    61             yuv[0]=255;
    62     }
    63 
    64     /* clamp values...if you need to, we don't seem to have a need */
    65     /*
    66     for(i=0;i<3;i++)
    67     {
    68         if(yuv[i]<0)
    69             yuv[i]=0;
    70         if(yuv[i]>255)
    71             yuv[i]=255;
    72     }
    73     */
    74 }
    75 
    76 ConvertRGBtoYV12(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
    77 {
    78 	int x,y;
    79 	int yuv[3];
    80 	Uint8 *p,*op[3];
    81 
    82 	SDL_LockSurface(s);
    83 	SDL_LockYUVOverlay(o);
    84 
    85 	/* Black initialization */
    86 	/*
    87 	memset(o->pixels[0],0,o->pitches[0]*o->h);
    88 	memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
    89 	memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
    90 	*/
    91 
    92 	/* Convert */
    93 	for(y=0; y<s->h && y<o->h; y++)
    94 	{
    95 		p=s->pixels+s->pitch*y;
    96 		op[0]=o->pixels[0]+o->pitches[0]*y;
    97 		op[1]=o->pixels[1]+o->pitches[1]*(y/2);
    98 		op[2]=o->pixels[2]+o->pitches[2]*(y/2);
    99 		for(x=0; x<s->w && x<o->w; x++)
   100 		{
   101 			RGBtoYUV(p, yuv, monochrome, luminance);
   102 			*(op[0]++)=yuv[0];
   103 			if(x%2==0 && y%2==0)
   104 			{
   105 				*(op[1]++)=yuv[2];
   106 				*(op[2]++)=yuv[1];
   107 			}
   108 			p+=s->format->BytesPerPixel;
   109 		}
   110 	}
   111 
   112 	SDL_UnlockYUVOverlay(o);
   113 	SDL_UnlockSurface(s);
   114 }
   115 
   116 ConvertRGBtoIYUV(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
   117 {
   118 	int x,y;
   119 	int yuv[3];
   120 	Uint8 *p,*op[3];
   121 
   122 	SDL_LockSurface(s);
   123 	SDL_LockYUVOverlay(o);
   124 
   125 	/* Black initialization */
   126 	/*
   127 	memset(o->pixels[0],0,o->pitches[0]*o->h);
   128 	memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
   129 	memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
   130 	*/
   131 
   132 	/* Convert */
   133 	for(y=0; y<s->h && y<o->h; y++)
   134 	{
   135 		p=s->pixels+s->pitch*y;
   136 		op[0]=o->pixels[0]+o->pitches[0]*y;
   137 		op[1]=o->pixels[1]+o->pitches[1]*(y/2);
   138 		op[2]=o->pixels[2]+o->pitches[2]*(y/2);
   139 		for(x=0; x<s->w && x<o->w; x++)
   140 		{
   141 			RGBtoYUV(p,yuv, monochrome, luminance);
   142 			*(op[0]++)=yuv[0];
   143 			if(x%2==0 && y%2==0)
   144 			{
   145 				*(op[1]++)=yuv[1];
   146 				*(op[2]++)=yuv[2];
   147 			}
   148 			p+=s->format->BytesPerPixel;
   149 		}
   150 	}
   151 
   152 	SDL_UnlockYUVOverlay(o);
   153 	SDL_UnlockSurface(s);
   154 }
   155 
   156 ConvertRGBtoUYVY(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
   157 {
   158 	int x,y;
   159 	int yuv[3];
   160 	Uint8 *p,*op;
   161 
   162 	SDL_LockSurface(s);
   163 	SDL_LockYUVOverlay(o);
   164 
   165 	for(y=0; y<s->h && y<o->h; y++)
   166 	{
   167 		p=s->pixels+s->pitch*y;
   168 		op=o->pixels[0]+o->pitches[0]*y;
   169 		for(x=0; x<s->w && x<o->w; x++)
   170 		{
   171 			RGBtoYUV(p, yuv, monochrome, luminance);
   172 			if(x%2==0)
   173 			{
   174 				*(op++)=yuv[1];
   175 				*(op++)=yuv[0];
   176 				*(op++)=yuv[2];
   177 			}
   178 			else
   179 				*(op++)=yuv[0];
   180 
   181 			p+=s->format->BytesPerPixel;
   182 		}
   183 	}
   184 
   185 	SDL_UnlockYUVOverlay(o);
   186 	SDL_UnlockSurface(s);
   187 }
   188 
   189 ConvertRGBtoYVYU(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
   190 {
   191 	int x,y;
   192 	int yuv[3];
   193 	Uint8 *p,*op;
   194 
   195 	SDL_LockSurface(s);
   196 	SDL_LockYUVOverlay(o);
   197 
   198 	for(y=0; y<s->h && y<o->h; y++)
   199 	{
   200 		p=s->pixels+s->pitch*y;
   201 		op=o->pixels[0]+o->pitches[0]*y;
   202 		for(x=0; x<s->w && x<o->w; x++)
   203 		{
   204 			RGBtoYUV(p,yuv, monochrome, luminance);
   205 			if(x%2==0)
   206 			{
   207 				*(op++)=yuv[0];
   208 				*(op++)=yuv[2];
   209 				op[1]=yuv[1];
   210 			}
   211 			else
   212 			{
   213 				*op=yuv[0];
   214 				op+=2;
   215 			}
   216 
   217 			p+=s->format->BytesPerPixel;
   218 		}
   219 	}
   220 
   221 	SDL_UnlockYUVOverlay(o);
   222 	SDL_UnlockSurface(s);
   223 }
   224 
   225 ConvertRGBtoYUY2(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
   226 {
   227 	int x,y;
   228 	int yuv[3];
   229 	Uint8 *p,*op;
   230 
   231 	SDL_LockSurface(s);
   232 	SDL_LockYUVOverlay(o);
   233 
   234 	for(y=0; y<s->h && y<o->h; y++)
   235 	{
   236 		p=s->pixels+s->pitch*y;
   237 		op=o->pixels[0]+o->pitches[0]*y;
   238 		for(x=0; x<s->w && x<o->w; x++)
   239 		{
   240 			RGBtoYUV(p,yuv, monochrome, luminance);
   241 			if(x%2==0)
   242 			{
   243 				*(op++)=yuv[0];
   244 				*(op++)=yuv[1];
   245 				op[1]=yuv[2];
   246 			}
   247 			else
   248 			{
   249 				*op=yuv[0];
   250 				op+=2;
   251 			}
   252 
   253 			p+=s->format->BytesPerPixel;
   254 		}
   255 	}
   256 
   257 	SDL_UnlockYUVOverlay(o);
   258 	SDL_UnlockSurface(s);
   259 }
   260 
   261 void Draw()
   262 {
   263 	SDL_Rect rect;
   264 	int i;
   265         int disp;
   266 
   267 	if(!scale)
   268 	{
   269 		rect.w=overlay->w;
   270 		rect.h=overlay->h;
   271 		for(i=0; i<h-rect.h && i<w-rect.w; i++)
   272 		{
   273 			rect.x=i;
   274 			rect.y=i;
   275 			SDL_DisplayYUVOverlay(overlay,&rect);
   276 		}
   277 	}
   278 	else
   279 	{
   280 		rect.w=overlay->w/2;
   281 		rect.h=overlay->h/2;
   282 		rect.x=(w-rect.w)/2;
   283 		rect.y=(h-rect.h)/2;
   284                 disp=rect.y-1;
   285 		for(i=0; i<disp; i++)
   286 		{
   287                         rect.w+=2;
   288                         rect.h+=2;
   289                         rect.x--;
   290                         rect.y--;
   291 			SDL_DisplayYUVOverlay(overlay,&rect);
   292 		}
   293 	}
   294 	printf("Displayed %d times.\n",i);
   295 }
   296 
   297 static void PrintUsage(char *argv0)
   298 {
   299 	fprintf(stderr, "Usage: %s [arg] [arg] [arg] ...\n", argv0);
   300 	fprintf(stderr, "Where 'arg' is one of:\n");
   301 	fprintf(stderr, "	-delay <seconds>\n");
   302 	fprintf(stderr, "	-width <pixels>\n");
   303 	fprintf(stderr, "	-height <pixels>\n");
   304 	fprintf(stderr, "	-bpp <bits>\n");
   305 	fprintf(stderr, "	-format <fmt> (one of the: YV12, IYUV, YUY2, UYVY, YVYU)\n");
   306 	fprintf(stderr, "	-hw\n");
   307 	fprintf(stderr, "	-flip\n");
   308 	fprintf(stderr, "	-scale (test scaling features, from 50%% upto window size)\n");
   309 	fprintf(stderr, "	-mono (use monochromatic RGB2YUV conversion)\n");
   310 	fprintf(stderr, "	-lum <perc> (use luminance correction during RGB2YUV conversion,\n");
   311 	fprintf(stderr, "	             from 0%% to unlimited, normal is 100%%)\n");
   312 	fprintf(stderr, "	-help (shows this help)\n");
   313 	fprintf(stderr, "	-fullscreen (test overlay in fullscreen mode)\n");
   314 }
   315 
   316 int main(int argc, char **argv)
   317 {
   318 	int flip;
   319 	int delay;
   320 	int desired_bpp;
   321 	Uint32 video_flags, overlay_format;
   322 	char *bmpfile;
   323 #ifdef BENCHMARK_SDL
   324 	Uint32 then, now;
   325 #endif
   326 	int i;
   327 
   328 	/* Set default options and check command-line */
   329 	flip = 0;
   330 	scale=0;
   331         monochrome=0;
   332         luminance=100;
   333 	delay = 1;
   334 	w = WINDOW_WIDTH;
   335 	h = WINDOW_HEIGHT;
   336 	desired_bpp = 0;
   337 	video_flags = 0;
   338 	overlay_format = SDL_YV12_OVERLAY;
   339 
   340 	while ( argc > 1 ) {
   341 		if ( strcmp(argv[1], "-delay") == 0 ) {
   342 			if ( argv[2] ) {
   343 				delay = atoi(argv[2]);
   344 				argv += 2;
   345 				argc -= 2;
   346 			} else {
   347 				fprintf(stderr,
   348 				"The -delay option requires an argument\n");
   349 				exit(1);
   350 			}
   351 		} else
   352 		if ( strcmp(argv[1], "-width") == 0 ) {
   353 			if ( argv[2] && ((w = atoi(argv[2])) > 0) ) {
   354 				argv += 2;
   355 				argc -= 2;
   356 			} else {
   357 				fprintf(stderr,
   358 				"The -width option requires an argument\n");
   359 				exit(1);
   360 			}
   361 		} else
   362 		if ( strcmp(argv[1], "-height") == 0 ) {
   363 			if ( argv[2] && ((h = atoi(argv[2])) > 0) ) {
   364 				argv += 2;
   365 				argc -= 2;
   366 			} else {
   367 				fprintf(stderr,
   368 				"The -height option requires an argument\n");
   369 				exit(1);
   370 			}
   371 		} else
   372 		if ( strcmp(argv[1], "-bpp") == 0 ) {
   373 			if ( argv[2] ) {
   374 				desired_bpp = atoi(argv[2]);
   375 				argv += 2;
   376 				argc -= 2;
   377 			} else {
   378 				fprintf(stderr,
   379 				"The -bpp option requires an argument\n");
   380 				exit(1);
   381 			}
   382 		} else
   383 		if ( strcmp(argv[1], "-lum") == 0 ) {
   384 			if ( argv[2] ) {
   385 				luminance = atoi(argv[2]);
   386 				argv += 2;
   387 				argc -= 2;
   388 			} else {
   389 				fprintf(stderr,
   390 				"The -lum option requires an argument\n");
   391 				exit(1);
   392 			}
   393 		} else
   394 		if ( strcmp(argv[1], "-format") == 0 ) {
   395 			if ( argv[2] ) {
   396 				if(!strcmp(argv[2],"YV12"))
   397 					overlay_format = SDL_YV12_OVERLAY;
   398 				else if(!strcmp(argv[2],"IYUV"))
   399 					overlay_format = SDL_IYUV_OVERLAY;
   400 				else if(!strcmp(argv[2],"YUY2"))
   401 					overlay_format = SDL_YUY2_OVERLAY;
   402 				else if(!strcmp(argv[2],"UYVY"))
   403 					overlay_format = SDL_UYVY_OVERLAY;
   404 				else if(!strcmp(argv[2],"YVYU"))
   405 					overlay_format = SDL_YVYU_OVERLAY;
   406 				else
   407 				{
   408 					fprintf(stderr, "The -format option %s is not recognized\n",argv[2]);
   409 					exit(1);
   410 				}
   411 				argv += 2;
   412 				argc -= 2;
   413 			} else {
   414 				fprintf(stderr,
   415 				"The -format option requires an argument\n");
   416 				exit(1);
   417 			}
   418 		} else
   419 		if ( strcmp(argv[1], "-hw") == 0 ) {
   420 			video_flags |= SDL_HWSURFACE;
   421 			argv += 1;
   422 			argc -= 1;
   423 		} else
   424 		if ( strcmp(argv[1], "-flip") == 0 ) {
   425 			video_flags |= SDL_DOUBLEBUF;
   426 			argv += 1;
   427 			argc -= 1;
   428 		} else
   429 		if ( strcmp(argv[1], "-scale") == 0 ) {
   430 			scale = 1;
   431 			argv += 1;
   432 			argc -= 1;
   433 		} else
   434 		if ( strcmp(argv[1], "-mono") == 0 ) {
   435 			monochrome = 1;
   436 			argv += 1;
   437 			argc -= 1;
   438 		} else
   439 		if (( strcmp(argv[1], "-help") == 0 ) || (strcmp(argv[1], "-h") == 0)) {
   440                         PrintUsage(argv[0]);
   441                         exit(1);
   442 		} else
   443 		if ( strcmp(argv[1], "-fullscreen") == 0 ) {
   444 			video_flags |= SDL_FULLSCREEN;
   445 			argv += 1;
   446 			argc -= 1;
   447 		} else
   448 			break;
   449 	}
   450 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
   451 		fprintf(stderr,
   452 			"Couldn't initialize SDL: %s\n", SDL_GetError());
   453 		exit(1);
   454 	}
   455 	atexit(SDL_Quit);			/* Clean up on exit */
   456 
   457 	/* Initialize the display */
   458 	screen = SDL_SetVideoMode(w, h, desired_bpp, video_flags);
   459 	if ( screen == NULL ) {
   460 		fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
   461 					w, h, desired_bpp, SDL_GetError());
   462 		exit(1);
   463 	}
   464 	printf("Set%s %dx%dx%d mode\n",
   465 			screen->flags & SDL_FULLSCREEN ? " fullscreen" : "",
   466 			screen->w, screen->h, screen->format->BitsPerPixel);
   467 	printf("(video surface located in %s memory)\n",
   468 			(screen->flags&SDL_HWSURFACE) ? "video" : "system");
   469 	if ( screen->flags & SDL_DOUBLEBUF ) {
   470 		printf("Double-buffering enabled\n");
   471 		flip = 1;
   472 	}
   473 
   474 	/* Set the window manager title bar */
   475 	SDL_WM_SetCaption("SDL test overlay", "testoverlay");
   476 
   477 	/* Load picture */
   478 	bmpfile=(argv[1]?argv[1]:"sample.bmp");
   479 	pic = SDL_LoadBMP(bmpfile);
   480 	if ( pic == NULL ) {
   481 		fprintf(stderr, "Couldn't load %s: %s\n", bmpfile,
   482 							SDL_GetError());
   483 		exit(1);
   484 	}
   485 
   486 	/* Convert the picture to 32bits, for easy conversion */
   487 	{
   488 		SDL_Surface *newsurf;
   489 		SDL_PixelFormat format;
   490 
   491 		format.palette=NULL;
   492 		format.BitsPerPixel=32;
   493 		format.BytesPerPixel=4;
   494 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   495 		format.Rshift=0;
   496 		format.Gshift=8;
   497 		format.Bshift=16;
   498 #else
   499 		format.Rshift=24;
   500 		format.Gshift=16;
   501 		format.Bshift=8;
   502 #endif
   503 		format.Ashift=0;
   504 		format.Rmask=0xff<<format.Rshift;
   505 		format.Gmask=0xff<<format.Gshift;
   506 		format.Bmask=0xff<<format.Bshift;
   507 		format.Amask=0;
   508 		format.Rloss=0;
   509 		format.Gloss=0;
   510 		format.Bloss=0;
   511 		format.Aloss=8;
   512 		format.colorkey=0;
   513 		format.alpha=0;
   514 
   515 		newsurf=SDL_ConvertSurface(pic, &format, SDL_SWSURFACE);
   516 		if(!newsurf)
   517 		{
   518 			fprintf(stderr, "Couldn't convert picture to 32bits RGB: %s\n",
   519 							SDL_GetError());
   520 			exit(1);
   521 		}
   522 		SDL_FreeSurface(pic);
   523 		pic=newsurf;
   524 	}
   525 	
   526 	/* Create the overlay */
   527 	overlay = SDL_CreateYUVOverlay(pic->w, pic->h, overlay_format, screen);
   528 	if ( overlay == NULL ) {
   529 		fprintf(stderr, "Couldn't create overlay: %s\n", SDL_GetError());
   530 		exit(1);
   531 	}
   532 	printf("Created %dx%dx%d %s %s overlay\n",overlay->w,overlay->h,overlay->planes,
   533 			overlay->hw_overlay?"hardware":"software",
   534 			overlay->format==SDL_YV12_OVERLAY?"YV12":
   535 			overlay->format==SDL_IYUV_OVERLAY?"IYUV":
   536 			overlay->format==SDL_YUY2_OVERLAY?"YUY2":
   537 			overlay->format==SDL_UYVY_OVERLAY?"UYVY":
   538 			overlay->format==SDL_YVYU_OVERLAY?"YVYU":
   539 			"Unknown");
   540 	for(i=0; i<overlay->planes; i++)
   541 	{
   542 		printf("  plane %d: pitch=%d\n", i, overlay->pitches[i]);
   543 	}
   544 	
   545 	/* Convert to YUV, and draw to the overlay */
   546 #ifdef BENCHMARK_SDL
   547 	then = SDL_GetTicks();
   548 #endif
   549 	switch(overlay->format)
   550 	{
   551 		case SDL_YV12_OVERLAY:
   552 			ConvertRGBtoYV12(pic,overlay,monochrome,luminance);
   553 			break;
   554 		case SDL_UYVY_OVERLAY:
   555 			ConvertRGBtoUYVY(pic,overlay,monochrome,luminance);
   556 			break;
   557 		case SDL_YVYU_OVERLAY:
   558 			ConvertRGBtoYVYU(pic,overlay,monochrome,luminance);
   559 			break;
   560 		case SDL_YUY2_OVERLAY:
   561 			ConvertRGBtoYUY2(pic,overlay,monochrome,luminance);
   562 			break;
   563 		case SDL_IYUV_OVERLAY:
   564 			ConvertRGBtoIYUV(pic,overlay,monochrome,luminance);
   565 			break;
   566 		default:
   567 			printf("cannot convert RGB picture to obtained YUV format!\n");
   568 			exit(1);
   569 			break;
   570 	}
   571 #ifdef BENCHMARK_SDL
   572 	now = SDL_GetTicks();
   573 	printf("Conversion Time: %d milliseconds\n", now-then);
   574 #endif
   575 	
   576 	/* Do all the drawing work */
   577 #ifdef BENCHMARK_SDL
   578 	then = SDL_GetTicks();
   579 #endif
   580 	Draw();
   581 #ifdef BENCHMARK_SDL
   582 	now = SDL_GetTicks();
   583 	printf("Time: %d milliseconds\n", now-then);
   584 #endif
   585 	SDL_Delay(delay*1000);
   586 	return(0);
   587 }
   588