|
Packit |
78deda |
/* ppmtowinicon.c - read portable pixmap file(s) and write a MS Windows .ico
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Copyright (C) 2000 by Lee Benfield - lee@benf.org
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
78deda |
** documentation for any purpose and without fee is hereby granted, provided
|
|
Packit |
78deda |
** that the above copyright notice appear in all copies and that both that
|
|
Packit |
78deda |
** copyright notice and this permission notice appear in supporting
|
|
Packit |
78deda |
** documentation. This software is provided "as is" without express or
|
|
Packit |
78deda |
** implied warranty.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <math.h>
|
|
Packit |
78deda |
#include <string.h>
|
|
Packit |
38c941 |
#include <stdlib.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "winico.h"
|
|
Packit |
78deda |
#include "ppm.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
#include "shhopt.h"
|
|
Packit |
78deda |
#include "nstring.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define MAJVERSION 0
|
|
Packit |
78deda |
#define MINVERSION 3
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define MAXCOLORS 256
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct cmdlineInfo {
|
|
Packit |
78deda |
/* All the information the user supplied in the command line,
|
|
Packit |
78deda |
in a form easy for the program to use.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
unsigned int iconCount;
|
|
Packit |
78deda |
const char **inputFilespec; /* '-' if stdin; malloc'ed array */
|
|
Packit |
78deda |
const char **andpgmFilespec; /* NULL if unspecified; malloc'ed array */
|
|
Packit |
78deda |
const char *output; /* '-' if unspecified */
|
|
Packit |
78deda |
unsigned int truetransparent;
|
|
Packit |
78deda |
unsigned int verbose;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static bool verbose;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static int file_offset = 0; /* not actually used, but useful for debug. */
|
|
Packit |
78deda |
static FILE * ofp;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
parseCommandLine(int argc,
|
|
Packit |
78deda |
char ** argv,
|
|
Packit |
78deda |
struct cmdlineInfo *cmdlineP ) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Parse program command line described in Unix standard form by argc
|
|
Packit |
78deda |
and argv. Return the information in the options as *cmdlineP.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If command line is internally inconsistent (invalid options, etc.),
|
|
Packit |
78deda |
issue error message to stderr and abort program.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Note that the strings we return are stored in the storage that
|
|
Packit |
78deda |
was passed to us as the argv array. We also trash *argv.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
optEntry *option_def;
|
|
Packit |
78deda |
/* Instructions to pm_optParseOptions3 on how to parse our options.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
optStruct3 opt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int option_def_index;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int outputSpec, andpgms;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(option_def, 100);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
option_def_index = 0; /* incremented by OPTENT3 */
|
|
Packit |
78deda |
OPTENT3(0, "output", OPT_STRING, &cmdlineP->output,
|
|
Packit |
78deda |
&outputSpec, 0);
|
|
Packit |
78deda |
OPTENT3(0, "andpgms", OPT_FLAG, NULL,
|
|
Packit |
78deda |
&andpgms, 0);
|
|
Packit |
78deda |
OPTENT3(0, "truetransparent", OPT_FLAG, NULL,
|
|
Packit |
78deda |
&cmdlineP->truetransparent, 0);
|
|
Packit |
78deda |
OPTENT3(0, "verbose", OPT_STRING, NULL,
|
|
Packit |
78deda |
&cmdlineP->verbose, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
opt.opt_table = option_def;
|
|
Packit |
78deda |
opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
|
|
Packit |
78deda |
opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
|
|
Packit |
78deda |
/* Uses and sets argc, argv, and some of *cmdlineP and others. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!outputSpec)
|
|
Packit |
78deda |
cmdlineP->output = "-";
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!andpgms) {
|
|
Packit |
78deda |
if (argc-1 == 0) {
|
|
Packit |
78deda |
cmdlineP->iconCount = 1;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, cmdlineP->iconCount);
|
|
Packit |
78deda |
cmdlineP->inputFilespec[0] = "-";
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned int iconIndex;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cmdlineP->iconCount = argc-1;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, cmdlineP->iconCount);
|
|
Packit |
78deda |
for (iconIndex = 0; iconIndex < cmdlineP->iconCount; ++iconIndex)
|
|
Packit |
78deda |
cmdlineP->inputFilespec[iconIndex] = argv[iconIndex+1];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
unsigned int iconIndex;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmdlineP->andpgmFilespec, cmdlineP->iconCount);
|
|
Packit |
78deda |
for (iconIndex = 0; iconIndex < cmdlineP->iconCount; ++iconIndex)
|
|
Packit |
78deda |
cmdlineP->andpgmFilespec[iconIndex] = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
if (argc-1 < 2)
|
|
Packit |
78deda |
pm_error("with -andpgms, you must specify at least two "
|
|
Packit |
78deda |
"arguments: image file name and and mask file name. "
|
|
Packit |
78deda |
"You specified %d", argc-1);
|
|
Packit |
78deda |
else if ((argc-1)/2*2 != (argc-1))
|
|
Packit |
78deda |
pm_error("with -andpgms, you must specify an even number of "
|
|
Packit |
78deda |
"arguments. You specified %d", argc-1);
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
unsigned int iconIndex;
|
|
Packit |
78deda |
cmdlineP->iconCount = (argc-1)/2;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, cmdlineP->iconCount);
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmdlineP->andpgmFilespec, cmdlineP->iconCount);
|
|
Packit |
78deda |
for (iconIndex = 0; iconIndex < cmdlineP->iconCount; ++iconIndex) {
|
|
Packit |
78deda |
cmdlineP->inputFilespec[iconIndex] = argv[1 + iconIndex*2];
|
|
Packit |
78deda |
cmdlineP->andpgmFilespec[iconIndex] = argv[2 + iconIndex*2];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PutByte(int const v) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (putc(v, ofp) == EOF)
|
|
Packit |
78deda |
pm_error("Unable to write byte to output file.");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PutShort(short const v) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (pm_writelittleshort(ofp, v) == -1)
|
|
Packit |
78deda |
pm_error("Unable to write short integer to output file");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PutLong(long const v) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (pm_writelittlelong(ofp, v) == -1)
|
|
Packit |
78deda |
pm_error("Unable to write long integer to output file");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* These have no purpose but to wrapper the Byte, Short & Long
|
|
Packit |
78deda |
* functions.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeU1 (u1 const v) {
|
|
Packit |
78deda |
file_offset++;
|
|
Packit |
78deda |
PutByte(v);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeU2 (u2 const v) {
|
|
Packit |
78deda |
file_offset +=2;
|
|
Packit |
78deda |
PutShort(v);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeU4 (u4 const v) {
|
|
Packit |
78deda |
file_offset += 4;
|
|
Packit |
78deda |
PutLong(v);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static MS_Ico
|
|
Packit |
78deda |
createIconFile (void) {
|
|
Packit |
78deda |
MS_Ico MSIconData;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(MSIconData);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MSIconData->reserved = 0;
|
|
Packit |
78deda |
MSIconData->type = 1;
|
|
Packit |
78deda |
MSIconData->count = 0;
|
|
Packit |
78deda |
MSIconData->entries = NULL;
|
|
Packit |
78deda |
return MSIconData;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* create andBitmap from pgm */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static ICON_bmp
|
|
Packit |
78deda |
createAndBitmap (gray ** const ba, int const cols, int const rows,
|
|
Packit |
78deda |
gray const maxval) {
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* How wide should the u1 string for each row be?
|
|
Packit |
78deda |
* each byte is 8 pixels, but must be a multiple of 4 bytes.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
unsigned int const xBytes = ROUNDUP(cols, 32)/8;
|
|
Packit |
78deda |
ICON_bmp icBitmap;
|
|
Packit |
78deda |
int y,x;
|
|
Packit |
78deda |
u1 ** rowData;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(icBitmap);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(rowData, rows);
|
|
Packit |
78deda |
icBitmap->xBytes = xBytes;
|
|
Packit |
78deda |
icBitmap->data = rowData;
|
|
Packit |
38c941 |
overflow2(xBytes, rows);
|
|
Packit |
78deda |
icBitmap->size = xBytes * rows;
|
|
Packit |
78deda |
for (y=0;y
|
|
Packit |
78deda |
u1 * row;
|
|
Packit |
78deda |
int byteOn = 0;
|
|
Packit |
78deda |
int bitOn = 128;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(row, xBytes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
memset (row, 0, xBytes);
|
|
Packit |
78deda |
rowData[rows-y-1] = row;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Check there's a bit array, otherwise we're just faking this...
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (ba) {
|
|
Packit |
78deda |
for (x=0;x
|
|
Packit |
78deda |
/* Black (bit clear) is transparent in PGM alpha maps,
|
|
Packit |
78deda |
* in ICO bit *set* is transparent.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (ba[y][x] <= maxval/2) row[byteOn] |= bitOn;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bitOn == 1) {
|
|
Packit |
78deda |
byteOn++;
|
|
Packit |
78deda |
bitOn = 128;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
bitOn >>= 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return icBitmap;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the
|
|
Packit |
78deda |
* encoding mechanism is different.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* I didn't re-use the code from ppmtobmp since I need to keep the
|
|
Packit |
78deda |
* bitmaps in memory till I've loaded all ppms.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* 8bpp => 1 byte/palette index.
|
|
Packit |
78deda |
* 4bpp => High Nibble, Low Nibble
|
|
Packit |
78deda |
* 1bpp => 1 palette value per bit, high bit 1st.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
static ICON_bmp
|
|
Packit |
78deda |
create1Bitmap (pixel ** const pa, int const cols, int const rows,
|
|
Packit |
78deda |
colorhash_table const cht) {
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* How wide should the u1 string for each row be?
|
|
Packit |
78deda |
* each byte is 8 pixels, but must be a multiple of 4 bytes.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
ICON_bmp icBitmap;
|
|
Packit |
78deda |
int xBytes,y,x;
|
|
Packit |
78deda |
int wt = cols;
|
|
Packit |
78deda |
u1 ** rowData;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(icBitmap);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
wt >>= 3;
|
|
Packit |
78deda |
if (wt & 3) {
|
|
Packit |
78deda |
wt = (wt & ~3) + 4;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
xBytes = wt;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(rowData, rows);
|
|
Packit |
78deda |
icBitmap->xBytes = xBytes;
|
|
Packit |
78deda |
icBitmap->data = rowData;
|
|
Packit |
78deda |
icBitmap->size = xBytes * rows;
|
|
Packit |
78deda |
for (y=0;y
|
|
Packit |
78deda |
u1 * row;
|
|
Packit |
78deda |
int byteOn = 0;
|
|
Packit |
78deda |
int bitOn = 128;
|
|
Packit |
78deda |
int value;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(row, xBytes);
|
|
Packit |
78deda |
memset (row, 0, xBytes);
|
|
Packit |
78deda |
rowData[rows-y-1] = row;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Check there's a pixel array, otherwise we're just faking this...
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (pa) {
|
|
Packit |
78deda |
for (x=0;x
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* So we've got a colorhash_table with two colors in it.
|
|
Packit |
78deda |
* Which is black?!
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Unless the hashing function changes, 0's black.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
value = ppm_lookupcolor(cht, &pa[y][x]);
|
|
Packit |
78deda |
if (!value) {
|
|
Packit |
78deda |
/* leave black. */
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
row[byteOn] |= bitOn;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (bitOn == 1) {
|
|
Packit |
78deda |
byteOn++;
|
|
Packit |
78deda |
bitOn = 128;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
bitOn >>= 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return icBitmap;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static ICON_bmp
|
|
Packit |
78deda |
create4Bitmap (pixel ** const pa, int const cols, int const rows,
|
|
Packit |
78deda |
colorhash_table const cht) {
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* How wide should the u1 string for each row be?
|
|
Packit |
78deda |
* each byte is 8 pixels, but must be a multiple of 4 bytes.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
ICON_bmp icBitmap;
|
|
Packit |
78deda |
int xBytes,y,x;
|
|
Packit |
78deda |
int wt = cols;
|
|
Packit |
78deda |
u1 ** rowData;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(icBitmap);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
wt >>= 1;
|
|
Packit |
78deda |
if (wt & 3) {
|
|
Packit |
78deda |
wt = (wt & ~3) + 4;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
xBytes = wt;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(rowData, rows);
|
|
Packit |
78deda |
icBitmap->xBytes = xBytes;
|
|
Packit |
78deda |
icBitmap->data = rowData;
|
|
Packit |
38c941 |
overflow2(xBytes, rows);
|
|
Packit |
78deda |
icBitmap->size = xBytes * rows;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (y=0;y
|
|
Packit |
78deda |
u1 * row;
|
|
Packit |
78deda |
int byteOn = 0;
|
|
Packit |
78deda |
int nibble = 1; /* high nibble = 1, low nibble = 0; */
|
|
Packit |
78deda |
int value;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(row, xBytes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
memset (row, 0, xBytes);
|
|
Packit |
78deda |
rowData[rows-y-1] = row;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Check there's a pixel array, otherwise we're just faking this...
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (pa) {
|
|
Packit |
78deda |
for (x=0;x
|
|
Packit |
78deda |
value = ppm_lookupcolor(cht, &pa[y][x]);
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Shift it, if we're putting it in the high nibble.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (nibble) {
|
|
Packit |
78deda |
value <<= 4;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
row[byteOn] |= value;
|
|
Packit |
78deda |
if (nibble) {
|
|
Packit |
78deda |
nibble = 0;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
nibble = 1;
|
|
Packit |
78deda |
byteOn++;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return icBitmap;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static ICON_bmp
|
|
Packit |
78deda |
create8Bitmap (pixel ** const pa, int const cols, int const rows,
|
|
Packit |
78deda |
colorhash_table const cht) {
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* How wide should the u1 string for each row be?
|
|
Packit |
78deda |
* each byte is 8 pixels, but must be a multiple of 4 bytes.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
ICON_bmp icBitmap;
|
|
Packit |
78deda |
int xBytes,y,x;
|
|
Packit |
78deda |
int wt = cols;
|
|
Packit |
78deda |
u1 ** rowData;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(icBitmap);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (wt & 3) {
|
|
Packit |
78deda |
wt = (wt & ~3) + 4;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
xBytes = wt;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(rowData, rows);
|
|
Packit |
78deda |
icBitmap->xBytes = xBytes;
|
|
Packit |
78deda |
icBitmap->data = rowData;
|
|
Packit |
38c941 |
overflow2(xBytes, rows);
|
|
Packit |
78deda |
icBitmap->size = xBytes * rows;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (y=0;y
|
|
Packit |
78deda |
u1 * row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(row, xBytes);
|
|
Packit |
78deda |
memset (row, 0, xBytes);
|
|
Packit |
78deda |
rowData[rows-y-1] = row;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Check there's a pixel array, otherwise we're just faking this...
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (pa) {
|
|
Packit |
78deda |
for (x=0;x
|
|
Packit |
78deda |
row[x] = ppm_lookupcolor(cht, &pa[y][x]);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return icBitmap;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static IC_InfoHeader
|
|
Packit |
78deda |
createInfoHeader(IC_Entry const entry, ICON_bmp const xbmp,
|
|
Packit |
78deda |
ICON_bmp const abmp) {
|
|
Packit |
78deda |
IC_InfoHeader ih;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(ih);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ih->size = 40;
|
|
Packit |
78deda |
ih->width = entry->width;
|
|
Packit |
78deda |
ih->height = entry->height * 2;
|
|
Packit |
78deda |
ih->planes = 1;
|
|
Packit |
78deda |
ih->bitcount = entry->bitcount;
|
|
Packit |
78deda |
ih->compression = 0;
|
|
Packit |
78deda |
ih->imagesize = entry->width * entry->height * 8 / entry->bitcount;
|
|
Packit |
78deda |
ih->x_pixels_per_m= 0;
|
|
Packit |
78deda |
ih->y_pixels_per_m= 0;
|
|
Packit |
78deda |
ih->colors_used = 1 << entry->bitcount;
|
|
Packit |
78deda |
ih->colors_important = 0;
|
|
Packit |
78deda |
return ih;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static IC_Palette
|
|
Packit |
78deda |
createCleanPalette(void) {
|
|
Packit |
78deda |
IC_Palette palette;
|
|
Packit |
78deda |
int x;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(palette);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(palette->colors, MAXCOLORS);
|
|
Packit |
78deda |
for (x=0;x
|
|
Packit |
78deda |
palette->colors[x] = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return palette;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
addColorToPalette(IC_Palette const palette, int const i,
|
|
Packit |
78deda |
int const r, int const g, int const b) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(palette->colors[i]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
palette->colors[i]->red = r;
|
|
Packit |
78deda |
palette->colors[i]->green = g;
|
|
Packit |
78deda |
palette->colors[i]->blue = b;
|
|
Packit |
78deda |
palette->colors[i]->reserved = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static ICON_bmp
|
|
Packit |
78deda |
createBitmap (int const bpp, pixel ** const pa,
|
|
Packit |
78deda |
int const cols, int const rows,
|
|
Packit |
78deda |
colorhash_table const cht) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ICON_bmp retval;
|
|
Packit |
78deda |
const int assumed_bpp = (pa == NULL) ? 1 : bpp;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (assumed_bpp) {
|
|
Packit |
78deda |
case 1:
|
|
Packit |
78deda |
retval = create1Bitmap (pa,cols,rows,cht);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case 4:
|
|
Packit |
78deda |
retval = create4Bitmap (pa,cols,rows,cht);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case 8:
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
retval = create8Bitmap (pa,cols,rows,cht);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return retval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
makePalette(pixel ** const xorPPMarray,
|
|
Packit |
78deda |
int const xorCols,
|
|
Packit |
78deda |
int const xorRows,
|
|
Packit |
78deda |
pixval const xorMaxval,
|
|
Packit |
78deda |
IC_Palette * const paletteP,
|
|
Packit |
78deda |
colorhash_table * const xorChtP,
|
|
Packit |
78deda |
int * const colorsP,
|
|
Packit |
78deda |
const char ** const errorP) {
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Figure out the colormap and turn it into the appropriate GIF
|
|
Packit |
78deda |
* colormap - this code's pretty much straight from ppmtobpm
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
colorhist_vector xorChv;
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
int colors;
|
|
Packit |
78deda |
IC_Palette palette = createCleanPalette();
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (verbose) pm_message("computing colormap...");
|
|
Packit |
78deda |
xorChv = ppm_computecolorhist(xorPPMarray, xorCols, xorRows, MAXCOLORS,
|
|
Packit |
78deda |
&colors);
|
|
Packit |
78deda |
if (xorChv == NULL)
|
|
Packit |
78deda |
pm_asprintf(errorP,
|
|
Packit |
78deda |
"image has too many colors - try doing a 'pnmquant %d'",
|
|
Packit |
78deda |
MAXCOLORS);
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
*errorP = NULL;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (verbose) pm_message("%d colors found", colors);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (verbose && (xorMaxval > 255))
|
|
Packit |
78deda |
pm_message("maxval is not 255 - automatically rescaling colors");
|
|
Packit |
78deda |
for (i = 0; i < colors; ++i) {
|
|
Packit |
78deda |
if (xorMaxval == 255) {
|
|
Packit |
78deda |
addColorToPalette(palette,i,
|
|
Packit |
78deda |
PPM_GETR(xorChv[i].color),
|
|
Packit |
78deda |
PPM_GETG(xorChv[i].color),
|
|
Packit |
78deda |
PPM_GETB(xorChv[i].color));
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
addColorToPalette(palette,i,
|
|
Packit |
78deda |
PPM_GETR(xorChv[i].color) * 255 / xorMaxval,
|
|
Packit |
78deda |
PPM_GETG(xorChv[i].color) * 255 / xorMaxval,
|
|
Packit |
78deda |
PPM_GETB(xorChv[i].color) * 255 / xorMaxval);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* And make a hash table for fast lookup. */
|
|
Packit |
78deda |
*xorChtP = ppm_colorhisttocolorhash(xorChv, colors);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_freecolorhist(xorChv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*paletteP = palette;
|
|
Packit |
78deda |
*colorsP = colors;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
getOrFakeAndMap(const char * const andPgmFname,
|
|
Packit |
78deda |
int const xorCols,
|
|
Packit |
78deda |
int const xorRows,
|
|
Packit |
78deda |
gray *** const andPGMarrayP,
|
|
Packit |
78deda |
pixval * const andMaxvalP,
|
|
Packit |
78deda |
colorhash_table * const andChtP,
|
|
Packit |
78deda |
const char ** const errorP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int andRows, andCols;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!andPgmFname) {
|
|
Packit |
78deda |
/* He's not supplying a bitmap for 'and'. Fake the bitmap. */
|
|
Packit |
78deda |
*andPGMarrayP = NULL;
|
|
Packit |
78deda |
*andMaxvalP = 1;
|
|
Packit |
78deda |
*andChtP = NULL;
|
|
Packit |
78deda |
*errorP = NULL;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
FILE * andfile;
|
|
Packit |
78deda |
andfile = pm_openr(andPgmFname);
|
|
Packit |
78deda |
*andPGMarrayP = pgm_readpgm(andfile, &andCols, &andRows, andMaxvalP);
|
|
Packit |
78deda |
pm_close(andfile);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if ((andCols != xorCols) || (andRows != xorRows)) {
|
|
Packit |
78deda |
pm_asprintf(errorP,
|
|
Packit |
78deda |
"And mask and image have different dimensions "
|
|
Packit |
78deda |
"(%d x %d vs %d x %d). Aborting.",
|
|
Packit |
78deda |
andCols, xorCols, andRows, xorRows);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
*errorP = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
blackenTransparentAreas(pixel ** const xorPPMarray,
|
|
Packit |
78deda |
int const cols,
|
|
Packit |
78deda |
int const rows,
|
|
Packit |
78deda |
gray ** const andPGMarray,
|
|
Packit |
78deda |
pixval const andMaxval) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (verbose) pm_message("Setting transparent pixels to black");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row) {
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col) {
|
|
Packit |
78deda |
if (andPGMarray[row][col] < andMaxval)
|
|
Packit |
78deda |
/* It's not opaque here; make it black */
|
|
Packit |
78deda |
PPM_ASSIGN(xorPPMarray[row][col], 0, 0, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
addEntryToIcon(MS_Ico const MSIconData,
|
|
Packit |
78deda |
const char * const xorPpmFname,
|
|
Packit |
78deda |
const char * const andPgmFname,
|
|
Packit |
78deda |
bool const trueTransparent) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
IC_Entry entry;
|
|
Packit |
78deda |
FILE * xorfile;
|
|
Packit |
78deda |
pixel ** xorPPMarray;
|
|
Packit |
78deda |
gray ** andPGMarray;
|
|
Packit |
78deda |
ICON_bmp xorBitmap;
|
|
Packit |
78deda |
ICON_bmp andBitmap;
|
|
Packit |
78deda |
int rows, cols;
|
|
Packit |
78deda |
int bpp, colors;
|
|
Packit |
78deda |
int entry_cols;
|
|
Packit |
78deda |
IC_Palette palette;
|
|
Packit |
78deda |
colorhash_table xorCht;
|
|
Packit |
78deda |
colorhash_table andCht;
|
|
Packit |
78deda |
const char * error;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pixval xorMaxval;
|
|
Packit |
78deda |
gray andMaxval;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(entry);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Read the xor PPM.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
xorfile = pm_openr(xorPpmFname);
|
|
Packit |
78deda |
xorPPMarray = ppm_readppm(xorfile, &cols, &rows, &xorMaxval);
|
|
Packit |
78deda |
pm_close(xorfile);
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Since the entry uses 1 byte to hold the width and height of the icon, the
|
|
Packit |
78deda |
* image can't be more than 256 x 256.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (rows > 255 || cols > 255) {
|
|
Packit |
78deda |
pm_error("Max size for a icon is 255 x 255 (1 byte fields). "
|
|
Packit |
78deda |
"%s is %d x %d", xorPpmFname, cols, rows);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (verbose) pm_message("read PPM: %dw x %dh, maxval = %d",
|
|
Packit |
78deda |
cols, rows, xorMaxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
makePalette(xorPPMarray, cols, rows, xorMaxval,
|
|
Packit |
78deda |
&palette, &xorCht, &colors, &error);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (error)
|
|
Packit |
78deda |
pm_error("Unable to make palette for '%s'. %s", xorPpmFname, error);
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* All the icons I found seemed to pad the palette to the max entries
|
|
Packit |
78deda |
* for that bitdepth.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* The spec indicates this isn't necessary, but I'll follow this behaviour
|
|
Packit |
78deda |
* just in case.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (colors < 3) {
|
|
Packit |
78deda |
bpp = 1;
|
|
Packit |
78deda |
entry_cols = 2;
|
|
Packit |
78deda |
} else if (colors < 17) {
|
|
Packit |
78deda |
bpp = 4;
|
|
Packit |
78deda |
entry_cols = 16;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
bpp = 8;
|
|
Packit |
78deda |
entry_cols = 256;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
getOrFakeAndMap(andPgmFname, cols, rows,
|
|
Packit |
78deda |
&andPGMarray, &andMaxval, &andCht, &error);
|
|
Packit |
78deda |
if (error)
|
|
Packit |
78deda |
pm_error("Error in and map for '%s'. %s", xorPpmFname, error);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (andPGMarray && trueTransparent)
|
|
Packit |
78deda |
blackenTransparentAreas(xorPPMarray, cols, rows,
|
|
Packit |
78deda |
andPGMarray, andMaxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
xorBitmap = createBitmap(bpp, xorPPMarray, cols, rows, xorCht);
|
|
Packit |
78deda |
andBitmap = createAndBitmap(andPGMarray, cols, rows, andMaxval);
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Fill in the entry data fields.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
entry->width = cols;
|
|
Packit |
78deda |
entry->height = rows;
|
|
Packit |
78deda |
entry->color_count = entry_cols;
|
|
Packit |
78deda |
entry->reserved = 0;
|
|
Packit |
78deda |
entry->planes = 1;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* all the icons I looked at ignored this value...
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
entry->bitcount = bpp;
|
|
Packit |
78deda |
entry->ih = createInfoHeader(entry, xorBitmap, andBitmap);
|
|
Packit |
78deda |
entry->colors = palette->colors;
|
|
Packit |
38c941 |
overflow2(4, entry->color_count);
|
|
Packit |
38c941 |
overflow_add(xorBitmap->size, andBitmap->size);
|
|
Packit |
38c941 |
overflow_add(xorBitmap->size + andBitmap->size, 40);
|
|
Packit |
38c941 |
overflow_add(xorBitmap->size + andBitmap->size + 40, 4 * entry->color_count);
|
|
Packit |
38c941 |
entry->size_in_bytes =
|
|
Packit |
78deda |
xorBitmap->size + andBitmap->size + 40 + (4 * entry->color_count);
|
|
Packit |
78deda |
if (verbose)
|
|
Packit |
78deda |
pm_message("entry->size_in_bytes = %d + %d + %d = %d",
|
|
Packit |
78deda |
xorBitmap->size ,andBitmap->size,
|
|
Packit |
78deda |
40, entry->size_in_bytes );
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* We don't know the offset ATM, set to 0 for now.
|
|
Packit |
78deda |
* Have to calculate this at the end.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
entry->file_offset = 0;
|
|
Packit |
78deda |
entry->xorBitmapOut = xorBitmap->data;
|
|
Packit |
78deda |
entry->andBitmapOut = andBitmap->data;
|
|
Packit |
78deda |
entry->xBytesXor = xorBitmap->xBytes;
|
|
Packit |
78deda |
entry->xBytesAnd = andBitmap->xBytes;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Add the entry to the entries array.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
++MSIconData->count;
|
|
Packit |
78deda |
/* Perhaps I should allocate ahead, and take fewer trips to the well. */
|
|
Packit |
78deda |
REALLOCARRAY(MSIconData->entries, MSIconData->count);
|
|
Packit |
78deda |
MSIconData->entries[MSIconData->count-1] = entry;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeIC_Entry (IC_Entry const entry) {
|
|
Packit |
78deda |
writeU1(entry->width);
|
|
Packit |
78deda |
writeU1(entry->height);
|
|
Packit |
78deda |
writeU1(entry->color_count); /* chops 256->0 on its own.. */
|
|
Packit |
78deda |
writeU1(entry->reserved);
|
|
Packit |
78deda |
writeU2(entry->planes);
|
|
Packit |
78deda |
writeU2(entry->bitcount);
|
|
Packit |
78deda |
writeU4(entry->size_in_bytes);
|
|
Packit |
78deda |
writeU4(entry->file_offset);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeIC_InfoHeader (IC_InfoHeader const ih) {
|
|
Packit |
78deda |
writeU4(ih->size);
|
|
Packit |
78deda |
writeU4(ih->width);
|
|
Packit |
78deda |
writeU4(ih->height);
|
|
Packit |
78deda |
writeU2(ih->planes);
|
|
Packit |
78deda |
writeU2(ih->bitcount);
|
|
Packit |
78deda |
writeU4(ih->compression);
|
|
Packit |
78deda |
writeU4(ih->imagesize);
|
|
Packit |
78deda |
writeU4(ih->x_pixels_per_m);
|
|
Packit |
78deda |
writeU4(ih->y_pixels_per_m);
|
|
Packit |
78deda |
writeU4(ih->colors_used);
|
|
Packit |
78deda |
writeU4(ih->colors_important);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeIC_Color (IC_Color const col) {
|
|
Packit |
78deda |
/* Since the ppm might not have as many colors in it as we'd like,
|
|
Packit |
78deda |
* (2, 16, 256), stick 0 in the gaps.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* This means that we lose palette information, but that can't be
|
|
Packit |
78deda |
* helped.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (col == NULL) {
|
|
Packit |
78deda |
writeU1(0);
|
|
Packit |
78deda |
writeU1(0);
|
|
Packit |
78deda |
writeU1(0);
|
|
Packit |
78deda |
writeU1(0);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
writeU1(col->blue);
|
|
Packit |
78deda |
writeU1(col->green);
|
|
Packit |
78deda |
writeU1(col->red);
|
|
Packit |
78deda |
writeU1(col->reserved);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeBitmap(u1 ** const bitmap, int const xBytes, int const height) {
|
|
Packit |
78deda |
int y;
|
|
Packit |
78deda |
for (y = 0;y
|
|
Packit |
78deda |
fwrite (bitmap[y],1,xBytes,ofp);
|
|
Packit |
78deda |
file_offset += xBytes;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
writeMS_Ico(MS_Ico const MSIconData,
|
|
Packit |
78deda |
const char * const outFname) {
|
|
Packit |
78deda |
int x,y;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ofp = pm_openw(outFname);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
writeU2(MSIconData->reserved);
|
|
Packit |
78deda |
writeU2(MSIconData->type);
|
|
Packit |
78deda |
writeU2(MSIconData->count);
|
|
Packit |
78deda |
for (x=0;x<MSIconData->count;x++) writeIC_Entry(MSIconData->entries[x]);
|
|
Packit |
78deda |
for (x=0;x<MSIconData->count;x++) {
|
|
Packit |
78deda |
writeIC_InfoHeader(MSIconData->entries[x]->ih);
|
|
Packit |
78deda |
for (y=0;y<(MSIconData->entries[x]->color_count);y++) {
|
|
Packit |
78deda |
writeIC_Color(MSIconData->entries[x]->colors[y]);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (verbose) pm_message("writing xor bitmap");
|
|
Packit |
78deda |
writeBitmap(MSIconData->entries[x]->xorBitmapOut,
|
|
Packit |
78deda |
MSIconData->entries[x]->xBytesXor,
|
|
Packit |
78deda |
MSIconData->entries[x]->height);
|
|
Packit |
78deda |
if (verbose) pm_message("writing and bitmap");
|
|
Packit |
78deda |
writeBitmap(MSIconData->entries[x]->andBitmapOut,
|
|
Packit |
78deda |
MSIconData->entries[x]->xBytesAnd,
|
|
Packit |
78deda |
MSIconData->entries[x]->height);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
fclose(ofp);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, char ** argv) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct cmdlineInfo cmdline;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MS_Ico const MSIconDataP = createIconFile();
|
|
Packit |
78deda |
unsigned int iconIndex;
|
|
Packit |
78deda |
unsigned int offset;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_init (&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
parseCommandLine(argc, argv, &cmdline);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
verbose = cmdline.verbose;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (iconIndex = 0; iconIndex < cmdline.iconCount; ++iconIndex) {
|
|
Packit |
78deda |
addEntryToIcon(MSIconDataP, cmdline.inputFilespec[iconIndex],
|
|
Packit |
78deda |
cmdline.andpgmFilespec[iconIndex],
|
|
Packit |
78deda |
cmdline.truetransparent);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Now we have to go through and calculate the offsets.
|
|
Packit |
78deda |
* The first infoheader starts at 6 + count*16 bytes.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
offset = (MSIconDataP->count * 16) + 6;
|
|
Packit |
78deda |
for (iconIndex = 0; iconIndex < MSIconDataP->count; ++iconIndex) {
|
|
Packit |
78deda |
IC_Entry entry = MSIconDataP->entries[iconIndex];
|
|
Packit |
78deda |
entry->file_offset = offset;
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Increase the offset by the size of this offset & data.
|
|
Packit |
78deda |
* this includes the size of the color data.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
offset += entry->size_in_bytes;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* And now, we have to actually SAVE the .ico!
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
writeMS_Ico(MSIconDataP, cmdline.output);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(cmdline.inputFilespec);
|
|
Packit |
78deda |
free(cmdline.andpgmFilespec);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|