diff options
| author | karl <karl> | 2004-04-19 22:56:26 +0000 |
|---|---|---|
| committer | karl <karl> | 2004-04-19 22:56:26 +0000 |
| commit | d2ffca200655a89c5d140b66d69001e92173e3da (patch) | |
| tree | 6fa1965e6e8362c5913e1554b12507a924dba7f1 /imageto | |
| parent | eb33f9ace5a3ddfe8a983866468f3352abaa6391 (diff) | |
| download | fontutils-d2ffca200655a89c5d140b66d69001e92173e3da.tar.gz | |
init
Diffstat (limited to 'imageto')
| -rw-r--r-- | imageto/ChangeLog | 1113 | ||||
| -rw-r--r-- | imageto/GNUmakefile | 43 | ||||
| -rw-r--r-- | imageto/README | 46 | ||||
| -rw-r--r-- | imageto/bitmap2.c | 83 | ||||
| -rw-r--r-- | imageto/bitmap2.h | 34 | ||||
| -rw-r--r-- | imageto/extract.c | 239 | ||||
| -rw-r--r-- | imageto/extract.h | 50 | ||||
| -rw-r--r-- | imageto/ifi.c | 196 | ||||
| -rw-r--r-- | imageto/ifi.h | 91 | ||||
| -rw-r--r-- | imageto/image-char.c | 69 | ||||
| -rw-r--r-- | imageto/image-char.h | 89 | ||||
| -rw-r--r-- | imageto/image-header.h | 35 | ||||
| -rw-r--r-- | imageto/input-img.c | 159 | ||||
| -rw-r--r-- | imageto/input-img.h | 43 | ||||
| -rw-r--r-- | imageto/input-pbm.c | 88 | ||||
| -rw-r--r-- | imageto/input-pbm.h | 44 | ||||
| -rw-r--r-- | imageto/main.c | 416 | ||||
| -rw-r--r-- | imageto/main.h | 42 | ||||
| -rw-r--r-- | imageto/out-chars.c | 750 | ||||
| -rw-r--r-- | imageto/out-chars.h | 34 | ||||
| -rw-r--r-- | imageto/out-epsf.c | 166 | ||||
| -rw-r--r-- | imageto/out-epsf.h | 28 | ||||
| -rw-r--r-- | imageto/out-strips.c | 94 | ||||
| -rw-r--r-- | imageto/out-strips.h | 27 | ||||
| -rw-r--r-- | imageto/strips.tex | 85 | ||||
| -rw-r--r-- | imageto/version.c | 1 |
26 files changed, 4065 insertions, 0 deletions
diff --git a/imageto/ChangeLog b/imageto/ChangeLog new file mode 100644 index 0000000..7870509 --- /dev/null +++ b/imageto/ChangeLog @@ -0,0 +1,1113 @@ +Mon Apr 8 09:25:30 1996 Kathy Hargreaves <letters@cs.umb.edu> + + * out-chars.c: doc fix. + +Sat Dec 9 07:21:29 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (do_image_line): doc fix. + +Wed Dec 6 08:28:15 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (output_chars): doc fix. + +Tue Dec 5 09:40:23 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: doc fix. + +Mon Dec 4 07:40:24 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * main.c (USAGE): doc fix. + + * out-chars.c: doc fix. Changed image_bitmap to image_line_bitmap. + (do_image_line): Changed original_box_count to previous_box_count. + +Sun Dec 3 09:05:05 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (do_image_line): doc fix. + +Thu Nov 30 09:03:47 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (output_chars): doc fix. + +Tue Nov 28 09:47:19 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (output_chars): reconsider the current bounding box + if the current character is ignored. + +Thu Nov 23 08:36:07 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (bitmap_to_gf_char): call kpse_find_tfm instead of + find_tfm_filename. + +Thu Nov 16 09:01:31 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (bitmap_to_gf_char): Remove output_name's suffix + before calling find_tfm_filename with it. + + * main.c: (OUTPUT_NAME): Made on-static so could do below. + + * main.h: Added output_name extern declaration. + + * out-chars.c: (bitmap_to_gf_char): Call kpse_find_tfm with + find_tfm_filename(output_name) instead of something built with + input_name, so that will have the design size in the name. + +Tue Nov 14 07:28:21 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * ifi.c: (read_ifi_file): increment n after setting the charcode, + not before, so first character will have charcode 0. + +Sat Oct 14 14:54:27 1995 Kathy Hargreaves <karl@cs.umb.edu> + + * out-chars.c: (bitmap_to_gf_char): Also have to call + remove_suffix on input name passed to kpse_find_tfm. + +Thu Oct 12 10:44:23 1995 Karl Berry <karl@cs.umb.edu> + + * out-chars.c (bitmap_to_gf_char): Have to call basename on the + input name passed to kpse_find_tfm. + +Sun Aug 13 18:01:11 1995 Karl Berry <karl@cs.umb.edu> + + * main.c: Call kpse_set_progname. + +Sun May 15 11:32:54 1994 Karl Berry (karl@cs.umb.edu) + + * out-chars.c (output_chars): Change `x' to `<ignored>'. + +Fri May 13 15:27:29 1994 Karl Berry (karl@cs.umb.edu) + + * out-chars.c (bitmap_to_gf_char): Call kpse_find_tfm, now that it + exists. + +Sun Aug 22 13:32:49 1993 Karl Berry (karl@cs.umb.edu) + + * out-epsf.c (PIXELS_TO_BP): No longer needed. + +Sat Aug 7 13:44:10 1993 Karl Berry (karl@cs.umb.edu) + + * input-img.c (img_get_header): Allow grayscale images. + + * *.h: types.h now in kpathsea. + +Tue Jul 27 09:04:12 1993 Karl Berry (karl@cs.umb.edu) + + * GNUmakefile (libraries): Add tfm. + +Sun Jul 25 19:20:04 1993 Karl Berry (karl@cs.umb.edu) + + * out-chars.c (bitmap_to_gf_char): Get TFM width from existing TFM + file, if we can find one. Convert for use with kpathsea. + +Thu May 20 17:11:25 1993 Karl Berry (karl@cs.umb.edu) + + * ifi.c: Doc fix. + +Mon Nov 9 09:46:32 1992 Karl Berry (karl@cs.umb.edu) + + * image-header.h: Doc fix. + +Tue Oct 27 13:02:04 1992 Karl Berry (karl@cs.umb.edu) + + * Version 0.6. + +Sat Oct 24 05:13:02 1992 Karl Berry (karl@cs.umb.edu) + + * ifi.c (read_ifi_file): Just do successive character codes if we + don't have an encoding file. + * main.c (USAGE): Change doc. + +Fri Oct 23 10:43:46 1992 Karl Berry (karl@cs.umb.edu) + + * out-chars.c (output_chars): Free the bounding box list we construct. + + * out-chars.c (output_chars): If the IFI struct says no bounding + boxes, don't read any of the bitmap, and reconsider the current bb. + +Tue Oct 20 17:17:26 1992 Karl Berry (karl@cs.umb.edu) + + * GNUmakefile (install): Make the second arg a file, not a directory. + +Fri Oct 16 15:40:53 1992 Karl Berry (karl@cs.umb.edu) + + * out-epsf.c: Doc fix. + +Mon Oct 5 09:31:30 1992 Karl Berry (karl@cs.umb.edu) + + * main.c (read_command_line): Make -print-clean-info imply -verbose. + (main): Remove now-redundant test for `print_clean_info'. + + * out-chars.c (write_image_chars): Only report "+" if we have to + keep reading vertically, not horizontally. + (do_image_line): Remove the report from here. + +Sun Oct 4 08:59:55 1992 Karl Berry (karl@cs.umb.edu) + + * out-chars.c (write_image_chars): Don't keep adding to + `row_height' for appended image rows, just assign. + + * main.c (main): Test for zero resolution here. + (set_input_format): Not here. + + * out-chars.c (clean_threshold): Remove. + * out-chars.h: Likewise. + * main.c (USAGE, read_command_line): And here. + + * out-chars.c (bb_equal_p): New fn. + + * out-chars.c (offset_bb_list): Function moved here from bb-outline.c. + + * out-chars.c (clean_bitmap): Rewrite to take a list of known + boxes, and remove those that aren't in the list. + (output_chars): Only call `clean_bitmap' once, after we've + combined everything. + (image_to_bitmap_bbs): New fn. + +Sat Oct 3 13:54:39 1992 Karl Berry (karl@cs.umb.edu) + + * out-chars.c (write_image_chars): Don't abort if the image ends + prematurely, just give a warning and return. + + * out-chars.c (OUTPUT_CHAR_P): New macro. + (output_chars): Use it, instead of repeating the same expr several + times. + +Fri Oct 2 16:14:03 1992 Karl Berry (karl@cs.umb.edu) + + * out-chars.[ch]: New files constructed from main.[ch]. + * main.c: Include out-chars.h. + + * extract.c (REPORT_SCANLINE): use REPORT. + + * main.c (-info-filename): remove this option. + + * {epsf,strips}.[ch]: Rename to out-*. + * GNUmakefile (c_and_h): Likewise. + + * ifi.[ch]: New files constructed from image-char.[ch] and main.c. + * main.c: include ifi.h. + (extract_chars): Change call to read_ifi_file. + * GNUmakefile (c_and_h): add `ifi', remove `image-char'. + +Mon Sep 28 11:11:59 1992 Karl Berry (karl@cs.umb.edu) + + * main.c: change `fprintf (stderr's to use REPORT*. + + * main.c (clean_bitmap): print the size of the bounding box being + cleaned, not that of the enclosing character. (halvers@sol.crd.ge.com) + +Tue Sep 22 13:01:54 1992 Karl Berry (karl@cs.umb.edu) + + * main.c (read_ifi_file): call make_suffix to make the default IFI + filename, instead of appending to the root. + (input_rootname): remove. + (main): don't assign to input_rootname; just set output_name to + the fn call. + (input_name): new static. + + * main.c (clean_bitmap): if clean_threshold is 1.0, do nothing; + else only clean if the gray value is > threshold, not >=. + + * main.c: make diagnostic messages consistent. + + * main.c (do_image_line): set `bb_offset' to just the width + of the previous bb, since we're already incorporating the + interbb whitespace in the second bb. + +Mon Sep 21 10:32:07 1992 Karl Berry (karl@cs.umb.edu) + + * main.c (read_command_line): new option -ifi-file, a synonym for + -info-file. + (USAGE): document it. + + * main.c (set_input_format): don't call strcmp on NULL if the + input filename lacks an extension. + +Thu Sep 3 09:30:54 1992 Karl Berry (karl@hayley) + + * Version 0.5. + +Sat Aug 29 16:14:35 1992 Karl Berry (karl@hayley) + + * GNUmakefile (dist, install): new targets to deal with strips.tex. + +Fri Aug 21 16:14:10 1992 Karl Berry (karl@hayley) + + * main.c (read_ifi_file): improve warning message. + +Mon Jul 13 16:58:44 1992 Karl Berry (karl@hayley) + + * epsf.c (write_epsf): use `width_used' for the width of image buffer. + +Thu Jul 2 14:06:09 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (BB_TO_CARTESIAN): subtract IMAGE_CHAR_BASELINE_ADJUST(.) + instead of adding it. + + * main.c (bitmap_to_gf_char): removed `char_baseline'. + +Sun Jun 28 11:54:23 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (bitmap_to_gf_char): added cartesian_bb; fill it using + BB_TO_CARTESIAN and assign to the GF char. Print out the GF + char's rows for baseline adjustment. + +Fri Jun 26 13:45:20 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (read_ifi_file): changed warning to include encoding name. + +Mon Jun 15 07:37:29 1992 Karl Berry (karl@hayley) + + * extract.c (get_image_row): allocate more than one row at a time. + + * extract.c (get_image_row): don't realloc if we're keeping + leading white rows. + + * main.c (extract_chars): change `nchars_per_line' to one if + `print_guidelines' is true. + + * main.c (read_ifi_file): if the character name is undefined in + the encoding, omit it from the output. + + * main.c (get_image_info): rename to `read_ifi_file'. + + * main.c (get_image_info): make `.notdef' mean omission, instead + of `-1'. + + * image-char.h (image_char_type): new field `charname'. + (IMAGE_CHARNAME): new accessor macro. + * main.c (bitmap_to_gf_char): print the character name, instead of + relying on %c. + (get_image_info): set it. + + * main.h (print_scanline): new routine. + * main.c (print_scanline): define it. + * input-img.c (img_get_scanline): print the scanlines if + `trace_scanlines' is set. + * input-pbm.c (pbm_get_scanline): call it, instead of doing the + printing inline. + +Sat Jun 13 12:04:00 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (get_image_info): renamed charcode_str to charname_str. + Removed comment-handling stuff. + + * main.c (encoding_name, encoding_info): added. + (get_image_info): added `encoding_info'; call `encoding_number' + on `charcode_str' instead of `xparse_charcode'. + (USAGE, read_command_line): added -encoding option. + +Tue Jun 9 13:45:42 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (output_chars): deleted clean_all_bbs. + (clean_bitmap): deleted CLEAN_ALL_BBS; call find_outline_bbs + with false instead of this. Updated doc. Now only check + bounding boxes which don't enclose the whole character, instead + of those which also are on the edge, unless clean_all_bbs is + true, whereupon check those also. + (get_image_info): don't handle CLEAN_ALL_BBS_FLAG anymore. + + * image-char.h (image_char_type): deleted clean_inner_bbs field. + (IMAGE_CHAR_CLEAN_ALL_BBS, CLEAN_ALL_BBS_FLAG): deleted + +Mon Jun 8 12:33:45 1992 Kathy Hargreaves (kathy@hayley) + + * input-pbm.c (pbm_get_scanline): increment scanline_count after + printing it. + + * main.c (BB_TO_CARTESIAN): added. + (bitmap_to_gf_char): when print-guidelines is true, print the + bounding box's max and min (in that order) row in Cartesian + coordinates, not the GF char's min and max row. + +Fri Jun 5 21:18:12 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (output_chars): don't clean bounding boxes unless + outputting the character. + + * main.c (get_image_info): set clean_all_bbs field of `c' false if + there's not a CLEAN_ALL_BBS_FLAG at the end of the character string. + +Fri Jun 5 09:19:48 1992 Karl Berry (karl@hayley) + + * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert) + +Tue Jun 2 18:03:52 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (output_chars): call clean_bitmap with 0's for LEFT_MARK + and RIGHT_MARK if clean_all_bbs is true. + +Mon Jun 1 11:19:46 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (output_chars): added clean_all_bbs to send to clean_bitmap. + + * main.c (clean_bitmap): clean only those boxes which are on the + edges only if CLEAN_ALL_BBS is false; otherwise, clean them all. + + * main.c (get_image_info): if there's a CLEAN_ALL_BBS_FLAG appended + to the character code, then set the clean_all_bbs field of c. + + * image-char.h (image_char_type): added clean_all_bbs field. + +Sun May 31 13:10:48 1992 Karl Berry (karl@hayley) + + * main.c: rename `design-size' option to `designsize'. + + * epsf.c (write_epsf): change the EPS output to not write one + gigantic image. + +Sat May 30 11:58:02 1992 Kathy Hargreaves (kathy@hayley) + + * main.c (USAGE -clean-threshold): doc fix. + +Fri May 29 11:34:52 1992 Karl Berry (karl@hayley) + + * main.c (main): declare to return an int. + +Tue May 26 07:56:34 1992 Karl Berry (karl@hayley) + + * main.c: simplify comments on IFI file format, since now the real + documentation describes it. + +Mon May 25 11:45:49 1992 Karl Berry (karl@hayley) + + * main.c (clean_bitmap): wasn't printing clean info for bbs that + weren't cleared. + + * main.c (read_command_line): make -print-guidelines => -verbose. + (USAGE): document this. + (main): don't bother to test `print_guidelines' anymore when we + doing verbose things. + + * main.c (main): use `output_name', not `gf_name' (which we no + longer need). + + * main.c (set_{pbm,img}_input_format): set `input_extension' to + just `pbm' or `img', omitting the leading `.'. + +Sun May 24 18:03:09 1992 Karl Berry (karl@hayley) + + * main.c (read_command_line): in -input-format, complain if they + give an unrecognized input format. + (main): call set_input_format. + (set_input_format): new routine to intuit the input format from + the input filename if they didn't specify. + (set_{pbm,img}_input_format): new routines. + +Thu May 21 10:59:23 1992 Karl Berry (karl@hayley) + + * GNUmakefile, version.c, main.c: change `imagetofont' to `imageto'. + + * strips.c (write_chars_as_strips): don't bother to initialize + `gf_row'. + +Wed May 20 07:34:38 1992 Karl Berry (karl@hayley) + + * strips.h: include image-header.h, not input-img.h. + + * main.c (extract_chars): new fn (to shorten main). + (main): call it. + + * main.c (do_epsf): new global. + (read_command_line): new option `-epsf'. + (main): call `write_epsf' if set. + * GNUmakefile (c_and_h): add epsf. + * epsf.[ch]: new files. + +Mon May 4 09:27:55 1992 Karl Berry (karl@hayley) + + * main.c (main): don't lose the `<dpi>gf' from the output name. + + * strips.c (write_chars_as_strips): add one to `lines_per_char' to + compensate for roundoff error. + + * main.c (verbose): remove this, as it's defined in report.c. + +Sun May 3 19:31:29 1992 Karl Berry (karl@hayley) + + * strips.c (write_chars_as_strips): use REPORT for the progress + report. + +Tue Apr 21 07:44:36 1992 Karl Berry (karl@hayley) + + * extract.c (append_next_image_row): use XTALLOC1. + +Mon Apr 20 12:53:43 1992 Karl Berry (karl@hayley) + + * main.c (main): simplify logic again for figuring out the output + filename; remove any suffix from the input filename before it is + used to make the IFI or output filename. + (get_image_info): the variable is named `input_rootname' now, not + `input_basename'. + +Wed Apr 15 15:26:53 1992 Karl Berry (karl@hayley) + + * main.c (main): `make_output_filename' is now `extend_filename'. + +Wed Apr 8 12:28:59 1992 Karl Berry (karl@hayley) + + * main.c (do_image_line): don't increment the max_col transition + in the horizontally concatenated block, either. + + * main.c: make most of the globals static. + * main.h: remove declarations for unneeded globals. + + * main.c (debug): add this. + +Mon Apr 6 16:43:39 1992 Karl Berry (karl@hayley) + + * extract.c (get_image_row): count white rows in image size; free + the scanline storage after we've copied it. + +Sun Apr 5 11:46:33 1992 Karl Berry (karl@hayley) + + * main.c (do_image_line): don't increment the transition which we + use for the maximum column. + +Sat Apr 4 12:57:15 1992 Karl Berry (karl@hayley) + + * main.c (do_image_line): move test for enough boxes to above + dealing with the current bitmap, so garbage at the end doesn't + mess us up. (from wales@cs.ucla.edu) + +Wed Apr 1 16:17:18 1992 Karl Berry (karl at hayley) + + * main.c (main): simplify the output name creation code. + + * main.c (font_name_extension): rename to `input_extension', and + don't bother to initialize it. + +Sat Mar 28 07:48:43 1992 Karl Berry (karl at hayley) + + * Version 0.4. + + * Change copyright years to 1992 only. + +Mon Mar 9 16:46:10 1992 Kathy Hargreaves (kathy at hayley) + + * main.c (main): move setting of dpi to above (and out of) + do_strips test. + + * main.c (main): set output_name_suffix with static strings + and xmalloc dpi and design_size_str. + + * main.c (main): if output_name has no suffix, append either + output_name_suffix or design_size to its stem before appending + a suffix. + +Sat Mar 7 09:55:42 1992 Karl Berry (karl at hayley) + + * GNUmakefile (libraries): define again. + (files, headers, sources): replace with `c_and_h', etc. + +Thu Mar 5 06:47:26 1992 Karl Berry (karl at hayley) + + * main.c (output_filename): rename to `output_name', and remove + the other `output_name' declaration. + +Wed Mar 4 17:21:32 1992 Kathy Hargreaves (kathy at hayley) + + * main.c (main) changed `output_basename' to `output_name'. + Deleted add_suffix and add_design_size. + Added dpi, design_size_str, and output_name_suffix. + Use make_output_filename to check if output name has a suffix. + If output_name not given and not doing strips, set design_size_str. + If doing strips, set output_name_suffix to "sp". + Always set dpi. + +Mon Mar 2 12:15:52 1992 Karl Berry (karl at hayley) + + * main.c (main): decrease nchars_per_line to 11. + +Sun Mar 1 13:03:23 1992 Karl Berry (karl at hayley) + + * GNUmakefile (files): remove bb-outline. + + * GNUmakefile (need_pbm_library): define. + (sources): remove the PBM stuff. + +Fri Feb 28 07:53:09 1992 Karl Berry (karl at hayley) + + * extract.c (image_row_transitions): new routine. + (some_black_to_all_white_row): call it after getting the image row. + (append_next_image_row): call it after appending. + (get_image_row): do not compute the transitions here. + + * main.c (bitmap_to_gf_char): the GF min_row is the depth, the GF + max_row is the height; we had it the other way around. Also, + `row_baseline' is one-origin, but char rows are 0-origin. + +Tue Feb 25 14:40:54 1992 Karl Berry (karl at hayley) + + * main.c (main): decrease number of chars reported without + guidelines to 12. + + * input-pbm.c (pbm_get_scanline): declare the test character for + EOF as int, not char. Also, print the scanlines if + trace_scanlines is set. + * main.c (trace_scanlines): new global. + (read_command_line): new option. + + * bitmap2.c (bitmap_vconcat): put one blank row between the + bitmaps, to compensate for what some_black... removed. + + * extract.c (get_image_row): don't keep leading white rows if + there weren't any; always append scanline, even if there were. + +Fri Jan 31 17:08:38 1992 Karl Berry (karl at hayley) + + * main.c (read_command_line): declare `option_index' (for new + getopt). + +Tue Jan 21 11:47:26 1992 Kathy Hargreaves (kathy at hayley) + + * main.c (main): wasn't putting the suffix on the gf name when + gave an output filename without a suffix because was finding the + dot in the pathname `../fonts'. + + * main.c (bitmap_to_gf_char): were switching the minimum and + maximum rows when assigning to the gf char. + + * main.c (main): malloc gf_name more precisely. + + * main.c (bitmap_to_gf_char): fixed calculation of gf char's rows. + (main): changed how build the gf output filename: if the user + specifies an output file, don't ever add on a design size and don't + add a suffix if there's one already. + + * main.c (bitmap_to_gf_char): now print gf character's (baseline- + adjusted) row instead of the bounding box's (unadjusted) ones. + +Mon Jan 20 14:46:16 1992 Kathy Hargreaves (kathy at hayley) + + * main.c (main): added variable `output_basename' so user could + specify an output file basename. + (read_command_line): Added `output-file' option. + +Tue Jan 14 13:14:46 1992 Kathy Hargreaves (kathy at hayley) + + * main.c (get_image_info): when call libfile_start with + info_filename, specify "ifi" as the (now-default) suffix. + + * main.c [USAGE] (info-file): use <filename>.ifi if <filename> + doesn't have a dotted suffix; otherwise use <filename>. + +Thu Jan 9 08:29:52 1992 Karl Berry (karl at hayley) + + * main.c (read_command_line): rename `scan_integer_list' to + `scan_unsigned_list'. + + * *.c: do not include global.h. + + * *.h: remove #pragma once. + +Wed Jan 8 15:28:00 1992 Karl Berry (karl at hayley) + + * update copyright messages. + + * change `allocate to `xmalloc', `reallocate' to `xrealloc', and + `string_copy' to `strdup'. + +Tue Jul 30 13:18:48 1991 Karl Berry (karl at ra.cs.umb.edu) + + * Version 0.3. + +Fri Jul 26 07:02:28 1991 Karl Berry (karl at hayley) + + * main.c (get_image_info): read the left and side bearings from + the IFI file, if present. + (bitmap_to_gf_char): use these numbers. + * image-char.h (image_char_type): new members `lsb' and `rsb'. + (IMAGE_CHAR_{L,R}SB): new accessor macros. + +Wed Jul 24 06:07:11 1991 Karl Berry (karl at hayley) + + * bitmap2.c (bitmap_concat): the height of the result is the + height of one, not twice that. + + * main.c (do_image_line): rename `concat_bitmaps' to + `bitmap_concat'. + * GNUmakefile (files): new file `bitmap2'. + + * main.c (do_image_line): return a boolean saying if we need + another image row. + (main): if `do_image_line' fails, read more of the image. + * extract.h (append_next_image_row): declare new routine. + * extract.c (append_next_image_row): define it. + (get_image_row): new routine. + (some_black_to_all_white_row): call `get_image_row'. + + * make-gsfont.ps (octal-value): prepend 0 to the character code. + + * extract.c (some_black_to_all_white_row): use xcalloc to initialize + `or_of_all', not allocate. We need it to be all zeroes + initially. + + * main.c, version.c: change `imgtogf' to `imagetofont'. + + * make-gsfont.ps: remove all the if-verbose's. + + * main.c: doc fix. + +Mon Jul 22 07:54:42 1991 Karl Berry (karl at hayley) + + * make-gsfont.ps (output-encoding): set /output-encoding to the + dictionary. + + * main.c: output ``imagetofont'' as our name in the GF file header, + instead of ``IMGtoGF''. + + * make-gsfont.ps (print-char-dimensions-if-verbose): lose the + `-if-verbose'. + + * make-gsfont.ps (octal-value): `get' the character name, don't + `load' it, so we find it in the right dictionary. + + * libpbm1.c: declare parms, external functions to avoid warnings. + +Sat Jun 15 09:50:46 1991 Karl Berry (karl at hayley) + + * input-*.c: change `checked_' to `x'. + +Thu Jun 6 07:29:06 1991 Karl Berry (karl at hayley) + + * All files: change to version 2 of the GPL. + +Sat Jun 1 15:18:11 1991 Kathy Hargreaves (kathy at hayley) + + * main.c (get_image_info): Now build an info filename if the + variable info_filename *is* NULL, not when it's not. + (USAGE): Deleted that resolution was set only for pbm input. + Stated that input-format is required and shortened comment. + +Fri May 31 14:30:01 1991 Kathy Hargreaves (kathy at hayley) + + * imgtogf: Moved directory to `imagetofont'. + + * GNUmakefile: Changed program name from `imgtogf' to `imagetofont'. + + * main.c (get_image_info): Make default image info file be + <fontname>.ifi instead of imginf.<fontname>. + + * main.[hc], input-*.[hc]: *_get_header now don't return a + header but rather modify the global header in main.c. Changed + all references to `[img, pbm]_header->' to `image_header.'. + + * main.c, image-char.[hc]: Replaced all instances of `img_char' + with `image_char'. + + * image-char.[hc]: Moved from img-char.[hc]. + + * main.h (image_header): Made this visible to the outside. + + * input-[pbm, img].c ([pbm, img]_get_header): Set h to + image_header in main.c. #include main.h. + + * main.c (read_command_line): Cast the assignment to + image_header.hres to type two_bytes. + + * image-header.h, input-*.[hc], main.[hc]: Changed `img-header.h' + to `image-header.h'. + + * main.c: Replaced all instances of `img_header*' with + `image_header*'. Moved `img_' and `pbm_' to the front of the + function names. + + * img-header.h: Moved to image_header.h and replaced all + instances of `img_header*' with `image_header*'. + + * input-img.[hc] (*_img_*): Moved `img_' to the front of the + variable names. Replaced instances of `img_header_type' with + `image_header_type'. + + * input-pbm.[hc] (*_pbm_*): Moved `pbm_' to the front of the + variable names. + + * extract.c, strips.c: (ptr_get_scanline): Removed `ptr_' from in + front of this function's name and replaced it with `image'. + Replaced instances of `img_header*' with `image_header*', if any. + + * main.h (ptr_open_input_file, ptr_close_input_file, ptr_get_header, + ptr_get_scanline): Removed `ptr_' from the front of all these + names and replaced it with `image'. Replaced `img_header_type' + with `image_header_type'. + + * main.c (ptr_open_input_file, ptr_close_input_file, ptr_get_header, + ptr_get_scanline): Moved and set all to NULL. + Removed `ptr_' from the front of all these names and replaced it + with `image'. + (read_command_line): Remove "img-input-format" from option + structure. + Removed variable need_resolutions, as don't need it. + Force them to specify the input format on the command line + rather than having a default. + +Wed May 29 16:19:57 1991 Kathy Hargreaves (kathy at hayley) + + * input-pbm.c (line_in_bytes): Deleted this global variable, as + don't need it. (pbm_readpbmrow reads right into line_in_bits in + get_pbm_scanline.) + + * pbm.h: Took out #include for types.h. + + * input-pbm.c (get_pbm_scanline): Check if at EOF before calling + pbm_readpbmrow. + + * libpbm2.c (pbm_readpbmrow): Restored to original; can test if at + EOF in the wrapper get_pbm_scanline. + Took out #include for types.h. + + * input-pbm.c (get_pbm_scanline): Hooked up to libpbm2.c routine. + + * main.c (read_command_line): Combined some options and changed + their names and their input. + Make input-format take an argument. + +Mon May 27 14:52:45 1991 Kathy Hargreaves (kathy at hayley) + + * main.c (read_commandline): If both resolutions are missing and + are required on the commandline, print that they both are, not + just that the horizontal one is. + + * bb-outline.c (is_outline_edge): Changed VALID_LOCATION to + BITMAP_VALID_PIXEL. + + * pbmplus.h: Commented out malloc, etc. declarations. + + * libpbm2.c (pbmreadpbmrow): Make it return a boolean instead of a + void, so will fit into our code. + Make it return false instead of an error message. + + * pbm.h (top): pbmplus.h is in the current directory, so take out + the `../' before it in the #include. + (pbmreadpbmrow): Make it return a boolean instead of a void, so + will fit into our code. + + * extract.c (top): Now #include input-pbm.h. + (some_black_to_all_white_row): Changed all instances of + get_img_scanline to get_scanline. + + * input-img.c (top): Now #include img-header.h. + (get_img_header): Got rid of variable format, as now put that in + the header. + + * main.c: (open_input_file, close_input_file, get_header, + get_scanline): Declared these pointers to functions so could set + them to a set of routines belonging to the type of input we're + using. Set them to .pbm input format routines as a default. + (font_name_extension): Added this static variable so could set + it when get read the input format on the command line. Set to + `.pbm' by default. + (main): Initialize img_header to all zeros so will know if the + user set them using the command line. + Changed call to open_img_input_file to open_input_file and + concat font_name_extension instead of ".img" for the argument. + Changed some comments. + Changed the call to get_img_header to get_header. + Changed the call to close_img_input_file to close_input_file. + (USAGE): Added horz-resolution, img-input-format, + pbm-input-format, and vert-resolution. + (read_command_line): Added boolean variable need_resolutions to + keep track of whether or not the user needs to input the + horizontal and vertical resolutions on the command line. + Added horz-resolution, img-input-format, pbm-input-format, and + vert-resolution to the option variable long_options. + If the argument is horz-resolution or vert-resolution, then set + the appropriate field in the header. + If the argument if img-input-format or pbm-input-format, the set + the input function pointers in main to the appropriate set of + functions that belong to the input format. If the argument is + the former, then set needs_resolution to false; if it's the latter, + set it to true. + If the user wants .pbm input format, then check that the header's + resolutions are set; if not, issue an error message and exit. + + * main.h (open_input_file, close_input_file, get_header, get_scanline): + Added these function pointer declarations so extract.c and strips.c + could use them. + + * strips.c (top): Now #include input-pbm.h. + (write_chars_as_strips): Changed the call to get_img_scanline to + a call to get_scanline. + +Sat Apr 13 17:13:51 1991 Karl Berry (karl at hayley) + + * main.c (get_image_info): use the libfile routines to read the + image info files. + + * main.c, input-img.c: new includes from the library + rearrangements. + +Mon Feb 25 16:32:45 1991 Karl Berry (karl at hayley) + + * main.c, strips.c: use `gf_...' instead of `..._gf_...'. + +Sun Feb 17 09:39:20 1991 Karl Berry (karl at hayley) + + * *.c: include config.h. + +Tue Jan 22 15:43:19 1991 Karl Berry (karl at hayley) + + * extract.[ch] (extract_subimage): move to kbase. + +Thu Jan 17 10:32:09 1991 Karl Berry (karl at hayley) + + * main.c (main): don't put the day of the week in the font comment. + +Tue Oct 9 09:07:02 1990 Karl Berry (karl at hayley) + + * main.c (scan_baseline_list): move to kbase. + (baseline_list): make a vector of ints, not unsigneds. + (main): test for the end of the baseline list being -1, not 0. + +Mon Oct 8 16:37:07 1990 Karl Berry (karl at hayley) + + * main.c: #include cmdline.h. + (read_command_line): call FINISH_COMMAND_LINE. + +Sun Sep 30 09:15:25 1990 Karl Berry (karl at hayley) + + * main.c (do_image_line): don't give a report when we read part of + the line, after all. + +Fri Sep 28 13:47:15 1990 Karl Berry (karl at hayley) + + * main.c (scan_integer_list): use strtok, instead of doing the + work ourselves. + +Sat Sep 22 06:16:49 1990 Karl Berry (karl at hayley) + + * main.c (output_chars): don't increment `current_char' if we've + already seen the box. + +Fri Sep 21 08:40:49 1990 Karl Berry (karl at hayley) + + * img-char.h (img_char_type): new element, `alternating'. + (IMG_CHAR_BB_ALTERNATING): macro to access it. + * main.c (get_image_info): if the bb count is negative, set + `alternating' (and make it positive). + (output_chars): handle the bounding boxes alternating. + + * main.c (do_image_line): give a progress report when we read part + of the line. + + * main.c (read_command_line): return NULL at the end; the POSIX + include files don't declare `exit' as volatile, more's the pity. + * bb-output.c (is_outline_edge): return false at the end, for the + same reason. + +Sun Sep 16 11:13:43 1990 Karl Berry (karl at hayley) + + * main.c: include "getopt.h" instead of <getopt.h>. + + * main.c (read_command_line): change call of PARSE_CHAR_CODE to + xparse_char_code. + + * main.c (main): make the default info filename `imginf.<name>', + not `imginfo.<name>'. + +Sat Sep 8 10:06:19 1990 Karl Berry (karl at hayley) + + * main.c (read_command_line): remove any suffix on the font name + before returning it. + + * main.c (read_command_line): use GET_RANGE. + + * main.c (get_image_info): use PARSE_CHAR_CODE to get the + character code from the file. + +Thu Sep 6 06:16:29 1990 Karl Berry (karl at hayley) + + * main.c (scan_integer_list): doc fix. + +Wed Sep 5 06:19:53 1990 Karl Berry (karl at hayley) + + * main.c (USAGE): doc fix in -range. + +Tue Sep 4 09:33:49 1990 Karl Berry (karl at hayley) + + * main.c (do_image_line): pass the current character to + output_chars, not the current box count. + + * extract.c (REPORT_SCANLINE): output to stderr instead of stdout. + + * main.c (get_image_info): always assign to the character code and + omit fields. + +Mon Sep 3 16:57:02 1990 Karl Berry (karl at hayley) + + * main.c (get_image_info): use NULL in subsequent calls to strtok. + + * main.c (get_encoding): replace with get_image_info; change + callers. + * img-char.[ch]: new files to support the data structure. + +Thu Aug 16 08:00:19 1990 Karl Berry (karl at hayley) + + * bb-outline.c (free_bounding_box_list): check if the list is + allocated before freeing it. + + * main.c (do_image_line): only say that we've read too many boxes + once. + +Wed Aug 8 08:06:53 1990 Karl Berry (karl at hayley) + + * main.c (read_command_line): change `encoding-file' to + `info-file'. + +Tue Aug 7 08:53:13 1990 Karl Berry (karl at hayley) + + * main.c (main): use the basename of the image filename to + construct the output name, instead of the full name. + + * main.c (USAGE): explain `-baselines' better. + +Thu Jul 26 06:54:56 1990 Karl Berry (karl at hayley) + + * extract.c (find_transitions): move to kbase. + +Tue Jul 24 13:09:38 1990 Karl Berry (karl at hayley) + + * main.c: don't include time.h. + +Thu Jul 19 15:22:29 1990 Karl Berry (karl at aten) + + * main.c (main): don't dereference baseline_list if it's null. + +Mon Jul 16 08:56:41 1990 Karl Berry (karl at hayley) + + * main.c (clean_bitmap): only print the `. ' if we're printing the + cleaning info. + +Sun Jul 15 08:27:52 1990 Karl Berry (karl at hayley) + + * bb-outline.c (append_bounding_box_list): don't change anything + if we're appending a list of length zero. + +Fri Jul 13 11:35:15 1990 Karl Berry (karl at hayley) + + * main.c (clean_bitmap): also potentially clean bounding boxes on + the bottom edge. + + * main.c (SET_EDGES): make coordinates relative to the bitmap of + the character. + + * main.c (clean_bitmap): only test the gray value for bounding + boxes that are on the edge. + + * main.c (output_chars): return the number of characters actually + output, omitting the ones out of range. + + * main.c (clean_bitmap): print gray values for the bounding boxes + if requested. + (read_command_line): new option, `print_clean_info'. + +Thu Jul 12 06:08:33 1990 Karl Berry (karl at hayley) + + * extract.c (some_black_to_all_white_row): don't output a newline + after reading the scanlines. + + * main.h: new file. + * extract.c: include it, remove declaration of verbose. + + * strips.[ch]: new files. + * main.c (main): cut the image into strips if requested. + (read_command_line): new option `strips'. + + * extract.c (find_transitions): new routine. + (some_black_to_all_white_row): call it, at the end, with a new + variable that is the logical or of all the rows we read. + (some_black_to_all_white_column, found_color_in_column): these + routines aren't needed any more. + * main.c (do_image_line): use the transition vector to set + `char_bitmap'. + + * main.c (scan_integer_list): increment length after checking the + exit condition. + + * main.c (do_image_line): new routine, consisting of a lot of the + main loop. + + * main.c (bitmap_to_gf_char): determine the baseline. + (read_command_line): new option `baselines' to set the baselines. + (scan_integer_list): new routine. + + * extract.c (found_color_in_column): start halfway down the + bitmap. + +Wed Jul 11 06:19:51 1990 Karl Berry (karl at hayley) + + * main.c (bitmap_to_gf_char): take another argument, the character + code, to consolidate where the GF char is set. + + * main.c (nchars_per_line): new static to say how many characters + we can report on per line; different for `print_guidelines' being + set and not set. + + * main.c (print_guidelines): new global. + (read_command_line): new option to set it. + (bitmap_to_gf_char): print the row numbers if it's set. + + * bb-outline.c (find_outline_bbs): take two additional arguments: + column numbers between which we don't look. + * bb-outline.h (find_outline_bbs): change the declaration. + * main.c (main), (clean_bitmap): change the calls. + + * bb-outline.c (append_bounding_box_list): reallocate based on the + element size, not the list size. + + * bb-outline.c (set_bounding_box_list_offset): replace by + `offset_bounding_box_list'. + (append_bb): don't offset the bounding boxes as they come in. + * bb-outline.h (set_bounding_box_list_offset): likewise. + * main.c (main): change call. + + * main.c (output_chars): set char_code to *next_code at the bottom + of the loop, and increment next_code. + +Tue Jul 10 06:10:05 1990 Karl Berry (karl at hayley) + + * bb-outline.c (set_bounding_box_list_offset): new routine. + (append_bb): move the bounding box to the right by the offset. + * bb-outline.h (set_bounding_box_list_offset): declare it. + + * main.c (get_char_code): rename to get_encoding, and read the + whole file. + + * bb-outline.h (init_bounding_box_list, append_bounding_box_list): + declare new routines. + bb-outline.c (same): define them. + +Mon Jul 9 08:10:20 1990 Karl Berry (karl at hayley) + + * main.c (main): don't split each line at white columns. + + * extract.c (clean_bitmap): set verbose to false before calling + find_outline_bbs. + + * main.c (get_char_code): make sure we actually find a character + code. + + * main.c (output_chars): don't extract or clean anything if the + character isn't within range. + + * extract.c (REPORT_SCANLINE): report every 100 scanlines. + + * main.c (output_chars): only give the status report if we + actually output the character. + +Sat Jul 7 10:43:18 1990 Karl Berry (karl at hayley) + + * bb-outline.c (append_bb): changed MAX_ROW, instead of MAX_COL. + + * main.c (clean_bitmap): new routine. + (output_gf_chars): call it. + * bb-outline.c (find_outline_bbs): take an additional parameter to + determine whether to look for inside outlines or not. + + * extract.c (REPORT_SCANLINE): report every 50 scanlines, instead + of every 10. + + * bb-outline.c (find_outline_bbs): look for outlines in + column-major order, instead of row-major. + diff --git a/imageto/GNUmakefile b/imageto/GNUmakefile new file mode 100644 index 0000000..2fcac49 --- /dev/null +++ b/imageto/GNUmakefile @@ -0,0 +1,43 @@ +# Makefile for image conversion program. +# +# Copyright (C) 1992 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +program = imageto + +c_and_h = bitmap2 extract ifi input-img input-pbm main \ + out-chars out-epsf out-strips +h_only = image-header +c_only = version + +libraries = gf pbm tfm + +include ../data/defs.make +include ../data/defsprog.make + +check: + cd /w/ourfonts/dingbats ; gftopk -v g111236.1200gf + + +dist:: + ln strips.tex $(distdir) + +install:: + $(INSTALL_DATA) strips.tex $(texinputdir)/strips.tex + +include M.depend + + diff --git a/imageto/README b/imageto/README new file mode 100644 index 0000000..31f228f --- /dev/null +++ b/imageto/README @@ -0,0 +1,46 @@ +This program extracts the characters from a big image to a GF font file. +Information about the image is given in an ``image font information'' +(IFI) file; that file format is described in the documentation. + +Currently the program can read the IMG files output by the Scan7650 +software, which works with the fancy Xerox 9750 scanner. (I think IMG +output is used by other GEM applications as well.) These images are +used by the Interleaf desktop publishing program. The image format +isn't proprietary, though -- it doesn't have any novel features. The +message below describes the format. + +It can also read PBM files. + + +Date: Thu, 5 Jul 90 11:22:55 EDT +From: rgw@hq.ileaf.com (Bob Watkins x5545) +To: karl@cs.umb.edu + +The image file consists of an OPSHEADER followed by an IMGHEADER, followed +by raster data. The version field of the OPSHEADER determines which of the +IMGHEADER structures to use. Most likely this will be 2, but there is a +chance that it might be 1 -- it depends on how recently the software for +that scanner was written. + +When reading the headers structures, it is a good idea to read them a field +at a time rather than all at once, since not all compilers use the same +structure padding conventions. + +The resolution numbers are in pixels/inch. Their primary purpose is to +allow TPS to scale the image to the correct physical dimensions when it is +pasted into the document. Other than that, they aren't that useful. + +The flags field should be zero -- there is a stupid marketing reason why it +is there at all, but I won't go into that. + +The w and h fields are the width and height of the image in pixels; the d +field is the depth in bits/pixel. The depth is either 1 or 8, depending on +whether the image is a lineart image or a contone image. + +The format field specifies the encoding of the raster data. A format of 0 +means that the data is uncompressed. The data itself is stored in scanline- +major order. In the case of lineart image, 8 pixels are packed into each +byte, with most-to-least significant order within the byte representing left- +to-right order in the image. A 0 bit corresponds to a black pixel, and a 1 +bit corresponds to a white pixel. If necessary, the scanlines are padded out +to the next 16-bit boundary. diff --git a/imageto/bitmap2.c b/imageto/bitmap2.c new file mode 100644 index 0000000..67d3d09 --- /dev/null +++ b/imageto/bitmap2.c @@ -0,0 +1,83 @@ +/* bitmap2.c: extra bitmap manipulation routines. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bitmap.h" + +#include "bitmap2.h" + + + +/* Put B2 to the right of B1, changing B1. For example, if B1 looked + like `A' and B2 like `B', the result would look like `AB'. The two + bitmaps must have the same number of rows. */ + +void +bitmap_concat (bitmap_type *b1, bitmap_type b2) +{ + bitmap_type new; + dimensions_type new_dimens; + unsigned row; + + assert (BITMAP_HEIGHT (*b1) == BITMAP_HEIGHT (b2)); + + DIMENSIONS_WIDTH (new_dimens) = BITMAP_WIDTH (*b1) + BITMAP_WIDTH (b2); + DIMENSIONS_HEIGHT (new_dimens) = BITMAP_HEIGHT (b2); + new = new_bitmap (new_dimens); + + /* Choice of `b2' or `b1' here is arbitrary, of course. */ + for (row = 0; row < BITMAP_HEIGHT (b2); row++) + { + one_byte *target1 = BITMAP_ROW (new, row); + one_byte *target2 = target1 + BITMAP_WIDTH (*b1); + + memcpy (target1, BITMAP_ROW (*b1, row), BITMAP_WIDTH (*b1)); + memcpy (target2, BITMAP_ROW (b2, row), BITMAP_WIDTH (b2)); + } + + free_bitmap (b1); + *b1 = new; +} + + +/* Return a bitmap which consists of B1, one blank row, and B2. The two + bitmaps must have the same width. (The blank row is necessary + because one blank row is removed the first time we call + some_black_to_all_white; consider the row consisting of just an `!'.)*/ + +bitmap_type +bitmap_vconcat (bitmap_type b1, bitmap_type b2) +{ + bitmap_type new; + dimensions_type new_dimens; + unsigned width = BITMAP_WIDTH (b1); + unsigned size1 = width * BITMAP_HEIGHT (b1); + unsigned size2 = width * BITMAP_HEIGHT (b2); + + assert (width == BITMAP_WIDTH (b2)); + + DIMENSIONS_WIDTH (new_dimens) = width; + DIMENSIONS_HEIGHT (new_dimens) = BITMAP_HEIGHT (b1) + BITMAP_HEIGHT (b2) + 1; + new = new_bitmap (new_dimens); + + memcpy (BITMAP_BITS (new), BITMAP_BITS (b1), size1); + memcpy (BITMAP_BITS (new) + size1 + width, BITMAP_BITS (b2), size2); + + return new; +} diff --git a/imageto/bitmap2.h b/imageto/bitmap2.h new file mode 100644 index 0000000..d643117 --- /dev/null +++ b/imageto/bitmap2.h @@ -0,0 +1,34 @@ +/* bitmap2.h: declare extra bitmap manipulation routines. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef BITMAP2_H +#define BITMAP2_H + +#include "bitmap.h" + + +/* Put B2 to the right of B1, changing B2. The two bitmaps must have + the same number of rows. */ +extern void bitmap_concat (bitmap_type *b1, bitmap_type b2); + + +/* Put B2 below B1. The two bitmaps must have the same number of + columns. */ +extern bitmap_type bitmap_vconcat (bitmap_type b1, bitmap_type b2); + +#endif /* not BITMAP2_H */ diff --git a/imageto/extract.c b/imageto/extract.c new file mode 100644 index 0000000..2482646 --- /dev/null +++ b/imageto/extract.c @@ -0,0 +1,239 @@ +/* extract.c: operations on bitmaps. These could be put in + lib/bitmap.c, but since they are not particularly common + operations, we may as well define them separately for now. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "bitmap.h" +#include "bounding-box.h" +#include "report.h" + +#include "bitmap2.h" +#include "extract.h" +#include "main.h" +#include "input-img.h" +#include "input-pbm.h" + +static bitmap_type *get_image_row (boolean, unsigned); +static unsigned *image_row_transitions (bitmap_type); + + + + +/* Combine the images in the bitmaps B1 and B2, returning the result in + B1. The relative position of the bitmaps is given by the bounding + boxes BB1 and BB2. We update the bounding box, also. */ + +void +combine_images (bitmap_type *b1, bitmap_type b2, + bounding_box_type *bb1, bounding_box_type bb2) +{ + int this_row, this_col; + bitmap_type whole_bitmap; + bounding_box_type whole_bb; + + /* If either of the bitmaps are nonexistent, we have nothing + significant to do. */ + if (BITMAP_BITS (b2) == NULL) + return; + if (BITMAP_BITS (*b1) == NULL) + { + *b1 = b2; + return; + } + + MIN_ROW (whole_bb) = MIN (MIN_ROW (*bb1), MIN_ROW (bb2)); + MAX_ROW (whole_bb) = MAX (MAX_ROW (*bb1), MAX_ROW (bb2)); + MIN_COL (whole_bb) = MIN (MIN_COL (*bb1), MIN_COL (bb2)); + MAX_COL (whole_bb) = MAX (MAX_COL (*bb1), MAX_COL (bb2)); + + whole_bitmap = new_bitmap (bb_to_dimensions (whole_bb)); + + /* First, copy the first image in. */ + for (this_row = MIN_ROW (*bb1); this_row <= MAX_ROW (*bb1); this_row++) + { + one_byte *target_row + = BITMAP_BITS (whole_bitmap) + + (this_row - MIN_ROW (whole_bb)) * BITMAP_WIDTH (whole_bitmap) + + MIN_COL (*bb1) - MIN_COL (whole_bb); + one_byte *source_row + = BITMAP_BITS (*b1) + + (this_row - MIN_ROW (*bb1)) * BITMAP_WIDTH (*b1); + + memcpy (target_row, source_row, BITMAP_WIDTH (*b1)); + } + + /* Put the second image in. */ + for (this_row = MIN_ROW (bb2); this_row <= MAX_ROW (bb2); this_row++) + for (this_col = MIN_COL (bb2); this_col < MAX_COL (bb2); this_col++) + { + if (BITMAP_PIXEL (b2, this_row - MIN_ROW (bb2), + this_col - MIN_COL (bb2)) == BLACK) + BITMAP_PIXEL (whole_bitmap, this_row - MIN_ROW (whole_bb), + this_col - MIN_COL (whole_bb)) + = BLACK; + } + + free_bitmap (b1); + *b1 = whole_bitmap; + *bb1 = whole_bb; +} + +/* Get the next image row of width WIDTH, ignoring leading white rows. + Return the columns at which there are black-to-white or white-black + transitions in TRANSITIONS. */ + +bitmap_type * +some_black_to_all_white_row (unsigned width, unsigned **transitions) +{ + bitmap_type *new = get_image_row (false, width); + if (new == NULL) + return NULL; + + *transitions = image_row_transitions (*new); + return new; +} + + +/* Get the next image row, including leading blank rows, concatenating + it below B with one blank row between. Otherwise like + `some_black_to_all_white_row'. */ + +bitmap_type * +append_next_image_row (bitmap_type b, unsigned width, unsigned **transitions) +{ + bitmap_type *new = XTALLOC1 (bitmap_type); + bitmap_type *next = get_image_row (true, width); + + if (next == NULL) + return NULL; + + *new = bitmap_vconcat (b, *next); + *transitions = image_row_transitions (*new); + return new; +} + +/* Because scanlines take a relatively long time to read, we will want + some kind of status report. */ + +#define REPORT_SCANLINE() if (++scanline_count % 100 == 0) REPORT (".") + +/* Read scanlines of width WIDTH from the image file until we get one + that has at least one black pixel in it (i.e., found part of a + character). Then read scanlines until we get one that is entirely + white. If KEEP_LEADING_WHITE_ROWS, then include the white rows we + found at the beginning in the returned bitmap; otherwise, it's just + the rows from the first-black to the one before the all-white. */ + +static bitmap_type * +get_image_row (boolean keep_leading_white_rows, unsigned width) +{ + static unsigned scanline_count = 0; + bitmap_type *bitmap; + boolean found_white_row; + one_byte *image; + unsigned rows_used, rows_allocated; + boolean found_black_row = false; + one_byte *scanline = xmalloc (width); + unsigned white_row_count = 0; + + while ((*image_get_scanline) (scanline)) + { + REPORT_SCANLINE (); + + found_black_row = memchr (scanline, BLACK, width) != NULL; + if (found_black_row) + break; + + white_row_count++; + } + + /* If reached end of the image before finding a black row, return NULL. */ + if (!found_black_row) + return NULL; + + /* Initialize the image to either the scanline with some black that we + just found, or to a bitmap with as many all-white rows as we've + seen, depending on `keep_leading_white_rows'. */ + rows_used = 1; + if (keep_leading_white_rows && white_row_count > 0) + { /* We clear the last row unnecessarily, since the next we do is + memcpy into it -- but that's better than realloc-ing. */ + image = xcalloc (white_row_count + 1, width); + rows_used += white_row_count; + memcpy (image + white_row_count * width, scanline, width); + free (scanline); + } + else + image = scanline; + + /* Found the row with a black pixel; now look for the all-white row. + When we start off here, we've allocated exactly as much space as + we've used so far. */ + rows_allocated = rows_used; + found_white_row = false; + while (!found_white_row) + { /* Since we only need one more row at a time, we don't need a + `while' loop here. */ + if (rows_used + 1 > rows_allocated) + { /* Perhaps doubling is the wrong thing to do here, as it may + waste quite a bit of memory. But it's simple. */ + rows_allocated += 100 /* ;<<= 1*/; + image = xrealloc (image, rows_allocated * width); + } + + scanline = image + rows_used * width; + if (!(*image_get_scanline) (scanline)) + break; + REPORT_SCANLINE (); + rows_used++; + found_white_row = memchr (scanline, BLACK, width) == NULL; + } + + bitmap = XTALLOC1 (bitmap_type); + BITMAP_WIDTH (*bitmap) = width; + BITMAP_HEIGHT (*bitmap) = rows_used; + BITMAP_BITS (*bitmap) = image; + + return bitmap; +} + + +/* Return a vector of the column numbers at which B changes from black + to white or white to black, terminated with an element which is B's + width + 1. */ + +static unsigned * +image_row_transitions (bitmap_type b) +{ + unsigned *transitions; + unsigned row, col; + unsigned width = BITMAP_WIDTH (b); + one_byte *or_of_all = xcalloc (width, 1); + + for (row = 0; row < BITMAP_HEIGHT (b); row++) + for (col = 0; col < width; col++) + or_of_all[col] |= BITMAP_PIXEL (b, row, col); + + /* We use `or_of_all' to find transitions: its ith column is 1 + if any row in the image had a black pixel at the ith column. */ + transitions = bitmap_find_transitions (or_of_all, width); + + return transitions; +} diff --git a/imageto/extract.h b/imageto/extract.h new file mode 100644 index 0000000..b1c29e3 --- /dev/null +++ b/imageto/extract.h @@ -0,0 +1,50 @@ +/* extract.h: declare operations on bitmaps. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef EXTRACT_H +#define EXTRACT_H + +#include "bitmap.h" +#include "bounding-box.h" + + +/* Return the segment in B starting after the column START that begins + with a column with at least one black pixel, to a column that is all + white (or the end of the bitmap). If no such segment is found, + return NULL. */ +extern bitmap_type *some_black_to_all_white_column (bitmap_type b); + +/* Read scanlines of width WIDTH (in pixels) from the input file until + we find a segment starting with a row with at least one black pixel, + and ending with a row that is all white (or the end of the file). If + no such segment is found, return NULL. In TRANSITIONS we return the + column numbers where white changes to black or black to white. The + first transition is black-to-white. */ +extern bitmap_type *some_black_to_all_white_row (unsigned width, + unsigned **transitions); + +/* Like `some_black_to_all_white_row', except appends both the white + rows and then the black ones to B. */ +extern bitmap_type *append_next_image_row + (bitmap_type b, unsigned width, unsigned **transitions); + +/* Combine the bitmaps B1 and B2 based on the bounding boxes, returning + the result in B1. Also combine the bounding boxes. */ +extern void combine_images (bitmap_type *b1, bitmap_type b2, + bounding_box_type *, bounding_box_type); +#endif /* not EXTRACT_H */ diff --git a/imageto/ifi.c b/imageto/ifi.c new file mode 100644 index 0000000..45d6b4c --- /dev/null +++ b/imageto/ifi.c @@ -0,0 +1,196 @@ +/* ifi.c: read an IFI file. */ + +#include "config.h" + +#include "encoding.h" +#include "libfile.h" + +#include "ifi.h" +#include "main.h" + + +/* The name of the encoding file specified by the user, and the + structure we parse it into. (-encoding) */ +string encoding_name = NULL; + +/* The name of the IFI file. (-ifi-file) */ +string ifi_filename = NULL; + + +static void append_image_char (image_char_list_type *l, image_char_type c); +static image_char_list_type new_image_char_list (void); + +/* Read the IFI file `ifi_filename' (or construct the IFI filename from + `input_name'), which gives us information about the image we are + going to read. + + See the documentation for full details and examples of IFI files. + Here we just sketch the bare bones. + + Each (non-blank, non-comment) line in this file represents a + ``character'' in the image, and has one to five entries, separated by + spaces and/or tabs. Comments start with `%' and continue to the end + of the line. + + The first entry represents the character code. See the documentation + for the various forms of charcodes. We also allow `.notdef', meaning + the ``character'' should not be output in the font. + + The second entry, if it exists, is an adjustment to the + baseline. We move the baseline down for negative numbers, and up + for positive ones. Default is zero. + + The third entry, if it exists, is the number of bounding boxes that + comprise this character. If it is negative, the bounding boxes + are not consecutive in the image; instead, they alternate with + bounding boxes for some other character. + + The fourth and fifth entries, if they exist, are the left and right + side bearings, respectively. */ + +image_char_list_type +read_ifi_file (unsigned *total_count) +{ + string line; + int bb_count; + encoding_info_type *encoding_info; + int n = 0; + image_char_list_type image_char_list = new_image_char_list (); + + if (encoding_name) + { + encoding_info = XTALLOC1 (encoding_info_type); + *encoding_info = read_encoding_file (encoding_name); + } + else + encoding_info = NULL; + + if (!ifi_filename) + ifi_filename = make_suffix (input_name, "ifi"); + + libfile_start (ifi_filename, "ifi"); + + *total_count = 0; + + while ((line = libfile_line ()) != NULL) + { + image_char_type c; + string baseline_adjust_str, bb_count_str, charname; + string lsb_str, rsb_str; + string save_line = line; /* So we can free it. */ + + /* The character name. */ + charname = strtok (line, " \t"); + + /* `libfile_line' should never return an empty line. */ + assert (charname != NULL); + + if (STREQ (charname, ".notdef")) + IMAGE_CHAR_OMIT (c) = true; + else + { + if (encoding_info) + n = encoding_number (*encoding_info, charname); + /* Otherwise, start n at 0. */ + + if (n == -1) + { + LIBFILE_WARN2 ("Character `%s' undefined in encoding `%s'", + charname, ENCODING_SCHEME_NAME (*encoding_info)); + IMAGE_CHAR_OMIT (c) = true; + } + else + { + IMAGE_CHARCODE (c) = n++; + IMAGE_CHARNAME (c) = xstrdup (charname); + IMAGE_CHAR_OMIT (c) = false; + } + } + + /* The baseline adjustment. */ + baseline_adjust_str = strtok (NULL, " \t"); + IMAGE_CHAR_BASELINE_ADJUST (c) + = baseline_adjust_str == NULL ? 0 : atoi (baseline_adjust_str); + + /* The bounding box count. */ + bb_count_str = strtok (NULL, " \t"); + bb_count = bb_count_str == NULL ? 1 : atoi (bb_count_str); + + if (bb_count < 0) + { + IMAGE_CHAR_BB_COUNT (c) = -bb_count; + IMAGE_CHAR_BB_ALTERNATING (c) = true; + } + else + { + IMAGE_CHAR_BB_COUNT (c) = bb_count; + IMAGE_CHAR_BB_ALTERNATING (c) = false; + } + + /* The left side bearing. */ + lsb_str = strtok (NULL, " \t"); + IMAGE_CHAR_LSB (c) = lsb_str == NULL ? 0 : atoi (lsb_str); + + /* The right side bearing. */ + rsb_str = strtok (NULL, " \t"); + IMAGE_CHAR_RSB (c) = rsb_str == NULL ? 0 : atoi (rsb_str); + + *total_count += IMAGE_CHAR_BB_COUNT (c); + append_image_char (&image_char_list, c); + free (save_line); + } + + libfile_close (); + if (encoding_info) + free (encoding_info); + + return image_char_list; +} + +/* Return an initialized, empty list. */ + +static image_char_list_type +new_image_char_list () +{ + image_char_list_type l; + + IMAGE_CHAR_LIST_LENGTH (l) = 0; + IMAGE_CHAR_LIST_DATA (l) = NULL; + + return l; +} + + +/* Append the character C to the list L. */ + +void +append_image_char (image_char_list_type *l, image_char_type c) +{ + IMAGE_CHAR_LIST_LENGTH (*l)++; + IMAGE_CHAR_LIST_DATA (*l) + = xrealloc (IMAGE_CHAR_LIST_DATA (*l), + IMAGE_CHAR_LIST_LENGTH (*l) * sizeof (image_char_type)); + IMAGE_CHAR (*l, IMAGE_CHAR_LIST_LENGTH (*l) - 1) = c; +} + + +/* Return false if the box BOX_COUNT boxes beyond FIRST_CHAR in LIST + is in the middle of a character, true otherwise. To do this, we + add up all the box counts for characters starting at FIRST_CHAR, + until we see where we land. */ + +boolean +box_at_char_boundary_p (image_char_list_type list, unsigned first_char, + unsigned box_count) +{ + unsigned count = 0; + + while (count < box_count && first_char < IMAGE_CHAR_LIST_LENGTH (list)) + { + image_char_type c = IMAGE_CHAR (list, first_char); + count += IMAGE_CHAR_BB_COUNT (c); + first_char++; + } + + return count == box_count; +} diff --git a/imageto/ifi.h b/imageto/ifi.h new file mode 100644 index 0000000..e013d26 --- /dev/null +++ b/imageto/ifi.h @@ -0,0 +1,91 @@ +/* ifi.h: information about the characters in the image. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef IFI_H +#define IFI_H + +#include <kpathsea/types.h> + + +/* See ifi.c. */ +extern string encoding_name, ifi_filename; + + +/* A single character in the image. */ +typedef struct +{ + charcode_type charcode; + string charname; + boolean omit; + int baseline_adjust; + unsigned bb_count; + boolean alternating; + int lsb, rsb; +} image_char_type; + +/* The character code. This is garbage if `omit' is true. */ +#define IMAGE_CHARCODE(c) ((c).charcode) + +/* The character name. */ +#define IMAGE_CHARNAME(c) ((c).charname) + +/* Says whether this character should be output. */ +#define IMAGE_CHAR_OMIT(c) ((c).omit) + +/* How far the baseline should be moved from the row's baseline. */ +#define IMAGE_CHAR_BASELINE_ADJUST(c) ((c).baseline_adjust) + +/* How many bounding boxes comprise this character. */ +#define IMAGE_CHAR_BB_COUNT(c) ((c).bb_count) + +/* Says whether the bounding boxes in this character are consecutive + (the usual case) or alternate. */ +#define IMAGE_CHAR_BB_ALTERNATING(c) ((c).alternating) + +/* The side bearings. */ +#define IMAGE_CHAR_LSB(c) ((c).lsb) +#define IMAGE_CHAR_RSB(c) ((c).rsb) + + +/* A list of the above. */ +typedef struct +{ + image_char_type *data; + unsigned length; +} image_char_list_type; + +/* The Nth element of the list L. */ +#define IMAGE_CHAR(l, n) ((l).data[n]) + +/* The list as a whole. */ +#define IMAGE_CHAR_LIST_DATA(l) ((l).data) + +/* The length of the list. */ +#define IMAGE_CHAR_LIST_LENGTH(l) ((l).length) + + +/* Read the IFI file IFI_FILENAME. Return the total number of characters + read in TOTAL_COUNT. */ +extern image_char_list_type read_ifi_file (unsigned *total_count); + +/* Return false if the box BOX_COUNT boxes beyond FIRST_CHAR in LIST + is in the middle of a character, true otherwise. */ +extern boolean box_at_char_boundary_p + (image_char_list_type list, unsigned first_char, unsigned box_count); + +#endif /* not IFI_H */ diff --git a/imageto/image-char.c b/imageto/image-char.c new file mode 100644 index 0000000..2f9fc56 --- /dev/null +++ b/imageto/image-char.c @@ -0,0 +1,69 @@ +/* image-char.c: manipulate information about the characters in the image. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "image-char.h" + + +/* Return an initialized, empty list. */ +image_char_list_type +new_image_char_list () +{ + image_char_list_type l; + + IMAGE_CHAR_LIST_LENGTH (l) = 0; + IMAGE_CHAR_LIST_DATA (l) = NULL; + + return l; +} + + +/* Append the character C to the list L. */ + +void +append_image_char (image_char_list_type *l, image_char_type c) +{ + IMAGE_CHAR_LIST_LENGTH (*l)++; + IMAGE_CHAR_LIST_DATA (*l) + = xrealloc (IMAGE_CHAR_LIST_DATA (*l), + IMAGE_CHAR_LIST_LENGTH (*l) * sizeof (image_char_type)); + IMAGE_CHAR (*l, IMAGE_CHAR_LIST_LENGTH (*l) - 1) = c; +} + + +/* Return false if the box BOX_COUNT boxes beyond CURRENT_CHAR in LIST + is in the middle of a character, true otherwise. To do this, we must + add up all the box counts for characters starting at FIRST_CHAR, + until we see where we land. */ + +boolean +box_at_char_boundary_p (image_char_list_type list, unsigned current_char, + unsigned box_count) +{ + unsigned count = 0; + + while (count < box_count && current_char < IMAGE_CHAR_LIST_LENGTH (list)) + { + image_char_type c = IMAGE_CHAR (list, current_char); + count += IMAGE_CHAR_BB_COUNT (c); + current_char++; + } + + return count == box_count; +} diff --git a/imageto/image-char.h b/imageto/image-char.h new file mode 100644 index 0000000..c1b2880 --- /dev/null +++ b/imageto/image-char.h @@ -0,0 +1,89 @@ +/* image-char.h: information about the characters in the image. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef IMAGE_CHAR_H +#define IMAGE_CHAR_H + +#include "types.h" + + +/* A single character in the image. */ +typedef struct +{ + charcode_type charcode; + string charname; + boolean omit; + int baseline_adjust; + unsigned bb_count; + boolean alternating; + int lsb, rsb; +} image_char_type; + +/* The character code. This is garbage if `omit' is true. */ +#define IMAGE_CHARCODE(c) ((c).charcode) + +/* The character name. */ +#define IMAGE_CHARNAME(c) ((c).charname) + +/* Says whether this character should be output. */ +#define IMAGE_CHAR_OMIT(c) ((c).omit) + +/* How far the baseline should be moved from the row's baseline. */ +#define IMAGE_CHAR_BASELINE_ADJUST(c) ((c).baseline_adjust) + +/* How many bounding boxes comprise this character. */ +#define IMAGE_CHAR_BB_COUNT(c) ((c).bb_count) + +/* Says whether the bounding boxes in this character are consecutive + (the usual case) or alternate. */ +#define IMAGE_CHAR_BB_ALTERNATING(c) ((c).alternating) + +/* The side bearings. */ +#define IMAGE_CHAR_LSB(c) ((c).lsb) +#define IMAGE_CHAR_RSB(c) ((c).rsb) + + +/* A list of the above. */ +typedef struct +{ + image_char_type *data; + unsigned length; +} image_char_list_type; + +/* The Nth element of the list L. */ +#define IMAGE_CHAR(l, n) ((l).data[n]) + +/* The list as a whole. */ +#define IMAGE_CHAR_LIST_DATA(l) ((l).data) + +/* The length of the list. */ +#define IMAGE_CHAR_LIST_LENGTH(l) ((l).length) + + +/* Return an empty list. */ +extern image_char_list_type new_image_char_list (void); + +/* Append the character C to the list L. */ +extern void append_image_char (image_char_list_type *l, image_char_type c); + +/* Return false if the box BOX_COUNT boxes beyond FIRST_CHAR in LIST + is in the middle of a character, true otherwise. */ +extern boolean box_at_char_boundary_p + (image_char_list_type list, unsigned first_char, unsigned box_count); + +#endif /* not IMAGE_CHAR_H */ diff --git a/imageto/image-header.h b/imageto/image-header.h new file mode 100644 index 0000000..9d48a60 --- /dev/null +++ b/imageto/image-header.h @@ -0,0 +1,35 @@ +/* image-header.h: declarations for a generic image header. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef IMAGE_HEADER_H +#define IMAGE_HEADER_H + +#include <kpathsea/types.h> + +/* The important general information about the image data. + See `get_{img,pbm}_header' for the full details of the headers for + the particular formats. */ +typedef struct +{ + two_bytes hres, vres; /* In pixels per inch. */ + two_bytes width, height; /* In bits. */ + two_bytes depth; + unsigned format; /* (for pbm) Whether packed or not. */ +} image_header_type; + +#endif /* not IMAGE_HEADER_H */ diff --git a/imageto/input-img.c b/imageto/input-img.c new file mode 100644 index 0000000..1930350 --- /dev/null +++ b/imageto/input-img.c @@ -0,0 +1,159 @@ +/* input-img.c: read Interleaf .img files. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "file-input.h" + +#include "main.h" +#include "image-header.h" +#include "input-img.h" + + +/* Where the input comes from. */ +static FILE *img_input_file; +static string img_input_filename; + +/* What we'll read the raw data for each scanline into. */ +static one_byte *line_in_bytes; + +/* How big `line_in_bytes' is, in both bytes and pixels. */ +static unsigned byte_width; +static unsigned pixel_width; +static unsigned pixel_depth; + +/* Macros for convenient input. The routines are defined in kbase. */ +#define IMG_MATCH_BYTE(v) match_byte (v, img_input_file, img_input_filename) + +#define IMG_GET_TWO() get_two (img_input_file, img_input_filename) +#define IMG_GET_FOUR() get_four (img_input_file, img_input_filename) + +/* Only one file can be open at a time. We do no path searching. If + FILENAME can't be opened, we quit. */ + +void +img_open_input_file (string filename) +{ + assert (img_input_file == NULL); + + img_input_file = xfopen (filename, "r"); + img_input_filename = filename; +} + + +/* Close the input file. If it hasn't been opened, we quit. */ + +void +img_close_input_file () +{ + assert (img_input_file != NULL); + + xfclose (img_input_file, img_input_filename); + img_input_file = NULL; +} + +/* Read the header information. + Modifies the global image_header in main.c. */ + +void +img_get_header () +{ + unsigned flags; + unsigned pixels_per_short; + unsigned short_width; + + /* The ``magic number''. */ + IMG_MATCH_BYTE (0211); + IMG_MATCH_BYTE ('O'); + IMG_MATCH_BYTE ('P'); + IMG_MATCH_BYTE ('S'); + + /* The version number. */ + IMG_MATCH_BYTE (0); + IMG_MATCH_BYTE (2); + + image_header.hres = IMG_GET_TWO (); + image_header.vres = IMG_GET_TWO (); + flags = IMG_GET_FOUR (); + if (flags != 0) + FATAL1 ("img_get_header: Expected flags to be zero, not %u", flags); + image_header.width = IMG_GET_TWO (); + image_header.height = IMG_GET_TWO (); + pixel_depth = image_header.depth = IMG_GET_TWO (); + image_header.format = IMG_GET_TWO (); + if (image_header.format != 0) + FATAL1 ("img_get_header: Expected format to be zero, not %u", + image_header.format); + + /* Allocate the space that we will read into (since that space is the + same from scanline to scanline). The width is derived from the + header information, which must already have been read. + Specifically, the width in the header is given in bits. Each + scanline is padded to a 16-bit boundary. For example, suppose the + header width = 1516, that is 94.75 shorts; we round up to 95, + thus getting a scanline width of 1520 bits, or 190 bytes. (For + monochrome images.) */ + pixel_width = image_header.width; + pixels_per_short = 16 / image_header.depth; + short_width = pixel_width / pixels_per_short + + (pixel_width % pixels_per_short != 0); + byte_width = short_width * 2; + line_in_bytes = xmalloc (byte_width); +} + +/* Read one scanline of the image, returning each bit of the scanline in + a separate byte. We may use the `line_in_bytes' variable, allocated in + `img_get_header' just above, to read into. */ + +boolean +img_get_scanline (one_byte *line_in_pixels) +{ + /* No point in using temp. buffer if pixels and bytes are the same. */ + if (fread (line_in_bytes, byte_width, 1, img_input_file) != 1) + { + if (feof (img_input_file)) + return false; + else + FATAL1 ("img_get_scanline: fread of %u bytes failed", byte_width); + } + + /* Don't handle cases other than depth 1 or 8. */ + if (pixel_depth == 1) + { + unsigned this_bit, this_byte, mask; + for (this_bit = 0, this_byte = 0, mask = 0x80; + this_bit < pixel_width; this_bit++) + { + /* Somewhere along the line, black and white got reversed. */ + line_in_pixels[this_bit] = (line_in_bytes[this_byte] & mask) == 0; + if (this_bit % 8 == 0) + { + this_byte = this_bit / 8; + mask = 0x80; + } + else + mask >>= 1; + } + } + else + memcpy (line_in_pixels, line_in_bytes, byte_width); + + print_scanline (line_in_pixels, pixel_width); + + return true; +} diff --git a/imageto/input-img.h b/imageto/input-img.h new file mode 100644 index 0000000..afbaaeb --- /dev/null +++ b/imageto/input-img.h @@ -0,0 +1,43 @@ +/* input-img.h: declarations for reading an IMG file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef INPUT_IMG_H +#define INPUT_IMG_H + +#include <kpathsea/types.h> +#include "image-header.h" + + +/* Prepare to read FILENAME. */ +extern void img_open_input_file (string filename); + +/* Close up gracefully. */ +extern void img_close_input_file (void); + + +/* Read the header. */ +extern void img_get_header (void); + + +/* Read a single scanline into P. P must point to a large-enough block + for one entire scanline (the width of the image is given in the + header). If at the end of the input file, returns false, else + returns true. */ +extern boolean img_get_scanline (one_byte *p); + +#endif /* not INPUT_IMG_H */ diff --git a/imageto/input-pbm.c b/imageto/input-pbm.c new file mode 100644 index 0000000..9fe47ba --- /dev/null +++ b/imageto/input-pbm.c @@ -0,0 +1,88 @@ +/* input-pbm.c: read PBM files. + +Copyright (C) 1990, 1991, 19 19ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "file-input.h" + +#include "main.h" +#include "image-header.h" +#include "input-pbm.h" + +#include "pbmplus.h" +#include "pbm.h" + + +/* Where the input comes from. */ +static FILE *pbm_input_file; +static string pbm_input_filename; + + + +/* Only one file can be open at a time. We do no path searching. If + FILENAME can't be opened, we quit. */ + +void +pbm_open_input_file (string filename) +{ + assert (pbm_input_file == NULL); + + pbm_input_file = xfopen (filename, "r"); + pbm_input_filename = filename; +} + + +/* Close the input file. If it hasn't been opened, we quit. */ + +void +pbm_close_input_file () +{ + assert (pbm_input_file != NULL); + + xfclose (pbm_input_file, pbm_input_filename); + pbm_input_file = NULL; +} + + + +/* Read the header information. + Modifies the global image_header in main.c. */ + +void +pbm_get_header () +{ + int width, height, format; + + pbm_readpbminit (pbm_input_file, &width, &height, &format); + image_header.width = (two_bytes) width; + image_header.height = (two_bytes) height; + image_header.depth = 0; + image_header.format = (two_bytes) format; +} + + + +/* Read one scanline of the image. */ + +boolean +pbm_get_scanline (one_byte *line_in_bits) +{ + int c = getc (pbm_input_file); + + if (c == EOF) + return false; + + ungetc (c, pbm_input_file); + pbm_readpbmrow (pbm_input_file, line_in_bits, image_header.width, + image_header.format); + + print_scanline (line_in_bits, image_header.width); + return true; +} diff --git a/imageto/input-pbm.h b/imageto/input-pbm.h new file mode 100644 index 0000000..522d2de --- /dev/null +++ b/imageto/input-pbm.h @@ -0,0 +1,44 @@ +/* input-pbm.h: declarations for reading an PBM file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef INPUT_PBM_H +#define INPUT_PBM_H + +#include <kpathsea/types.h> +#include "image-header.h" + + +/* Prepare to read FILENAME. */ +extern void pbm_open_input_file (string filename); + +/* Close up gracefully. */ +extern void pbm_close_input_file (void); + + +/* Read the header. */ +extern void pbm_get_header (void); + + +/* Read a single scanline into P. P must point to a large-enough block + for one entire scanline (the width of the image is given in the + header). If at the end of the input file, returns false, else + returns true. */ +extern boolean pbm_get_scanline (one_byte *p); + +#endif /* not INPUT_PBM_H */ + diff --git a/imageto/main.c b/imageto/main.c new file mode 100644 index 0000000..e3215c8 --- /dev/null +++ b/imageto/main.c @@ -0,0 +1,416 @@ +/* imageto -- convert a scanned image. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/concatn.h> + +#define CMDLINE_NO_DPI /* It's not in the input filename. */ +#include "cmdline.h" +#include "encoding.h" /* For `DEFAULT_ENCODING'. */ +#include "getopt.h" +#include "gf.h" +#include "report.h" + +#include "ifi.h" /* For `encoding_name'. */ +#include "image-header.h" +#include "input-img.h" +#include "input-pbm.h" +#include "main.h" +#include "out-chars.h" +#include "out-epsf.h" +#include "out-strips.h" + + +/* General information about the image. Set by the input routines. */ +image_header_type image_header; + +/* Pointers to functions based on input format. (-input-format) */ +void (*image_open_input_file) (string) = NULL; +void (*image_close_input_file) (void) = NULL; +void (*image_get_header) (void) = NULL; +boolean (*image_get_scanline) (one_byte *) = NULL; + +/* The filename for the input image. */ +string input_name; + +/* Show every scanline on the terminal as we read it? (-trace-scanlines) */ +boolean trace_scanlines = false; + +/* Private variables. */ + +/* The design size of the font we're creating. (-designsize) */ +static real design_size = 10.0; + +/* The suffix for the image file. */ +static string input_extension; + +/* If set, write an EPSF file. (-epsf) */ +static boolean output_epsf = false; + +/* The name of the file we're going to write. (-output-file) */ +string output_name; + +/* If set, make each ``character'' a (more or less) constant number of + scanlines. (-strips) */ +static boolean do_strips = false; + + +static string read_command_line (int, string[]); +static void set_img_input_format (void); +static void set_input_format (string); +static void set_pbm_input_format (void); + +/* We have three different strategies for processing the image: + 1) (normal) analyze the image and write out the ``true'' characters, + 2) (-strips) takes a constant number of scanlines as each character, + 3) (-epsf) write out the image as an Encapsulated PostScript file. + + The output name is, correspondingly, constructed differently: + 1) if `output_name' was supplied, and has a suffix, that's it. + 2) if `output_name' was supplied, but has no suffix, append `.eps' + if we're doing EPSF, else append `<suffix>.<dpi>gf', where + <suffix> is + a) `sp', if we are doing strips; + b) the design size, if not. + 3) if `output_name' was not supplied, use the basename of the input + filename extended as in #2. + */ + +int +main (int argc, string argv[]) +{ + boolean writing_gf; + + kpse_set_progname (argv[0]); + + input_name = read_command_line (argc, argv); + writing_gf = !output_epsf; + + set_input_format (input_name); + + /* If the input format is PBM, then they must also tell us the dpi. */ + if (image_open_input_file == pbm_open_input_file + && image_header.hres == 0) + { + fprintf (stderr, "If you use PBM format, you must supply the dpi.\n"); + fprintf (stderr, "For more information, use ``-help''.\n"); + exit (1); + } + + /* Open the main input file. */ + (*image_open_input_file) (extend_filename (input_name, input_extension)); + + /* We need the horizontal resolution before we can make the GF name, + so, at least for IMG input, have to read the header. */ + (*image_get_header) (); + + /* If the user didn't give an output name, use the input name. */ + if (output_name == NULL) + output_name = remove_suffix (basename (input_name)); + + /* If they didn't give an output name with a suffix, use ours. */ + if (find_suffix (output_name) == NULL) + { + if (writing_gf) + { + char dpi[MAX_INT_LENGTH + 1]; + string suffix = do_strips ? "sp" : itoa ((unsigned) design_size); + + sprintf (dpi, "%u", image_header.hres); + output_name = concatn (output_name, suffix, ".", dpi, "gf", NULL); + } + else if (output_epsf) + output_name = concat (output_name, ".eps"); + else + abort (); /* Should never happen. */ + } + + /* If necessary, open the GF file. */ + if (writing_gf) + { + if (!gf_open_output_file (output_name)) + FATAL_PERROR (output_name); + + /* Identify ourselves in the GF comment. */ + gf_put_preamble (concat ("imageto output ", now () + 4)); + } + + /* Do the real work, whichever the user wants. */ + if (do_strips) + { /* The design size is irrelevant when we're creating strips, + but it should be pretty large, lest the relative dimensions in + the TFM file get too big. */ + design_size = 100.0; + write_chars_as_strips (image_header, design_size); + } + else if (output_epsf) + write_epsf (output_name, image_header); + else + write_image_chars (image_header, design_size); + + /* Clean up. */ + if (verbose) + REPORT ("\n"); + + if (writing_gf) + { + /* We've read all the characters we're supposed to (or else the whole + image). Finish up the font. */ + gf_put_postamble (real_to_fix (design_size), + (real) image_header.hres, (real) image_header.vres); + gf_close_output_file (); + } + + (*image_close_input_file) (); + + return 0; +} + +/* We are semi-clever about printing this, for the sake of huge images. */ + +void +print_scanline (one_byte line[], unsigned width) +{ + static unsigned scanline_count = 0; + + if (trace_scanlines) + { + printf ("%7d:", scanline_count++); + + /* If the line is entirely white, don't print anything. */ + if (memchr (line, BLACK, width)) + { + unsigned c; + + for (c = 0; c < width; c++) + { /* Compress eight consecutive spaces to a tab, if we're at + the beginning of a tab mark. This handles the usual + case, although we could do still better. */ + if (c % 8 == 0 && c + 7 < width + && memchr (line + c, BLACK, 8) == NULL) + { + putchar ('\t'); + c += 7; + } + else + putchar (line[c] ? '*' : ' '); + } + } + + putchar ('\n'); + } +} + +/* Reading the options. */ + +/* This is defined in version.c. */ +extern string version_string; + +#define USAGE "Options: +<font_name> should be a base filename, e.g., `ggmr'. (More properly, it +is an <image_name>, not a <font_name>.)" \ + GETOPT_USAGE \ +"baselines <row1>,<row2>,...: define the baselines for each image row. + The baseline of the first image row is taken to be scanline <row1>, etc. +designsize <real>: set the designsize of the font to <real>; default is 10.0. +dpi <unsigned>: resolution (required for pbm input). +encoding <filename>: read ligature and other encoding information + from `<filename>.enc'; the default is to assign successive character codes. +epsf: write the image as an Encapsulated PostScript file, instead of a + bitmap font. +help: print this message. +ifi-file <filename>: use <filename>.ifi (if <filename doesn't have a + suffix; otherwise use <filename>) for the IFI filename; default is + `<font_name>.ifi'. +input-format <format>: specify format of input image; <format> must be + one of `pbm' or `img'. +nchars <unsigned>: only write the first <unsigned> (approximately) + characters to the font; default is infinity. +output-file <filename>: write to <filename> if <filename> has a suffix. + If <filename> doesn't have a suffix, then if writing strips, write to + <filename>sp.<dpi>gf and to <filename>.<dpi>gf if not. By default, + use <font_name> for <filename>. +print-clean-info: print gray values for the bounding boxes that are + considered for cleaning. This implies `-verbose'. +print-guidelines: print the numbers of the top and bottom rows (in that + order) of each character. This implies `-verbose'. +range <char1>-<char2>: only output characters between <char1> and + <char2>, inclusive. +strips: take a constant number of scanlines as each character, + instead of using an IFI file to analyze the image. +trace-scanlines: show every scanline as we read it. +verbose: output progress reports. +version: print the version number of this program. +" + +static string +read_command_line (int argc, string argv[]) +{ + int g; /* `getopt' return code. */ + int option_index; + boolean printed_version = false; + struct option long_options[] + = { { "baselines", 1, 0, 0 }, + { "designsize", 1, 0, 0 }, + { "encoding", 1, 0, 0 }, + { "epsf", 0, (int *) &output_epsf, 1 }, + { "help", 0, 0, 0 }, + { "dpi", 1, 0, 0 }, + { "ifi-file", 1, 0, 0 }, + { "nchars", 1, 0, 0 }, + { "input-format", 1, 0, 0 }, + { "output-file", 1, 0, 0 }, + { "print-clean-info", 0, (int *) &print_clean_info, 1 }, + { "print-guidelines", 0, (int *) &print_guidelines, 1 }, + { "range", 1, 0, 0 }, + { "strips", 0, (int *) &do_strips, 1 }, + { "trace-scanlines", 0, (int *) &trace_scanlines, 1 }, + { "verbose", 0, (int *) &verbose, 1 }, + { "version", 0, (int *) &printed_version, 1 }, + { 0, 0, 0, 0 } }; + + while (true) + { + g = getopt_long_only (argc, argv, "", long_options, &option_index); + + if (g == EOF) + break; + + if (g == '?') + exit (1); /* Unknown option. */ + + assert (g == 0); /* We have no short option names. */ + + if (ARGUMENT_IS ("baselines")) + baseline_list = scan_unsigned_list (optarg); + + else if (ARGUMENT_IS ("designsize")) + design_size = atof (optarg); + + else if (ARGUMENT_IS ("dpi")) + { + image_header.hres = (two_bytes) atou (optarg); + image_header.vres = image_header.hres; + } + + else if (ARGUMENT_IS ("encoding")) + encoding_name = optarg; + + else if (ARGUMENT_IS ("help")) + { + fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]); + fprintf (stderr, USAGE); + exit (0); + } + + else if (ARGUMENT_IS ("ifi-file")) + ifi_filename = optarg; + + else if (ARGUMENT_IS ("input-format")) + { + if (STREQ ("pbm", optarg)) + set_pbm_input_format (); + else if (STREQ ("img", optarg)) + set_img_input_format (); + else + FATAL1 ("imageto: Unknown input format `%s'; expected one of \ +`img' or `pbm'", optarg); + } + + else if (ARGUMENT_IS ("nchars")) + nchars_wanted = atou (optarg); + + else if (ARGUMENT_IS ("output-file")) + output_name = optarg; + + else if (ARGUMENT_IS ("print-clean-info") + || ARGUMENT_IS ("print-guidelines")) + verbose = true; + + else if (ARGUMENT_IS ("range")) + GET_RANGE (optarg, starting_char, ending_char); + + else if (ARGUMENT_IS ("version")) + printf ("%s.\n", version_string); + + /* Else it was a flag; getopt has already done the assignment. */ + } + + if (do_strips && output_epsf) + FATAL ("imageto: Sorry, -strips and -epsf are mutually exclusive"); + + FINISH_COMMAND_LINE (); +} + +/* If the input format wasn't explicitly set on the command line, + attempt to intuit it from FILENAME, and set the necessary variables. + If we can't tell what the format should be, quit. */ + +static void +set_input_format (string filename) +{ + string input_extension; + + /* If it's already set, just return. */ + if (image_open_input_file != NULL) + return; + + /* Try to guess based on FILENAME. */ + input_extension = find_suffix (filename) ? : ""; + + if (STREQ (input_extension, "img")) + set_img_input_format (); + + else if (STREQ (input_extension, "pbm")) + set_pbm_input_format (); + + else /* Can't guess it; quit. */ + { + fprintf (stderr, "You must supply an input format.\n"); + fprintf (stderr, "(I can't guess from the filename `%s'.)\n", filename); + fprintf (stderr, "For more information, use ``-help''.\n"); + exit (1); + } +} + + +/* Set up for reading a PBM file. */ + +static void +set_pbm_input_format () +{ + image_open_input_file = pbm_open_input_file; + image_close_input_file = pbm_close_input_file; + image_get_header = pbm_get_header; + image_get_scanline = pbm_get_scanline; + input_extension = "pbm"; +} + + +/* Set up for reading an IMG file. */ + +static void +set_img_input_format () +{ + image_open_input_file = img_open_input_file; + image_close_input_file = img_close_input_file; + image_get_header = img_get_header; + image_get_scanline = img_get_scanline; + input_extension = "img"; +} diff --git a/imageto/main.h b/imageto/main.h new file mode 100644 index 0000000..7d2f7c1 --- /dev/null +++ b/imageto/main.h @@ -0,0 +1,42 @@ +/* main.h: global variable declarations. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef MAIN_H +#define MAIN_H + +#include <kpathsea/types.h> +#include "image-header.h" + + +/* See main.c for explanations of these globals. */ +extern boolean trace_scanlines; +extern image_header_type image_header; +extern string input_name; +extern string output_name; + +/* Generic routines to manipulate the image. */ +extern void (*image_open_input_file) (string filename); +extern void (*image_close_input_file) (void); +extern void (*image_get_header) (void); +extern boolean (*image_get_scanline) (one_byte *); + + +/* Print a scanline LINE of width WIDTH, if `trace_scanlines' is true.. */ +extern void print_scanline (one_byte line[], unsigned width); + +#endif /* not MAIN_H */ diff --git a/imageto/out-chars.c b/imageto/out-chars.c new file mode 100644 index 0000000..b0dc6f4 --- /dev/null +++ b/imageto/out-chars.c @@ -0,0 +1,750 @@ +/* out-chars.c: try to extract the real characters from the image. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include <kpathsea/tex-file.h> +#include <kpathsea/pathsearch.h> +#include <kpathsea/paths.h> + +#include "bb-outline.h" +#include "gf.h" +#include "report.h" + +#include "bitmap2.h" +#include "extract.h" +#include "ifi.h" +#include "image-header.h" +#include "main.h" +#include "out-strips.h" + +/*xx*/ +FILE *testfileptr; +const char* whole_bitmap_filename = "test-whole-bitmap"; +const char* bb_whole_bitmap_filename = "test-bb-whole-bitmap"; +const char* subbitmap_filename = "test-subbitmap"; +const char* bb_subbitmap_filename = "test-bb-subbitmap"; +const char* line_subbitmap_filename = "test-line-subbitmap"; +const char* line_bb_subbitmap_filename = "test-line-bb-subbitmap"; +const char* gf_bitmap_filename = "test-gf-bitmap"; +const char* gf_bb_bitmap_filename = "test-gf-bb-bitmap"; + + + +/* A list of the image rows on which the baselines occur. The end of + the list is marked with an element -1. (-baselines) */ +int *baseline_list = NULL; + +/* Find about this many characters in the image, then stop. This is + useful only for testing, because converting the entire image takes a long + time. So we might in truth output a few more characters than + specified here. (-nchars) */ +unsigned nchars_wanted = MAX_CHARCODE + 1; + +/* If set, prints diagnostics about which boxes are and aren't cleaned. + (-print-clean-info) */ +boolean print_clean_info = false; + +/* Says whether to print the row numbers of each character as we go, + so that the user can decide how to adjust jumping baselines. + (-print-guidelines) */ +boolean print_guidelines = false; + +/* Says which characters to output. This is independent of the + ordering in the font file. (-range) */ +int starting_char = 0; +int ending_char = MAX_CHARCODE; + +/* The design size of the font we're creating. */ +static real design_size; + +/* Where the baseline of the current row is in the image. The first row + is #1, and so on. We start over at row 1 at each image row.*/ +static unsigned row_baseline; +static unsigned row_height; + +/* How many boxes total the characters take up. */ +static unsigned total_boxes_expected; + + +static boolean bb_equal_p (bounding_box_type, bounding_box_type); +static gf_char_type bitmap_to_gf_char + (bitmap_type, real, bounding_box_type, image_char_type); +static void clean_bitmap (bitmap_type *, bb_list_type); +static boolean do_image_line + (bitmap_type, unsigned *, unsigned *, real, image_char_list_type); +static void image_to_bitmap_bbs (bb_list_type *); +extern void offset_bb_list (bb_list_type *l, int offset); +static unsigned output_chars + (bb_list_type, bitmap_type, real, image_char_list_type, unsigned); + +/* Analyze the input image, outputting the characters we find. */ + +void +write_image_chars (image_header_type image_header, real ds) +{ + bitmap_type *image_line_bitmap; + unsigned nchars_done = 0; + + /* Read the image information. This tells us to which character + each bounding box belongs, among other things. */ + image_char_list_type image_char_list = read_ifi_file (&total_boxes_expected); + + /* Remember this so we don't need to pass it through all the + intervening routines to the low-level output. */ + design_size = ds; + + /* The main loop also (and more commonly) exits when we've read the + entire image. */ + while (nchars_done < nchars_wanted) + { + /* Vector of column numbers where the image column alternates + between some black to all white; used to get the bounding box + column min and max for each character. */ + unsigned *transitions; + + /* Read one line of characters, noting the transitions (see + above), in the image. After this, `image_line_bitmap' is, for + example, `a...z', with blank columns at the left and right. + Whatever is in the original image. */ + image_line_bitmap + = some_black_to_all_white_row (image_header.width, &transitions); + + if (image_line_bitmap == NULL) + break; /* We've read the whole image file. */ + + if (baseline_list == NULL || *baseline_list == -1) + { + if (baseline_list != NULL) + WARNING ("imageto: Not enough baselines specified"); + row_baseline = 0; + } + else + row_baseline = *baseline_list++; + + row_height = BITMAP_HEIGHT (*image_line_bitmap); + + /* Process one line of characters. If `do_image_line' fails, we + need to read the next row in the image, and put it directly + below the current line to complete a character. For example, + if a line has only an `!' on it, we will only get the stem on + the first call to `some_black_to_all_white_row'. We want to + get the dot in there, too. */ + while (!do_image_line (*image_line_bitmap, transitions, &nchars_done, + (real) image_header.hres, image_char_list)) + { + bitmap_type *revised + = append_next_image_row (*image_line_bitmap, image_header.width, + &transitions); + if (revised == NULL) + { + WARNING ("imageto: Image ended in the midst of a character"); + break; + } + + /* Tell the user the image row didn't end on a character. */ + REPORT ("+"); + + free_bitmap (image_line_bitmap); + image_line_bitmap = revised; + if (baseline_list == NULL) + row_baseline = 0; + + row_height = BITMAP_HEIGHT (*image_line_bitmap); + } + + free_bitmap (image_line_bitmap); + } +} + +/* Analyze and output all of the bitmap IMAGE, which is one line of type + in the original. The resolution of the image is H_RESOLUTION, and + we've read NCHARS characters (including .notdefs) so far. We use + IMAGE_CHAR_LIST, a list of character information from the IFI file, + and the transition vector TRANSITIONS, which has in it how IMAGE + breaks into characters or character groups. + + We return false if we need to be given another image row to complete + a character. */ + +#define NEXT_TRANSITION() ({ \ + if (*transitions == BITMAP_WIDTH (image) + 1) \ + { \ + WARNING ("imageto: Expected more transitions"); \ + break; \ + } \ + *transitions++; \ +}) + +static boolean +do_image_line (bitmap_type image, unsigned *transitions, unsigned *nchars, + real h_resolution, image_char_list_type image_char_list) +{ + static unsigned box_count = 0; + bounding_box_type bb; + + /* We always use the entire image line vertically. */ + MIN_ROW (bb) = 0; + MAX_ROW (bb) = BITMAP_HEIGHT (image) - 1; + + /* `nchars_wanted' is an option to the program, defined at the top. + Go through the whole line, unless we've found as many characters + as the user requested. */ + while (*nchars < nchars_wanted && *transitions != BITMAP_WIDTH (image) + 1) + { + int bb_offset = 0; + unsigned previous_box_count = box_count; + bb_list_type boxes = bb_list_init (); + bitmap_type *char_bitmap = XTALLOC1 (bitmap_type); + bitmap_type *temp_bitmap = XTALLOC1 (bitmap_type); + + /* The first element of TRANSITIONS is white-to-black. + Thereafter, they alternate. */ + MIN_COL (bb) = NEXT_TRANSITION (); + MAX_COL (bb) = NEXT_TRANSITION (); + + /* Get the bitmap of the first transition. `char_bitmap' is + either a single character (if the character didn't overlap with + a consecutive one in the font specimen) or more than one (if + the characters did overlap). For example, it might contain + just an `a' this time through the loop (with blank rows above + and below, because `a' has neither a descender nor an + ascender), then next time a `b', and so on. Or it might + contain `ij' (if they overlap in the specimen) instead of `i' + this time and `j' next time. */ + *char_bitmap = extract_subbitmap (image, bb); + *temp_bitmap = copy_bitmap (*char_bitmap); +/*xx*/ +if ((testfileptr = fopen(line_subbitmap_filename, "w")) != NULL) +print_bitmap(testfileptr, *temp_bitmap); +else +printf("Bad file pointer for printing subbitmap.\n"); +fclose(testfileptr); +if ((testfileptr = fopen(line_bb_subbitmap_filename, "w")) != NULL) +print_bounded_bitmap(testfileptr, *temp_bitmap, bb); +else +printf("Bad file pointer for printing bb-subbitmap.\n"); +fclose(testfileptr); + + /* Unless we've read enough boxes, find the ones in the current + character(s), and exit, either: 1) to output a character if the + boxes ``finish'' a character, or 2) to exit the routine with + false, if they don't. If don't find all the boxes needed to + finish a character (i.e., it has vertical white space in it, + loop around getting more ``transitions'' until we do. */ + while (true) + { + bb_list_type temp_boxes; + bounding_box_type previous_bb; + + /* If we've read all the bounding boxes specified (in the IFI + file), we're done. */ + if (box_count == total_boxes_expected) + break; + + /* If we've read more boxes than we expected to, trouble. */ + if (box_count > total_boxes_expected) + { + WARNING2 ("imageto: Read box #%u but expected only %u", + box_count, total_boxes_expected); + /* No point in giving this message more than once. */ + total_boxes_expected = INT_MAX; + } + + /* Find the bounding boxes around all the shapes in `temp_bitmap'. + (The first time through the loop, `temp_bitmap' is the same + as `char_bitmap.') Continuing the above `ij' example, this + would result in four bounding boxes (one for the ``dotless'' + part of the `i,' one for the ``dotless'' part of the `j' + and two for each of the dots). */ + temp_boxes = find_outline_bbs (*temp_bitmap, false, 0, 0); + + /* The subimages we've created all start at column zero. But + if there are overlapping characters (the `ij' example + above), we want to put the images (for, e.g., `i' and `j') + side-by-side instead of overlaying them. So we change the + bounding box numbers for `temp_boxes' by adding `bb_offset.' */ + offset_bb_list (&temp_boxes, bb_offset); + + box_count += BB_LIST_LENGTH (temp_boxes); + bb_list_splice (&boxes, temp_boxes); + + /* Break if the number of boxes indicated for the current + character(s) coincide with the end of a character. This + translates to: if the white column was at the end of some + character in the list, exit the loop to output what we've got. */ + if (box_at_char_boundary_p (image_char_list, *nchars, + box_count - previous_box_count)) + break; + + /* If we're at the end of the image row, return to our caller + that we had to quit in the middle of a character. */ + if (*transitions == BITMAP_WIDTH (image) + 1) + { /* Forget that we've seen these boxes. */ + box_count = previous_box_count; + return false; + } + /* If the character has white vertical space between its + parts, e.g., double quotes or ellipses, have to get the + rest of its bitmap. */ + previous_bb = bb; + MIN_COL (bb) = NEXT_TRANSITION (); + MAX_COL (bb) = NEXT_TRANSITION (); + + /* Leave in the white space between the character parts. */ + MIN_COL (bb) = MAX_COL (previous_bb); + + free_bitmap (temp_bitmap); + *temp_bitmap = extract_subbitmap (image, bb); +/*xx*/ +if ((testfileptr = fopen(line_subbitmap_filename, "w")) != NULL) +print_bitmap(testfileptr, *temp_bitmap); +else +printf("Bad file pointer for printing subbitmap.\n"); +fclose(testfileptr); +if ((testfileptr = fopen(line_bb_subbitmap_filename, "w")) != NULL) +print_bounded_bitmap(testfileptr, *temp_bitmap, bb); +else +printf("Bad file pointer for printing bb-subbitmap.\n"); +fclose(testfileptr); + if (temp_bitmap == NULL) + { + WARNING1 ("imageto: Expected more bounding boxes for `%d'", + IMAGE_CHARCODE (IMAGE_CHAR (image_char_list, *nchars))); + break; + } + + /* Next time through the loop, the boxes `temp_bitmap' should + be just to the right of the bitmap we've accumulated in + `char_bitmap'. This happens if the character has vertical + white space between its parts. */ + bb_offset = BITMAP_WIDTH (*char_bitmap); + + /* When this happens, it usually means that the IFI file + didn't specify enough bounding boxes for some character, + and so things are out of sync. */ + if (BITMAP_HEIGHT (*char_bitmap) != BITMAP_HEIGHT (*temp_bitmap)) + { + WARNING ("imageto: Line ended inside a character"); + break; + } + bitmap_concat (char_bitmap, *temp_bitmap); + } /* while (true) */ + + free_bitmap (temp_bitmap); + + /* Convert the bits inside those bounding boxes into one (if not + overlapping with another) or more (if overlapping) characters + in the GF font. */ + *nchars += output_chars (boxes, *char_bitmap, h_resolution, + image_char_list, *nchars); + free_bitmap (char_bitmap); + bb_list_free (&boxes); + } /* end while (*nchars < nchars_wanted + && *transitions != BITMAP_WIDTH (image) + 1) */ + + return true; +} + +/* Move all the elements in BB_LIST to the right by OFFSET. */ + +void +offset_bb_list (bb_list_type *bb_list, int offset) +{ + unsigned this_bb; + + for (this_bb = 0; this_bb < BB_LIST_LENGTH (*bb_list); this_bb++) + { + bounding_box_type *bb = &BB_LIST_ELT (*bb_list, this_bb); + MIN_COL (*bb) += offset; + MAX_COL (*bb) += offset; + } +} + + +/* Return true if BB1 and BB2 are equal. */ + +static boolean +bb_equal_p (bounding_box_type bb1, bounding_box_type bb2) +{ + return + MIN_COL (bb1) == MIN_COL (bb2) + && MIN_ROW (bb1) == MIN_ROW (bb2) + && MAX_COL (bb1) == MAX_COL (bb2) + && MAX_ROW (bb1) == MAX_ROW (bb2); +} + +/* For each bounding box in the list BOXES, extract from IMAGE_LINE_BITMAP + and turn the resulting bitmap into a single character in the font. + The information in IMAGE_CHAR_LIST maps bounding boxes to character codes; + consecutive bounding boxes may belong to the same character. For + example, `i' will appear twice, once for the dot and once for the + stem. We assume that all the bounding boxes for a given character + will appear in IMAGE_LINE_BITMAP. + + We return the number of characters (not bounding boxes) found, + including characters that were omitted. */ + +/* Predicate to tell us if we want to actually write the character. */ +#define OUTPUT_CHAR_P(code, image_char) \ + ((code) >= starting_char && (code) <= ending_char \ + && !IMAGE_CHAR_OMIT (image_char)) + +static unsigned +output_chars (bb_list_type boxes, bitmap_type image_line_bitmap, + real h_resolution, image_char_list_type image_char_list, + unsigned current_char) +{ + static unsigned char_count = 0; + int this_box; /* Because we might have to subtract when it's zero. */ + boolean done[BB_LIST_LENGTH (boxes)]; + + /* Since we report (a lot) more information when `print_guidelines' is + true, we can fit fewer characters per line. */ + unsigned nchars_per_line = print_guidelines ? 1 : 11; + + unsigned nchars_written = 0; + + for (this_box = 0; this_box < BB_LIST_LENGTH (boxes); this_box++) + done[this_box] = false; + + for (this_box = 0; this_box < BB_LIST_LENGTH (boxes); this_box++) + { + bounding_box_type bb; + bitmap_type bitmap; + image_char_type c; + charcode_type charcode; + bb_list_type bb_list = bb_list_init (); + + /* `done[this_box]' will be set if we get to a bounding box that + has already been combined with a previous one, because of + an alternating combination. Since we never go backwards, we + don't bother to set `done' for every box we look at. */ + if (done[this_box]) + continue; + + c = IMAGE_CHAR (image_char_list, current_char++); + charcode = IMAGE_CHARCODE (c); + + REPORT ("["); + + /* Only bother to collect the character image if we're going to + output it; otherwise, it just wastes a lot of time and space. */ + if (OUTPUT_CHAR_P (charcode, c)) + { /* A character consisting of zero bounding boxes is invisible; + e.g., a space. We don't want to read any of the bitmap for + such a thing. */ + if (IMAGE_CHAR_BB_COUNT (c) == 0) + { + BITMAP_HEIGHT (bitmap) = 0; + BITMAP_WIDTH (bitmap) = 0; + BITMAP_BITS (bitmap) = NULL; + bb = (bounding_box_type) { 0, 0, 0, 0 }; + + /* Since we're not eating up any bounding boxes, + reconsider the current one. */ + this_box--; + } + else + { + bb = BB_LIST_ELT (boxes, this_box); + bitmap = extract_subbitmap (image_line_bitmap, bb); +/*xx*/ +if ((testfileptr = fopen(subbitmap_filename, "w")) != NULL) +print_bitmap(testfileptr, bitmap); +else +printf("Bad file pointer for printing subbitmap.\n"); +fclose(testfileptr); +if ((testfileptr = fopen(bb_subbitmap_filename, "w")) != NULL) +print_bounded_bitmap(testfileptr, bitmap, bb); +else +printf("Bad file pointer for printing bb-subbitmap.\n"); +fclose(testfileptr); + bb_list_append (&bb_list, bb); + } + } + + while (IMAGE_CHAR_BB_COUNT (c)-- > 1) + { + unsigned combine_box; + + if (IMAGE_CHAR_BB_ALTERNATING (c)) + { + /* Don't increment `this_box', since it is incremented at + the end of the loop, and the next box is part of + another character. */ + combine_box = this_box + 2; + /* Don't look at the second box again in the outer loop. */ + done[combine_box] = true; + } + else + /* Increment `this_box' so can keep combining nonalternating + bounding boxes until they are used up or we hit an + alternating one. */ + combine_box = ++this_box; + + /* combine_box starts at 0 and BB_LIST_LENGTH starts at 1, so... */ + if (combine_box >= BB_LIST_LENGTH (boxes)) + { + WARNING1 ("imageto: Not enough outlines for char %u", + (unsigned) charcode); + break; + } + + if (OUTPUT_CHAR_P (charcode, c)) + { + /* Get the shape to combine with `bitmap'. */ + bounding_box_type next_bb = BB_LIST_ELT (boxes, combine_box); + bitmap_type next_bitmap + = extract_subbitmap (image_line_bitmap, next_bb); +/*xx*/ +if ((testfileptr = fopen(subbitmap_filename, "w")) != NULL) +print_bitmap(testfileptr, next_bitmap); +else +printf("Bad file pointer for printing subbitmap.\n"); +fclose(testfileptr); +if ((testfileptr = fopen(bb_subbitmap_filename, "w")) != NULL) +print_bounded_bitmap(testfileptr, next_bitmap, next_bb); +else +printf("Bad file pointer for printing bb-subbitmap.\n"); +fclose(testfileptr); + bb_list_append (&bb_list, next_bb); + combine_images (&bitmap, next_bitmap, &bb, next_bb); +/*xx*/ +if ((testfileptr = fopen(whole_bitmap_filename, "w")) != NULL) +print_bitmap(testfileptr, bitmap); +else +printf("Bad file pointer for printing whole_bitmap.\n"); +fclose(testfileptr); +if ((testfileptr = fopen(bb_whole_bitmap_filename, "w")) != NULL) +print_bounded_bitmap(testfileptr, bitmap, bb); +else +printf("Bad file pointer for printing bb_whole_bitmap.\n"); +fclose(testfileptr); + free_bitmap (&next_bitmap); + } + } /* while (IMAGE_CHAR_BB_COUNT (c)-- > 1) */ + + if (OUTPUT_CHAR_P (charcode, c)) + { + gf_char_type gf_char; + + if (BITMAP_BITS (bitmap) != NULL) + clean_bitmap (&bitmap, bb_list); + + gf_char = bitmap_to_gf_char (bitmap, h_resolution, bb, c); + gf_put_char (gf_char); + + /* This and the GF character's bitmap are the same, so we only + need to free one of the two. */ + if (BITMAP_BITS (bitmap) != NULL) + free_bitmap (&bitmap); + } + else + { + REPORT ("<ignored>"); /* We're ignoring this character. */ +/*xx this_box--;*//* Reconsider the bounding box. */ + } + REPORT1 ("]%c", ++char_count % nchars_per_line ? ' ' : '\n'); + nchars_written++; + + bb_list_free (&bb_list); + } /* for (this_box = 0; this_box < BB_LIST_LENGTH (boxes); this_box++) */ + + + return nchars_written; +} + +/* Remove bits of adjacent characters that may have crept into B because + of overlapping characters in the original image. KNOWN_BOXES lists + all the known parts of B; if we find other bounding boxes in B, we + remove them. */ + +static void +clean_bitmap (bitmap_type *b, bb_list_type known_boxes) +{ + unsigned test; + bb_list_type test_boxes = find_outline_bbs (*b, false, BITMAP_WIDTH (*b), 0); + + if (print_clean_info) + REPORT2 ("Cleaning %ux%u bitmap:\n", + BITMAP_WIDTH (*b), BITMAP_HEIGHT (*b)); + + /* Convert KNOWN_BOXES to the same coordinates as `test_boxes'. */ + image_to_bitmap_bbs (&known_boxes); + + for (test = 0; test < BB_LIST_LENGTH (test_boxes); test++) + { + unsigned known; + unsigned known_length = BB_LIST_LENGTH (known_boxes); + bounding_box_type test_bb = BB_LIST_ELT (test_boxes, test); + + if (print_clean_info) + REPORT4 (" checking (%d,%d)-(%d,%d) ... ", + MIN_COL (test_bb), MIN_ROW (test_bb), + MAX_COL (test_bb), MAX_ROW (test_bb)); + + /* If we want to keep `test_bb', it will be one of the elements of + BB_LIST. Otherwise, it is a piece of an adjacent character, + and we should erase it. */ + for (known = 0; known < known_length && !bb_equal_p (test_bb, + BB_LIST_ELT (known_boxes, known)); + known++) + ; + + if (known == known_length) + { + unsigned r; + int test_bb_width = BB_WIDTH (test_bb); + + assert (test_bb_width > 0); + + if (print_clean_info) + REPORT ("clearing.\n"); + + for (r = MIN_ROW (test_bb); r <= MAX_ROW (test_bb); r++) + { + one_byte *row = BITMAP_ROW (*b, r); + memset (row + MIN_COL (test_bb), 0, test_bb_width); + } + } + else if (print_clean_info) + REPORT ("keeping.\n"); + } +} + + +/* Translate the elements of BOXES to the origin, i.e., shift each down + by the minimum row and column. We use this in `clean_bitmap' to + change bounding boxes in the coordinates of the entire image to the + coordinates of the single character we are cleaning. */ + +static void +image_to_bitmap_bbs (bb_list_type *boxes) +{ + unsigned b; + unsigned min_col = UINT_MAX; + unsigned min_row = UINT_MAX; + + /* First find the minimum row and column of all the bb's in BOXES. */ + for (b = 0; b < BB_LIST_LENGTH (*boxes); b++) + { + bounding_box_type bb = BB_LIST_ELT (*boxes, b); + + assert (MIN_COL (bb) >= 0 && MIN_ROW (bb) >= 0); + + MIN_EQUALS (min_col, MIN_COL (bb)); + MIN_EQUALS (min_row, MIN_ROW (bb)); + } + + /* Now translate all the bb's by those minimums. */ + for (b = 0; b < BB_LIST_LENGTH (*boxes); b++) + { + bounding_box_type *bb = &BB_LIST_ELT (*boxes, b); + + MIN_COL (*bb) -= min_col; + MAX_COL (*bb) -= min_col; + MIN_ROW (*bb) -= min_row; + MAX_ROW (*bb) -= min_row; + } +} + +/* Derive the information necessary to output the font character from + the bitmap B, and return it. The resolution of the bitmap is given + in pixels per inch as H_RESOLUTION. The bounding box BB encloses the + character in the image coordinates. We use BB and the static + variables `row_baseline' and `row_height' to determine the + positioning of the GF character. */ + +#define BB_TO_CARTESIAN(x) \ + (row_height - 1 - (x) - row_baseline \ + - IMAGE_CHAR_BASELINE_ADJUST (image_char)) + +static gf_char_type +bitmap_to_gf_char (bitmap_type b, real h_resolution, + bounding_box_type bb, image_char_type image_char) +{ + static boolean first = true; + static boolean have_tfm_file = false; + gf_char_type gf_char; + bounding_box_type cartesian_bb; + charcode_type charcode = IMAGE_CHARCODE (image_char); + boolean have_tfm_width = false; + +/*xx*/ +if(b.bitmap){ +if ((testfileptr = fopen(gf_bitmap_filename, "w")) != NULL) +print_bitmap(testfileptr, b); +else +printf("Bad file pointer for printing gf_bitmap.\n"); +fclose(testfileptr); +if ((testfileptr = fopen(gf_bb_bitmap_filename, "w")) != NULL) +print_bounded_bitmap(testfileptr, b, bb); +else +printf("Bad file pointer for printing gf_bb_bitmap.\n"); +fclose(testfileptr); +} + MIN_ROW (cartesian_bb) = BB_TO_CARTESIAN (MAX_ROW (bb)); + MAX_ROW (cartesian_bb) = BB_TO_CARTESIAN (MIN_ROW (bb)); + + REPORT1 ("%u", charcode); + + GF_CHARCODE (gf_char) = charcode; + GF_BITMAP (gf_char) = b; + GF_CHAR_MIN_COL (gf_char) = IMAGE_CHAR_LSB (image_char); + GF_CHAR_MAX_COL (gf_char) = GF_CHAR_MIN_COL (gf_char) + BITMAP_WIDTH (b); + GF_CHAR_MIN_ROW (gf_char) = MIN_ROW (cartesian_bb); + GF_CHAR_MAX_ROW (gf_char) = MAX_ROW (cartesian_bb); + + GF_H_ESCAPEMENT (gf_char) = (GF_CHAR_MAX_COL (gf_char) + + IMAGE_CHAR_RSB (image_char)); + if (first) + { + string tfm_name = kpse_find_tfm (remove_suffix (output_name)); + + if (tfm_name) + have_tfm_file = tfm_open_input_file (tfm_name); + first = false; + } + + have_tfm_width = false; + if (have_tfm_file) + { + tfm_char_type *tfm_char = tfm_get_char (charcode); + if (tfm_char) + { + GF_TFM_WIDTH (gf_char) = TFM_FIX_WIDTH (*tfm_char); + have_tfm_width = true; + } + } + + /* If no TFM file, or the TFM file doesn't define this character, + use the pixel width for the TFM value. */ + if (!have_tfm_width) + { + real width_in_points + = GF_H_ESCAPEMENT (gf_char) * POINTS_PER_INCH / h_resolution; + GF_TFM_WIDTH (gf_char) = real_to_fix (width_in_points / design_size); + } + + if (print_guidelines) + REPORT3 (" (%s) %d/%d", IMAGE_CHARNAME (image_char), + MIN_ROW (cartesian_bb), MAX_ROW (cartesian_bb)); + + return gf_char; +} diff --git a/imageto/out-chars.h b/imageto/out-chars.h new file mode 100644 index 0000000..0b91ade --- /dev/null +++ b/imageto/out-chars.h @@ -0,0 +1,34 @@ +/* out-chars.h: extract the characters from the image. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef OUT_CHARS_H +#define OUT_CHARS_H + +#include "image-header.h" + + +/* See out-chars.c. */ +extern int *baseline_list; +extern boolean print_clean_info, print_guidelines; +extern unsigned nchars_wanted; +extern int starting_char, ending_char; + + +extern void write_image_chars (image_header_type, real design_size); + +#endif /* not OUT_CHARS_H */ diff --git a/imageto/out-epsf.c b/imageto/out-epsf.c new file mode 100644 index 0000000..564807c --- /dev/null +++ b/imageto/out-epsf.c @@ -0,0 +1,166 @@ +/* out-epsf.c: output the whole image as an EPS file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "hexify.h" +#include "report.h" + +#include "main.h" +#include "out-epsf.h" + +extern string version_string; + +static void pack_scanline (one_byte *, unsigned); + +/* Abbreviations for output to `eps_file'. */ +#define OUT_STRING(s) fprintf (eps_file, "%s", s) +#define OUT_SIMPLE(s) fprintf (eps_file, "%%%%%s\n", s) +#define OUT_COMMENT(s, v) fprintf (eps_file, "%%%%%s: %s\n", s, v) +#define OUT1(s, v1) fprintf (eps_file, s, v1) +#define OUT2(s, v1, v2) fprintf (eps_file, s, v1, v2) +#define OUT3(s, v1, v2, v3) fprintf (eps_file, s, v1, v2, v3) + +/* Write an Encapsulated PostScript file corresponding to the image. */ + +void +write_epsf (string output_name, image_header_type image_header) +{ + /* Just black & white, or do we have grayscale? */ + boolean monochrome_p = image_header.depth == 1; + + /* Just for convenience. */ + unsigned width = image_header.width; + unsigned height = image_header.height; + + /* We pack the image tightly if it's monochrome. */ + unsigned width_used = monochrome_p ? width / 8 + !!(width % 8) : width; + + /* Buffer into which we'll read the image data. */ + unsigned scanline_count = 0; + one_byte *scanline = xmalloc (width); + + /* Open the output file OUTPUT_NAME. */ + FILE *eps_file = xfopen (output_name, "w"); + + OUT_STRING ("%!PS-Adobe-3.0 EPSF-3.0\n"); + OUT2 ("%%%%BoundingBox: 0 0 %u %u\n", width, height); + OUT_COMMENT ("Creator", version_string); + OUT_COMMENT ("Title", output_name); + OUT_COMMENT ("CreationDate", now ()); + OUT_COMMENT ("DocumentData", "Clean7Bit"); + OUT_SIMPLE ("EndComments"); + + /* We map the image to the unit square for image(mask) and scale the + coordinate system to get back to the original size. I can't grasp + how to use the matrix argument to image(mask) to avoid the scaling, + but I'm sure it's possible. */ + OUT2 ("gsave\n %u %u scale\n", width, height); + + /* We need a buffer to hold the string chunks as we read them. It + can't be of arbitrary size: it must be an exact multiple of the + total number of data characters. Otherwise, we will read past the + end of the data. */ + OUT1 ("/image-buffer %u string def\n", width_used); + + /* If we are monochrome, we use the `imagemask' operator; else `image'. */ + OUT2 (" %u %u", width, height); + + if (monochrome_p) + OUT_STRING (" true"); /* The `invert' argument. */ + else + OUT1 (" %u", image_header.depth); /* bits/sample */ + + OUT3 (" [%u 0 0 -%u 0 %u]\n", width, height, height); + OUT_STRING ("{currentfile image-buffer readhexstring pop}\n"); + OUT1 ("%s\n", monochrome_p ? "imagemask" : "image"); + + /* Read the image. */ + while ((*image_get_scanline) (scanline)) + { + string h; + unsigned loc; + + scanline_count++; + if (scanline_count % 10 == 0) + REPORT1 (".%s", scanline_count % 790 == 0 ? "\n" : ""); + + /* Monochrome images are output with eight samples/byte; grayscale + images are output with one sample/byte. */ + if (monochrome_p) + pack_scanline (scanline, width); + + /* Convert binary to ASCII hexadecimal. */ + h = hexify (scanline, width_used); + + /* Adobe says lines in EPS files should be no more than 255 + characters. How silly. */ + for (loc = 1; loc <= 2 * width_used; loc++) + { + putc (h[loc - 1], eps_file); + if (loc % 255 == 0) + putc ('\n', eps_file); + } + + free (h); + putc ('\n', eps_file); + } + + /* Restore the ctm. */ + OUT_STRING ("grestore\n"); + + if (scanline_count != image_header.height) + WARNING2 ("Expected %u scanlines, read %u", image_header.height, + scanline_count); + + OUT_SIMPLE ("TRAILER"); + OUT_SIMPLE ("EOF"); +} + +/* Change the one bit/byte representation (call each byte a `cell') of + LENGTH bits in DATA to be eight bits/byte. Pad the last byte with + zero. We don't change those bytes beyond the end of packed portion, + thus assuming they are not looked at. */ + +static void +pack_scanline (one_byte *data, unsigned length) +{ + unsigned cell; /* Which bit in the original data we're on. */ + unsigned packing_loc = 0; /* Which byte we're currently packing. */ + unsigned packing_bit = 8; /* How much to shift. */ + + /* The very first cell has to be treated specially, because we must + initialize it with itself shifted left (if we're going to use data + in place, that is.) */ + data[0] <<= 7; + + for (cell = 0; cell < length; cell++) + { + packing_bit--; + data[packing_loc] |= data[cell] << packing_bit; + if (packing_bit == 0) + { + packing_bit = 8; + packing_loc++; + + /* After the first byte, we can just clear the byte at + `packing_loc', since `cell' has already moved beyond it. */ + data[packing_loc] = 0; + } + } +} diff --git a/imageto/out-epsf.h b/imageto/out-epsf.h new file mode 100644 index 0000000..c664772 --- /dev/null +++ b/imageto/out-epsf.h @@ -0,0 +1,28 @@ +/* out-epsf.h: output the whole image as an EPS file. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef OUT_EPSF_H +#define OUT_EPSF_H + +#include "image-header.h" + + +/* Output an EPS file for the image with header H to OUTPUT_NAME. */ +extern void write_epsf (string output_name, image_header_type h); + +#endif /* not OUT_EPSF_H */ diff --git a/imageto/out-strips.c b/imageto/out-strips.c new file mode 100644 index 0000000..a43a411 --- /dev/null +++ b/imageto/out-strips.c @@ -0,0 +1,94 @@ +/* out-strips.c: cut the entire image into strips. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "config.h" + +#include "gf.h" +#include "report.h" + +#include "main.h" +#include "out-strips.h" + +/* Output a ``font'' in which each ``character'' is a constant number of + scanlines from the image. This might use less than resources than + the giant PostScript file that -epsf outputs. + + We only output the GF characters here; we assume the postamble and + preamble are written by the caller. */ + +void +write_chars_as_strips (image_header_type image_header, real design_size) +{ + dimensions_type char_dimens; + gf_char_type gf_char; + unsigned gf_row; + unsigned lines_per_char; + one_byte *scanline; + real width_in_points; + boolean first_char = true; + unsigned scanline_count = 0; + + /* Set up for the first character. We divide the image into 256 parts, + each of which will turn into one ``character''. */ + lines_per_char = image_header.height / 256 + 1; + GF_CHARCODE (gf_char) = 0; + DIMENSIONS_WIDTH (char_dimens) = image_header.width; + DIMENSIONS_HEIGHT (char_dimens) = lines_per_char; + GF_BITMAP (gf_char) = new_bitmap (char_dimens); + GF_CHAR_MIN_COL (gf_char) = GF_CHAR_MIN_ROW (gf_char) = 0; + GF_CHAR_MAX_COL (gf_char) = DIMENSIONS_WIDTH (char_dimens); + GF_CHAR_MAX_ROW (gf_char) = DIMENSIONS_HEIGHT (char_dimens) - 1; + + /* We aren't going to have any side bearings. */ + GF_H_ESCAPEMENT (gf_char) = DIMENSIONS_WIDTH (char_dimens); + width_in_points = DIMENSIONS_WIDTH (char_dimens) * POINTS_PER_INCH + / (real) image_header.hres; + GF_TFM_WIDTH (gf_char) = real_to_fix (width_in_points / design_size); + + + /* Read the image. */ + while (true) + { + if (scanline_count % lines_per_char == 0) + { + /* We get here when scanline_count == 0, and we haven't read + anything, so we can't write anything. */ + if (!first_char) + { + gf_put_char (gf_char); + REPORT2 ("[%u]%c", GF_CHARCODE (gf_char), + (GF_CHARCODE (gf_char) + 1) % 13 ? ' ' : '\n'); + GF_CHARCODE (gf_char)++; + } + else + first_char = false; + gf_row = 0; + } + + scanline = BITMAP_BITS (GF_BITMAP (gf_char)) + + gf_row * DIMENSIONS_WIDTH (char_dimens); + if (!(*image_get_scanline) (scanline)) break; + + scanline_count++; + gf_row++; + } + + if (scanline_count != image_header.height) + WARNING2 ("Expected %u scanlines, read %u", image_header.height, + scanline_count); +} diff --git a/imageto/out-strips.h b/imageto/out-strips.h new file mode 100644 index 0000000..401c124 --- /dev/null +++ b/imageto/out-strips.h @@ -0,0 +1,27 @@ +/* out-strips.h: cut the image into strips. + +Copyright (C) 1992 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef OUT_STRIPS_H +#define OUT_STRIPS_H + +#include "image-header.h" + + +extern void write_chars_as_strips (image_header_type, real design_size); + +#endif /* not OUT_STRIPS_H */ diff --git a/imageto/strips.tex b/imageto/strips.tex new file mode 100644 index 0000000..1b7a3ee --- /dev/null +++ b/imageto/strips.tex @@ -0,0 +1,85 @@ +% TeX file to display a ``font'' made from imagetofont's -strips option. + +% Set up our font. +\message{Fontname? } +\read -1 to \testfontname +\font\testfont = \testfontname\space +\testfont + +% \monthname produces the name of the month, abbreviated to three +% letters. The primitive \month should never be zero. +% +\def\monthname{% + \ifcase\month + \or Jan\or Feb\or Mar\or Apr\or May\or Jun% + \or Jul\or Aug\or Sep\or Oct\or Nov\or Dec% + \fi +}% + +% \timestring produces the current time, in a format like `1:14 p.m.'. +% +\def\timestring{\begingroup + \count0 = \time + \divide\count0 by 60 + \count2 = \count0 % The hour, from zero to 23. + % + \count4 = \time + \multiply\count0 by 60 + \advance\count4 by -\count0 % The minute, from zero to 59. + % But we need the minutes with a leading zero, if necessary. + \ifnum\count4<10 + \toks1 = {0}% + \else + \toks1 = {}% + \fi + % + % Convert the hour into `a.m.' or `p.m.', and make it mod 12. + \ifnum\count2<12 + \toks0 = {a.m.}% + \else + \toks0 = {p.m.}% + \advance\count2 by -12 + \fi + % + % If it's midnight, call it `12', not `0'. + \ifnum\count2=0 + \count2 = 12 + \fi + % + % Produce the output. + \number\count2:\the\toks1 \number\count4 \thinspace \the\toks0 +\endgroup}% +% +% +% \timestamp produces a text string for the whole thing like +% `23 Apr 1964 1:14 p.m.'. +% +\def\timestamp{\number\day\space\monthname\space\number\year\quad\timestring}% + +\nopagenumbers +\headline = {\hfil \tt \testfontname \quad \timestamp} + +% Use as much of the page as we dare. +\hoffset = -5pc \hsize = 49pc +\voffset = -5pc \vsize = 64pc + +% Don't worry if there's no good place to break pages. +\vbadness = 10000 + +% No leading between ``lines''. +\offinterlineskip + +% Don't worry if the font doesn't have exactly 256 characters, since +% roundoff error makes this likely. +\tracinglostchars = 0 + + +\count255 = 0 +\loop + %\setbox0 = \hbox{\char\count255} + \leftline{\char\count255} + \advance\count255 by 1 + \ifnum\count255<256 +\repeat + +\end diff --git a/imageto/version.c b/imageto/version.c new file mode 100644 index 0000000..b39f56a --- /dev/null +++ b/imageto/version.c @@ -0,0 +1 @@ +char *version_string = "imageto version REPLACE-WITH-VERSION"; |
