home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gems / gemsiii / motblur.c < prev    next >
Text File  |  1992-03-30  |  7KB  |  198 lines

  1. /*******************************************************************************
  2. The following code implements motion blur on a HP9000 Series 800 computer, 
  3. including computing on fields and compensation for lack of subpixel positioning.
  4. The anti-flicker filter discussed in Section 4 is not included.
  5. In the interests of brevity and clarity, the code presented here is
  6. not the most efficient possible, but note:
  7.  
  8.     1. Rather than initializing the image accumulation buffer to 0 before each
  9.        frame in mb_frame(), the buffer can be initialized to the value of the 
  10.        first subframe.
  11.  
  12.     2. If the number of subframes per field is a power of two, then shifting the
  13.        accumulated result is faster than dividing.
  14.  
  15.     3. If more processing must be done to the image in output(), such as 
  16.        conversion from RGB to YUV, it is most efficient to do the processing
  17.        within the mb_average() routine, rather than to make another pass over 
  18.        the same memory.  
  19.  
  20.     4. Results of the averaging are stored in place in a single accumulation
  21.        buffer.  Depending on the additional processing that must be done by the
  22.        output() procedure, it may be advantageous to store the final result in a
  23.        different buffer instead, such as an array of unsigned char rather than
  24.        unsigned short.
  25. *******************************************************************************/
  26.  
  27. #define FB_STRIDE 2048    /* framebuffer stride -- pixels in a scan line */
  28. #define VID_XRES   640    /* video x resolution */
  29. #define VID_YRES   486    /* video y resolution */
  30.  
  31. /* framebuffer address -- pixels stored in unsigned ints */
  32. /* we assume frame is initialzed to point to the memory-mapped framebuffer */
  33. static unsigned int *frame;                     
  34. #define BB(v)  ( ((v) <<24)>>24 )    /* extract blue byte from fb pixel */
  35. #define BG(v)  ( ((v) <<16)>>24 )    /* extract green byte from fb pixel */
  36. #define BR(v)  ( ((v) << 8)>>24 )    /* extract red byte from fb pixel */
  37.  
  38. /* accumulation buffer -- pixels stored as r,g,b, r,g,b,... */
  39. static unsigned short acc[VID_XRES*VID_YRES*3]; 
  40.  
  41. void mb_average(), mb_accumulate();
  42.  
  43. /*******************************************************************************
  44. Compute and output a motion blurred frame.
  45.  
  46. External Procedures:
  47.  
  48.     void shift_image(int x,int y) - adjusts the viewing transformation to
  49.                                     render the image shifted by an integral
  50.                                     number of pixels in x and y 
  51.  
  52.     void draw(double t)           - renders a subframe at time t
  53.  
  54.     void output(unsigned short *acc,int w,int h) - outputs an image (e.g. 
  55.                                                    records a frame of the 
  56.                                                    animation onto the output
  57.                                                    device)
  58.  
  59. Entry:
  60.     t0      - frame start time
  61.     delta   - shutter open time
  62.     n       - number of subframes
  63. *******************************************************************************/
  64. void mb_frame(t0,delta,n)
  65. double t0;
  66. double delta;
  67. int n;
  68. {
  69.     int i;
  70.     int nfield = n/2; /* number of subframes per field */
  71.     int field = 1;    /* current field; first 1, then 0 */
  72.  
  73.     /* pixel offsets for 16 subframes/field, gives triangle filter in x and y */
  74.     static int x_off[] = {0,1,0,1, -1,0,-1,0,  0, 1, 0,1, -1, 0,-1,0};
  75.     static int y_off[] = {0,1,1,0,  0,1, 1,0,  0,-1,-1,0,  0,-1,-1,0};
  76. #define NOFFS ( sizeof(x_off)/sizeof(x_off[0]) )
  77.  
  78.     /* clear accumulation buffer */
  79.     memset(acc,0,sizeof(acc));
  80.  
  81.     for (i = 0; i < n; i++) {
  82.         shift_image(x_off[(i%nfield)%NOFFS],y_off[(i%nfield)%NOFFS]);
  83.         draw(t0 + i*delta/(n-1));
  84.         if (i == nfield-1 || i == n-1) {
  85.             mb_average(nfield,field);
  86.             field = !field;
  87.         } else {  
  88.             mb_accumulate(field);
  89.         }
  90.     }
  91.  
  92.     /* output final image */
  93.     output(acc,VID_XRES,VID_YRES);
  94. }
  95.  
  96. /*******************************************************************************
  97. Add another subframe to the accumulation buffer, computing on fields.  
  98.  
  99. Entry:
  100.     field   - field number (0 or 1)
  101. *******************************************************************************/
  102. void mb_accumulate(field)
  103. int field;
  104. {
  105.     register unsigned int *iptr;
  106.     register unsigned short *optr;
  107.     register int i,j;
  108.  
  109.     /* shift input and output pointers by one scan line if field 1 */
  110.     if (field) {
  111.         iptr = frame + FB_STRIDE;
  112.         optr = acc + 3*VID_XRES;
  113.     } else {
  114.         iptr = frame;
  115.         optr = acc;
  116.     }
  117.  
  118.     /* add in field to accumulation buffer */
  119.     for (i = 0; i < VID_YRES; i+=2) {
  120.         for (j = 0; j < VID_XRES; j+=4) {
  121.             /* process 4 pixels, skipping every other one */
  122.             register unsigned int v1 = iptr[0];
  123.             register unsigned int v3 = iptr[2];
  124.             register unsigned int v5 = iptr[4];
  125.             register unsigned int v7 = iptr[6];
  126.  
  127.             optr[0] += BR(v1); optr[1]  += BG(v1); optr[2]  += BB(v1);
  128.             optr[3] += BR(v3); optr[4]  += BG(v3); optr[5]  += BB(v3);
  129.             optr[6] += BR(v5); optr[7]  += BG(v5); optr[8]  += BB(v5);
  130.             optr[9] += BR(v7); optr[10] += BG(v7); optr[11] += BB(v7);
  131.  
  132.             iptr += 8;
  133.             optr += 12;
  134.         }
  135.         iptr += 4*FB_STRIDE-VID_XRES*2; /* process every fourth scan line */
  136.         optr += 3*VID_XRES;             /* skip to next field scan line */
  137.     }
  138. }
  139.  
  140. /*******************************************************************************
  141. Add another subframe and divide by the number of field subframes.
  142. The result is placed back into the accumulation buffer.
  143.  
  144. Entry:
  145.     n       - number of subframes in a field
  146.     field   - field number (0 or 1)
  147. *******************************************************************************/
  148. void mb_average(n,field)
  149. int n;
  150. int field;
  151. {
  152.     register unsigned int *iptr;
  153.     register unsigned short *optr;
  154.     register int i,j;
  155.  
  156.     /* shift input and output pointers by one scan line if field 1 */
  157.     if (field) {
  158.         iptr = frame + FB_STRIDE;
  159.         optr = acc + 3*VID_XRES;
  160.     } else {
  161.         iptr = frame;
  162.         optr = acc;
  163.     }
  164.  
  165.     /* add in field to accumulation buffer and divide */
  166.     for (i = 0; i < VID_YRES; i+=2) {
  167.         for (j = 0; j < VID_XRES; j+=4) {
  168.             /* process 4 pixels, skipping every other one */
  169.             register unsigned int v1 = iptr[0];
  170.             register unsigned int v3 = iptr[2];
  171.             register unsigned int v5 = iptr[4];
  172.             register unsigned int v7 = iptr[6];
  173.  
  174.             optr[0] = (optr[0]+BR(v1))/n; 
  175.             optr[1] = (optr[1]+BG(v1))/n; 
  176.             optr[2] = (optr[2]+BB(v1))/n;
  177.  
  178.             optr[3] = (optr[3]+BR(v3))/n; 
  179.             optr[4] = (optr[4]+BG(v3))/n; 
  180.             optr[5] = (optr[5]+BB(v3))/n;
  181.  
  182.             optr[6] = (optr[6]+BR(v5))/n; 
  183.             optr[7] = (optr[7]+BG(v5))/n; 
  184.             optr[8] = (optr[8]+BB(v5))/n;
  185.  
  186.             optr[9] = (optr[9]+BR(v7))/n; 
  187.             optr[10] = (optr[10]+BG(v7))/n; 
  188.             optr[11] = (optr[11]+BB(v7))/n;
  189.  
  190.             iptr += 8;
  191.             optr += 12;
  192.         }
  193.         iptr += 4*FB_STRIDE-VID_XRES*2; /* process every fourth scan line */
  194.         optr += 3*VID_XRES;             /* skip to next field scan line */
  195.     }
  196. }
  197.  
  198.