Skip to content

Instantly share code, notes, and snippets.

@Cairnarvon
Created August 18, 2012 22:50
Show Gist options
  • Save Cairnarvon/3390247 to your computer and use it in GitHub Desktop.
Save Cairnarvon/3390247 to your computer and use it in GitHub Desktop.
imgcat, a cat in an image^W^W^Wfor images
$ wget -q http://www.secretareaofvipquality.net/maiddog.png
$ ./imgcat maiddog.png
▟████▙██▄█▟▄██▜▙
▞▜▙███▄▄▄▄▟██▜▞▚▄
▄████████████████▛▘
▝▀▀▘ ▖▖███▛▘▄▙▄▞▜██████▀▌
▐██▌ ▖▜██▛██████▌ ▀▜██▙▝█▚
▗▄▄▖ ▙▟█▌▟▀███▀▀▜█▛▄▟█████▙
▗▜██▙█▟████████████████▙
▗▄███▛▀▜█████████████████▌
▗▄█████▖ ██████████████████
▖▗ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜▚▟▀██▄ ▀▀▀▙████████████▌
▖ ▗▄▖ ▀█████████████████▘ ▀▀▀▘ ▝▀▀▜█▟████████▖
▗▄▄▖ ▝ ▗ ▝▀████████████▘ ▝████████████▘
▗▄▄▄▄▟▙▟ ▞▘ ▀█████████▛ ▜▙████████████▜▌▘
▗▄███▛██▙▙▖ ▝▀██████▌ ▝▀▀▀▜████▛▀█ ▄▄▄▖
▟████████████▄ ▝▀▜██▙ ▚▖ ▄▛ ▄▀██▄▄
███▟█████████████▄▖ ▝▀█▖ ▐██▙▄▄▄▄▄▛▘ ▟██▙▄███▄▖
███████████████████▙▖ █▌ ▐███████▛ ▝▀████▙▟█▙▄▄
▙▟██████████▛▜███████▙▖ ▝▘ ▄▄▖ ▟██▛███▀ ▘▜████▄██▙▄▄▖
▜▛█████████▚▗██████████ ▗▟███████▛ ▜▘▗▄▖ ▗▖ ▝▜█████▟▛▙▟
▌▗▖▝▀▘▀▀▛▀▗▐████████████▖ ▝ ▜█████████▄█▀▀▛▘ ▘ ▀ ▗ ▜█████▙▟
▄▄▄▄██████▀ ██████▄▖ ▗ ▄▄ ▄ ▀▀███████▄█▌ ▗▖▞▀
▄▄██████▙▞▘▝▀ ▀▜█▛▚ ▄▄▄▟▄▟▀▗ ▄▜███████▘ ▝▀▘ ▀▀▀
▀▀▝ ▀███ ▘▖ ▝▀▀ ▀▀▀▀▀██▙ ▐▟███████▌ ▝▀▀▘
▀▀▌ ▖ ▀▛▚ ▐█▛ ▗▄▗▄▖ ▀▀▀▀▀██▙ ▝▘▘▝▀▀▜▀▟▘
▗▄ ▀▟██▌▝ ▝ ▝ ▀▚▄▄▄▗
#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;
}
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment