Skip to content

Instantly share code, notes, and snippets.

@Cairnarvon
Created August 18, 2012 22:50

Revisions

  1. Cairnarvon created this gist Aug 18, 2012.
    12 changes: 12 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    MW = `MagickWand-config --cflags --ldflags --libs`
    WARNS = -Wall -Wextra -pedantic -std=c99

    .PHONY: all
    all: imgcat

    imgcat: imgcat.c
    $(CC) -o $@ $(MW) $(WARNS) $(CFLAGS) $^

    .PHONY: clean
    clean:
    rm -rf imgcat
    27 changes: 27 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    $ wget -q http://www.secretareaofvipquality.net/maiddog.png
    $ ./imgcat maiddog.png
    ▟████▙██▄█▟▄██▜▙
    ▞▜▙███▄▄▄▄▟██▜▞▚▄
    ▄████████████████▛▘
    ▝▀▀▘ ▖▖███▛▘▄▙▄▞▜██████▀▌
    ▐██▌ ▖▜██▛██████▌ ▀▜██▙▝█▚
    ▗▄▄▖ ▙▟█▌▟▀███▀▀▜█▛▄▟█████▙
    ▗▜██▙█▟████████████████▙
    ▗▄███▛▀▜█████████████████▌
    ▗▄█████▖ ██████████████████
    ▖▗ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜▚▟▀██▄ ▀▀▀▙████████████▌
    ▖ ▗▄▖ ▀█████████████████▘ ▀▀▀▘ ▝▀▀▜█▟████████▖
    ▗▄▄▖ ▝ ▗ ▝▀████████████▘ ▝████████████▘
    ▗▄▄▄▄▟▙▟ ▞▘ ▀█████████▛ ▜▙████████████▜▌▘
    ▗▄███▛██▙▙▖ ▝▀██████▌ ▝▀▀▀▜████▛▀█ ▄▄▄▖
    ▟████████████▄ ▝▀▜██▙ ▚▖ ▄▛ ▄▀██▄▄
    ███▟█████████████▄▖ ▝▀█▖ ▐██▙▄▄▄▄▄▛▘ ▟██▙▄███▄▖
    ███████████████████▙▖ █▌ ▐███████▛ ▝▀████▙▟█▙▄▄
    ▙▟██████████▛▜███████▙▖ ▝▘ ▄▄▖ ▟██▛███▀ ▘▜████▄██▙▄▄▖
    ▜▛█████████▚▗██████████ ▗▟███████▛ ▜▘▗▄▖ ▗▖ ▝▜█████▟▛▙▟
    ▌▗▖▝▀▘▀▀▛▀▗▐████████████▖ ▝ ▜█████████▄█▀▀▛▘ ▘ ▀ ▗ ▜█████▙▟
    ▄▄▄▄██████▀ ██████▄▖ ▗ ▄▄ ▄ ▀▀███████▄█▌ ▗▖▞▀
    ▄▄██████▙▞▘▝▀ ▀▜█▛▚ ▄▄▄▟▄▟▀▗ ▄▜███████▘ ▝▀▘ ▀▀▀
    ▀▀▝ ▀███ ▘▖ ▝▀▀ ▀▀▀▀▀██▙ ▐▟███████▌ ▝▀▀▘
    ▀▀▌ ▖ ▀▛▚ ▐█▛ ▗▄▗▄▖ ▀▀▀▀▀██▙ ▝▘▘▝▀▀▜▀▟▘
    ▗▄ ▀▟██▌▝ ▝ ▝ ▀▚▄▄▄▗
    167 changes: 167 additions & 0 deletions imgcat.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,167 @@
    #include <getopt.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <wand/magick_wand.h>

    void usage(char *argv_0) {
    fprintf(
    stderr,
    "Usage: %s [OPTIONS] FILENAME\n"
    "\n"
    "Options:\n"
    "\t-w N|auto\n"
    "\t\tSpecify width of the output, or `auto' for terminal width.\n"
    "\t\tPreserves aspect ratio if unspecified. Defaults to 80 if both\n"
    "\t\t-w and -h are omitted.\n"
    "\n"
    "\t-h N|auto\n"
    "\t\tSpecify height of the output, or `auto' for terminal height.\n"
    "\t\tPreserves aspect ratio if unspecified.\n"
    "\n"
    "\t-n\n"
    "\t\tNormalise image.\n"
    "\n"
    "\t-i\n"
    "\t\tInvert colours.\n"
    "\n",
    argv_0);
    exit(1);
    }

    int main(int argc, char **argv)
    {
    int width = 0, height = 0, normalise = 0, invert = 0;
    char *shades[] = {" ", "▘", "▝", "▀", "▖", "▌", "▞", "▛",
    "▗", "▚", "▐", "▜", "▄", "▙", "▟", "█"};


    /* Parse options. */

    int c;
    extern int optind;
    extern char *optarg;

    while ((c = getopt(argc, argv, "+w:h:ni")) != -1) {
    switch (c) {
    case 'w':
    if (strcmp(optarg, "auto") == 0) {
    struct winsize w;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    width = w.ws_col;
    } else
    width = atoi(optarg);
    if (width < 0)
    usage(argv[0]);
    break;

    case 'h':
    if (strcmp(optarg, "auto") == 0) {
    struct winsize w;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    height = w.ws_row;
    } else
    height = atoi(optarg);
    if (height < 0)
    usage(argv[0]);
    break;

    case 'n':
    normalise = 1;
    break;

    case 'i':
    invert = 1;
    break;

    default:
    usage(argv[0]);
    }
    }

    if (optind == argc)
    usage(argv[0]);


    /* Try to load image. */

    MagickWand *m_wand;

    MagickWandGenesis();
    m_wand = NewMagickWand();

    if (MagickReadImage(m_wand, argv[optind]) == MagickFalse) {
    perror("Can't into file");
    return 1;
    }


    /* Resize and optionally normalise and invert image. */

    size_t w = MagickGetImageWidth(m_wand),
    h = MagickGetImageHeight(m_wand);

    width *= 2;
    height *= 2;

    if (!height) {
    if (!width)
    width = 160;
    height = h * width / w / 2;
    }
    if (!width)
    width = w * height * 2 / h;

    if (width & 1) ++width;
    if (height & 1) ++height;

    MagickResizeImage(m_wand, width, height, LanczosFilter, 1.0);

    if (normalise) {
    MagickSetImageType(m_wand, GrayscaleType);
    MagickNormalizeImage(m_wand);
    }

    if (invert)
    MagickNegateImage(m_wand, MagickFalse);


    /* Output. */

    for (int i = 0; i < height; i += 2) {
    for (int j = 0; j < width; j += 2) {
    PixelWand *p_wand = NewPixelWand();
    double h, s, l;
    int p = 0;

    MagickGetImagePixelColor(m_wand, j, i, p_wand);
    PixelGetHSL(p_wand, &h, &s, &l);
    if (l > 0.5)
    p |= 1;

    MagickGetImagePixelColor(m_wand, j + 1, i, p_wand);
    PixelGetHSL(p_wand, &h, &s, &l);
    if (l > 0.5)
    p |= 2;

    MagickGetImagePixelColor(m_wand, j, i + 1, p_wand);
    PixelGetHSL(p_wand, &h, &s, &l);
    if (l > 0.5)
    p |= 4;

    MagickGetImagePixelColor(m_wand, j + 1, i + 1, p_wand);
    PixelGetHSL(p_wand, &h, &s, &l);
    if (l > 0.5)
    p |= 8;

    printf("%s", shades[p]);

    DestroyPixelWand(p_wand);
    }
    puts("");
    }

    return 0;
    }