forked from ichinaski/pxl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimage.go
68 lines (58 loc) · 1.89 KB
/
image.go
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 pxl
import (
"image"
"math"
"os"
"syscall"
"unsafe"
)
const defaultRatio float64 = 7.0 / 3.0 // The terminal's default cursor width/height ratio
// canvasSize returns the terminal columns, rows, and cursor aspect ratio
func canvasSize() (int, int, float64, error) {
var size [4]uint16
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(os.Stdout.Fd()), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&size)), 0, 0, 0); err != 0 {
return 0, 0, 0, err
}
rows, cols, width, height := size[0], size[1], size[2], size[3]
var whratio = defaultRatio
if width > 0 && height > 0 {
whratio = float64(height/rows) / float64(width/cols)
}
return int(cols), int(rows), whratio, nil
}
// scales calculates the image scale to fit within the terminal width/height
func scale(imgW, imgH, termW, termH int, whratio float64) float64 {
hr := float64(imgH) / (float64(termH) * whratio)
wr := float64(imgW) / float64(termW)
scale := math.Max(hr, wr)
scale = math.Max(scale, 1)
return scale
}
// imgArea calcuates the approximate rectangle a terminal cell takes up
func imgArea(termX, termY int, imgScale, whratio float64) (int, int, int, int) {
startX, startY := float64(termX)*imgScale, float64(termY)*imgScale*whratio
endX, endY := startX+imgScale, startY+imgScale*whratio
return int(startX), int(startY), int(endX), int(endY)
}
// avgRGB calculates the average RGB color within the given
// rectangle, and returns the [0,1] range of each component.
func avgRGB(img image.Image, startX, startY, endX, endY int) (uint16, uint16, uint16) {
var total = [3]uint16{}
var count uint16
for x := startX; x < endX; x++ {
for y := startY; y < endY; y++ {
if (!image.Point{x, y}.In(img.Bounds())) {
continue
}
r, g, b := rgb(img.At(x, y))
total[0] += r
total[1] += g
total[2] += b
count++
}
}
r := total[0] / count
g := total[1] / count
b := total[2] / count
return r, g, b
}