blob: e516440e28d96f55fe8015a884af25d64d66bd2d [file] [log] [blame]
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* NAME
* fbuf.c
*
* DESCRIPTION
* This file contains the private data definitions and code for
* manipulating the virtual framebuffer.
*
* Routines include:
* Run-length encoding a scanline.
* Allocating and initializing the framebuffer.
* Adding color to a pixel.
* Writing the framebuffer to a file.
*/
#include <stdio.h>
#include <math.h>
#include "rt.h"
static struct /* Runlength pixel definition. */
{
U8 r, g, b; /* Color. */
U8 count; /* Pixel count for color. */
}
image[MAX_X];
/*
image does not have have to be made an array for tango-lite
since it is only used in RunLengthEncode, which is only
called by CloseFrameBuffer, which is only called after
all children have terminated
*/
/*
* NAME
* RunLengthEncode - rl encode a scanline and write the result to file
*
* SYNOPSIS
* VOID RunLengthEncode(pf, fb, xsize)
* FILE *pf; // File pointer.
* PIXEL *fb; // Framebuffer pointer.
* INT xsize; // Size of scanline in x coordinates.
*
* RETURNS
* Nothing.
*/
VOID RunLengthEncode(pf, fb, xsize)
FILE *pf;
PIXEL *fb;
INT xsize;
{
INT x; /* Original buffer entry address. */
INT rl; /* Runlength buffer entry address. */
INT numpixels; /* Running count of identical pixels.*/
U8 red, green, blue; /* Color holders. */
rl = 0;
numpixels = 0;
image[0].r = (U8)( (INT) (fb[0].r * 255.0));
image[0].g = (U8)( (INT) (fb[0].g * 255.0));
image[0].b = (U8)( (INT) (fb[0].b * 255.0));
for (x = 1; x < xsize; x++)
{
red = (U8)( (INT) (fb[x].r * 255.0));
green = (U8)( (INT) (fb[x].g * 255.0));
blue = (U8)( (INT) (fb[x].b * 255.0));
if (red == image[rl].r &&
green == image[rl].g &&
blue == image[rl].b &&
numpixels < 255)
numpixels++;
else
{
image[rl].count = (U8)numpixels;
rl++;
image[rl].r = red;
image[rl].g = green;
image[rl].b = blue;
numpixels = 0;
}
}
image[rl].count = (U8)numpixels;
for (x = 0; x <= rl; x++)
fprintf(pf, "%c%c%c%c", image[x].r, image[x].g, image[x].b, image[x].count);
}
/*
* NAME
* OpenFrameBuffer - allocate and clear framebuffer
*
* SYNOPSIS
* VOID OpenFrameBuffer()
*
* RETURNS
* Nothing.
*/
VOID OpenFrameBuffer()
{
INT i;
PIXEL *fb;
fb = Display.framebuffer = GlobalMalloc(Display.numpixels*sizeof(PIXEL), "fbuf.c");
for (i = 0; i < Display.numpixels; i++)
{
fb->r = 0.0;
fb->g = 0.0;
fb->b = 0.0;
fb++;
}
}
/*
* NAME
* AddPixelColor - color is added to the frame buffer pixel at x,y
*
* SYNOPSIS
* VOID AddPixelColor(c, x, y)
* COLOR c; // Pixel contribution color.
* INT x; // X coordinate of pixel.
* INT y; // Y coordinate of pixel.
*
* RETURNS
* Nothing.
*/
VOID AddPixelColor(c, x, y)
COLOR c;
INT x;
INT y;
{
INT addr; /* Index into framebuffer. */
PIXEL *fb; /* Ptr to framebuffer. */
addr = Display.xres * y + x;
fb = Display.framebuffer;
fb[addr].r += c[0];
fb[addr].g += c[1];
fb[addr].b += c[2];
}
/*
* NAME
* CloseFrameBuffer - write the frame buffer pixels to a file
*
* SYNOPSIS
* VOID CloseFrameBuffer(PicFileName, mode)
* CHAR *PicFileName; // Picture file name to create.
*
* RETURNS
* Nothing.
*/
VOID CloseFrameBuffer(PicFileName)
CHAR *PicFileName;
{
INT x;
INT y;
PIXEL *fb; /* Ptr to framebuffer. */
FILE *pf; /* Ptr to picture file. */
pf = fopen(PicFileName, "wb");
if (!pf)
{
printf("Unable to open picture file %s.\n", PicFileName);
exit(-1);
}
/* Write file header. */
x = Display.xres;
y = Display.yres;
fb = Display.framebuffer;
fprintf(pf, "%c%c%c%c%c%c%c%c",
(char)(0), (char)(0), (char)(x/256), (char) (x%256),
(char)(0), (char)(0), (char)(y/256), (char) (y%256));
/* Clamp, run-length encode, and write out pixels on a scanline basis. */
for (y = 0; y < Display.yres; y++)
{
for (x = 0; x < Display.xres; x++)
{
fb[x].r = Min(fb[x].r, 1.0);
fb[x].g = Min(fb[x].g, 1.0);
fb[x].b = Min(fb[x].b, 1.0);
fb[x].r = Max(fb[x].r, 0.0);
fb[x].g = Max(fb[x].g, 0.0);
fb[x].b = Max(fb[x].b, 0.0);
}
RunLengthEncode(pf, fb, Display.xres);
fb += Display.xres;
}
fclose(pf);
GlobalFree(Display.framebuffer);
}