GNU Unifont 15.0.02
Pan-Unicode font with complete Unicode Plane 0 coverage and partial coverage of higher planes
unihex2bmp.c File Reference

unihex2bmp - Turn a GNU Unifont hex glyph page of 256 code points into a bitmap for editing More...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Include dependency graph for unihex2bmp.c:

Go to the source code of this file.

Macros

#define MAXBUF   256
 

Functions

int main (int argc, char *argv[])
 The main function. More...
 
int hex2bit (char *instring, unsigned char character[32][4])
 Generate a bitmap for one glyph. More...
 
int init (unsigned char bitmap[17 *32][18 *4])
 Initialize the bitmap grid. More...
 

Variables

char * hex [18]
 GNU Unifont bitmaps for hexadecimal digits. More...
 
unsigned char hexbits [18][32]
 The digits converted into bitmaps. More...
 
unsigned unipage =0
 Unicode page number, 0x00..0xff. More...
 
int flip =1
 Transpose entire matrix as in Unicode book. More...
 

Detailed Description

unihex2bmp - Turn a GNU Unifont hex glyph page of 256 code points into a bitmap for editing

Author
Paul Hardy, unifoundry <at> unifoundry.com, December 2007

This program reads in a GNU Unifont .hex file, extracts a range of 256 code points, and converts it a Microsoft Bitmap (.bmp) or Wireless Bitmap file.

Synopsis: unihex2bmp [-iin_file.hex] [-oout_file.bmp] [-f] [-phex_page_num] [-w]

Definition in file unihex2bmp.c.

Macro Definition Documentation

◆ MAXBUF

#define MAXBUF   256

Definition at line 47 of file unihex2bmp.c.

Function Documentation

◆ hex2bit()

int hex2bit ( char *  instring,
unsigned char  character[32][4] 
)

Generate a bitmap for one glyph.

Convert the portion of a hex string after the ':' into a character bitmap.

If string is >= 128 characters, it will fill all 4 bytes per row. If string is >= 64 characters and < 128, it will fill 2 bytes per row. Otherwise, it will fill 1 byte per row.

Parameters
[in]instringThe character array containing the glyph bitmap.
[out]characterGlyph bitmap, 8, 16, or 32 columns by 16 rows tall.
Returns
Always returns 0.

Definition at line 361 of file unihex2bmp.c.

362{
363
364 int i; /* current row in bitmap character */
365 int j; /* current character in input string */
366 int k; /* current byte in bitmap character */
367 int width; /* number of output bytes to fill - 1: 0, 1, 2, or 3 */
368
369 for (i=0; i<32; i++) /* erase previous character */
370 character[i][0] = character[i][1] = character[i][2] = character[i][3] = 0;
371 j=0; /* current location is at beginning of instring */
372
373 if (strlen (instring) <= 34) /* 32 + possible '\r', '\n' */
374 width = 0;
375 else if (strlen (instring) <= 66) /* 64 + possible '\r', '\n' */
376 width = 1;
377 else if (strlen (instring) <= 98) /* 96 + possible '\r', '\n' */
378 width = 3;
379 else /* the maximum allowed is quadruple-width */
380 width = 4;
381
382 k = (width > 1) ? 0 : 1; /* if width > double, start at index 1 else at 0 */
383
384 for (i=8; i<24; i++) { /* 16 rows per input character, rows 8..23 */
385 sscanf (&instring[j], "%2hhx", &character[i][k]);
386 j += 2;
387 if (width > 0) { /* add next pair of hex digits to this row */
388 sscanf (&instring[j], "%2hhx", &character[i][k+1]);
389 j += 2;
390 if (width > 1) { /* add next pair of hex digits to this row */
391 sscanf (&instring[j], "%2hhx", &character[i][k+2]);
392 j += 2;
393 if (width > 2) { /* quadruple-width is maximum width */
394 sscanf (&instring[j], "%2hhx", &character[i][k+3]);
395 j += 2;
396 }
397 }
398 }
399 }
400
401 return (0);
402}
Here is the caller graph for this function:

