github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/charting/img.go (about) 1 package charting 2 3 import ( 4 "fmt" 5 "image" 6 "image/color" 7 8 "appengine" 9 10 "image/png" 11 12 // Package image/png ... imported for its initialization side-effect 13 // => image.Decode understands PNG formatted images. 14 _ "image/jpeg" 15 _ "image/png" 16 // uncomment to allow understanding of GIF images... 17 // _ "image/gif" 18 19 "bytes" 20 "net/http" 21 "os" 22 23 //"github.com/pbberlin/tools/util" 24 25 "github.com/pbberlin/tools/conv" 26 "github.com/pbberlin/tools/net/http/loghttp" 27 ) 28 29 // An example demonstrating decoding JPEG img + examining its pixels. 30 func imageAnalyze(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { 31 32 c := appengine.NewContext(r) 33 34 // Decode the JPEG data. 35 // If reading from file, create a reader with 36 // reader, err := os.Open("testdata/video-001.q50.420.jpeg") 37 // if err != nil { c.Errorf(err) } 38 // defer reader.Close() 39 40 img, whichFormat := conv.Base64_str_to_img(conv.Img_jpeg_base64) 41 c.Infof("retrieved img from base64: format %v - type %T\n", whichFormat, img) 42 43 bounds := img.Bounds() 44 45 // Calculate a 16-bin histogram for m's red, green, blue and alpha components. 46 // An image's bounds do not necessarily start at (0, 0), so the two loops start 47 // at bounds.Min.Y and bounds.Min.X. Looping over Y first and X second is more 48 // likely to result in better memory access patterns than X first and Y second. 49 var histogram [16][4]int 50 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 51 for x := bounds.Min.X; x < bounds.Max.X; x++ { 52 r, g, b, a := img.At(x, y).RGBA() 53 // A color's RGBA method returns values in the range [0, 65535]. 54 // Shifting by 12 reduces this to the range [0, 15]. 55 histogram[r>>12][0]++ 56 histogram[g>>12][1]++ 57 histogram[b>>12][2]++ 58 histogram[a>>12][3]++ 59 } 60 } 61 62 b1 := new(bytes.Buffer) 63 s1 := fmt.Sprintf("%-14s %6s %6s %6s %6s\n", "bin", "red", "green", "blue", "alpha") 64 b1.WriteString(s1) 65 66 for i, x := range histogram { 67 s1 := fmt.Sprintf("0x%04x-0x%04x: %6d %6d %6d %6d\n", i<<12, (i+1)<<12-1, x[0], x[1], x[2], x[3]) 68 b1.WriteString(s1) 69 } 70 71 w.Header().Set("Content-Type", "text/plain") 72 w.Write(b1.Bytes()) 73 } 74 75 func drawLinesOverGrid(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { 76 77 c := appengine.NewContext(r) 78 79 // prepare a line color 80 lineCol := color.RGBA{} 81 lineCol.R, lineCol.G, lineCol.B, lineCol.A = 255, 244, 22, 0 82 c.Infof("brush color %#v \n", lineCol) 83 84 p := r.FormValue("p") 85 if p == "" { 86 p = "static/chartbg_400x960__480x1040__12x10.png" 87 } 88 if p == "" { 89 p = "static/pberg1.png" 90 } 91 92 f, err := os.Open(p) 93 loghttp.E(w, r, err, false) 94 defer f.Close() 95 96 img, whichFormat, err := image.Decode(f) 97 loghttp.E(w, r, err, false, "only jpeg and png are 'activated' ") 98 c.Infof("serving img format %v %T\n", whichFormat, img) 99 100 switch imgXFull := img.(type) { 101 102 default: 103 loghttp.E(w, r, false, true, "convertibility into internal color format image.RGBA required") 104 105 case *image.RGBA: 106 107 drawLine := FuncDrawLiner(lineCol, imgXFull) 108 109 xb, yb := 40, 440 110 P0 := image.Point{xb + 0, yb - 0} 111 drawLine(P0, lineCol, imgXFull) 112 113 for i := 0; i < 1; i++ { 114 115 P1 := image.Point{xb + 80, yb - 80} 116 drawLine(P1, lineCol, imgXFull) 117 P1.X = xb + 160 118 P1.Y = yb - 160 119 drawLine(P1, lineCol, imgXFull) 120 P1.X = xb + 240 121 P1.Y = yb - 240 122 drawLine(P1, lineCol, imgXFull) 123 P1.X = xb + 320 124 P1.Y = yb - 320 125 drawLine(P1, lineCol, imgXFull) 126 P1.X = xb + 400 127 P1.Y = yb - 400 128 drawLine(P1, lineCol, imgXFull) 129 130 drawLine = FuncDrawLiner(lineCol, imgXFull) 131 yb = 440 132 P0 = image.Point{xb + 0, yb - 0} 133 drawLine(P0, lineCol, imgXFull) 134 135 P1 = image.Point{xb + 80, yb - 40} 136 drawLine(P1, lineCol, imgXFull) 137 P1.X = xb + 160 138 P1.Y = yb - 90 139 drawLine(P1, lineCol, imgXFull) 140 P1.X = xb + 240 141 P1.Y = yb - 120 142 drawLine(P1, lineCol, imgXFull) 143 P1.X = xb + 320 144 P1.Y = yb - 300 145 drawLine(P1, lineCol, imgXFull) 146 P1.X = xb + 400 147 P1.Y = yb - 310 148 drawLine(P1, lineCol, imgXFull) 149 150 } 151 152 SaveImageToDatastore(w, r, imgXFull, "chart1") 153 img := GetImageFromDatastore(w, r, "chart1") 154 155 w.Header().Set("Content-Type", "image/png") 156 png.Encode(w, img) 157 158 // end case 159 160 } 161 } 162 163 func init() { 164 http.HandleFunc("/image/analyze", loghttp.Adapter(imageAnalyze)) 165 http.HandleFunc("/image/draw-lines-example", loghttp.Adapter(drawLinesOverGrid)) 166 }