-
Notifications
You must be signed in to change notification settings - Fork 0
/
pixlist.go
127 lines (119 loc) · 2.73 KB
/
pixlist.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) 2014, J. Salvador Arias <jsalarias@csnat.unt.edu.ar>
// All rights reserved.
// Distributed under BSD2 license that can be found in LICENSE file.
package raster
import "image"
// A PixList raster is a raster in which pixels are stored as a simple list
// of the cells in which the pixel have a non 0 value.
type PixList struct {
// List of the pixels, it is not guaranteed that the list is ordered.
Pixel []Pixel
// Rect is the raster bounds.
Rect image.Rectangle
}
// NewPixList returns a new empty PixList.
func NewPixList() *PixList {
return &PixList{}
}
// Bounds are the bounds of the PixList.
func (p *PixList) Bounds() image.Rectangle {
return p.Rect
}
// At returns the value of the indicated point.
func (p *PixList) At(pt image.Point) int {
if !pt.In(p.Rect) {
return 0
}
for _, px := range p.Pixel {
if px.Eq(pt) {
return px.Value
}
}
return 0
}
// Set sets the value of the indicated point.
func (p *PixList) Set(pt image.Point, val int) {
if val == 0 {
if len(p.Pixel) == 0 {
return
}
if !pt.In(p.Rect) {
return
}
isIn := false
for i, px := range p.Pixel {
if px.Eq(pt) {
p.Pixel[i] = p.Pixel[len(p.Pixel)-1]
p.Pixel[len(p.Pixel)-1] = Pixel{}
p.Pixel = p.Pixel[:len(p.Pixel)-1]
isIn = true
break
}
}
if !isIn {
return
}
if len(p.Pixel) == 0 {
p.Rect = image.Rectangle{}
return
}
if len(p.Pixel) == 1 {
p.Rect.Min.X, p.Rect.Min.Y = p.Pixel[0].X, p.Pixel[0].Y
p.Rect.Max.X, p.Rect.Max.Y = p.Pixel[0].X, p.Pixel[0].Y
return
}
if (pt.X == p.Rect.Min.X) || (pt.X == p.Rect.Max.X) || (pt.Y == p.Rect.Min.Y) || (pt.Y == p.Rect.Max.Y) {
minX, maxX := p.Rect.Max.X, p.Rect.Min.X
minY, maxY := p.Rect.Max.Y, p.Rect.Min.Y
for _, px := range p.Pixel {
if px.X > maxX {
maxX = px.X + 1
}
if px.X < minX {
minX = px.X
}
if px.Y > maxY {
maxY = px.Y + 1
}
if px.Y < minY {
minY = px.Y
}
}
p.Rect = image.Rect(minX, minY, maxX, maxY)
}
return
}
if !pt.In(p.Rect) {
p.Pixel = append(p.Pixel, Pixel{image.Point{X: pt.X, Y: pt.Y}, val})
if len(p.Pixel) == 1 {
p.Rect.Min.X, p.Rect.Min.Y = p.Pixel[0].X, p.Pixel[0].Y
p.Rect.Max.X, p.Rect.Max.Y = p.Pixel[0].X, p.Pixel[0].Y
return
}
minX, maxX := p.Rect.Max.X, p.Rect.Min.X
minY, maxY := p.Rect.Max.Y, p.Rect.Min.Y
for _, px := range p.Pixel {
if px.X > maxX {
maxX = px.X + 1
}
if px.X < minX {
minX = px.X
}
if px.Y > maxY {
maxY = px.Y + 1
}
if px.Y < minY {
minY = px.Y
}
}
p.Rect = image.Rect(minX, minY, maxX, maxY)
return
}
for _, px := range p.Pixel {
if px.Eq(pt) {
px.Value = val
return
}
}
p.Pixel = append(p.Pixel, Pixel{image.Point{X: pt.X, Y: pt.Y}, val})
}