| /*************************************************************************/ |
| /* */ |
| /* 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); |
| } |
| |