/*----------------------------------------------------------------------------
                               pamtopnm
------------------------------------------------------------------------------
  Part of the Netpbm package.

  Convert PAM images to PBM, PGM, or PPM (i.e. PNM)

  By Bryan Henderson, San Jose CA 2000.08.05

  Contributed to the public domain by its author 2000.08.05.
-----------------------------------------------------------------------------*/

#include "pam.h"
#include "shhopt.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 *input_filespec;  /* Filespecs of input files */
    int assume;    /* -assume option */
};


static void
parse_command_line(int argc, char ** argv,
                   struct cmdline_info *cmdline_p) {
/*----------------------------------------------------------------------------
   Note that the file spec array we return is stored in the storage that
   was passed to us as the argv array.
-----------------------------------------------------------------------------*/
    optStruct *option_def = malloc(100*sizeof(optStruct));
        /* Instructions to OptParseOptions2 on how to parse our options.
         */
    optStruct2 opt;

    unsigned int option_def_index;

    option_def_index = 0;   /* incremented by OPTENTRY */
    OPTENTRY(0,   "assume",     OPT_FLAG,   &cmdline_p->assume,         0);

    /* Set the defaults */
    cmdline_p->assume = FALSE;

    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 */

    optParseOptions2(&argc, argv, opt, 0);
        /* Uses and sets argc, argv, and some of *cmdline_p and others. */

    if (argc-1 == 0) 
        cmdline_p->input_filespec = "-";
    else if (argc-1 != 1)
        pm_error("Program takes zero or one argument (filename).  You "
                 "specified %d", argc-1);
    else
        cmdline_p->input_filespec = argv[1];

}



static void
validate_tuple_type(const struct pam inpam, const int assume_tuple_type) {

    if (assume_tuple_type) {
        /* User says tuple type is appropriate regardless of tuple_type. */
        if (inpam.depth != 1 && inpam.depth != 3)
            pm_error("Input image has %d channels.  To convert to a PNM, "
                     "it must have 1 or 3.", inpam.depth);
    } else {
        if (inpam.depth == 1 && 
            strcmp(inpam.tuple_type, PAM_PBM_TUPLETYPE) == 0) {
            /* It's a PBMable image */
        } else if (inpam.depth == 1 && 
                   strcmp(inpam.tuple_type, PAM_PGM_TUPLETYPE) == 0) {
            /* It's a PGMable image */
        } else if (inpam.depth == 3 &&
                   strcmp(inpam.tuple_type, PAM_PPM_TUPLETYPE) == 0) {
            /* It's a PPMable image */
        } else 
            pm_error("PAM image does not have a depth and tuple_type "
                     "consistent with a PNM\nimage.\n"
                     "According to its "
                     "header, depth is %d and tuple_type is '%s'.\n"
                     "Use the -assume option to convert anyway.",
                     inpam.depth, inpam.tuple_type);
    }
}



int
main(int argc, char *argv[]) {

    struct cmdline_info cmdline;
    FILE* ifp;
    struct pam inpam;   /* Input PAM image */
    struct pam outpam;  /* Output PNM image */

    pnm_init(&argc, argv);

    parse_command_line(argc, argv, &cmdline);

    ifp = pm_openr(cmdline.input_filespec);

    pnm_readpaminit(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type));

    validate_tuple_type(inpam, cmdline.assume);

    outpam = inpam;
    outpam.file = stdout;
    
    if (inpam.depth == 1) {
        if (inpam.maxval == 1)
            outpam.format = PBM_FORMAT;
        else 
            outpam.format = PGM_FORMAT;
    } else
        outpam.format = PPM_FORMAT;

    pnm_writepaminit(&outpam);

    {
        tuple *tuplerow;
        
        tuplerow = pnm_allocpamrow(&inpam);      
        { 
            int row;
            
            for (row = 0; row < inpam.height; row++) {
                pnm_readpamrow(&inpam, tuplerow);
                pnm_writepamrow(&outpam, tuplerow);
            }
        }
        pnm_freepamrow(tuplerow);        
    }
    exit(0);
}

