├── contributors.txt ├── tests ├── test1.png ├── test2.png ├── test3.tif ├── test4.jpg ├── test5.jpg ├── test6.jpg ├── test7.jpg ├── test3.txt ├── test1.txt ├── test6.txt ├── test4.txt ├── test2.txt ├── test7.txt └── test5.txt ├── docs └── screenshot1.png ├── src ├── main.h ├── gui.h ├── asciimatic.h ├── logging.h ├── utils.h ├── utils.c ├── logging.c ├── gui.c ├── main.c └── asciimatic.c ├── config └── asciimatic.cfg ├── Makefile └── README.md /contributors.txt: -------------------------------------------------------------------------------- 1 | Nathan Taylor 2 | -------------------------------------------------------------------------------- /tests/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test1.png -------------------------------------------------------------------------------- /tests/test2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test2.png -------------------------------------------------------------------------------- /tests/test3.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test3.tif -------------------------------------------------------------------------------- /tests/test4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test4.jpg -------------------------------------------------------------------------------- /tests/test5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test5.jpg -------------------------------------------------------------------------------- /tests/test6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test6.jpg -------------------------------------------------------------------------------- /tests/test7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/tests/test7.jpg -------------------------------------------------------------------------------- /docs/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dijkstracula/Asciimatic/HEAD/docs/screenshot1.png -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAIN_H_ 2 | #define __MAIN_H_ 3 | 4 | #define VERSION_STRING "0.1" 5 | 6 | typedef enum {false = 0, true} bool_t; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/gui.h: -------------------------------------------------------------------------------- 1 | #ifndef _GUI_H_ 2 | #define _GUI_H_ 3 | 4 | void 5 | init_gui(void); 6 | 7 | void 8 | gui_loop(void); 9 | 10 | void 11 | shutdown_gui(void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /config/asciimatic.cfg: -------------------------------------------------------------------------------- 1 | valid_characters = " -|+\/'^:_" 2 | 3 | syslog = false; 4 | threads = 4; 5 | 6 | # Canny edge detection default params 7 | threshold1 = 100; 8 | max_threshold1 = 1000; 9 | threshold2 = 300; 10 | max_threshold2 = 1000; 11 | -------------------------------------------------------------------------------- /src/asciimatic.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASCIIMATIC_H_ 2 | #define _ASCIIMATIC_H_ 3 | 4 | #include 5 | 6 | void init_asciimatic(const char *filename, int r, int c); 7 | void asciify(IplImage *edges); 8 | IplImage *detect_edges(IplImage *dst, IplImage *src); 9 | void shutdown_asciimatic(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/logging.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGGING_H_ 2 | #define __LOGGING_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "main.h" 8 | 9 | bool_t init_logging(); 10 | bool_t shutdown_logging(); 11 | 12 | void xlog(int prio, char *fmt, ...); 13 | void vxlog(int prio, const char *fmt, va_list ap); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-g -Wall -Wextra -std=gnu99 3 | LDFLAGS=-lconfig `pkg-config --libs opencv` `pkg-config --libs cairo` 4 | SRCDIR=src 5 | 6 | SOURCES=$(wildcard $(SRCDIR)/*.c) 7 | OBJECTS=$(SOURCES:.c=.o) 8 | 9 | TARGET=asciimatic 10 | 11 | $(TARGET): $(OBJECTS) 12 | $(CC) $(OBJECTS) -o $@ $(LDFLAGS) 13 | 14 | $(OBJECTS): %.o : %.c 15 | $(CC) $(CFLAGS) -c $< -o $@ 16 | 17 | clean: 18 | rm $(OBJECTS) 19 | rm $(TARGET) 20 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* utils.h */ 2 | 3 | #ifndef __UTILS_H_ 4 | #define __UTILS_H_ 5 | 6 | #include 7 | 8 | #define stripnl(x) x[strlen(x) - 1] = '\0'; 9 | 10 | void panic(int, const char *, ...); 11 | void panicx(int, const char *, ...); 12 | 13 | char *xstrdup(const char *str); 14 | void *xcalloc(size_t count, size_t sz); 15 | void *xrealloc(void *p, size_t sz); 16 | void *xmalloc(size_t sz); 17 | 18 | FILE *xfopen(const char *path, const char *flags); 19 | 20 | ssize_t xgetline(char **lineptr, size_t *n, FILE *stream); 21 | #endif 22 | -------------------------------------------------------------------------------- /tests/test3.txt: -------------------------------------------------------------------------------- 1 | ize of character image: 988 x 60 2 | Characters correspond to 3x8 pixel blocks 3 | X--------------------AA--^ ^ooA-V 4 | ----- A- + ooA-+ 5 | A--------------- -----+------- ^- V 6 | -X +---- -------+----------- --- 7 | --------------+A^--+^-+ ---oo---+A A--------+TX---- +-^^ 8 | ^-------------+- -^-A-----^ V^V ^-\| -A^-+ A^o 9 | -+ X++A o^A--Ao--------ALV+-------VA o +-X -A++ 10 | -------------- - oA-/ AAAAA-VA AAA^ ^--^TT X- ^XX-\o AA^ +o-X 11 | ----------^ AJXV+VV+-------o+-o-----XV A-- AAV ^XXAA -Ao -A+A +^oA XV V 12 | -----o----^A XVo----------VoAAAoX -AA A JV AXAXA- +V^ +AAooX L^ -X 13 | /-V XVA-------------LV^+o LL V-AA- -XAoVA- Vo A^ oo+- ^ 14 | ^--AV/-A+ ---------^ LV^-X^VAA TV Y ^oAX-^ -TX V^ -- 15 | +-TX-LoV V ---^^---^^ -AV\AAAL AAVA--X-+XAoL -----o---\ V^ 16 | -++-+AXX A+A-J------------A-^A--o-AA-AAAAVJ ^XA- A-XA---To-+ AA A 17 | -A^-+ A -X|^T ---+ +XA -A-X V--^AAXX^----o---- L A^ 18 | A-^ A-^ -^A----+------- -A---o-+----- --A---- T^ A 19 | A-+ A L+ --------+ ++-------------^ T | 20 | +\o-L T------^ --+-----o-^ -------------------V | 21 | A-o--VVLA LA A- --------- ^X+A+-X-- o\ -^ A- | 22 | L+A---AA AV^A --oA----- ^^^-+ AAJVAAA^ A^ -^ --^A A T --^- 23 | ^+-o -AX V Ao-----^ ^oXA AAA+-TT AAAX^X --A -- -AA AAAX A^++ ^ 24 | o^o ^-^A-^-o A A^- XXA VV V | L^ VA^V+ -AV^V-^ V ^VA ^V 25 | --------o-AVX -A^- XAX-+^+ -AA A--AA^ V--AXAAL---o^ --o-+A-+- V/+ +Xo 26 | -+ -\+ V+ ^oA^+X - AXXXV AA VAAo ^ - ---TX ^V A--XVAV 27 | - V\^ A^^+Xo-^V VV o TA AVV--o- ^XV AV -V -- 28 | ---- Vo +AX-o AA- -TA -XAA ^AA ^X+ 29 | ------A-^^+L------- +--+ ^VV |T V+A^-Ao ^XX 30 | ---- --o V-----AA +-X--^ /Y ^-- TA ^-X-V ^+^X 31 | -A- +-VV-^ +-- TA^----^--- ^o+oT^ -V-^ 32 | -- --^-VA- - -^Vooo-^----A- oA 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Asciimatic - an edge-based ASCII art generator 2 | ============ 3 | 4 | This repository contains a cleaned-up mirror of the SVN repo for Nathan 5 | Taylor's final project in CPSC 505: Image Understanding, Fall 2009, at the 6 | University of British Columbia. 7 | 8 | ![Alt text](/docs/screenshot1.png) 9 | 10 | >Typically, tools to generate ASCII art from raster images, such as aalib or libcaca, quantize the input image to a series of brightness levels, and a printable ASCII character is then assigned to a corresponding subregion of the image, where a "darker" brightness level is assigned a "denser" character, and lighter brightness levels are assigned "sparser" characters. While simple to implement and fast enough for real-time purposes (both mplayer and VLC can display video as ASCII, and Quake has been modified to run in the terminal), it is difficult to see what the image is unless the characters are very small; additionally, ANSI colour information is often needed in order to improve the "shading" of the image. 11 | > 12 | >One can observe that more information than simply "brightness" can be encoded in an ASCII character; in particular, certain characters such as slashes, dashes, pipes, and other punctuation marks suggest strong direction. Also, the choice of character itself could suggest fine detail within the image (ie. a '+' when two near-parallel lines intersect, a 'O' for small circular features, etc.) Additionally, large swatches of similar colours look very busy to the eye; therefore, we may only want to register characters for regions of the image that correspond to changes in intensity; in other words, it is fruitful to consider an edge-based approach to ASCII-art generation. 13 | > 14 | >My CPSC 505 miniproject performs Canny edge-detection on an input in order to extract the primal sketch of an image. Additionally, each subregion of the Canny primal sketch is treated as a filter, and template matching is applied to a subset of printable ASCII characters in order to ask the question, "what character best approximates this region of interest?" The character that corresponds to the highest normalized cross corellation with the filter is outputted. 15 | > 16 | >Initially, the entire range of printable ASCII characters were used. However, this resulted in a very noisy output. Therefore, a subset was chosen by hand that perhaps best represents the kind of edges we would like to capture in text. Different characters could be chosen to represent different "shading types", at the artistic whim of the user. 17 | 18 | Building and installation 19 | ------------------------- 20 | 21 | `$ make` 22 | `$ ./asciimatic [flags] ` 23 | 24 | Additional configuration parameters may be specified in `./config/asciimatic.cfg`. 25 | 26 | Dependencies 27 | ------------ 28 | 29 | * cairo 30 | * libconfig 31 | * libpthread 32 | * opencv 33 | * qt 34 | 35 | Note that qt is an optional dependency for opencv and that you might have to specify its inclusion yourself. 36 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /* utils.c 2 | * Various utility functions. 3 | * 4 | * Copyright (c) 2014 Nathan Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "logging.h" 27 | #include "utils.h" 28 | 29 | void panic(int exitcode, const char *fmt, ...) { 30 | va_list ap; 31 | 32 | va_start(ap, fmt); 33 | vxlog(LOG_ERR, fmt, ap); 34 | va_end(ap); 35 | 36 | shutdown_logging(); 37 | exit(exitcode); 38 | } 39 | 40 | char *xstrdup(const char *str) { 41 | char *p = strdup(str); 42 | 43 | if (!p) { 44 | panic(1, "strdup failed: %s", strerror(errno)); 45 | } 46 | 47 | return p; 48 | } 49 | 50 | void *xcalloc(size_t count, size_t sz) { 51 | void *p = calloc(count, sz); 52 | 53 | if (!p) { 54 | panic(1, "calloc(%lu, %lu) failed: %s", count, sz, strerror(errno)); 55 | } 56 | 57 | return p; 58 | } 59 | 60 | void *xrealloc(void *p, size_t sz) { 61 | void *r = realloc(p, sz); 62 | 63 | if (!r) { 64 | panic(1, "realloc failed: %s", strerror(errno)); 65 | } 66 | 67 | return r; 68 | } 69 | 70 | void *xmalloc(size_t sz) { 71 | void *p = malloc(sz); 72 | 73 | if (!p) { 74 | panic(1, "malloc(%lu) failed: %s", sz, strerror(errno)); 75 | } 76 | 77 | return p; 78 | } 79 | 80 | int xopen(const char *file, int oflag) { 81 | int fd; 82 | 83 | while ((fd = open(file, oflag)) == -1) { 84 | if (errno != EINTR) { 85 | panic(1, "Can't open file %s: %s", file, strerror(errno)); 86 | } 87 | } 88 | 89 | return fd; 90 | } 91 | 92 | FILE *xfopen(const char *file, const char *mode) { 93 | FILE *f = fopen(file, mode); 94 | 95 | if (!f) { 96 | panic(1, "Can't open file %s: %s", file, strerror(errno)); 97 | } 98 | 99 | return f; 100 | } 101 | 102 | ssize_t xgetline(char **lineptr, size_t *n, FILE *stream) { 103 | ssize_t chars = getline(lineptr, n, stream); 104 | 105 | if (chars == -1 && errno == EINVAL) { 106 | panic(1, "Bad arguments to getline()"); 107 | } 108 | 109 | return chars; 110 | } 111 | 112 | -------------------------------------------------------------------------------- /src/logging.c: -------------------------------------------------------------------------------- 1 | /* logging.c 2 | * Wrapper around syslog or writing to a file/stderr. 3 | * 4 | * Copyright (c) 2014 Nathan Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include "logging.h" 29 | #include "main.h" 30 | #include "utils.h" 31 | 32 | extern const char *__progname; 33 | extern config_t config; 34 | extern bool_t verbose_mode; 35 | 36 | bool_t syslog_enabled; 37 | static FILE *logf = NULL; 38 | static bool_t initialised = false; 39 | 40 | bool_t init_logging() { 41 | if (initialised) 42 | return false; 43 | 44 | config_lookup_bool(&config, "syslog", (int *)&syslog_enabled); 45 | 46 | const char *log_path = NULL; 47 | config_lookup_string(&config, "logfile", &log_path); 48 | 49 | if (syslog_enabled && log_path != NULL) { 50 | panic(1, "Error in configuration file: both syslog logging and file logging are specified."); 51 | } 52 | 53 | if (syslog_enabled) { 54 | openlog(__progname, LOG_PID, LOG_USER); 55 | } else if (log_path != NULL) { 56 | logf = xfopen(log_path, "a"); /* TODO: should come up with a log rotation plan */ 57 | } else { 58 | logf = stderr; 59 | } 60 | 61 | initialised = true; 62 | return true; 63 | } 64 | 65 | bool_t shutdown_logging() { 66 | if (!initialised) 67 | return false; 68 | 69 | if (logf && logf != stderr) 70 | fclose(logf); 71 | 72 | return true; 73 | } 74 | 75 | char *getlogdate() { 76 | char *tp; 77 | time_t tm = time(NULL); 78 | 79 | tp = ctime(&tm); 80 | stripnl(tp); 81 | return(tp); 82 | } 83 | 84 | void xlog(int prio, char *fmt, ...) { 85 | va_list ap; 86 | 87 | va_start(ap, fmt); 88 | vxlog(prio, fmt, ap); 89 | va_end(ap); 90 | } 91 | 92 | void vxlog(int prio, const char *fmt, va_list ap) { 93 | if(prio == LOG_DEBUG && !verbose_mode) 94 | return; 95 | 96 | if (!initialised) { 97 | logf = stderr; 98 | } 99 | 100 | if (syslog_enabled) { 101 | vsyslog(prio, fmt, ap); 102 | } else { 103 | fprintf(logf, "%s [%d]: %s: ", getlogdate(), getpid(), __progname); 104 | vfprintf(logf, fmt, ap); 105 | fprintf(logf, "\n"); 106 | fflush(logf); 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/gui.c: -------------------------------------------------------------------------------- 1 | /* gui.c 2 | * GUI rendering and interface management. 3 | * 4 | * Copyright (c) 2014 Nathan Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "asciimatic.h" 28 | #include "logging.h" 29 | #include "main.h" 30 | #include "utils.h" 31 | 32 | /* Clobal config stuff */ 33 | extern config_t config; 34 | 35 | extern IplImage *src; 36 | extern int first_thresh; 37 | extern int second_thresh; 38 | 39 | /* GUI painting state */ 40 | static int lbutton_down = 0; //default to up 41 | static int dirty = 1; /* Only repaint if there's something to repaint */ 42 | 43 | static const char *window_name = "Asciimatic"; 44 | 45 | IplImage *edges; 46 | 47 | 48 | 49 | static void 50 | on_trackbar(int val) { 51 | (void)val; 52 | dirty = 1; 53 | } 54 | 55 | static void 56 | on_mouse(int event, int x, int y, int flags, void *p) { 57 | (void)flags; 58 | (void)p; 59 | 60 | if (event == CV_EVENT_LBUTTONDOWN) { 61 | lbutton_down = 1; 62 | } 63 | else if (event == CV_EVENT_LBUTTONUP) { 64 | lbutton_down = 0; 65 | } 66 | 67 | if (!lbutton_down) { 68 | return; 69 | } 70 | 71 | dirty = 0; 72 | 73 | CvRect roi = cvRect( 74 | MAX(x-11, 0), 75 | MAX(y-11, 0), 76 | 11,11); 77 | cvSetImageROI(edges, roi); 78 | cvSetZero(edges); 79 | cvResetImageROI(edges); 80 | } 81 | 82 | void 83 | init_gui() { 84 | int max_thresh1, max_thresh2; 85 | 86 | if (!config_lookup_int(&config, "max_threshold1", &max_thresh1)) { 87 | panic(1, "Missing default maximum threshold1 parameter in config file"); 88 | } 89 | if (!config_lookup_int(&config, "max_threshold2", &max_thresh2)) { 90 | panic(1, "Missing default maximum threshold2 parameter in config file"); 91 | } 92 | 93 | cvNamedWindow(window_name, CV_WINDOW_NORMAL); 94 | cvCreateTrackbar("low_th", window_name, &first_thresh, max_thresh1, on_trackbar); 95 | cvCreateTrackbar("high_th", window_name, &second_thresh, max_thresh2, on_trackbar); 96 | cvSetMouseCallback(window_name, on_mouse, NULL); 97 | } 98 | 99 | void 100 | gui_loop() { 101 | char c; 102 | 103 | while ((c = cvWaitKey(50)) != 27) { 104 | if (dirty) { 105 | edges = detect_edges(edges, src); 106 | } 107 | cvShowImage(window_name, edges); 108 | } 109 | //TODO: make this nicer than just as we exit the loop 110 | asciify(edges); 111 | cvReleaseImage(&edges); 112 | } 113 | 114 | void 115 | shutdown_gui() { 116 | cvDestroyAllWindows(); 117 | } 118 | -------------------------------------------------------------------------------- /tests/test1.txt: -------------------------------------------------------------------------------- 1 | Size of character image: 988 x 60 2 | Characters correspond to 4x8 pixel blocks 3 | _+ ^ ----- 4 | Y+------_X-X-X_o - 5 | _----A-- A+ A-A 6 | -------^ ----^--- XX 7 | X-+ ------^ _/--^-A ^-+^J 8 | ^o------o- -+-- -^--^---+-A AYA 9 | JL--oX- -A A --J-- X ^X 10 | VLA++ -JX A-o+ Y A+ 11 | A--_ -| -^V 12 | -A--- T-X -- 13 | -A+Y -o|+J+\A _-- 14 | |TL --+_/ J -A-- 15 | -LAA --A J _--A+ 16 | VYV^- _TT+ L^X 17 | +A+ -J L-- --V-+X V- 18 | -V ------ X / 19 | -Xo -T ^ 20 | Lo A-o A-^^-A-A 21 | ^ AA Y |V AX X^- 22 | A-+ A^ X- ^o /AX-Lo -L^A- 23 | \ -V +X-YX_-A X^TX- 24 | |+ _V _^---V X+ _--J VX+ A- 25 | o / +X -| A +J- _AA -+V 26 | AY _/ | A^--+ +^V 27 | + / -o A^ 28 | V _-X+ T __ 29 | / JXVY | A-^ 30 | _T /L- Y- -^-o- 31 | / AXV +V--+_VVV J- 32 | ^V-^+VJ _XJ / -^ :-- 33 | -^J X+ |J+---^V 34 | ----+ -A+ ----- 35 | V^---_-^+ 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/test6.txt: -------------------------------------------------------------------------------- 1 | ^--^__--^_^ 2 | - ^o^A--_-^ _ --^^_+ 3 | o-^^+---^-^_Jo ^^Yo: '^J_-^A^ _^ \\^ 4 | ^o-YT+^--To-^oTLo\/o^oXL^Ao^oXXT\_ X-^-' ^\ ^_ \ 5 | XAX/TT+--A^AA\^+JLALXTJX+X+-XJ/+^J_^ \-Jo\o^-+oooTo-+\ 6 | ^^-XoA++AXoo/ALoY\o\XJYo_oXo_^oo+J-oA^o^_^Jo^-\\^-+LT+XJ^\A^ A^^ 7 | AXA\JAooT+J-o\\oTo^'/TAL-X'o^^^o-X +^A^L^X oAJoTo-Ao+XXoAoAoA-To^ 8 | A/o^+|o-^-oVLL-^Ao\o^AAAAoA+^\^+oAY/^ T-| ^o_TXJ\Ao^ooXJXoo-_Lo-^ 9 | '-J^-Y^+AX^^ +o--YL\|L-oA:^ oAo-^J^o\T ^:X YL+ooY--^/J^+AAA-o^oLA|YJ 10 | oYoV^^VX-Lo ^V XT\ L+YA+o _^AT '- ^V/JAJ^oo XooLJ+AXAAAo-V\\|oT 11 | T+AoY+Xoo|^J^X\oJ+/-AXTLLV '^\oo-o-^ ---A-o-o^\J YoV'X^Xoo+J/ ^o^L/ 12 | AYLoXLL^XXoo\AAo-\^AJ Y-:-YA^T ^VYJ -/AY -oX\ +o^'Y 13 | \AJVoAJAAL-VJXo^Y ^-^ L o -^ 'YX / X\^ 14 | L^^oAVoo^YoL--V\^ ^J\^o-oo \ :o // :^\o XY\ 15 | X^J|XAoJAoX _^/\\ --XT-o^' ' V A ^V^o_\\o/ X 16 | V^-^J-YJA-^^^^-JTYoAJ-ooXJ-+ ^YY +Y- ^JJ^/ \^^^ 17 | ^^^ --- ^o^:-^^o_^:^Xo^' o-L^^ -^^ Y -/+^--^^T ^_ \ |_^/ 18 | o\^ --^--^o-^^-^//X+^^Y^ /AoAX-T-Y^/^/ ^\_^^ / ^/ 19 | -\^_^-_--J_o--o^-^^-^ L-oLoAV/X^ / X^^/- 20 | -- o^^-^^-^A ---+- --+AT^T J ^_^__o ----_-^-^ 21 | ^^^ YA ^JA J-^-^- T^-T 22 | AT^^_^^ ^JJV 23 | o/ ^-- Y T\ 24 | / ^Yooo^^\JX -\ 25 | ^/YooJ+L ^_-^' Y^^\ 26 | o/+LTo|TXoAT Y T 27 | oAYAXLX^X+JL ^Y 28 | ^-_o^^ o^-^^ 29 | oJ ^/ \ A 30 | X LoV -/ | 31 | \\ ooo/^o--\ ^| 32 | |'X-V-XJTo\o o 33 | /^ATV/+V'-JLXXY 34 | J /-^-^-XX-TXoT+Xo+oJAoL_o-+^o_+ J 35 | T\-^oX^^-AY-^ -^-TJo^oTY^-+LXYo-^+XX^_/oXAo-T^_----\ 36 | ooo^o+X^Ao/A+ooYXoVooo+o-^VoX+JA^o-oAA-A+AoTXAVXX\^^T-\ 37 | LX-oooo-YTJAoY--ATLYA+XJoYAX-XVAX-XJ^ooXAV^J\oA+oXJA o/ 38 | +---_-------^--V-JJoAVo-+oV^AXTAA_^TA^o+J:ooA^-oALo---oA-JoX^-TJAT-^-oX^o^^^------_--o 39 | ^_ - 'AA+_-' ^TJ^J-:A^+J^XYXooXXooA+^'o\AooA-T^--\-ooooJoLoo-\X^A-L^oJ^A---^ 40 | _-+o-Lo+o_^-ooo++--^-^-^o-^-+----_--: -: __-- ^- __^-^_--+ -- --_--_------__-------o-_-------^-oA:_- 41 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* main.c 2 | * The entry point. 3 | * 4 | * Copyright (c) 2014 Nathan Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "asciimatic.h" 26 | #include "gui.h" 27 | #include "logging.h" 28 | #include "utils.h" 29 | 30 | config_t config; 31 | 32 | bool_t verbose_mode; /* Log LOG_DEBUG messages, bounds checking, etc? */ 33 | 34 | extern const char *__progname; 35 | const char *input_filename; 36 | int output_rows; 37 | int output_cols; 38 | 39 | static void validate_config(int argc, char **argv) { 40 | char optch; 41 | extern int optind; 42 | extern char *optarg; 43 | bool_t show_usage = false; 44 | bool_t show_version = false; 45 | bool_t valid_usage = true; 46 | 47 | 48 | extern FILE *output_file; 49 | output_file = stdout; 50 | 51 | while ((optch = getopt(argc, argv, "ho:v")) != EOF) { 52 | switch (optch) { 53 | case 'o': 54 | output_file = xfopen(optarg, "w"); 55 | case 'v': 56 | show_version = true; 57 | break; 58 | default: 59 | valid_usage = false; /* FALLTHROUGH */ 60 | case 'h': 61 | show_usage = true; 62 | break; 63 | } 64 | } 65 | 66 | if (show_version) { 67 | printf("%s version %s\n", __progname, VERSION_STRING); 68 | exit(0); 69 | } 70 | 71 | argc -= optind; 72 | argv += optind; 73 | 74 | if (argc != 3) { 75 | show_usage = true; 76 | goto done; 77 | } 78 | 79 | output_cols = strtol(argv[0], NULL, 10); 80 | if (output_cols== 0 || output_rows > 1024) { 81 | panic(1, "Bad column count size"); 82 | } 83 | output_rows = strtol(argv[1], NULL, 10); 84 | if (output_cols == 0 || output_cols > 4096) { 85 | panic(1, "Bad row count size"); 86 | } 87 | input_filename = argv[2]; 88 | 89 | done: 90 | if (show_usage) { 91 | fprintf(stderr, "usage: %s [options] \n", __progname); 92 | fprintf(stderr, " -h: display this message\n"); 93 | fprintf(stderr, " -o : output ASCII image to file rather than stdout\n"); 94 | fprintf(stderr, " -v: show version\n"); 95 | exit(valid_usage ? 0 : 1); 96 | } 97 | 98 | } 99 | 100 | /* Parses the configuration file. Returns whether the file is present (e.g. whether we are 101 | * using default values. 102 | */ 103 | static bool_t read_config() { 104 | config_init(&config); 105 | 106 | char *cf_path; 107 | if (asprintf(&cf_path, "config/%s.cfg", __progname) == -1) { 108 | panic(1, "Can't allocate space for asprintf()"); 109 | } 110 | 111 | FILE *cfile = xfopen(cf_path, "r"); 112 | if (config_read(&config, cfile) == CONFIG_FALSE) { 113 | panic(1, "Can't parse %s:%d : %s", 114 | config_error_file(&config), config_error_line(&config), 115 | (config_error_text(&config) ? config_error_text(&config) : "")); 116 | } 117 | 118 | free(cf_path); 119 | return true; 120 | } 121 | 122 | int main(int argc, char **argv) { 123 | read_config(); 124 | validate_config(argc, argv); 125 | 126 | init_logging(); 127 | init_asciimatic(input_filename, output_rows, output_cols); 128 | init_gui(); 129 | 130 | gui_loop(); 131 | 132 | shutdown_gui(); 133 | shutdown_asciimatic(); 134 | shutdown_logging(); 135 | 136 | config_destroy(&config); 137 | } 138 | -------------------------------------------------------------------------------- /tests/test4.txt: -------------------------------------------------------------------------------- 1 | Size of character image: 988 x 60 2 | Characters correspond to 5x11 pixel blocks 3 | 4 | T----------------------------------------------------------------------------------| 5 | | -^--^ | 6 | | ^^- | 7 | | ^^^T | 8 | | ^^^ ------^---T -----^ | 9 | | ^A ---^---- -^ o\ | 10 | | ^Y- ^^^ J +\ | 11 | | oX Ao- _ ^\L | 12 | | oV /o \A | 13 | | /V / A^^ | 14 | | A/ ---__-T -T | 15 | | / o _'^Y- | 16 | | A^ AY -----L-^ AV ---_ | 17 | | | ^/ --^--^- +| -V^ _ - | 18 | | | / ^^ ^^A -_-- V+ Y ^o--_o- | 19 | | | |Y +/ ^---^-^ JA LA --- | 20 | | | - /-^A^oo----^^--A^^ Y^ | 21 | | X -L \L - /V^-_ --^--Y^- ^^ _^ | 22 | | VA A \__ --- ^-- AT __ LY | 23 | | V^ VL ^X _-^ Y | 24 | | -X X\^ ^---Y^T | 25 | | X------^V^- ^ T-T--^ -- | 26 | | V -^^-_\-\^ ^ Vo-_^-----\ | 27 | | L L --T \^ ^ _ oX | 28 | | VL Y| X^ V+ \A -^ ------V | 29 | | \LLAYT A' \L Y ^^- oX | 30 | | \\XV_ XX \ LT^^AY ^---^-^-^ | 31 | | \\\^A:X^^ A\ A^^^-_T -^--- | 32 | | ^LAo---A'XAV\ ^_- L--_- | 33 | | A^--^^^V\\V\ -^: _ -- ---------_^- | 34 | | ---T +\A^^ ^A | 35 | | \A-__^ --^AT ^ | 36 | | \\ -----_- - ---- ^X/ | 37 | | -\\^^ --^-- ---_-^ ^o/ | 38 | | --_o\--^_ ^XT^V | 39 | | _--^-^ -\L A^^ ^^- / | 40 | | --L-L-- \+ +--^ -^_T /' | 41 | | ---- \\ --_-^ -^A ^/ | 42 | | ^-^^T o\\+ ^_- -\ -^o---^_ / | 43 | | ^_^- A\\\ o/ ^^- ---X^ | 44 | | ^^- L +\o^ Y ^^- AV | 45 | |^Y- ^A A^^-^X -^AT o/ -- | 46 | Lo V ------- -X ^^-- --^^ | 47 | | AA o^TA-T -^A-- / ^VT-Y----^L-\^ | 48 | | YA/ A-^ /^ / / Y Y | 49 | | Y/ -A-^ oV X--_--------+Y | 50 | | Y^ oVATA-X L-_----_---o | 51 | | Y+---X^ A--_-T | 52 | | ------ | 53 | | |---| |----| -_--- -^_-^ L-------------_^L |--------------T | 54 | | | | | | ^^- AJ^ | ------_ \A | ---------| | 55 | | | | | | /V ^------^^ \o | | -\ | | |T T | 56 | | | ^------- | V /T VA L | |------/ | | L---------T | 57 | | | | | | | | | XV | | | 58 | | | L------| | A \^ ^V -/ | o--------^^T | T---------- | 59 | | | | | | V\ -_----^^T ^/ | | | L---------- | 60 | | | | | | -L^L -^^ | | | | | 61 | | L---L L----T ----------^-^ L----A L--------------L | 62 | L----------------------------------------------------------------------------------| 63 | -------------------------------------------------------------------------------- /tests/test2.txt: -------------------------------------------------------------------------------- 1 | Size of character image: 988 x 60 2 | Characters correspond to 3x5 pixel blocks 3 | 4 | 5 | ^^ 6 | A V --+-^^A-A^ 7 | A+A^ ^ 8 | +^V V ++A ^ 9 | +^A A-AA^ 10 | ^A^^+ 11 | +T+ 12 | +VV L-+ 13 | T AA 14 | X A ^Y^o \ ++ 15 | A^ ++^- AAVA^ ^+^XA^^ AA+ 16 | AA^ ^+ AAAA TT 17 | AA A+A+ +AA^ ^A + 18 | VA- ^Ao AAA AA 19 | /V V A+A A+^ ^ 20 | AV A +AV +^+ 21 | T^ T - 22 | |+A A ^^--^-^-- /V 23 | A+A VA^--AA^ AA-^^^-^^^A+ A A+ 24 | VA A^A^--^ +X AA V ^^^ A^ 25 | VT V^ AL ^AX AA ^V 26 | AJ ^L^---A T ++-------^-++ ^T+ T 27 | AV^ AX^ |AX+X^^VAAA+^V-\A AXXA^+A-L-^--^X^- A+^ 28 | ^V+A TYA V ^XAAA^AA ^AA+ V A+A-A+AA^ -^-^+-+^ ^A+ 29 | A-AX T AAT ++ AA^ A-+ A A^A^ A^A TV 30 | A+AA^XA AA AA A^^ A^A 31 | ^L AAV AJ AX +T + AA A 32 | ^AV | / +X VA T^ T^A ^ TAA 33 | AX | AAVA++^+ ^ ^T A+XA^+^ ++AV 34 | | V V ^A-^^A^ AA AA AAT +VT^ 35 | +A^ T ++A++X ^+ A ^^JA T 36 | X A ^V+-^--++A A+++A^ A^+ A AV 37 | XX | +V^ ^AV A AAAA ^VA Y+ 38 | LA L^ T A++AAAo^A^- ^ AA^ A ^T V +A^ V+ 39 | AL XA T --V ^-^^-^YT ^T \ A+++-+ ^+ 40 | A ^A A^ +^ ^V A^ V ^T ^ A ^VV 41 | V AA VAAoV+ ^TA ^T +VT 42 | A + ^V T o^ +A+ 43 | A+ V^ o^ ++A^ ^J YV Y^ 44 | T^ A-^T+^A^V^V^ +V --+V ^+A + VV ^X 45 | A^ A^ ^^A^ A^A- L A^VV 46 | A^ YV+^-+ 47 | AV T^ 48 | AAA AA 49 | +V+ L 50 | VA- A++ 51 | AAA ^---A^ +A 52 | +A AA 53 | +A^ A 54 | ----^---^-------^------------A^ AA 55 | ^V+^ AA^ 56 | ^+^^^ A+ 57 | +V+ VA ^^^^ 58 | -------------------------------------------------------------------------------- /src/asciimatic.c: -------------------------------------------------------------------------------- 1 | /* asciimatic.c 2 | * OpenCV driver. 3 | * 4 | * Copyright (c) 2014 Nathan Taylor 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "asciimatic.h" 29 | #include "logging.h" 30 | #include "main.h" 31 | #include "utils.h" 32 | 33 | /* Clobal config stuff */ 34 | extern config_t config; 35 | 36 | static int output_rows; 37 | static int output_cols; 38 | 39 | static int num_threads; 40 | 41 | /* Edge detection stuff */ 42 | IplImage *src; 43 | 44 | int first_thresh; 45 | int second_thresh; 46 | const char *valid_characters; 47 | 48 | FILE *input_file; 49 | FILE *output_file; 50 | 51 | /* Given the supplied set of valid characters, generate the templates we'll be 52 | * matching against. 53 | */ 54 | static IplImage** 55 | init_templates(int char_width, int char_height) { 56 | IplImage **templates; 57 | int num_chars = strlen(valid_characters); 58 | 59 | templates = xmalloc(sizeof(IplImage*) * (1 + num_chars)); 60 | templates[num_chars] = NULL; 61 | 62 | int square_side = MAX(char_width, char_height); 63 | 64 | /* For each character, render each as a square image and then scale it to the 65 | * (char_width x char_height) dimension. 66 | */ 67 | for (int i = 0; i < num_chars; i++) { 68 | cairo_text_extents_t te; 69 | char c = valid_characters[i]; 70 | char letter[2] = {c, '\0'}; 71 | 72 | cairo_surface_t *surface = 73 | cairo_image_surface_create(CAIRO_FORMAT_ARGB32, char_width, char_height); 74 | cairo_t *cr = cairo_create(surface); 75 | 76 | /* Render the text onto the image. */ 77 | cairo_set_source_rgb (cr, 0, 0, 0); 78 | cairo_paint(cr); 79 | 80 | cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); 81 | cairo_set_font_size(cr, (int)(char_height * (4.0/3))); // x px <-> (4/3)x pt 82 | cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); 83 | cairo_text_extents (cr, letter, &te); 84 | cairo_move_to(cr, (char_width / 2) - te.x_bearing - te.width / 2, 85 | (char_height / 2) - te.y_bearing - te.height / 2); 86 | cairo_show_text(cr, letter); 87 | cairo_surface_flush(surface); 88 | 89 | /* Copy the Cairo surface into an IplImage... */ 90 | IplImage *image = cvCreateImageHeader(cvSize(char_width, char_height), IPL_DEPTH_8U, 4); 91 | char *data = xmalloc(char_width * char_height * sizeof(uint32_t)); 92 | memcpy(data, cairo_image_surface_get_data(surface), char_width * char_height * sizeof(uint32_t)); 93 | cvSetData(image, data, char_width * sizeof(uint32_t)); 94 | 95 | /* ...next, convert to grayscale. */ 96 | IplImage *grayscale_image = cvCreateImage(cvSize(char_width, char_height), IPL_DEPTH_8U, 1); 97 | cvCvtColor(image, grayscale_image, CV_RGB2GRAY); 98 | 99 | templates[i] = grayscale_image; 100 | 101 | free(image->imageData); 102 | cvReleaseImageHeader(&image); 103 | cairo_surface_destroy(surface); 104 | cairo_destroy(cr); 105 | } 106 | 107 | return templates; 108 | } 109 | 110 | void 111 | free_templates(IplImage **templates) { 112 | int i, num_chars; 113 | 114 | num_chars = strlen(valid_characters); 115 | for (i = 0; i < num_chars; i++) { 116 | cvReleaseImage(&templates[i]); 117 | } 118 | free(templates); 119 | 120 | cvReleaseImage(&src); 121 | } 122 | 123 | static char 124 | char_for_subimage(IplImage *image, IplImage **templates, IplImage *scratch) { 125 | IplImage **t; 126 | int i = 0, best_match; 127 | double global_maxval = -1.0; 128 | 129 | for (t = templates; *t != NULL; t++) { 130 | double minval, maxval; 131 | 132 | cvMatchTemplate(image, *t, scratch, CV_TM_SQDIFF_NORMED); 133 | cvPow(scratch, scratch, 3); 134 | cvNormalize(scratch, scratch, 1, 0, CV_MINMAX, 0); 135 | 136 | cvMinMaxLoc(scratch, &minval, &maxval, NULL, NULL, 0); 137 | 138 | if (maxval > global_maxval) { 139 | global_maxval = maxval; 140 | best_match = i; 141 | } 142 | i++; 143 | } 144 | 145 | return valid_characters[best_match]; 146 | } 147 | 148 | void 149 | asciify(IplImage *edges) { 150 | int i, j; 151 | int char_height = edges->height / output_rows; 152 | int char_width = edges->width / output_cols; 153 | IplImage *scratch; 154 | 155 | xlog(LOG_INFO, "Characters correspond to %dx%d pixel blocks\n", char_width, char_height); 156 | 157 | IplImage **templates = init_templates(char_width, char_height); 158 | 159 | /* subimage will be size [w*2,h*2] 160 | * http://docs.opencv.org/modules/imgproc/doc/object_detection.html#matchtemplate */ 161 | scratch = cvCreateImage(cvSize(char_width + 1, char_height + 1), IPL_DEPTH_32F, 1); 162 | 163 | for (j = 0; j < output_rows; j++) { 164 | for (i = 0; i < output_cols; i++) { 165 | IplImage *subimage; 166 | 167 | CvRect char_area = cvRect(i * char_width, j * char_height, char_width, char_height); 168 | cvSetImageROI(edges, char_area); 169 | 170 | subimage = cvCreateImage(cvSize(char_width * 2, char_height * 2), IPL_DEPTH_8U, 1); 171 | cvCopyMakeBorder(edges, subimage, cvPoint(char_width / 2, char_height / 2), IPL_BORDER_CONSTANT, cvScalarAll(0)); 172 | 173 | fprintf(stderr, "%c", char_for_subimage(subimage, templates, scratch)); 174 | 175 | cvReleaseImage(&subimage); 176 | } 177 | fprintf(stderr, "\n"); 178 | } 179 | 180 | cvReleaseImage(&scratch); 181 | free_templates(templates); 182 | } 183 | 184 | /* Performs Canny edge detection on an input image. Caller is responsible for freeing the 185 | * allocated memory in the return value. 186 | */ 187 | IplImage * 188 | detect_edges(IplImage *dst, IplImage *src) { 189 | if (dst != NULL) { 190 | cvReleaseImage(&dst); 191 | } 192 | dst = cvCreateImage(cvGetSize(src), 8, 1 ); 193 | 194 | cvCanny(src, dst, first_thresh, second_thresh, 3); 195 | return dst; 196 | } 197 | 198 | void 199 | init_asciimatic(const char *filename, int r, int c) { 200 | if (!config_lookup_int(&config, "threshold1", &first_thresh)) { 201 | panic(1, "Missing default threshold1 parameter in config file"); 202 | } 203 | if (!config_lookup_int(&config, "threshold2", &second_thresh)) { 204 | panic(1, "Missing default threshold2 parameter in config file"); 205 | } 206 | if (!config_lookup_string(&config, "valid_characters", &valid_characters)) { 207 | panic(1, "Missing valid character set in config file"); 208 | } 209 | 210 | src = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE); 211 | if (src == NULL) { 212 | panic(1, "Can't load source image \"%s\"", filename); 213 | } 214 | cvSmooth(src, src, CV_GAUSSIAN, 3, 3, 0, 0); 215 | output_rows = r; 216 | output_cols = c; 217 | } 218 | 219 | void 220 | shutdown_asciimatic(void) { 221 | cvReleaseImage(&src); 222 | } 223 | -------------------------------------------------------------------------------- /tests/test7.txt: -------------------------------------------------------------------------------- 1 | 2 | J 3 | |^ 4 | |T 5 | |L 6 | |T| 7 | LJY_ 8 | JJV| 9 | LJT| 10 | |+o| 11 | ooLTL^ - 12 | o oJ||V| o 13 | | JooXAA |L 14 | |Y^/oLAJ\^|L 15 | L ||JYYL-AX-X| 16 | || | X A^ T| 17 | --^ ||Y L | |V^||| 18 | LXo L| | | |o |Y| 19 | YA o ^- Y+--+--L-L-A^ 20 | --_-o-\ -_ -^ oY o++_ | YT - oA | | ToYL| +X o 21 | A-- A---JY--||---- --_oTJL' | o^ Y--V-\^|\ oLX -T-Y+YoTY^^ +' JL | 22 | ------o-o-o-Ao L_oALJ^| |TLX^JT | oo-o J-^o- TT-^-o \JLo+-------_A-o ^ |^- | -JT -L^- -_ || ^X-- -+o L|o 23 | A|T---_-----^ - -T----+---o-+^-- ^---T ATo-T -A-+oJ+-+-A+ --T-- AT--VL--------A---X+---Y---T -LA+A AVL Yo| TJXA- 24 | ^LLo----Y-------\ o-o _- o- --^ -^ -^ -_ -A--+o---+-T+----T-----o--T---T-X-----X T--L----X-o^^T-Lo-Xo \A -_ -^ L| ^|-Ao 25 | VYY\---oL--TY X-----------X-----oV--L/-VL+--Lo ATo LJ LX^ -oALL- LJ LoLJ LoX-|LJ| L-T LJ LT| |AXYTLYoXo|J+JYL-LLT AV_ ^ --Vo J ^-^-LL^Yo-+o-+-AT--o 26 | ---------AoLT |ToTT VTTT-To-oT||XTToT |Xo+++------o|-o-^o-oo---TXT o- T|J^ YT^-|Lo| L-| T-o T|| |T|LJL|L|JL----L-----VT JAJoX-^|L----+^o^|T+--^ T--|o-_-T+-A-oLLTL||-T--++AT--- 27 | - A-VA--|AoY- |LoLY XoLJ-LXY LY|L/LLJ |-LJJLL/LL-LL|LY /JXLJ L||L- LY LoA- -o |o | A^Y L-T LYL -oX|oToo-o-|-oJ-JTTAoo TJL---o---_--TA-JA--LA-A-_| o|LTXJ+J-T--|TA+---LT T-+^oL|-- |--+ 28 | LT |A+LT |JXY/ L|TTLTL-JTLLL|T|| YTTT|TJTTL-Y-|AT-TTTXTXXT||T || |||| AXLLV|T| T+| ooV o^|--------- LYLLVL|JLTL++XX|L-VLV|-A-X||+\oTV^AY TVoJYoX--X_^ ||L|Y -o -YA-+-^-TT Y || |-- |LA- 29 | |ooA- J---- -A-A--X-^+YT-+----|+^Y-AYAoA+LAL^LAL-ALAX-Y|---L--o----+o--LoL----X_------JAToTTYTTYT-_Y|AYTATT-XYAXo-o- |---L|L--X^L+o--J TX||+|--A- LX|| +|XJo-TL-+X-+^-| -||-+A--_ LA-- 30 | LY Y || |AYL/_LJALTYL-J+Lo-X:-oo|oVLTLXJLLJJVLLXAXJLALY^JL\Y -|AJ- ^^ ---o-----||AT+--Ao---L-L+_-J-J-|^|^-AT--T|oJTL+T^|^ ||----|--o+|^ L-||-- o_o ||TX\ |LYoA-o-+-V++T|Ao^-AJ|^A|L+A-oo-^ 31 | +o |-o | _A AA--oAXXXoVoTT|LT+XLATooAALo-LY+oLA+oAAX-+Y-XLAL-++-+L--oT----+ooToT |oA-L- L--oLXX-A--L-^VL|TL-+YA-|-Xooo| o^ |AT-AV+^-AXT-|T--YX+|YALL--oAX---|---AoAT|A---YoTTLA+++-A+-- 32 | --- |LLJL_ TXLY| L|YV-+L-AVL+-L^---o--TXY-ALo-J-ATX-LJTXA|Y^V---^oo----+--^---LLooo--+TTATL||_ o oLLLLoTA---L-ATYJLLLLA-LJo+o-L---_J--T-oL-AoT+o--^-A-TA|-o+--^Y | |YLoo+TJL+--XA^---L\L- 33 | -----L--T--+-----LJL^---^--Xo-Y--AoA+-^----T-TX+-oo-++ -Y--AXV-AL-^A-_--A T |ooTVoV-VYoo||ooAT|oL-------------VX^---------_^-^---------^^ ------------L----------A---^-J-----+----L-------------^------ 34 | J---^----o_-----oX----ooLo \-----V--------------------^T ^Y oA-----L-LL--LL-------^----------------T --VX 35 | -+-+- X\ 36 | --^+-_ ^^-^^ AA-----T -^ ^ -- 37 | -- -T --- ---+ ------- ----- --o--A-+o- -_ ---- 38 | -- -_ J--L-_- ^_ -----_--o+---L -----^--------T -- ----- 39 | ---A-------- ^---------A^-------_ ^-----^--_ -- ------_ ^-L--o------------ ' ' ---A------- J ^-- +--+ -+ 40 | ^--T-+- -------T --------- ------^-^--^-------- ^ ---_----^L -+---- -----^+L-A-----_ --- ^^---o-- ^-----------+---A--o----_ -- 41 | ^-A^^-T-T---------A- ----- _A-------------^--------- - -A---+------Y--^--- ^---------^------o--o--------^- ----+-- ----^--------- ^---- 42 | ------A----------^---T J---------^_-A-------_-- -^-- ^---^-------X-^-o---- --^-_^T-----^-T_-----L--_--L-T--- -------A+--- -----^-------- ------_-^------A- _--+-------- -T-------------_-- 43 | -----------------------------------------------------------------JV /^A J^ --------------^ --- ---+---------------+---^---------------------+o-----T-T -------------------^--- ------X-^oA-Y--^--X--- 44 | -------------------------------------------------------------------------------- /tests/test5.txt: -------------------------------------------------------------------------------- 1 | Size of character image: 988 x 60 2 | Characters correspond to 6x14 pixel blocks 3 | A- ^^+ /J- Ao 4 | | / |YA\ J^ T^ -ooYAT-^ ^^ -^ 5 | | | ^J :+ oY^ ^^A-^^/V ^ooT' LL -+ ^^o 6 | | | o++-^^ \- -\- ^^+^ X\^^-Y ^X^^-^^ ^ ^^^^ + 7 | | | VALX^A^^_ -\ ^-V JY^^ ^XYoLoA^--- ^^-A -^^ - +^Aoo ^^AT 8 | | | ^ T^^_o^ JAA ^+ Jo^ ^^ /Y-^^AJ-^- ^^ A^^ -^\---A--o^^\^^ 9 | | X -Loo \Y Vo /X- ^^^--^ JAL^^-Y-^ \ -^^ \\- AY 10 | | | -o^ Loo\J/T J^^^Ao^^^-^ LA | | -T -^\ _ T^\ - 11 | | -_---_--- | \Aoo -/ o/_----^-- A//T / | ---A_ \\ T- -^^ _^^T ^^_^^ 12 | | ^ ^ | +--_ \Y:^/ ^o^-A |T' J T To T^-^^_- ^\+ \A -^\ ^^^- ^--^^ \J^ 13 | | T_A--------_-^L^J^+ --A^^^ oA/ ^A-J_-- -YT Y |L ^ -^--\- Y ^^-YT \\- 14 | | -^- Y -^^o^^ ^^^ / +o---- -^--X_VAY | X ^---_- '^\ TA o - _^J \Y 15 | | _A^ A^T +^^--/A\^-\o +Jo- TL/^/^TA------- -AL-^^-J |X Y -- ^- -A\ A\ Y /V ^^- ^^L^^^ +^^ 16 | | / -o^^ +| /L Vo\o_A^-YJ'TAY| ^^^-^^^^T^- T | Lo --^-^- ^-- L/+/^^ +--- J_ ^\o 17 | | ^ ^^-X L |'' J T^o | --^--^+^^\\-L+V | | ---------^-_-^ /| ^' ^YXT -^XTT----------- \^ 18 | |^A- /^T T | | ^o | +^ --^^^^X +- | X -^o +T-- |V oYT ^ X A_ T-------------+^^ 19 | Y Ao^ T L |To +^| -^^ ^^T --'| | | +--^----+----- TA AX | -A^^ 20 | +Y^ | L || ^/ J TAT_^ J J T T^^ -^_--^ ^^-/X:|^^^^ To+ X -\- 21 | o_ -/X X X-^ XX' Y -^ +| :| X^X- ^^^- | TY- | - To\JA+J^ | -T--^------T 22 | oo^- ^- | |Y -A-^XX +| /-^^ AT AY XX+^^- - | X / A^A \ | T 23 | YooT| ^ YT o | ^^^LX^--- T^^- | | |-^ -^o|- X | Y T A V+L^X | 24 | | Y To ^^_-^| | | --+ T-^^ / | | ^^XAV | LA| / Y Yo^ ^+^ | 25 | | | ^^-| VT- |J + A-^ J/ ^-' o| | | L^^ | L+| TX--' o/o | 26 | | |+^^^ | YJ +A o^T ^^ T+^^ ^V\| |o-T ---L---- / A------^---'VV ^ +- o 27 | | TT | '| ^T+/ ^YA ^\^--|/ -^o--^- |Y\\ T | Y---++A 28 | L+- A\ Y -/| '/ ^/ ^X ^L^ |^ \\^ | ^T-V-o--^ 29 | | ^^Ao_ T JY^| -/ +/ -/T\ \o | \\ | Y ^^A- 30 | J|^ -Jo Y o- ^ o JX /Y ^- |V\ T\o L -T- | 31 | oT ^J |' ^ JA/ -----_ XY X- \| \^- VY_ | oA--------- 32 | J| -| |L // XY X ^ \ \ \^- | | 33 | oo ^A |- AV ^/ | J^ 'X \+^ | JT 34 | oX J| A/ ^- +- /T \ _------------T ^^'+|^ \\ Y | --- 35 | Lo J| o/ YV-^^T A^-/ J^- Lo | o^^ ^ +-^ | | -L- 36 | J| ^/ ^^^ ^Y T | ^YX^ V^ ^Lo L | 37 | XT JA Jo- V L | | ^ T\A TT Jo+TX+ A L -^^_ 38 | oJ ^V J/ ^^_oX_^- \ / oT | | \\ X_ ^ ' | | 39 | | +/ ----^ -^_^^ J ' -+YX- L^ | |X \\ ^\^+-+ |LX+------------+ 40 | |' / -^-^- --^^LLA JYX | _--_- ^ | A --^V^------------^------------T^V 41 | T|-^-_Y ^JY' -_^A -A-+XA' AX --T-T-TA-AY-------^---XT ^ +/ V\ +T 42 | o| ^Y --^^ VT o/ ^^^- |Y /+ L \^ Lo 43 | 'o L^T | ^Y +^oXL--------------^Y ^^- o/-o- +- -+ A | 44 | |X----------^-A | oo^^o^T TA_J ---A T---------------^ ^-' -^--A-^- ---^^ _^ 45 | L^J T^ ^- L - | +^-^^-^ | - 46 | J| \Ao X --A | T ^ 47 | oo -J- L-_^ \ L -^J---_---^-- | | T\^ 48 | oY ^^--^X--_-o Lo ^^--^ J | / -AY- 49 | XJ /^V \X ++-A-- ^- X-|^^ L +XX^\\ 50 | :| -^o o T T^-^- TAY ' | TXAT -\^ 51 | |-^J | | ^- YA^X L A | ^T \o 52 | T|A- Y-^--^- | YV ----A - YJ/ | - +^^ V^^ 53 | |Y / +'o-_---^-^ ^A+A---^- T-------^_----^-^-/Y Y J\- 54 | Lo ^- '^V -Y--_o-- T ^\ A+ 55 | |Y ^^Y ^- L: V\- +\---------_ 56 | |T _ -- ---------------------------_^^----------------------| \\---_---_-----_ ^-A -- 57 | oo J/T +^- | | 58 | oo JX TX' | |T 59 | Lo ^ TX | 60 | |Y | | 61 | L| o |' 62 | ------------------------------------------------------------------------------------------------^ o--------------A-^-- 63 | --------------------------------------------------------------------------------