diff options
Diffstat (limited to 'converter/other/pamtopdbimg.c')
-rw-r--r-- | converter/other/pamtopdbimg.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/converter/other/pamtopdbimg.c b/converter/other/pamtopdbimg.c new file mode 100644 index 00000000..58869d56 --- /dev/null +++ b/converter/other/pamtopdbimg.c @@ -0,0 +1,269 @@ +/*============================================================================= + pamtopdbimg +=============================================================================== + + Convert Netpbm image to Palm Pilot PDB Image format (for viewing by + Pilot Image Viewer). + + Bryan Henderson derived this from Eric Howe's programs named + 'pgmtoimgv' and 'pbmtoimgv'. +=============================================================================*/ +/* + * Copyright (C) 1997 Eric A. Howe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Authors: Eric A. Howe (mu@trends.net) + * Bryan Henderson, September 2010. + */ + +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include "pm_c_util.h" +#include "mallocvar.h" +#include "nstring.h" +#include "shhopt.h" +#include "pam.h" + +#include "ipdb.h" + +enum CompMode {COMPRESSED, MAYBE, UNCOMPRESSED}; + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; /* '-' if stdin */ + const char * title; + const char * notefile; /* NULL if not specified */ + enum CompMode compMode; + unsigned int depth4; +}; + + + +static void +parseCommandLine(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + parse program command line described in Unix standard form by argc + and argv. Return the information in the options as *cmdlineP. + + If command line is internally inconsistent (invalid options, etc.), + issue error message to stderr and abort program. + + Note that the strings we return are stored in the storage that + was passed to us as the argv array. We also trash *argv. +-----------------------------------------------------------------------------*/ + optEntry *option_def; + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + + unsigned int titleSpec, notefileSpec; + unsigned int compressed, maybeCompressed, uncompressed; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "title", OPT_STRING, &cmdlineP->title, + &titleSpec, 0); + OPTENT3(0, "notefile", OPT_STRING, &cmdlineP->notefile, + ¬efileSpec, 0); + OPTENT3(0, "compressed", OPT_FLAG, NULL, + &compressed, 0); + OPTENT3(0, "maybecompressed", OPT_FLAG, NULL, + &maybeCompressed, 0); + OPTENT3(0, "uncompressed", OPT_FLAG, NULL, + &uncompressed, 0); + OPTENT3(0, "4depth", OPT_FLAG, NULL, + &cmdlineP->depth4, 0); + + opt.opt_table = option_def; + opt.short_allowed = false; /* We have no short (old-fashioned) options */ + opt.allowNegNum = false; /* We have no parms that are negative numbers */ + + optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + + if (!titleSpec) + cmdlineP->title = "unnamed"; + + if (!notefileSpec) + cmdlineP->notefile = NULL; + + if (compressed + uncompressed + maybeCompressed > 1) + pm_error("You may specify only one of -compressed, -uncompressed, " + "-maybecompressed"); + if (compressed) + cmdlineP->compMode = COMPRESSED; + else if (uncompressed) + cmdlineP->compMode = UNCOMPRESSED; + else if (maybeCompressed) + cmdlineP->compMode = MAYBE; + else + cmdlineP->compMode = MAYBE; + + if (argc-1 < 1) + cmdlineP->inputFileName = "-"; + else if (argc-1 == 1) + cmdlineP->inputFileName = argv[1]; + else + pm_error("Program takes at most one argument: input file name"); +} + + + +static void +readimg(IPDB * const pdbP, + FILE * const ifP, + bool const depth4) { + + struct pam inpam; + tuple * tuplerow; + int status; + uint8_t * imgRaster; + unsigned int row; + + pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); + + if (strneq(inpam.tuple_type, "RGB", 3)) + pm_error("Input image is color. Cannot make a Palm color image."); + + MALLOCARRAY(imgRaster, inpam.width * inpam.height); + + tuplerow = pnm_allocpamrow(&inpam); + + for (row = 0; row < inpam.height; ++row) { + unsigned int col; + + pnm_readpamrow(&inpam, tuplerow); + + for (col = 0; col < inpam.width; ++col) + imgRaster[row * inpam.height + col] = tuplerow[col][0]; + } + + if (inpam.maxval == 1) + status = ipdb_insert_mimage(pdbP, inpam.width, inpam.height, + imgRaster); + else if (depth4) + status = ipdb_insert_g16image(pdbP, inpam.width, inpam.height, + imgRaster); + else + status = ipdb_insert_gimage(pdbP, inpam.width, inpam.height, + imgRaster); + + if (status != 0) + pm_error("ipdb_insert failed. Error %d (%s)", + status, ipdb_err(status)); + + pnm_freepamrow(tuplerow); + free(imgRaster); +} + + + +static void +readtxt(IPDB * const pdbP, + const char * const noteFileName) { + + struct stat st; + char * fileContent; + FILE * fP; + int n; + int rc; + size_t bytesRead; + + rc = stat(noteFileName, &st); + + if (rc != 0) + pm_error("stat of '%s' failed, errno = %d (%s)", + noteFileName, errno, strerror(errno)); + + fP = pm_openr(noteFileName); + + MALLOCARRAY(fileContent, st.st_size + 1); + + if (fileContent == NULL) + pm_error("Couldn't get %lu bytes of storage to read in note file", + (unsigned long) st.st_size); + + bytesRead = fread(fileContent, 1, st.st_size, fP); + + if (bytesRead != st.st_size) + pm_error("Failed to read note file '%s'. Errno = %d (%s)", + noteFileName, errno, strerror(errno)); + + pm_close(fP); + + /* Chop of trailing newlines */ + for (n = strlen(fileContent) - 1; n >= 0 && fileContent[n] == '\n'; --n) + fileContent[n] = '\0'; + + ipdb_insert_text(pdbP, fileContent); +} + + + +int +main(int argc, const char **argv) { + + struct cmdlineInfo cmdline; + IPDB * pdbP; + FILE * ifP; + int comp; + int status; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + + switch (cmdline.compMode) { + case COMPRESSED: comp = IPDB_COMPRESS; break; + case UNCOMPRESSED: comp = IPDB_NOCOMPRESS; break; + case MAYBE: comp = IPDB_COMPMAYBE; break; + } + + pdbP = ipdb_alloc(cmdline.title); + + if (pdbP == NULL) + pm_error("Failed to allocate IPDB structure"); + + readimg(pdbP, ifP, cmdline.depth4); + + if (cmdline.notefile) + readtxt(pdbP, cmdline.notefile); + + status = ipdb_write(pdbP, comp, stdout); + + if (status != 0) + pm_error("Failed to write PDB. %s.", ipdb_err(status)); + + if (comp == IPDB_COMPMAYBE && !ipdb_compressed(pdbP)) + pm_message("Image too complex to be compressed."); + + ipdb_free(pdbP); + + pm_close(ifP); + + return EXIT_SUCCESS; +} |