func index(w http.ResponseWriter, r *http.Request) { fmt.Printf("%v %v\n", time.Now(), r) w.Header().Set("Content-Type", "text/html") maxColors := 256 fmt.Fprintf(w, `<!doctype html> <html> <head> <meta charset='utf-8'> <title>Go Vibrant!</title> <style> * { box-sizing: border-box; margin: 0; } *:focus { outline: none; } *::-moz-focus-inner, *::-moz-focus-outer { border: 0; } body { font-family: sans-serif; max-width: 800px; margin: auto; } h3 { color: #800; } hr { margin: 1em 0; border: 0; border-top: 1px ridge; } h1, form { display: inline-block; } form { margin-left: 1em; } button { background: #9cf; color: #fff; border: 0; padding: .5em 1em; border-radius: 3px; text-transform: uppercase; letter-spacing: .5px; box-shadow: 0 0 5px #ccc; transition: all 125ms cubic-bezier(.8,0,.2,1); cursor: pointer; z-index: 1; position: relative; } button:hover { box-shadow: none; } button:active { box-shadow: 0 0 0 100vmax rgba(153,204,255,1); } input[type="text"] { margin-right: 1em; } </style> </head> <body> <h1>choose an image:</h1> <form action='/' method='post' enctype='multipart/form-data'> <input type='file' name='test' accept='image/*' required> <input type='text' size='4' maxlength='10' name='maxColors' title='maxColors (default: %d)'> <button type='submit' name='vibrant' value='q'>Go Vibrant!</button> </form>`, maxColors) defer func() { fmt.Fprintf(w, "\n </body>\n</html>") }() if r.FormValue("vibrant") == "" { //w.WriteHeader(http.StatusOK) return } fmt.Fprintf(w, " <hr>\n") file, header, err := r.FormFile("test") if err != nil { //w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, " <h3>Error: 400 Bad Request</h3>") return } switch header.Header["Content-Type"][0] { case "image/jpeg": case "image/png": default: if err != nil { //w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, " <h3>Error: JPG/PNG only plz.</h3>") return } } img, _, err := image.Decode(file) file.Seek(0, 0) buf := bytes.NewBuffer(nil) io.Copy(buf, file) file.Close() datauri := fmt.Sprintf("data:%s;base64,%s", header.Header["Content-Type"][0], base64.StdEncoding.EncodeToString(buf.Bytes())) if err != nil { //w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, " <h3>Error: %s</h3>", err) return } if max := r.FormValue("maxColors"); max != "" { n, err := strconv.Atoi(max) if err != nil { fmt.Fprintf(w, " <h3>Error: %s</h3>", err) } maxColors = n } start := time.Now() bitmap := vibrant.NewBitmap(img) palette, err := vibrant.NewPalette(bitmap, maxColors) benchmark := time.Since(start) if err != nil { //w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, " <h3>Error: %s</h3>", err) return } fmt.Fprintf(w, ` <style> figure { box-shadow: 0 0 10px #ccc; } img { max-width: 100%%; display: block; margin: auto; } figcaption { display: flex; flex-wrap: wrap; } figcaption div { flex: 1 1 16.6667%%; padding: 3vw 0; text-align: center; display: inline-block; } textarea { margin: 1em auto; width: 100%%; display: block; height: 12em; resize: none; border: 0; } h2 { text-align: center; }`) awesome := palette.ExtractAwesome() stylesheet := "" for _, sw := range awesome { stylesheet += fmt.Sprintf("%s\n", sw) if sw.Name == "Vibrant" { vendorPrefixingIsAWESOME := fmt.Sprintf("{\n background-color: %s;\n color: %s;\n}\n", sw.RGBHex(), sw.TitleTextColor()) fmt.Fprintf(w, "::selection %s::-moz-selection %s::-webkit-selection %s", vendorPrefixingIsAWESOME, vendorPrefixingIsAWESOME, vendorPrefixingIsAWESOME) } } fmt.Fprintf(w, "%s\n </style>\n", stylesheet) fmt.Fprintf(w, " <figure>\n <img src='%s' alt='something happened'>\n", datauri) fmt.Fprintf(w, ` <figcaption> <div class="vibrant">Vibrant</div> <div class="lightvibrant">LightVibrant</div> <div class="darkvibrant">DarkVibrant</div> <div class="muted">Muted</div> <div class="lightmuted">LightMuted</div> <div class="darkmuted">DarkMuted</div> </figcaption> </figure>`) fmt.Fprintf(w, "\n <textarea readonly onclick='this.select()'>%s</textarea>\n", stylesheet) if len(awesome) != 6 { fmt.Fprintf(w, "<h3>If color swatches are missing which you believe should be present, try increasing <code>maxColors</code> in the text field above.</h3>\n") } fmt.Fprintf(w, "<h2>%v</h2>", benchmark) }
func index(w http.ResponseWriter, r *http.Request) { log.Println("<-", r.Method, r.URL) setStatus := func(status int) { w.WriteHeader(status) statusText := "" switch status { case 200: statusText = "OK" case 400: statusText = "Bad Request" case 500: statusText = "Internal Server Error" } log.Println("->", status, statusText) } w.Header().Set("Content-Type", "text/html") data := &struct { Response bool Error string Selection string Stylesheet string DataURI string Missing bool Benchmark time.Duration DefaultMaxColors int MaxColors int }{DefaultMaxColors: vibrant.DEFAULT_CALCULATE_NUMBER_COLORS, MaxColors: vibrant.DEFAULT_CALCULATE_NUMBER_COLORS} defer func() { t, err := template.New("").Parse(tpl) if err != nil { panic(err) } buf := new(bytes.Buffer) if err := t.Execute(buf, data); err != nil { panic(err) } io.Copy(w, buf) }() if r.Method != "POST" { setStatus(200) return } file, header, err := r.FormFile("test") if err != nil { setStatus(400) data.Error = "400 Bad Request" return } switch header.Header["Content-Type"][0] { case "image/jpeg": case "image/png": default: setStatus(400) data.Error = "JPG/PNG only plz." return } if max := r.FormValue("maxColors"); max != "" { n, err := strconv.Atoi(max) if err != nil || n < 1 { setStatus(500) data.Error = err.Error() return } data.MaxColors = n } img, _, err := image.Decode(file) if err != nil { w.WriteHeader(http.StatusBadRequest) data.Error = err.Error() return } file.Seek(0, 0) buf := bytes.NewBuffer(nil) io.Copy(buf, file) file.Close() data.DataURI = fmt.Sprintf("data:%s;base64,%s", header.Header["Content-Type"][0], base64.StdEncoding.EncodeToString(buf.Bytes())) start := time.Now() palette, err := vibrant.NewPalette(img, data.MaxColors) data.Benchmark = time.Since(start) if err != nil { setStatus(500) data.Error = err.Error() return } awesome := palette.ExtractAwesome() stylesheet := "" for _, sw := range awesome { stylesheet += fmt.Sprintf("%s\n", sw) if sw.Name == "Vibrant" { vendorPrefixingIsAWESOME := fmt.Sprintf("{\n background-color: %s;\n color: %s;\n}\n", sw.Color.RGBHex(), sw.Color.TitleTextColor()) data.Selection = fmt.Sprintf("::selection %s::-moz-selection %s::-webkit-selection %s", vendorPrefixingIsAWESOME, vendorPrefixingIsAWESOME, vendorPrefixingIsAWESOME) } } data.Stylesheet = stylesheet data.Missing = len(awesome) != 6 setStatus(200) data.Response = true return }