aboutsummaryrefslogtreecommitdiffstats
path: root/icat.go
blob: f2c3f08237740ae83e1df33b5e1aafab47258232 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package main

import (
	"bufio"
	"fmt"
	"golang.org/x/image/draw"
	"golang.org/x/term"
	"image"
	_ "image/jpeg"
	_ "image/png"
	"os"
)

func load(filename string) (image.Image, error) {
	file := os.Stdin
	if filename != "-" {
		var err error
		file, err = os.Open(filename)
		if err != nil {
			return nil, err
		}
		defer file.Close()
	}

	img, _, err := image.Decode(file)
	if err != nil {
		return nil, fmt.Errorf("decode %q: %s", filename, err)
	}

	return img, nil
}

func printImg(filename string, cols, lines int) error {
	img, err := load(filename)
	if err != nil {
		return err
	}

	// Try not to stretch the image.
	if img.Bounds().Dy()*cols <= img.Bounds().Dx()*lines*5/2 {
		lines = img.Bounds().Dy() * cols / (img.Bounds().Dx() * 5 / 2)
	} else {
		cols = img.Bounds().Dx() * lines * 5 / 2 / img.Bounds().Dy()
	}

	dst := image.NewRGBA(image.Rect(0, 0, cols, lines))
	draw.ApproxBiLinear.Scale(dst, dst.Bounds(), img, img.Bounds(), draw.Over, nil)

	buf := bufio.NewWriter(os.Stdout)
	defer buf.Flush()
	for y := 0; y < lines; y++ {
		for x := 0; x < cols; x++ {
			r, g, b, _ := dst.At(x, y).RGBA()
			fmt.Fprintf(buf, "\033[48;2;%d;%d;%dm ", r>>8, g>>8, b>>8)
		}
		fmt.Fprintln(buf, "\033[49m")
	}
	return nil
}

func icat(args []string) error {
	cols, lines, err := term.GetSize(1)
	if err != nil {
		return fmt.Errorf("terminal size: %s", err)
	}
	lines-- // Leave a line for the status bar.

	if len(args) == 0 {
		args = []string{"-"}
	}
	for _, f := range args {
		if err := printImg(f, cols, lines); err != nil {
			return err
		}
	}
	return nil
}

func main() {
	if err := icat(os.Args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "Failed: %s\n", err)
		os.Exit(1)
	}
}