~samwhited/avatar

f2411809f12c87169db2d03dc1f23d9570e44045 — Sam Whited 1 year, 4 months ago f493421
Initial public release
7 files changed, 171 insertions(+), 0 deletions(-)

A CONTRIBUTING.md
A LICENSE
A README.md
A avatars.go
A avatars_test.go
A go.mod
A go.sum
A CONTRIBUTING.md => CONTRIBUTING.md +31 -0
@@ 0,0 1,31 @@
## Submitting Patches

To submit a patch, first learn to use `git send-email` by reading
[git-send-email.io], then read the SourceHut [mailing list etiquette] guide.
You can send patches to my general purpose patches [mailing list].

Please prefix the subject with `[PATCH avatar]`.
To configure your checkout of this repo to always use the correct prefix and
send to the correct list cd into the repo and run:

    git config sendemail.to ~samwhited/patches@lists.sr.ht
    git config format.subjectPrefix 'PATCH avatar'

[git-send-email.io]: https://git-send-email.io/
[mailing list etiquette]: https://man.sr.ht/lists.sr.ht/etiquette.md
[mailing list]: https://lists.sr.ht/~samwhited/patches


## License

Licensed under the BSD 2 Clause License ([LICENSE] or
https://opensource.org/licenses/BSD-2-Clause)

[LICENSE]: https://git.sr.ht/~samwhited/avatar/tree/master/LICENSE.md


### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you shall be licensed as above, without any
additional terms or conditions.

A LICENSE => LICENSE +23 -0
@@ 0,0 1,23 @@
Copyright © 2014 The Soquee Contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

A README.md => README.md +21 -0
@@ 0,0 1,21 @@
# testlog

Package **`avatar`** contains functions for creating default user avatars.

```go
import (
	"code.soquee.net/avatar"
)
```


## License

The package may be used under the terms of the BSD 2-Clause License a copy of
which may be found in the [`LICENSE`] file.

Unless you explicitly state otherwise, any contribution submitted for inclusion
in the work by you shall be licensed as above, without any additional terms or
conditions.

[`LICENSE`]: ./LICENSE

A avatars.go => avatars.go +60 -0
@@ 0,0 1,60 @@
// Package avatar contains functions for creating user avatars.
package avatar // import "code.soquee.net/avatar"

import (
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"net/http"

	colorHash "mellium.im/xmpp/color"
)

const (
	edgeLen = 512
)

type circle struct {
	p image.Point
	r int
}

func (c *circle) ColorModel() color.Model {
	return color.AlphaModel
}

func (c *circle) Bounds() image.Rectangle {
	return image.Rect(c.p.X-c.r, c.p.Y-c.r, c.p.X+c.r, c.p.Y+c.r)
}

func (c *circle) At(x, y int) color.Color {
	xx, yy, rr := float64(x-c.p.X)+0.5, float64(y-c.p.Y)+0.5, float64(c.r)
	if xx*xx+yy*yy < rr*rr {
		return color.Alpha{255}
	}
	return color.Alpha{0}
}

// Handler returns an HTTP handler that renders a PNG avatar based on a hash of
// the request path.
func Handler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		c := colorHash.String(r.URL.Path, 187, colorHash.None)

		img := image.NewPaletted(
			image.Rect(0, 0, edgeLen, edgeLen),
			color.Palette{c, color.White},
		)
		src := image.NewPaletted(
			image.Rect(0, 0, edgeLen, edgeLen),
			color.Palette{color.White},
		)

		draw.DrawMask(img, img.Bounds(), src, image.ZP, &circle{image.Point{X: edgeLen / 2, Y: edgeLen / 2}, edgeLen * 0.25}, image.ZP, draw.Over)

		w.Header().Set("Content-Type", "image/png")
		/* #nosec */
		png.Encode(w, img)
	}
}

A avatars_test.go => avatars_test.go +22 -0
@@ 0,0 1,22 @@
package avatar_test

import (
	"net/http/httptest"
	"testing"

	"code.soquee.net/avatar"
)

func TestAvatarContentType(t *testing.T) {
	h := avatar.Handler()

	req := httptest.NewRequest("GET", "/avatars", nil)
	w := httptest.NewRecorder()
	h.ServeHTTP(w, req)

	const expect = "image/png"
	ct := w.Header().Get("Content-Type")
	if ct != expect {
		t.Errorf("Unexpected Content-Type: want=%q, got=%q", expect, ct)
	}
}

A go.mod => go.mod +5 -0
@@ 0,0 1,5 @@
module code.soquee.net/avatar

go 1.11

require mellium.im/xmpp v0.9.0

A go.sum => go.sum +9 -0
@@ 0,0 1,9 @@
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/image v0.0.0-20171214225156-12117c17ca67/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/net v0.0.0-20180216171745-136a25c244d3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
mellium.im/reader v0.0.4/go.mod h1:rtqlYmkQriWPf1vKtmH0iIellTSRU/1JUFV8MVS6vek=
mellium.im/sasl v0.1.1/go.mod h1:vmQYTr1V4pFjgdorcqVEwA4WXck2n1JLx30pawPsSuY=
mellium.im/xmlstream v0.13.1/go.mod h1:PDwtcQeiAyF7FrUBRWnVO91nIskvhOFYzOeftngiM7Q=
mellium.im/xmpp v0.9.0 h1:xbrIopplkizD+1cyihUc23L0hFk4sQhZhjetK8l1SDw=
mellium.im/xmpp v0.9.0/go.mod h1:Vs4gsNv+vnF4lYpBD63cjfwLIOqGqmdMJpgMhNwkGro=