📄 palmtopnm.c
字号:
/****************************************************************************** palmtopnm******************************************************************************* By Bryan Henderson, San Jose, California, June 2004. Inspired by and using methods from Tbmptopnm by Ian Goldberg <iang@cs.berkeley.edu>, and Bill Janssen <bill@janssen.org>. Bryan's work is contributed to the public domain by its author.******************************************************************************/#include <assert.h>#include "pnm.h"#include "shhopt.h"#include "mallocvar.h"#include "palm.h"enum palmCompressionType { COMPRESSION_NONE, COMPRESSION_RLE, COMPRESSION_SCANLINE, COMPRESSION_PACKBITS};struct palmHeader { unsigned short cols; unsigned short rows; unsigned short bytesPerRow; unsigned short flags; unsigned char pixelSize; unsigned char version; unsigned char transparentIndex; enum palmCompressionType compressionType;};struct directColorInfo { unsigned int redbits; unsigned int greenbits; unsigned int bluebits; Color_s transparentColor;};struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ const char * inputFilespec; unsigned int verbose; unsigned int rendition; unsigned int showhist; unsigned int transparent;};static voidparseCommandLine(int argc, char ** argv, struct cmdlineInfo *cmdlineP) {/*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array.-----------------------------------------------------------------------------*/ optEntry *option_def = malloc( 100*sizeof( optEntry ) ); /* Instructions to optParseOptions3 on how to parse our options. */ optStruct3 opt; unsigned int renditionSpec; unsigned int option_def_index; option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); OPTENT3(0, "showhist", OPT_FLAG, NULL, &cmdlineP->showhist, 0); OPTENT3(0, "transparent", OPT_FLAG, NULL, &cmdlineP->transparent, 0); OPTENT3(0, "rendition", OPT_UINT, &cmdlineP->rendition, &renditionSpec, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */ optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (renditionSpec) { if (cmdlineP->rendition < 1) pm_error("The -rendition value must be at least 1"); } else cmdlineP->rendition = 1; if (cmdlineP->transparent) { if (renditionSpec) pm_error("You can't specify -rendition with -transparent"); if (cmdlineP->showhist) pm_error("You can't specify -showhist with -transparent"); } if (argc-1 < 1) cmdlineP->inputFilespec = "-"; else { cmdlineP->inputFilespec = argv[1]; if (argc-1 > 1) pm_error("Too many arguments (%d). The only non-option " "argument is the file name", argc-1); }}static xelval *createGraymap(unsigned int const ncolors, unsigned int const minval, xelval const maxval) { int i; xelval *map; MALLOCARRAY_NOFAIL(map, ncolors); for (i = 0; i < ncolors; ++i) { map[i] = maxval - (i * (maxval - minval)) / (ncolors - 1); } return map;}static void skipbytes(FILE * const ifP, unsigned int const nbytes) { unsigned char buf[256]; unsigned int n; n = nbytes; /* initial value */ while (n > 0) { if (n > sizeof(buf)) { fread(buf, sizeof(buf), 1, ifP); n -= sizeof(buf); } else { fread(buf, n, 1, ifP); n = 0; } } }static voidinterpretCompression(unsigned short const flags, unsigned char const compressionValue, enum palmCompressionType * const compressionTypeP) { switch (compressionValue) { case PALM_COMPRESSION_RLE: *compressionTypeP = COMPRESSION_RLE; break; case PALM_COMPRESSION_SCANLINE: *compressionTypeP = COMPRESSION_SCANLINE; break; case PALM_COMPRESSION_PACKBITS: *compressionTypeP = COMPRESSION_PACKBITS; break; case PALM_COMPRESSION_NONE: *compressionTypeP = COMPRESSION_NONE; break; default: pm_error("The Palm image header has an unrecognized value for " "compression type: 0x%02x", (unsigned)compressionValue); }}static voidreadHeader(FILE * const ifP, unsigned int const requestedRendition, struct palmHeader * const palmHeaderP) { bool gotHeader; unsigned int currentRendition; gotHeader = FALSE; currentRendition = 1; while (!gotHeader) { short cols, rows, bytesPerRow, flags, nextDepthOffset; unsigned char pixelSize, version; pm_readbigshort(ifP, &cols); pm_readbigshort(ifP, &rows); pm_readbigshort(ifP, &bytesPerRow); pm_readbigshort(ifP, &flags); pixelSize = fgetc(ifP); version = fgetc(ifP); pm_readbigshort(ifP, &nextDepthOffset); if (currentRendition < requestedRendition) { if (nextDepthOffset == 0) pm_error("Not enough renditions in the input pixmap " "to extract the %dth", requestedRendition); /* nextDepthOffset is calculated in 4 byte words * from the beginning of this bitmap (so it equals it's size) */ skipbytes(ifP, (nextDepthOffset*4)-12); ++currentRendition; } else { short pad; unsigned char compressionType; palmHeaderP->transparentIndex = fgetc(ifP); compressionType = fgetc(ifP); pm_readbigshort(ifP, &pad); /* reserved by Palm as of 8/9/00 */ gotHeader = TRUE; palmHeaderP->cols = cols; palmHeaderP->rows = rows; palmHeaderP->bytesPerRow = bytesPerRow; palmHeaderP->flags = flags; palmHeaderP->pixelSize = pixelSize; palmHeaderP->version = version; interpretCompression(palmHeaderP->flags, compressionType, &palmHeaderP->compressionType); } }}static voidreportPalmHeader(struct palmHeader const palmHeader) { const char *ctype; switch (palmHeader.compressionType) { case COMPRESSION_RLE: ctype = "rle (Palm OS 3.5)"; break; case COMPRESSION_SCANLINE: ctype = "scanline (Palm OS 2.0)"; break; case COMPRESSION_PACKBITS: ctype = "packbits (Palm OS 4.0)"; break; case COMPRESSION_NONE: ctype = "none"; break; } pm_message("Dimensions: %hu columns x %hu rows", palmHeader.cols, palmHeader.rows); pm_message("Row layout: %hu bytes per row, %hu bits per pixel", palmHeader.bytesPerRow, palmHeader.pixelSize); pm_message("Flags: 0x%04hx", palmHeader.flags); pm_message("Version %d", palmHeader.version); pm_message("Transparent index: %d", palmHeader.transparentIndex); pm_message("Compression type: %s", ctype);}static voiddetermineOutputFormat(struct palmHeader const palmHeader, int * const formatP, xelval * const maxvalP) { if (palmHeader.flags & PALM_DIRECT_COLOR) { *formatP = PPM_TYPE; *maxvalP = 255; } else if (palmHeader.flags & PALM_HAS_COLORMAP_FLAG) { *formatP = PPM_TYPE; *maxvalP = 255; } else if (palmHeader.pixelSize == 1) { *formatP = PBM_TYPE; *maxvalP = 1; } else if (palmHeader.pixelSize >= 8) { *formatP = PPM_TYPE; *maxvalP = pm_bitstomaxval(palmHeader.pixelSize); } else { *formatP = PGM_TYPE; *maxvalP = pm_bitstomaxval(palmHeader.pixelSize); }}static voidgetColorInfo(struct palmHeader const palmHeader, FILE * const ifP, Colormap * const colormapP, unsigned int * const ncolorsP, struct directColorInfo * const directColorInfoP) { if (palmHeader.flags & PALM_DIRECT_COLOR) { *colormapP = NULL; directColorInfoP->redbits = fgetc(ifP); directColorInfoP->greenbits = fgetc(ifP); directColorInfoP->bluebits = fgetc(ifP); fgetc(ifP); /* padding */ fgetc(ifP); /* padding */ directColorInfoP->transparentColor = (fgetc(ifP) << 16) | (fgetc(ifP) << 8) | fgetc(ifP); } else if (palmHeader.flags & PALM_HAS_COLORMAP_FLAG) *colormapP = palmcolor_read_colormap (ifP); else if (palmHeader.pixelSize >= 8) { Colormap colormap; colormap = palmcolor_build_default_8bit_colormap(); qsort(colormap->color_entries, colormap->ncolors, sizeof(Color_s), palmcolor_compare_indices); *colormapP = colormap; } else *colormapP = NULL; *ncolorsP = 1 << palmHeader.pixelSize;}static voiddoTransparent(unsigned short const flags, unsigned char const transparentIndex, unsigned char const pixelSize, Colormap const colormap, struct directColorInfo const directColorInfo) { if (flags & PALM_HAS_TRANSPARENCY_FLAG) { if (colormap) { Color_s const color = transparentIndex << 24; Color const actualColor = (bsearch(&color, colormap->color_entries, colormap->ncolors, sizeof(color), palmcolor_compare_indices)); printf("#%02x%02x%02x\n", (unsigned int) ((*actualColor >> 16) & 0xFF), (unsigned int) ((*actualColor >> 8) & 0xFF), (unsigned int) ((*actualColor >> 0 )& 0xFF)); } else if (flags & PALM_DIRECT_COLOR) { Color_s const color = directColorInfo.transparentColor; printf("#%02x%02x%02x\n", (unsigned int)((color >> 16) & 0xFF), (unsigned int)((color >> 8) & 0xFF), (unsigned int)((color >> 0 )& 0xFF)); } else { unsigned int const maxval = pm_bitstomaxval(pixelSize); unsigned int const grayval = ((maxval - transparentIndex) * 256) / maxval; printf("#%02x%02x%02x\n", grayval, grayval, grayval); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -