unibmp2hex.c File Reference

unibmp2hex - Turn a .bmp or .wbmp glyph matrix into a GNU Unifont hex glyph set of 256 characters More...

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

Go to the source code of this file.

## Macros

#define | MAXBUF 256
| Maximum input file line length - 1. More...

## Functions

int | main (int argc, char *argv[])
| The main function. More...

## Variables

unsigned | hexdigit [16][4]
| 32 bit representation of 16x8 0..F bitmap More...
unsigned | uniplane =0
| Unicode plane number, 0..0xff ff ff. More...
unsigned | planeset =0
| =1: use plane specified with -p parameter More...
unsigned | flip =0
| =1 if we're transposing glyph matrix More...
unsigned | forcewide =0
| =1 to set each glyph to 16 pixels wide More...
unsigned | unidigit [6][4]
struct {
char filetype [2]
int file_size
int image_offset
int info_size
int width
int height
int nplanes
int bits_per_pixel
int compression
int image_size
int x_ppm
int y_ppm
int ncolors
int important_colors
} | bmp_header
unsigned char | color_table [256][4]

## Detailed Description

unibmp2hex - Turn a .bmp or .wbmp glyph matrix into a GNU Unifont hex glyph set of 256 characters

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

Copyright
  Copyright (C) 2007, 2008, 2013, 2017, 2019, 2022 Paul Hardy

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

Definition in file unibmp2hex.c.

## Macro Definition Documentation

## MAXBUF

#define MAXBUF 256

Maximum input file line length - 1.

Definition at line 116 of file unibmp2hex.c.

## Function Documentation

## main()

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

The main function.

Parameters

  [in] | argc | The count of command line arguments.
  [in] | argv | Pointer to array of command line arguments.

Returns
  This program exits with status 0.

Definition at line 161 of file unibmp2hex.c.

{
int i, j, k; /* loop variables */
unsigned char inchar; /* temporary input character */
char header[MAXBUF]; /* input buffer for bitmap file header */
int wbmp=0; /* =0 for Windows Bitmap (.bmp); 1 for Wireless Bitmap (.wbmp) */
int fatal; /* =1 if a fatal error occurred */
int match; /* =1 if we're still matching a pattern, 0 if no match */
int empty1, empty2; /* =1 if bytes tested are all zeroes */
unsigned char thischar1[16], thischar2[16]; /* bytes of hex char */
unsigned char thischar0[16], thischar3[16]; /* bytes for quadruple-width */
int thisrow; /* index to point into thischar1[] and thischar2[] */
int tmpsum; /* temporary sum to see if a character is blank */
unsigned this_pixel; /* color of one pixel, if > 1 bit per pixel */
unsigned next_pixels; /* pending group of 8 pixels being read */
unsigned color_mask = 0x00; /* to invert monochrome bitmap, set to 0xFF */
unsigned char bitmap[17*32][18*32/8]; /* final bitmap */
/* For wide array:
0 = don't force glyph to double-width;
1 = force glyph to double-width;
4 = force glyph to quadruple-width.
*/
char wide[0x200000]={0x200000 * 0};
char *infile="", *outfile=""; /* names of input and output files */
FILE *infp, *outfp; /* file pointers of input and output files */
if (argc > 1) {
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') { /* this is an option argument */
switch (argv[i][1]) {
case 'i': /* name of input file */
infile = &argv[i][2];
break;
case 'o': /* name of output file */
outfile = &argv[i][2];
break;
case 'p': /* specify a Unicode plane */
sscanf (&argv[i][2], "%x", &uniplane); /* Get Unicode plane */
planeset = 1; /* Use specified range, not what's in bitmap */
break;
case 'w': /* force wide (16 pixels) for each glyph */
forcewide = 1;
break;
default: /* if unrecognized option, print list and exit */
fprintf (stderr, "\nSyntax:\n\n");
fprintf (stderr, " %s -p<Unicode_Page> ", argv[0]);
fprintf (stderr, "-i<Input_File> -o<Output_File> -w\n\n");
fprintf (stderr, " -w specifies .wbmp output instead of ");
fprintf (stderr, "default Windows .bmp output.\n\n");
fprintf (stderr, " -p is followed by 1 to 6 ");
fprintf (stderr, "Unicode plane hex digits ");
fprintf (stderr, "(default is Page 0).\n\n");
fprintf (stderr, "\nExample:\n\n");
fprintf (stderr, " %s -p83 -iunifont.hex -ou83.bmp\n\n\n",
argv[0]);
exit (1);
}
}
}
}
/*
Make sure we can open any I/O files that were specified before
doing anything else.
*/
if (strlen (infile) > 0) {
if ((infp = fopen (infile, "r")) == NULL) {
fprintf (stderr, "Error: can't open %s for input.\n", infile);
exit (1);
}
}
else {
infp = stdin;
}
if (strlen (outfile) > 0) {
if ((outfp = fopen (outfile, "w")) == NULL) {
fprintf (stderr, "Error: can't open %s for output.\n", outfile);
exit (1);
}
}
else {
outfp = stdout;
}
/*
Initialize selected code points for double width (16x16).
Double-width is forced in cases where a glyph (usually a combining
glyph) only occupies the left-hand side of a 16x16 grid, but must
be rendered as double-width to appear properly with other glyphs
in a given script. If additions were made to a script after
Unicode 5.0, the Unicode version is given in parentheses after
the script name.
*/
for (i = 0x0700; i <= 0x074F; i++) wide[i] = 1; /* Syriac */
for (i = 0x0800; i <= 0x083F; i++) wide[i] = 1; /* Samaritan (5.2) */
for (i = 0x0900; i <= 0x0DFF; i++) wide[i] = 1; /* Indic */
for (i = 0x1000; i <= 0x109F; i++) wide[i] = 1; /* Myanmar */
for (i = 0x1100; i <= 0x11FF; i++) wide[i] = 1; /* Hangul Jamo */
for (i = 0x1400; i <= 0x167F; i++) wide[i] = 1; /* Canadian Aboriginal */
for (i = 0x1700; i <= 0x171F; i++) wide[i] = 1; /* Tagalog */
for (i = 0x1720; i <= 0x173F; i++) wide[i] = 1; /* Hanunoo */
for (i = 0x1740; i <= 0x175F; i++) wide[i] = 1; /* Buhid */
for (i = 0x1760; i <= 0x177F; i++) wide[i] = 1; /* Tagbanwa */
for (i = 0x1780; i <= 0x17FF; i++) wide[i] = 1; /* Khmer */
for (i = 0x18B0; i <= 0x18FF; i++) wide[i] = 1; /* Ext. Can. Aboriginal */
for (i = 0x1800; i <= 0x18AF; i++) wide[i] = 1; /* Mongolian */
for (i = 0x1900; i <= 0x194F; i++) wide[i] = 1; /* Limbu */
// for (i = 0x1980; i <= 0x19DF; i++) wide[i] = 1; /* New Tai Lue */
for (i = 0x1A00; i <= 0x1A1F; i++) wide[i] = 1; /* Buginese */
for (i = 0x1A20; i <= 0x1AAF; i++) wide[i] = 1; /* Tai Tham (5.2) */
for (i = 0x1B00; i <= 0x1B7F; i++) wide[i] = 1; /* Balinese */
for (i = 0x1B80; i <= 0x1BBF; i++) wide[i] = 1; /* Sundanese (5.1) */
for (i = 0x1BC0; i <= 0x1BFF; i++) wide[i] = 1; /* Batak (6.0) */
for (i = 0x1C00; i <= 0x1C4F; i++) wide[i] = 1; /* Lepcha (5.1) */
for (i = 0x1CC0; i <= 0x1CCF; i++) wide[i] = 1; /* Sundanese Supplement */
for (i = 0x1CD0; i <= 0x1CFF; i++) wide[i] = 1; /* Vedic Extensions (5.2) */
wide[0x2329] = wide[0x232A] = 1; /* Left- & Right-pointing Angle Brackets */
for (i = 0x2E80; i <= 0xA4CF; i++) wide[i] = 1; /* CJK */
// for (i = 0x9FD8; i <= 0x9FE9; i++) wide[i] = 4; /* CJK quadruple-width */
for (i = 0xA900; i <= 0xA92F; i++) wide[i] = 1; /* Kayah Li (5.1) */
for (i = 0xA930; i <= 0xA95F; i++) wide[i] = 1; /* Rejang (5.1) */
for (i = 0xA960; i <= 0xA97F; i++) wide[i] = 1; /* Hangul Jamo Extended-A */
for (i = 0xA980; i <= 0xA9DF; i++) wide[i] = 1; /* Javanese (5.2) */
for (i = 0xAA00; i <= 0xAA5F; i++) wide[i] = 1; /* Cham (5.1) */
for (i = 0xA9E0; i <= 0xA9FF; i++) wide[i] = 1; /* Myanmar Extended-B */
for (i = 0xAA00; i <= 0xAA5F; i++) wide[i] = 1; /* Cham */
for (i = 0xAA60; i <= 0xAA7F; i++) wide[i] = 1; /* Myanmar Extended-A */
for (i = 0xAAE0; i <= 0xAAFF; i++) wide[i] = 1; /* Meetei Mayek Ext (6.0) */
for (i = 0xABC0; i <= 0xABFF; i++) wide[i] = 1; /* Meetei Mayek (5.2) */
for (i = 0xAC00; i <= 0xD7AF; i++) wide[i] = 1; /* Hangul Syllables */
for (i = 0xD7B0; i <= 0xD7FF; i++) wide[i] = 1; /* Hangul Jamo Extended-B */
for (i = 0xF900; i <= 0xFAFF; i++) wide[i] = 1; /* CJK Compatibility */
for (i = 0xFE10; i <= 0xFE1F; i++) wide[i] = 1; /* Vertical Forms */
for (i = 0xFE30; i <= 0xFE60; i++) wide[i] = 1; /* CJK Compatibility Forms*/
for (i = 0xFFE0; i <= 0xFFE6; i++) wide[i] = 1; /* CJK Compatibility Forms*/
wide[0x303F] = 0; /* CJK half-space fill */
/* Supplemental Multilingual Plane (Plane 01) */
for (i = 0x0105C0; i <= 0x0105FF; i++) wide[i] = 1; /* Todhri */
for (i = 0x010A00; i <= 0x010A5F; i++) wide[i] = 1; /* Kharoshthi */
for (i = 0x011000; i <= 0x01107F; i++) wide[i] = 1; /* Brahmi */
for (i = 0x011080; i <= 0x0110CF; i++) wide[i] = 1; /* Kaithi */
for (i = 0x011100; i <= 0x01114F; i++) wide[i] = 1; /* Chakma */
for (i = 0x011180; i <= 0x0111DF; i++) wide[i] = 1; /* Sharada */
for (i = 0x011200; i <= 0x01124F; i++) wide[i] = 1; /* Khojki */
for (i = 0x0112B0; i <= 0x0112FF; i++) wide[i] = 1; /* Khudawadi */
for (i = 0x011300; i <= 0x01137F; i++) wide[i] = 1; /* Grantha */
for (i = 0x011380; i <= 0x0113FF; i++) wide[i] = 1; /* Tulu-Tigalari */
for (i = 0x011400; i <= 0x01147F; i++) wide[i] = 1; /* Newa */
for (i = 0x011480; i <= 0x0114DF; i++) wide[i] = 1; /* Tirhuta */
for (i = 0x011580; i <= 0x0115FF; i++) wide[i] = 1; /* Siddham */
for (i = 0x011600; i <= 0x01165F; i++) wide[i] = 1; /* Modi */
for (i = 0x011660; i <= 0x01167F; i++) wide[i] = 1; /* Mongolian Suppl. */
for (i = 0x011680; i <= 0x0116CF; i++) wide[i] = 1; /* Takri */
for (i = 0x0116D0; i <= 0x0116FF; i++) wide[i] = 1; /* Myanmar Extended-C */
for (i = 0x011700; i <= 0x01173F; i++) wide[i] = 1; /* Ahom */
for (i = 0x011800; i <= 0x01184F; i++) wide[i] = 1; /* Dogra */
for (i = 0x011900; i <= 0x01195F; i++) wide[i] = 1; /* Dives Akuru */
for (i = 0x0119A0; i <= 0x0119FF; i++) wide[i] = 1; /* Nandinagari */
for (i = 0x011A00; i <= 0x011A4F; i++) wide[i] = 1; /* Zanabazar Square */
for (i = 0x011A50; i <= 0x011AAF; i++) wide[i] = 1; /* Soyombo */
for (i = 0x011B00; i <= 0x011B5F; i++) wide[i] = 1;/*Devanagari Extended-A*/
for (i = 0x011F00; i <= 0x011F5F; i++) wide[i] = 1; /* Kawi */
for (i = 0x011C00; i <= 0x011C6F; i++) wide[i] = 1; /* Bhaiksuki */
for (i = 0x011C70; i <= 0x011CBF; i++) wide[i] = 1; /* Marchen */
for (i = 0x011D00; i <= 0x011D5F; i++) wide[i] = 1; /* Masaram Gondi */
for (i = 0x011EE0; i <= 0x011EFF; i++) wide[i] = 1; /* Makasar */
for (i = 0x011F00; i <= 0x011F5F; i++) wide[i] = 1; /* Kawi */
for (i = 0x012F90; i <= 0x012FFF; i++) wide[i] = 1; /* Cypro-Minoan */
/* Make Bassa Vah all single width or all double width */
for (i = 0x016100; i <= 0x01613F; i++) wide[i] = 1; /* Gurung Khema */
for (i = 0x016AD0; i <= 0x016AFF; i++) wide[i] = 1; /* Bassa Vah */
for (i = 0x016B00; i <= 0x016B8F; i++) wide[i] = 1; /* Pahawh Hmong */
for (i = 0x016D40; i <= 0x016D7F; i++) wide[i] = 1; /* Kirat Rai */
for (i = 0x016F00; i <= 0x016F9F; i++) wide[i] = 1; /* Miao */
for (i = 0x016FE0; i <= 0x016FFF; i++) wide[i] = 1; /* Ideograph Sym/Punct*/
for (i = 0x017000; i <= 0x0187FF; i++) wide[i] = 1; /* Tangut */
for (i = 0x018800; i <= 0x018AFF; i++) wide[i] = 1; /* Tangut Components */
for (i = 0x018B00; i <= 0x018CFF; i++) wide[i] = 1; /* Khitan Small Script*/
for (i = 0x01AFF0; i <= 0x01AFFF; i++) wide[i] = 1; /* Kana Extended-B */
for (i = 0x01B000; i <= 0x01B0FF; i++) wide[i] = 1; /* Kana Supplement */
for (i = 0x01B100; i <= 0x01B12F; i++) wide[i] = 1; /* Kana Extended-A */
for (i = 0x01B170; i <= 0x01B2FF; i++) wide[i] = 1; /* Nushu */
for (i = 0x01CF00; i <= 0x01CFCF; i++) wide[i] = 1; /* Znamenny Musical */
for (i = 0x01D800; i <= 0x01DAAF; i++) wide[i] = 1; /* Sutton SignWriting */
for (i = 0x01E2C0; i <= 0x01E2FF; i++) wide[i] = 1; /* Wancho */
for (i = 0x01E500; i <= 0x01E5FF; i++) wide[i] = 1; /* Ol Onal */
for (i = 0x01E800; i <= 0x01E8DF; i++) wide[i] = 1; /* Mende Kikakui */
for (i = 0x01F200; i <= 0x01F2FF; i++) wide[i] = 1; /* Encl Ideograp Suppl*/
wide[0x01F5E7] = 1; /* Three Rays Right */
/*
Determine whether or not the file is a Microsoft Windows Bitmap file.
If it starts with 'B', 'M', assume it's a Windows Bitmap file.
Otherwise, assume it's a Wireless Bitmap file.
WARNING: There isn't much in the way of error checking here --
if you give it a file that wasn't first created by hex2bmp.c,
all bets are off.
*/
fatal = 0; /* assume everything is okay with reading input file */
if ((header[0] = fgetc (infp)) != EOF) {
if ((header[1] = fgetc (infp)) != EOF) {
if (header[0] == 'B' && header[1] == 'M') {
wbmp = 0; /* Not a Wireless Bitmap -- it's a Windows Bitmap */
}
else {
wbmp = 1; /* Assume it's a Wireless Bitmap */
}
}
else
fatal = 1;
}
else
fatal = 1;
if (fatal) {
fprintf (stderr, "Fatal error; end of input file.\n\n");
exit (1);
}
/*
If this is a Wireless Bitmap (.wbmp) format file,
skip the header and point to the start of the bitmap itself.
*/
if (wbmp) {
for (i=2; i<6; i++)
header[i] = fgetc (infp);
/*
Now read the bitmap.
*/
for (i=0; i < 32*17; i++) {
for (j=0; j < 32*18/8; j++) {
inchar = fgetc (infp);
bitmap[i][j] = ~inchar; /* invert bits for proper color */
}
}
}
/*
Otherwise, treat this as a Windows Bitmap file, because we checked
that it began with "BM". Save the header contents for future use.
Expect a 14 byte standard BITMAPFILEHEADER format header followed
by a 40 byte standard BITMAPINFOHEADER Device Independent Bitmap
header, with data stored in little-endian format.
*/
else {
for (i = 2; i < 54; i++)
header[i] = fgetc (infp);
bmp_header.filetype[0] = 'B';
bmp_header.filetype[1] = 'M';
bmp_header.file_size =
(header[2] & 0xFF) | ((header[3] & 0xFF) << 8) |
((header[4] & 0xFF) << 16) | ((header[5] & 0xFF) << 24);
/* header bytes 6..9 are reserved */
bmp_header.image_offset =
(header[10] & 0xFF) | ((header[11] & 0xFF) << 8) |
((header[12] & 0xFF) << 16) | ((header[13] & 0xFF) << 24);
bmp_header.info_size =
(header[14] & 0xFF) | ((header[15] & 0xFF) << 8) |
((header[16] & 0xFF) << 16) | ((header[17] & 0xFF) << 24);
bmp_header.width =
(header[18] & 0xFF) | ((header[19] & 0xFF) << 8) |
((header[20] & 0xFF) << 16) | ((header[21] & 0xFF) << 24);
bmp_header.height =
(header[22] & 0xFF) | ((header[23] & 0xFF) << 8) |
((header[24] & 0xFF) << 16) | ((header[25] & 0xFF) << 24);
bmp_header.nplanes =
(header[26] & 0xFF) | ((header[27] & 0xFF) << 8);
bmp_header.bits_per_pixel =
(header[28] & 0xFF) | ((header[29] & 0xFF) << 8);
bmp_header.compression =
(header[30] & 0xFF) | ((header[31] & 0xFF) << 8) |
((header[32] & 0xFF) << 16) | ((header[33] & 0xFF) << 24);
bmp_header.image_size =
(header[34] & 0xFF) | ((header[35] & 0xFF) << 8) |
((header[36] & 0xFF) << 16) | ((header[37] & 0xFF) << 24);
bmp_header.x_ppm =
(header[38] & 0xFF) | ((header[39] & 0xFF) << 8) |
((header[40] & 0xFF) << 16) | ((header[41] & 0xFF) << 24);
bmp_header.y_ppm =
(header[42] & 0xFF) | ((header[43] & 0xFF) << 8) |
((header[44] & 0xFF) << 16) | ((header[45] & 0xFF) << 24);
bmp_header.ncolors =
(header[46] & 0xFF) | ((header[47] & 0xFF) << 8) |
((header[48] & 0xFF) << 16) | ((header[49] & 0xFF) << 24);
bmp_header.important_colors =
(header[50] & 0xFF) | ((header[51] & 0xFF) << 8) |
((header[52] & 0xFF) << 16) | ((header[53] & 0xFF) << 24);
if (bmp_header.ncolors == 0)
bmp_header.ncolors = 1 << bmp_header.bits_per_pixel;
/* If a Color Table exists, read it */
if (bmp_header.ncolors > 0 && bmp_header.bits_per_pixel <= 8) {
for (i = 0; i < bmp_header.ncolors; i++) {
color_table[i][0] = fgetc (infp); /* Red */
color_table[i][1] = fgetc (infp); /* Green */
color_table[i][2] = fgetc (infp); /* Blue */
color_table[i][3] = fgetc (infp); /* Alpha */
}
/*
Determine from the first color table entry whether we
are inverting the resulting bitmap image.
*/
if ( (color_table[0][0] + color_table[0][1] + color_table[0][2])
< (3 * 128) ) {
color_mask = 0xFF;
}
}
#ifdef DEBUG
/*
Print header info for possibly adding support for
additional file formats in the future, to determine
how the bitmap is encoded.
*/
fprintf (stderr, "Filetype: '%c%c'\n",
bmp_header.filetype[0], bmp_header.filetype[1]);
fprintf (stderr, "File Size: %d\n", bmp_header.file_size);
fprintf (stderr, "Image Offset: %d\n", bmp_header.image_offset);
fprintf (stderr, "Info Header Size: %d\n", bmp_header.info_size);
fprintf (stderr, "Image Width: %d\n", bmp_header.width);
fprintf (stderr, "Image Height: %d\n", bmp_header.height);
fprintf (stderr, "Number of Planes: %d\n", bmp_header.nplanes);
fprintf (stderr, "Bits per Pixel: %d\n", bmp_header.bits_per_pixel);
fprintf (stderr, "Compression Method: %d\n", bmp_header.compression);
fprintf (stderr, "Image Size: %d\n", bmp_header.image_size);
fprintf (stderr, "X Pixels per Meter: %d\n", bmp_header.x_ppm);
fprintf (stderr, "Y Pixels per Meter: %d\n", bmp_header.y_ppm);
fprintf (stderr, "Number of Colors: %d\n", bmp_header.ncolors);
fprintf (stderr, "Important Colors: %d\n", bmp_header.important_colors);
#endif
/*
Now read the bitmap.
*/
for (i = 32*17-1; i >= 0; i--) {
for (j=0; j < 32*18/8; j++) {
next_pixels = 0x00; /* initialize next group of 8 pixels */
/* Read a monochrome image -- the original case */
if (bmp_header.bits_per_pixel == 1) {
next_pixels = fgetc (infp);
}
/* Read a 32 bit per pixel RGB image; convert to monochrome */
else if ( bmp_header.bits_per_pixel == 24 ||
bmp_header.bits_per_pixel == 32) {
next_pixels = 0;
for (k = 0; k < 8; k++) { /* get next 8 pixels */
this_pixel = (fgetc (infp) & 0xFF) +
(fgetc (infp) & 0xFF) +
(fgetc (infp) & 0xFF);
if (bmp_header.bits_per_pixel == 32) {
(void) fgetc (infp); /* ignore alpha value */
}
/* convert RGB color space to monochrome */
if (this_pixel >= (128 * 3))
this_pixel = 0;
else
this_pixel = 1;
/* shift next pixel color into place for 8 pixels total */
next_pixels = (next_pixels << 1) | this_pixel;
}
}
if (bmp_header.height < 0) { /* Bitmap drawn top to bottom */
bitmap [(32*17-1) - i] [j] = next_pixels;
}
else { /* Bitmap drawn bottom to top */
bitmap [i][j] = next_pixels;
}
}
}
/*
If any bits are set in color_mask, apply it to
entire bitmap to invert black <--> white.
*/
if (color_mask != 0x00) {
for (i = 32*17-1; i >= 0; i--) {
for (j=0; j < 32*18/8; j++) {
bitmap [i][j] ^= color_mask;
}
}
}
}
/*
We've read the entire file. Now close the input file pointer.
*/
fclose (infp);
/*
We now have the header portion in the header[] array,
and have the bitmap portion from top-to-bottom in the bitmap[] array.
*/
/*
If no Unicode range (U+nnnnnn00 through U+nnnnnnFF) was specified
with a -p parameter, determine the range from the digits in the
bitmap itself.
Store bitmaps for the hex digit patterns that this file uses.
*/
if (!planeset) { /* If Unicode range not specified with -p parameter */
for (i = 0x0; i <= 0xF; i++) { /* hex digit pattern we're storing */
for (j = 0; j < 4; j++) {
hexdigit[i][j] =
((unsigned)bitmap[32 * (i+1) + 4 * j + 8 ][6] << 24 ) |
((unsigned)bitmap[32 * (i+1) + 4 * j + 8 + 1][6] << 16 ) |
((unsigned)bitmap[32 * (i+1) + 4 * j + 8 + 2][6] << 8 ) |
((unsigned)bitmap[32 * (i+1) + 4 * j + 8 + 3][6] );
}
}
/*
Read the Unicode plane digits into arrays for comparison, to
determine the upper four hex digits of the glyph addresses.
*/
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
unidigit[i][j] =
((unsigned)bitmap[32 * 0 + 4 * j + 8 + 1][i + 3] << 24 ) |
((unsigned)bitmap[32 * 0 + 4 * j + 8 + 2][i + 3] << 16 ) |
((unsigned)bitmap[32 * 0 + 4 * j + 8 + 3][i + 3] << 8 ) |
((unsigned)bitmap[32 * 0 + 4 * j + 8 + 4][i + 3] );
}
}
tmpsum = 0;
for (i = 4; i < 6; i++) {
for (j = 0; j < 4; j++) {
unidigit[i][j] =
((unsigned)bitmap[32 * 1 + 4 * j + 8 ][i] << 24 ) |
((unsigned)bitmap[32 * 1 + 4 * j + 8 + 1][i] << 16 ) |
((unsigned)bitmap[32 * 1 + 4 * j + 8 + 2][i] << 8 ) |
((unsigned)bitmap[32 * 1 + 4 * j + 8 + 3][i] );
tmpsum |= unidigit[i][j];
}
}
if (tmpsum == 0) { /* the glyph matrix is transposed */
flip = 1; /* note transposed order for processing glyphs in matrix */
/*
Get 5th and 6th hex digits by shifting first column header left by
1.5 columns, thereby shifting the hex digit right after the leading
"U+nnnn" page number.
*/
for (i = 0x08; i < 0x18; i++) {
bitmap[i][7] = (bitmap[i][8] << 4) | ((bitmap[i][ 9] >> 4) & 0xf);
bitmap[i][8] = (bitmap[i][9] << 4) | ((bitmap[i][10] >> 4) & 0xf);
}
for (i = 4; i < 6; i++) {
for (j = 0; j < 4; j++) {
unidigit[i][j] =
((unsigned)bitmap[4 * j + 8 + 1][i + 3] << 24 ) |
((unsigned)bitmap[4 * j + 8 + 2][i + 3] << 16 ) |
((unsigned)bitmap[4 * j + 8 + 3][i + 3] << 8 ) |
((unsigned)bitmap[4 * j + 8 + 4][i + 3] );
}
}
}
/*
Now determine the Unicode plane by comparing unidigit[0..5] to
the hexdigit[0x0..0xF] array.
*/
uniplane = 0;
for (i=0; i<6; i++) { /* go through one bitmap digit at a time */
match = 0; /* haven't found pattern yet */
for (j = 0x0; !match && j <= 0xF; j++) {
if (unidigit[i][0] == hexdigit[j][0] &&
unidigit[i][1] == hexdigit[j][1] &&
unidigit[i][2] == hexdigit[j][2] &&
unidigit[i][3] == hexdigit[j][3]) { /* we found the digit */
uniplane |= j;
match = 1;
}
}
uniplane <<= 4;
}
uniplane >>= 4;
}
/*
Now read each glyph and print it as hex.
*/
for (i = 0x0; i <= 0xf; i++) {
for (j = 0x0; j <= 0xf; j++) {
for (k = 0; k < 16; k++) {
if (flip) { /* transpose glyph matrix */
thischar0[k] = bitmap[32*(j+1) + k + 7][4 * (i+2) ];
thischar1[k] = bitmap[32*(j+1) + k + 7][4 * (i+2) + 1];
thischar2[k] = bitmap[32*(j+1) + k + 7][4 * (i+2) + 2];
thischar3[k] = bitmap[32*(j+1) + k + 7][4 * (i+2) + 3];
}
else {
thischar0[k] = bitmap[32*(i+1) + k + 7][4 * (j+2) ];
thischar1[k] = bitmap[32*(i+1) + k + 7][4 * (j+2) + 1];
thischar2[k] = bitmap[32*(i+1) + k + 7][4 * (j+2) + 2];
thischar3[k] = bitmap[32*(i+1) + k + 7][4 * (j+2) + 3];
}
}
/*
If the second half of the 16*16 character is all zeroes, this
character is only 8 bits wide, so print a half-width character.
*/
empty1 = empty2 = 1;
for (k=0; (empty1 || empty2) && k < 16; k++) {
if (thischar1[k] != 0) empty1 = 0;
if (thischar2[k] != 0) empty2 = 0;
}
/*
Only print this glyph if it isn't blank.
*/
if (!empty1 || !empty2) {
/*
If the second half is empty, this is a half-width character.
Only print the first half.
*/
/*
Original GNU Unifont format is four hexadecimal digit character
code followed by a colon followed by a hex string. Add support
for codes beyond the Basic Multilingual Plane.
Unicode ranges from U+0000 to U+10FFFF, so print either a
4-digit or a 6-digit code point. Note that this software
should support up to an 8-digit code point, extending beyond
the normal Unicode range, but this has not been fully tested.
*/
if (uniplane > 0xff)
fprintf (outfp, "%04X%X%X:", uniplane, i, j); // 6 digit code pt.
else
fprintf (outfp, "%02X%X%X:", uniplane, i, j); // 4 digit code pt.
for (thisrow=0; thisrow<16; thisrow++) {
/*
If second half is empty and we're not forcing this
code point to double width, print as single width.
*/
if (!forcewide &&
empty2 && !wide[(uniplane << 8) | (i << 4) | j]) {
fprintf (outfp,
"%02X",
thischar1[thisrow]);
}
else if (wide[(uniplane << 8) | (i << 4) | j] == 4) {
/* quadruple-width; force 32nd pixel to zero */
fprintf (outfp,
"%02X%02X%02X%02X",
thischar0[thisrow], thischar1[thisrow],
thischar2[thisrow], thischar3[thisrow] & 0xFE);
}
else { /* treat as double-width */
fprintf (outfp,
"%02X%02X",
thischar1[thisrow], thischar2[thisrow]);
}
}
fprintf (outfp, "\n");
}
}
}
exit (0);
}
planeset
unsigned planeset
=1: use plane specified with -p parameter
Definition: unibmp2hex.c:122
unidigit
unsigned unidigit[6][4]
Definition: unibmp2hex.c:127
uniplane
unsigned uniplane
Unicode plane number, 0..0xff ff ff.
Definition: unibmp2hex.c:121
forcewide
unsigned forcewide
=1 to set each glyph to 16 pixels wide
Definition: unibmp2hex.c:124
bmp_header
struct @0 bmp_header
hexdigit
unsigned hexdigit[16][4]
32 bit representation of 16x8 0..F bitmap
Definition: unibmp2hex.c:119
color_table
unsigned char color_table[256][4]
Definition: unibmp2hex.c:149
MAXBUF
#define MAXBUF
Maximum input file line length - 1.
Definition: unibmp2hex.c:116
flip
unsigned flip
=1 if we're transposing glyph matrix
Definition: unibmp2hex.c:123

## Variable Documentation

## bits_per_pixel

int bits_per_pixel

Definition at line 139 of file unibmp2hex.c.

##

struct { ... } bmp_header

Bitmap Header parameters

## color_table

unsigned char color_table[256][4]

Bitmap Color Table – maximum of 256 colors in a BMP file

Definition at line 149 of file unibmp2hex.c.

## compression

int compression

Definition at line 140 of file unibmp2hex.c.

## file_size

int file_size

Definition at line 133 of file unibmp2hex.c.

## filetype

char filetype[2]

Definition at line 132 of file unibmp2hex.c.

## flip

unsigned flip =0

=1 if we're transposing glyph matrix

Definition at line 123 of file unibmp2hex.c.

## forcewide

unsigned forcewide =0

=1 to set each glyph to 16 pixels wide

Definition at line 124 of file unibmp2hex.c.

## height

int height

Definition at line 137 of file unibmp2hex.c.

## hexdigit

unsigned hexdigit[16][4]

32 bit representation of 16x8 0..F bitmap

Definition at line 119 of file unibmp2hex.c.

## image_offset

int image_offset

Definition at line 134 of file unibmp2hex.c.

## image_size

int image_size

Definition at line 141 of file unibmp2hex.c.

## important_colors

int important_colors

Definition at line 145 of file unibmp2hex.c.

## info_size

int info_size

Definition at line 135 of file unibmp2hex.c.

## ncolors

int ncolors

Definition at line 144 of file unibmp2hex.c.

## nplanes

int nplanes

Definition at line 138 of file unibmp2hex.c.

## planeset

unsigned planeset =0

=1: use plane specified with -p parameter

Definition at line 122 of file unibmp2hex.c.

## unidigit

unsigned unidigit[6][4]

The six Unicode plane digits, from left-most (0) to right-most (5)

Definition at line 127 of file unibmp2hex.c.

## uniplane

unsigned uniplane =0

Unicode plane number, 0..0xff ff ff.

Definition at line 121 of file unibmp2hex.c.

## width

int width

Definition at line 136 of file unibmp2hex.c.

## x_ppm

int x_ppm

Definition at line 142 of file unibmp2hex.c.

## y_ppm

int y_ppm

Definition at line 143 of file unibmp2hex.c.