rtoss

Subversion Repositories:
Compare Path: Rev
With Path: Rev
/ @ 314  →  / @ 315
New file
/bfdbmp-tools/bdf2bmp.c
@@ -0,0 +1,821 @@
/*
* bdf2bmp -- output all glyphs in a bdf-font to a bmp-image-file
* version: 0.6
* date: Wed Jan 10 23:59:03 2001
* author: ITOU Hiroki (itouh@lycos.ne.jp)
*/
 
/*
* Copyright (c) 2000,2001 ITOU Hiroki
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
 
/* modify if you want; color of spacing */
#define COLOR_SPACING_RED 0x9a
#define COLOR_SPACING_GREEN 0x9a
#define COLOR_SPACING_BLUE 0xbd
/* modify if you want; out-of-dwidth over baseline */
#define COLOR_OVERBL_RED 0xca
#define COLOR_OVERBL_GREEN 0xca
#define COLOR_OVERBL_BLUE 0xd8
/* modify if you want; out-of-dwidth under baseline */
#define COLOR_UNDERBL_RED 0xde
#define COLOR_UNDERBL_GREEN 0xde
#define COLOR_UNDERBL_BLUE 0xe7
 
#define VERBOSE
 
#include <stdio.h> /* printf(), fopen(), fwrite() */
#include <stdlib.h> /* malloc(), EXIT_SUCCESS, strtol(), exit() */
#include <string.h> /* strcmp(), strcpy() */
#include <limits.h> /* strtol() */
#include <sys/stat.h> /* stat() */
#include <sys/types.h> /* stat ? */
#include <ctype.h> /* isdigit() */
 
#define LINE_CHARMAX 1000 /* number of max characters in bdf-font-file; number is without reason */
#define FILENAME_CHARMAX 256 /* number of max characters in filenames; number is without reason */
#define ON 1 /* number is without reason; only needs the difference to OFF */
#define OFF 0 /* number is without reason; only needs the difference to ON */
#define PARAM_MAX 10 /* max number of parameters */
 
#ifdef DEBUG
#define d_printf(message,arg) printf(message,arg)
#else /* not DEBUG */
#define d_printf(message,arg)
#endif /* DEBUG */
 
#ifdef VERBOSE
#define v_printf(message,arg) printf(message,arg)
#else /* not VERBOSE */
#define v_printf(message,arg)
#endif /* VERBOSE */
 
/* macro */
#define STOREBITMAP() if(flagBitmap == ON){\
memcpy(nextP, sP, length);\
nextP += length;\
}
 
struct boundingbox{
int w; /* width (pixel) */
int h; /* height */
int offx; /* offset y (pixel) */
int offy; /* offset y */
};
 
/* global var */
struct boundingbox font; /* global boundingbox */
static int chars; /* total number of glyphs in a bdf file */
static int dwflag = OFF; /* device width; only used for proportional-fonts */
static int endian; /* 0 = MSB, 1 = LSB */
 
/* func prototype */
void checkEndian(void);
void dwrite(const void *ptrP, int n, FILE *outP);
void writeBmpFile(unsigned char *bitmapP, int spacing, int colchar, FILE *bmpP);
void assignBitmap(unsigned char *bitmapP, char *glyphP, int sizeglyphP, struct boundingbox glyph, int dw);
int getLine(char* lineP, int max, FILE* inputP);
unsigned char *readBdfFile(unsigned char *bitmapP, FILE *readP);
void printhelp(void);
int main(int argc, char *argv[]);
 
 
 
/*
* Is your-CPU-byte-order MSB or LSB?
* MSB .. Most Significant Byte first (BigEndian) e.g. PowerPC, SPARC
* LSB .. Least Significant Byte first (LittleEndian) e.g. Intel Pentium
*/
void checkEndian(void){
unsigned long ulong = 0x12345678;
unsigned char *ucharP;
 
ucharP = (unsigned char *)(&ulong);
if(*ucharP == 0x78){
d_printf("LSB 0x%x\n", *ucharP);
endian = 1;
}else{
d_printf("MSB 0x%x\n", *ucharP);
endian = 0;
}
}
 
 
 
/*
* write to disk; with arranging LSBfirst(LittleEndian) byte order,
* because BMP-file is defined as LSB-first
*/
void dwrite(const void *varP, int n, FILE *outP){
const unsigned char *p = varP;
int i;
unsigned char tmp;
 
if(endian == 1){
/* LSB; write without arranging */
for(i=0; i<n; i++){
tmp = fwrite(p+i, 1, sizeof(unsigned char), outP);
if(tmp != sizeof(unsigned char)){
printf("error: cannot write an output-file\n");
exit(EXIT_FAILURE);
}
}
}else{
/* MSB; write with arranging */
for(i=n-1; i>=0; i--){
tmp = fwrite(p+i, 1, sizeof(unsigned char), outP);
if(tmp != sizeof(unsigned char)){
printf("error: cannot write an output-file\n");
exit(EXIT_FAILURE);
}
}
}
}
 
 
 
