diff options
Diffstat (limited to 'converter/other/infotopam.c')
-rw-r--r-- | converter/other/infotopam.c | 633 |
1 files changed, 376 insertions, 257 deletions
diff --git a/converter/other/infotopam.c b/converter/other/infotopam.c index 3467891c..e9ce4d04 100644 --- a/converter/other/infotopam.c +++ b/converter/other/infotopam.c @@ -29,10 +29,10 @@ * * The icon data has the following format: * - * BIT-PLANE planes, each with HEIGHT rows of (WIDTH +15) / 16 * 2 bytes - * length. + * BIT-PLANE planes, each with HEIGHT rows WIDTH bits long, rounded up to + * a multiple of 2 bytes. * - * So if you have a 9x3x2 icon, the icon data will look like this: + * So if you have a 9x3x2 icon, the icon data looks like this: * * aaaa aaaa a000 0000 * aaaa aaaa a000 0000 @@ -45,9 +45,128 @@ * bit-plane, and '0' is padding. Thanks again to Ben Hutchings for his * very helpful post! * - * This program uses code from "sidplay" and an older "infotoxpm" program I - * wrote, both of which are released under GPL. + *----------------------------------------------------------------------------- + * The following specification for the DiskObject header is from + * http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node0241.html + * on 2024.03.14. * + * The DiskObject C structure is defined in the include file + * <workbench/workbench.h>. For a complete listing, see the Amiga ROM Kernel + * Reference Manual: Includes and Autodocs. The DiskObject structure contains + * the following elements: + * + * struct DiskObject { + * UWORD do_Magic; magic number at start of file + * UWORD do_Version; so we can change structure + * struct Gadget do_Gadget; a copy of in core gadget + * UBYTE do_Type; + * char *do_DefaultTool; + * char **do_ToolTypes; + * LONG do_CurrentX; + * LONG do_CurrentY; + * struct DrawerData *do_DrawerData; + * char *do_ToolWindow; applies only to tools + * LONG do_StackSize; applies only to tools + * }; + * + * do_Magic + * + * A magic number that the icon library looks for to make sure that the + * file it is reading really contains an icon. It should be the manifest + * constant WB_DISKMAGIC. PutDiskObject() will put this value in the + * structure, and GetDiskObject() will not believe that a file is really + * an icon unless this value is correct. + * + * do_Version + * + * This provides a way to enhance the .info file in an upwardly-compatible + * way. It should be WB_DISKVERSION. The icon library will set this value + * for you and will not believe weird values. + * + * do_Gadget + * + * This contains all the imagery for the icon. See the "Gadget Structure" + * section below for more details. + * + * do_Type + * + * The type of the icon; can be set to any of the following values. + * + * WBDISK The root of a disk + * WBDRAWER A directory on the disk + * WBTOOL An executable program + * WBPROJECT A data file + * WBGARBAGE The Trashcan directory + * WBKICK A Kickstart disk + * WBAPPICON Any object not directly associated with a filing system + * object, such as a print spooler (new in Release 2). + * + * do_DefaultTool + * + * Default tools are used for project and disk icons. For projects (data + * files), the default tool is the program Workbench runs when the project + * is activated. Any valid AmigaDOS path may be entered in this field + * such as "SYS:myprogram", "df0:mypaint", "myeditor" or ":work/mytool". + * + * For disk icons, the default tool is the diskcopy program + * ("SYS:System/DiskCopy") that will be used when this disk is the source + * of a copy. + * + * do_ToolTypes + * + * This is an array of free-format strings. Workbench does not enforce + * any rules on these strings, but they are useful for passing + * environment information. See the section on "The Tool Types Array" + * below for more information. + * + * do_CurrentX, do_CurrentY + * + * Drawers have a virtual coordinate system. The user can scroll around + * in this system using the scroll gadgets on the window that opens when + * the drawer is activated. Each icon in the drawer has a position in + * the coordinate system. CurrentX and CurrentY contain the icon's + * current position in the drawer. Picking a position for a newly + * created icon can be tricky. NO_ICON_POSITION is a system constant + * for do_CurrentX and do_CurrentY that instructs Workbench to pick a + * reasonable place for the icon. Workbench will place the icon in an + * unused region of the drawer. If there is no space in the drawers + * window, the icon will be placed just to the right of the visible + * region. + * + * do_DrawerData + * + * If the icon is associated with a directory (WBDISK, WBDRAWER, + * WBGARBAGE), it needs a DrawerData structure to go with it. This + * structure contains an Intuition NewWindow structure (see the + * "Intuition Windows" chapter for more information): + * + * struct DrawerData { + * struct NewWindow dd_NewWindow; structure to open window + * LONG dd_CurrentX; current x coordinate of origin + * LONG dd_CurrentY; current y coordinate of origin + * }; + * + * Workbench uses this to hold the current window position and size of + * the window so it will reopen in the same place. + * + * do_ToolWindow + * + * This field is reserved for future use. + * + * do_StackSize + * + * This is the size of the stack (in bytes) used for running the tool. + * If this is NULL, then Workbench will use a reasonable default stack + * size (currently 4K bytes). + * + * When a tool is run via the default tool mechanism (i.e., a project + * was activated, not the tool itself), Workbench uses the stack size + * specified in the project's .info file and the tool's .info file is + * ignored. + * + *------------------------------------------------------------------------- + * This program uses code from "sidplay" and an older "infotoxpm" program + * Richard Griswold wrote, both of which are offered under GPL. *------------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or @@ -65,42 +184,51 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "pm_c_util.h" -#include "pam.h" -#include "shhopt.h" -#include "mallocvar.h" - -#include <errno.h> -#include <stdio.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <stdio.h> +#include "pm_c_util.h" +#include "mallocvar.h" +#include "nstring.h" +#include "shhopt.h" +#include "pam.h" -/* Struct to hold miscellaneous icon information */ -typedef struct IconInfo_ { - const char *name; /* Icon file name */ - FILE *fp; /* Input file pointer */ - bool forceColor; /* Convert 1 bitplane icon to color icon */ - unsigned int numColors; /* Number of colors to override */ - bool selected; /* Converting selected (second) icon */ +typedef struct CmdlineInfo_ { + const char * inputFileNm; + unsigned int forcecolor; + pixel colors[4]; /* Colors to use for converted icons */ + unsigned int selected; + unsigned int verbose; +} CmdlineInfo; - bool drawerData; /* Icon has drawer data */ - unsigned int version; /* Icon version */ - unsigned int width; /* Width in pixels */ - unsigned int height; /* Height in pixels */ - unsigned int depth; /* Bits of color per pixel */ - pixel colors[4]; /* Colors to use for converted icons */ - unsigned char *icon; /* Completed icon */ +typedef struct IconInfo_ { + /* Miscellaneous icon information */ + FILE * ifP; /* Input file */ + bool hasDrawerData; /* Icon has drawer data */ + unsigned int version; /* Icon version */ + unsigned int width; /* Width in pixels */ + unsigned int height; /* Height in pixels */ + unsigned int depth; /* Bits of color per pixel */ + unsigned int bpwidth; + /* Bitplane width; Width of each row in icon, including padding */ + unsigned char * icon; /* Completed icon */ } IconInfo; -/* Header for each icon image */ typedef struct IconHeader_ { /* 20 bytes */ - unsigned char pad0[4]; /* Padding (always seems to be zero) */ + /* Text of header for one icon image */ + unsigned char type[4]; + /* Reverse engineered. This always seems to be 0x00000000 in + icon headers, but we've seen 0x00000010 in some 51-byte object + we don't understand. + */ unsigned char iconWidth[2]; /* Width (usually equal to Gadget width) */ unsigned char iconHeight[2]; - /* Height (usually equal to Gadget height -1) */ + /* Height (usually equal to Gadget height -1) */ unsigned char bpp[2]; /* Bits per pixel */ unsigned char pad1[10]; /* ??? */ } IconHeader; @@ -110,6 +238,7 @@ typedef struct IconHeader_ { /* 20 bytes */ * http://www.geocities.com/SiliconValley/Lakes/5147/sidplay/linux.html */ typedef struct DiskObject_ { /* 78 bytes (including Gadget struct) */ + /* Text of Info Disk Object header */ unsigned char magic[2]; /* Magic number at the start of the file */ unsigned char version[2]; /* Object version number */ unsigned char gadget[44]; /* Copy of in memory gadget (44 by */ @@ -127,139 +256,140 @@ typedef struct DiskObject_ { /* 78 bytes (including Gadget struct) */ static void -parseCommandLine( int argc, - char * argv[], - IconInfo * const infoP ) { - - unsigned int numColorArgs, /* Number of arguments for overriding colors */ - colorIdx, /* Color index */ - i; /* Argument index */ - const char * const colors[4] = { - /* Pixel colors based on original Amiga colors */ - "#0055AA", /* Blue 0, 85, 170 */ - "#FFFFFF", /* White 255, 255, 255 */ - "#000020", /* Black 0, 0, 32 */ - "#FF8A00" /* Orange 255, 138, 0 */ - }; - - /* Option entry variables */ - optEntry *option_def; - optStruct3 opt; - unsigned int option_def_index; - unsigned int numColorsSpec, forceColorSpec, selectedSpec; +parseCommandLine(int argc, + const char ** argv, + CmdlineInfo * const cmdlineP) { + + unsigned int argIdx; + optEntry * option_def; + optStruct3 opt; + unsigned int option_def_index; + unsigned int numcolorsSpec; + unsigned int numcolors; MALLOCARRAY_NOFAIL(option_def, 100); /* Set command line options */ option_def_index = 0; /* Incremented by OPTENT3 */ - OPTENT3(0, "forcecolor", OPT_FLAG, NULL, &forceColorSpec, 0); - OPTENT3(0, "numcolors", OPT_UINT, &infoP->numColors, &numColorsSpec, 0); - OPTENT3(0, "selected", OPT_FLAG, NULL, &selectedSpec, 0); - - /* Initialize the iconInfo struct */ - infoP->name = NULL; - infoP->fp = NULL; - infoP->drawerData = FALSE; - infoP->version = 0; - infoP->width = 0; - infoP->height = 0; - infoP->depth = 0; - infoP->icon = NULL; - for ( colorIdx = 0; colorIdx < 4; colorIdx++ ) - infoP->colors[colorIdx] = - ppm_parsecolor( (char*) colors[colorIdx], 0xFF ); - - /* Initialize option structure */ + OPTENT3(0, "forcecolor", OPT_FLAG, NULL, &cmdlineP->forcecolor, + 0); + OPTENT3(0, "numcolors", OPT_UINT, &numcolors, &numcolorsSpec, + 0); + OPTENT3(0, "selected", OPT_FLAG, NULL, &cmdlineP->selected, + 0); + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, + 0); + opt.opt_table = option_def; - opt.short_allowed = FALSE; /* No short (old-fashioned) options */ - opt.allowNegNum = FALSE; /* No negative number parameters */ - - /* Parse the command line */ - pm_optParseOptions3( &argc, argv, opt, sizeof( opt ), 0 ); - - infoP->forceColor = forceColorSpec; - infoP->selected = selectedSpec; - if (!numColorsSpec) - infoP->numColors = 0; - - /* Get colors and file name */ - numColorArgs = infoP->numColors * 2; - if ( ( argc - 1 != numColorArgs ) && ( argc - 1 != numColorArgs + 1 ) ) { - pm_error( "Wrong number of arguments for number of colors. " - "For %u colors, you need %u color arguments, " - "with possibly one more argument for the input file name.", - infoP->numColors, numColorArgs ); - } + opt.short_allowed = false; /* No short (old-fashioned) options */ + opt.allowNegNum = false; /* No negative number parameters */ + + pm_optParseOptions4(&argc, argv, opt, sizeof(opt), 0); + + { + const char * const colors[4] = { + /* Pixel colors based on original Amiga colors */ + "#0055AA", /* Blue 0, 85, 170 */ + "#FFFFFF", /* White 255, 255, 255 */ + "#000020", /* Black 0, 0, 32 */ + "#FF8A00" /* Orange 255, 138, 0 */ + }; + + unsigned int colorArgCt; + /* Number of arguments for overriding colors */ - /* Convert color arguments */ - for ( i = 1; i < numColorArgs; i += 2 ) { - char * endptr; /* End pointer for strtol() */ unsigned int colorIdx; - /* Get color index from argument */ - colorIdx = strtoul( argv[i], &endptr, 0 ); + if (numcolorsSpec) { + colorArgCt = numcolors * 2; + if (argc-1 < colorArgCt) { + pm_error("Insufficient arguments for %u color " + "specifications. Need at least %u arguments", + numcolors, colorArgCt); + } + } else + colorArgCt = 0; - if ( *endptr != '\0' ) { - pm_error( "'%s' is not a valid color index", argv[i] ); - } + /* Initialize palette to defaults */ + for (colorIdx = 0; colorIdx < 4; ++colorIdx) + cmdlineP->colors[colorIdx] = + ppm_parsecolor(colors[colorIdx], 0xFF); - /* Check color index range (current 0 to 3) */ - if ( ( colorIdx < 0 ) || ( colorIdx > 3 ) ) { - pm_error( "%u is not a valid color index (minimum 0, maximum 3)", - colorIdx ); - } + /* Convert color arguments */ + for (argIdx = 1; argIdx < colorArgCt; argIdx += 2) { + char * endptr; /* End pointer for strtol() */ + unsigned int colorIdx; + + /* Get color index from argument */ + colorIdx = strtoul(argv[argIdx], &endptr, 0); + + if (*endptr != '\0') { + pm_error("'%s' is not a valid color index", argv[argIdx]); + } + + if ((colorIdx < 0) || (colorIdx > 3)) { + pm_error( + "%u is not a valid color index (minimum 0, maximum 3)", + colorIdx); + } - /* Convert the color for this color index */ - infoP->colors[colorIdx] = ppm_parsecolor( argv[i+1], 0xFF ); + cmdlineP->colors[colorIdx] = ppm_parsecolor(argv[argIdx+1], 0xFF); + } } - /* Set file name */ - if ( i > argc-1 ) - infoP->name = "-"; /* Read from standard input */ + if (argIdx > argc-1) + cmdlineP->inputFileNm = "-"; /* Read from standard input */ else - infoP->name = argv[i]; + cmdlineP->inputFileNm = argv[argIdx]; } static void -getDiskObject( IconInfo * const infoP ) { -/*------------------------------------------------------------------------- - * Get fields from disk object portion of info file - *-------------------------------------------------------------------------*/ +readDiskObjectHeader(FILE * const ifP, + unsigned int * const versionP, + bool * const hasDrawerDataP) { +/*--------------------------------------------------------------------------- + Read disk object header from file *ifP; validate it and return its contents. +----------------------------------------------------------------------------*/ DiskObject dobj; /* Disk object structure */ - size_t bytesRead; + size_t bytesReadCt; /* Read the disk object header */ - bytesRead = fread( &dobj, 1, sizeof(dobj), infoP->fp ); - if (ferror(infoP->fp)) - pm_error("Cannot read disk object header for file '%s'. " + bytesReadCt = fread(&dobj, 1, sizeof(dobj), ifP); + if (ferror(ifP)) + pm_error("Cannot read disk object header. " "fread() errno = %d (%s)", - infoP->name, errno, strerror(errno)); - else if (bytesRead != sizeof(dobj)) - pm_error("Cannot read entire disk object header for file '%s'. " + errno, strerror(errno)); + else if (bytesReadCt != sizeof(dobj)) + pm_error("Cannot read entire disk object header. " "Only read 0x%X of 0x%X bytes", - infoP->name, (unsigned)bytesRead, (unsigned)sizeof(dobj)); + (unsigned)bytesReadCt, (unsigned)sizeof(dobj)); - /* Check magic number */ + /* Validate magic number */ if ((dobj.magic[0] != 0xE3) && (dobj.magic[1] != 0x10)) - pm_error("Wrong magic number for file '%s'. " + pm_error("Wrong magic number in icon file. " "Expected 0xE310, but got 0x%X%X", - infoP->name, dobj.magic[0], dobj.magic[1]); + dobj.magic[0], dobj.magic[1]); + + *versionP = (dobj.version[0] << 8) + (dobj.version[1]); - /* Set version info and have drawer data flag */ - infoP->version = (dobj.version[0] << 8) + - (dobj.version[1] ); - infoP->drawerData = (dobj.pDrawerData[0] << 24) + + *hasDrawerDataP = + (dobj.pDrawerData[0] << 24) + (dobj.pDrawerData[1] << 16) + (dobj.pDrawerData[2] << 8) + - (dobj.pDrawerData[3] ) ? TRUE : FALSE; + (dobj.pDrawerData[3] ) + > 0; } static void -getIconHeader(IconInfo * const infoP) { +readIconHeader(FILE * const ifP, + unsigned int * const widthP, + unsigned int * const heightP, + unsigned int * const depthP, + unsigned int * const bpwidthP) { /*------------------------------------------------------------------------- * Get fields from icon header portion of info file *-------------------------------------------------------------------------*/ @@ -267,25 +397,37 @@ getIconHeader(IconInfo * const infoP) { size_t bytesRead; /* Read icon header */ - bytesRead = fread(&ihead, 1, sizeof(ihead), infoP->fp); - if (ferror(infoP->fp)) - pm_error("Cannot read icon header for file '%s'. " - "fread() errno = %d (%s)", - infoP->name, errno, strerror(errno)); + bytesRead = fread(&ihead, 1, sizeof(ihead), ifP); + if (ferror(ifP)) + pm_error("Failed to read icon header. fread() errno = %d (%s)", + errno, strerror(errno)); else if (bytesRead != sizeof(ihead)) - pm_error("Cannot read the entire icon header for file '%s'. " - "Only read 0x%X of 0x%X bytes", - infoP->name, (unsigned)bytesRead, (unsigned)sizeof(ihead)); + pm_error("Failed to read the entire icon header. " + "Read only %u of %u bytes", + (unsigned)bytesRead, (unsigned)sizeof(ihead)); + + if (!memeq(ihead.type, "\0\0\0\0", 4)) { + pm_message("Unrecognized object where icon header expected. " + "First 4 bytes are 0x%02x%02x%02x%02x. We expect " + "0x00000000", + ihead.type[0], ihead.type[1], ihead.type[2], ihead.type[3]); + } - /* Get icon width, height, and bitplanes */ - infoP->width = (ihead.iconWidth[0] << 8) + ihead.iconWidth[1]; - infoP->height = (ihead.iconHeight[0] << 8) + ihead.iconHeight[1]; - infoP->depth = (ihead.bpp[0] << 8) + ihead.bpp[1]; + *widthP = (ihead.iconWidth[0] << 8) + ihead.iconWidth[1]; + *heightP = (ihead.iconHeight[0] << 8) + ihead.iconHeight[1]; + *depthP = (ihead.bpp[0] << 8) + ihead.bpp[1]; - /* Check number of bit planes */ - if ((infoP->depth > 2) || (infoP->depth < 1)) - pm_error("We don't know how to interpret %u bitplanes file '%s'. ", - infoP->depth, infoP->name); + if (*widthP < 1) + pm_error("Invalid width value in icon header: %u", *widthP); + + if (*heightP < 1) + pm_error("Invalid height value in icon header: %u", *heightP); + + if (*depthP > 2 || *depthP < 1) + pm_error("We don't know how to interpret file with %u bitplanes. ", + *depthP); + + *bpwidthP = ROUNDUP(*widthP, 16); } @@ -298,17 +440,16 @@ addBitplane(unsigned char * const icon, Add bitplane to existing icon image -----------------------------------------------------------------------------*/ unsigned int i; - unsigned int j; - - for (i = j = 0; i < bpsize; ++i, j += 8) { - icon[j+0] = (icon[j+0] << 1) | ((buff[i] >> 7) & 0x01); - icon[j+1] = (icon[j+1] << 1) | ((buff[i] >> 6) & 0x01); - icon[j+2] = (icon[j+2] << 1) | ((buff[i] >> 5) & 0x01); - icon[j+3] = (icon[j+3] << 1) | ((buff[i] >> 4) & 0x01); - icon[j+4] = (icon[j+4] << 1) | ((buff[i] >> 3) & 0x01); - icon[j+5] = (icon[j+5] << 1) | ((buff[i] >> 2) & 0x01); - icon[j+6] = (icon[j+6] << 1) | ((buff[i] >> 1) & 0x01); - icon[j+7] = (icon[j+7] << 1) | ((buff[i] >> 0) & 0x01); + + for (i = 0; i < bpsize; ++i) { + icon[(i*8)+0] = (icon[(i*8)+0] << 1) | ((buff[i] >> 7) & 0x01); + icon[(i*8)+1] = (icon[(i*8)+1] << 1) | ((buff[i] >> 6) & 0x01); + icon[(i*8)+2] = (icon[(i*8)+2] << 1) | ((buff[i] >> 5) & 0x01); + icon[(i*8)+3] = (icon[(i*8)+3] << 1) | ((buff[i] >> 4) & 0x01); + icon[(i*8)+4] = (icon[(i*8)+4] << 1) | ((buff[i] >> 3) & 0x01); + icon[(i*8)+5] = (icon[(i*8)+5] << 1) | ((buff[i] >> 2) & 0x01); + icon[(i*8)+6] = (icon[(i*8)+6] << 1) | ((buff[i] >> 1) & 0x01); + icon[(i*8)+7] = (icon[(i*8)+7] << 1) | ((buff[i] >> 0) & 0x01); } } @@ -392,156 +533,134 @@ readIconData(FILE * const fileP, static void -writeIconData( IconInfo * const infoP, - struct pam * const pamP ) { +writeRaster(IconInfo * const infoP, + struct pam * const pamP, + bool const wantColor, + const pixel * const colors) { /*------------------------------------------------------------------------- - * Write icon data to file - *-------------------------------------------------------------------------*/ - unsigned int const bpwidth = ( ( infoP->width + 15 ) / 16 ) * 16; - /* Bitplane width; Width of each row in icon, including padding */ + Write out raster of PAM image described by *pamP. - tuple * row; /* Output row */ + 'wantColor' means the user wants the PAM to be tuple type RGB, regardless + of the input image type. - /* Allocate row */ - row = pnm_allocpamrow( pamP ); + 'colors' is the palette. It has 4 entries, one for each of the possible + color indices in the input icon raster. +--------------------------------------------------------------------------*/ + unsigned int row; + tuple * tuplerow; /* Output row */ - /* Write icon image to output file */ - /* Put if check outside for loop to reduce number of times check is made */ - if ( infoP->depth == 1 ) { - if ( infoP->forceColor ) { - /* Convert 1 bitplane icon into color PAM */ - unsigned int i; - for ( i = 0; i < infoP->height; ++i ) { - unsigned int j; - for ( j = 0; j < infoP->width; ++j ) { + tuplerow = pnm_allocpamrow(pamP); + + for (row = 0; row < infoP->height; ++row) { + unsigned int col; + + for (col = 0; col < infoP->width; ++col) { + if (infoP->depth == 1) { + if (wantColor) { /* 1 is black and 0 is white */ unsigned int colorIdx = - infoP->icon[ i * bpwidth + j ] ? 2 : 1; - row[j][PAM_RED_PLANE] = - PPM_GETR( infoP->colors[colorIdx] ); - row[j][PAM_GRN_PLANE] = - PPM_GETG( infoP->colors[colorIdx] ); - row[j][PAM_BLU_PLANE] = - PPM_GETB( infoP->colors[colorIdx] ); - } - pnm_writepamrow( pamP, row ); - } - } else { - /* Convert 1 bitplane icon into bitmap PAM */ - unsigned int i; - for ( i = 0; i < infoP->height; ++i ) { - unsigned int j; - for ( j = 0; j < infoP->width; j++ ) { + infoP->icon[row * infoP->bpwidth + col] ? 2 : 1; + + tuplerow[col][PAM_RED_PLANE] = PPM_GETR(colors[colorIdx]); + tuplerow[col][PAM_GRN_PLANE] = PPM_GETG(colors[colorIdx]); + tuplerow[col][PAM_BLU_PLANE] = PPM_GETB(colors[colorIdx]); + } else { /* 1 is black and 0 is white */ - row[j][0] = infoP->icon[ i * bpwidth + j ] ? 0 : 1; + tuplerow[col][0] = + infoP->icon[row * infoP->bpwidth + col] ? 0 : 1; } - pnm_writepamrow( pamP, row ); + } else { + unsigned int const colorIdx = + infoP->icon[row * infoP->bpwidth + col]; + tuplerow[col][PAM_RED_PLANE] = PPM_GETR(colors[colorIdx]); + tuplerow[col][PAM_GRN_PLANE] = PPM_GETG(colors[colorIdx]); + tuplerow[col][PAM_BLU_PLANE] = PPM_GETB(colors[colorIdx]); } } - } else { - /* Convert color icon into color PAM */ - unsigned int i; - for ( i = 0; i < infoP->height; ++i ) { - unsigned int j; - for ( j = 0; j < infoP->width; ++j ) { - unsigned int const colorIdx = infoP->icon[ i * bpwidth + j ]; - row[j][PAM_RED_PLANE] = PPM_GETR( infoP->colors[colorIdx] ); - row[j][PAM_GRN_PLANE] = PPM_GETG( infoP->colors[colorIdx] ); - row[j][PAM_BLU_PLANE] = PPM_GETB( infoP->colors[colorIdx] ); - } - pnm_writepamrow( pamP, row ); - } + pnm_writepamrow(pamP, tuplerow); } - /* Clean up allocated memory */ - pnm_freepamrow( row ); + pnm_freepamrow(tuplerow); } int -main( int argc, - char *argv[] ) { +main(int argc, const char **argv) { - IconInfo info; /* Miscellaneous icon information */ - struct pam pam; /* PAM header */ - int skip; /* Bytes to skip to read next icon header */ + CmdlineInfo cmdline; + IconInfo info; /* Miscellaneous icon information */ + struct pam pam; /* PAM header */ - /* Init PNM library */ - pnm_init( &argc, argv ); + pm_proginit(&argc, argv); - /* Parse command line arguments */ - parseCommandLine( argc, argv, &info ); + parseCommandLine(argc, argv, &cmdline); - /* Open input file */ - info.fp = pm_openr( info.name ); + info.ifP = pm_openr(cmdline.inputFileNm); - /* Read disk object header */ - getDiskObject( &info ); + readDiskObjectHeader(info.ifP, &info.version, &info.hasDrawerData); /* Skip drawer data, if any */ - if ( info.drawerData ) { - skip = 56; /* Draw data size */ - if ( fseek( info.fp, skip, SEEK_CUR ) < 0 ) - pm_error( "Cannot skip header information in file '%s'. " - "fseek() errno = %d (%s)", - info.name, errno, strerror( errno ) ); - } + if (info.hasDrawerData) { + unsigned int const skipCt = 56; /* Draw data size */ - /* Get dimensions for first icon */ - getIconHeader( &info ); + int rc; - /* Skip ahead to next header if converting second icon */ - if ( info.selected ) { - skip = info.height * ( ( ( info.width + 15 ) / 16 ) * 2 ) * info.depth; + rc = fseek(info.ifP, skipCt, SEEK_CUR); + if (rc < 0) { + pm_error("Failed to skip header information in input file. " + "fseek() errno = %d (%s)", + errno, strerror(errno)); + } + } - if ( fseek( info.fp, skip, SEEK_CUR ) < 0 ) - pm_error( "Cannot skip to next icon in file '%s'. " - "fseek() errno = %d (%s)", - info.name, errno, strerror( errno ) ); + /* Read header of first icon */ + readIconHeader(info.ifP, &info.width, &info.height, &info.depth, + &info.bpwidth); - /* Get dimensions for second icon */ - getIconHeader( &info ); - } + readIconData(info.ifP, info.width, info.height, info.depth, &info.icon); - /* Read icon data */ - readIconData( info.fp, info.width, info.height, info.depth, &info.icon ); + if (cmdline.selected) { + /* He wants the second icon, so update info.width, etc. to be for the + second icon. + */ + readIconHeader(info.ifP, &info.width, &info.height, &info.depth, + &info.bpwidth); - /* Print icon info */ - pm_message( "converting %s, version %d, %s icon: %d X %d X %d", - info.name, info.version, info.selected ? "second" : "first", - info.width, info.height, info.depth ); + readIconData(info.ifP, info.width, info.height, info.depth, + &info.icon); + } - /* Write PAM header */ - pam.size = sizeof( pam ); - pam.len = PAM_STRUCT_SIZE( tuple_type ); + if (cmdline.verbose) { + pm_message("Version %u .info file, %s icon: %uW x %uH x %u deep", + info.version, cmdline.selected ? "second" : "first", + info.width, info.height, info.depth); + } + pam.size = sizeof(pam); + pam.len = PAM_STRUCT_SIZE(tuple_type); pam.file = stdout; pam.height = info.height; pam.width = info.width; pam.format = PAM_FORMAT; - if ( ( info.depth == 1 ) && ( info.forceColor == FALSE ) ) { + if ((info.depth == 1) && !cmdline.forcecolor) { pam.depth = 1; pam.maxval = 1; - strcpy( pam.tuple_type, "BLACKANDWHITE" ); + strcpy(pam.tuple_type, "BLACKANDWHITE"); } else { pam.depth = 3; pam.maxval = 0xFF; - strcpy( pam.tuple_type, "RGB" ); + strcpy(pam.tuple_type, "RGB"); } - pnm_writepaminit( &pam ); + pnm_writepaminit(&pam); - /* Write icon data */ - writeIconData( &info, &pam ); + writeRaster(&info, &pam, cmdline.forcecolor, cmdline.colors); - free( info.icon ); - - /* Close input file and return */ - pm_close( pam.file ); - pm_close( info.fp ); + free(info.icon); + pm_close(pam.file); + pm_close(info.ifP); return 0; } - |