/* * 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. */ /* * rla.c - interface with Wavefront's RLA format. * * Author: Raul Rivero * Mathematics Dept. * University of Oviedo * Date: Sat Jan 4 1992 * Copyright (c) 1992, Raul Rivero * */ #include #include #include #define no_complete() { Error( 18 ); \ free(raux); \ free(gaux); \ free(baux); \ free(offsets); \ free(ptr); \ return 1; } extern int LUGverbose; read_rla_file( name, bitmap ) char *name; bitmap_hdr *bitmap; { FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "rb" ); else error( 20 ); /* Read the bitmap */ read_rla( handle, bitmap ); rm_compress(); /* 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)) no_complete(); /* * 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);*/ } } write_rla_file( name, image ) char *name; bitmap_hdr *image; { FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "wb" ); else handle = stdout; /* Write the bitmap */ write_rla( handle, image ); /* Close the file */ Fclose( handle ); } write_rla(handle, image) FILE *handle; bitmap_hdr *image; { register int i; RLA_HEADER header; byte *matte; int *offsets; byte *r, *g, *b; byte buffer[2560]; short no_bytes; if ( image->magic != LUGUSED ) error( 19 ); /* Fill RLA's header with zeros ( and save later work ) */ bzero(&header, 740); VPRINTF(stderr, "Writing RLA's header\n"); /* Fill RLA's header ( with datas ) */ header.window.left = 0; header.window.bottom = 0; header.window.right = image->xsize - 1; header.window.top = image->ysize - 1; /* Sorry, but I don't define the active window */ header.act_window.left = 0; header.act_window.bottom = 0; header.act_window.right = image->xsize - 1; header.act_window.top = image->ysize - 1; /* Three channels, RGB */ header.num_chan = 3; /* One matte channel, puff ! */ header.num_matte = 1; /* Other definitions */ header.frame = 1; strcpy( header.gamma, "2.2" ); strcpy( header.red_pri , "0.670 0.330" ); strcpy( header.green_pri, "0.210 0.710" ); strcpy( header.blue_pri , "0.140 0.080" ); strcpy( header.white_pt , "0.310 0.316" ); strcpy( header.name, "unknown" ); strcpy( header.desc, "converted from LUG library" ); gethostname( header.machine, 32 ); strcpy( header.user, cuserid(NULL) ); strcpy( header.aspect, "user defined" ); strcpy( header.chan, "rgb" ); /* * Write the RLA's header. */ fwrite(&header, 740, 1, handle), fflush(handle); /* * Allocate memory for offset buffer ( and a simulated * scanline matte table ). */ offsets = (int *) Malloc( image->ysize * sizeof(int) ); matte = (byte *) Malloc( image->xsize ); /* * We need write the ( incorrect ) offsets now, so that ... */ fwrite(offsets, image->ysize, sizeof(int), handle); VPRINTF( stderr, "Compressing scanline info\n"); r = image->r; g = image->g; b = image->b; for ( i = 0; i < image->ysize; i++ ) { #ifdef DEBUG VPRINTF( stderr, "Line: %4d\r", i); VFLUSH( stderr ); #endif /* Store the file position */ offsets[image->ysize-i-1]= (int) ftell(handle); /* * R channel. */ no_bytes = encodeRLA(r, buffer, image->xsize); Fwrite( &no_bytes, sizeof(short), 1, handle ); Fwrite( buffer, 1, no_bytes, handle ); r += image->xsize; /* * G channel. */ no_bytes = encodeRLA(g, buffer, image->xsize); Fwrite( &no_bytes, sizeof(short), 1, handle ); Fwrite( buffer, 1, no_bytes, handle ); g += image->xsize; /* * B channel. */ no_bytes = encodeRLA(b, buffer, image->xsize); Fwrite( &no_bytes, sizeof(short), 1, handle ); Fwrite( buffer, 1, no_bytes, handle ); b += image->xsize; /* * Matte channel ( always the same but ... ). */ no_bytes = encodeRLA(matte, buffer, image->xsize); Fwrite( &no_bytes, sizeof(short), 1, handle ); Fwrite( buffer, 1, no_bytes, handle ); } VPRINTF( stderr, "Rewriting offsets\n"); /* * Well, now we have the correct offsets and we need * write them, so ... */ fflush(handle); fseek(handle, 740, 0); fwrite(offsets, image->ysize, sizeof(int), handle); /* * Free memory. */ free(matte); free(offsets); } encodeRLA(c_in, c_out, width) byte *c_in; byte *c_out; int width; { int len; int ct; len = 0; while ( width > 0 ) { if ( width > 1 && c_in[0] == c_in[1] ) { for ( ct = 2; ct < width; ct++ ) { if ( c_in[ct] != c_in[ct-1] ) break; if (ct >= 127) break; } /* write out count */ *c_out++ = ct - 1; len++; /* write out value */ *c_out++ = *c_in; len++; width -= ct; c_in += ct; }else { for ( ct = 1; ct < width; ct++ ) { if ( width - ct > 1 && c_in[ct] == c_in[ct+1] ) break; if (ct >= 127) break; } /* write out count */ *c_out++ = 256 - ct; len++; /* copy string of pixels */ for ( ; ct-- > 0; len++, width-- ) *c_out++ = *c_in++; } } return len; }