cnv/rlatorle.c
/*
* 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.
*/
/*
* rlatorle - A program which will convert Wavefront's "rla" or "rlb" images
* into Utah's "rle" image format.
*
* Author: Wesley C. Barris
* AHPCRC
* Minnesota Supercomputer Center, Inc.
* Date: June 20, 1990
* Copyright @ 1990, Minnesota Supercomputer Center, Inc.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure of this software and its documentation
* by the Government is subject to restrictions as set forth in subdivision
* { (b) (3) (ii) } of the Rights in Technical Data and Computer Software
* clause at 52.227-7013.
*/
static char rcsid[] = "$Header: /l/spencer/src/urt/cnv/RCS/rlatorle.c,v 3.0.1.5 1992/04/30 13:58:32 spencer Exp $";
/*
rlatorle() Tag the file.
*/
/*-----------------------------------------------------------------------------
* System includes.
*/
#include "rle.h"
#include <string.h>
#include "rla_header.h"
#include "rlb_header.h"
#define VPRINTF if (verbose || header) fprintf
typedef unsigned char U_CHAR;
/*
* Global variables.
*/
rle_hdr hdr;
union
{
RLA_HEADER rla_head;
RLB_HEADER rlb_head;
} head;
#ifdef CRAY2CC
#define SHORTREAD(var, fp) {fread(&craybuf, 2, 1, fp); *var=craybuf>>48;}
#define LONGREAD(var, fp) {fread(&craybuf, 4, 1, fp); *var=craybuf>>32;}
#else
#define SHORTREAD(var, fp) {fread(var, 2, 1, fp);}
#define LONGREAD(var, fp) {fread(var, 4, 1, fp);}
#endif
static FILE *fp;
static int act_x_res, act_y_res;
static int width, height;
static int verbose = 0, header = 0, do_matte = 0;
static int rlb_flag = 0;
/*-----------------------------------------------------------------------------
* Read the Wavefront image file header.
*/
void read_rla_header(act_x_res, act_y_res, width, height)
int *act_x_res;
int *act_y_res;
int *width;
int *height;
{
#ifdef CRAY2CC
long craybuf;
SHORTREAD(&head.rla_head.window.left, fp);
SHORTREAD(&head.rla_head.window.right, fp);
SHORTREAD(&head.rla_head.window.bottom, fp);
SHORTREAD(&head.rla_head.window.top, fp);
SHORTREAD(&head.rla_head.active_window.left, fp);
SHORTREAD(&head.rla_head.active_window.right, fp);
SHORTREAD(&head.rla_head.active_window.bottom, fp);
SHORTREAD(&head.rla_head.active_window.top, fp);
SHORTREAD(&head.rla_head.frame, fp);
SHORTREAD(&head.rla_head.storage_type, fp);
SHORTREAD(&head.rla_head.num_chan, fp);
SHORTREAD(&head.rla_head.num_matte, fp);
SHORTREAD(&head.rla_head.num_aux, fp);
SHORTREAD(&head.rla_head.aux_mask, fp);
fread(&head.rla_head.gamma, 16, 1, fp);
fread(&head.rla_head.red_pri, 24, 1, fp);
fread(&head.rla_head.green_pri, 24, 1, fp);
fread(&head.rla_head.blue_pri, 24, 1, fp);
fread(&head.rla_head.white_pt, 24, 1, fp);
LONGREAD(&head.rla_head.job_num, fp);
fread(&head.rla_head.name, 128, 1, fp);
fread(&head.rla_head.desc, 128, 1, fp);
fread(&head.rla_head.program, 64, 1, fp);
fread(&head.rla_head.machine, 32, 1, fp);
fread(&head.rla_head.user, 32, 1, fp);
fread(&head.rla_head.date, 20, 1, fp);
if (rlb_flag) {
fread(&head.rlb_head.aspect, 24, 1, fp);
fread(&head.rlb_head.aspect_ratio, 8, 1, fp);
fread(&head.rlb_head.chan, 32, 1, fp);
SHORTREAD(&head.rlb_head.field, fp);
SHORTREAD(&head.rlb_head.filter_type, fp);
LONGREAD(&head.rlb_head.magic_number, fp);
LONGREAD(&head.rlb_head.lut_size, fp);
LONGREAD(&head.rlb_head.user_space_size, fp);
LONGREAD(&head.rlb_head.wf_space_size, fp);
SHORTREAD(&head.rlb_head.lut_type, fp);
SHORTREAD(&head.rlb_head.mix_type, fp);
SHORTREAD(&head.rlb_head.encode_type, fp);
SHORTREAD(&head.rlb_head.padding, fp);
fread(&head.rlb_head.space, 100, 1, fp);
}
else {
fread(&head.rla_head.aspect, 32, 1, fp);
fread(&head.rla_head.chan, 32, 1, fp);
fread(&head.rla_head.space, 128, 1, fp);
}
#else
if (fread(&head, 740, 1, fp) != 1) {
fprintf(stderr, "Error reading Wavefront file header!\n");
exit(-2);
}
#endif
*act_x_res = head.rla_head.active_window.right-
head.rla_head.active_window.left+1;
*act_y_res = head.rla_head.active_window.top-
head.rla_head.active_window.bottom+1;
*width = head.rla_head.window.right-head.rla_head.window.left+1;
*height = head.rla_head.window.top-head.rla_head.window.bottom+1;
VPRINTF(stderr, "Full image: %dx%d\n", *width, *height);
VPRINTF(stderr, "Active window: %dx%d\n", *act_x_res, *act_y_res);
VPRINTF(stderr, "Number of channels: %d\n", head.rla_head.num_chan);
VPRINTF(stderr, "Number of mattes: %d\n", head.rla_head.num_matte);
VPRINTF(stderr, "Image gamma: %s\n", head.rla_head.gamma);
VPRINTF(stderr, "Original filename: %s\n", head.rla_head.name);
VPRINTF(stderr, "Description: %s\n", head.rla_head.desc);
VPRINTF(stderr, "Machine: %s\n", head.rla_head.machine);
VPRINTF(stderr, "User: %s\n", head.rla_head.user);
VPRINTF(stderr, "Date: %s\n", head.rla_head.date);
if ( rlb_flag ) {
VPRINTF(stderr, "Aspect: %s\n", head.rlb_head.aspect);
VPRINTF(stderr, "Aspect ratio: %s\n", head.rlb_head.aspect_ratio);
}
else {
VPRINTF(stderr, "Aspect: %s\n", head.rla_head.aspect);
VPRINTF(stderr, "Aspect ratio: %s\n", "-unused-");
}
VPRINTF(stderr, "Channel color space %s\n", head.rla_head.chan);
if ( rlb_flag )
VPRINTF(stderr, "Interlaced? %s\n", head.rlb_head.filter_type);
else
VPRINTF(stderr, "Interlaced? %s\n", "-unused-");
if (do_matte)
VPRINTF(stderr, "Converting matte channel only...\n");
}
/*-----------------------------------------------------------------------------
* Write the rle image file header.
*/
void write_rle_header()
{
hdr.xmin = head.rla_head.window.left;
hdr.xmax = head.rla_head.window.right;
hdr.ymin = head.rla_head.window.bottom;
hdr.ymax = head.rla_head.window.top;
hdr.alpha = (head.rla_head.num_matte && !do_matte ? 1 : 0);
hdr.ncolors = (do_matte ? 1 : head.rla_head.num_chan);
/*hdr.ncmap = (map ? 3 : 0);*/
/*hdr.cmaplen = (map ? 8 : 0);*/
/*hdr.cmap = (map ? color_map : NULL);*/
rle_putcom(head.rla_head.desc, &hdr);
/*hdr.background = 0;*/
if (hdr.alpha)
RLE_SET_BIT(hdr, RLE_ALPHA);
if (!do_matte) {
RLE_SET_BIT(hdr, RLE_RED);
RLE_SET_BIT(hdr, RLE_GREEN);
RLE_SET_BIT(hdr, RLE_BLUE);
}
rle_put_setup(&hdr);
}
/*-----------------------------------------------------------------------------
* Decode run length encoded pixels.
*/
void
decode(c_in, c_out, len)
U_CHAR *c_in;
U_CHAR *c_out;
int len;
{
int ct;
while(len > 0) {
ct = *c_in++;
len--;
if (ct < 128) {
/*
* Repeat pixel value ct+1 times.
*/
while (ct-- >= 0)
*c_out++ = *c_in;
c_in++;
len--;
}
else {
/*
* Copy ct unencoded values.
*/
for (ct = 256-ct; ct-- > 0; len--)
*c_out++ = *c_in++;
}
}
}
/*-----------------------------------------------------------------------------
* Write the rle data portion of the file.
*/
void write_rle_data()
{
int *offset;
int x;
int bottom;
int left;
int scan;
#ifdef CRAY2CC
long craybuf;
#endif
U_CHAR *red, *green, *blue, *matte;
U_CHAR *buf;
short len;
rle_pixel *scanline[4];
/*
* Read scanline offset table.
*/
if (!(offset = (int *)malloc(sizeof(int) * act_y_res))) {
fprintf(stderr, "Offset malloc failed!\n");
exit(-3);
}
#ifdef CRAY2CC
for (scan=0;scan<act_y_res;scan++) {
fread(&craybuf, 4, 1, fp); offset[scan] = craybuf >> 32;
}
#else
if (fread(offset, 4, act_y_res, fp) != act_y_res) {
fprintf(stderr, "Offset table read failed!\n");
exit(-4);
}
#endif
/*
* Allocate some memory.
*/
if (!(buf = (U_CHAR *)malloc(width * 2))) {
fprintf(stderr, "Buf malloc failed!\n");
exit(-7);
}
if (!(red = (U_CHAR *)malloc(width * 4))) {
fprintf(stderr, "Red scanline malloc failed!\n");
exit(-8);
}
green = &red[width];
blue = &green[width];
matte = &blue[width];
/*bzero((char *)blank, width*4);*/
if (((scanline[0]=(rle_pixel *)malloc(width))==NULL) ||
((scanline[1]=(rle_pixel *)malloc(width))==NULL) ||
((scanline[2]=(rle_pixel *)malloc(width))==NULL) ||
((scanline[3]=(rle_pixel *)malloc(width))==NULL)) {
fprintf(stderr, "Unable to malloc space for pixels\n");
exit(-1);
}
/*
* Loop through the rla files image window, write blank lines outside
* active window.
*/
bottom = head.rla_head.active_window.bottom;
left = head.rla_head.active_window.left;
for (scan = head.rla_head.window.bottom;
scan <= head.rla_head.window.top; scan++) {
/*
* Check for black regions outside active window.
*/
if ((scan < head.rla_head.active_window.bottom) ||
(scan > head.rla_head.active_window.top))
rle_skiprow(&hdr, 1);
else {
if (fseek(fp, (long)offset[scan-bottom], 0)) {
fprintf(stderr, "rla file incomplete!\n");
exit(-9);
}
/*
* Red scanline.
*/
SHORTREAD(&len, fp);
fread(buf, 1, (int)len, fp);
decode(buf, red, (int)len);
/*
* Green scanline.
*/
SHORTREAD(&len, fp);
fread(buf, 1, (int)len, fp);
decode(buf, green, (int)len);
/*
* Blue scanline.
*/
SHORTREAD(&len, fp);
fread(buf, 1, (int)len, fp);
decode(buf, blue, (int)len);
/*
* Matte scanline.
*/
SHORTREAD(&len, fp);
fread(buf, 1, (int)len, fp);
decode(buf, matte, (int)len);
/*
* Write out RGBM for each pixel.
*/
for (x=head.rla_head.window.left;
x<=head.rla_head.window.right; x++) {
if ((x < head.rla_head.active_window.left) ||
(x > head.rla_head.active_window.right)) {
scanline[0][x] = 0;
scanline[1][x] = 0;
scanline[2][x] = 0;
scanline[3][x] = 0;
}
else
if (do_matte) {
scanline[0][x] = (red[x-left] ||
green[x-left] ||
blue[x-left] ? 255 : 0);
}
else {
scanline[0][x] = matte[x-left];
scanline[1][x] = red[x-left];
scanline[2][x] = green[x-left];
scanline[3][x] = blue[x-left];
}
}
if (do_matte)
rle_putrow(scanline, width, &hdr);
else
rle_putrow(scanline + 1, width, &hdr);
} /* end of if scan is within active y */
} /* end of for every scanline */
VPRINTF(stderr, "Done -- write oef to RLE data.\n");
rle_puteof(&hdr);
/*
* Free up some stuff.
*/
free(offset);
/*free(blank);*/
free(buf);
free(red);
free(scanline[0]);
free(scanline[1]);
free(scanline[2]);
free(scanline[3]);
}
/*-----------------------------------------------------------------------------
* Convert an Wavefront image file into an rle image file.
*/
int
main(argc, argv)
int argc;
char **argv;
{
char *periodP, *inname = NULL, *outname = NULL;
static char filename[BUFSIZ];
int oflag = 0;
/*
* Get those options.
*/
if (!scanargs(argc,argv,
"% b%- v%- h%- m%- o%-outfile!s infile.rla%s",
&rlb_flag,
&verbose,
&header,
&do_matte,
&oflag, &outname,
&inname))
exit(-1);
/*
* Open the file.
*/
if (inname == NULL) {
strcpy(filename, "stdin");
fp = stdin;
}
else {
periodP = strrchr(inname, (int)'.');
strcpy(filename, inname);
if (periodP) {
if (rlb_flag) {
if (strcmp(periodP, ".rlb")) { /* does not end in rla */
if (!strcmp(periodP, ".rla")) {
fprintf(stderr, "This is an rla file -- don't use the -b flag.\n");
exit(1);
}
strcat(filename, ".rlb");
}
}
else {
if (strcmp(periodP, ".rla")) { /* does not end in rla */
if (!strcmp(periodP, ".rlb"))
rlb_flag = 1;
else
strcat(filename, ".rla");
}
}
}
else /* no ext -- add one */
if (rlb_flag)
strcat(filename, ".rlb");
else
strcat(filename, ".rla");
if (!(fp = fopen(filename, "r"))) {
fprintf(stderr, "Cannot open %s for reading.\n", filename);
exit(-1);
}
}
/*
* Read the Wavefront file file header.
*/
read_rla_header(&act_x_res, &act_y_res, &width, &height);
if (header)
exit(0);
/*
* Write the rle file header.
*/
hdr = *rle_hdr_init( (rle_hdr *)NULL );
hdr.rle_file = rle_open_f( cmd_name(argv), outname, "w" );
rle_names( &hdr, cmd_name(argv), outname, 0 );
rle_addhist(argv, (rle_hdr *)NULL, &hdr);
write_rle_header();
/*
* Write the rle file data.
*/
write_rle_data();
fclose(fp);
return 0;
}