package main import ( "os" "image" "log" "image/png" "math" "time" "github.com/nfnt/resize" ) //var filename = "JPSS1_VIIRS_I01_2017-12-20T07:54:34-02:00.png" var filename = "JPSS1_VIIRS_I01_2017-12-20T08:39:35-02:00.png" type Setting struct { id int name string width int params [6]int params2 [6]int bits int } type BowTie struct { x0 int y0 int x1 int y1 int } var settings = map[string]Setting { "I01": { id: 818, name: "I01", width: 6400, params: [6]int{1280, 736, 1184, 1184, 736, 1280}, params2: [6]int{6, 2, 0, 0, 2, 6}, bits: 31, }, } func IsBlack(r,g,b uint32) bool { return r == 0 && g == 0 && b == 0 } func LinearInterp(r float32, q0, q1 uint32) uint16 { return uint16(float32(q0) * (1 - r) + float32(q1) * (r)) } func CosineInterp(r float32, q0, q1 uint32) uint16 { var mu = float64(r) var mu2 = (1 - math.Cos(mu * math.Pi)) / 2 return uint16(float64(q0) * (1 - mu2) + float64(q1) * (mu2)) } var numPasses = 4 func ProcessBowTie(m image.Image, bt BowTie) { var gm = m.(*image.Gray16) var w = bt.x1 - bt.x0 var h = bt.y1 - bt.y0 var btImg = image.NewGray16(image.Rect(0, 0, w, 2)) // Slice Two lines for x := 0; x < w; x++ { btImg.Set(x, 0, gm.At(bt.x0 + x, bt.y0 - 1)) btImg.Set(x, 1, gm.At(bt.x0 + x, bt.y1 + 1)) } btImgRes := resize.Resize(uint(float32(w)), uint(h) , btImg, resize.Lanczos3) for x := 0; x < w; x++ { for y := 0; y < h; y++ { gm.Set(bt.x0 + x, bt.y0 + y, btImgRes.At(x, y)) } } //var gm = m.(*image.Gray16) //var h = float32(bt.y1 - bt.y0) + 2 //for x := bt.x0; x <= bt.x1; x++ { // var q0, _, _, _ = m.At(x, bt.y0 - 1).RGBA() // var q1, _, _, _ = m.At(x, bt.y1 + 1).RGBA() // for y := bt.y0; y <= bt.y1; y++ { // // Linear / Cosine // var r = float32(y - bt.y0) / float32(h) // gm.Set(x, y, color.Gray16{ Y: LinearInterp(r, q0, q1) }) // } //} //for i := 0; i < numPasses; i++ { // for x := bt.x0; x < bt.x1; x++ { // for y := bt.y0; y < bt.y1; y++ { // var q2, _, _, _= m.At(x, y).RGBA() // var q3, _, _, _= m.At(x+1, y).RGBA() // gm.Set(x, y, color.Gray16{Y: LinearInterp(0.5, q2, q3)}) // } // } //} } func main() { reader, err := os.Open(filename) if err != nil { panic(err) } m, format, err := image.Decode(reader) if err != nil { panic(err) } log.Println("Found image format", format) reader.Close() var currSetting = settings["I01"] var bowTies []BowTie bounds := m.Bounds() startTime := time.Now() // Find head bowtie var x = bounds.Min.X for z := 0; z < 6; z++ { if z == 2 || z == 3 { x += currSetting.params[z] continue } var csw = currSetting.params[z] var csh = currSetting.params2[z] for y := bounds.Min.Y; y < bounds.Max.Y; y++ { r, g, b, _ := m.At(x, y).RGBA() if IsBlack(r, g, b) { //log.Println("Found black pixel at", y) var nextY = y + csh if nextY > bounds.Max.Y || nextY + 1 > bounds.Max.Y { break } nr, ng, nb, _ := m.At(x, nextY).RGBA() n2r, n2g, n2b, _ := m.At(x, nextY + 1).RGBA() if IsBlack(nr, ng, nb) && !IsBlack(n2r, n2g, n2b) { bt := BowTie{ x0: x, y0: y, x1: x + csw + 1, y1: y + csh + 1, } bowTies = append(bowTies, bt) y += currSetting.params2[0] } } } x += currSetting.params[z] } // Fill Bow Ties with red for i := 0; i < len(bowTies); i++ { //log.Println("Paiting bowtie", i) ProcessBowTie(m, bowTies[i]) } delta := time.Now().Sub(startTime).Seconds() log.Println("Took", delta, "seconds to debowtie!") out, err := os.Create("out.png") err = png.Encode(out, m) if err != nil { panic(err) } out.Close() }