📄 pnmtopalm.c
字号:
/* pnmtopalm.c - read a portable pixmap and write a Palm Tbmp file * * Program originally ppmtoTbmp.c by Ian Goldberg <iang@cs.berkeley.edu> * * Mods for multiple bits per pixel by George Caswell * <tetsujin@sourceforge.net> * and Bill Janssen <bill@janssen.org> * * See LICENSE file for licensing information. * * Based on ppmtopuzz.c by Jef Poskanzer, from the netpbm-1mar1994 package. */#include <stdio.h>#include <assert.h>#include <limits.h>#include "pnm.h"#include "palm.h"#include "shhopt.h"#include "mallocvar.h"struct cmdline_info { /* All the information the user supplied in the command line, in a form easy for the program to use. */ const char *inputFilespec; /* Filespecs of input files */ char *transparent; /* -transparent value. Null if unspec */ unsigned int depth; /* -depth value. 0 if unspec */ unsigned int maxdepth; /* -maxdepth value. 0 if unspec */ unsigned int rle_compression; unsigned int scanline_compression; unsigned int verbose; unsigned int colormap; unsigned int offset;};static voidparseCommandLine(int argc, char ** argv, struct cmdline_info *cmdlineP) {/*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array.-----------------------------------------------------------------------------*/ optStruct3 opt; /* set by OPTENT3 */ optEntry *option_def; unsigned int option_def_index; unsigned int transSpec, depthSpec, maxdepthSpec; MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "transparent", OPT_STRING, &cmdlineP->transparent, &transSpec, 0); OPTENT3(0, "depth", OPT_UINT, &cmdlineP->depth, &depthSpec, 0); OPTENT3(0, "maxdepth", OPT_UINT, &cmdlineP->maxdepth, &maxdepthSpec, 0); OPTENT3(0, "rle_compression", OPT_FLAG, NULL, &cmdlineP->rle_compression, 0); OPTENT3(0, "scanline_compression", OPT_FLAG, NULL, &cmdlineP->scanline_compression, 0); OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); OPTENT3(0, "colormap", OPT_FLAG, NULL, &cmdlineP->colormap, 0); OPTENT3(0, "offset", OPT_FLAG, NULL, &cmdlineP->offset, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have some 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 some of *cmdline_p and others. */ if (depthSpec) { if (cmdlineP->depth != 1 && cmdlineP->depth != 2 && cmdlineP->depth != 4 && cmdlineP->depth != 8 && cmdlineP->depth != 16) pm_error("invalid value for -depth: %u. Valid values are " "1, 2, 4, 8, and 16", cmdlineP->depth); } else cmdlineP->depth = 0; if (maxdepthSpec) { if (cmdlineP->maxdepth != 1 && cmdlineP->maxdepth != 2 && cmdlineP->maxdepth != 4 && cmdlineP->maxdepth != 8 && cmdlineP->maxdepth != 16) pm_error("invalid value for -maxdepth: %u. Valid values are " "1, 2, 4, 8, and 16", cmdlineP->maxdepth); } else cmdlineP->maxdepth = 0; if (depthSpec && maxdepthSpec && cmdlineP->depth > cmdlineP->maxdepth) pm_error("-depth value (%u) is greater than -maxdepth (%u) value.", cmdlineP->depth, cmdlineP->maxdepth); if (!transSpec) cmdlineP->transparent = NULL; if (cmdlineP->offset && (cmdlineP->rle_compression || cmdlineP->scanline_compression)) pm_error("You can't specify -offset with -rle_compression or " "-scanline_compression."); if (argc-1 > 1) pm_error("This program takes at most 1 argument: the file name. " "You specified %d", argc-1); else if (argc-1 > 0) cmdlineP->inputFilespec = argv[1]; else cmdlineP->inputFilespec = "-";}static voiddeterminePalmFormat(unsigned int const cols, unsigned int const rows, xelval const maxval, int const format, xel ** const xels, unsigned int const specified_bpp, unsigned int const max_bpp, bool const custom_colormap, bool const verbose, unsigned int * const bppP, unsigned int * const maxmaxvalP, bool * const directColorP, Colormap * const colormapP) { if (PNM_FORMAT_TYPE(format) == PBM_TYPE) { if (custom_colormap) pm_error("You specified -colormap with a black and white input " "image. -colormap is valid only with color."); if (specified_bpp) *bppP = specified_bpp; else *bppP = 1; /* no point in wasting bits */ *maxmaxvalP = 1; *directColorP = FALSE; *colormapP = NULL; if (verbose) pm_message("output is black and white"); } else if (PNM_FORMAT_TYPE(format) == PGM_TYPE) { /* we can usually handle this one, but may not have enough pixels. So check... */ if (custom_colormap) pm_error("You specified -colormap with a black and white input" "image. -colormap is valid only with color."); if (specified_bpp) *bppP = specified_bpp; else if (max_bpp && (maxval >= (1 << max_bpp))) *bppP = max_bpp; else if (maxval > 16) *bppP = 4; else { /* scale to minimum number of bpp needed */ for (*bppP = 1; (1 << *bppP) < maxval; *bppP *= 2) ; } if (*bppP > 4) *bppP = 4; if (verbose) pm_message("output is grayscale %d bits-per-pixel", *bppP); *maxmaxvalP = PGM_OVERALLMAXVAL; *directColorP = FALSE; *colormapP = NULL; } else if (PNM_FORMAT_TYPE(format) == PPM_TYPE) { /* We assume that we only get a PPM if the image cannot be represented as PBM or PGM. There are two options here: either 8-bit with a colormap, either the standard one or a custom one, or 16-bit direct color. In the 8-bit case, if "custom_colormap" is specified (not recommended by Palm) we will put in our own colormap; otherwise we will assume that the colors have been mapped to the default Palm colormap by appropriate use of pnmquant. We try for 8-bit color first, since it works on more PalmOS devices. */ if ((specified_bpp == 16) || (specified_bpp == 0 && max_bpp == 16)) { /* we do the 16-bit direct color */ *directColorP = TRUE; *colormapP = NULL; *bppP = 16; } else if (!custom_colormap) { /* standard indexed 8-bit color */ *colormapP = palmcolor_build_default_8bit_colormap(); *bppP = 8; if (((specified_bpp != 0) && (specified_bpp != 8)) || ((max_bpp != 0) && (max_bpp < 8))) pm_error("Must use depth of 8 for color pixmap without " "custom color table."); *directColorP = FALSE; if (verbose) pm_message("Output is color with default colormap at 8 bpp"); } else { /* indexed 8-bit color with a custom colormap */ *colormapP = palmcolor_build_custom_8bit_colormap(rows, cols, xels); for (*bppP = 1; (1 << *bppP) < (*colormapP)->ncolors; *bppP *= 2); if (specified_bpp != 0) { if (specified_bpp >= *bppP) *bppP = specified_bpp; else pm_error("Too many colors for specified depth. " "Use pnmquant to reduce."); } else if ((max_bpp != 0) && (max_bpp < *bppP)) { pm_error("Too many colors for specified max depth. " "Use pnmquant to reduce."); } *directColorP = FALSE; if (verbose) pm_message("Output is color with custom colormap " "with %d colors at %d bpp", (*colormapP)->ncolors, *bppP); } *maxmaxvalP = PPM_OVERALLMAXVAL; } else { pm_error("unknown format 0x%x on input file\n", (unsigned) format); }}static const char * formatName(int const format) { const char * retval; switch(PNM_FORMAT_TYPE(format)) { case PBM_TYPE: retval = "black and white"; break; case PGM_TYPE: retval = "grayscale"; break; case PPM_TYPE: retval = "color"; break; default: retval = "???"; break; } return retval;} static voidfindTransparentColor(char * const colorSpec, pixval const newMaxval, bool const directColor, pixval const maxval, Colormap const colormap, xel * const transcolorP, unsigned int * const transindexP) { *transcolorP = ppm_parsecolor(colorSpec, maxval); if (!directColor) { Color_s const temp_color = ((((PPM_GETR(*transcolorP)*newMaxval) / maxval) << 16) | (((PPM_GETG(*transcolorP)*newMaxval) / maxval) << 8) | ((PPM_GETB(*transcolorP)*newMaxval) / maxval)); Color const found = (bsearch(&temp_color, colormap->color_entries, colormap->ncolors, sizeof(Color_s), palmcolor_compare_colors)); if (!found) { pm_error("Specified transparent color %s not found " "in colormap.", colorSpec); } else *transindexP = (*found >> 24) & 0xFF; }}static voidwriteHeader(unsigned int const cols, unsigned int const rows, unsigned int const rowbytes, unsigned int const bpp, bool const transparent, unsigned int const transindex, bool const rleCompression, bool const scanlineCompression, bool const colormap, bool const directColor, unsigned int const nextDepthOffset) {/*---------------------------------------------------------------------------- Write the Tbmp header. This is 16 bytes; it does not include colormap.-----------------------------------------------------------------------------*/ unsigned short flags; int version; flags = 0; /* initial value */ if (transparent) flags |= PALM_HAS_TRANSPARENCY_FLAG; if (colormap) flags |= PALM_HAS_COLORMAP_FLAG; if (rleCompression || scanlineCompression) flags |= PALM_IS_COMPRESSED_FLAG; if (directColor) flags |= PALM_DIRECT_COLOR; if (cols > USHRT_MAX) pm_error("Too many columns for Palm pixmap: %u", cols); pm_writebigshort(stdout, cols); /* width */ if (rows > USHRT_MAX) pm_error("Too many columns for Palm pixmap: %u", rows); pm_writebigshort(stdout, rows); /* height */ if (rows > USHRT_MAX) pm_error("Too many bytes per row for Palm pixmap: %u", rowbytes); pm_writebigshort(stdout, rowbytes); pm_writebigshort(stdout, flags); assert(bpp <= UCHAR_MAX); fputc(bpp, stdout); /* we need to mark this as version 1 if we use more than 1 bpp, version 2 if we use compression or transparency */ version = (transparent || rleCompression || scanlineCompression) ? 2 : (((bpp > 1) || colormap) ? 1 : 0); fputc(version, stdout); if (nextDepthOffset > USHRT_MAX) pm_error("Image too large for Palm pixmap"); pm_writebigshort(stdout, nextDepthOffset); assert(transindex <= UCHAR_MAX); fputc(transindex, stdout); /* transparent index */ if (rleCompression) fputc(PALM_COMPRESSION_RLE, stdout); else if (scanlineCompression) fputc(PALM_COMPRESSION_SCANLINE, stdout); else fputc(PALM_COMPRESSION_NONE, stdout); pm_writebigshort(stdout, 0); /* reserved by Palm */}static voidwriteColormap(bool const explicitColormap, Colormap const colormap, bool const directColor, unsigned int const bpp, bool const transparent, xel const transcolor, xelval const maxval) { /* if there's a colormap, write it out */ if (explicitColormap) { unsigned int row; if (!colormap) pm_error("Internal error: user specified -colormap, but we did " "not generate a colormap."); qsort (colormap->color_entries, colormap->ncolors, sizeof(Color_s), palmcolor_compare_indices); pm_writebigshort( stdout, colormap->ncolors ); for (row = 0; row < colormap->ncolors; ++row) pm_writebiglong (stdout, colormap->color_entries[row]); qsort (colormap->color_entries, colormap->ncolors, sizeof(Color_s), palmcolor_compare_colors); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -