This is XtndRunget.c in view mode; [Download] [Up]
/* * XtndRunget.c - Extended Run Length Encoded retrieval. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Tue Aug 10 1982 * Copyright (c) 1982 Spencer W. Thomas * $Id: XtndRunget.c,v 3.0.1.1 90/11/19 16:45:12 spencer Exp $ * $Log: XtndRunget.c,v $ * Revision 3.0.1.1 90/11/19 16:45:12 spencer * patch2: Add rle_config.h. * * Revision 3.0 90/08/03 15:26:10 spencer * Establish version 3.0 base. * * Revision 1.3 90/07/13 15:21:42 spencer * Add void*malloc(). Cast malloc calls. * * Revision 1.2 90/06/18 23:53:24 spencer * Get rid of sv_ names. * * Revision 1.1 90/06/18 23:50:31 spencer * Initial revision * * Revision 2.10 86/10/08 13:10:55 thomas * typo fix. * * Revision 2.9 86/10/08 13:01:57 thomas * Add ability to read (and print) picture comments. * Recognize EOF opcode. * * Revision 2.8 86/03/10 15:45:29 thomas * Fix up getchan/putchan. * * Revision 2.7 86/02/27 10:03:39 thomas * fprintf on stderr, not on a string. * * Revision 2.6 86/02/25 17:31:13 thomas * Add channel munging (get single channel capability). * * Revision 2.5 85/04/26 15:04:46 thomas * Lint fixes. * New flags and variable length background color. * * Revision 2.4 85/04/06 01:21:42 thomas * Was only right justifying first channel of color map. * * Revision 2.3 85/04/02 00:41:26 thomas * Move "comment" code in Byte and Run code. * * Revision 2.2 85/03/05 21:17:28 thomas * Make sure to not put more than 510 bytes in a byte unpacker operation. * * Revision 2.1 85/03/05 15:59:17 thomas * *** empty log message *** * * Revision 1.3 84/03/12 21:29:15 thomas * Add "bread" routine, reduce output buffer size. * */ #include "rle_config.h" #include "stdio.h" #include "getfb.h" #include "rle_code.h" #include <fb.h> #ifndef VOID_STAR extern char * malloc(); #else extern void *malloc(); #endif #define BREAD(type, var, len)\ if ( fd->_cnt < len )\ bread( (char *)&var, len, fd );\ else\ {\ var = *(type *)fd->_ptr;\ fd->_ptr += len;\ fd->_cnt -= len;\ } #define OPCODE(inst) (inst.opcode & ~LONG) #define LONGP(inst) (inst.opcode & LONG) #define DATUM(inst) (0x00ff & inst.datum) #ifdef BIGENDIAN #define SWAB(shrt) (shrt = ((shrt >> 8) & 0xff) | ((shrt << 8) & 0xff00)) #else #define SWAB(shrt) #endif extern int cflag, getchan, putchan; /* to load single channel */ /* ARGSUSED */ XtndRunGet(magic) short magic; { struct XtndRsetup setup; unsigned char * bg_color; register short * fbptr; register struct fd_file * fbbuf = (struct fd_file *) ((char *) buffer + 1024); register int fbx, fby, n; int i, j, len; int fbbufsize = (sizeof buffer - 1024) / sizeof(short); short word, long_data; long maplen; struct inst { short opcode:8, datum:8; } inst; char * comment_buf, ** comments; if ( fbbufsize > 2048 ) fbbufsize = 2048; /* make it look faster */ if (bread ((char *)&setup, SETUPSIZE, fd) < 1) { fprintf (stderr, "getgmr: Couldn't read setup information\n"); exit (1); } /* * Machines with big-endian byte order need to swap some bytes on * input. */ SWAB( setup.h_xpos ); SWAB( setup.h_ypos ); SWAB( setup.h_xlen ); SWAB( setup.h_ylen ); /* * Get background colors if present. */ if ( !(setup.h_flags & H_NO_BACKGROUND) ) { bg_color = (unsigned char *)malloc( 1 + (setup.h_ncolors/2) * 2 ); bread( (char *)bg_color, 1 + (setup.h_ncolors/2) * 2, fd ); } else bread( (char *)&word, 1, fd ); /* skip filler byte */ /* * Read color map if present */ if (setup.h_ncmap) { maplen = 1 << setup.h_cmaplen; if ( maplen * setup.h_ncmap > (sizeof buffer) ) { fprintf( stderr, "Color map too big (%d entries total), giving up\n", maplen * setup.h_ncmap ); } for ( i = 0; i < setup.h_ncmap; i++ ) { bread((char *)&buffer[maplen*i], sizeof(short) * maplen, fd); for ( j = 0; j < 256; j++ ) if ( j >= maplen ) buffer[j + 256*i] = 0; /* fill in short map */ else buffer[j + 256*i] = ( buffer[j + 256*i] >> 8 ) & 0xff; } /* * If < 3 channels in color map, copy from the first into the * missing ones. */ for ( ; i < 3; i++ ) for ( j = 0; j < 255; j++ ) buffer[j + 256 * i] = buffer[j]; } /* * Read comments if present */ if ( setup.h_flags & H_COMMENT ) { short comlen, evenlen; register char * cp; /* get comment length */ BREAD( short, comlen, sizeof comlen ); /* get comment length */ SWAB( comlen ); evenlen = (comlen + 1) & ~1; /* make it even */ comment_buf = (char *)malloc( (unsigned) evenlen ); if ( comment_buf == NULL ) { fprintf( stderr, "getgmr: Malloc failed for comment buffer of size %d\n", comlen ); return -2; } fread( comment_buf, 1, evenlen, fd ); /* Count the comments */ for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ ) if ( *cp == 0 ) i++; i++; /* extra for NULL pointer at end */ /* Get space to put pointers to comments */ comments = (char **)malloc( (unsigned)(i * sizeof(char *)) ); if ( comments == NULL ) { fprintf( stderr, "getgmr: Malloc failed for %d comment pointers\n", i ); return -2; } /* Get pointers to the comments */ *comments = comment_buf; for ( i = 1, cp = comment_buf + 1; cp < comment_buf + comlen; cp++ ) if ( *(cp - 1) == 0 ) comments[i++] = cp; } if (query) { if ( setup.h_ncolors != 3 ) fprintf( stderr, "%d color channels were saved.\n", setup.h_ncolors); if ( setup.h_flags & H_ALPHA ) fprintf( stderr, "Alpha channel was saved.\n" ); fprintf (stderr, "Originally positioned at (%d, %d), size (%d %d)\n", setup.h_xpos, setup.h_ypos, setup.h_xlen, setup.h_ylen); if ( setup.h_flags & H_CLEARFIRST ) fprintf( stderr, "Screen will be cleared to " ); else if ( !(setup.h_flags & H_NO_BACKGROUND) ) fprintf( stderr, "Saved in overlay mode with original " ); if ( setup.h_flags & H_NO_BACKGROUND ) fprintf( stderr, "No background color was saved.\n" ); else { fprintf (stderr, "background color" ); for ( i = 0; i < setup.h_ncolors; i++ ) fprintf( stderr, " %d", bg_color[i] ); fprintf( stderr, "\n" ); } if (setup.h_ncmap) { fprintf (stderr, "%d channels of color map %d entries long were saved.\n", setup.h_ncmap, 1 << setup.h_cmaplen ); } if ( setup.h_flags & H_COMMENT ) { fprintf( stderr, "Comments:\n" ); for ( i = 0; comments[i] != NULL; i++ ) fprintf( stderr, "%s\n", comments[i] ); } exit (0); } Fbinit(); /* * Handle -c getchan [putchan] option. * * If both getchan & putchan are specified, take the input data in * the channel (getchan) and place it on the fb in the channel * (putchan). If only getchan is specified, put the data from the * input channel into the same color channel in the fb. * * As a special case, -c getchan acts as -c 0 getchan for a B&W * image (this accounts for much of the extra complexity of the * following block). */ if ( cflag ) { if ( getchan > setup.h_ncolors && setup.h_ncolors > 1 ) { fprintf( stderr, "Requested channel (%d) not in input file (%d channels)\n", getchan, setup.h_ncolors ); exit( 1 ); } if ( getchan < 0 && (setup.h_flags & H_ALPHA) == 0 ) { fprintf( stderr, "getgmr: No alpha channel in input file\n" ); exit( 1 ); } if ( putchan == -1 ) putchan = getchan; if ( putchan < 0 || putchan > 2 ) { fprintf( stderr, "getgmr: Requested output channel (%d) doesn't exist.\n", putchan ); exit( 1 ); } if ( setup.h_ncolors == 1 && getchan > 0 ) getchan = 0; } if (posflag) { fprintf (stderr, "Originally positioned at (%d, %d)\n", setup.h_xpos, setup.h_ypos); if (posflag == 1) /* incremental positioning */ { setup.h_xpos = (x + setup.h_xpos) & 0777; setup.h_ypos = (y + setup.h_ypos) & 0777; } else { setup.h_xpos = x & 0777; setup.h_ypos = y & 0777; } } if (background == 0) { if (setup.h_flags & H_CLEARFIRST) background = 2; else background = 1; } if ( setup.h_ncmap ) Fmbput(0, buffer); /* write color map */ Fdstart(fbbuf, fbbufsize, 0); /* do some output buffering */ if (background == 2) { if ( cflag ) { Fchn( 1 << putchan ); Frvput( 0, 511, 0, 511, bg_color[getchan] ); } else if ( setup.h_ncolors >= 3 ) Fr3put(0, 511, 0, 511, bg_color[0], bg_color[1], bg_color[2]); else Fr3put(0, 511, 0, 511, bg_color[0], bg_color[0], bg_color[0]); } fbx = setup.h_xpos; fby = setup.h_ypos; /* This is a middle exit loop */ for (;;) { BREAD(struct inst, inst, 2 ); if ( feof(fd) ) break; switch( OPCODE(inst) ) { case RSkipLinesOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); fby += long_data; if (debug) fprintf(stderr, "Skip Lines %d\n", long_data); } else { fby += DATUM(inst); if (debug) fprintf(stderr, "Skip Lines %d\n", inst.datum); } break; case RSetColorOp: if ( cflag ) { if ( (getchan&0xff) == DATUM(inst) ) Fchn( 1 << putchan ); else Fchn( 0 ); } else { if (setup.h_ncolors == 1) Fchn(7); else Fchn(1<<DATUM(inst)); /* select color channel */ } fbx = setup.h_xpos; if (debug) fprintf(stderr, "Set Color %d\n", inst.datum); break; case RSkipPixelsOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); fbx += long_data; if (debug) fprintf(stderr, "Skip Pixels %d\n", long_data); } else { fbx += DATUM(inst); if (debug) fprintf(stderr, "Skip Pixels %d\n", DATUM(inst)); } break; case RByteDataOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); n = (int)long_data; } else { n = DATUM(inst); } /* Fbvput( fbx, fbx+n, fby, fby, buffer ); */ n++; if (debug) fprintf(stderr, "Byte Data, length %d\n", n); do { len = n <= 510 ? n : 510; /* blasted byteunpacker */ _Fdreserve( (len+1)/2 + 7 ); fbptr = &fbbuf->fd_list[fbbuf->fd_len]; *fbptr++ = SelectPeripheralDevice | ByteUnpacker; *fbptr++ = LoadEA | (fbx & 0777); *fbptr++ = LoadEB | 1; *fbptr++ = LoadLA | (fby & 0777); *fbptr++ = LoadUpdateMode | A_AB; *fbptr++ = LoadPRegister | (1<<9) | ((len & 1) << 8) | ((len + 1) >> 1); bread((char *)fbptr, (len+1) & ~1, fd); /* Round up to multiple of 2 */ fbptr += (len+1)/2; fbx += len; fbbuf->fd_len = fbptr - fbbuf->fd_list; n -= len; } while ( n > 0 ); break; case RRunDataOp: if ( LONGP(inst) ) { BREAD( short, long_data, sizeof long_data ); SWAB( long_data ); n = long_data; } else { n = DATUM(inst); } BREAD( short, word, sizeof(short) ); /* Frvput(fbx, fbx+n, fby, fby, word);*/ _Fdreserve( 5 ); fbptr = &fbbuf->fd_list[fbbuf->fd_len]; *fbptr++ = LoadEA | (fbx & 0777); *fbptr++ = LoadEB | n; *fbptr++ = LoadLA | (fby & 0777); *fbptr++ = LoadSubchannelMask | (word & 07777); *fbptr++ = LoadLB | GoWrite; fbbuf->fd_len = fbptr - fbbuf->fd_list; fbx += n+1; if (debug) fprintf(stderr, "Run, length %d, color %d\n", n+1, word); break; case REOFOp: break; default: fprintf(stderr, "getgmr: Unrecognized opcode: %d\n", OPCODE(inst)); Fdstop(); Fddraw(fbbuf); /* flush the buffer */ exit(1); } if ( OPCODE( inst ) == REOFOp ) break; /* end of input here */ } Fdstop(); Fddraw(fbbuf); /* flush the buffer */ }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.