void main (int argc, string argv[]) { int code; string font_name = read_command_line (argc, argv); bitmap_font_type f = get_bitmap_font (font_name, atou (dpi)); string font_basename = basename (font_name); /* Initializing the display might involve forking a process. We wouldn't want that process to get copies of open output files, since then when it exited, random stuff might get written to the end of the file. */ init_display (f); if (logging) log_file = xfopen (concat (font_basename, ".log"), "w"); if (strlen (BITMAP_FONT_COMMENT (f)) > 0) REPORT1 ("{%s}\n", BITMAP_FONT_COMMENT (f)); if (output_name == NULL) output_name = font_basename; bzr_start_output (output_name, f); /* The main loop: for each character, find the outline of the shape, then fit the splines to it. */ for (code = starting_char; code <= ending_char; code++) { pixel_outline_list_type pixels; spline_list_array_type splines; char_info_type *c = get_char (font_name, code); if (c == NULL) continue; REPORT1 ("[%u ", code); if (logging) { LOG ("\n\n\f"); print_char (log_file, *c); } x_start_char (*c); pixels = find_outline_pixels (*c); /* `find_outline_pixels' uses corners as the coordinates, instead of the pixel centers. So we have to increase the bounding box. */ CHAR_MIN_COL (*c)--; CHAR_MAX_COL (*c)++; CHAR_MIN_ROW (*c)--; CHAR_MAX_ROW (*c)++; REPORT ("|"); splines = fitted_splines (pixels); bzr_output_char (*c, splines); /* Flush output before displaying the character, in case the user is interested in looking at it and the online version simultaneously. */ flush_log_output (); x_output_char (*c, splines); REPORT ("]\n"); /* If the character was empty, it won't have a bitmap. */ if (BITMAP_BITS (CHAR_BITMAP (*c)) != NULL) free_bitmap (&CHAR_BITMAP (*c)); free_pixel_outline_list (&pixels); free_spline_list_array (&splines); } bzr_finish_output (); close_display (); close_font (font_name); exit (0); }
/* at_splines_new_full modifies its 'bitmap' argument when it does the thin_image thing. */ at_spline_list_array_type * at_splines_new_full(at_bitmap_type * const bitmap, at_fitting_opts_type * const opts, at_msg_func msg_func, void * const msg_data, at_progress_func notify_progress, void * const progress_data, at_testcancel_func test_cancel, void * const testcancel_data) { at_spline_list_array_type * retval; image_header_type image_header; pixel_outline_list_type pixelOutlineList; at_exception_type exp; distance_map_type distanceMap; bool haveDistMap; exp = at_exception_new(msg_func, msg_data); image_header.width = at_bitmap_get_width(bitmap); image_header.height = at_bitmap_get_height(bitmap); if (opts->centerline) { if (opts->preserve_width) { /* Preserve line width prior to thinning. */ bool const paddedTrue = true; distanceMap = new_distance_map(*bitmap, 255, paddedTrue, &exp); haveDistMap = true; } else haveDistMap = false; thin_image(bitmap, opts->backgroundSpec, opts->background_color, &exp); } else haveDistMap = false; if (at_exception_got_fatal(&exp)) retval = NULL; else { if (opts->centerline) { pixel background_color; if (opts->backgroundSpec) background_color = opts->background_color; else PPM_ASSIGN(background_color, 255, 255, 255); pixelOutlineList = find_centerline_pixels(*bitmap, background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp); } else pixelOutlineList = find_outline_pixels(*bitmap, opts->backgroundSpec, opts->background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp); if (at_exception_got_fatal(&exp) || (test_cancel && test_cancel(testcancel_data))) retval = NULL; else { at_spline_list_array_type * splinesP; MALLOCVAR_NOFAIL(splinesP); fit_outlines_to_splines(pixelOutlineList, opts, haveDistMap ? &distanceMap : NULL, image_header.width, image_header.height, &exp, notify_progress, progress_data, test_cancel, testcancel_data, splinesP); if (at_exception_got_fatal(&exp) || (test_cancel && test_cancel(testcancel_data))) retval = NULL; else { if (notify_progress) notify_progress(1.0, progress_data); retval = splinesP; } free_pixel_outline_list(&pixelOutlineList); } if (haveDistMap) free_distance_map(&distanceMap); } return retval; }
/* at_splines_new_full modify its argument: BITMAP when despeckle, quantize and/or thin_image are invoked. */ at_splines_type * at_splines_new_full (at_bitmap * bitmap, at_fitting_opts_type * opts, at_msg_func msg_func, gpointer msg_data, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data) { image_header_type image_header; at_splines_type * splines = NULL; pixel_outline_list_type pixels; QuantizeObj *myQuant = NULL; /* curently not used */ at_exception_type exp = at_exception_new(msg_func, msg_data); at_distance_map dist_map, *dist = NULL; #define CANCELP (test_cancel && test_cancel(testcancel_data)) #define FATALP (at_exception_got_fatal(&exp)) #define FREE_SPLINE() do {if (splines) {at_splines_free(splines); splines = NULL;}} while(0) #define CANCEL_THEN_CLEANUP_DIST() if (CANCELP) goto cleanup_dist; #define CANCEL_THEN_CLEANUP_PIXELS() if (CANCELP) {FREE_SPLINE(); goto cleanup_pixels;} #define FATAL_THEN_RETURN() if (FATALP) return splines; #define FATAL_THEN_CLEANUP_DIST() if (FATALP) goto cleanup_dist; #define FATAL_THEN_CLEANUP_PIXELS() if (FATALP) {FREE_SPLINE(); goto cleanup_pixels;} if (opts->despeckle_level > 0) { despeckle (bitmap, opts->despeckle_level, opts->despeckle_tightness, opts->noise_removal, &exp); FATAL_THEN_RETURN(); } image_header.width = at_bitmap_get_width(bitmap); image_header.height = at_bitmap_get_height(bitmap); if (opts->color_count > 0) { quantize (bitmap, opts->color_count, opts->background_color, &myQuant, &exp); if (myQuant) quantize_object_free(myQuant); /* curently not used */ FATAL_THEN_RETURN(); } if (opts->centerline) { if (opts->preserve_width) { /* Preserve line width prior to thinning. */ dist_map = new_distance_map(bitmap, 255, /*padded=*/TRUE, &exp); dist = &dist_map; FATAL_THEN_RETURN(); } /* Hereafter, dist is allocated. dist must be freed if the execution is canceled or exception is raised; use FATAL_THEN_CLEANUP_DIST. */ thin_image (bitmap, opts->background_color, &exp); FATAL_THEN_CLEANUP_DIST() } /* Hereafter, pixels is allocated. pixels must be freed if the execution is canceled; use CANCEL_THEN_CLEANUP_PIXELS. */ if (opts->centerline) { at_color background_color = { 0xff, 0xff, 0xff }; if (opts->background_color) background_color = *opts->background_color; pixels = find_centerline_pixels(bitmap, background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp); } else pixels = find_outline_pixels(bitmap, opts->background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp); FATAL_THEN_CLEANUP_DIST(); CANCEL_THEN_CLEANUP_DIST(); XMALLOC(splines, sizeof(at_splines_type)); *splines = fitted_splines (pixels, opts, dist, image_header.width, image_header.height, &exp, notify_progress, progress_data, test_cancel, testcancel_data); FATAL_THEN_CLEANUP_PIXELS(); CANCEL_THEN_CLEANUP_PIXELS(); if (notify_progress) notify_progress(1.0, progress_data); cleanup_pixels: free_pixel_outline_list (&pixels); cleanup_dist: if (dist) free_distance_map (dist); return splines; #undef CANCELP #undef FATALP #undef FREE_SPLINE #undef CANCEL_THEN_CLEANUP_DIST #undef CANCEL_THEN_CLEANUP_PIXELS #undef FATAL_THEN_RETURN #undef FATAL_THEN_CLEANUP_DIST #undef FATAL_THEN_CLEANUP_PIXELS }