diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/3rdparty/autotrace/autotrace.c | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/3rdparty/autotrace/autotrace.c | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/src/3rdparty/autotrace/autotrace.c b/src/3rdparty/autotrace/autotrace.c new file mode 100644 index 0000000..a2b65de --- /dev/null +++ b/src/3rdparty/autotrace/autotrace.c @@ -0,0 +1,386 @@ +/* autotrace.c --- Autotrace API + + Copyright (C) 2000, 2001, 2002 Martin Weber + + The author can be contacted at <martweb@gmx.net> + + 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 of the License, 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. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* Def: HAVE_CONFIG_H */ +#include "intl.h" + +#include "private.h" + +#include "autotrace.h" +#include "exception.h" + +#include "fit.h" +#include "bitmap.h" +#include "spline.h" + +#include "input.h" + +#include "xstd.h" +#include "image-header.h" +#include "image-proc.h" +#include "quantize.h" +#include "thin-image.h" +#include "despeckle.h" + +#include <locale.h> +#include <time.h> +#include <stdlib.h> +#include <string.h> + +#define AT_DEFAULT_DPI 72 + +at_fitting_opts_type *at_fitting_opts_new(void) +{ + at_fitting_opts_type *opts; + XMALLOC(opts, sizeof(at_fitting_opts_type)); + *opts = new_fitting_opts(); + return opts; +} + +at_fitting_opts_type *at_fitting_opts_copy(at_fitting_opts_type * original) +{ + at_fitting_opts_type *new_opts; + if (original == NULL) + return NULL; + + new_opts = at_fitting_opts_new(); + *new_opts = *original; + if (original->background_color) + new_opts->background_color = at_color_copy(original->background_color); + return new_opts; +} + +void at_fitting_opts_free(at_fitting_opts_type * opts) +{ + free(opts->background_color); + free(opts); +} + +at_input_opts_type *at_input_opts_new(void) +{ + at_input_opts_type *opts; + XMALLOC(opts, sizeof(at_input_opts_type)); + opts->background_color = NULL; + opts->charcode = 0; + return opts; +} + +at_input_opts_type *at_input_opts_copy(at_input_opts_type * original) +{ + at_input_opts_type *opts; + opts = at_input_opts_new(); + *opts = *original; + if (original->background_color) + opts->background_color = at_color_copy(original->background_color); + return opts; +} + +void at_input_opts_free(at_input_opts_type * opts) +{ + free(opts->background_color); + free(opts); +} + +at_output_opts_type *at_output_opts_new(void) +{ + at_output_opts_type *opts; + XMALLOC(opts, sizeof(at_output_opts_type)); + opts->dpi = AT_DEFAULT_DPI; + return opts; +} + +at_output_opts_type *at_output_opts_copy(at_output_opts_type * original) +{ + at_output_opts_type *opts = at_output_opts_new(); + *opts = *original; + return opts; +} + +void at_output_opts_free(at_output_opts_type * opts) +{ + free(opts); +} + +at_bitmap *at_bitmap_read(at_bitmap_reader * reader, gchar * filename, at_input_opts_type * opts, at_msg_func msg_func, gpointer msg_data) +{ + gboolean new_opts = FALSE; + at_bitmap *bitmap; + XMALLOC(bitmap, sizeof(at_bitmap)); + if (opts == NULL) { + opts = at_input_opts_new(); + new_opts = TRUE; + } + *bitmap = (*reader->func) (filename, opts, msg_func, msg_data, reader->data); + if (new_opts) + at_input_opts_free(opts); + return bitmap; +} + +at_bitmap *at_bitmap_new(unsigned short width, unsigned short height, unsigned int planes) +{ + at_bitmap *bitmap; + XMALLOC(bitmap, sizeof(at_bitmap)); + *bitmap = at_bitmap_init(NULL, width, height, planes); + return bitmap; +} + +at_bitmap *at_bitmap_copy(const at_bitmap * src) +{ + at_bitmap *dist; + unsigned short width, height, planes; + + width = at_bitmap_get_width(src); + height = at_bitmap_get_height(src); + planes = at_bitmap_get_planes(src); + + dist = at_bitmap_new(width, height, planes); + memcpy(dist->bitmap, src->bitmap, width * height * planes * sizeof(unsigned char)); + return dist; +} + +at_bitmap at_bitmap_init(unsigned char *area, unsigned short width, unsigned short height, unsigned int planes) +{ + at_bitmap bitmap; + + if (area) + bitmap.bitmap = area; + else { + if (0 == (width * height)) + bitmap.bitmap = NULL; + else + XCALLOC(bitmap.bitmap, width * height * planes * sizeof(unsigned char)); + } + + bitmap.width = width; + bitmap.height = height; + bitmap.np = planes; + return bitmap; +} + +void at_bitmap_free(at_bitmap * bitmap) +{ + free(AT_BITMAP_BITS(bitmap)); + free(bitmap); +} + +unsigned short at_bitmap_get_width(const at_bitmap * bitmap) +{ + return bitmap->width; +} + +unsigned short at_bitmap_get_height(const at_bitmap * bitmap) +{ + return bitmap->height; +} + +unsigned short at_bitmap_get_planes(const at_bitmap * bitmap) +{ + /* Here we use cast rather changing the type definition of + at_bitmap::np to keep binary compatibility. */ + return (unsigned short)bitmap->np; +} + +void at_bitmap_get_color(const at_bitmap * bitmap, unsigned int row, unsigned int col, at_color * color) +{ + unsigned char *p; + g_return_if_fail(color); + g_return_if_fail(bitmap); + + p = AT_BITMAP_PIXEL(bitmap, row, col); + if (at_bitmap_get_planes(bitmap) >= 3) + at_color_set(color, p[0], p[1], p[2]); + else + at_color_set(color, p[0], p[0], p[0]); +} + +gboolean at_bitmap_equal_color(const at_bitmap * bitmap, unsigned int row, unsigned int col, at_color * color) +{ + at_color c; + + g_return_val_if_fail(bitmap, FALSE); + g_return_val_if_fail(color, FALSE); + + at_bitmap_get_color(bitmap, row, col, &c); + return at_color_equal(&c, color); +} + +at_splines_type *at_splines_new(at_bitmap * bitmap, at_fitting_opts_type * opts, at_msg_func msg_func, gpointer msg_data) +{ + return at_splines_new_full(bitmap, opts, msg_func, msg_data, NULL, NULL, NULL, NULL); +} + +/* 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 + +} + +void at_splines_write(at_spline_writer * writer, FILE * writeto, gchar * file_name, at_output_opts_type * opts, at_splines_type * splines, at_msg_func msg_func, gpointer msg_data) +{ + gboolean new_opts = FALSE; + int llx, lly, urx, ury; + llx = 0; + lly = 0; + urx = splines->width; + ury = splines->height; + + if (!file_name) + file_name = ""; + + if (opts == NULL) { + new_opts = TRUE; + opts = at_output_opts_new(); + } + + setlocale(LC_NUMERIC, "C"); + (*writer->func) (writeto, file_name, llx, lly, urx, ury, opts, *splines, msg_func, msg_data, writer->data); + if (new_opts) + at_output_opts_free(opts); +} + +void at_splines_free(at_splines_type * splines) +{ + free_spline_list_array(splines); + if (splines->background_color) + at_color_free(splines->background_color); + free(splines); +} + +const char *at_version(gboolean long_format) +{ + if (long_format) + return "AutoTrace version " AUTOTRACE_VERSION; + + return AUTOTRACE_VERSION; +} + +const char *at_home_site(void) +{ + return AUTOTRACE_WEB; +} + +void autotrace_init(void) +{ + static int initialized = 0; + if (!initialized) { +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + //bindtextdomain(PACKAGE, LOCALEDIR); +#endif /* Def: ENABLE_NLS */ + + /* Initialize subsystems */ + at_input_init(); + at_output_init(); + at_module_init(); + + initialized = 1; + } +} + +const char *at_fitting_opts_doc_func(char *string) +{ + return _(string); +} |