This is rlezoom.c in view mode; [Download] [Up]
/* * 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. */ /* * rlezoom.c - Zoom an RLE file. * * Author: Spencer W. Thomas * Computer Science Dept. * University of Utah * Date: Thu Feb 26 1987 * Copyright (c) 1987, University of Utah */ #include <stdio.h> #include <rle.h> #include <rle_raw.h> #ifdef USE_STDLIB_H #include <stdlib.h> #else #ifdef VOID_STAR extern void *malloc(), *calloc(); #else extern char *malloc(), *calloc(); #endif extern void free(); #endif /* USE_STDLIB_H */ #define ROUND(x) ((int)((x) + 0.5)) static void integer_zoom(), expand_raw(), float_zoom(), build_row(); static int advance_fp(); /***************************************************************** * TAG( main ) * * Zoom an RLE file by an integral factor. * * Usage: * rlezoom [-f] factor [y-factor] [-o outfile] [rlefile] * Inputs: * -f: If specified, output image will have same * dimensions as * fant -p 0 0 -s factor y-factor * would produce. * factor: Factor to zoom by. Must be positive. * y-factor: If provided, Y axis will be zoomed by this * factor, X axis by 'factor'. * rlefile: Input RLE file. Default is stdin. * Outputs: * Writes magnified RLE file to standard output or file specified by * the -o flag. * Assumptions: * ... * Algorithm: * Read input file in raw mode. For each line, expand it by the * X expansion factor. If the factor is > 3, convert pixel data * into runs. Write each line a number of times equal to the Y * factor. */ void main( argc, argv ) int argc; char **argv; { float xfact, yfact = 0; rle_hdr in_hdr, out_hdr; char * rlename = NULL, * out_fname = NULL; FILE *outfile = stdout; int oflag = 0, fflag = 0; int rle_cnt, rle_err; if ( scanargs( argc, argv, "% f%- o%-outfile!s factor!f y-factor%f rlefile%s", &fflag, &oflag, &out_fname, &xfact, &yfact, &rlename ) == 0 ) exit( 1 ); /* Error check */ if ( xfact <= 0 ) { fprintf( stderr, "%s: Zoom factor (%g) must be >= 0\n", cmd_name( argv ), xfact ); exit( 1 ); } if ( yfact < 0 ) { fprintf( stderr, "%s: Y zoom factor (%g) must be >= 0\n", cmd_name( argv ), yfact ); exit( 1 ); } /* If yfact is 0, it wasn't specified, set it to xfact */ if ( yfact == 0 ) yfact = xfact; /* Open input rle file and read header */ in_hdr.rle_file = rle_open_f(cmd_name( argv ), rlename, "r"); for ( rle_cnt = 0; (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS; rle_cnt++ ) { /* Figure out output file size and parameters */ out_hdr = in_hdr; if ( rle_cnt == 0 ) outfile = rle_open_f( cmd_name( argv ), out_fname, "w" ); out_hdr.rle_file = outfile; rle_addhist( argv, &in_hdr, &out_hdr ); /* more error checks */ if ( (float)(out_hdr.xmax + 1) * xfact > 32767 ) { fprintf( stderr, "%s: X zoom factor (%g) makes image too large (%g)\n", cmd_name( argv ), xfact, (float)(out_hdr.xmax + 1) * xfact ); exit( 1 ); } if ( (float)(out_hdr.ymax + 1) * yfact > 32767 ) { fprintf( stderr, "%s: Y zoom factor (%g) makes image too large (%g)\n", cmd_name( argv ), yfact, (float)(out_hdr.ymax + 1) * (float)yfact ); exit( 1 ); } if ( fflag ) { /* Use 'fant' arithmetic. */ out_hdr.xmin = ROUND( in_hdr.xmin * xfact ); out_hdr.ymin = ROUND( in_hdr.ymin * yfact ); out_hdr.xmax = ROUND( in_hdr.xmax * xfact ); out_hdr.ymax = ROUND( in_hdr.ymax * xfact ); } else { out_hdr.xmin = ROUND( xfact * in_hdr.xmin ); out_hdr.xmax = ROUND( xfact * (in_hdr.xmax - in_hdr.xmin + 1) ) + out_hdr.xmin - 1; out_hdr.ymin = ROUND( yfact * in_hdr.ymin ); out_hdr.ymax = ROUND( yfact * (in_hdr.ymax - in_hdr.ymin + 1) ) + out_hdr.ymin - 1; } rle_put_setup( &out_hdr ); if ( xfact == (float)(int)xfact && yfact == (float)(int)yfact ) integer_zoom( &in_hdr, (int)xfact, (int)yfact, &out_hdr ); else float_zoom( &in_hdr, xfact, yfact, &out_hdr ); } /* Check for an error. EOF or EMPTY is ok if at least one image * has been read. Otherwise, print an error message. */ if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) ) rle_get_error( rle_err, cmd_name( argv ), rlename ); exit( 0 ); } /***************************************************************** * TAG( integer_zoom ) * * Zoom the input image by an integer factor. * Inputs: * in_hdr: Input image header. * xfact, yfact: X and Y expansion factors. * Outputs: * out_hdr: Output image header. * Assumptions: * xfact, yfact > 0. * Algorithm: * Read input file in "raw" form, expand pixels and runs, write * output file in "raw" form. If xfact >= 4, each input pixel * expands to an output run. */ static void integer_zoom( in_hdr, xfact, yfact, out_hdr ) rle_hdr *in_hdr; int xfact; int yfact; rle_hdr *out_hdr; { int y, ynext, i; rle_op ** in_raw, ** out_raw; int * in_nraw, * out_nraw; /* Create raw arrays for input and output files */ rle_raw_alloc( in_hdr, &in_raw, &in_nraw ); rle_raw_alloc( out_hdr, &out_raw, &out_nraw ); y = in_hdr->ymin; while ( (ynext = rle_getraw( in_hdr, in_raw, in_nraw )) != 32768 ) { if ( ynext - y > 1 ) rle_skiprow( out_hdr, yfact * (ynext - y) ); expand_raw( in_hdr, in_raw, in_nraw, xfact, out_raw, out_nraw ); for ( i = 0; i < yfact; i++ ) rle_putraw( out_raw, out_nraw, out_hdr ); rle_freeraw( in_hdr, in_raw, in_nraw ); rle_freeraw( out_hdr, out_raw, out_nraw ); y = ynext; } rle_puteof( out_hdr ); rle_raw_free( in_hdr, in_raw, in_nraw ); rle_raw_free( out_hdr, out_raw, out_nraw ); } /***************************************************************** * TAG( expand_raw ) * * Zoom the input scanline by an integer factor. * Inputs: * the_hdr: Used for ncolors and alpha channel indication. * in_raw: Input raw opcodes. * in_nraw: Input raw opcode counts. * xfact: Magnification factor. * Outputs: * out_raw: Output raw opcodes. * out_nraw: Output counts. * Assumptions: * * Algorithm: * Replicate pixels by xfact. If xfact > 3, turn pixel data into * runs. */ static void expand_raw( the_hdr, in_raw, in_nraw, xfact, out_raw, out_nraw ) rle_hdr * the_hdr; rle_op **in_raw; int xfact; int *in_nraw; rle_op **out_raw; int *out_nraw; { register rle_op * inp, * outp; register rle_pixel * inc, * outc; int chan, i, j, k; for ( chan = -the_hdr->alpha; chan < the_hdr->ncolors; chan++ ) { for ( inp = in_raw[chan], outp = out_raw[chan], i = in_nraw[chan]; i > 0; i--, inp++ ) { *outp = *inp; /* copy, then modify */ outp->xloc *= xfact; if ( inp->opcode == RRunDataOp ) { /* Just change length */ outp->length *= xfact; outp++; } else /* must be byte data */ if ( xfact < 4 ) { /* Be cheap, replicate pixel data for small zooms */ outp->length *= xfact; outp->u.pixels = (rle_pixel *)malloc( outp->length * sizeof(rle_pixel)); for ( inc = inp->u.pixels, outc = outp->u.pixels, j = inp->length; j > 0; j--, inc++ ) for ( k = 0; k < xfact; k++ ) *outc++ = *inc; outp++; } else { /* * Change pixels to runs, coalesce adjacent * identical pixels */ for ( inc = inp->u.pixels, j = 0; j < inp->length; j++, inc++ ) if ( j > 0 && outp[-1].u.run_val == *inc ) outp[-1].length += xfact; else { outp->opcode = RRunDataOp; outp->xloc = (inp->xloc + j) * xfact; outp->length = xfact; outp->u.run_val = *inc; outp++; } } } /* Remember how many in this row */ out_nraw[chan] = outp - out_raw[chan]; } } /***************************************************************** * TAG( float_zoom ) * * Expand (or contract) input image by floating point amount. * Inputs: * in_hdr: Header for input image. * xfact: X scaling factor. * yfact: Y scaling factor. * Outputs: * out_hdr: Header for output image. * Assumptions: * xfact, yfact > 0. * Algorithm: * Simple sub/super-sampling based on DDA line drawing algorithm. */ static void float_zoom( in_hdr, xfact, yfact, out_hdr ) rle_hdr *in_hdr; float xfact; float yfact; rle_hdr *out_hdr; { rle_pixel **in_scan, **out_scan; rle_pixel **out_rows; int curr_row, in_row; int wid, i; rle_row_alloc( in_hdr, &in_scan ); rle_row_alloc( out_hdr, &out_scan ); /* Set up pointers for rle_putrow to use. The problem is that * rle_putrow expects pointers to the [xmin] element of each * scanline, while rle_getrow expects pointers to the [0] element * of each scanline. */ out_rows = (rle_pixel **)calloc( (out_hdr->ncolors + out_hdr->alpha), sizeof(rle_pixel *) ); for ( i = -out_hdr->alpha; i < out_hdr->ncolors; i++ ) out_rows[i] = out_hdr->xmin + out_scan[i]; wid = out_hdr->xmax - out_hdr->xmin + 1; curr_row = -1; /* Current input row (in in_scan). */ for ( i = out_hdr->ymin; i <= out_hdr->ymax; i++ ) { in_row = (int)(i / yfact); if ( curr_row < in_row ) { curr_row = advance_fp( in_hdr, in_row, in_scan ); build_row( out_hdr, xfact, in_scan, out_scan ); } rle_putrow( out_rows, wid, out_hdr ); } rle_puteof( out_hdr ); /* If any input left, skip over it. */ while (rle_getskip( in_hdr ) < 32768 ) ; rle_row_free( in_hdr, in_scan ); rle_row_free( out_hdr, out_scan ); free( out_rows ); } /***************************************************************** * TAG( advance_fp ) * * Advance the input to the specified row. * Inputs: * hdr: Input image header. * des_row: The desired row. * Outputs: * in_scan: Input scanline data array. * Returns scanline number of last row read. * Assumptions: * [None] * Algorithm: * Read scanlines until des_row is reached; return scanline * number of row last read (should = des_row). */ static int advance_fp( hdr, des_row, in_scan ) rle_hdr *hdr; int des_row; rle_pixel **in_scan; { int row; while ( (row = rle_getrow( hdr, in_scan )) < des_row ) ; return row; } /***************************************************************** * TAG( build_row ) * * Build zoomed output scanline from an input scanline. * Inputs: * hdr: Output image header. * fact: Scaling factor. * in_scan: Input scanline data. * Outputs: * out_scan: Output scanline data. * Assumptions: * Input scanline data runs from hdr->xmin/fact to hdr->xmax/fact. * Algorithm: * For each output pixel, determine the input pixel it comes from * by a trivial mapping. */ static void build_row( hdr, fact, in_scan, out_scan ) rle_hdr *hdr; float fact; rle_pixel **in_scan; rle_pixel **out_scan; { register rle_pixel *is, *os; register int i; int c; int m = hdr->xmax; for ( c = -hdr->alpha; c < hdr->ncolors; c++ ) { is = in_scan[c]; os = out_scan[c]; for ( i = hdr->xmin; i <= m; i++ ) os[i] = is[(int)(i / fact)]; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.