~dricottone/image2ascii

ref: 4ad980ef244f080f793177b991b50fa6460c1eb8 image2ascii/ascii/ascii.go -rw-r--r-- 2.0 KiB
4ad980ef — qeesung Refactor the code to match the oop mode for easy mock and test 6 years ago
                                                                                
49547468 qeesung
5f88c33e qeesung
c5de7795 qeesung
5f88c33e qeesung
4ad980ef qeesung
49547468 qeesung
4ad980ef qeesung
32c6345e qeesung
5f88c33e qeesung
32c6345e qeesung
4ad980ef qeesung
5f88c33e qeesung
4ad980ef qeesung
5f88c33e qeesung
32c6345e qeesung
4ad980ef qeesung
32c6345e qeesung
4ad980ef qeesung
c5de7795 qeesung
5f88c33e qeesung
4ad980ef qeesung
5f88c33e qeesung
4ad980ef qeesung
5f88c33e qeesung
4ad980ef qeesung
5f88c33e qeesung
c5de7795 qeesung
49547468 qeesung
4ad980ef qeesung
c5de7795 qeesung
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
// Package ascii can convert a image pixel to a raw char
// base on it's RGBA value, in another word, input a image pixel
// output a raw char ascii.
package ascii

import (
	"github.com/aybabtme/rgbterm"
	"image/color"
	"math"
	"reflect"
)

func NewPixelConverter() PixelConverter {
	return PixelASCIIConverter{}
}

type PixelConverter interface {
	ConvertPixelToASCII(pixel color.Color, options *Options) string
}

type PixelASCIIConverter struct {
}

// ConvertPixelToASCII converts a pixel to a ASCII char string
func (converter PixelASCIIConverter) ConvertPixelToASCII(pixel color.Color, options *Options) string {
	convertOptions := NewOptions()
	convertOptions.mergeOptions(options)

	if convertOptions.Reversed {
		convertOptions.Pixels = converter.reverse(convertOptions.Pixels)
	}

	r := reflect.ValueOf(pixel).FieldByName("R").Uint()
	g := reflect.ValueOf(pixel).FieldByName("G").Uint()
	b := reflect.ValueOf(pixel).FieldByName("B").Uint()
	a := reflect.ValueOf(pixel).FieldByName("A").Uint()
	value := converter.intensity(r, g, b, a)

	// Choose the char
	precision := float64(255 * 3 / (len(convertOptions.Pixels) - 1))
	rawChar := convertOptions.Pixels[converter.roundValue(float64(value)/precision)]
	if convertOptions.Colored {
		return converter.decorateWithColor(r, g, b, rawChar)
	}
	return string([]byte{rawChar})
}

func (converter PixelASCIIConverter) roundValue(value float64) int {
	return int(math.Floor(value + 0.5))
}

func (converter PixelASCIIConverter) reverse(numbers []byte) []byte {
	for i := 0; i < len(numbers)/2; i++ {
		j := len(numbers) - i - 1
		numbers[i], numbers[j] = numbers[j], numbers[i]
	}
	return numbers
}

func (converter PixelASCIIConverter) intensity(r, g, b, a uint64) uint64 {
	return (r + g + b) * a / 255
}

// decorateWithColor decorate the raw char with the color base on r,g,b value
func (converter PixelASCIIConverter) decorateWithColor(r, g, b uint64, rawChar byte) string {
	coloredChar := rgbterm.FgString(string([]byte{rawChar}), uint8(r), uint8(g), uint8(b))
	return coloredChar
}