Category : C Source Code
Archive   : GRAFGEM3.ZIP
Filename : MOTBLUR.C

 
Output of file : MOTBLUR.C contained in archive : GRAFGEM3.ZIP
/*******************************************************************************
The following code implements motion blur on a HP9000 Series 800 computer,
including computing on fields and compensation for lack of subpixel positioning.
The anti-flicker filter discussed in Section 4 is not included.
In the interests of brevity and clarity, the code presented here is
not the most efficient possible, but note:

1. Rather than initializing the image accumulation buffer to 0 before each
frame in mb_frame(), the buffer can be initialized to the value of the
first subframe.

2. If the number of subframes per field is a power of two, then shifting the
accumulated result is faster than dividing.

3. If more processing must be done to the image in output(), such as
conversion from RGB to YUV, it is most efficient to do the processing
within the mb_average() routine, rather than to make another pass over
the same memory.

4. Results of the averaging are stored in place in a single accumulation
buffer. Depending on the additional processing that must be done by the
output() procedure, it may be advantageous to store the final result in a
different buffer instead, such as an array of unsigned char rather than
unsigned short.
*******************************************************************************/

#define FB_STRIDE 2048 /* framebuffer stride -- pixels in a scan line */
#define VID_XRES 640 /* video x resolution */
#define VID_YRES 486 /* video y resolution */

/* framebuffer address -- pixels stored in unsigned ints */
/* we assume frame is initialzed to point to the memory-mapped framebuffer */
static unsigned int *frame;
#define BB(v) ( ((v) <<24)>>24 ) /* extract blue byte from fb pixel */
#define BG(v) ( ((v) <<16)>>24 ) /* extract green byte from fb pixel */
#define BR(v) ( ((v) << 8)>>24 ) /* extract red byte from fb pixel */

/* accumulation buffer -- pixels stored as r,g,b, r,g,b,... */
static unsigned short acc[VID_XRES*VID_YRES*3];

void mb_average(), mb_accumulate();

/*******************************************************************************
Compute and output a motion blurred frame.

External Procedures:

void shift_image(int x,int y) - adjusts the viewing transformation to
render the image shifted by an integral
number of pixels in x and y

void draw(double t) - renders a subframe at time t

void output(unsigned short *acc,int w,int h) - outputs an image (e.g.
records a frame of the
animation onto the output
device)

Entry:
t0 - frame start time
delta - shutter open time
n - number of subframes
*******************************************************************************/
void mb_frame(t0,delta,n)
double t0;
double delta;
int n;
{
int i;
int nfield = n/2; /* number of subframes per field */
int field = 1; /* current field; first 1, then 0 */

/* pixel offsets for 16 subframes/field, gives triangle filter in x and y */
static int x_off[] = {0,1,0,1, -1,0,-1,0, 0, 1, 0,1, -1, 0,-1,0};
static int y_off[] = {0,1,1,0, 0,1, 1,0, 0,-1,-1,0, 0,-1,-1,0};
#define NOFFS ( sizeof(x_off)/sizeof(x_off[0]) )

/* clear accumulation buffer */
memset(acc,0,sizeof(acc));

for (i = 0; i < n; i++) {
shift_image(x_off[(i%nfield)%NOFFS],y_off[(i%nfield)%NOFFS]);
draw(t0 + i*delta/(n-1));
if (i == nfield-1 || i == n-1) {
mb_average(nfield,field);
field = !field;
} else {
mb_accumulate(field);
}
}

/* output final image */
output(acc,VID_XRES,VID_YRES);
}

/*******************************************************************************
Add another subframe to the accumulation buffer, computing on fields.

Entry:
field - field number (0 or 1)
*******************************************************************************/
void mb_accumulate(field)
int field;
{
register unsigned int *iptr;
register unsigned short *optr;
register int i,j;

/* shift input and output pointers by one scan line if field 1 */
if (field) {
iptr = frame + FB_STRIDE;
optr = acc + 3*VID_XRES;
} else {
iptr = frame;
optr = acc;
}

/* add in field to accumulation buffer */
for (i = 0; i < VID_YRES; i+=2) {
for (j = 0; j < VID_XRES; j+=4) {
/* process 4 pixels, skipping every other one */
register unsigned int v1 = iptr[0];
register unsigned int v3 = iptr[2];
register unsigned int v5 = iptr[4];
register unsigned int v7 = iptr[6];

optr[0] += BR(v1); optr[1] += BG(v1); optr[2] += BB(v1);
optr[3] += BR(v3); optr[4] += BG(v3); optr[5] += BB(v3);
optr[6] += BR(v5); optr[7] += BG(v5); optr[8] += BB(v5);
optr[9] += BR(v7); optr[10] += BG(v7); optr[11] += BB(v7);

iptr += 8;
optr += 12;
}
iptr += 4*FB_STRIDE-VID_XRES*2; /* process every fourth scan line */
optr += 3*VID_XRES; /* skip to next field scan line */
}
}

/*******************************************************************************
Add another subframe and divide by the number of field subframes.
The result is placed back into the accumulation buffer.

Entry:
n - number of subframes in a field
field - field number (0 or 1)
*******************************************************************************/
void mb_average(n,field)
int n;
int field;
{
register unsigned int *iptr;
register unsigned short *optr;
register int i,j;

/* shift input and output pointers by one scan line if field 1 */
if (field) {
iptr = frame + FB_STRIDE;
optr = acc + 3*VID_XRES;
} else {
iptr = frame;
optr = acc;
}

/* add in field to accumulation buffer and divide */
for (i = 0; i < VID_YRES; i+=2) {
for (j = 0; j < VID_XRES; j+=4) {
/* process 4 pixels, skipping every other one */
register unsigned int v1 = iptr[0];
register unsigned int v3 = iptr[2];
register unsigned int v5 = iptr[4];
register unsigned int v7 = iptr[6];

optr[0] = (optr[0]+BR(v1))/n;
optr[1] = (optr[1]+BG(v1))/n;
optr[2] = (optr[2]+BB(v1))/n;

optr[3] = (optr[3]+BR(v3))/n;
optr[4] = (optr[4]+BG(v3))/n;
optr[5] = (optr[5]+BB(v3))/n;

optr[6] = (optr[6]+BR(v5))/n;
optr[7] = (optr[7]+BG(v5))/n;
optr[8] = (optr[8]+BB(v5))/n;

optr[9] = (optr[9]+BR(v7))/n;
optr[10] = (optr[10]+BG(v7))/n;
optr[11] = (optr[11]+BB(v7))/n;

iptr += 8;
optr += 12;
}
iptr += 4*FB_STRIDE-VID_XRES*2; /* process every fourth scan line */
optr += 3*VID_XRES; /* skip to next field scan line */
}
}



  3 Responses to “Category : C Source Code
Archive   : GRAFGEM3.ZIP
Filename : MOTBLUR.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/