/* pbmmake.c - create a blank bitmap of a specified size
*
* Akira Urushibata ("Douso") wrote some of the core code that went
* into the Netpbm 10.23 (July 2004) version of this program and licenses
* that code to the public under GPL.
*
* Bryan Henderson wrote the rest of that version and contributed his
* work to the public domain.
*
* See doc/HISTORY for a full history of this program.
**
*/
#include "pm_c_util.h"
#include "shhopt.h"
#include "mallocvar.h"
#include "pbm.h"
enum color {COLOR_BLACK, COLOR_WHITE, COLOR_GRAY};
struct cmdlineInfo {
/* All the information the user supplied in the command line,
in a form easy for the program to use.
*/
unsigned int width;
unsigned int height;
enum color color;
};
static void
parseCommandLine(int argc, char ** argv,
struct cmdlineInfo *cmdlineP) {
/*----------------------------------------------------------------------------
Note that the file spec array we return is stored in the storage that
was passed to us as the argv array.
-----------------------------------------------------------------------------*/
optEntry *option_def;
/* Instructions to pm_optParseOptions3 on how to parse our options.
*/
optStruct3 opt;
unsigned int option_def_index;
unsigned int blackOpt, whiteOpt, grayOpt;
MALLOCARRAY_NOFAIL(option_def, 100);
option_def_index = 0; /* incremented by OPTENTRY */
OPTENT3(0, "black", OPT_FLAG, NULL, &blackOpt, 0);
OPTENT3(0, "white", OPT_FLAG, NULL, &whiteOpt, 0);
OPTENT3(0, "gray", OPT_FLAG, NULL, &grayOpt, 0);
OPTENT3(0, "grey", OPT_FLAG, NULL, &grayOpt, 0);
opt.opt_table = option_def;
opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */
pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
/* Uses and sets argc, argv, and some of *cmdlineP and others. */
if (blackOpt + whiteOpt + grayOpt > 1)
pm_error("You can specify only one of -black, -white, and -gray");
if (blackOpt)
cmdlineP->color = COLOR_BLACK;
else if (whiteOpt)
cmdlineP->color = COLOR_WHITE;
else if (grayOpt)
cmdlineP->color = COLOR_GRAY;
else
cmdlineP->color = COLOR_WHITE;
if (argc-1 != 2)
pm_error("Wrong number of arguments (%d). There are two "
"non-option arguments: width and height in pixels",
argc-1);
else {
cmdlineP->width = pm_parse_width(argv[1]);
cmdlineP->height = pm_parse_height(argv[2]);
}
}
static void
writeGrayRaster(unsigned int const cols,
unsigned int const rows,
FILE * const ofP) {
unsigned int const lastCol = (cols-1)/8;
unsigned char * bitrow0, * bitrow1;
unsigned int i;
bitrow0 = pbm_allocrow_packed(cols);
bitrow1 = pbm_allocrow_packed(cols);
for (i=0; i <= lastCol; ++i) {
bitrow0[i] = (PBM_WHITE*0xaa) | (PBM_BLACK*0x55);
bitrow1[i] = (PBM_WHITE*0x55) | (PBM_BLACK*0xaa);
/* 0xaa = 10101010 ; 0x55 = 01010101 */
}
pbm_cleanrowend_packed(bitrow0, cols);
pbm_cleanrowend_packed(bitrow1, cols);
if (rows > 1) {
unsigned int row;
for (row = 1; row < rows; row += 2) {
pbm_writepbmrow_packed(ofP, bitrow0, cols, 0);
pbm_writepbmrow_packed(ofP, bitrow1, cols, 0);
}
}
if (rows % 2 == 1)
pbm_writepbmrow_packed(ofP, bitrow0, cols, 0);
pbm_freerow(bitrow0);
pbm_freerow(bitrow1);
}
static void
writeSingleColorRaster(unsigned int const cols,
unsigned int const rows,
bit const color,
FILE * const ofP) {
unsigned int const lastCol = (cols-1)/8;
unsigned char * bitrow0;
unsigned int i;
bitrow0 = pbm_allocrow_packed(cols);
for (i = 0; i <= lastCol; ++i)
bitrow0[i] = color*0xff;
if (color != 0)
pbm_cleanrowend_packed(bitrow0, cols);
/* row end trimming, not necessary with white */
{
unsigned int row;
for (row = 0; row < rows; ++row)
pbm_writepbmrow_packed(ofP, bitrow0, cols, 0);
}
pbm_freerow(bitrow0);
}
int
main(int argc, char * argv[]) {
struct cmdlineInfo cmdline;
pbm_init(&argc, argv);
parseCommandLine(argc, argv, &cmdline);
pbm_writepbminit(stdout, cmdline.width, cmdline.height, 0);
if (cmdline.color == COLOR_GRAY)
writeGrayRaster(cmdline.width, cmdline.height, stdout);
else {
bit const color = cmdline.color == COLOR_WHITE ? PBM_WHITE : PBM_BLACK;
writeSingleColorRaster(cmdline.width, cmdline.height, color, stdout);
}
pm_close(stdout);
return 0;
}