/* 520.643 Digital Multimedia Coding and Processing */ /* Prof. Trac D. Tran */ /* Department of Electrical and Computer Engineering */ /* The Johns Hopkins University */ /* sequence animation program taken out from tmndec gcc splay.c -o splay -lm -L/usr/X11R6/lib -lXext -lX11 */ #include #include #include #include #include #include #include #include /* Some macros */ #define mmax(a, b) ((a) > (b) ? (a) : (b)) #define mmin(a, b) ((a) < (b) ? (a) : (b)) char errortext[256]; unsigned char *refframe[3],*newframe[3],*exnewframe[3]; unsigned char *clp; int horizontal_size,vertical_size,mb_width,mb_height; int chrom_width,chrom_height,blk_cnt; int loopflag,expand,matrix_coefficients; /* Gamma correction stuff */ #define GAMMA_CORRECTION(x) ((int)(pow((x)/255.0, 1.0/gammaCorrect)*255.0)) #define CHROMA_CORRECTION256(x) ((x) >= 128 ? 128 + mmin(127, (int)(((x) - 128.0) * chromaCorrect)) : 128 - mmin(128, (int)((128.0 - (x)) * chromaCorrect))) #define CHROMA_CORRECTION128(x) ((x) >= 0 ? mmin(127, (int)(((x) * chromaCorrect))) : mmax(-128, (int)(((x) * chromaCorrect)))) #define CHROMA_CORRECTION256D(x) ((x) >= 128 ? 128.0 + mmin(127.0, (((x) - 128.0) * chromaCorrect)) : 128.0 - mmin(128.0, (((128.0 - (x)) * chromaCorrect)))) #define CHROMA_CORRECTION128D(x) ((x) >= 0 ? mmin(127.0, ((x) * chromaCorrect)) : mmax(-128.0, ((x) * chromaCorrect))) /* color space conversion coefficients * * entries are {crv,cbu,cgu,cgv} * * crv=(255/224)*65536*(1-cr)/0.5 * cbu=(255/224)*65536*(1-cb)/0.5 * cgu=(255/224)*65536*(cb/cg)*(1-cb)/0.5 * cgv=(255/224)*65536*(cr/cg)*(1-cr)/0.5 * * where Y=cr*R+cg*G+cb*B (cr+cg+cb=1) */ int convmat[8][4] = { {117504, 138453, 13954, 34903}, {117504, 138453, 13954, 34903}, {104597, 132201, 25675, 53279}, {104597, 132201, 25675, 53279}, {104448, 132798, 24759, 53109}, {104597, 132201, 25675, 53279}, {104597, 132201, 25675, 53279}, {117579, 136230, 16907, 35559}}; /* Data for ConvertYUVtoRGB*/ long int crv_tab[256]; long int cbu_tab[256]; long int cgu_tab[256]; long int cgv_tab[256]; long int tab_76309[256]; /* display related data */ unsigned long wpixel[3]; static unsigned char *dithered_image; /* X11 related variables */ static Display *display; static Window window; static GC gc; static int dpy_depth; /* Flag for gamma correction */ int gammaCorrectFlag = 0; double gammaCorrect = 1.0; /* Flag for chroma correction */ int chromaCorrectFlag = 0; double chromaCorrect = 1.0; XImage *ximage; unsigned char pixel[256]; extern unsigned char pixel[256]; static unsigned char ytab[16 * (256 + 16)]; static unsigned char uvtab[256 * 269 + 270]; static int *L_tab, *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab; static long *r_2_pix; static long *g_2_pix; static long *b_2_pix; static long *r_2_pix_alloc; static long *g_2_pix_alloc; static long *b_2_pix_alloc; static int shmem_flag; static XShmSegmentInfo shminfo1, shminfo2; static int gXErrorFlag; static int CompletionType = -1; int main(argc,argv) int argc; char *argv[]; { FILE *infile; int i, cc, size; int im_size, first, last, skip; long offset; loopflag = 1; /* always loop sequences */ if (argc != 8) { printf("\nUsage:%s input horizontal_size vertical_size first last skip expand\n",argv[0]); return 0;} horizontal_size = atoi(argv[2]); vertical_size = atoi(argv[3]); if (horizontal_size <= 0 || vertical_size <= 0){ printf("\nError:image size is wrong\n"); return 0;} im_size = horizontal_size * vertical_size * 3 / 2; first = atoi(argv[4]); last = atoi(argv[5]); skip = atoi(argv[6]); if(skip < 0 ){ printf("\nError: skip >= 0 && integer\n\n"); return 0 ;} if((expand = atoi(argv[7])) != 0 && expand != 1){ printf("\n\tUsage: %s qcif_sequence expand (0 , 1)\n", argv[1]); return 0 ;} if ((infile=fopen(argv[1],"r"))==NULL) { sprintf(errortext,"Input file %s not found\n",argv[1]); error(errortext); } offset = im_size * skip; /* clip table */ if (!(clp=(unsigned char *)malloc(1024))) error("malloc failed\n"); clp += 384; for (i=-384; i<640; i++) clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i); chrom_width = horizontal_size>>1; chrom_height = vertical_size>>1; for (cc=0; cc<3; cc++) { if (cc==0) size = horizontal_size*vertical_size; else size = chrom_width*chrom_height; if (!(refframe[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); } if (expand) { for (cc=0; cc<3; cc++) { if (cc==0) size = horizontal_size*vertical_size*4; else size = chrom_width*chrom_height*4; if (!(exnewframe[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); } } init_display(""); do { rewind(infile); fseek(infile,im_size*first,1); for(i = first; i < last; i += (skip+1)) { /* printf("frame%03d\n",i); */ fread(refframe[0],sizeof(unsigned char), horizontal_size*vertical_size,infile); fread(refframe[1],sizeof(unsigned char), chrom_width*chrom_height,infile); fread(refframe[2],sizeof(unsigned char), chrom_width*chrom_height,infile); if (expand) { interpolate_image(refframe[0], exnewframe[0], horizontal_size, vertical_size); interpolate_image(refframe[1],exnewframe[1],chrom_width,chrom_height); interpolate_image(refframe[2],exnewframe[2],chrom_width,chrom_height); dither(exnewframe); } else dither(refframe); if(skip) fseek(infile,offset,1); } } while (loopflag); fclose(infile); exit_display(); return 0; } error(text) char *text; { fprintf(stderr,text); exit(1); } static int HandleXError(dpy, event) Display *dpy; XErrorEvent *event; { gXErrorFlag = 1; return 0; } static void InstallXErrorHandler() { XSetErrorHandler(HandleXError); XFlush(display); } static void DeInstallXErrorHandler() { XSetErrorHandler(NULL); XFlush(display); } /* connect to server, create and map window, * allocate colors and (shared) memory */ init_display(name) char *name; { int crv, cbu, cgu, cgv; int y, u, v, r, g, b; int i; char dummy; int screen; Visual *visual; int dpy_class; Colormap cmap; int private; XColor xcolor; unsigned int fg, bg; char *hello = "Sequence Display"; XSizeHints hint; XEvent xev; XSetWindowAttributes xswa; unsigned long tmp_pixel; unsigned int mask; display = XOpenDisplay(name); if (display == NULL) error("Can not open display\n"); screen = DefaultScreen(display); visual = DefaultVisual (display, screen); dpy_depth = DefaultDepth (display, screen); dpy_class = visual->class; if (!((dpy_class == TrueColor && dpy_depth == 32) || (dpy_class == TrueColor && dpy_depth == 24) || (dpy_class == TrueColor && dpy_depth == 16) || (dpy_class == PseudoColor && dpy_depth == 8))) error ("requires 8 bit PseudoColor or 16/24/32 bit TrueColor display\n"); if (dpy_class == TrueColor && dpy_depth == 32) printf("TrueColor : 32 bit colordepth\n"); if (dpy_class == TrueColor && dpy_depth == 24) printf("TrueColor : 24 bit colordepth\n"); if (dpy_class == TrueColor && dpy_depth == 16) printf("TrueColor : 16 bit colordepth\n"); if (dpy_class == PseudoColor && dpy_depth == 8) printf("PseudoColor : 8 bit colordepth, 4x4 ordered dither\n"); /* width and height of the display window */ if (expand) { hint.min_width = hint.max_width = hint.width = 2*horizontal_size; hint.min_height = hint.max_height = hint.height = 2*vertical_size; } else { hint.min_width = hint.max_width = hint.width = horizontal_size; hint.min_height = hint.max_height = hint.height = vertical_size; } hint.flags = PSize | PMinSize | PMaxSize; /* Get some colors */ bg = WhitePixel (display, screen); fg = BlackPixel (display, screen); /* Make the window */ mask = CWBackPixel | CWBorderPixel; if (dpy_depth == 32 || dpy_depth == 24 || dpy_depth == 16) { mask |= CWColormap; xswa.colormap = XCreateColormap (display, DefaultRootWindow (display), visual, AllocNone); } xswa.background_pixel = bg; xswa.border_pixel = fg; window = XCreateWindow (display, DefaultRootWindow (display), hint.x, hint.y, hint.width, hint.height, 1, dpy_depth, InputOutput, visual, mask, &xswa); XSelectInput(display, window, StructureNotifyMask); /* Tell other applications about this window */ XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint); /* Map window. */ XMapWindow(display, window); /* Wait for map. */ do { XNextEvent(display, &xev); } while (xev.type != MapNotify || xev.xmap.event != window); XSelectInput(display, window, NoEventMask); /* allocate colors */ gc = DefaultGC(display, screen); if (dpy_depth == 8) { XWindowAttributes xwa; cmap = DefaultColormap(display, screen); private = 0; /* matrix coefficients */ crv = convmat[matrix_coefficients][0]; cbu = convmat[matrix_coefficients][1]; cgu = convmat[matrix_coefficients][2]; cgv = convmat[matrix_coefficients][3]; /* color allocation: * i is the (internal) 8 bit color number, it consists of separate * bit fields for Y, U and V: i = (yyyyuuvv), we don't use yyyy=0000 * yyyy=0001 and yyyy=1111, this leaves 48 colors for other applications * * the allocated colors correspond to the following Y, U and V values: * Y: 40, 56, 72, 88, 104, 120, 136, 152, 168, 184, 200, 216, 232 * U,V: -48, -16, 16, 48 * * U and V values span only about half the color space; this gives * usually much better quality, although highly saturated colors can * not be displayed properly * * translation to R,G,B is implicitly done by the color look-up table */ for (i=32; i<240; i++) { /* color space conversion */ y = 16*((i>>4)&15) + 8; u = 32*((i>>2)&3) - 48; v = 32*(i&3) - 48; y = 76309 * (y - 16); /* (255/219)*65536 */ r = clp[(y + crv*v + 32768)>>16]; g = clp[(y - cgu*u -cgv*v + 32768)>>16]; b = clp[(y + cbu*u + 32786)>>16]; /* X11 colors are 16 bit */ xcolor.red = r << 8; xcolor.green = g << 8; xcolor.blue = b << 8; if (XAllocColor(display, cmap, &xcolor) != 0) pixel[i] = xcolor.pixel; else { /* allocation failed, have to use a private colormap */ if (private) error("Couldn't allocate private colormap"); private = 1; /* Free colors. */ while (--i >= 32) { tmp_pixel = pixel[i]; /* because XFreeColors expects unsigned long */ XFreeColors(display, cmap, &tmp_pixel, 1, 0); } /* i is now 31, this restarts the outer loop */ /* create private colormap */ XGetWindowAttributes(display, window, &xwa); cmap = XCreateColormap(display, window, xwa.visual, AllocNone); XSetWindowColormap(display, window, cmap); } } } if (XShmQueryExtension(display)) shmem_flag = 1; else shmem_flag = 0; if (shmem_flag) CompletionType = XShmGetEventBase(display) + ShmCompletion; InstallXErrorHandler(); if (shmem_flag) { if (expand) ximage = XShmCreateImage(display, visual, dpy_depth, ZPixmap, NULL, &shminfo1, 2*horizontal_size, 2*vertical_size); else ximage = XShmCreateImage(display, visual, dpy_depth, ZPixmap, NULL, &shminfo1, horizontal_size, vertical_size); /* If no go, then revert to normal Xlib calls. */ if (ximage==NULL) { if (ximage!=NULL) XDestroyImage(ximage); goto shmemerror; } /* Success here, continue. */ shminfo1.shmid = shmget(IPC_PRIVATE,ximage->bytes_per_line*ximage->height, IPC_CREAT | 0777); if (shminfo1.shmid<0) { XDestroyImage(ximage); goto shmemerror; } shminfo1.shmaddr = (char *) shmat(shminfo1.shmid, 0, 0); shminfo2.shmaddr = (char *) shmat(shminfo2.shmid, 0, 0); if (shminfo1.shmaddr==((char *) -1)) { XDestroyImage(ximage); if (shminfo1.shmaddr!=((char *) -1)) shmdt(shminfo1.shmaddr); goto shmemerror; } ximage->data = shminfo1.shmaddr; dithered_image = (unsigned char *)ximage->data; shminfo1.readOnly = False; XShmAttach(display, &shminfo1); XSync(display, False); if (gXErrorFlag) { /* Ultimate failure here. */ XDestroyImage(ximage); shmdt(shminfo1.shmaddr); gXErrorFlag = 0; goto shmemerror; } else shmctl(shminfo1.shmid, IPC_RMID, 0); fprintf(stderr, "Sharing memory.\n"); } else { shmemerror: shmem_flag = 0; if (expand) { ximage = XCreateImage(display,visual,dpy_depth,ZPixmap,0,&dummy, 2*horizontal_size,2*vertical_size,8,0); if (!(dithered_image = (unsigned char *)malloc(horizontal_size*vertical_size* (dpy_depth > 8 ? sizeof (int)*4 : sizeof (unsigned char))*4))) error("malloc failed"); } else { ximage = XCreateImage(display,visual,dpy_depth,ZPixmap,0,&dummy, horizontal_size,vertical_size,8,0); if (!(dithered_image = (unsigned char *)malloc(horizontal_size*vertical_size* (dpy_depth > 8 ? sizeof (int) : sizeof (unsigned char))))) error("malloc failed"); } } DeInstallXErrorHandler(); if (dpy_depth == 32 || dpy_depth == 24 || dpy_depth == 16) { XWindowAttributes xwa; XGetWindowAttributes(display, window, &xwa); wpixel[0] = xwa.visual->red_mask; wpixel[1] = xwa.visual->green_mask; wpixel[2] = xwa.visual->blue_mask; /* If the colors in 16/24/32-bit mode are wrong, try this instead of the above three lines */ /* wpixel[2] = xwa.visual->red_mask; wpixel[1] = xwa.visual->green_mask; wpixel[0] = xwa.visual->blue_mask; */ InitColorDither(dpy_depth == 24 || dpy_depth == 32); } else ord4x4_dither_init (); } exit_display() { if (shmem_flag) { XShmDetach(display, &shminfo1); XDestroyImage(ximage); shmdt(shminfo1.shmaddr); } } static void display_image(ximage,dithered_image) XImage *ximage; unsigned char *dithered_image; { int t = 1; /* Always work in native bit and byte order. This tells Xlib to reverse bit and byte order if necessary when crossing a network. Frankly, this part of XImages is somewhat underdocumented, so this may not be exactly correct. */ if (*(char *)&t == 1) { ximage->byte_order = LSBFirst; ximage->bitmap_bit_order = LSBFirst; } else { ximage->byte_order = MSBFirst; ximage->bitmap_bit_order = MSBFirst; } /* display dithered image */ if (shmem_flag) { XShmPutImage(display, window, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height, True); XFlush(display); while (1) { XEvent xev; XNextEvent(display, &xev); if (xev.type == CompletionType) break; } } else { ximage->data = (char *) dithered_image; XPutImage(display,window,gc,ximage,0,0,0,0,ximage->width,ximage->height); } } dither(src) unsigned char *src[]; { if (dpy_depth == 24 || dpy_depth == 32) { if (ximage->bits_per_pixel == 24) ConvertYUVtoRGB(src[0],src[1],src[2], dithered_image, horizontal_size, vertical_size); else Color32DitherImage(src, dithered_image); } else if (dpy_depth == 16) Color16DitherImage(src, dithered_image); else ord4x4_dither_frame (src, dithered_image); display_image (ximage, dithered_image); } /**************************************************************************** 4x4 ordered dither Threshold pattern: 0 8 2 10 12 4 14 6 3 11 1 9 15 7 13 5 ****************************************************************************/ ord4x4_dither_init (void) { int i, j, v; unsigned char ctab[256 + 32]; for (i = 0; i < 256 + 16; i++) { v = (i - 8) >> 4; if (v < 2) v = 2; else if (v > 14) v = 14; for (j = 0; j < 16; j++) ytab[16 * i + j] = pixel[(v << 4) + j]; } for (i = 0; i < 256 + 32; i++) { v = (i + 48 - 128) >> 5; if (v < 0) v = 0; else if (v > 3) v = 3; ctab[i] = v; } for (i = 0; i < 255 + 15; i++) for (j = 0; j < 255 + 15; j++) uvtab[256*i+j]=(ctab[i+16]<<6)|(ctab[j+16]<<4)|(ctab[i]<<2)|ctab[j]; } ord4x4_dither_frame (unsigned char *src[], unsigned char *dst) { int i, j; unsigned char *py = src[0]; unsigned char *pu = src[1]; unsigned char *pv = src[2]; int width, height, cwidth; if (expand) { width = 2 * horizontal_size; height = 2 * vertical_size; cwidth = 2 * chrom_width; } else { width = horizontal_size; height = vertical_size; cwidth = chrom_width; } for (j = 0; j < height; j += 4) { register unsigned int uv; /* line j + 0 */ for (i = 0; i < width; i += 8) { uv = uvtab[(*pu++ << 8) | *pv++]; *dst++ = ytab[((*py++) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 8) << 4) | (uv >> 4)]; uv = uvtab[((*pu++ << 8) | *pv++) + 1028]; *dst++ = ytab[((*py++ + 2) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 10) << 4) | (uv >> 4)]; uv = uvtab[(*pu++ << 8) | *pv++]; *dst++ = ytab[((*py++) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 8) << 4) | (uv >> 4)]; uv = uvtab[((*pu++ << 8) | *pv++) + 1028]; *dst++ = ytab[((*py++ + 2) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 10) << 4) | (uv >> 4)]; } pu -= cwidth; pv -= cwidth; /* line j + 1 */ for (i = 0; i < width; i += 8) { uv = uvtab[((*pu++ << 8) | *pv++) + 2056]; *dst++ = ytab[((*py++ + 12) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 4) << 4) | (uv & 15)]; uv = uvtab[((*pu++ << 8) | *pv++) + 3084]; *dst++ = ytab[((*py++ + 14) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 6) << 4) | (uv & 15)]; uv = uvtab[((*pu++ << 8) | *pv++) + 2056]; *dst++ = ytab[((*py++ + 12) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 4) << 4) | (uv & 15)]; uv = uvtab[((*pu++ << 8) | *pv++) + 3084]; *dst++ = ytab[((*py++ + 14) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 6) << 4) | (uv & 15)]; } /* line j + 2 */ for (i = 0; i < width; i += 8) { uv = uvtab[((*pu++ << 8) | *pv++) + 1542]; *dst++ = ytab[((*py++ + 3) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 11) << 4) | (uv >> 4)]; uv = uvtab[((*pu++ << 8) | *pv++) + 514]; *dst++ = ytab[((*py++ + 1) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 9) << 4) | (uv >> 4)]; uv = uvtab[((*pu++ << 8) | *pv++) + 1542]; *dst++ = ytab[((*py++ + 3) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 11) << 4) | (uv >> 4)]; uv = uvtab[((*pu++ << 8) | *pv++) + 514]; *dst++ = ytab[((*py++ + 1) << 4) | (uv & 15)]; *dst++ = ytab[((*py++ + 9) << 4) | (uv >> 4)]; } pu -= cwidth; pv -= cwidth; /* line j + 3 */ for (i = 0; i < width; i += 8) { uv = uvtab[((*pu++ << 8) | *pv++) + 3598]; *dst++ = ytab[((*py++ + 15) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 7) << 4) | (uv & 15)]; uv = uvtab[((*pu++ << 8) | *pv++) + 2570]; *dst++ = ytab[((*py++ + 13) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 5) << 4) | (uv & 15)]; uv = uvtab[((*pu++ << 8) | *pv++) + 3598]; *dst++ = ytab[((*py++ + 15) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 7) << 4) | (uv & 15)]; uv = uvtab[((*pu++ << 8) | *pv++) + 2570]; *dst++ = ytab[((*py++ + 13) << 4) | (uv >> 4)]; *dst++ = ytab[((*py++ + 5) << 4) | (uv & 15)]; } } } /* * Converts image into 32 bit color (or 24-bit non-packed). * */ Color32DitherImage(src, out) unsigned char *src[]; unsigned char *out; { unsigned char *lum = src[0]; unsigned char *cb = src[1]; unsigned char *cr = src[2]; int cols; int rows; int L, CR, CB; unsigned int *row1, *row2; unsigned char *lum2; int x, y; int cr_r; int cr_g; int cb_g; int cb_b; int cols_2; cols = horizontal_size; rows = vertical_size; if (expand) { cols *= 2; rows *= 2; } cols_2 = cols/2; row1 = (unsigned int *)out; row2 = row1 + cols_2 + cols_2; lum2 = lum + cols_2 + cols_2; for (y=0; ybits_per_pixel == 24) /* not necessary in non-packed mode */ init_dither_tab(); L_tab = (int *)malloc(256*sizeof(int)); Cr_r_tab = (int *)malloc(256*sizeof(int)); Cr_g_tab = (int *)malloc(256*sizeof(int)); Cb_g_tab = (int *)malloc(256*sizeof(int)); Cb_b_tab = (int *)malloc(256*sizeof(int)); r_2_pix_alloc = (long *)malloc(768*sizeof(long)); g_2_pix_alloc = (long *)malloc(768*sizeof(long)); b_2_pix_alloc = (long *)malloc(768*sizeof(long)); if (L_tab == NULL || Cr_r_tab == NULL || Cr_g_tab == NULL || Cb_g_tab == NULL || Cb_b_tab == NULL || r_2_pix_alloc == NULL || g_2_pix_alloc == NULL || b_2_pix_alloc == NULL) { fprintf(stderr, "Could not get enough memory in InitColorDither\n"); exit(1); } for (i=0; i<256; i++) { L_tab[i] = i; if (gammaCorrectFlag) { L_tab[i] = GAMMA_CORRECTION(i); } CB = CR = i; if (chromaCorrectFlag) { CB -= 128; CB = CHROMA_CORRECTION128(CB); CR -= 128; CR = CHROMA_CORRECTION128(CR); } else { CB -= 128; CR -= 128; } Cr_r_tab[i] = (0.419/0.299) * CR; Cr_g_tab[i] = -(0.299/0.419) * CR; Cb_g_tab[i] = -(0.114/0.331) * CB; Cb_b_tab[i] = (0.587/0.331) * CB; } /* * Set up entries 0-255 in rgb-to-pixel value tables. */ for (i = 0; i < 256; i++) { r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(red_mask)); r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(red_mask); g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(green_mask)); g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(green_mask); b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(blue_mask)); b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(blue_mask); /* * If we have 16-bit output depth, then we double the value * in the top word. This means that we can write out both * pixels in the pixel doubling mode with one op. It is * harmless in the normal case as storing a 32-bit value * through a short pointer will lose the top bits anyway. * A similar optimisation for Alpha for 64 bit has been * prepared for, but is not yet implemented. */ if(!thirty2) { r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16; g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16; b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16; } } /* * Spread out the values we have to the rest of the array so that * we do not need to check for overflow. */ for (i = 0; i < 256; i++) { r_2_pix_alloc[i] = r_2_pix_alloc[256]; r_2_pix_alloc[i+ 512] = r_2_pix_alloc[511]; g_2_pix_alloc[i] = g_2_pix_alloc[256]; g_2_pix_alloc[i+ 512] = g_2_pix_alloc[511]; b_2_pix_alloc[i] = b_2_pix_alloc[256]; b_2_pix_alloc[i+ 512] = b_2_pix_alloc[511]; } r_2_pix = r_2_pix_alloc + 256; g_2_pix = g_2_pix_alloc + 256; b_2_pix = b_2_pix_alloc + 256; } /* * How many 0 bits are there at most significant end of longword. * Low performance, do not call often. */ static int free_bits_at_top(a) unsigned long a; { if(!a) return sizeof(unsigned long) * 8; /* assume char is 8 bits */ if(((long)a) < 0l) return 0; /* assume twos complement */ return 1 + free_bits_at_top ( a << 1); } /* * How many 0 bits are there at least significant end of longword. * Low performance, do not call often. */ int free_bits_at_bottom(a) unsigned long a; { if(!a) return sizeof(unsigned long) * 8; /* assume char is 8 bits */ if(((long)a) & 1l) return 0; return 1 + free_bits_at_bottom ( a >> 1); } /* * How many 1 bits are there in the longword. * Low performance, do not call often. */ int number_of_bits_set(a) unsigned long a; { if(!a) return 0; if(a & 1) return 1 + number_of_bits_set(a >> 1); return(number_of_bits_set(a >> 1)); } /* * Shift the 0s in the least significant end out of the longword. * Low performance, do not call often. */ static unsigned long shifted_down(a) unsigned long a; { if(!a) return 0; if(a & 1) return a; return a >> 1; } init_dither_tab() { long int crv,cbu,cgu,cgv; int i; crv = 104597; cbu = 132201; /* fra matrise i global.h */ cgu = 25675; cgv = 53279; for (i = 0; i < 256; i++) { crv_tab[i] = (i-128) * crv; cbu_tab[i] = (i-128) * cbu; cgu_tab[i] = (i-128) * cgu; cgv_tab[i] = (i-128) * cgv; tab_76309[i] = 76309*(i-16); } } ConvertYUVtoRGB(src0,src1,src2,dst_ori,width,height) unsigned char *src0, *src1, *src2; unsigned char *dst_ori; int width, height; { extern long int crv_tab[]; extern long int cbu_tab[]; extern long int cgu_tab[]; extern long int cgv_tab[]; extern long int tab_76309[]; int y11,y21; int y12,y22; int y13,y23; int y14,y24; int u,v; int i,j; int c11, c21, c31, c41; int c12, c22, c32, c42; unsigned int DW; unsigned int *id1, *id2; unsigned char *py1,*py2,*pu,*pv; unsigned char *d1, *d2; d1 = dst_ori; d1 += width*height*3 - width*3; d2 = d1 - width*3; py1 = src0; pu = src1; pv = src2; py2 = py1 + width; id1 = (unsigned int *)d1; id2 = (unsigned int *)d2; for (j = 0; j < height; j += 2) { /* line j + 0 */ for (i = 0; i < width; i += 4) { u = *pu++; v = *pv++; c11 = crv_tab[v]; c21 = cgu_tab[u]; c31 = cgv_tab[v]; c41 = cbu_tab[u]; u = *pu++; v = *pv++; c12 = crv_tab[v]; c22 = cgu_tab[u]; c32 = cgv_tab[v]; c42 = cbu_tab[u]; y11 = tab_76309[*py1++]; /* (255/219)*65536 */ y12 = tab_76309[*py1++]; y13 = tab_76309[*py1++]; /* (255/219)*65536 */ y14 = tab_76309[*py1++]; y21 = tab_76309[*py2++]; y22 = tab_76309[*py2++]; y23 = tab_76309[*py2++]; y24 = tab_76309[*py2++]; /* RGBR*/ DW = ((clp[(y11 + c41)>>16])) | ((clp[(y11 - c21 - c31)>>16])<<8) | ((clp[(y11 + c11)>>16])<<16) | ((clp[(y12 + c41)>>16])<<24); *id1++ = DW; /* GBRG*/ DW = ((clp[(y12 - c21 - c31)>>16])) | ((clp[(y12 + c11)>>16])<<8) | ((clp[(y13 + c42)>>16])<<16) | ((clp[(y13 - c22 - c32)>>16])<<24); *id1++ = DW; /* BRGB*/ DW = ((clp[(y13 + c12)>>16])) | ((clp[(y14 + c42)>>16])<<8) | ((clp[(y14 - c22 - c32)>>16])<<16) | ((clp[(y14 + c12)>>16])<<24); *id1++ = DW; /* RGBR*/ DW = ((clp[(y21 + c41)>>16])) | ((clp[(y21 - c21 - c31)>>16])<<8) | ((clp[(y21 + c11)>>16])<<16) | ((clp[(y22 + c41)>>16])<<24); *id2++ = DW; /* GBRG*/ DW = ((clp[(y22 - c21 - c31)>>16])) | ((clp[(y22 + c11)>>16])<<8) | ((clp[(y23 + c42)>>16])<<16) | ((clp[(y23 - c22 - c32)>>16])<<24); *id2++ = DW; /* BRGB*/ DW = ((clp[(y23 + c12)>>16])) | ((clp[(y24 + c42)>>16])<<8) | ((clp[(y24 - c22 - c32)>>16])<<16) | ((clp[(y24 + c12)>>16])<<24); *id2++ = DW; } id1 -= (9 * width)>>2; id2 -= (9 * width)>>2; py1 += width; py2 += width; } } interpolate_image(in, out, width, height) /* only used for displayed interpolated frames, not reconstructed ones */ unsigned char *in, *out; int width, height; { int x,xx,y,w2; unsigned char *pp,*ii; w2 = 2*width; /* Horizontally */ pp = out; ii = in; for (y = 0; y < height-1; y++) { for (x = 0,xx=0; x < width-1; x++,xx+=2) { *(pp + xx) = *(ii + x); *(pp + xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1)))>>1; *(pp + w2 + xx) = ((unsigned int)(*(ii + x) + *(ii + x + width)))>>1; *(pp + w2 + xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + *(ii + x + width) + *(ii + x + width + 1)))>>2; } *(pp + w2 - 2) = *(ii + width - 1); *(pp + w2 - 1) = *(ii + width - 1); *(pp + w2 + w2 - 2) = *(ii + width + width - 1); *(pp + w2 + w2 - 1) = *(ii + width + width - 1); pp += w2<<1; ii += width; } /* last lines */ for (x = 0,xx=0; x < width-1; x++,xx+=2) { *(pp+ xx) = *(ii + x); *(pp+ xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + 1))>>1; *(pp+ w2+ xx) = *(ii + x); *(pp+ w2+ xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + 1))>>1; } /* bottom right corner pels */ *(pp + (width<<1) - 2) = *(ii + width -1); *(pp + (width<<1) - 1) = *(ii + width -1); *(pp + (width<<2) - 2) = *(ii + width -1); *(pp + (width<<2) - 1) = *(ii + width -1); return; }