📄 pnmtopalm.c
字号:
if (directColor) { if (bpp == 16) { fputc(5, stdout); /* # of bits of red */ fputc(6, stdout); /* # of bits of green */ fputc(5, stdout); /* # of bits of blue */ fputc(0, stdout); /* reserved by Palm */ } else pm_error("Don't know how to create %d bit DirectColor bitmaps.", bpp); if (transparent) { fputc(0, stdout); fputc((PPM_GETR(transcolor) * 255) / maxval, stdout); fputc((PPM_GETG(transcolor) * 255) / maxval, stdout); fputc((PPM_GETB(transcolor) * 255) / maxval, stdout); } else pm_writebiglong(stdout, 0); /* no transparent color */ }}static voidwriteSize(bool const scanline_compression, bool const rle_compression) { unsigned int compressedSize = 0; /* Quick hack -- at least some readers can read these images. The full job requires knowing at this point in the processing how big the compressed image will be. */ if (scanline_compression || rle_compression) pm_writebigshort(stdout, compressedSize); }static voidcomputeRawRowDirectColor(const xel * const xelrow, unsigned int const cols, xelval const maxval, unsigned char * const rowdata) { unsigned int col; unsigned char *outptr; for (col = 0, outptr = rowdata; col < cols; ++col) { unsigned int const color = ((((PPM_GETR(xelrow[col])*31)/maxval) << 11) | (((PPM_GETG(xelrow[col])*63)/maxval) << 5) | ((PPM_GETB(xelrow[col])*31)/maxval)); *outptr++ = (color >> 8) & 0xFF; *outptr++ = color & 0xFF; }}static voidcomputeRawRowNonDirect(const xel * const xelrow, unsigned int const cols, xelval const maxval, unsigned int const bpp, Colormap const colormap, unsigned int const newMaxval, unsigned char * const rowdata) { unsigned int col; unsigned char *outptr; unsigned char outbyte; /* Accumulated bits to be output */ unsigned char outbit; /* The lowest bit number we want to access for this pixel */ outbyte = 0x00; outptr = rowdata; for (outbit = 8 - bpp, col = 0; col < cols; ++col) { unsigned int color; if (!colormap) { /* we assume grayscale, and use simple scaling */ color = (PNM_GET1(xelrow[col]) * newMaxval)/maxval; if (color > newMaxval) pm_error("oops. Bug in color re-calculation code. " "color of %u.", color); color = newMaxval - color; /* note grayscale maps are inverted */ } else { Color_s const temp_color = ((((PPM_GETR(xelrow[col])*newMaxval)/maxval)<<16) | (((PPM_GETG(xelrow[col])*newMaxval)/maxval)<<8) | (((PPM_GETB(xelrow[col])*newMaxval)/maxval))); Color const found = (bsearch (&temp_color, colormap->color_entries, colormap->ncolors, sizeof(Color_s), palmcolor_compare_colors)); if (!found) { pm_error("Color %d:%d:%d not found in colormap. " "Try using pnmquant to reduce the " "number of colors.", PPM_GETR(xelrow[col]), PPM_GETG(xelrow[col]), PPM_GETB(xelrow[col])); } color = (*found >> 24) & 0xFF; } if (color > newMaxval) pm_error("oops. Bug in color re-calculation code. " "color of %u.", color); outbyte |= (color << outbit); if (outbit == 0) { /* Bit buffer is full. Flush to to rowdata. */ *outptr++ = outbyte; outbyte = 0x00; outbit = 8 - bpp; } else outbit -= bpp; } if ((cols % (8 / bpp)) != 0) { /* Flush bits remaining in the bit buffer to rowdata */ *outptr++ = outbyte; }}static voidscanlineCompressAndWriteRow(const unsigned char * const rowdata, unsigned int const rowbytes, const unsigned char * const lastrow) { unsigned int col; for (col = 0; col < rowbytes; col += 8) { unsigned int const limit = MIN(rowbytes - col, 8); unsigned char outbit; unsigned char map; /* mask indicating which of the next 8 pixels are different from the previous row, and therefore present in the file immediately following the map byte. */ unsigned char *outptr; unsigned char differentPixels[8]; for (outbit = 0, map = 0x00, outptr = differentPixels; outbit < limit; ++outbit) { if (!lastrow || (lastrow[col + outbit] != rowdata[col + outbit])) { map |= (1 << (7 - outbit)); *outptr++ = rowdata[col + outbit]; } } putc(map, stdout); fwrite(differentPixels, (outptr - differentPixels), 1, stdout); }}static voidrleCompressAndWriteRow(const unsigned char * const rowdata, unsigned int const rowbytes) { unsigned int col; /* we output a count of the number of bytes a value is repeated, followed by that byte value */ col = 0; while (col < rowbytes) { unsigned int repeatcount; for (repeatcount = 1; repeatcount < (rowbytes - col) && repeatcount < 255; ++repeatcount) if (rowdata[col+repeatcount] != rowdata[col]) break; putc(repeatcount, stdout); putc(rowdata[col], stdout); col += repeatcount; }}static voidwriteRowFromRawRowdata(const unsigned char * const rowdata, unsigned int const rowbytes, bool const scanlineCompression, bool const rleCompression, const unsigned char * const lastrow) {/*---------------------------------------------------------------------------- Starting with a raw (uncompressed) Palm raster line, do the required compression and write the row to stdout.-----------------------------------------------------------------------------*/ if (scanlineCompression) scanlineCompressAndWriteRow(rowdata, rowbytes, lastrow); else if (rleCompression) rleCompressAndWriteRow(rowdata, rowbytes); else fwrite(rowdata, rowbytes, 1, stdout);}static voidwriteRow(const xel * const xelrow, unsigned int const cols, xelval const maxval, unsigned int const rowbytes, unsigned int const bpp, unsigned int const newMaxval, bool const scanlineCompression, bool const rleCompression, bool const directColor, Colormap const colormap, unsigned char * const rowdata, unsigned char * const lastrow) {/*---------------------------------------------------------------------------- Write one row of the raster to stdout. 'rowdata' is a work buffer 'rowbytes' in size. 'lastrow' is the contents of the row most recently written (useful in doing compression), or NULL if there is no previous row.-----------------------------------------------------------------------------*/ if (directColor) computeRawRowDirectColor(xelrow, cols, maxval, rowdata); else computeRawRowNonDirect(xelrow, cols, maxval, bpp, colormap, newMaxval, rowdata); writeRowFromRawRowdata(rowdata, rowbytes, scanlineCompression, rleCompression, lastrow);}static void writeRaster(xel ** const xels, unsigned int const cols, unsigned int const rows, xelval const maxval, unsigned int const rowbytes, unsigned int const bpp, unsigned int const newMaxval, bool const scanlineCompression, bool const rleCompression, bool const directColor, Colormap const colormap) { unsigned char * rowdata; unsigned char * lastrow; unsigned int row; MALLOCARRAY_NOFAIL(rowdata, rowbytes); MALLOCARRAY_NOFAIL(lastrow, rowbytes); /* And write out the data. */ for (row = 0; row < rows; ++row) { writeRow(xels[row], cols, maxval, rowbytes, bpp, newMaxval, scanlineCompression, rleCompression, directColor, colormap, rowdata, row > 0 ? lastrow : NULL); memcpy(lastrow, rowdata, rowbytes); } free(lastrow); free(rowdata);}int main( int argc, char **argv ) { struct cmdline_info cmdline; FILE* ifp; xel** xels; xel transcolor; unsigned int transindex; int rows, cols; unsigned int rowbytes; xelval maxval; int format; unsigned int bpp; bool directColor; unsigned int maxmaxval; unsigned int newMaxval; Colormap colormap; unsigned int nextDepthOffset; /* Offset from the beginning of the image we write to the beginning of the next one, assuming User writes another one following this one. */ unsigned int padBytesRequired; /* Number of bytes of padding we need to put after the image in order to align properly for User to add the next image to the stream. */ unsigned int i; /* Parse default params */ pnm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); ifp = pm_openr(cmdline.inputFilespec); xels = pnm_readpnm (ifp, &cols, &rows, &maxval, &format); pm_close(ifp); if (cmdline.verbose) pm_message("Input is %dx%d %s, maxval %d", cols, rows, formatName(format), maxval); determinePalmFormat(cols, rows, maxval, format, xels, cmdline.depth, cmdline.maxdepth, cmdline.colormap, cmdline.verbose, &bpp, &maxmaxval, &directColor, &colormap); newMaxval = (1 << bpp) - 1; if (cmdline.transparent) findTransparentColor(cmdline.transparent, newMaxval, directColor, maxval, colormap, &transcolor, &transindex); else transindex = 0; rowbytes = ((cols + (16 / bpp -1)) / (16 / bpp)) * 2; /* bytes per row - always a word boundary */ if (cmdline.offset) { /* Offset is measured in 4-byte words (double words in Intel/Microsoft terminology). Account for header, colormap, and raster size and round up */ unsigned int const rasterSize = rowbytes * rows; unsigned int const headerSize = 16; unsigned int const colormapSize = (directColor ? 8 : 0) + (cmdline.colormap ? (2 + colormap->ncolors * 4) : 0); nextDepthOffset = (rasterSize + headerSize + colormapSize + 3) / 4; padBytesRequired = 4 - (rasterSize + headerSize + colormapSize)%4; } else { nextDepthOffset = 0; padBytesRequired = 0; } writeHeader(cols, rows, rowbytes, bpp, !!cmdline.transparent, transindex, cmdline.rle_compression, cmdline.scanline_compression, cmdline.colormap, directColor, nextDepthOffset); writeColormap(cmdline.colormap, colormap, directColor, bpp, !!cmdline.transparent, transcolor, maxval); writeSize(cmdline.scanline_compression, cmdline.rle_compression); writeRaster(xels, cols, rows, maxval, rowbytes, bpp, newMaxval, cmdline.scanline_compression, cmdline.rle_compression, directColor, colormap); for (i = 0; i < padBytesRequired; ++i) fputc(0x00, stdout); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -