#include "display.h" SDL_Surface *SDLVideo = NULL; static int SDL_BPP = 0; static int SDL_Width = 0; static int SDL_Height = 0; struct gstruct { int active; unsigned int *map; double gamma; double gain; int brightness; int src_bpp; }; #define MAX_PROPERTIES 10 static struct gstruct PropList[MAX_PROPERTIES]; static void GetXvInfo(xvinfo_t *xvinfo); static void ByteSwap(unsigned char *data, int nbytes); static unsigned int * GetPropertyMap(int p, int src_bpp); static unsigned int * CreatePropertyMap_16bpp_565(int p); static unsigned int * CreatePropertyMap_16bpp_888(int p); static int _SDLDisplay_8bpp(struct Image *img, unsigned int *map, int x_off, int y_off); static int _SDLDisplay_16bpp(struct Image *img, unsigned int *map, int x_off, int y_off); static int _SDLDisplay_24bpp(struct Image *img, unsigned int *map, int x_off, int y_off); void Message(char *str) { fprintf(stderr,"%s\n",str); } void FatalError(char *str) { Message(str); exit(1); } // Create a "property", ie a collection of display parameters to be applied to // an image int CreateProperty(int brightness, double gain, double gamma) { int i; for(i=0; i= MAX_PROPERTIES) return; PropList[i].gain = 1.0; PropList[i].gamma = 1.0; if (PropList[i].map) free(PropList[i].map); PropList[i].map = NULL; PropList[i].src_bpp = 0; PropList[i].active = 0; } // Generate a lookup table that will convert image values of the designated src_bpp into pixels // taking into account the property adjustments static unsigned int * GetPropertyMap(int p, int src_bpp) { // Has someone already generated the map ? if (PropList[p].map != NULL && PropList[p].src_bpp == src_bpp) return PropList[p].map; // Otherwise create a lookup table that maps image pixels + display properties // onto screen pixels. switch (src_bpp) { case 16: if (SDL_BPP==16) return CreatePropertyMap_16bpp_565(p); if (SDL_BPP==32) return CreatePropertyMap_16bpp_888(p); printf("Unknown SDL_BPP %d\n",SDL_BPP); exit(1); break; default: printf("unknown or not supported src_bpp %d\n",src_bpp); exit(1); break; } printf("GetPropertyMap: don't support bpp=%d and SDL_BPP=%d\n",PropList[p].src_bpp,SDL_BPP); exit(1); return NULL; } /* * create a lookup table that maps a value (multiplied by gain) to 565 */ static unsigned int * CreatePropertyMap_16bpp_565(int p) { int i; int brightness = PropList[p].brightness; double gain = PropList[p].gain; double gamma = PropList[p].gamma; unsigned int *map; if (PropList[p].map == NULL) PropList[p].map = (unsigned int *)Malloc(65536 * 4); map = PropList[p].map; for(i=0; i<65536; ++i) { int n = i * gain + brightness; if (n>65535) n = 65535; if (n<0) n=0; unsigned int v = (unsigned int) (pow((double)n / 65535.0, 1.0/gamma) * 65535); if (v>65535) v=65535; if (v<0) v=0; // convert to 5-6-5 format map[i] = (v&0xf800) | ((v&0xfc00)>>5) | (v>>11); } PropList[p].src_bpp = 16; return map; } static unsigned int * CreatePropertyMap_16bpp_888(int p) { int i; int brightness = PropList[p].brightness; double gain = PropList[p].gain; double gamma = PropList[p].gamma; unsigned int *map; if (PropList[p].map == NULL) PropList[p].map = (unsigned int *)Malloc(65536 * 4); map = PropList[p].map; for(i=0; i<65536; ++i) { int n = i * gain + brightness; if (n>65535) n = 65535; if (n<0) n=0; unsigned int v = (unsigned int) (pow((double)n / 65535.0, 1.0/gamma) * 65535); if (v>65535) v=65535; if (v<0) v=0; v >>= 8; // convert to 5-6-5 format map[i] = v | (v<<8) | (v<<16); } PropList[p].src_bpp = 16; return map; } int InitProperties() { int i; for(i=0; imax_height=-1; xvinfo->max_width=-1; if(!(xvinfo->dpy = XOpenDisplay(NULL))) { FatalError("Unable to open display"); return; } if((Success != XvQueryExtension(xvinfo->dpy, &ver, &rev, &reqB, &eventB, &errorB))) { //Message("xvinfo: No X-Video Extension"); return; } i=0; // 0: we use only the first screen XvQueryAdaptors(xvinfo->dpy, RootWindow(xvinfo->dpy, i), &xvinfo->nadaptors, &xvinfo->ainfo); if( !xvinfo->nadaptors || !xvinfo->ainfo ){ //Message( "xvinfo: No adpators present\n" ); return; } j=0; // 0: we use only the first adaptor XvQueryEncodings(xvinfo->dpy, xvinfo->ainfo[j].base_id, &xvinfo->nencode, &xvinfo->encodings); if(xvinfo->encodings && xvinfo->nencode) { xvinfo->ImageEncodings = 0; for(n = 0; n < xvinfo->nencode; n++) { if(!strcmp(xvinfo->encodings[n].name, "XV_IMAGE")) xvinfo->ImageEncodings++; } if(xvinfo->ImageEncodings && (xvinfo->ainfo[j].type & XvImageMask)) { //char imageName[5] = {0, 0, 0, 0, 0}; for(n = 0; n < xvinfo->nencode; n++) { if(!strcmp(xvinfo->encodings[n].name, "XV_IMAGE")) { //fprintf(stdout, "maximum XvImage size: %li x %li\n", xvinfo->encodings[n].width, xvinfo->encodings[n].height); xvinfo->max_height=(int)xvinfo->encodings[n].height; xvinfo->max_width=(int)xvinfo->encodings[n].width; break; } } /* formats = XvListImageFormats(dpy, ainfo[j].base_id, &numImages); fprintf(stdout, " Number of image formats: %i\n", numImages); for(n = 0; n < numImages; n++) { memcpy(imageName, &(formats[n].id), 4); fprintf(stdout, " id: 0x%x", formats[n].id); if(isprint(imageName[0]) && isprint(imageName[1]) && isprint(imageName[2]) && isprint(imageName[3])) { fprintf(stdout, " (%s)\n", imageName); } else { fprintf(stdout, "\n"); } fprintf(stdout, " bits per pixel: %i\n", formats[n].bits_per_pixel); fprintf(stdout, " number of planes: %i\n", formats[n].num_planes); fprintf(stdout, " type: %s (%s)\n", (formats[n].type == XvRGB) ? "RGB" : "YUV", (formats[n].format == XvPacked) ? "packed" : "planar"); if(formats[n].type == XvRGB) { fprintf(stdout, " depth: %i\n", formats[n].depth); fprintf(stdout, " red, green, blue masks: 0x%x, 0x%x, 0x%x\n", formats[n].red_mask, formats[n].green_mask, formats[n].blue_mask); } } if(formats) XFree(formats); */ } XvFreeEncodingInfo(xvinfo->encodings); } XvFreeAdaptorInfo(xvinfo->ainfo); #else xvinfo->max_height=-1; xvinfo->max_width=-1; #endif //fprintf(stderr,"%d %d\n", xvinfo->max_height, xvinfo->max_width); } void ShutdownDisplay() { SDL_Quit(); } // Display an image, format can be: 8bpp mono, 16bpp mono, 24bpp colour // p is a property index // (x_off,y_off) is the origin of the image // return 1 for success, 0 on error int DisplayImage(struct Image *img, int p, int x_off,int y_off) { unsigned int *map; int rval; if (! (map = GetPropertyMap(p,img->depth))) { printf("DisplayImage: cannot get property map\n"); return 0; } switch(img->depth) { case 8: rval= _SDLDisplay_8bpp(img,map,x_off,y_off); break; case 16: rval= _SDLDisplay_16bpp(img,map,x_off,y_off); break; case 24: rval= _SDLDisplay_24bpp(img,map,x_off,y_off); break; default: printf("DisplayImage: unknown image depth %d\n",img->depth); exit(1); break; } return rval; } // display an image using a lookup table to convert src values into pixels // assuming a 8bpp monochrome src image static int _SDLDisplay_8bpp(struct Image *img, unsigned int *map, int x_off, int y_off) { unsigned char *data = (unsigned char *)img->data; int x,y,x1,y1,x2,y2; int W,width = img->width; int H,height = img->height; const SDL_PixelFormat *f = SDLVideo->format; int bpp = f->BytesPerPixel; // may be displaying a subregion x1 = img->cutout.x1; y1 = img->cutout.y1; x2 = img->cutout.x2; y2 = img->cutout.y2; if (x1<0) x1=0; if (x2>=width) x2=width-1; if (y1<0) y1=0; if (y2>= height) y2=height-1; W = x2-x1+1; // dimensions of region we are transferring H = y2-y1+1; SDL_LockSurface(SDLVideo); for(y=y1; y<=y2; ++y) { register unsigned char *sptr = data + y * width + x1; if (SDL_BPP == 16) { register unsigned short *dst = (unsigned short *)((Uint8 *)SDLVideo->pixels + (y_off+y-y1) * SDLVideo->pitch + x_off * bpp); for(x=0; xpixels + (y_off+y-y1) * SDLVideo->pitch + x_off * bpp); for(x=0; xdata; int x,y,x1,y1,x2,y2; int W,width = img->width; int H,height = img->height; const SDL_PixelFormat *f = SDLVideo->format; int bpp = f->BytesPerPixel; // may be displaying a subregion x1 = img->cutout.x1; y1 = img->cutout.y1; x2 = img->cutout.x2; y2 = img->cutout.y2; if (x1<0) x1=0; if (x2>=width) x2=width-1; if (y1<0) y1=0; if (y2>= height) y2=height-1; W = x2-x1+1; // dimensions of region we are transferring H = y2-y1+1; //printf("DisplayImage: SDL_BPP=%d, bpp=%d, (%d,%d) - (%d,%d) [%d,%d] w=%d h=%d\n",SDL_BPP,bpp,x1,y1,x2,y2,x_off,y_off,W,H); //fflush(stdout); SDL_LockSurface(SDLVideo); for(y=y1; y<=y2; ++y) { register unsigned short *sptr = data + y * width + x1; if (SDL_BPP == 16) { register unsigned short *dst = (unsigned short *)((Uint8 *)SDLVideo->pixels + (y_off+y-y1) * SDLVideo->pitch + x_off * bpp); for(x=0; xpixels + (y_off+y-y1) * SDLVideo->pitch + x_off * bpp); for(x=0; xdata; int x,y,x1,y1,x2,y2; int W,width = img->width; int H,height = img->height; const SDL_PixelFormat *f = SDLVideo->format; int bpp = f->BytesPerPixel; // may be displaying a subregion x1 = img->cutout.x1; y1 = img->cutout.y1; x2 = img->cutout.x2; y2 = img->cutout.y2; if (x1<0) x1=0; if (x2>=width) x2=width-1; if (y1<0) y1=0; if (y2>= height) y2=height-1; W = x2-x1+1; // dimensions of region we are transferring H = y2-y1+1; SDL_LockSurface(SDLVideo); for(y=y1; y<=y2; ++y) { register unsigned char *sptr = data + (y * width + x1) * 3; if (SDL_BPP == 16) { register unsigned short *dst = (unsigned short *)((Uint8 *)SDLVideo->pixels + (y_off+y-y1) * SDLVideo->pitch + x_off * bpp); for(x=0; xpixels + (y_off+y-y1) * SDLVideo->pitch + x_off * bpp); for(x=0; x