/* * 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. */ /* * pix.c - interface with Alias "pix" format. * * Author: Raul Rivero * Mathematics Dept. * University of Oviedo * Date: Mon Jan 6 1992 * Copyright (c) 1992, Raul Rivero * */ #include #include extern int LUGverbose; read_alias_file( name, bitmap ) char *name; bitmap_hdr *bitmap; { FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "rb" ); else handle = stdin; /* Read the bitmap */ read_alias( handle, bitmap ); rm_compress(); /* 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 ). */ #ifdef NO_BIGENDIAN can_read_all = 0; #else can_read_all = (handle != stdin); /* a regular file ? */ VPRINTF(stderr, "Reading Alias from %s\n", (can_read_all ? "file" : "stdin")); #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: 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: => 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++; } } } write_alias_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_alias( handle, image ); /* Close the file */ Fclose( handle ); } write_alias(handle, image) FILE *handle; bitmap_hdr *image; { register int i; byte buffer[10]; byte *rbuf, *gbuf, *bbuf; if ( image->magic != LUGUSED ) error( 19 ); /* * Alias 8 bits files are b&w ( no cmap ), so Alias * don't support really a 8 bits file. */ if (image->depth <= 8) { fprintf(stderr, "Bitmap with 8 planes\n"); error(99); } VPRINTF(stderr, "Writing Alias file\n"); /* Fill the Alias header and write it */ buffer[0] = MSB( image->xsize ); buffer[1] = LSB( image->xsize ); buffer[2] = MSB( image->ysize ); buffer[3] = LSB( image->ysize ); buffer[4] = 0; buffer[5] = 0; buffer[6] = 0; buffer[7] = 0; buffer[8] = MSB( image->depth ); buffer[9] = LSB( image->depth ); Fwrite( buffer, 10, 1, handle ); /* Set the pointers to buffers */ rbuf = image->r; gbuf = image->g; bbuf = image->b; /* Compress each line */ for (i= 0; i< image->ysize; i++) { /* * Alias "pix" format do a compression method on * each raster line. */ code_alias24(rbuf, gbuf, bbuf, image->xsize, handle); /* Move pointers to next lines */ rbuf += image->xsize; gbuf += image->xsize; bbuf += image->xsize; } } code_alias24(rbuf, gbuf, bbuf, xmax, handle) byte *rbuf, *gbuf, *bbuf; int xmax; FILE *handle; { byte r, g, b; unsigned int number= 0; int repeat= 1; static byte buf[5120]; byte *bufptr, *end; bufptr= buf; end= rbuf + xmax; r= *rbuf++; g= *gbuf++; b= *bbuf++; while (rbuf < end) /* * While we have the same pattern ( and < 255 ), we continue * skipping bytes ( pixels ). */ if (r== *rbuf && g== *gbuf && b== *bbuf && repeat < 255) { repeat++; rbuf++; gbuf++; bbuf++; }else { /* * A different triple or repeat == 255 was found, then we add * this to the output buffer. */ *bufptr++ = repeat; *bufptr++ = b; *bufptr++ = g; *bufptr++ = r; number += 4; repeat = 1; r= *rbuf++; g= *gbuf++; b= *bbuf++; } /* * We need add the last triplet. */ *bufptr++ = repeat; *bufptr++ = b; *bufptr++ = g; *bufptr++ = r; number += 4; /* * And ... write it ! */ Fwrite(buf, number, 1, handle); }