diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/other/rletopnm.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other/rletopnm.c')
-rw-r--r-- | converter/other/rletopnm.c | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/converter/other/rletopnm.c b/converter/other/rletopnm.c new file mode 100644 index 00000000..aaa86388 --- /dev/null +++ b/converter/other/rletopnm.c @@ -0,0 +1,497 @@ +/* + * This is derived from the file of the same name dated June 5, 1995, + * copied from the Army High Performance Computing Research Center's + * media-tools.tar.gz package, received from + * http://www.arc.umn.edu/gvl-software/media-tools.tar.gz on 2000.04.13. + * + * 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. + */ +/* + * rletopnm - A conversion program to convert from Utah's "rle" image format + * to pbmplus ppm or pgm image formats. + * + * Author: Wes Barris (wes@msc.edu) + * AHPCRC + * Minnesota Supercomputer Center, Inc. + * Date: March 30, 1994 + * Copyright (c) Minnesota Supercomputer Center 1994 + * + * 2000.04.13 adapted for Netpbm by Bryan Henderson. Quieted compiler + * warnings. Added --alpha option. Accept input on stdin + * + */ + +#define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ + +/*----------------------------------------------------------------------------- + * System includes. + */ +#include <string.h> +#include <stdio.h> +#define NO_DECLARE_MALLOC +#include <rle.h> + +#include "pnm.h" +#include "shhopt.h" +#include "mallocvar.h" +#include "nstring.h" + +#define HMSG if (headerDump) pm_message +#define GRAYSCALE 001 /* 8 bits, no colormap */ +#define PSEUDOCOLOR 010 /* 8 bits, colormap */ +#define TRUECOLOR 011 /* 24 bits, colormap */ +#define DIRECTCOLOR 100 /* 24 bits, no colormap */ +#define RLE_MAXVAL 255 +/* + * Utah type declarations. + */ +rle_hdr hdr; +rle_map *colormap; + + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + char *input_filename; + unsigned int headerdump; + unsigned int verbose; + char *alpha_filename; + bool alpha_stdout; +}; + + + +/* + * Other declarations. + */ +int visual, maplen; +int width, height; + + + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that many of the strings that this function returns in the + *cmdlineP structure are actually in the supplied argv array. And + sometimes, one of these strings is actually just a suffix of an entry + in argv! +-----------------------------------------------------------------------------*/ + optEntry * option_def; /* malloc'ed */ + optStruct3 opt; + unsigned int option_def_index; + + unsigned int alphaoutSpec; + + MALLOCARRAY(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3('h', "headerdump", OPT_FLAG, + NULL, &cmdlineP->headerdump, 0); + OPTENT3('v', "verbose", OPT_FLAG, + NULL, &cmdlineP->verbose, 0); + OPTENT3(0, "alphaout", OPT_STRING, + &cmdlineP->alpha_filename, &alphaoutSpec, 0); + + opt.opt_table = option_def; + opt.short_allowed = TRUE; /* We have short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and all of *cmdlineP. */ + + if (!alphaoutSpec) + cmdlineP->alpha_filename = NULL; + + if (argc - 1 == 0) + cmdlineP->input_filename = NULL; /* he wants stdin */ + else if (argc - 1 == 1) { + if (STREQ(argv[1], "-")) + cmdlineP->input_filename = NULL; /* he wants stdin */ + else + cmdlineP->input_filename = strdup(argv[1]); + } else + pm_error("Too many arguments. The only argument accepted " + "is the input file specification"); + + if (cmdlineP->alpha_filename && + STREQ(cmdlineP->alpha_filename, "-")) + cmdlineP->alpha_stdout = TRUE; + else + cmdlineP->alpha_stdout = FALSE; +} + + + +static void +reportRleGetSetupError(int const rleGetSetupRc) { + + switch (rleGetSetupRc) { + case -1: + pm_error("According to the URT library, the input is not " + "an RLE file. rle_get_setup() failed."); + break; + case -2: + pm_error("Unable to get memory for the color map. " + "rle_get_setup() failed."); + break; + case -3: + pm_error("Input file is empty. rle_get_setup() failed."); + break; + case -4: + pm_error("End of file in the middle of where the RLE header should " + "be. rle_get_setup() failed."); + break; + default: + pm_error("rle_get_setup() failed for an unknown reason"); + } +} + + +/*----------------------------------------------------------------------------- + * Read the rle header. + */ +static void +read_rle_header(FILE * const ifp, + bool const headerDump) { + int rc; + int i; + hdr.rle_file = ifp; + rc = rle_get_setup(&hdr); + if (rc != 0) + reportRleGetSetupError(rc); + + width = hdr.xmax - hdr.xmin + 1; + height = hdr.ymax - hdr.ymin + 1; + HMSG("Image size: %dx%d", width, height); + if (hdr.ncolors == 1 && hdr.ncmap == 3) { + visual = PSEUDOCOLOR; + colormap = hdr.cmap; + maplen = (1 << hdr.cmaplen); + HMSG("Mapped color image with a map of length %d.", + maplen); + } + else if (hdr.ncolors == 3 && hdr.ncmap == 0) { + visual = DIRECTCOLOR; + HMSG("24 bit color image, no colormap."); + } + else if (hdr.ncolors == 3 && hdr.ncmap == 3) { + visual = TRUECOLOR; + colormap = hdr.cmap; + maplen = (1 << hdr.cmaplen); + HMSG( + "24 bit color image with color map of length %d" ,maplen); + } + else if (hdr.ncolors == 1 && hdr.ncmap == 0) { + visual = GRAYSCALE; + HMSG("Grayscale image."); + } + else { + fprintf(stderr, + "ncolors = %d, ncmap = %d, I don't know how to handle this!", + hdr.ncolors, hdr.ncmap); + exit(-1); + } + if (hdr.alpha == 0) { + HMSG("No alpha channel."); + } else if (hdr.alpha == 1) { + HMSG("Alpha channel exists!"); + } else { + fprintf(stderr, "alpha = %d, I don't know how to handle this!\n", + hdr.alpha); + exit(-1); + } + switch (hdr.background) { + case 0: + HMSG("Use all pixels, ignore background color."); + break; + case 1: + HMSG("Use only non-background pixels, ignore background color."); + break; + case 2: + HMSG("Use only non-background pixels, " + "clear to background color (default)."); + break; + default: + HMSG("Unknown background flag!"); + break; + } + if (hdr.background == 2) + for (i = 0; i < hdr.ncolors; i++) + HMSG(" %d", hdr.bg_color[i]); + if (hdr.ncolors == 1 && hdr.ncmap == 3) { + HMSG(" (%d %d %d)", + hdr.cmap[hdr.bg_color[0]]>>8, + hdr.cmap[hdr.bg_color[0]+256]>>8, + hdr.cmap[hdr.bg_color[0]+512]>>8); + } + else if (hdr.ncolors == 3 && hdr.ncmap == 3) { + HMSG(" (%d %d %d)", + hdr.cmap[hdr.bg_color[0]]>>8, + hdr.cmap[hdr.bg_color[1]+256]>>8, + hdr.cmap[hdr.bg_color[2]+512]>>8); + } + if (hdr.comments) + for (i = 0; hdr.comments[i] != NULL; i++) + HMSG("%s", hdr.comments[i]); +} +/*----------------------------------------------------------------------------- + * Write the ppm image data. + */ +static void +write_ppm_data(FILE * const imageout_file, + FILE * const alpha_file) { + + rle_pixel ***scanlines, **scanline; + pixval r, g, b; + pixel *pixelrow; + gray *alpharow; + + int scan, x, y; + /* + * Allocate some stuff. + */ + pixelrow = ppm_allocrow(width); + alpharow = pgm_allocrow(width); + + MALLOCARRAY(scanlines, height); + RLE_CHECK_ALLOC( hdr.cmd, scanlines, "scanline pointers" ); + + for ( scan = 0; scan < height; scan++ ) + RLE_CHECK_ALLOC( hdr.cmd, (rle_row_alloc(&hdr, &scanlines[scan]) >= 0), + "pixel memory" ); + /* + * Loop through those scan lines. + */ + for (scan = 0; scan < height; scan++) + y = rle_getrow(&hdr, scanlines[height - scan - 1]); + for (scan = 0; scan < height; scan++) { + scanline = scanlines[scan]; + switch (visual) { + case GRAYSCALE: /* 8 bits without colormap */ + for (x = 0; x < width; x++) { + r = scanline[0][x]; + g = scanline[0][x]; + b = scanline[0][x]; + PPM_ASSIGN(pixelrow[x], r, g, b); + if (hdr.alpha) + alpharow[x] = scanline[-1][x]; + else + alpharow[x] = 0; + } + break; + case TRUECOLOR: /* 24 bits with colormap */ + for (x = 0; x < width; x++) { + r = colormap[scanline[0][x]]>>8; + g = colormap[scanline[1][x]+256]>>8; + b = colormap[scanline[2][x]+512]>>8; + PPM_ASSIGN(pixelrow[x], r, g, b); + if (hdr.alpha) + alpharow[x] = colormap[scanline[-1][x]]; + else + alpharow[x] = 0; + } + break; + case DIRECTCOLOR: /* 24 bits without colormap */ + for (x = 0; x < width; x++) { + r = scanline[0][x]; + g = scanline[1][x]; + b = scanline[2][x]; + PPM_ASSIGN(pixelrow[x], r, g, b); + if (hdr.alpha) + alpharow[x] = scanline[-1][x]; + else + alpharow[x] = 0; + } + break; + case PSEUDOCOLOR: /* 8 bits with colormap */ + for (x = 0; x < width; x++) { + r = colormap[scanline[0][x]]>>8; + g = colormap[scanline[0][x]+256]>>8; + b = colormap[scanline[0][x]+512]>>8; + PPM_ASSIGN(pixelrow[x], r, g, b); + if (hdr.alpha) + alpharow[x] = colormap[scanline[-1][x]]; + else + alpharow[x] = 0; + } + break; + default: + break; + } + /* + * Write the scan line. + */ + if (imageout_file ) + ppm_writeppmrow(imageout_file, pixelrow, width, RLE_MAXVAL, 0); + if (alpha_file) + pgm_writepgmrow(alpha_file, alpharow, width, RLE_MAXVAL, 0); + + } /* end of for scan = 0 to height */ + + /* Free scanline memory. */ + for ( scan = 0; scan < height; scan++ ) + rle_row_free( &hdr, scanlines[scan] ); + free( scanlines ); + ppm_freerow(pixelrow); + pgm_freerow(alpharow); +} + + + +static void +write_pgm_data(FILE * const imageout_file, + FILE * const alpha_file) { +/*---------------------------------------------------------------------------- + Write the PGM image data +-----------------------------------------------------------------------------*/ + rle_pixel ***scanlines, **scanline; + gray * pixelrow; + gray * alpharow; + int scan; + int y; + /* + * Allocate some stuff. + */ + pixelrow = pgm_allocrow(width); + alpharow = pgm_allocrow(width); + + MALLOCARRAY(scanlines, height); + RLE_CHECK_ALLOC( hdr.cmd, scanlines, "scanline pointers" ); + + for (scan = 0; scan < height; ++scan) + RLE_CHECK_ALLOC(hdr.cmd, (rle_row_alloc(&hdr, &scanlines[scan]) >= 0), + "pixel memory" ); + /* + * Loop through those scan lines. + */ + for (scan = 0; scan < height; ++scan) + y = rle_getrow(&hdr, scanlines[height - scan - 1]); + + for (scan = 0; scan < height; ++scan) { + int x; + scanline = scanlines[scan]; + for (x = 0; x < width; ++x) { + pixelrow[x] = scanline[0][x]; + if (hdr.alpha) + alpharow[x] = scanline[1][x]; + else + alpharow[x] = 0; + } + if (imageout_file) + pgm_writepgmrow(imageout_file, pixelrow, width, RLE_MAXVAL, 0); + if (alpha_file) + pgm_writepgmrow(alpha_file, alpharow, width, RLE_MAXVAL, 0); + + } /* end of for scan = 0 to height */ + + /* Free scanline memory. */ + for (scan = 0; scan < height; ++scan) + rle_row_free(&hdr, scanlines[scan]); + free(scanlines); + pgm_freerow(pixelrow); + pgm_freerow(alpharow); +} + + + +/*----------------------------------------------------------------------------- + * Convert a Utah rle file to a pbmplus pnm file. + */ +int +main(int argc, char ** argv) { + + struct cmdlineInfo cmdline; + FILE *ifp; + FILE *imageout_file, *alpha_file; + char *fname = NULL; + + pnm_init( &argc, argv ); + + parseCommandLine(argc, argv, &cmdline); + + if ( cmdline.input_filename != NULL ) + ifp = pm_openr( cmdline.input_filename ); + else + ifp = stdin; + + if (cmdline.alpha_stdout) + alpha_file = stdout; + else if (cmdline.alpha_filename == NULL) + alpha_file = NULL; + else { + alpha_file = pm_openw(cmdline.alpha_filename); + } + + if (cmdline.alpha_stdout) + imageout_file = NULL; + else + imageout_file = stdout; + + + /* + * Open the file. + */ + /* Initialize header. */ + hdr = *rle_hdr_init( (rle_hdr *)NULL ); + rle_names( &hdr, cmd_name( argv ), fname, 0 ); + + /* + * Read the rle file header. + */ + read_rle_header(ifp, cmdline.headerdump || cmdline.verbose); + if (cmdline.headerdump) + exit(0); + + /* + * Write the alpha file header + */ + if (alpha_file) + pgm_writepgminit(alpha_file, width, height, RLE_MAXVAL, 0); + + /* + * Write the pnm file header. + */ + switch (visual) { + case GRAYSCALE: /* 8 bits without colormap -> pgm */ + if (cmdline.verbose) + pm_message("Writing pgm file."); + if (imageout_file) + pgm_writepgminit(imageout_file, width, height, RLE_MAXVAL, 0); + write_pgm_data(imageout_file, alpha_file); + break; + default: /* anything else -> ppm */ + if (cmdline.verbose) + pm_message("Writing ppm file."); + if (imageout_file) + ppm_writeppminit(imageout_file, width, height, RLE_MAXVAL, 0); + write_ppm_data(imageout_file, alpha_file); + break; + } + + pm_close(ifp); + if (imageout_file) + pm_close( imageout_file ); + if (alpha_file) + pm_close( alpha_file ); + + return 0; +} |