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  }