/*
* 3. read bitmapAREA(onMemory) and write bmpFile with adding spacing
* BMP-file: noCompression(BI_RGB), 8bitColor, Windows-Win32 type
*/
void writeBmpFile(unsigned char *bitmapP, int spacing, int colchar, FILE *bmpP){
long bmpw; /* bmp-image width (pixel) */
long bmph; /* bmp-image height (pixel) */
int bmppad; /* number of padding pixels */
unsigned long bmpTotalSize; /* bmp filesize (byte) */
/* bmp-lines needs to be long alined and padded with 0 */
unsigned long ulong;
unsigned short ushort;
signed long slong;
unsigned char uchar;
int i,x,y,g,tmp;
int rowchar; /* number of row glyphs */
int bx, by;
 
/* bmp-image width */
bmpw = (font.w+spacing)*colchar + spacing;
 
/* bmp-image height */
rowchar = (chars/colchar) + (chars%colchar!=0);
bmph = (font.h+spacing)*rowchar + spacing;
 
v_printf(" BMP width = %d pixels\n", (int)bmpw);
v_printf(" BMP height = %d pixels\n", (int)bmph);
d_printf(" number of glyphs column=%d ", colchar);
d_printf("row=%d\n", rowchar);
 
bmppad = ((bmpw + 3) / 4 * 4) - bmpw;
bmpTotalSize = (bmpw + bmppad) * bmph
+ sizeof(long)*11 + sizeof(short)*5 + sizeof(char)*4*256;
v_printf(" BMP filesize = %d bytes\n", (int)bmpTotalSize);
 
 
/*
* BITMAPFILEHEADER struct
*/
ushort = 0x4d42; /* 4d = 'M', 42 = 'B' */
dwrite(&ushort, sizeof(ushort), bmpP);
ulong = bmpTotalSize;
dwrite(&ulong, sizeof(ulong), bmpP);
ushort = 0x00;
dwrite(&ushort, sizeof(ushort), bmpP); /* reserved as 0 */
dwrite(&ushort, sizeof(ushort), bmpP); /* reserved as 0 */
 
/* bfOffBits: offset to image-data array */
ulong = sizeof(long)*11 + sizeof(short)*5 + sizeof(char)*4*256;
dwrite(&ulong, sizeof(ulong), bmpP);
 
 
/*
* BITMAPINFOHEADER struct
*/
ulong = 40; /* when Windows-BMP, this is 40 */
dwrite(&ulong, sizeof(ulong), bmpP);
slong = bmpw; /* biWidth */
dwrite(&slong, sizeof(slong), bmpP);
slong = bmph; /* biHeight: down-top */
dwrite(&slong, sizeof(slong), bmpP);
ushort = 1; /* biPlanes: must be 1 */
dwrite(&ushort, sizeof(ushort), bmpP);
ushort = 8; /* biBitCount: 8bitColor */
dwrite(&ushort, sizeof(ushort), bmpP);
ulong = 0; /* biCompression: noCompression(BI_RGB) */
dwrite(&ulong, sizeof(ulong), bmpP);
ulong = 0; /* biSizeImage: when noComprsn, 0 is ok */
dwrite(&ulong, sizeof(ulong), bmpP);
slong = 0; /* biXPelsPerMeter: resolution x; 0 ok */
dwrite(&slong, sizeof(slong), bmpP);
slong = 0; /* biYPelsPerMeter: res y; 0 is ok */
dwrite(&slong, sizeof(slong), bmpP);
ulong = 0; /* biClrUsed: optimized color palette; not used */
dwrite(&ulong, sizeof(ulong), bmpP);
ulong = 0; /* biClrImportant: 0 is ok */
dwrite(&ulong, sizeof(ulong), bmpP);
 
/*
* RGBQUAD[256]: color palette
*/
/* palette[0]: background of glyphs */
uchar = 0xff;
dwrite(&uchar, sizeof(uchar), bmpP); /* rgbBlue: B */
dwrite(&uchar, sizeof(uchar), bmpP); /* rgbGreen: G */
dwrite(&uchar, sizeof(uchar), bmpP); /* rgbRed: R */
uchar = 0;
dwrite(&uchar, sizeof(uchar), bmpP); /* rgbReserved: must be 0 */
 
/* palette[1]: foreground of glyphs */
uchar = 0;
for(i=0; i<4; i++)
dwrite(&uchar, sizeof(uchar), bmpP); /* palette[1]: #000000 */
 
/* palette[2]: spacing */
uchar = COLOR_SPACING_BLUE;
dwrite(&uchar, sizeof(uchar), bmpP); /* B */
uchar = COLOR_SPACING_GREEN;
dwrite(&uchar, sizeof(uchar), bmpP); /* G */
uchar = COLOR_SPACING_RED;
dwrite(&uchar, sizeof(uchar), bmpP); /* R */
uchar = 0;
dwrite(&uchar, sizeof(uchar), bmpP); /* must be 0 */
 
/* palette[3]: out of dwidth over baseline */
uchar = COLOR_OVERBL_BLUE;
dwrite(&uchar, sizeof(uchar), bmpP); /* B */
uchar = COLOR_OVERBL_GREEN;
dwrite(&uchar, sizeof(uchar), bmpP); /* G */
uchar = COLOR_OVERBL_RED;
dwrite(&uchar, sizeof(uchar), bmpP); /* R */
uchar = 0;
dwrite(&uchar, sizeof(uchar), bmpP); /* must be 0 */
 
/* palette[4]: out of dwidth; under baseline */
uchar = COLOR_UNDERBL_BLUE;
dwrite(&uchar, sizeof(uchar), bmpP); /* B */
uchar = COLOR_UNDERBL_GREEN;
dwrite(&uchar, sizeof(uchar), bmpP); /* G */
uchar = COLOR_UNDERBL_RED;
dwrite(&uchar, sizeof(uchar), bmpP); /* R */
uchar = 0;
dwrite(&uchar, sizeof(uchar), bmpP); /* must be 0 */
 
/* palette[5] to palette[255]: not used */
for(i=5; i<256; i++){
uchar = 0x00; /* palette[5to255]: #000000 */
dwrite(&uchar, sizeof(uchar), bmpP);
dwrite(&uchar, sizeof(uchar), bmpP);
dwrite(&uchar, sizeof(uchar), bmpP);
dwrite(&uchar, sizeof(uchar), bmpP);
}
 
/*
* IMAGE DATA array
*/
for(y=bmph-1; y>=0; y--){
for(x=0; x<bmpw+bmppad; x++){
if(x>=bmpw){
/* padding: long(4bytes) aligned */
uchar = 0; /* must pad with 0 */
dwrite(&uchar, sizeof(uchar), bmpP);
}else{
if( (y%(font.h+spacing)<spacing) || (x%(font.w+spacing)<spacing) ){
/* spacing */
uchar = 2; /* fill palette[2] */
dwrite(&uchar, sizeof(uchar), bmpP);
}else{
/* read bitmapAREA & write bmpFile */
g = (x/(font.w+spacing)) + (y/(font.h+spacing)*colchar);
bx = x - (spacing*(g%colchar)) - spacing;
by = y - (spacing*(g/colchar)) - spacing;
tmp = g*(font.h*font.w) + (by%font.h)*font.w + (bx%font.w);
if(tmp >= chars*font.h*font.w){
/* spacing over the last glyph */
uchar = 2; /* fill palette[2] */
}else
uchar = *( bitmapP + tmp);
dwrite(&uchar, sizeof(uchar), bmpP);
}
}
}
}
return;
}
 
 
 
 
/*
* 2. transfer bdf-font-file to bitmapAREA(onMemory) one glyph by one
*/
void assignBitmap(unsigned char *bitmapP, char *glyphP, int sizeglyphP, struct boundingbox glyph, int dw){
static char *hex2binP[]= {
"0000","0001","0010","0011","0100","0101","0110","0111",
"1000","1001","1010","1011","1100","1101","1110","1111"
};
int d; /* decimal number translated from hexNumber */
int hexlen; /* a line length(without newline code) */
char binP[LINE_CHARMAX]; /* binary strings translated from decimal number */
static int nowchar = 0; /* number of glyphs handlled until now */
char *tmpP;
char tmpsP[LINE_CHARMAX];
int bitAh, bitAw; /* bitA width, height */
int offtop, offbottom, offleft; /* glyph offset */
unsigned char *bitAP;
unsigned char *bitBP;
int i,j,x,y;
 
/*
* 2.1) change hexadecimal strings to a bitmap of glyph( called bitA)
*/
tmpP = strstr(glyphP, "\n");
if(tmpP == NULL){
/* if there is BITMAP\nENDCHAR in a given bdf-file */
*glyphP = '0';
*(glyphP+1) = '0';
*(glyphP+2) = '\n';
tmpP = glyphP + 2;
sizeglyphP = 3;
}
hexlen = tmpP - glyphP;
bitAw = hexlen * 4;
bitAh = sizeglyphP / (hexlen+1);
bitAP = malloc(bitAw * bitAh); /* address of bitA */
if(bitAP == NULL){
printf("error bitA malloc\n");
exit(EXIT_FAILURE);
}
for(i=0,x=0,y=0; i<sizeglyphP; i++){
if(glyphP[i] == '\n'){
x=0; y++;
}else{
sprintf(tmpsP, "0x%c", glyphP[i]); /* get one character from hexadecimal strings */
d = (int)strtol(tmpsP,(char **)NULL, 16);
strcpy(binP, hex2binP[d]); /* change hexa strings to bin strings */
for(j=0; j<4; j++,x++){
if( bitAP+y*bitAw+x > bitAP+bitAw*bitAh ){
printf("error: bitA pointer\n");
exit(EXIT_FAILURE);
}else{
*(bitAP + y*bitAw + x) = binP[j] - '0';
}
}
}
}
 
/*
* 2.2)make another bitmap area(called bitB)
* bitB is sized to FONTBOUNDINGBOX
*/
bitBP = malloc(font.w * font.h); /* address of bitB */
if(bitBP == NULL){
printf("error bitB malloc\n");
exit(EXIT_FAILURE);
}
for(i=0; i<font.h; i++){
for(j=0; j<font.w; j++){
if(dwflag == OFF){
/* all in boundingbox: palette[0] */
*(bitBP + i*font.w + j) = 0;
}else{
/* show the baselines and widths of glyphs */
if( (j < (-1)*font.offx) || (j >= (-1)*font.offx+dw)){
if(i < font.h - (-1)*font.offy){
/* over baseline: palette[3] */
*(bitBP + i*font.w + j) = 3;
}else{
/* under baseline: palette[4] */
*(bitBP + i*font.w + j) = 4;
}
}else{
/* in dwidth: palette[0] */
*(bitBP + i*font.w + j) = 0;
}
}
}
}
 
/*
* 2.3) copy bitA inside BBX (smaller) to bitB (bigger)
* with offset-shifting;
* a scope beyond bitA is already filled with palette[0or3]
*/
offleft = (-1)*font.offx + glyph.offx;
/* offright = font.w - glyph.w - offleft; */
 
offbottom = (-1)*font.offy + glyph.offy;
offtop = font.h - glyph.h - offbottom;
 
for(i=0; i<font.h; i++){
if( i<offtop || i>=offtop+glyph.h )
; /* do nothing */
else
for(j=0; j<font.w; j++)
if( j<offleft || j>=offleft+glyph.w )
; /* do nothing */
else
*(bitBP + i*font.w + j) = *(bitAP + (i-offtop)*bitAw + (j-offleft));
}
 
/*
* 2.4) copy bitB to bitmapAREA
*/
for(i=0; i<font.h; i++)
for(j=0; j<font.w; j++)
*(bitmapP + (nowchar*font.w*font.h) + (i*font.w) + j) = *(bitBP + i*font.w + j);
 
nowchar++;
free(bitAP);
free(bitBP);
}
 
 
/*
* read oneline from textfile
*/
int getLine(char* lineP, int max, FILE* inputP){
if (fgets(lineP, max, inputP) == NULL)
return 0;
else
return strlen(lineP); /* fgets returns strings included '\n' */
}
 
 
/*
* 1. read BDF-file and transfer to assignBitmap()
*/
unsigned char *readBdfFile(unsigned char *bitmapP, FILE *readP){
int i;
int length;
char sP[LINE_CHARMAX]; /* one line(strings) from bdf-font-file */
static int cnt; /* only used in debugging: counter of appeared glyphs */
struct boundingbox glyph; /* an indivisual glyph width, height,offset x,y */
int flagBitmap = OFF; /* this line is bitmap-data?(ON) or no?(OFF) */
char *tokP; /* top address of a token from strings */
char *glyphP = NULL; /* bitmap-data(hexadecimal strings) */
char* nextP = NULL; /* address of writing next in glyphP */
int dw = 0; /* dwidth */
static int bdfflag = OFF; /* the given bdf-file is valid or not */
 
while(1){
length = getLine(sP, LINE_CHARMAX, readP);
if((bdfflag == OFF) && (length == 0)){
/* given input-file is not a bdf-file */
printf("error: input-file is not a bdf file\n");
exit(EXIT_FAILURE);
}
if(length == 0)
break; /* escape from while-loop */
 
/* remove carriage-return(CR) */
for(i=0; i<length; i++){
if(sP[i] == '\r'){
sP[i] = '\n';
length--;
}
}
 
/* classify from the top character of sP */
switch(sP[0]){
case 'S':
if(bdfflag == OFF){
/* top of the bdf-file */
if(strncmp(sP, "STARTFONT ", 10) == 0){
bdfflag = ON;
d_printf("startfont exists %d\n", bdfflag);
}else{
/* given input-file is not a bdf-file */
printf("error: input-file is not a bdf file\n");
exit(EXIT_FAILURE);
}
}
break;
case 'F':
if(strncmp(sP, "FONTBOUNDINGBOX ", 16) == 0){
/* 16 means no comparing '\0' */
 
/* get font.w, font.h, font.offx, and font.offy */
tokP = strtok(sP, " ");/* tokP addresses next space of FONTBOUNDINGBOX */
tokP += (strlen(tokP)+1);/* tokP addresses top character of width in FONTBOUNDINGBOX */
tokP = strtok(tokP, " ");/* set NUL on space after width */
font.w = atoi(tokP);
tokP += (strlen(tokP)+1);/* height in FONTBOUNDINGBOX */
tokP = strtok(tokP, " ");
font.h = atoi(tokP);
tokP += (strlen(tokP)+1);
tokP = strtok(tokP, " ");
font.offx = atoi(tokP);
tokP += (strlen(tokP)+1);
tokP = strtok(tokP, "\n");
font.offy = atoi(tokP);
d_printf("global glyph width=%dpixels ",font.w);
d_printf("height=%dpixels\n",font.h);
d_printf("global glyph offset x=%dpixels ",font.offx);
d_printf("y=%dpixels\n",font.offy);
}else
STOREBITMAP();
break;
case 'C':
if(strncmp(sP, "CHARS ", 6) == 0){
/* get chars */
tokP = strtok(sP, " ");
tokP += (strlen(tokP)+1);
tokP = strtok(tokP, "\n");
chars = atoi(tokP);
v_printf(" Total glyphs = %d\n",chars);
cnt=0;
 
/* allocate bitmapAREA */
bitmapP = (unsigned char*)malloc(chars * font.h * font.w );
if(bitmapP == NULL){
printf("error malloc\n");
exit(EXIT_FAILURE);
}
}else
STOREBITMAP();
break;
case 'D':
if(strncmp(sP, "DWIDTH ", 7) == 0){
/* get dw */
tokP = strtok(sP, " ");
tokP += (strlen(tokP)+1);
tokP = strtok(tokP, " ");
dw = atoi(tokP);
}else
STOREBITMAP();
break;
case 'B':
if(strncmp(sP, "BITMAP", 6) == 0){
/* allocate glyphP */
glyphP = (char*)malloc(font.w*font.h); /* allocate more room */
if(glyphP == NULL){
printf("error malloc bdf\n");
exit(EXIT_FAILURE);
}
memset(glyphP, 0, font.w*font.h); /* zero clear */
nextP = glyphP;
flagBitmap = ON;
}else if(strncmp(sP, "BBX ", 4) == 0){
/* get glyph.offx, glyph.offy, glyph.w, and glyph.h */
tokP = strtok(sP, " ");/* space after 'BBX' */
tokP += (strlen(tokP)+1);/* top of width */
tokP = strtok(tokP, " ");/* set NUL on space after width */
glyph.w = atoi(tokP);
tokP += (strlen(tokP)+1);/* height */
tokP = strtok(tokP, " ");
glyph.h = atoi(tokP);
tokP += (strlen(tokP)+1);/* offx */
tokP = strtok(tokP, " ");
glyph.offx = atoi(tokP);
tokP += (strlen(tokP)+1);/* offy */
tokP = strtok(tokP, "\n");
glyph.offy = atoi(tokP);
/* d_printf("glyph width=%dpixels ",glyph.w); */
/* d_printf("height=%dpixels\n",glyph.h); */
/* d_printf("glyph offset x=%dpixels ",glyph.offx); */
/* d_printf("y=%dpixels\n",glyph.offy); */
}else
STOREBITMAP();
break;
case 'E':
if(strncmp(sP, "ENDCHAR", 7) == 0){
d_printf("\nglyph %d\n", cnt);
d_printf("%s\n",glyphP);
assignBitmap(bitmapP, glyphP, nextP - glyphP, glyph, dw);
flagBitmap = OFF;
free(glyphP);
cnt++;
}else
STOREBITMAP();
break;
default:
STOREBITMAP();
break;
}/* switch */
}/* while */
/* 'break' goto here */
return bitmapP;
}
 
 
/*
*
*/
void printhelp(void){
printf("bdf2bmp version 0.6\n");
printf("Usage: bdf2bmp [-option] input-bdf-file output-bmp-file\n");
printf("Option:\n");
printf(" -sN spacing N pixels (default N=2)\n");
printf(" N value can range from 0 to 32\n");
printf(" -cN specifying N colomns in grid (default N=32)\n");
printf(" N value can range from 1 to 1024\n");
printf(" -w showing the baseline and the widths of glyphs\n");
printf(" with gray colors\n");
printf(" -i prompting whether to overwrite an existing file\n");
printf(" -h print help\n");
exit(EXIT_FAILURE);
}
 
 
 
