Last active 1 month ago

JPSS "bowdetie" script

racerxdl's Avatar Lucas Teske revised this gist 7 years ago. Go to revision

1 file changed, 36 insertions, 36 deletions

bowdetie.go

@@ -5,9 +5,9 @@ import (
5 5 "image"
6 6 "log"
7 7 "image/png"
8 - "image/color"
9 8 "math"
10 9 "time"
10 + "github.com/nfnt/resize"
11 11 )
12 12
13 13 //var filename = "JPSS1_VIIRS_I01_2017-12-20T07:54:34-02:00.png"
@@ -44,26 +44,8 @@ func IsBlack(r,g,b uint32) bool {
44 44 return r == 0 && g == 0 && b == 0
45 45 }
46 46
47 - func BilinearInterp(x, y float32, q0, q1, q2, q3 uint32) uint16 {
48 - rx := int(math.Floor(float64(x)))
49 - ry := int(math.Floor(float64(y)))
50 - fracX := float64(x) - float64(rx)
51 - fracY := float64(y) - float64(ry)
52 - invFracX := 1 - fracX
53 - invFracY := 1 - fracY
54 -
55 - q0f := float64(q0)
56 - q1f := float64(q1)
57 - q2f := float64(q2)
58 - q3f := float64(q3)
59 -
60 - val := (q0f * invFracX + q1f * fracX + q2f * invFracY + q3f * fracY) / 2
61 -
62 - return uint16(val)
63 - }
64 -
65 47 func LinearInterp(r float32, q0, q1 uint32) uint16 {
66 - return uint16(float32(q0) * r + float32(q1) * (1 - r))
48 + return uint16(float32(q0) * (1 - r) + float32(q1) * (r))
67 49 }
68 50
69 51 func CosineInterp(r float32, q0, q1 uint32) uint16 {
@@ -77,25 +59,43 @@ var numPasses = 4
77 59
78 60 func ProcessBowTie(m image.Image, bt BowTie) {
79 61 var gm = m.(*image.Gray16)
80 - var h = float32(bt.y1 - bt.y0)
81 - for x := bt.x0; x < bt.x1; x++ {
82 - var q0, _, _, _ = m.At(x, bt.y0 - 1).RGBA()
83 - var q1, _, _, _ = m.At(x, bt.y1 + 1).RGBA()
84 - for y := bt.y0; y < bt.y1; y++ {
85 - // Linear / Cosine
86 - var r = float32(y - bt.y0) / float32(h)
87 - gm.Set(x, y, color.Gray16{ Y: LinearInterp(r, q0, q1) })
88 - }
62 + var w = bt.x1 - bt.x0
63 + var h = bt.y1 - bt.y0
64 + var btImg = image.NewGray16(image.Rect(0, 0, w, 2))
65 + // Slice Two lines
66 + for x := 0; x < w; x++ {
67 + btImg.Set(x, 0, gm.At(bt.x0 + x, bt.y0 - 1))
68 + btImg.Set(x, 1, gm.At(bt.x0 + x, bt.y1 + 1))
89 69 }
90 - for i := 0; i < numPasses; i++ {
91 - for x := bt.x0; x < bt.x1; x++ {
92 - for y := bt.y0; y < bt.y1; y++ {
93 - var q2, _, _, _= m.At(x, y).RGBA()
94 - var q3, _, _, _= m.At(x+1, y).RGBA()
95 - gm.Set(x, y, color.Gray16{Y: LinearInterp(0.5, q2, q3)})
96 - }
70 +
71 + btImgRes := resize.Resize(uint(float32(w)), uint(h) , btImg, resize.Lanczos3)
72 +
73 + for x := 0; x < w; x++ {
74 + for y := 0; y < h; y++ {
75 + gm.Set(bt.x0 + x, bt.y0 + y, btImgRes.At(x, y))
97 76 }
98 77 }
78 +
79 + //var gm = m.(*image.Gray16)
80 + //var h = float32(bt.y1 - bt.y0) + 2
81 + //for x := bt.x0; x <= bt.x1; x++ {
82 + // var q0, _, _, _ = m.At(x, bt.y0 - 1).RGBA()
83 + // var q1, _, _, _ = m.At(x, bt.y1 + 1).RGBA()
84 + // for y := bt.y0; y <= bt.y1; y++ {
85 + // // Linear / Cosine
86 + // var r = float32(y - bt.y0) / float32(h)
87 + // gm.Set(x, y, color.Gray16{ Y: LinearInterp(r, q0, q1) })
88 + // }
89 + //}
90 + //for i := 0; i < numPasses; i++ {
91 + // for x := bt.x0; x < bt.x1; x++ {
92 + // for y := bt.y0; y < bt.y1; y++ {
93 + // var q2, _, _, _= m.At(x, y).RGBA()
94 + // var q3, _, _, _= m.At(x+1, y).RGBA()
95 + // gm.Set(x, y, color.Gray16{Y: LinearInterp(0.5, q2, q3)})
96 + // }
97 + // }
98 + //}
99 99 }
100 100
101 101 func main() {

racerxdl's Avatar Lucas Teske revised this gist 7 years ago. Go to revision

1 file changed, 174 insertions

bowdetie.go(file created)

@@ -0,0 +1,174 @@
1 + package main
2 +
3 + import (
4 + "os"
5 + "image"
6 + "log"
7 + "image/png"
8 + "image/color"
9 + "math"
10 + "time"
11 + )
12 +
13 + //var filename = "JPSS1_VIIRS_I01_2017-12-20T07:54:34-02:00.png"
14 + var filename = "JPSS1_VIIRS_I01_2017-12-20T08:39:35-02:00.png"
15 +
16 + type Setting struct {
17 + id int
18 + name string
19 + width int
20 + params [6]int
21 + params2 [6]int
22 + bits int
23 + }
24 +
25 + type BowTie struct {
26 + x0 int
27 + y0 int
28 + x1 int
29 + y1 int
30 + }
31 +
32 + var settings = map[string]Setting {
33 + "I01": {
34 + id: 818,
35 + name: "I01",
36 + width: 6400,
37 + params: [6]int{1280, 736, 1184, 1184, 736, 1280},
38 + params2: [6]int{6, 2, 0, 0, 2, 6},
39 + bits: 31,
40 + },
41 + }
42 +
43 + func IsBlack(r,g,b uint32) bool {
44 + return r == 0 && g == 0 && b == 0
45 + }
46 +
47 + func BilinearInterp(x, y float32, q0, q1, q2, q3 uint32) uint16 {
48 + rx := int(math.Floor(float64(x)))
49 + ry := int(math.Floor(float64(y)))
50 + fracX := float64(x) - float64(rx)
51 + fracY := float64(y) - float64(ry)
52 + invFracX := 1 - fracX
53 + invFracY := 1 - fracY
54 +
55 + q0f := float64(q0)
56 + q1f := float64(q1)
57 + q2f := float64(q2)
58 + q3f := float64(q3)
59 +
60 + val := (q0f * invFracX + q1f * fracX + q2f * invFracY + q3f * fracY) / 2
61 +
62 + return uint16(val)
63 + }
64 +
65 + func LinearInterp(r float32, q0, q1 uint32) uint16 {
66 + return uint16(float32(q0) * r + float32(q1) * (1 - r))
67 + }
68 +
69 + func CosineInterp(r float32, q0, q1 uint32) uint16 {
70 + var mu = float64(r)
71 + var mu2 = (1 - math.Cos(mu * math.Pi)) / 2
72 +
73 + return uint16(float64(q0) * (1 - mu2) + float64(q1) * (mu2))
74 + }
75 +
76 + var numPasses = 4
77 +
78 + func ProcessBowTie(m image.Image, bt BowTie) {
79 + var gm = m.(*image.Gray16)
80 + var h = float32(bt.y1 - bt.y0)
81 + for x := bt.x0; x < bt.x1; x++ {
82 + var q0, _, _, _ = m.At(x, bt.y0 - 1).RGBA()
83 + var q1, _, _, _ = m.At(x, bt.y1 + 1).RGBA()
84 + for y := bt.y0; y < bt.y1; y++ {
85 + // Linear / Cosine
86 + var r = float32(y - bt.y0) / float32(h)
87 + gm.Set(x, y, color.Gray16{ Y: LinearInterp(r, q0, q1) })
88 + }
89 + }
90 + for i := 0; i < numPasses; i++ {
91 + for x := bt.x0; x < bt.x1; x++ {
92 + for y := bt.y0; y < bt.y1; y++ {
93 + var q2, _, _, _= m.At(x, y).RGBA()
94 + var q3, _, _, _= m.At(x+1, y).RGBA()
95 + gm.Set(x, y, color.Gray16{Y: LinearInterp(0.5, q2, q3)})
96 + }
97 + }
98 + }
99 + }
100 +
101 + func main() {
102 + reader, err := os.Open(filename)
103 + if err != nil {
104 + panic(err)
105 + }
106 +
107 + m, format, err := image.Decode(reader)
108 +
109 + if err != nil {
110 + panic(err)
111 + }
112 +
113 + log.Println("Found image format", format)
114 +
115 + reader.Close()
116 +
117 + var currSetting = settings["I01"]
118 + var bowTies []BowTie
119 +
120 + bounds := m.Bounds()
121 +
122 + startTime := time.Now()
123 +
124 + // Find head bowtie
125 + var x = bounds.Min.X
126 + for z := 0; z < 6; z++ {
127 + if z == 2 || z == 3 {
128 + x += currSetting.params[z]
129 + continue
130 + }
131 + var csw = currSetting.params[z]
132 + var csh = currSetting.params2[z]
133 + for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
134 + r, g, b, _ := m.At(x, y).RGBA()
135 + if IsBlack(r, g, b) {
136 + //log.Println("Found black pixel at", y)
137 + var nextY = y + csh
138 + if nextY > bounds.Max.Y || nextY + 1 > bounds.Max.Y {
139 + break
140 + }
141 + nr, ng, nb, _ := m.At(x, nextY).RGBA()
142 + n2r, n2g, n2b, _ := m.At(x, nextY + 1).RGBA()
143 + if IsBlack(nr, ng, nb) && !IsBlack(n2r, n2g, n2b) {
144 + bt := BowTie{
145 + x0: x,
146 + y0: y,
147 + x1: x + csw + 1,
148 + y1: y + csh + 1,
149 + }
150 + bowTies = append(bowTies, bt)
151 + y += currSetting.params2[0]
152 + }
153 + }
154 + }
155 + x += currSetting.params[z]
156 + }
157 +
158 + // Fill Bow Ties with red
159 + for i := 0; i < len(bowTies); i++ {
160 + //log.Println("Paiting bowtie", i)
161 + ProcessBowTie(m, bowTies[i])
162 + }
163 +
164 + delta := time.Now().Sub(startTime).Seconds()
165 +
166 + log.Println("Took", delta, "seconds to debowtie!")
167 +
168 + out, err := os.Create("out.png")
169 + err = png.Encode(out, m)
170 + if err != nil {
171 + panic(err)
172 + }
173 + out.Close()
174 + }
Newer Older