/* * 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. */ /* +------------------------------------------------------------------+ */ /* | Copyright 1989, David Koblas. | */ /* | You may copy this file in whole or in part as long as you | */ /* | don't try to make money off it, or pretend that you wrote it. | */ /* +------------------------------------------------------------------+ */ #include #include "rle.h" #ifdef USE_STDLIB_H #include #else #ifdef USE_STRING_H #include #else #include #endif #ifdef VOID_STAR extern void *malloc(); #else extern char *malloc(); #endif extern void free(); #endif /* USE_STDLIB_H */ #ifndef lint static char rcsid[] = "$Id: giftorle.c,v 1.1.1.1 1993/10/05 08:51:29 ljo Exp $"; #endif #define MAXCOLORMAPSIZE 256 #define TRUE 1 #define FALSE 0 #define CM_RED 0 #define CM_GREEN 1 #define CM_BLUE 2 #define MAX_LWZ_BITS 12 #define ReadOK(file,buffer,len) (fread(buffer,len,1,file)!=0) #define EasyFail(str,status) {fprintf(stderr,str);return(status);} #define HardFail(str,status) {fprintf(stderr,str);exit (status);} #define LM_to_uint(a,b) (((b)<<8)|(a)) int ReadGIF(); int ReadColorMap(), IgnoreExtention(), GetCode(), LWZReadByte(); int ReadInterlaced(), ReadRaster(); static rle_map out_map[3*(1<<8)]; CONST_DECL char *MY_NAME = "giftorle"; FILE *outfile; struct { unsigned int Width; unsigned int Height; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned int BitPixel; unsigned int ColorResolution; unsigned int Background; } Screen; static int output_colormap = FALSE; void main(argc,argv) int argc; char **argv; { int oflag = 0, nfname = 0; char *outfname = NULL, **infname = NULL; MY_NAME = cmd_name( argv ); if ( scanargs( argc, argv, "% c%- o%-outfile.rle!s infile.gif%*s", &output_colormap, &oflag, &outfname, &nfname, &infname ) == 0 ) exit( 1 ); outfile = rle_open_f( MY_NAME, outfname, "w" ); rle_addhist( argv, (rle_hdr *)0, &rle_dflt_hdr ); /* Always read at least one (standard input). */ if ( nfname == 0 ) (void)ReadGIF( NULL ); while ( nfname-- > 0 ) (void)ReadGIF( *infname++ ); } int ReadGIF(filename) char *filename; { unsigned char buf[16]; unsigned char c; unsigned char LocalColorMap[3][MAXCOLORMAPSIZE]; FILE *fd; int use_global_colormap; int bit_pixel; int count=0; fd = rle_open_f( MY_NAME, filename, "r" ); if (! ReadOK(fd,buf,6)) EasyFail("error reading magic number\n",TRUE); if (strncmp((char *)buf,"GIF87a",6)!=0) EasyFail("bad magic number (version mismatch?)\n",TRUE); if (! ReadOK(fd,buf,7)) EasyFail("error reading screen descriptor\n",TRUE); Screen.Width = LM_to_uint(buf[0],buf[1]); Screen.Height = LM_to_uint(buf[2],buf[3]); Screen.BitPixel = 2<<(buf[4]&0x07); Screen.ColorResolution = (((buf[4]&0x70)>>3)+1); Screen.Background = buf[5]; if ((buf[4]&0x80)==0x80) { if (ReadColorMap(fd,Screen.BitPixel,Screen.ColorMap)) return (TRUE); } while (1) { if (! ReadOK(fd,&c,1)) EasyFail("No image data -- EOF\n",TRUE); if (c == ';') return FALSE; if (c == '!') { if (! ReadOK(fd,&c,1)) EasyFail("No extention function code -- EOF\n",TRUE); if (IgnoreExtention(fd)) return(TRUE); } if (c != ',') { fprintf(stderr,"Bogus character ignoring '%c'\n",c); continue; } if (count == 1) HardFail("This file contains more than one image! FAILING\n",1); count++; if (! ReadOK(fd,buf,9)) EasyFail("Couldn't read left/top/width/height\n",TRUE); if ((buf[8]&0x80)==0x80) use_global_colormap = FALSE ; else use_global_colormap = TRUE ; bit_pixel = 1<<((buf[8]&0x07)+1); if (! use_global_colormap) { if (ReadColorMap(fd,bit_pixel,LocalColorMap)) return TRUE; } if ((buf[8]&0x40)==0x40) { if (ReadInterlaced(fd,LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), use_global_colormap?Screen.ColorMap:LocalColorMap)) return TRUE; } else { if (ReadRaster(fd,LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), use_global_colormap?Screen.ColorMap:LocalColorMap)) return TRUE; } } } int ReadColorMap(fd,number,buffer) FILE *fd; int number; unsigned char buffer[3][MAXCOLORMAPSIZE]; { int i; unsigned char rgb[3]; for (i=0;i= lastbit) { if (done) { if (curbit>=lastbit) EasyFail("Ran off the end of my bits\n",-1); } buf[0] = buf[last_byte-2]; buf[1] = buf[last_byte-1]; if (! ReadOK(fd,&count,1)) { EasyFail("Error in getting buffer size\n",-1); } if (count == 0) { done = TRUE; } else if (! ReadOK(fd,&buf[2],count)) EasyFail("Error in getting buffer\n",-1); last_byte = 2 + count; curbit = (curbit - lastbit) + 16; lastbit = (2+count)*8 ; } ret = 0; for( i = curbit, j = 0; j < code_size; i++, j++ ) ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; curbit += code_size; return ret; } int LWZReadByte(fd,flag,input_code_size) FILE *fd; int flag; int input_code_size; { static int fresh=FALSE; int code,incode; static int code_size,set_code_size; static int max_code,max_code_size; static int firstcode,oldcode; static int clear_code,end_code; static int table[2][(1<< MAX_LWZ_BITS)]; static int stack[(1<<(MAX_LWZ_BITS))*2],*sp; register int i; if (flag) { set_code_size = input_code_size; code_size = set_code_size+1; clear_code = 1 << set_code_size ; end_code = clear_code + 1; max_code_size = 2*clear_code; max_code = clear_code+2; GetCode(fd,NULL,TRUE); fresh=TRUE; for (i=0;i stack) return *--sp; while ((code=GetCode(fd,code_size,FALSE))>=0) { if (code == clear_code) { for (i=0;i0 && ReadOK(fd,&junk,1)); if (count!=0) EasyFail("missing EOD in data stream (common occurance)\n",-3); return -2; } incode = code; if (code >= max_code) { *sp++ = firstcode; code = oldcode; } while (code >= clear_code) { *sp++ = table[1][code]; if (code == table[0][code]) EasyFail("Circular table entry BIG ERROR\n",-1); code = table[0][code]; } *sp++ = firstcode = table[1][code]; if ((code=max_code)<(1<= max_code_size) && (max_code_size < (1< stack) return *--sp; } return code; } int ReadInterlaced(fd,len,height,cmap) FILE *fd; int len,height; char cmap[3][MAXCOLORMAPSIZE]; { unsigned char c; int v; int xpos=0; rle_pixel **scanline[3]; rle_pixel *ptr[3] ; rle_hdr hdr; int i,j; int ypos=0,pass=0; for (j=0;j<(output_colormap?1:3);j++) { if ((scanline[j]=(rle_pixel **) malloc(height*sizeof(rle_pixel *)))==NULL) EasyFail("Unable to malloc space for pixels #1\n",1); for (i=0;i=0;j--) for (;i>=0;i--) if (scanline[j][i]!=NULL) free(scanline[i]); EasyFail("Unable to malloc space for pixels #2\n",1); } } } hdr = rle_dflt_hdr; if (output_colormap) { hdr.ncolors = 1; hdr.ncmap = 3; hdr.cmaplen = 8; hdr.cmap = out_map; for (i=0;i<(1<<8);i++) { out_map[i+(0<<8)] = cmap[CM_RED][i] << 8; out_map[i+(1<<8)] = cmap[CM_GREEN][i] << 8; out_map[i+(2<<8)] = cmap[CM_BLUE][i] << 8; } } else { RLE_SET_BIT(hdr, RLE_RED); RLE_SET_BIT(hdr, RLE_GREEN); RLE_SET_BIT(hdr, RLE_BLUE); hdr.ncolors = 3; } hdr.rle_file = outfile ; hdr.xmax = len - 1; hdr.ymax = height - 1; rle_put_setup(&hdr); if (! ReadOK(fd,&c,1)) EasyFail("Bogus image data -- EOF\n",TRUE); if (LWZReadByte(fd,TRUE,c)<0) return TRUE; while ((v=LWZReadByte(fd,FALSE,c))>=0) { if (output_colormap) { scanline[RLE_RED][ypos][xpos] = v ; } else { scanline[RLE_RED][ypos][xpos] = cmap[CM_RED][v] ; scanline[RLE_GREEN][ypos][xpos] = cmap[CM_GREEN][v] ; scanline[RLE_BLUE][ypos][xpos] = cmap[CM_BLUE][v] ; } xpos++; if (xpos==len) { xpos = 0; switch (pass) { case 0: case 1: ypos += 8; break; case 2: ypos += 4; break; case 3: ypos += 2; break; } if (ypos >= height) { pass++; switch (pass) { case 1: ypos = 4; break; case 2: ypos = 2; break; case 3: ypos = 1; break; } } } } for (i=0;i=0) { if (output_colormap) { scanline[RLE_RED][xpos] = v ; } else { scanline[RLE_RED][xpos] = cmap[CM_RED][v] ; scanline[RLE_GREEN][xpos] = cmap[CM_GREEN][v] ; scanline[RLE_BLUE][xpos] = cmap[CM_BLUE][v] ; } xpos++; if (xpos==len) { rle_putrow(scanline,len,&hdr); xpos=0; } } if (xpos!=0) rle_putrow(scanline,xpos,&hdr); rle_puteof(&hdr); free(scanline[0]); free(scanline[1]); free(scanline[2]); if (v==(-2)) return FALSE; return TRUE; }