/*
*
*/
int main(int argc, char *argv[]){
FILE *readP;
FILE *writeP;
char readFilename[FILENAME_CHARMAX] = "input.bdf";
char writeFilename[FILENAME_CHARMAX] = "output.bmp";
int i, j, tmp, n, dst, c;
char *sP;
unsigned char *bitmapP = NULL; /* address of bitmapAREA */
int spacing = 2; /* breadth of spacing (default 2) */
int flag;
int colchar = 32; /* number of columns(horizontal) (default 32) */
char paramP[PARAM_MAX][LINE_CHARMAX]; /* parameter strings */
int iflag = OFF;
struct stat fileinfo;
 
/*
* deal with arguments
*/
if(argc < 2){
/* printf("error: not enough arguments\n"); */
printhelp();
}
 
/* formatting arguments */
sP = calloc(LINE_CHARMAX, sizeof(char));
if(sP == NULL){
printf("error\n");
exit(1);
}
for(i=1,dst=0,n=0; i<argc; i++){
if(argv[i][0] == '-'){
/* command-line options */
for(j=1; j<(int)strlen(argv[i]); j++){
if(argv[i][j]=='w' ||
argv[i][j]=='i' ||
argv[i][j]=='h' ||
argv[i][j]=='v')
{
*(sP+dst) = '-'; dst++;
*(sP+dst) = argv[i][j]; dst++;
*(sP+dst) = '\0';
strcpy(paramP[n], sP); dst=0; n++;
memset(sP,0,LINE_CHARMAX);
if(n >= PARAM_MAX){
printf("error: too many arguments\n");
exit(EXIT_FAILURE);
}
 
}else if( (argv[i][j]=='s') ||
(argv[i][j]=='c'))
{
*(sP+dst) = '-'; dst++;
*(sP+dst) = argv[i][j]; dst++;
}else if( isdigit(argv[i][j]) == 0 ){
/* not [0-9] */
printf("error: invalid option -- '%c'\n", argv[i][j]);
exit(EXIT_FAILURE);
}else if( argv[i][j+1] == '\0' ){
*(sP+dst) = argv[i][j]; dst++;
*(sP+dst) = '\0';
strcpy(paramP[n], sP); dst=0; n++;
if(n >= PARAM_MAX){
printf("error: too many arguments\n");
exit(EXIT_FAILURE);
}
}else{
*(sP+dst) = argv[i][j]; dst++;
}
}
}else{
/* not command-line options */
for(j=0; j<(int)strlen(argv[i]); j++){
*(sP+dst) = argv[i][j]; dst++;
}
*(sP+dst) = '\0';
strcpy(paramP[n], sP); dst=0; n++;
memset(sP,0,LINE_CHARMAX);
if(n >= PARAM_MAX){
printf("error: too many arguments\n");
exit(EXIT_FAILURE);
}
}
}
free(sP);
 
/* interpretting arguments */
for(i=0, flag=0; i<n; i++){
switch( paramP[i][0] ){
case '-':
if(paramP[i][1] == 's')
spacing = atoi(&paramP[i][2]);
else if(paramP[i][1] == 'c')
colchar = atoi(&paramP[i][2]);
else if(paramP[i][1] == 'w')
dwflag = ON;
else if(paramP[i][1] == 'i')
iflag = ON;
else if( (paramP[i][1]=='v') || (paramP[i][1]=='h'))
printhelp();
break;
default:
if(flag == 0){
strcpy(readFilename, paramP[i]);
flag ++;
}else{
strcpy(writeFilename, paramP[i]);
if(strcmp(readFilename, writeFilename) == 0){
printf("error: input-filename and output-filename are same\n");
exit(EXIT_FAILURE);
}
flag ++;
}
break;
}
}
 
if(flag < 2){
printf("error: not enough arguments\n");
printf("Usage: bdf2bmp [-option] input-bdf-file output-bmp-file\n");
exit(EXIT_FAILURE);
}
 
/* colchar is limited from 1 to 1024 */
if(colchar < 1)
colchar = 1;
else if(colchar > 1024)
colchar = 1024;
 
/* spacing is limited from 0 to 32 */
if(spacing < 0)
spacing = 0;
else if(spacing > 32)
spacing = 32;
 
/* checkEndian */
checkEndian();
 
/*
* prepare to read&write files
*/
readP = fopen(readFilename, "r");
if(readP == NULL){
printf("bdf2bmp: '%s' does not exist\n", readFilename);
exit(EXIT_FAILURE);
}
/* Does writeFilename already exist? */
if((iflag==ON) && (stat(writeFilename, &fileinfo)==0)){
fprintf(stderr, "bdf2bmp: overwrite '%s'? ", writeFilename);
c = fgetc(stdin);
if((c=='y') || (c=='Y'))
; /* go next */
else
/* printf("not overwrite\n"); */
exit(EXIT_FAILURE);
}
writeP=fopen(writeFilename, "wb");
if(writeP == NULL){
printf("error: cannot write '%s'\n", writeFilename);
exit(EXIT_FAILURE);
}
 
 
/* read bdf-font-file */
bitmapP = readBdfFile(bitmapP, readP);
fclose(readP);
 
/* write bmp-image-file */
writeBmpFile(bitmapP, spacing, colchar, writeP);
tmp = fclose(writeP);
if(tmp == EOF){
printf("error: cannot write '%s'\n", writeFilename);
free(bitmapP);
exit(EXIT_FAILURE);
}
 
free(bitmapP);
return EXIT_SUCCESS;
}
New file
/bfdbmp-tools/bmp2bdf.c
@@ -0,0 +1,590 @@
/*
* bmp2bdf -- enable to modify glyphs in a bdf font
* version: 0.2
* date: Wed Feb 07 00:32:31 2001
* author: ITOU Hiroki (itouh@lycos.ne.jp)
*/
 
