home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume38
/
tovcr
/
part01
/
tovcr.c.A
< prev
Wrap
Text File
|
1993-07-14
|
46KB
|
1,984 lines
/*
* This software is copyrighted as noted below. It may be freely copied,
* modified, and redistributed, provided that the copyright notice is
* preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely "as is". Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*/
/*
* tovcr.c - display/record images on a Video Recorder using the SGI VFR.
*
* Author: Raul Rivero
* Mathematics Dept.
* University of Oviedo
* Date: Mon Aug 17 1992
* Copyright (c) 1992, Raul Rivero
*
*/
/*
* Revisions:
*
* 1.1
* Raul Rivero
* Mathematics Dept.
* University of Oviedo
* Mon May 17 1993
* ( nuevos@carreras.ccu.uniovi.es )
*
* i. New file formats supported ( JPEG, PBM/PGM/PPM, 24bits-PCX ).
* ii. Some little fixes.
*
* -----
*/
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include "image.h"
#include "vframer.h"
#ifdef iTIFF
# include "tiffio.h"
# define GetField(h, t, v) if ( !TIFFGetField(h, t, v ) ) error(18);
#endif /* iTIFF */
#ifdef iRLE
# include "rle.h"
# define PSEUDOCOLOR 1
# define DIRECTCOLOR 2
# define TRUECOLOR 3
# define GRAYSCALE 4
#endif /* iRLE */
#ifdef iJPEG
# include <jinclude.h>
#endif /* iJPEG */
/*
* The magic flag.
*/
#define LUGUSED 12345 /* why not ? */
#define byte unsigned char
#define ushort unsigned short
#define Fread(p, s, n, f) if ( fread(p, s, n, f) != n ) error(3)
#define Fwrite(p, s, n, f) if ( fwrite(p, s, n, f) != n ) error(4)
#define VPRINTF if (verbose) fprintf
#define VFLUSH if (verbose) fflush
#define NOBLUR 0
#define BLUR 1
#define CHROMABORDER 20
#define PREROLLTIME "3:00"
#define POSTROLLTIME "1:00"
#define AUTOINCREMENT 1
/*
* This is the name of the 'super' image. Be careful with
* the file format.
*/
#define SUPERNAME "/usr/a3demo/bin/fuentes/super"
/* More esasy */
#define equal(s, t) ( strstr(s,t) != NULL ? 1 : 0 )
/*
* ==========================================
* REMEMBER!!!
* I'm working with R-Y PAL, but you ?.
* ==========================================
*
* Be careful with the next 3 blocks of defines !!!.
*/
/*
* The image will be adjusted to ...
*
*/
#define XFBUFFER 780
#define YFBUFFER 576
#define XSIZE 710
#define YSIZE 576
#define VFR_LINESIZE 1024
/*
* Video FRamer default buffer names.
*/
#define DEFAULT_VFR_BUFFER "r_y_625"
#define OPTIONAL_VFR_BUFFER "rgb_625"
/*
* Last frame into SMPTE ( PAL has 25 frames per
* second ==> 24 ).
*/
#define FPS 24
/*
* TGA's defines.
*/
#define TGAINTERLACED(a) ( (a) & 0xc0 )
#define TGAFLIP(a) ( ((a) & 0x20) ? 0 : 1)
#define TGA_MAPPED 1
#define TGA_RGB 2
#define TGA_RLE_MAPPED 9
#define TGA_RLE_RGB 10
/*
* GIF's defines.
*/
#define GIFHEADER "GIF87a"
#define GIFIMGSEPAR ','
#define ENDGIF ';'
#define GIFEXISTCOLOR (1 << 7)
#define GIFINTERLAZE (1 << 6)
/*
* PCX's defines
*/
#define PCX_HEADERSIZE 128
#define PCX_MAGICNUMBER 0x0a
#define PCX_256COLORS 0x0c
#define PCX_COMPRESS 0xc0
#ifdef USE_STDLIB_H
# include <stdlib.h>
#else
# ifdef VOID_STAR
extern void *malloc();
# else
extern char *malloc();
# endif /* VOID_STAR */
extern void free();
#endif /* USE_STDLIB_H */
#ifndef BSD
# define bzero(s, n) memset((s), 0, (n))
# define bcopy(f, t, c) memcpy((t), (f), (c))
#endif /* BSD */
/*
* Pointer to funtions.
*/
typedef int (* ifunptr)();
/*
* My bitmap header.
*/
typedef struct {
int xsize, ysize;
int depth;
int colors;
byte *r, *g, *b;
byte *cmap;
int magic;
} bitmap_hdr;
/*
* Wavefront's RLA format headers.
*/
typedef struct {
short left, right, bottom, top;
} WINDOW_S;
typedef struct {
WINDOW_S window;
WINDOW_S act_window;
short frame;
short storage_type;
short num_chan;
short num_matte;
short num_aux;
short aux_mask;
char gamma[16];
char red_pri[24];
char green_pri[24];
char blue_pri[24];
char white_pt[24];
long job_num;
char name[128];
char desc[128];
char program[64];
char machine[32];
char user[32];
char date[20];
char aspect[32];
char chan[32];
char space[128];
} RLA_HEADER;
/*
* Targa header.
*/
typedef struct {
byte num_id;
byte cmap_type;
byte image_type;
ushort cmap_orign;
ushort cmap_length;
byte cmap_entry_size;
ushort xorig, yorig;
ushort xsize, ysize;
byte pixel_size;
byte image_descriptor;
} tga_hdr;
/*
* Alias header.
*/
typedef struct {
short xsize, ysize;
short xinit, yinit;
short depth;
} alias_hdr;
typedef byte color_map[3];
/*
* Prototypes ( only what is necesary ).
*/
FILE *Fopen();
char *Malloc();
long filelen();
char *read_file();
byte *create_bw_pallete();
byte *zoom();
byte *blur();
int fparent_ready();
int fchild_ready();
VFR_DEV *open_video();
int vfr_not_ready();
int error_from_other();
int press_break();
char *Vfr_Vlan_Cmd();
byte *shorttobyte();
byte *read_gif_screen_hdr();
byte *read_gif_image_hdr();
byte *unblockgif();
byte *flip();
#ifdef iJPEG
void get_jpeg_header();
void get_jpeg_cmap();
void get_jpeg_row();
void end_put_jpeg();
void d_ui_method_selection();
#endif /* iJPEG */
/*
* This pointer contents the funtion to read the
* input image file format.
*/
ifunptr read_image;
/*
* Current formats supported.
*/
int read_alias_file();
int read_rla_file();
int read_sgi_file();
int read_tga_file();
int read_gif_file();
int read_pcx_file();
int read_pbm_file();
#ifdef iTIFF
int read_tiff_file();
#endif
#ifdef iRLE
int read_rle_file();
#endif
#ifdef iJPEG
int read_jpeg_file();
#endif
/*
* The name of the program and an auxiliar file name
* to uncompress input file ( if compressed ).
*/
char *MY_NAME;
char aux_file[40];
/* Used by the GIF reader */
int lug_read_code_position;
/* Used by the JPEG reader */
#ifdef iJPEG
static bitmap_hdr *jpeg_image;
byte *jpeg_r, *jpeg_g, *jpeg_b;
#endif /* iJPEG */
/* IDs for child and parent process */
int cpid, parent_pid;
/* We'll simulate semaphores with ... */
int child_ready, parent_ready;
/*
* Flags ...
*/
int verbose = 0;
int super = 0;
int center = 0;
int resetvfr = 0;
int rgbvfr = 0;
int blurflag = 0;
int record_sequence = 0;
int forceblur = 0;
main(argc, argv)
int argc;
char **argv;
{
register int i;
char *inpoint;
int start, end;
MY_NAME = argv[0];
parent_pid = getpid();
/* Default is Alias "pix" format */
read_image = read_alias_file;
/*
* Get options ( some day I'll build a procedure ).
*/
if ( argc > 1 ) { /* else core on SGI */
while ( argv[1][0] == '-' ) {
for ( i = 1; argv[1][i]; i++ ) {
switch ( argv[1][i] ) {
case 'v':
verbose++;
break;
case 'b':
forceblur++;
break;
case 'c':
center++;
break;
case 's':
super++;
break;
case 'i':
resetvfr++;
break;
case 'r':
rgbvfr++;
resetvfr++;
break;
case 'n':
blurflag++;;
break;
#ifdef iTIFF
case 't':
read_image = read_tiff_file;
break;
#endif
#ifdef iRLE
case 'u':
read_image = read_rle_file;
break;
#endif
#ifdef iJPEG
case 'j':
read_image = read_jpeg_file;
break;
#endif
case 'w':
read_image = read_rla_file;
break;
case 'g':
read_image = read_sgi_file;
break;
case 'a':
read_image = read_tga_file;
break;
case 'f':
read_image = read_gif_file;
break;
case 'x':
read_image = read_pcx_file;
break;
case 'p':
read_image = read_pbm_file;
break;
case '!':
print_copyright();
break;
default :
error( 0 );
break;
}
}
argv++;
argc--;
}
}
if ( argc < 2 )
error( 0 );
/* Skip the command name */
argv++;
/*
* Auxiliar file name where uncompress images if
* it's necesary.
*/
sprintf(aux_file, "/usr/tmp/spix%d", parent_pid);
if ( is_a_incode( *argv ) ) {
/*
* We wanna record frames, so we read the incode.
*/
inpoint = *argv++;
start = Atoi( *argv++ );
if ( isnumber( *argv ) ) {
/*
* Hey!, it's a number. Ok, we wanna record a
* sequence of animated frames.
*/
record_sequence++;
end = Atoi( *argv++ );
/* Number of images to fade */
i = argc - 4;
}else {
/*
* We wanna record only a frame.
*/
end = start;
i = argc - 3;
}
/*
* Ok, all ready ...
*/
to_video( inpoint, start, end, i, argv );
}else {
/*
* What we wanna is display a image into the VFR, don't
* record it.
*/
show_vfr_image( argv, argc - 1 );
}
rm_compress();
}
show_vfr_image( original_names, no_frames )
char **original_names;
int no_frames;
{
register int i;
VFR_DEV *vfr;
bitmap_hdr outbitmap;
ifunptr save_read_interface;
/*
* Connect with VFR interface.
*/
vfr = ( VFR_DEV *) open_video();
/*
* Create the background image.
*/
create_solid_image( &outbitmap, XFBUFFER, YFBUFFER, 0, 0, 0 );
/*
* Load all the imames.
*/
for ( i = 0; i < no_frames; i++ ) {
add_image( &outbitmap, original_names[i], center );
}
if ( super ) {
/*
* Glue the super to end image ( but we need use
* Alias interface ).
*/
save_read_interface = read_image;
read_image = read_alias_file;
add_image( &outbitmap, SUPERNAME, 0 );
/* Restores old interface */
read_image = save_read_interface;
}
/*
* Outbitmap is the new image.
*/
write_vfr( vfr, &outbitmap );
freebitmap( &outbitmap );
}
to_video( inpoint, start, end, no_frames, original_names )
char *inpoint, **original_names;
int start, end, no_frames;
{
register int i;
VFR_DEV *vfr;
int point[4];
char *buffer_names[20];
char **frames_names;
int autoincrement;
/*
* Connect with VFR interface.
*/
vfr = ( VFR_DEV *) open_video();
/*
* Caugth errors from child and interrupt key.
*/
signal( SIGINT, press_break );
/* Convert inpoint to numbers */
convert_inpoint( inpoint, point );
if ( record_sequence ) {
/*
* We have a sequence of frames, so we'll build each
* name ( and need memory ) ...
*/
frames_names = buffer_names;
malloc_names( no_frames, original_names, frames_names);
creat_names( no_frames, original_names, frames_names, start );
/* Time for each frame */
autoincrement = AUTOINCREMENT;
}else {
/* Use original names */
frames_names = original_names;
/* Time for the frame */
autoincrement = start;
}
/*
* Child can build the image.
*/
cpid = release_child( vfr, no_frames, frames_names );
/*
* Initialize the VLAN.
*/
init_vlan( vfr, inpoint, autoincrement );
/*
* Now the child can put the image into VFR.
*/
unlock_vfr( cpid );
for ( i = start; i <= end; i++ ) {
/* Check if the video are ready, PAUSE */
check_point( vfr );
/* Wait for child ( the child put the image into the VFR ) */
wait_for_children( cpid );
/* PerForm */
(void)Vfr_Vlan_Cmd( vfr, "PF" );
write_current_frame( point, i );
if ( i != end ) {
/* Not the end, so creat next names */
creat_names( no_frames, original_names, frames_names, i+1 );
cpid = release_child( vfr, no_frames, frames_names );
}
/* Check if the video perform the record */
check_status( vfr );
/*
* If the video record the last frame then child
* can put current image into VFR.
*/
unlock_vfr( cpid );
}
if ( record_sequence ) {
free_names( no_frames, frames_names );
}
}
release_child ( vfr, no_frames, frames_names )
VFR_DEV *vfr;
int no_frames;
char **frames_names;
{
bitmap_hdr outbitmap;
ifunptr save_read_interface;
int pid;
int i;
child_ready = parent_ready = 0;
switch( pid = fork() ) {
case -1 :
/*
* fork() cannot respawn.
*/
error( 13 );
break;
case 0 :
signal( SIGUSR1, fparent_ready );
signal( SIGUSR2, error_from_other );
/*
* Create the background image.
*/
create_solid_image( &outbitmap, XFBUFFER, YFBUFFER, 0, 0, 0 );
/*
* Load all the images.
*/
for ( i = 0; i < no_frames; i++ ) {
add_image( &outbitmap, frames_names[i], center );
}
if ( super ) {
/*
* Glue the super to end image ( but we need use
* Alias interface ).
*/
save_read_interface = read_image;
read_image = read_alias_file;
add_image( &outbitmap, SUPERNAME, 0 );
/* Restores old interface */
read_image = save_read_interface;
}
/*
* Wait for parent.
*/
/*if ( !parent_ready )
pause();*/
while ( !parent_ready );
/*
* Outbitmap is the new image. We'll use last argument
* as file name.
*/
write_vfr( vfr, &outbitmap );
freebitmap( &outbitmap );
/*
* This is the end of the child so report it to
* the parent.
*/
exit( 0 );
break;
default:
signal( SIGUSR2, error_from_other );
return pid;
break;
}
}
add_image( base, filename, flag )
bitmap_hdr *base;
char *filename;
int flag;
{
bitmap_hdr inbitmap;
bitmap_hdr palbitmap;
/*
* Read the image.
*/
read_image( filename, &inbitmap );
/*
* Adjust file to PAL and glue it to end image.
*/
if ( !flag ) {
adjust( &inbitmap, &palbitmap, XSIZE, YSIZE, blurflag );
chroma( base, &palbitmap );
}else center_image( base, &inbitmap );
/*
* Free buffers.
*/
freebitmap( &inbitmap );
if( flag )
freebitmap( &palbitmap );
}
/**************************************
*
* SMPTE code handlers.
*
*/
calculate_outpoint( inpoint, outpoint, totalframes )
char *inpoint;
char *outpoint, totalframes;
{
register int i;
int point[4];
/* Convert inpoint to numbers */
convert_inpoint( inpoint, point );
/* Calculate the outpoint */
for ( i = 0; i < totalframes; i++ )
add_incode( point );
/* Convert outpoint numbers to a SMTPE format code */
sprintf ( outpoint, "%.2d:%.2d:%.2d:%.2d\n",
point[0], point[1], point[2], point[3] );
}
is_a_incode( inpoint )
char *inpoint;
{
int marks = 0;
while ( *inpoint )
if ( *inpoint++ == ':' )
marks++;
return( marks == 3 );
}
convert_inpoint( inpoint, point )
char *inpoint;
int *point;
{
sscanf( inpoint, "%d:%d:%d:%d", &point[0], &point[1],
&point[2], &point[3] );
if ( point[0] < 0 || point[1] < 0 || point[2] < 0 || point[3] < 0 ||
point[0] > 23 || point[1] > 59 || point[2] > 59 || point[3] > FPS )
error( 14 );
}
write_current_frame( point, frame )
int *point;
int frame;
{
#if AUTOINCREMENT > 1
register int i;
#endif
if ( record_sequence ) {
fprintf ( stdout, "Recording frame %d on %.2d:%.2d:%.2d:%.2d\n", frame,
point[0], point[1], point[2], point[3] );
}else {
fprintf ( stdout, "Recording frame on %.2d:%.2d:%.2d:%.2d\n",
point[0], point[1], point[2], point[3] );
}
/*
* If AUTOINCREMENT is greater than one then we need add more
* frames to the current, else we can skip this loop.
*/
#if AUTOINCREMENT > 1
for ( i = 0; i < AUTOINCREMENT; i++ )
#endif
add_incode( point );
}
add_incode( point )
int *point;
{
if ( point[3] == FPS ) {
point[3] = 0;
if ( point[2] == 59 ) {
point[2] = 0;
if ( point[1] == 59 ) {
point[1] = 0;
point[0]++;
}else point[1]++;
}else point[2]++;
}else point[3]++;
}
/**************************************
*
* File names builders.
*
*/
malloc_names( no_frames, original_names, frames_names )
int no_frames;
char **original_names, **frames_names;
{
register int i;
/* Allocate memory to sequence names */
for ( i = 0; i < no_frames; i++ ) {
frames_names[i] = (char *) Malloc( strlen(original_names[i] ) + 10 );
}
}
creat_names( no_frames, original_names, frames_names, current_frame )
int no_frames, current_frame;
char **original_names, **frames_names;
{
register int i;
/* Creat the names of frames */
for ( i = 0; i < no_frames; i++ ) {
sprintf( frames_names[i], "%s.%d", original_names[i], current_frame );
}
}
free_names( no_frames, frames_names )
int no_frames;
char **frames_names;
{
register int i;
/* Free sequence names */
for ( i = 0; i < no_frames; i++ ) {
Free( frames_names[i] );
}
}
/**************************************
*
* Signal handlers.
*
*/
vfr_not_ready()
{
/*
* The alarm has been actived, the VFR doesn't respond.
*/
error( 15 );
}
error_from_other()
{
/*
* The other process had an error.
*/
exit( 1 );
}
unlock_vfr( cpid )
int cpid;
{
/*
* Child can put image into VFR.
*/
kill( cpid, SIGUSR1 );
}
wait_for_children( cpid )
int cpid;
{
int rpid;
int status;
/*
* The parent are ready, but the child ?.
*/
rpid = wait( &status );
if ( ! WIFEXITED( status ) )
error( 16 );
signal( SIGUSR2, SIG_DFL );
}
press_break()
{
/*
* User press break, so we need kill
* child ( if exist ).
*/
if ( getpid() == parent_pid ) {
kill( cpid, SIGKILL );
}
rm_compress();
exit( 0 );
}
fparent_ready()
{
parent_ready = 1;
signal( SIGUSR1, fparent_ready );
}
fchild_ready()
{
child_ready = 1;
signal( SIGUSR1, fchild_ready );
}
/**************************************
*
* Digital Image Editing procedures.
*
*/
adjust(inbitmap, outbitmap, newx, newy, noblur)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
int newx, newy;
int noblur;
{
/* Really, is an image ? */
if ( inbitmap->magic != LUGUSED )
error( 21 );
/* An 8 bits image ? */
if ( inbitmap->depth <= 8)
error(7);
/* If PAL then return the same image */
if ( inbitmap->xsize == newx && inbitmap->ysize == newy ) {
copy_bitmap( inbitmap, outbitmap );
}else {
/*
* Fill new header ...
*/
outbitmap->magic = LUGUSED;
outbitmap->xsize = newx;
outbitmap->ysize = newy;
outbitmap->depth = inbitmap->depth; /* 24 planes */
outbitmap->colors = inbitmap->colors;
/*
* ... and zoom each component.
*/
VPRINTF(stderr, "Zooming R\n");
outbitmap->r= zoom( inbitmap->xsize, inbitmap->ysize,
newx, newy, inbitmap->r, noblur );
VPRINTF(stderr, "Zooming G\n");
outbitmap->g= zoom( inbitmap->xsize, inbitmap->ysize,
newx, newy, inbitmap->g, noblur );
VPRINTF(stderr, "Zooming B\n");
outbitmap->b= zoom( inbitmap->xsize, inbitmap->ysize,
newx, newy, inbitmap->b, noblur );
}
}
byte *zoom(oldx, oldy, newx, newy, buffer, noblur)
int oldx, oldy;
int newx, newy;
register byte *buffer;
int noblur;
{
register int i, j;
register byte *base, *i_base;
double relx, rely;
double nrelx, nrely;
byte *ptr;
byte *nbuffer;
double foldx, foldy;
double fnewx, fnewy;
/* Allocate memory for new zoomed image */
nbuffer = (byte *) Malloc( newx * newy );
/*
* We use double variables ( only once transformation ).
*/
fnewx = (double) newx, fnewy= (double) newy;
foldx = (double) oldx, foldy= (double) oldy;
for ( i = 0; i< newy; i++ ) {
/* pointer to first pixel in current row */
base = nbuffer + (int) (newx*i);
/* scale row from 0 to 1 with the new image */
nrely = ((double) i) / fnewy;
/* get equal value in old image */
rely = nrely * foldy;
/* pointer to first pixel in that row */
i_base = buffer + ((int) rely) * oldx;
for ( j = 0; j < newx; j++ ) {
/* scale column from 0 to 1 ... */
nrelx = ((double) j) / fnewx;
/* then we get position of old image */
relx = nrelx * foldx;
ptr = i_base + (int) relx;
*base++ = *ptr;
}
}
/*
* If image is greater then blur ( if no_blur switch
* is actived ).
*/
if ( (newx > oldx || newy > oldy) && !noblur ) {
/* Blur zoomed image */
ptr = blur( nbuffer, newx, newy );
/* We have a new [blur] image, free first */
Free( nbuffer );
return ptr;
}else {
return nbuffer;
}
}
byte *blur(buffer, xsize, ysize)
byte *buffer;
int xsize, ysize;
{
register int i;
int totalsize = xsize * ysize;
byte *nbuffer;
register byte *fin;
register byte *base, *line_before; /* pointers to new [blured] image */
register byte *last, *next_line; /* pointers to old [zoomed] image */
/* Allocate memory for new blured image */
nbuffer= (byte *) Malloc( totalsize );
/*
* First and last rows, and first and last pixels in
* each row are not modified, so we copy image into new
* buffer and keep all information.
*/
bcopy( buffer, nbuffer, totalsize );
/* Skip first and last row */
ysize--;
for ( i = 1; i < ysize; i++ ) {
/* Skip first pixel of current line */
base = nbuffer + i*xsize + 1;
/* Point to current line */
last = buffer + i*xsize + 1;
/* Point to line before */
line_before = last - xsize;
/* Point to next line */
next_line = last + xsize;
/*
* Pointer to last pixel for being modified of the current
* line ( skip last pixel ).
*/
fin = base + xsize - 1;
while ( base < fin ) {
/* Blur the current pixel */
*base++ = .4 * *last +
.1 * *(last-1) + .1 * *(last+1) +
.1 * *line_before + .1 * *next_line +
.05 * *(line_before-1) + .05 * *(line_before+1) +
.05 * *(next_line-1) + .05 * *(next_line+1);
/* Update pointers */
next_line++;
line_before++;
last++;
}
}
return nbuffer;
}
flip_image(inbitmap, outbitmap)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
{
/* Really, is an image ? */
if ( inbitmap->magic != LUGUSED )
error( 21 );
VPRINTF(stderr, "Flipping image\n");
/* Fill our header */
outbitmap->magic = LUGUSED;
outbitmap->xsize = inbitmap->xsize;
outbitmap->ysize = inbitmap->ysize;
outbitmap->depth = inbitmap->depth;
outbitmap->colors = inbitmap->colors;
outbitmap->r = flip( inbitmap->r, outbitmap->xsize, outbitmap->ysize );
if ( outbitmap->depth > 8 ) {
/* 24 planes */
outbitmap->g = flip( inbitmap->g, outbitmap->xsize, outbitmap->ysize );
outbitmap->b = flip( inbitmap->b, outbitmap->xsize, outbitmap->ysize );
}else outbitmap->cmap = inbitmap->cmap;
}
byte *flip(buffer, xsize, ysize)
byte *buffer;
int xsize, ysize;
{
register int i, j;
int twolines;
byte *image, *ptr;
ptr = image = (byte *) Malloc( xsize * ysize );
twolines = 2 * xsize;
buffer += xsize * ysize - xsize;
for ( i = 0; i < ysize; i++) {
for ( j = 0; j < xsize; j++ ) {
*ptr++ = *buffer++;
}
buffer -= twolines;
}
return image;
}
to24( inbitmap, outbitmap )
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
{
int total_size;
color_map *map;
byte *r, *g, *b;
byte *base;
byte *end;
/* Really, is an image ? */
if ( inbitmap->magic != LUGUSED )
error( 21 );
/* Fill new header */
outbitmap->magic = LUGUSED;
outbitmap->xsize = inbitmap->xsize;
outbitmap->ysize = inbitmap->ysize;
outbitmap->depth = 24;
outbitmap->colors = ( 1 << outbitmap->depth );
total_size = outbitmap->xsize * outbitmap->ysize;
r = outbitmap->r = (byte *) Malloc(total_size);
g = outbitmap->g = (byte *) Malloc(total_size);
b = outbitmap->b = (byte *) Malloc(total_size);
/* A pointer to cmap */
map = (color_map *) inbitmap->cmap;
/* A pointer to original 8 bits buffer */
base = inbitmap->r;
/* A pointer to the end */
end = base + total_size;
VPRINTF(stderr, "Reconverting to 24 planes\n");
while ( base < end ) {
*r++ = map[*base][0];
*g++ = map[*base][1];
*b++ = map[*base][2];
base++;
}
}
create_solid_image(image, xsize, ysize, r, g, b)
bitmap_hdr *image;
int xsize, ysize;
byte r, g, b;
{
int totalsize = xsize * ysize;
image->magic = LUGUSED;
image->xsize = xsize;
image->ysize = ysize;
image->depth = 24;
image->colors = ( 1 << image->depth );
image->r= (byte *) Malloc( totalsize );
image->g= (byte *) Malloc( totalsize );
image->b= (byte *) Malloc( totalsize );
if ( r )
memset( image->r, r, totalsize );
if ( g )
memset( image->g, g, totalsize );
if ( b )
memset( image->b, b, totalsize );
}
center_image( base, super )
bitmap_hdr *base, *super;
{
int xmid, ymid;
xmid = ( XSIZE / 2 ) - ( super->xsize / 2 );
ymid = ( YSIZE / 2 ) - ( super->ysize / 2 );
paste( base, super, xmid, ymid );
}
paste(base, super, xpos, ypos)
bitmap_hdr *base, *super;
int xpos, ypos;
{
register int i, j;
byte *r1, *g1, *b1;
byte *r2, *g2, *b2;
/* Really, are images ? */
if ( base->magic != LUGUSED || super->magic != LUGUSED )
error( 21 );
r1 = base->r, g1 = base->g, b1 = base->b;
r2 = super->r, g2 = super->g, b2 = super->b;
/*
* Skip pre-paste rows.
*/
for (i= 0; i< ypos; i++) {
r1 += base->xsize;
g1 += base->xsize;
b1 += base->xsize;
}
/*
* While we are inside surface to paste ...
*/
for ( i = 0; i < super->ysize; i++ ) {
for ( j = 0; j< base->xsize; j++ )
if ( j < xpos || j >= super->xsize+xpos ) {
r1++, g1++, b1++;
}else {
if ( (*r2 + *g2 + *b2) < CHROMABORDER ) {
r1++, g1++, b1++;
r2++, g2++, b2++;
}else {
*r1++ = *r2++;
*g1++ = *g2++;
*b1++ = *b2++;
}
}
}
}
chroma( base, super )
bitmap_hdr *base;
bitmap_hdr *super;
{
register int i, j;
byte *r1, *g1, *b1;
byte *r2, *g2, *b2;
/* Really, are images ? */
if ( base->magic != LUGUSED || super->magic != LUGUSED )
error( 21 );
/* Set pointers */
r1= base->r , g1= base->g , b1= base->b;
r2= super->r, g2= super->g, b2= super->b;
for ( i = 0; i < super->ysize; i++ ) {
for ( j = 0; j < base->xsize; j++ ) {
if ( j < super->xsize ) {
/* We are into super image. */
if ( (*r2 + *g2 + *b2) < CHROMABORDER ) {
r1++, g1++, b1++;
r2++, g2++, b2++;
}else {
*r1++ = *r2++;
*g1++ = *g2++;
*b1++ = *b2++;
}
}else {
/* Out of super borders */
r1++, g1++, b1++;
}
}
}
}
byte *create_bw_pallete()
{
register int i;
byte *buffer = (byte *) Malloc( 3 * 256 );
byte *ptr;
/* I'll use a pointer */
ptr = buffer;
for (i = 0; i < 256; i++) {
*ptr++= (byte) i; /* R */
*ptr++= (byte) i; /* G */
*ptr++= (byte) i; /* B */
}
return buffer;
}
/**************************************
*
* ALIAS interface
*
*/
read_alias_file( name, bitmap )
char *name;
bitmap_hdr *bitmap;
{
FILE *handle;
/* Open the file descriptor */
if ( name != NULL )
handle = Fopen( name, "r" );
else handle = stdin;
/* Read the bitmap */
read_alias( handle, bitmap );
/* Close the file */
Fclose( handle );
}
read_alias(handle, image)
FILE *handle;
bitmap_hdr *image;
{
register int i;
alias_hdr header;
int total_size;
register int xsize;
byte *end;
byte *r, *g, *b;
int can_read_all;
byte *buffer, *ptr;
int filesize;
int allplanes = 0;
int internalerror;
int cmapsize;
/*
* Alias "pix" is a bad format to read line per line. If every
* triplet is different to its next, then we read 4 bytes, 4 bytes ...
* ... and read a file of 1 Mb. with this form ... hmmmmmm !!!
* This is necesary if we are reading from stdin, but if we have
* a file, we'll read the file into memory ( one access to disk ).
*/
#ifndef DEC
can_read_all = (handle != stdin); /* a regular file ? */
VPRINTF(stderr, "Reading Alias from %s\n",
(can_read_all ? "file" : "stdin"));
#else
can_read_all = 0;
#endif
if (can_read_all) {
/*
* We are using a regular file ( not a pipe ), so we can
* read it into memory.
*/
ptr= buffer= (byte *) read_file(handle, &filesize);
VPRINTF(stderr, "File size: %d\n", filesize);
/* Copy the header */
bcopy(ptr, &header, sizeof(alias_hdr));
ptr += sizeof(alias_hdr); /* skip the header */
}else {
/*
* We are using stdin so ...
*/
/* We need the header of Alias pix */
VPRINTF(stderr, "Reading Alias header\n");
read_alias_header(handle, &header);
}
/* Size in pixels */
total_size = header.xsize * header.ysize;
/* Fill our header */
image->magic = LUGUSED;
image->xsize = header.xsize;
image->ysize = header.ysize;
image->depth = header.depth;
image->colors = 1 << image->depth;
allplanes = ( image->depth > 8 ); /* an image with 24 planes ? */
VPRINTF(stderr, "Image size: %dx%d\n", image->xsize, image->ysize);
VPRINTF(stderr, "Depth: %d\n", image->depth);
/* Get some memory */
if ( allplanes ) {
/*
* We have a image with 24 planes, so we need three buffers to
* store it.
*/
r= image->r = (byte *) Malloc(total_size);
g= image->g = (byte *) Malloc(total_size);
b= image->b = (byte *) Malloc(total_size);
}else {
/*
* The image has less than 256 colors, so we use one plane,
* for the bitmap, and the cmap.
*/
r= image->r = (byte *) Malloc(total_size);
cmapsize= image->colors * 3; /* size in bytes */
image->cmap = (byte *) Malloc(cmapsize);
/* Creating the cmap from file */
VPRINTF(stderr, "Creating cmap\n");
create_alias_cmap(image);
}
/*
* We are ready to uncompress Alias file.
*/
VPRINTF(stderr, "Uncompressing Alias file\n");
if (can_read_all) {
/*
* We have the file into memory so we uncode it directly.
*/
end = r + total_size; /* the end of main buffer */
if ( allplanes )
uncode_alias24(ptr, r, g, b, end);
else uncode_alias(ptr, r, end);
/*
* We have read the file and uncompressed, so we can
* free the memory ( and exit ).
*/
Free(buffer);
}else {
/*
* We'll read each line from Alias file ( stdin ) until we
* fill our buffers or we get an error.
*/
xsize = image->xsize;
for (i= 0; i< image->ysize; i++) {
/*
* Read and decode the Alias raster information, two cases:
* with planes > 8 => a triplet (RGB), else a index.
*/
if ( allplanes ) {
/* An image with 24 planes */
internalerror= read_line_alias24(handle, r, b, g, xsize);
}else {
/* An image with indexes to cmap */
internalerror= read_line_alias(handle, r, xsize);
}
if (internalerror) {
/* An error, so we exit */
fprintf(stderr, "Error while reading line %d\n", i);
return 1;
}else {
/* A line has been read, so we increment theirs pointers */
r += xsize;
if ( allplanes ) {
g += xsize;
b += xsize;
}
}
}
} /* end of reading from stdin */
/* Finish with no problems */
return 0;
}
read_alias_header(handle, header)
FILE *handle;
alias_hdr *header;
{
byte buffer[10];
/* Read the header */
Fread(buffer, 10, 1, handle);
/* Fill the header structure */
header->xsize = ( buffer[0] << 8 ) | buffer[1];
header->ysize = ( buffer[2] << 8 ) | buffer[3];
header->xinit = ( buffer[4] << 8 ) | buffer[5];
header->yinit = ( buffer[6] << 8 ) | buffer[7];
header->depth = ( buffer[8] << 8 ) | buffer[9];
/* Check some things */
if ( header->xsize < 1 || header->xsize > 2560 ||
header->ysize < 1 || header->ysize > 2560 )
error(5);
if ( header->depth > 24 || header->depth < 1 )
error(5);
}
read_line_alias24(handle, r, g, b, size)
FILE *handle;
byte *r, *g, *b;
register int size;
{
register int i;
register int count = 0;
byte *end;
byte buffer[4];
end = r + size;
while (count < size) {
/*
* Alias code format: <repeat>BGR => 4 bytes.
*/
if ( !fread(buffer, 4, 1, handle) ) /* read next buffer */
return 1; /* hey !, an EOF here ?. Hmmmm, this is an error ! */
count += buffer[0]; /* # of repetitions */
/* repeat 'buffer[0]' times these triplet */
for (i= 0; i< buffer[0]; i++) {
*r++ = buffer[3];
*g++ = buffer[1];
*b++ = buffer[2];
}
if ( r > end )
error(6); /* uncompress more bytes than size */
}
/* No problems */
return 0;
}
read_line_alias(handle, r, size)
FILE *handle;
byte *r;
register int size;
{
register int i;
register int count = 0;
byte *end;
byte buffer[2];
end = r + size;
while (count < size) {
/*
* Alias code format: <repeat><index> => 2 bytes.
*/
if ( !fread(buffer, 2, 1, handle) ) /* read next buffer */
return 1; /* hey !, an EOF here ?. Hmmmm, this is an error ! */
count += buffer[0]; /* # of repetitions */
/* repeat 'buffer[0]' times these index */
for (i= 0; i< buffer[0]; i++) {
*r++ = buffer[1];
}
if ( r > end )
error(6); /* uncompress more bytes than size */
}
/* No problems */
return 0;
}
create_alias_cmap(image)
bitmap_hdr *image;
{
register int i;
byte *ptr;
/*
* Alias 8 bits files are b&w, so ...
*/
ptr = (byte *) image->cmap;
for (i= 0; i< image->colors; i++) {
*ptr++ = i;
*ptr++ = i;
*ptr++ = i;
}
}
uncode_alias24(ptr, rbuf, gbuf, bbuf, end)
byte *ptr;
byte *rbuf, *gbuf, *bbuf;
byte *end;
{
register int i;
byte r, g, b;
while ( rbuf < end ) { /* while not end of buffer */
if ( (i= *ptr++) > 1 ) { /* how mary repetitions ? */
b= *ptr++;
g= *ptr++;
r= *ptr++;
while( i-- ) { /* copy these triplet 'i' times */
*rbuf++ = r;
*gbuf++ = g;
*bbuf++ = b;
}
}else { /* else, copy these triplet */
*bbuf++ = *ptr++;
*gbuf++ = *ptr++;
*rbuf++ = *ptr++;
}
}
}
uncode_alias(ptr, rbuf, end)
byte *ptr;
byte *rbuf;
byte *end;
{
register int i;
byte r;
while ( rbuf < end ) { /* while not end of buffer */
if ( (i= *ptr++) > 1 ) { /* how mary repetitions ? */
r= *ptr++;
while( i-- ) { /* copy these index 'i' times */
*rbuf++ = r;
}
}else { /* else, copy these index */
*rbuf++ = *ptr++;
}
}
}
/**************************************
*
* Wavefront's RLA interface.
*
*/
read_rla_file( name, bitmap )
char *name;
bitmap_hdr *bitmap;
{
FILE *handle;
/* Open the file descriptor */
if ( name != NULL )
handle = Fopen( name, "r" );
else error( 20 );
/* Read the bitmap */
read_rla( handle, bitmap );
/* Close the file */
Fclose( handle );
}
read_rla(handle, image)
FILE *handle;
bitmap_hdr *image;
{
register int i, j;
RLA_HEADER rla;
int totalsize;
byte *r, *g, *b;
int *offsets;
short no_bytes;
byte *ptr;
byte *raux, *gaux, *baux;
byte *rptr, *gptr, *bptr;
/*
* Read the RLA's header.
*/
Fread(&rla, 740, 1, handle);
image->magic = LUGUSED;
image->xsize = rla.window.right - rla.window.left + 1;
image->ysize = rla.window.top - rla.window.bottom + 1;
image->depth = 24;
image->colors = ( 1 << image->depth );
totalsize= image->xsize * image->ysize;
if ( image->xsize < 1 || image->xsize > 2559 ||
image->ysize < 1 || image->ysize > 2559 )
error(5);
/*
* Allocate for bitmap components.
*/
r = image->r = (byte *) Malloc(totalsize);
g = image->g = (byte *) Malloc(totalsize);
b = image->b = (byte *) Malloc(totalsize);
/* Some space to unpack scanlines */
raux = (byte *) Malloc(image->xsize);
gaux = (byte *) Malloc(image->xsize);
baux = (byte *) Malloc(image->xsize);
ptr = (byte *) Malloc(2560);
/* Allocate space for offsets */
offsets = (int *) Malloc(image->ysize*sizeof(int));
Fread(offsets, sizeof(int), image->ysize, handle);
for (i = rla.window.top; i >= rla.window.bottom; i--) {
if ( i > rla.act_window.top || i < rla.act_window.bottom ) {
/* Outlines => zeros ( done with Malloc ) */
r += image->xsize;
g += image->xsize;
b += image->xsize;
}else {
/*
* Set pointer where offsets table says.
*/
if (fseek(handle, (long) offsets[i - rla.act_window.bottom], 0))
error( 20 );
/*
* Uncode R channel.
*/
Fread(&no_bytes, sizeof(short), 1, handle);
Fread(ptr, (int) no_bytes, 1, handle);
decodeRLA(ptr, raux, no_bytes);
/*
* Uncode G channel.
*/
Fread(&no_bytes, sizeof(short), 1, handle);
Fread(ptr, (int) no_bytes, 1, handle);
decodeRLA(ptr, gaux, no_bytes);
/*
* Uncode B channel.
*/
Fread(&no_bytes, sizeof(short), 1, handle);
Fread(ptr, (int) no_bytes, 1, handle);
decodeRLA(ptr, baux, no_bytes);
/*
* If you wanna you do the same task with matte ( but I
* don't mind that channel ).
*/
/*
* We uncode the active window, now we fill the real window
* with these datas and aditional zeros.
*/
rptr= raux;
gptr= gaux;
bptr= baux;
for (j = rla.window.left; j <= rla.window.right; j++) {
if ( j < rla.act_window.left || j > rla.act_window.right ) {
/* Outlines => zeros ( done with Malloc ) */
*r++, *g++, *b++;
}else {
*r++ = *rptr++;
*g++ = *gptr++;
*b++ = *bptr++;
}
}
}
}
/*
* Free memory.
*/
Free(raux);
Free(gaux);
Free(baux);
Free(offsets);
Free(ptr);
/* no errors */
return 0;
}
decodeRLA(buf_in, buf_out, len)
byte *buf_in;
byte *buf_out;
int len;
{
int ct;
byte *end;
end = buf_out + len;
while(len > 0) {
ct = *buf_in++;
len--;
if (ct < 128) {
/* repeat pixel value ct+1 times */
while (ct-- >= 0)
*buf_out++ = *buf_in;
buf_in++;
len--;
}
else {
/* copy ct unencoded values */
for (ct = 256-ct; ct-- > 0; len--)
*buf_out++ = *buf_in++;
}
/* if ( buf_out > end )
error(6);*/
}
}
/**************************************
*
* SGI interface
*
*/
read_sgi_file( name, bitmap )
char *name;
bitmap_hdr *bitmap;
{
register int i, j;
IMAGE *sgi_image;
byte *r, *g, *b;
short *sgibuf;
int totalsize;
int flag24;
VPRINTF(stderr, "Reading SGI image\n");
if ( (sgi_image = iopen( name, "r" )) == NULL )
error( 1 );
/* if ( sgi_image->zsize < 3 )
error( 7 ); */
/*
* Fill our header.
*/
bitmap->magic = LUGUSED;
bitmap->xsize = sgi_image->xsize;
bitmap->ysize = sgi_image->ysize;
bitmap->depth = 8 * sgi_image->zsize;
bitmap->colors = ( 1 << bitmap->depth );
flag24 = (bitmap->depth > 8);
totalsize = bitmap->xsize * bitmap->ysize;
r = bitmap->r = (byte *) Malloc( totalsize );
if ( flag24 ) {
g = bitmap->g = (byte *) Malloc( totalsize );
b = bitmap->b = (byte *) Malloc( totalsize );
}else bitmap->cmap = (byte *) create_bw_pallete();
/*
* Allocate memory for sgi raster line.
*/
sgibuf = (short *) Malloc( sizeof(short) * bitmap->xsize );
for ( i = 0; i < bitmap->ysize; i++ ) {
j = bitmap->ysize - 1 - i;
getrow( sgi_image, sgibuf, j, 0 );
(void) shorttobyte( sgibuf, r, bitmap->xsize );
r += bitmap->xsize;
if ( flag24 ) {
getrow( sgi_image, sgibuf, j, 1 );
(void) shorttobyte( sgibuf, g, bitmap->xsize );
g += bitmap->xsize;
getrow( sgi_image, sgibuf, j, 2 );
(void) shorttobyte( sgibuf, b, bitmap->xsize );
b += bitmap->xsize;
}
}
iclose( sgi_image );
Free( sgibuf );
}
/**************************************
*
* TARGA interface
*
*/
read_tga_file( name, bitmap )
char *name;
bitmap_hdr *bitmap;
{
FILE *handle;
bitmap_hdr image;
/* Open the file descriptor */
if ( name != NULL )
handle = Fopen( name, "r" );
else handle = stdin;
/* Read the bitmap */
read_tga( handle, &image );
/* Close the file */
Fclose( handle );
/*
* Now we could have a 8 or 24 bits image, but 'tovcr'
* needs true color images, so check it...
*/
if ( image.depth > 8 ){
copy_bitmap( &image, bitmap );
}else {
to24( &image, bitmap );
}
/* Free the tmp bitmap */
freebitmap( &image );
}
read_tga(handle, image)
FILE *handle;
bitmap_hdr *image;
{
register int i;
tga_hdr tga;
int allplanes = 0;
int lessplanes = 0;
int forceallplanes = 0;
byte aux4[4];
int totalsize;
byte *ptr;
byte *r, *g, *b;
byte *aux;
/* Read the Tagar header */
read_tga_header( handle, &tga );
/* Fill our header */
image->magic = LUGUSED;
image->xsize = tga.xsize;
image->ysize = tga.ysize;
totalsize = image->xsize * image->ysize;
/*
* Targa format can be mapped but with moer than 256 colors,
* our mapped images only support 8 bits, so we need convert
* these images to 24 bits.
*/
switch ( tga.image_type ) {
case TGA_RGB:
case TGA_RLE_RGB:
allplanes = 1;
break;
case TGA_MAPPED:
case TGA_RLE_MAPPED:
lessplanes = 1;
if ( tga.cmap_type != 1 )
error( 10 );
if ( tga.cmap_length > 256 )
forceallplanes = 1;
break;
}
/*
* Read the cmap info ( if exists ).
*/
if ( tga.cmap_type ) {
VPRINTF(stderr, "Reading cmap info\n");
if ( allplanes ) {
/* We only need skip the cmap block */
for ( i = 0; i < tga.cmap_length; i++ )
read_tga_data( aux4, tga.cmap_entry_size, handle );
}else {
ptr = image->cmap = (byte *) Malloc( 3 * tga.cmap_length );
for ( i = 0; i < tga.cmap_length; i++) {
read_tga_data( ptr, tga.cmap_entry_size, handle );
ptr += 3;
}
}
}
/*
* Allocate memory for the bitmap and fill our header.
*/
image->xsize = tga.xsize;
image->ysize = tga.ysize;
totalsize = image->xsize * image->ysize;
if ( allplanes || forceallplanes ) {
r = image->r = (byte *) Malloc( totalsize );
g = image->g = (byte *) Malloc( totalsize );
b = image->b = (byte *) Malloc( totalsize );
image->depth = 24;
}else {
r = image->r = (byte *) Malloc( totalsize );
image->depth = no_bits( tga.cmap_length ) + 1;
}
image->colors = ( 1 << image->depth );
/*
* Read the raster information.
*/
if ( allplanes ) {
read_tga24( handle, r, g, b, &tga );
}else if ( forceallplanes )
read_tga_to24( handle, r, g, b, &tga, image->cmap );
else read_tga8( handle, r, &tga );
if ( TGAFLIP( tga.image_descriptor ) ) {
VPRINTF(stderr, "Flipping the image\n");
aux = (byte *) flip( r, image->xsize, image->ysize );
Free( r );
image->r = aux;
if ( allplanes ) {
/* A true color image, so we have G and B buffers */
aux = (byte *) flip( g, image->xsize, image->ysize );
Free( g );
image->g = aux;
aux = (byte *) flip( b, image->xsize, image->ysize );
Free( b );
image->b = aux;
}
}
}