rtoss - Blame information for rev 321

Subversion Repositories:
Rev:
Rev Author Line No. Line
315 roytam 1 /*
2  * bmp2bdf  --  enable to modify glyphs in a bdf font
3  * version: 0.2
4  * date:    Wed Feb 07 00:32:31 2001
5  * author:  ITOU Hiroki (itouh@lycos.ne.jp)
6  */
7  
8 /*
9  * Copyright (c) 2001 ITOU Hiroki
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33  
34  
35 #include <stdio.h>  /* printf(), fopen(), fwrite() */
36 #include <stdlib.h> /* malloc(), EXIT_SUCCESS, strtol(), exit() */
37 #include <string.h> /* strncmp(), strcpy() */
38 #include <limits.h> /* strtol() */
39 #include <sys/stat.h> /* stat() */
40 #include <ctype.h> /* isspace() */
41  
42 #define FILENAMECHARMAX 256
43 #define LINECHARMAX 1024
44 #define SIZEMAX 8
45 #define exiterror(msg,arg) {printf("error: " msg, arg); exitrm();}
46  
47 #ifdef DEBUG
48 #define d_printf(msg,arg) printf(msg, arg)
49 #else /* not DEBUG */
50 #define d_printf(msg,arg)
51 #endif /* DEBUG */
52  
53  
54 /* global var */
55 struct imageinfo{
56         long w;
57         long h;
58         int size;
59         int offset; /* bfOffBits: offset to image-data array */
60         int depth; /* bitdepth */
61         int sp; /* width of spacing */
62  
63 } img;
64  
65 struct {
66         int w; /* width (pixel) */
67         int h; /* height */
68         int offx; /* offset y (pixel) */
69         int offy; /* offset y */
70 } font;
71 int numcol; /*  numberOfColumns */
316 roytam 72 int dwidth;
321 roytam 73 int bbx_w, bbx_h, bbx_offx, bbx_offy;
315 roytam 74 char outfileBdfP[FILENAMECHARMAX];
75 FILE *outP;
76  
77  
78 /* func prototype */
79 int main(int argc, char *argv[]);
80 char *readBmp(char *infileBmpP);
81 void readwriteBdf(char *infileBdfP, char *imgP, char *outfileBdfP);
82 int getline(char* lineP, int max, FILE* inputP);
83 char *gettoken(char *strP);
84 void newglyphwrite(FILE *outP, int nglyph, char *imgP);
85 long mread(const void *varP, int size);
86 void exitrm(void);
87 void bmp8bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP);
88 void bmp24bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP);
89 void bmp4bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP);
90  
91 int main(int argc, char *argv[]){
92         char *imgP;
93         int arg;
94         char infileBdfP[FILENAMECHARMAX];
95         char infileBmpP[FILENAMECHARMAX];
96  
97         /* handling arguments */
98         if((argc<4) || (argc>5)){
99                 printf("bmp2bdf version 0.2\n");
100                 printf("Usage: bmp2bdf [numberOfColumns] input.bdf input.bmp output.bdf\n");
101                 exit(EXIT_FAILURE);
102         }
103         if(argc == 4){
104                 numcol = 32;
105                 arg = 0;
106         }else{
107                 numcol = atoi(argv[1]);
108                 arg = 1;
109         }
110         if((numcol<1) || (numcol>1024))
111                 exiterror("numberOfColumns(%d) is over the limit\n", numcol);
112         strcpy(infileBdfP, argv[1+arg]);
113         strcpy(infileBmpP, argv[2+arg]);
114         strcpy(outfileBdfP, argv[3+arg]);
115  
116         if(strcmp(infileBdfP, outfileBdfP) == 0)
117                 exiterror("'%s' appears twice\n", infileBdfP);
118  
119         /* read BMP file and change to IMG file */
120         imgP = readBmp(infileBmpP);
121  
122         /* read and write BDF file*/
123         readwriteBdf(infileBdfP, imgP, outfileBdfP);
124  
125         return EXIT_SUCCESS;
126 }
127  
128  
129 char *readBmp(char *infileBmpP){
130         struct stat fileinfo;
131         unsigned char *bmpP;
132         struct imageinfo bmp;
133         int val;
134         FILE *inP;
135         char *imgP;
136         unsigned long ul;
137  
138         /*
139          * open BMP file
140          */
141         if(stat(infileBmpP, &fileinfo) != 0)
142                 exiterror("'%s' does not exist", infileBmpP);
143         bmpP = malloc(fileinfo.st_size);
144         if(bmpP == NULL)
145                 exiterror("cannot allocate memory in %s'\n", infileBmpP);
146  
147         inP = fopen(infileBmpP, "rb");
148         if(inP == NULL)
149                 exiterror("cannot open '%s'\n", infileBmpP);
150  
151         val = fread(bmpP, 1, fileinfo.st_size, inP);
152         if(val != fileinfo.st_size)
153                 exiterror("cannot read '%s'\n", infileBmpP);
154         if(memcmp(bmpP, "BM", 2) != 0)
155                 exiterror("%s' is not a BMP file.\n", infileBmpP);
156         fclose(inP);
157  
158         /*
159          * analyze BMP file
160          */
161         bmp.offset = mread(bmpP+10, sizeof(long));
162         ul = (unsigned long)mread(bmpP+14, sizeof(unsigned long));
163         if(ul != 40)
164                 exiterror("'%s' is an OS/2-format BMP file\n", infileBmpP);
165         bmp.w = img.w = mread(bmpP+18, sizeof(long));
166         d_printf("BMP width = %ld ", bmp.w);
167         bmp.h = img.h = mread(bmpP+22, sizeof(long));
168         d_printf("height = %ld\n", bmp.h);
169         if(bmp.h < 0)
170                 exiterror("bmp height(%ld) is minus-number\n", bmp.h);
171  
172         bmp.depth = (short)mread(bmpP+28, sizeof(short));
173         if(bmp.depth!=4 && bmp.depth!=8 && bmp.depth!=24)
174                 exiterror("cannot accept %dbit BMP file\n",bmp.depth);
175         ul = (unsigned long)mread(bmpP+30, sizeof(unsigned long));
176         if(ul != 0L)
177                 exiterror("'%s' is a compressed BMP file\n", infileBmpP);
178         bmp.size = fileinfo.st_size;
179  
180         /*
181          * malloc IMG
182          */
183         img.size = img.w * img.h;
184         imgP = malloc(img.size); /*  free(imageP) does not exist */
185         if(imgP == NULL)
186                 exiterror("cannot allocate memory imageP %dbytes\n", img.size);
187  
188         /*
189          * BMP bitdepth
190          */
191         switch(bmp.depth){
192         case 4:
193                 bmp4bit2img(bmpP, bmp, imgP);
194                 break;
195         case 8:
196                 bmp8bit2img(bmpP, bmp, imgP);
197                 break;
198         case 24:
199                 bmp24bit2img(bmpP, bmp, imgP);
200                 break;
201         default:
202                 exiterror("cannot accept %d bit BMP file\n",bmp.depth);
203                 break;
204         }
205  
206         free(bmpP);
207         return imgP;
208 }
209  
210  
211 void readwriteBdf(char *infileBdfP, char *imgP, char *outfileBdfP){
212         FILE *inP;
213         enum {INBITMAP, OUTBITMAP};
214         struct stat fileinfo;
215         char lineP[LINECHARMAX];
216         char strP[LINECHARMAX]; /* for not-breaking lineP with '\0' */
217         int st; /* status */
218         int len, val;
219         int nglyph; /* number of glyphs that appeared */
220         char *tokenP; /* used for splitting tokens */
221  
222         /* file open */
223         if(stat(infileBdfP, &fileinfo) != 0)
224                 exiterror("'%s' does not exist\n", infileBdfP);
225         inP = fopen(infileBdfP, "r");
226         if(inP == NULL)
227                 exiterror("cannot open '%s'\n", infileBdfP);
228  
316 roytam 229         /*if(stat(outfileBdfP, &fileinfo) == 0){
315 roytam 230                 printf("error: '%s' already exists\n", outfileBdfP);
231                 exit(EXIT_FAILURE);
316 roytam 232         }*/
315 roytam 233         outP = fopen(outfileBdfP, "wb");
234         if(outP == NULL)
235                 exiterror("cannot write '%s'\n", outfileBdfP);
236  
237         /* file check */
238         memset(lineP, 0x00, LINECHARMAX);
239         len = getline(lineP, LINECHARMAX, inP);
240         d_printf("len=%d\n", len);
241         if((len == 0) || (strncmp(lineP, "STARTFONT", 9) != 0))
242                 exiterror("'%s' is not a BDF file.\n", infileBdfP);
243         val = fwrite(lineP, 1, strlen(lineP), outP);
244         if(val != (int)strlen(lineP))
245                 exiterror("cannot write '%s'\n", outfileBdfP);
246  
247  
248         /* read bdf file */
249         nglyph = 0;
250         st = OUTBITMAP;
251         for(;;){
252                 memset(lineP, 0x00, LINECHARMAX);
253                 len = getline(lineP, LINECHARMAX, inP);
254                 if(len == 0)
255                         break;
256  
257                 if(st == INBITMAP){
258                         if(strncmp(lineP, "ENDCHAR", 7)==0){
259                                 st = OUTBITMAP;
260                                 newglyphwrite(outP, nglyph, imgP);
261                                 nglyph++;
262                         }
263                 }else{ /*  stat != INBITMAP */
264                         switch(lineP[0]){
265                         case 'B':
321 roytam 266                                 if(strncmp(lineP, "BBX", 3)==0){
267                                         strcpy(strP, lineP);
268                                         tokenP = gettoken(strP);
269                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
270                                         bbx_w = atoi(tokenP);
271                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
272                                         bbx_h = atoi(tokenP);
273                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
274                                         bbx_offx = atoi(tokenP);
275                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
276                                         bbx_offy = atoi(tokenP);
277                                 } else if(strncmp(lineP, "BITMAP", 6)==0)
315 roytam 278                                         st = INBITMAP;
279                                 break; /* lines of BBX, BITMAP is written later */
316 roytam 280                         case 'D':
281                                 if(strncmp(lineP, "DWIDTH ", 7)==0){
282                                         strcpy(strP, lineP);
283                                         tokenP = gettoken(strP);
284                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
285                                         dwidth = atoi(tokenP);
286                                 }
321 roytam 287                                 break;
315 roytam 288                         case 'F':
289                                 if(strncmp(lineP, "FONTBOUNDINGBOX ", 16)==0){
290                                         strcpy(strP, lineP);
291                                         tokenP = gettoken(strP);
292                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
293                                         font.w = atoi(tokenP);
294                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
295                                         font.h = atoi(tokenP);
296                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
297                                         font.offx = atoi(tokenP);
298                                         tokenP = gettoken(tokenP + (int)strlen(tokenP) + 1);
299                                         font.offy = atoi(tokenP);
300  
301                                         if( (img.w-numcol*font.w) % (numcol+1) != 0){
302                                                 d_printf("numcol = %d ", numcol);
303                                                 d_printf("numcol*font.h = %d\n", numcol*font.h);
304  
305                                                 exiterror("NumberOfColumns(%d) and the BMP file do not match.\n", numcol);
306                                         }
307                                         img.sp = (img.w - numcol*font.w) / (numcol+1);
308                                         d_printf("font.w=%d ", font.w);
309                                         d_printf("font.h=%d ", font.h);
310                                         d_printf("font.offx=%d ", font.offx);
311                                         d_printf("font.offy=%d\n", font.offy);
312                                 }
313                                 /*  go next */
314                         default:
315                                 val = fwrite(lineP, 1, strlen(lineP), outP);
316                                 if(val != (int)strlen(lineP))
317                                         exiterror("cannot write '%s'\n", outfileBdfP);
318                         } /* switch */
319                 } /* if(stat=.. */
320         } /* for(;;) */
321  
322         fclose(inP);
323         fclose(outP);
324         d_printf("total glyphs = %d\n", nglyph);
325 }
326  
327  
328 /*
329  * read oneline from textfile
330  *    fgets returns strings included '\n'
331  */
332 int getline(char *lineP, int max, FILE* inputP){
333         char *p;
334  
335         if(fgets(lineP, max, inputP) == NULL){
336                 return 0;
337         }else{
338                 /* change CR+LF to LF */
339                 for(p=lineP ; *p!='\0'; p++){
340                         if(*p == '\r'){
341                                 *p = '\n';
342                                 *(p+1) = '\0';
343                         }
344                 }
345                 return strlen(lineP);
346         }
347 }
348  
349  
350 char *gettoken(char *strP){
351         enum {BEFORE, AFTER};
352         char *retP = strP;
353         int st; /* status */
354  
355         st = BEFORE;
356         while(*strP != '\0'){
357                 if((st==BEFORE) && (isspace(*strP)==0)){
358                         /* before first char of token, not space */
359                         retP = strP;
360                         st = AFTER;
361                 }else if((st==AFTER) && (isspace(*strP)!=0)){
362                         /* after first char of token, space */
363                         *strP = '\0';
364                         return retP;
365                 }
366                 strP++;
367         }
368  
369         /* This may read over a given string. dangerous */
370         return retP;
371 }
372  
373  
374 /*
375  *  read glyphimage from IMG
376  *     and change to BDF hexadecimal
377  */
378 void newglyphwrite(FILE *outP, int nglyph, char *imgP){
379         char *boxP;
380         int i,j,k, x,y, val;
321 roytam 381         int width, delta; /* width of a glyph (abs.) */
315 roytam 382         int widthaligned; /* width of a glyph (byte-aligned) */
383         char *bitstrP; /* BITMAP strings */
384         char strP[LINECHARMAX]; /* tmp buffer */
385         static char *hex2binP[]= {
386                 "0000","0001","0010","0011","0100","0101","0110","0111",
387                 "1000","1001","1010","1011","1100","1101","1110","1111"
388         };
389  
390         /*
391          * allocate 'box' area for a glyph image
392          */
321 roytam 393         //widthaligned = (font.w+7) / 8 * 8;
394         delta = bbx_w-bbx_offx-font.offx;
395         width = delta>dwidth ? delta : dwidth-(font.offx < 0 ? font.offx : 0);
396         widthaligned = (width+7) / 8 * 8;
315 roytam 397         boxP = malloc(widthaligned*font.h);
398         if(boxP == NULL)
399                 exiterror("cannot allocate memory newglyphwrite %dbytes\n", widthaligned*font.h);
400         memset(boxP, '0', widthaligned*font.h);
401  
402         /*
403          * read from IMG
404          */
405         /*   one glyph height  row */
406         y = (font.h+img.sp) * (nglyph/numcol) + img.sp;
407         /*   one glyph width   column */
408         x = (font.w+img.sp) * (nglyph%numcol) + img.sp;
409  
410         for(i=0; i<font.h; i++)
321 roytam 411                 for(j=0; j<width; j++)
315 roytam 412                         *(boxP + i*widthaligned + j) = *(imgP + (y+i)*img.w + x+j);
413  
414         /*
415          * change to hexadecimal
416          */
417         bitstrP = malloc(LINECHARMAX * font.h);
418         if(bitstrP == NULL)
419                 exiterror("cannot allocate memory: bitstrP %dbytes\n",LINECHARMAX*font.h);
420         memset(bitstrP, 0x00, LINECHARMAX*font.h);
421  
422         /* write BBX , BITMAP to tmpVariable */
321 roytam 423         sprintf(bitstrP, "DWIDTH %d 0\nBBX %d %d %d %d\nBITMAP\n",
424                 width, width, font.h, 0, font.offy);
315 roytam 425  
426         /* write bitmapData to tmpVariable */
427         for(i=0; i<font.h; i++){
428                 for(j=0; j<widthaligned; j+=4){
429                         for(k=0; k<16; k++){
430                                 if(strncmp(boxP+i*widthaligned+j, hex2binP[k],4)==0)
431                                         sprintf(strP, "%x", k);
432                         }
433                         strcat(bitstrP, strP);
434                 }
435                 strcat(bitstrP, "\n");
436         }
437         strcat(bitstrP, "ENDCHAR\n");
438  
439         /* write tmpVariable to disk */
440         val = fwrite(bitstrP, 1, strlen(bitstrP), outP);
441         if(val != (int)strlen(bitstrP))
442                 exiterror("cannot write a file: bitstrP %dbytes", (int)strlen(bitstrP));
443  
444         free(boxP);
445         free(bitstrP);
446         return;
447 }
448  
449  
450 /*
451  * read memory
452  */
453 long mread(const void *varP, int size){
454         const unsigned char *ucharP = varP;
455         char strP[LINECHARMAX];
456         char tmpP[SIZEMAX];
457         int i;
458  
459         strcpy(strP, "0x");
460  
461         /* Numbers in BMP file are LSB-ordered. */
462         for(i=size-1; i>=0; i--){
463                 sprintf(tmpP, "%02x", *(ucharP+i));
464                 strcat(strP, tmpP);
465         }
466  
467  
468         d_printf("'%s' ", strP);
469         return strtol(strP,(char **)NULL, 16);
470 }
471  
472  
473 void exitrm(void){
474         struct stat fileinfo;
475         int val;
476  
477         fclose(outP);
478         if(stat(outfileBdfP, &fileinfo) == 0){
479                 val = remove(outfileBdfP);
480                 if(val != 0)
481                         printf("error: cannot remove '%s'\n", outfileBdfP);
482         }
483         exit(EXIT_FAILURE);
484 }
485  
486  
487 void bmp8bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP){
488         int idx;
489         int nclut; /* number of CLUT(color lookup table) */
490         int notblack[256]; /* index number of palette */
491         long byteline; /* number of byte in BMP oneline */
492         int i, j, k;
493         char c;
494         unsigned char *b;
495         unsigned char buf;
496  
497         /* check CLUT; black(RGB=0,0,0) or not */
498         /*   '54' means CLUT address */
499         nclut = 0;
500         for(b=bmpP+54,idx=0; b<bmpP+bmp.offset; b+=4,idx++){
501                 if(*b==0 && *(b+1)==0 && *(b+2)==0)
502                         ; /* black; do nothing */
503                 else{
504                         /* not black */
505                         if(nclut >= 256)
506                                 exiterror("number of CLUT(%d) is too many\n", nclut);
507                         notblack[nclut] = idx;
508                         d_printf("%02x ", idx);
509                         nclut++;
510                 }
511         }
512         d_printf("  Not-black CLUT: %d\n", nclut);
513  
514         /*
515          * change BMP format to IMG format
516          *   IMG format(this-src-only format):
517          *               remove BMP-header,padding
518          *               reverse down-top to top-down
519          *               black pixels become '1'
520          *               white and gray and violet pixels become '0'
521          */
522         byteline = (bmp.w + 3) / 4 * 4;
523  
524         for(i=0; i<img.h; i++){
525                 for(j=0; j<img.w; j++){
526                         buf = *(bmpP + bmp.offset + (bmp.h-1-i)*byteline + j);
527  
528                         /* black? or not? */
529                         c = '1';
530                         for(k=0; k<nclut; k++)
531                                 if(buf == notblack[k])
532                                         c = '0'; /* not black */
533  
534                         *(imgP + i*img.w + j) = c;
535                 }
536         }
537         return;
538 }
539  
540 void bmp24bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP){
541         unsigned char *bufP;
542         char c;
543         int i,j;
544  
545         long byteline = (bmp.w * 3 + 3) / 4 * 4;
546  
547         for(i=0; i<img.h; i++){
548                 for(j=0; j<img.w; j++){
549                         c = '0';
550                         bufP = bmpP + bmp.offset + (bmp.h-1-i)*byteline + j*3;
551  
552                         /* black? or not? */
553                         if(*bufP==0 && *(bufP+1)==0 && *(bufP+2)==0)
554                                 c = '1'; /* black */
555  
556                         *(imgP + i*img.w + j) = c;
557                 }
558         }
559         return;
560 }
561  
562 void bmp4bit2img(unsigned char *bmpP, struct imageinfo bmp, char *imgP){
563         char c;
564         unsigned char buf;
565         unsigned char *b;
566         unsigned char *bufP;
567         int notblack[16];
568         int idx, nclut;
569         int i, j, k;
570         long byteline;
571  
572         /*
573          * read CLUT
574          */
575         nclut = 0;
576         for(b=bmpP+54,idx=0; b<bmpP+bmp.offset; b+=4,idx++){
577                 if(*b==0 && *(b+1)==0 && *(b+2)==0)
578                         ;/* black */
579                 else{
580                         /* not black */
581                         if(nclut >= 16)
582                                 exiterror("number of CLUT(%d) is too many\n", nclut);
583                         notblack[nclut] = idx;
584                         d_printf("%02x ", idx);
585                         nclut++;
586                 }
587         }
588         d_printf("  Not-black CLUT: %d\n", nclut);
589  
590         /*
591          * change BMP to IMG
592          */
593         byteline = ((bmp.w/2)+(bmp.w%2!=0)+3) / 4 * 4;
594  
595         for(i=0; i<img.h; i++){
596                 for(j=0; j<img.w; j++){
597                         bufP = bmpP + bmp.offset + (bmp.h-1-i)*byteline + j/2;
598                         if(j%2==0)
599                                 /* left half */
600                                 buf = ((*bufP)>>4) & 0x0f;
601                         else
602                                 /* right half */
603                                 buf = (*bufP) & 0x0f;
604  
605                         c = '1';
606                         for(k=0; k<nclut; k++)
607                                 if(buf == notblack[k])
608                                         c = '0'; /* not black */
609                         *(imgP + i*img.w + j) = c;
610                 }
611         }
612         return;
613 }