/*
* Copyright (c) 2001 ITOU Hiroki
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
 
 
#include <stdio.h> /* printf(), fopen(), fwrite() */
#include <stdlib.h> /* malloc(), EXIT_SUCCESS, strtol(), exit() */
#include <string.h> /* strncmp(), strcpy() */
#include <limits.h> /* strtol() */
#include <sys/stat.h> /* stat() */
#include <ctype.h> /* isspace() */
 
#define FILENAMECHARMAX 256
#define LINECHARMAX 1024
#define SIZEMAX 8
#define exiterror(msg,arg) {printf("error: " msg, arg); exitrm();}
 
#ifdef DEBUG
#define d_printf(msg,arg) printf(msg, arg)
#else /* not DEBUG */
#define d_printf(msg,arg)
#endif /* DEBUG */
 
 
/* global var */
struct imageinfo{
long w;
long h;
int size;
int offset; /* bfOffBits: offset to image-data array */
int depth; /* bitdepth */
int sp; /* width of spacing */
 
} img;
 
struct {
int w; /* width (pixel) */
int h; /* height */
int offx; /* offset y (pixel) */
int offy; /* offset y */
} font;
int numcol; /* numberOfColumns */
char outfileBdfP[FILENAMECHARMAX];
FILE *outP;
 
 
/* func prototype */
int main(int argc, char *argv[]);
char *readBmp(char *infileBmpP);
void readwriteBdf(char *infileBdfP, char *imgP, char *outfileBdfP);
int getline(char* lineP, int max, FILE* inputP);
char *gettoken(char *strP);
void newglyphwrite(FILE *outP, int nglyph, char *imgP);
long mread(const void *varP, int size);
void exitrm(void);
void bmp8bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP);
void bmp24bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP);
void bmp4bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP);
 