◆ init()

int init ( unsigned char  bitmap[17 *32][18 *4])

Initialize the bitmap grid.

Parameters
[out]bitmapThe bitmap to generate, with 32x32 pixel glyph areas.
Returns
Always returns 0.

Definition at line 412 of file unihex2bmp.c.

413{
414 int i, j;
415 unsigned char charbits[32][4]; /* bitmap for one character, 4 bytes/row */
416 unsigned toppixelrow;
417 unsigned thiscol;
418 unsigned char pnybble0, pnybble1, pnybble2, pnybble3;
419
420 for (i=0; i<18; i++) { /* bitmaps for '0'..'9', 'A'-'F', 'u', '+' */
421
422 hex2bit (&hex[i][5], charbits); /* convert hex string to 32*4 bitmap */
423
424 for (j=0; j<32; j++) hexbits[i][j] = ~charbits[j][1];
425 }
426
427 /*
428 Initialize bitmap to all white.
429 */
430 for (toppixelrow=0; toppixelrow < 17*32; toppixelrow++) {
431 for (thiscol=0; thiscol<18; thiscol++) {
432 bitmap[toppixelrow][(thiscol << 2) ] = 0xff;
433 bitmap[toppixelrow][(thiscol << 2) | 1] = 0xff;
434 bitmap[toppixelrow][(thiscol << 2) | 2] = 0xff;
435 bitmap[toppixelrow][(thiscol << 2) | 3] = 0xff;
436 }
437 }
438 /*
439 Write the "u+nnnn" table header in the upper left-hand corner,
440 where nnnn is the upper 16 bits of a 32-bit Unicode assignment.
441 */
442 pnybble3 = (unipage >> 20);
443 pnybble2 = (unipage >> 16) & 0xf;
444 pnybble1 = (unipage >> 12) & 0xf;
445 pnybble0 = (unipage >> 8) & 0xf;
446 for (i=0; i<32; i++) {
447 bitmap[i][1] = hexbits[16][i]; /* copy 'u' */
448 bitmap[i][2] = hexbits[17][i]; /* copy '+' */
449 bitmap[i][3] = hexbits[pnybble3][i];
450 bitmap[i][4] = hexbits[pnybble2][i];
451 bitmap[i][5] = hexbits[pnybble1][i];
452 bitmap[i][6] = hexbits[pnybble0][i];
453 }
454 /*
455 Write low-order 2 bytes of Unicode number assignments, as hex labels
456 */
457 pnybble3 = (unipage >> 4) & 0xf; /* Highest-order hex digit */
458 pnybble2 = (unipage ) & 0xf; /* Next highest-order hex digit */
459 /*
460 Write the column headers in bitmap[][] (row headers if flipped)
461 */
462 toppixelrow = 32 * 17 - 1; /* maximum pixel row number */
463 /*
464 Label the column headers. The hexbits[][] bytes are split across two
465 bitmap[][] entries to center a the hex digits in a column of 4 bytes.
466 OR highest byte with 0xf0 and lowest byte with 0x0f to make outer
467 nybbles white (0=black, 1-white).
468 */
469 for (i=0; i<16; i++) {
470 for (j=0; j<32; j++) {
471 if (flip) { /* transpose matrix */
472 bitmap[j][((i+2) << 2) | 0] = (hexbits[pnybble3][j] >> 4) | 0xf0;
473 bitmap[j][((i+2) << 2) | 1] = (hexbits[pnybble3][j] << 4) |
474 (hexbits[pnybble2][j] >> 4);
475 bitmap[j][((i+2) << 2) | 2] = (hexbits[pnybble2][j] << 4) |
476 (hexbits[i][j] >> 4);
477 bitmap[j][((i+2) << 2) | 3] = (hexbits[i][j] << 4) | 0x0f;
478 }
479 else {
480 bitmap[j][((i+2) << 2) | 1] = (hexbits[i][j] >> 4) | 0xf0;
481 bitmap[j][((i+2) << 2) | 2] = (hexbits[i][j] << 4) | 0x0f;
482 }
483 }
484 }
485 /*
486 Now use the single hex digit column graphics to label the row headers.
487 */
488 for (i=0; i<16; i++) {
489 toppixelrow = 32 * (i + 1) - 1; /* from bottom to top */
490
491 for (j=0; j<32; j++) {
492 if (!flip) { /* if not transposing matrix */
493 bitmap[toppixelrow + j][4] = hexbits[pnybble3][j];
494 bitmap[toppixelrow + j][5] = hexbits[pnybble2][j];
495 }
496 bitmap[toppixelrow + j][6] = hexbits[i][j];
497 }
498 }
499 /*
500 Now draw grid lines in bitmap, around characters we just copied.
501 */
502 /* draw vertical lines 2 pixels wide */
503 for (i=1*32; i<17*32; i++) {
504 if ((i & 0x1f) == 7)
505 i++;
506 else if ((i & 0x1f) == 14)
507 i += 2;
508 else if ((i & 0x1f) == 22)
509 i++;
510 for (j=1; j<18; j++) {
511 bitmap[i][(j << 2) | 3] &= 0xfe;
512 }
513 }
514 /* draw horizontal lines 1 pixel tall */
515 for (i=1*32-1; i<18*32-1; i+=32) {
516 for (j=2; j<18; j++) {
517 bitmap[i][(j << 2) ] = 0x00;
518 bitmap[i][(j << 2) | 1] = 0x81;
519 bitmap[i][(j << 2) | 2] = 0x81;
520 bitmap[i][(j << 2) | 3] = 0x00;
521 }
522 }
523 /* fill in top left corner pixel of grid */
524 bitmap[31][7] = 0xfe;
525
526 return (0);
527}
int hex2bit(char *instring, unsigned char character[32][4])
Generate a bitmap for one glyph.
Definition: unihex2bmp.c:361
unsigned unipage
Unicode page number, 0x00..0xff.
Definition: unihex2bmp.c:84
int flip
Transpose entire matrix as in Unicode book.
Definition: unihex2bmp.c:85
unsigned char hexbits[18][32]
The digits converted into bitmaps.
Definition: unihex2bmp.c:82
char * hex[18]
GNU Unifont bitmaps for hexadecimal digits.
Definition: unihex2bmp.c:62
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *  argv[] 
)

