-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathimage.go
79 lines (72 loc) · 1.67 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
69
70
71
72
73
74
75
76
77
78
79
package main
import (
"image"
"image/color"
)
// An Image is a rectangular grid of Colors. I'm not using the image.Image
// interface for now because my needs are a little different.
type Image struct {
Width, Height int
Pix []Color
}
func NewImage(width, height int) *Image {
return &Image{
Width: width,
Height: height,
Pix: make([]Color, width*height),
}
}
func (i *Image) At(x, y int) Color {
if x < 0 || x >= i.Width || y < 0 || y >= i.Height {
panic("Out of bounds for At() on Image.")
}
return i.Pix[y*i.Width+x]
}
func (i *Image) Set(x, y int, c Color) {
//if x < 0 || x >= i.Width || y < 0 || y >= i.Height {
// panic("Out of bounds for Set() on Image.")
//}
i.Pix[y*i.Width+x] = c
}
func (i *Image) SetLine(y int, c []Color) {
if len(c) != i.Width {
panic("line of wrong length")
}
copy(i.Pix[y*i.Width:], c)
}
// ToneMap scales down the range of colors to 32-bit RGBA. Right now it uses a
// simplistic heuristic: it just scales the values linearly such that the most
// intense channel value is 0xFF.
func (i *Image) ToneMap() *image.RGBA {
var max float64
for j := 0; j < i.Width*i.Height; j++ {
c := i.Pix[j]
if c.R < 0 || c.G < 0 || c.B < 0 {
panic("Negative color values")
}
if c.R > max {
max = c.R
}
if c.G > max {
max = c.G
}
if c.B > max {
max = c.B
}
}
factor := float64(0xFF) / max
img := image.NewRGBA(image.Rect(0, 0, i.Width, i.Height))
for x := 0; x < i.Width; x++ {
for y := 0; y < i.Height; y++ {
c := i.At(x, y)
rgba := color.RGBA{
R: uint8(c.R * factor),
G: uint8(c.G * factor),
B: uint8(c.B * factor),
A: 0xFF,
}
img.SetRGBA(x, y, rgba)
}
}
return img
}