int main(int argc, char *argv[]){
char *imgP;
int arg;
char infileBdfP[FILENAMECHARMAX];
char infileBmpP[FILENAMECHARMAX];
 
/* handling arguments */
if((argc<4) || (argc>5)){
printf("bmp2bdf version 0.2\n");
printf("Usage: bmp2bdf [numberOfColumns] input.bdf input.bmp output.bdf\n");
exit(EXIT_FAILURE);
}
if(argc == 4){
numcol = 32;
arg = 0;
}else{
numcol = atoi(argv[1]);
arg = 1;
}
if((numcol<1) || (numcol>1024))
exiterror("numberOfColumns(%d) is over the limit\n", numcol);
strcpy(infileBdfP, argv[1+arg]);
strcpy(infileBmpP, argv[2+arg]);
strcpy(outfileBdfP, argv[3+arg]);
 
if(strcmp(infileBdfP, outfileBdfP) == 0)
exiterror("'%s' appears twice\n", infileBdfP);
 
/* read BMP file and change to IMG file */
imgP = readBmp(infileBmpP);
 
/* read and write BDF file*/
readwriteBdf(infileBdfP, imgP, outfileBdfP);
 
return EXIT_SUCCESS;
}
 
 
char *readBmp(char *infileBmpP){
struct stat fileinfo;
unsigned char *bmpP;
struct imageinfo bmp;
int val;
FILE *inP;
char *imgP;
unsigned long ul;
 
/*
* open BMP file
*/
if(stat(infileBmpP, &fileinfo) != 0)
exiterror("'%s' does not exist", infileBmpP);
bmpP = malloc(fileinfo.st_size);
if(bmpP == NULL)
exiterror("cannot allocate memory in %s'\n", infileBmpP);
 
inP = fopen(infileBmpP, "rb");
if(inP == NULL)
exiterror("cannot open '%s'\n", infileBmpP);
 
val = fread(bmpP, 1, fileinfo.st_size, inP);
if(val != fileinfo.st_size)
exiterror("cannot read '%s'\n", infileBmpP);
if(memcmp(bmpP, "BM", 2) != 0)
exiterror("%s' is not a BMP file.\n", infileBmpP);
fclose(inP);
 
/*
* analyze BMP file
*/
bmp.offset = mread(bmpP+10, sizeof(long));
ul = (unsigned long)mread(bmpP+14, sizeof(unsigned long));
if(ul != 40)
exiterror("'%s' is an OS/2-format BMP file\n", infileBmpP);
bmp.w = img.w = mread(bmpP+18, sizeof(long));
d_printf("BMP width = %ld ", bmp.w);
bmp.h = img.h = mread(bmpP+22, sizeof(long));
d_printf("height = %ld\n", bmp.h);
if(bmp.h < 0)
exiterror("bmp height(%ld) is minus-number\n", bmp.h);
 
bmp.depth = (short)mread(bmpP+28, sizeof(short));
if(bmp.depth!=4 && bmp.depth!=8 && bmp.depth!=24)
exiterror("cannot accept %dbit BMP file\n",bmp.depth);
ul = (unsigned long)mread(bmpP+30, sizeof(unsigned long));
if(ul != 0L)
exiterror("'%s' is a compressed BMP file\n", infileBmpP);
bmp.size = fileinfo.st_size;
 
/*
* malloc IMG
*/
img.size = img.w * img.h;
imgP = malloc(img.size); /* free(imageP) does not exist */
if(imgP == NULL)
exiterror("cannot allocate memory imageP %dbytes\n", img.size);
 
/*
* BMP bitdepth
*/
switch(bmp.depth){
case 4:
bmp4bit2img(bmpP, bmp, imgP);
break;
case 8:
bmp8bit2img(bmpP, bmp, imgP);
break;
case 24:
bmp24bit2img(bmpP, bmp, imgP);
break;
default:
exiterror("cannot accept %d bit BMP file\n",bmp.depth);
break;
}
 
free(bmpP);
return imgP;
}
 
 
void readwriteBdf(char *infileBdfP, char *imgP, char *outfileBdfP){
FILE *inP;
enum {INBITMAP, OUTBITMAP};
struct stat fileinfo;
char lineP[LINECHARMAX];
char strP[LINECHARMAX]; /* for not-breaking lineP with '\0' */
int st; /* status */
int len, val;
int nglyph; /* number of glyphs that appeared */
char *tokenP; /* used for splitting tokens */
 
/* file open */
if(stat(infileBdfP, &fileinfo) != 0)
exiterror("'%s' does not exist\n", infileBdfP);
inP = fopen(infileBdfP, "r");
if(inP == NULL)
exiterror("cannot open '%s'\n", infileBdfP);
 
if(stat(outfileBdfP, &fileinfo) == 0){
printf("error: '%s' already exists\n", outfileBdfP);
exit(EXIT_FAILURE);
}
outP = fopen(outfileBdfP, "wb");
if(outP == NULL)
exiterror("cannot write '%s'\n", outfileBdfP);
 
/* file check */
memset(lineP, 0x00, LINECHARMAX);
len = getline(lineP, LINECHARMAX, inP);
d_printf("len=%d\n", len);
if((len == 0) || (strncmp(lineP, "STARTFONT", 9) != 0))
exiterror("'%s' is not a BDF file.\n", infileBdfP);
val = fwrite(lineP, 1, strlen(lineP), outP);
if(val != (int)strlen(lineP))
exiterror("cannot write '%s'\n", outfileBdfP);
 
 
/* read bdf file */
nglyph = 0;
st = OUTBITMAP;
for(;;){
memset(lineP, 0x00, LINECHARMAX);
len = getline(lineP, LINECHARMAX, inP);
if(len == 0)
break;
 
if(st == INBITMAP){
if(strncmp(lineP, "ENDCHAR", 7)==0){
st = OUTBITMAP;
newglyphwrite(outP, nglyph, imgP);
nglyph++;
}
}else{ /* stat != INBITMAP */
switch(lineP[0]){
case 'B':
if(strncmp(lineP, "BBX", 3)==0)
; /* do nothing */
else if(strncmp(lineP, "BITMAP", 6)==0)
st = INBITMAP;
break; /* lines of BBX, BITMAP is written later */
case 'F':
if(strncmp(lineP, "FONTBOUNDINGBOX ", 16)==0){
strcpy(strP, lineP);
tokenP = gettoken(strP);
tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
font.w = atoi(tokenP);
tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
font.h = atoi(tokenP);
tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
font.offx = atoi(tokenP);
tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
font.offy = atoi(tokenP);
 
if( (img.w-numcol*font.w) % (numcol+1) != 0){
d_printf("numcol = %d ", numcol);
d_printf("numcol*font.h = %d\n", numcol*font.h);
 
exiterror("NumberOfColumns(%d) and the BMP file do not match.\n", numcol);
}
img.sp = (img.w - numcol*font.w) / (numcol+1);
d_printf("font.w=%d ", font.w);
d_printf("font.h=%d ", font.h);
d_printf("font.offx=%d ", font.offx);
d_printf("font.offy=%d\n", font.offy);
}
/* go next */
default:
val = fwrite(lineP, 1, strlen(lineP), outP);
if(val != (int)strlen(lineP))
exiterror("cannot write '%s'\n", outfileBdfP);
} /* switch */
} /* if(stat=.. */
} /* for(;;) */
 
fclose(inP);
fclose(outP);
d_printf("total glyphs = %d\n", nglyph);
}
 
 
/*
* read oneline from textfile
* fgets returns strings included '\n'
*/
int getline(char *lineP, int max, FILE* inputP){
char *p;
 
if(fgets(lineP, max, inputP) == NULL){
return 0;
}else{
/* change CR+LF to LF */
for(p=lineP ; *p!='\0'; p++){
if(*p == '\r'){
*p = '\n';
*(p+1) = '\0';
}
}
return strlen(lineP);
}
}
 
 
char *gettoken(char *strP){
enum {BEFORE, AFTER};
char *retP = strP;
int st; /* status */
 
st = BEFORE;
while(*strP != '\0'){
if((st==BEFORE) && (isspace(*strP)==0)){
/* before first char of token, not space */
retP = strP;
st = AFTER;
}else if((st==AFTER) && (isspace(*strP)!=0)){
/* after first char of token, space */
*strP = '\0';
return retP;
}
strP++;
}
 
/* This may read over a given string. dangerous */
return retP;
}
 
 
/*
* read glyphimage from IMG
* and change to BDF hexadecimal
*/
void newglyphwrite(FILE *outP, int nglyph, char *imgP){
char *boxP;
int i,j,k, x,y, val;
int widthaligned; /* width of a glyph (byte-aligned) */
char *bitstrP; /* BITMAP strings */
char strP[LINECHARMAX]; /* tmp buffer */
static char *hex2binP[]= {
"0000","0001","0010","0011","0100","0101","0110","0111",
"1000","1001","1010","1011","1100","1101","1110","1111"
};
 
/*
* allocate 'box' area for a glyph image
*/
widthaligned = (font.w+7) / 8 * 8;
boxP = malloc(widthaligned*font.h);
if(boxP == NULL)
exiterror("cannot allocate memory newglyphwrite %dbytes\n", widthaligned*font.h);
memset(boxP, '0', widthaligned*font.h);
 
/*
* read from IMG
*/
/* one glyph height row */
y = (font.h+img.sp) * (nglyph/numcol) + img.sp;
/* one glyph width column */
x = (font.w+img.sp) * (nglyph%numcol) + img.sp;
 
for(i=0; i<font.h; i++)
for(j=0; j<font.w; j++)
*(boxP + i*widthaligned + j) = *(imgP + (y+i)*img.w + x+j);
 
/*
* change to hexadecimal
*/
bitstrP = malloc(LINECHARMAX * font.h);
if(bitstrP == NULL)
exiterror("cannot allocate memory: bitstrP %dbytes\n",LINECHARMAX*font.h);
memset(bitstrP, 0x00, LINECHARMAX*font.h);
 
/* write BBX , BITMAP to tmpVariable */
sprintf(bitstrP, "BBX %d %d %d %d\nBITMAP\n",
font.w, font.h, font.offx, font.offy);
 
/* write bitmapData to tmpVariable */
for(i=0; i<font.h; i++){
for(j=0; j<widthaligned; j+=4){
for(k=0; k<16; k++){
if(strncmp(boxP+i*widthaligned+j, hex2binP[k],4)==0)
sprintf(strP, "%x", k);
}
strcat(bitstrP, strP);
}
strcat(bitstrP, "\n");
}
strcat(bitstrP, "ENDCHAR\n");
 
/* write tmpVariable to disk */
val = fwrite(bitstrP, 1, strlen(bitstrP), outP);
if(val != (int)strlen(bitstrP))
exiterror("cannot write a file: bitstrP %dbytes", (int)strlen(bitstrP));
 
free(boxP);
free(bitstrP);
return;
}
 
 
/*
* read memory
*/
long mread(const void *varP, int size){
const unsigned char *ucharP = varP;
char strP[LINECHARMAX];
char tmpP[SIZEMAX];
int i;
 
strcpy(strP, "0x");
 
/* Numbers in BMP file are LSB-ordered. */
for(i=size-1; i>=0; i--){
sprintf(tmpP, "%02x", *(ucharP+i));
strcat(strP, tmpP);
}
 
 
d_printf("'%s' ", strP);
return strtol(strP,(char **)NULL, 16);
}
 
 
void exitrm(void){
struct stat fileinfo;
int val;
 
fclose(outP);
if(stat(outfileBdfP, &fileinfo) == 0){
val = remove(outfileBdfP);
if(val != 0)
printf("error: cannot remove '%s'\n", outfileBdfP);
}
exit(EXIT_FAILURE);
}
 
 
void bmp8bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP){
int idx;
int nclut; /* number of CLUT(color lookup table) */
int notblack[256]; /* index number of palette */
long byteline; /* number of byte in BMP oneline */
int i, j, k;
char c;
unsigned char *b;
unsigned char buf;
 
/* check CLUT; black(RGB=0,0,0) or not */
/* '54' means CLUT address */
nclut = 0;
for(b=bmpP+54,idx=0; b<bmpP+bmp.offset; b+=4,idx++){
if(*b==0 && *(b+1)==0 && *(b+2)==0)
; /* black; do nothing */
else{
/* not black */
if(nclut >= 256)
exiterror("number of CLUT(%d) is too many\n", nclut);
notblack[nclut] = idx;
d_printf("%02x ", idx);
nclut++;
}
}
d_printf(" Not-black CLUT: %d\n", nclut);
 
/*
* change BMP format to IMG format
* IMG format(this-src-only format):
* remove BMP-header,padding
* reverse down-top to top-down
* black pixels become '1'
* white and gray and violet pixels become '0'
*/
byteline = (bmp.w + 3) / 4 * 4;
 
for(i=0; i<img.h; i++){
for(j=0; j<img.w; j++){
buf = *(bmpP + bmp.offset + (bmp.h-1-i)*byteline + j);
 
/* black? or not? */
c = '1';
for(k=0; k<nclut; k++)
if(buf == notblack[k])
c = '0'; /* not black */
 
*(imgP + i*img.w + j) = c;
}
}
return;
}
 