The main function.

Parameters
[in]argcThe count of command line arguments.
[in]argvPointer to array of command line arguments.
Returns
This program exits with status 0.

Definition at line 96 of file unihex2bmp.c.

97{
98
99 int i, j; /* loop variables */
100 unsigned k0; /* temp Unicode char variable */
101 unsigned swap; /* temp variable for swapping values */
102 char inbuf[256]; /* input buffer */
103 unsigned filesize; /* size of file in bytes */
104 unsigned bitmapsize; /* size of bitmap image in bytes */
105 unsigned thischar; /* the current character */
106 unsigned char thischarbyte; /* unsigned char lowest byte of Unicode char */
107 int thischarrow; /* row 0..15 where this character belongs */
108 int thiscol; /* column 0..15 where this character belongs */
109 int toppixelrow; /* pixel row, 0..16*32-1 */
110 unsigned lastpage=0; /* the last Unicode page read in font file */
111 int wbmp=0; /* set to 1 if writing .wbmp format file */
112
113 unsigned char bitmap[17*32][18*4]; /* final bitmap */
114 unsigned char charbits[32][4]; /* bitmap for one character, 4 bytes/row */
115
116 char *infile="", *outfile=""; /* names of input and output files */
117 FILE *infp, *outfp; /* file pointers of input and output files */
118
119 int init(); /* initializes bitmap row/col labeling, &c. */
120 int hex2bit(); /* convert hex string --> bitmap */
121
122 bitmapsize = 17*32*18*4; /* 17 rows by 18 cols, each 4 bytes */
123
124 if (argc > 1) {
125 for (i = 1; i < argc; i++) {
126 if (argv[i][0] == '-') { /* this is an option argument */
127 switch (argv[i][1]) {
128 case 'f': /* flip (transpose) glyphs in bitmap as in standard */
129 flip = !flip;
130 break;
131 case 'i': /* name of input file */
132 infile = &argv[i][2];
133 break;
134 case 'o': /* name of output file */
135 outfile = &argv[i][2];
136 break;
137 case 'p': /* specify a Unicode page other than default of 0 */
138 sscanf (&argv[i][2], "%x", &unipage); /* Get Unicode page */
139 break;
140 case 'w': /* write a .wbmp file instead of a .bmp file */
141 wbmp = 1;
142 break;
143 default: /* if unrecognized option, print list and exit */
144 fprintf (stderr, "\nSyntax:\n\n");
145 fprintf (stderr, " %s -p<Unicode_Page> ", argv[0]);
146 fprintf (stderr, "-i<Input_File> -o<Output_File> -w\n\n");
147 fprintf (stderr, " -w specifies .wbmp output instead of ");
148 fprintf (stderr, "default Windows .bmp output.\n\n");
149 fprintf (stderr, " -p is followed by 1 to 6 ");
150 fprintf (stderr, "Unicode page hex digits ");
151 fprintf (stderr, "(default is Page 0).\n\n");
152 fprintf (stderr, "\nExample:\n\n");
153 fprintf (stderr, " %s -p83 -iunifont.hex -ou83.bmp\n\n\n",
154 argv[0]);
155 exit (1);
156 }
157 }
158 }
159 }
160 /*
161 Make sure we can open any I/O files that were specified before
162 doing anything else.
163 */
164 if (strlen (infile) > 0) {
165 if ((infp = fopen (infile, "r")) == NULL) {
166 fprintf (stderr, "Error: can't open %s for input.\n", infile);
167 exit (1);
168 }
169 }
170 else {
171 infp = stdin;
172 }
173 if (strlen (outfile) > 0) {
174 if ((outfp = fopen (outfile, "w")) == NULL) {
175 fprintf (stderr, "Error: can't open %s for output.\n", outfile);
176 exit (1);
177 }
178 }
179 else {
180 outfp = stdout;
181 }
182
183 (void)init(bitmap); /* initialize bitmap with row/column headers, etc. */
184
185 /*
186 Read in the characters in the page
187 */
188 while (lastpage <= unipage && fgets (inbuf, MAXBUF-1, infp) != NULL) {
189 sscanf (inbuf, "%x", &thischar);
190 lastpage = thischar >> 8; /* keep Unicode page to see if we can stop */
191 if (lastpage == unipage) {
192 thischarbyte = (unsigned char)(thischar & 0xff);
193 for (k0=0; inbuf[k0] != ':'; k0++);
194 k0++;
195 hex2bit (&inbuf[k0], charbits); /* convert hex string to 32*4 bitmap */
196
197 /*
198 Now write character bitmap upside-down in page array, to match
199 .bmp file order. In the .wbmp` and .bmp files, white is a '1'
200 bit and black is a '0' bit, so complement charbits[][].
201 */
202
203 thiscol = (thischarbyte & 0xf) + 2; /* column number will be 1..16 */
204 thischarrow = thischarbyte >> 4; /* charcter row number, 0..15 */
205 if (flip) { /* swap row and column placement */
206 swap = thiscol;
207 thiscol = thischarrow;
208 thischarrow = swap;
209 thiscol += 2; /* column index starts at 1 */
210 thischarrow -= 2; /* row index starts at 0 */
211 }
212 toppixelrow = 32 * (thischarrow + 1) - 1; /* from bottom to top */
213
214 /*
215 Copy the center of charbits[][] because hex characters only
216 occupy rows 8 to 23 and column byte 2 (and for 16 bit wide
217 characters, byte 3). The charbits[][] array was given 32 rows
218 and 4 column bytes for completeness in the beginning.
219 */
220 for (i=8; i<24; i++) {
221 bitmap[toppixelrow + i][(thiscol << 2) | 0] =
222 ~charbits[i][0] & 0xff;
223 bitmap[toppixelrow + i][(thiscol << 2) | 1] =
224 ~charbits[i][1] & 0xff;
225 bitmap[toppixelrow + i][(thiscol << 2) | 2] =
226 ~charbits[i][2] & 0xff;
227 /* Only use first 31 bits; leave vertical rule in 32nd column */
228 bitmap[toppixelrow + i][(thiscol << 2) | 3] =
229 ~charbits[i][3] & 0xfe;
230 }
231 /*
232 Leave white space in 32nd column of rows 8, 14, 15, and 23
233 to leave 16 pixel height upper, middle, and lower guides.
234 */
235 bitmap[toppixelrow + 8][(thiscol << 2) | 3] |= 1;
236 bitmap[toppixelrow + 14][(thiscol << 2) | 3] |= 1;
237 bitmap[toppixelrow + 15][(thiscol << 2) | 3] |= 1;
238 bitmap[toppixelrow + 23][(thiscol << 2) | 3] |= 1;
239 }
240 }
241 /*
242 Now write the appropriate bitmap file format, either
243 Wireless Bitmap or Microsoft Windows bitmap.
244 */
245 if (wbmp) { /* Write a Wireless Bitmap .wbmp format file */
246 /*
247 Write WBMP header
248 */
249 fprintf (outfp, "%c", 0x00); /* Type of image; always 0 (monochrome) */
250 fprintf (outfp, "%c", 0x00); /* Reserved; always 0 */
251 fprintf (outfp, "%c%c", 0x84, 0x40); /* Width = 576 pixels */
252 fprintf (outfp, "%c%c", 0x84, 0x20); /* Height = 544 pixels */
253 /*
254 Write bitmap image
255 */
256 for (toppixelrow=0; toppixelrow <= 17*32-1; toppixelrow++) {
257 for (j=0; j<18; j++) {
258 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) ]);
259 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) | 1]);
260 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) | 2]);
261 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) | 3]);
262 }
263 }
264 }
265 else { /* otherwise, write a Microsoft Windows .bmp format file */
266 /*
267 Write the .bmp file -- start with the header, then write the bitmap
268 */
269
270 /* 'B', 'M' appears at start of every .bmp file */
271 fprintf (outfp, "%c%c", 0x42, 0x4d);
272
273 /* Write file size in bytes */
274 filesize = 0x3E + bitmapsize;
275 fprintf (outfp, "%c", (unsigned char)((filesize ) & 0xff));
276 fprintf (outfp, "%c", (unsigned char)((filesize >> 0x08) & 0xff));
277 fprintf (outfp, "%c", (unsigned char)((filesize >> 0x10) & 0xff));
278 fprintf (outfp, "%c", (unsigned char)((filesize >> 0x18) & 0xff));
279
280 /* Reserved - 0's */
281 fprintf (outfp, "%c%c%c%c", 0x00, 0x00, 0x00, 0x00);
282
283 /* Offset from start of file to bitmap data */
284 fprintf (outfp, "%c%c%c%c", 0x3E, 0x00, 0x00, 0x00);
285
286 /* Length of bitmap info header */
287 fprintf (outfp, "%c%c%c%c", 0x28, 0x00, 0x00, 0x00);
288
289 /* Width of bitmap in pixels */
290 fprintf (outfp, "%c%c%c%c", 0x40, 0x02, 0x00, 0x00);
291
292 /* Height of bitmap in pixels */
293 fprintf (outfp, "%c%c%c%c", 0x20, 0x02, 0x00, 0x00);
294
295 /* Planes in bitmap (fixed at 1) */
296 fprintf (outfp, "%c%c", 0x01, 0x00);
297
298 /* bits per pixel (1 = monochrome) */
299 fprintf (outfp, "%c%c", 0x01, 0x00);
300
301 /* Compression (0 = none) */
302 fprintf (outfp, "%c%c%c%c", 0x00, 0x00, 0x00, 0x00);
303
304 /* Size of bitmap data in bytes */
305 fprintf (outfp, "%c", (unsigned char)((bitmapsize ) & 0xff));
306 fprintf (outfp, "%c", (unsigned char)((bitmapsize >> 0x08) & 0xff));
307 fprintf (outfp, "%c", (unsigned char)((bitmapsize >> 0x10) & 0xff));
308 fprintf (outfp, "%c", (unsigned char)((bitmapsize >> 0x18) & 0xff));
309
310 /* Horizontal resolution in pixels per meter */
311 fprintf (outfp, "%c%c%c%c", 0xC4, 0x0E, 0x00, 0x00);
312
313 /* Vertical resolution in pixels per meter */
314 fprintf (outfp, "%c%c%c%c", 0xC4, 0x0E, 0x00, 0x00);
315
316 /* Number of colors used */
317 fprintf (outfp, "%c%c%c%c", 0x02, 0x00, 0x00, 0x00);
318
319 /* Number of important colors */
320 fprintf (outfp, "%c%c%c%c", 0x02, 0x00, 0x00, 0x00);
321
322 /* The color black: B=0x00, G=0x00, R=0x00, Filler=0xFF */
323 fprintf (outfp, "%c%c%c%c", 0x00, 0x00, 0x00, 0x00);
324
325 /* The color white: B=0xFF, G=0xFF, R=0xFF, Filler=0xFF */
326 fprintf (outfp, "%c%c%c%c", 0xFF, 0xFF, 0xFF, 0x00);
327
328 /*
329 Now write the raw data bits. Data is written from the lower
330 left-hand corner of the image to the upper right-hand corner
331 of the image.
332 */
333 for (toppixelrow=17*32-1; toppixelrow >= 0; toppixelrow--) {
334 for (j=0; j<18; j++) {
335 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) ]);
336 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) | 1]);
337 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) | 2]);
338
339 fprintf (outfp, "%c", bitmap[toppixelrow][(j<<2) | 3]);
340 }
341 }
342 }
343 exit (0);
344}
int init(unsigned char bitmap[17 *32][18 *4])
Initialize the bitmap grid.
Definition: unihex2bmp.c:412
Here is the call graph for this function:

