~evanj/favicon

c51c1455cebd938de06e9ce0b2a02901b767adde — Evan M Jones 1 year, 11 months ago master
Feat(*): Project init.
5 files changed, 160 insertions(+), 0 deletions(-)

A .gitignore
A favicon.go
A go.mod
A go.sum
A static/index.html
A  => .gitignore +4 -0
@@ 1,4 @@
.now
favicon
now.json
.nowignore

A  => favicon.go +121 -0
@@ 1,121 @@
package handler

import (
	"bytes"
	"fmt"
	"image"
	"image/color"
	"image/png"

	"net/http"
	"strconv"
	"strings"

	// For ICO Encode
	ico "github.com/Kodeworks/golang-image-ico"
)

var (
	min         = image.Point{0, 0}
	alpha uint8 = 255
)

func newImage(width, height int, c color.RGBA) image.Image {
	max := image.Point{width, height}
	rect := image.Rectangle{min, max}
	rgba := image.NewRGBA(rect)
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			rgba.SetRGBA(x, y, c)
		}
	}
	return rgba
}

func paramuint8(val string) (uint8, error) {
	i, err := strconv.Atoi(val)
	if err != nil {
		return 0, err
	}
	if i > 255 || i < 0 {
		return 0, fmt.Errorf("value %s is out of range", val)
	}
	return uint8(i), nil
}

func collectErr(errors ...error) error {
	for _, err := range errors {
		if err != nil {
			return err
		}
	}
	return nil
}

func H(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()

	// Filetype.
	fn := strings.Split(q.Get("fn"), ".")
	if len(fn) < 2 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "must provide filetype")
		return
	}
	ft := fn[1]
	switch ft {
	case "ico":
	case "png":
	default:
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "filetype must be of `ico` or `png`")
		return
	}

	// Get colors and width.
	rColor, rerr := paramuint8(q.Get("r"))
	gColor, gerr := paramuint8(q.Get("g"))
	bColor, berr := paramuint8(q.Get("b"))
	wSize, werr := strconv.Atoi(q.Get("w"))
	hSize, herr := strconv.Atoi(q.Get("h"))
	err := collectErr(rerr, gerr, berr, werr, herr)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, err.Error())
		return
	}

	if wSize > 192 || hSize > 192 || wSize < 2 || hSize < 2 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "image dimensions not in correct bounds, 1-192 inclusive")
		return
	}

	// Put into image.
	c := color.RGBA{rColor, gColor, bColor, alpha}
	i := newImage(wSize, hSize, c)
	buf := bytes.Buffer{}

	// Encoding
	switch ft {
	case "png":
		err = png.Encode(&buf, i)
	case "ico":
		err = ico.Encode(&buf, i)
	}
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, err.Error())
		return
	}

	// Serve to client.
	w.WriteHeader(http.StatusOK)
	switch ft {
	case "png":
		w.Header().Add("Content-Type", "image/png")
	case "ico":
		w.Header().Add("Content-Type", "image/x-icon")
	}
	w.Write(buf.Bytes())
}

A  => go.mod +5 -0
@@ 1,5 @@
module git.evanjon.es/i/favicon

go 1.12

require github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9

A  => go.sum +2 -0
@@ 1,2 @@
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA=
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=

A  => static/index.html +28 -0
@@ 1,28 @@
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Favicon Placeholder as a Service</title>
  <link rel="icon" type="image/png" sizes="32x32" href="/255/0/0/32/favicon.png">
</head>
<body>
  <main>
    <h1>Favicon Placeholder as a Service</h1>
    <p>Use any color favicon placeholder you want, instantly. As either an `ico`
    or `png`.</p>
    <h2>Examples</h2>
    <p>Red favicon, sized 32 pixels, ICO:</p>
    <code>
      &lt;link rel=&quot;icon&quot; type=&quot;image/x-icon&quot; href=&quot;https://favicon.evanjon.es/255/0/0/32/favicon.ico&quot; /&gt;
    </code>
    <p>Burnt orange favicon, sized 192 pixels, PNG:</p>
    <code>
      &lt;link rel=&quot;icon&quot; type=&quot;image/png&quot; sizes=&quot;192x192&quot; href=&quot;https://favicon.evanjon.es/150/64/0/192/favicon.png&quot;&gt;
    </code>
    <p>Edge (browser) green favicon, sized 76 pixels, PNG:</p>
    <code>
      &lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;76x76&quot; href=&quot;https://favicon.evanjon.es/85/218/85/76/favicon.png&quot;&gt;
    </code>
  </main>
</body>
</html>