void bmp24bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP){
unsigned char *bufP;
char c;
int i,j;
 
long byteline = (bmp.w * 3 + 3) / 4 * 4;
 
for(i=0; i<img.h; i++){
for(j=0; j<img.w; j++){
c = '0';
bufP = bmpP + bmp.offset + (bmp.h-1-i)*byteline + j*3;
 
/* black? or not? */
if(*bufP==0 && *(bufP+1)==0 && *(bufP+2)==0)
c = '1'; /* black */
 
*(imgP + i*img.w + j) = c;
}
}
return;
}
 
void bmp4bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP){
char c;
unsigned char buf;
unsigned char *b;
unsigned char *bufP;
int notblack[16];
int idx, nclut;
int i, j, k;
long byteline;
 
/*
* read CLUT
*/
nclut = 0;
for(b=bmpP+54,idx=0; b<bmpP+bmp.offset; b+=4,idx++){
if(*b==0 && *(b+1)==0 && *(b+2)==0)
;/* black */
else{
/* not black */
if(nclut >= 16)
exiterror("number of CLUT(%d) is too many\n", nclut);
notblack[nclut] = idx;
d_printf("%02x ", idx);
nclut++;
}
}
d_printf(" Not-black CLUT: %d\n", nclut);
 
/*
* change BMP to IMG
*/
byteline = ((bmp.w/2)+(bmp.w%2!=0)+3) / 4 * 4;
 
for(i=0; i<img.h; i++){
for(j=0; j<img.w; j++){
bufP = bmpP + bmp.offset + (bmp.h-1-i)*byteline + j/2;
if(j%2==0)
/* left half */
buf = ((*bufP)>>4) & 0x0f;
else
/* right half */
buf = (*bufP) & 0x0f;
 
c = '1';
for(k=0; k<nclut; k++)
if(buf == notblack[k])
c = '0'; /* not black */
*(imgP + i*img.w + j) = c;
}
}
return;
}

Property changes:

Name: bugtraq:number
+ true

/bfdbmp-tools