Variable Documentation

◆ flip

int flip =1

Transpose entire matrix as in Unicode book.

Definition at line 85 of file unihex2bmp.c.

◆ hex

char* hex[18]
Initial value:
= {
"0030:00000000182442424242424224180000",
"0031:000000000818280808080808083E0000",
"0032:000000003C4242020C102040407E0000",
"0033:000000003C4242021C020242423C0000",
"0034:00000000040C142444447E0404040000",
"0035:000000007E4040407C020202423C0000",
"0036:000000001C2040407C424242423C0000",
"0037:000000007E0202040404080808080000",
"0038:000000003C4242423C424242423C0000",
"0039:000000003C4242423E02020204380000",
"0041:0000000018242442427E424242420000",
"0042:000000007C4242427C424242427C0000",
"0043:000000003C42424040404042423C0000",
"0044:00000000784442424242424244780000",
"0045:000000007E4040407C404040407E0000",
"0046:000000007E4040407C40404040400000",
"0055:000000004242424242424242423C0000",
"002B:0000000000000808087F080808000000"
}

GNU Unifont bitmaps for hexadecimal digits.

These are the GNU Unifont hex strings for '0'-'9' and 'A'-'F', for encoding as bit strings in row and column headers.

Looking at the final bitmap as a grid of 32*32 bit tiles, the first row contains a hexadecimal character string of the first 3 hex digits in a 4 digit Unicode character name; the top column contains a hex character string of the 4th (low-order) hex digit of the Unicode character.

Definition at line 62 of file unihex2bmp.c.

◆ hexbits

unsigned char hexbits[18][32]

The digits converted into bitmaps.

Definition at line 82 of file unihex2bmp.c.

◆ unipage

unsigned unipage =0

Unicode page number, 0x00..0xff.

Definition at line 84 of file unihex2bmp.c.