repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
dd8dc97
parent
80b3c18
author
Eric Bower
date
2022-08-31 04:20:45 +0000 UTC
refactor(imgs): use go-webp
4 files changed,  +29, -64
M go.mod
M go.sum
M go.mod
+1, -10
 1@@ -16,13 +16,13 @@ require (
 2 	github.com/charmbracelet/wish v0.5.0
 3 	github.com/gliderlabs/ssh v0.3.4
 4 	github.com/gorilla/feeds v1.1.1
 5+	github.com/kolesa-team/go-webp v1.0.1
 6 	github.com/lib/pq v1.10.6
 7 	github.com/matryer/is v1.4.0
 8 	github.com/microcosm-cc/bluemonday v1.0.19
 9 	github.com/minio/minio-go/v7 v7.0.34
10 	github.com/muesli/reflow v0.3.0
11 	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
12-	github.com/nickalie/go-webpbin v0.0.0-20220110095747-f10016bf2dc1
13 	github.com/pkg/sftp v1.13.5
14 	github.com/scottleedavis/go-exif-remove v0.0.0-20190908021517-58bdbaac8636
15 	github.com/yuin/goldmark v1.4.13
16@@ -44,17 +44,14 @@ require (
17 	github.com/charmbracelet/keygen v0.3.0 // indirect
18 	github.com/containerd/console v1.0.3 // indirect
19 	github.com/dlclark/regexp2 v1.7.0 // indirect
20-	github.com/dsnet/compress v0.0.1 // indirect
21 	github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect
22 	github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect
23 	github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 // indirect
24 	github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8 // indirect
25 	github.com/dustin/go-humanize v1.0.0 // indirect
26-	github.com/frankban/quicktest v1.14.3 // indirect
27 	github.com/go-errors/errors v1.0.1 // indirect
28 	github.com/golang/geo v0.0.0-20190812012225-f41920e961ce // indirect
29 	github.com/golang/protobuf v1.5.2 // indirect
30-	github.com/golang/snappy v0.0.4 // indirect
31 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
32 	github.com/google/uuid v1.3.0 // indirect
33 	github.com/gorilla/css v1.0.0 // indirect
34@@ -68,7 +65,6 @@ require (
35 	github.com/mattn/go-localereader v0.0.1 // indirect
36 	github.com/mattn/go-runewidth v0.0.13 // indirect
37 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
38-	github.com/mholt/archiver v3.1.1+incompatible // indirect
39 	github.com/minio/md5-simd v1.1.2 // indirect
40 	github.com/minio/sha256-simd v1.0.0 // indirect
41 	github.com/mitchellh/go-homedir v1.1.0 // indirect
42@@ -78,9 +74,6 @@ require (
43 	github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
44 	github.com/muesli/cancelreader v0.2.2 // indirect
45 	github.com/muesli/termenv v0.12.0 // indirect
46-	github.com/nickalie/go-binwrapper v0.0.0-20190114141239-525121d43c84 // indirect
47-	github.com/nwaples/rardecode v1.1.0 // indirect
48-	github.com/pierrec/lz4 v2.6.1+incompatible // indirect
49 	github.com/prometheus/client_golang v1.13.0 // indirect
50 	github.com/prometheus/client_model v0.2.0 // indirect
51 	github.com/prometheus/common v0.37.0 // indirect
52@@ -88,8 +81,6 @@ require (
53 	github.com/rivo/uniseg v0.3.4 // indirect
54 	github.com/rs/xid v1.4.0 // indirect
55 	github.com/sirupsen/logrus v1.9.0 // indirect
56-	github.com/ulikunitz/xz v0.5.10 // indirect
57-	github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
58 	go.uber.org/atomic v1.10.0 // indirect
59 	go.uber.org/multierr v1.8.0 // indirect
60 	golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c // indirect
M go.sum
+2, -25
 1@@ -91,9 +91,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 2 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 3 github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
 4 github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
 5-github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
 6-github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
 7-github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
 8 github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f h1:vqfYiZ+xF0xJvl9SZ1kovmMgKjaGZIz/Hn8JDQdyd9A=
 9 github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f/go.mod h1:DmMpU91/Ax6BAwoRkjgRCr2rmgEgS4tsmatfV7M+U+c=
10 github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 h1:9zARagUAxQJjibcDy+0+koUMR6sbX38L49Bk2Vni628=
11@@ -108,8 +105,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
12 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
13 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
14 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
15-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
16-github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
17 github.com/gliderlabs/ssh v0.3.4 h1:+AXBtim7MTKaLVPgvE+3mhewYRawNLTd+jEEz/wExZw=
18 github.com/gliderlabs/ssh v0.3.4/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
19 github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
20@@ -157,8 +152,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
21 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
22 github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
23 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
24-github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
25-github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
26 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
27 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
28 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
29@@ -170,7 +163,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
30 github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
31 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
32 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
33-github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
34 github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
35 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
36 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
37@@ -207,14 +199,14 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
38 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
39 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
40 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
41-github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
42 github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
43 github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
44-github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
45 github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
46 github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
47 github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
48 github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
49+github.com/kolesa-team/go-webp v1.0.1 h1:Btojkbzr6tt10zJ40xlbSfJeHFiNn0aR7H03QUqmMoI=
50+github.com/kolesa-team/go-webp v1.0.1/go.mod h1:oMvdivD6K+Q5qIIkVC2w4k2ZUnI1H+MyP7inwgWq9aA=
51 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
52 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
53 github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
54@@ -245,8 +237,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4
55 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
56 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
57 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
58-github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
59-github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
60 github.com/microcosm-cc/bluemonday v1.0.19 h1:OI7hoF5FY4pFz2VA//RN8TfM0YJ2dJcl4P4APrCWy6c=
61 github.com/microcosm-cc/bluemonday v1.0.19/go.mod h1:QNzV2UbLK2/53oIIwTOyLUSABMkjZ4tqiyC1g/DyqxE=
62 github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
63@@ -283,14 +273,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
64 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
65 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
66 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
67-github.com/nickalie/go-binwrapper v0.0.0-20190114141239-525121d43c84 h1:/6MoQlTdk1eAi0J9O89ypO8umkp+H7mpnSF2ggSL62Q=
68-github.com/nickalie/go-binwrapper v0.0.0-20190114141239-525121d43c84/go.mod h1:Eeech2fhQ/E4bS8cdc3+SGABQ+weQYGyWBvZ/mNr5uY=
69-github.com/nickalie/go-webpbin v0.0.0-20220110095747-f10016bf2dc1 h1:9awJsNP+gYOGCr3pQu9i217bCNsVwoQCmD3h7CYwxOw=
70-github.com/nickalie/go-webpbin v0.0.0-20220110095747-f10016bf2dc1/go.mod h1:m5oz0fmp+uyRBxxFkvciIpe1wd2JZ3pDVJ3x/D8/EGw=
71-github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
72-github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
73-github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
74-github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
75 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
76 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
77 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
78@@ -349,11 +331,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
79 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
80 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
81 github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
82-github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
83-github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
84-github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
85-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
86-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
87 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
88 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
89 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
M imgs/api.go
+24, -13
  1@@ -1,7 +1,6 @@
  2 package imgs
  3 
  4 import (
  5-	"bufio"
  6 	"bytes"
  7 	"fmt"
  8 	"html/template"
  9@@ -20,8 +19,9 @@ import (
 10 	"git.sr.ht/~erock/pico/imgs/storage"
 11 	"git.sr.ht/~erock/pico/shared"
 12 	"github.com/gorilla/feeds"
 13+	"github.com/kolesa-team/go-webp/encoder"
 14+	"github.com/kolesa-team/go-webp/webp"
 15 	"github.com/nfnt/resize"
 16-	"github.com/nickalie/go-webpbin"
 17 	"go.uber.org/zap"
 18 	"golang.org/x/exp/slices"
 19 )
 20@@ -201,7 +201,7 @@ type ImgOptimizer struct {
 21 	// Specify the compression factor for RGB channels between 0 and 100. The default is 75.
 22 	// A small factor produces a smaller file with lower quality.
 23 	// Best quality is achieved by using a value of 100.
 24-	Quality    uint
 25+	Quality    float32
 26 	Optimized  bool
 27 	Width      uint
 28 	Height     uint
 29@@ -227,6 +227,10 @@ func (h *ImgOptimizer) GetImage(contents []byte, mimeType string) (image.Image,
 30 }
 31 
 32 func (h *ImgOptimizer) GetRatio() error {
 33+	if h.Dimes == "" {
 34+		return nil
 35+	}
 36+
 37 	// dimes = x250 -- width is auto scaled and height is 250
 38 	if strings.HasPrefix(h.Dimes, "x") {
 39 		height, err := strconv.ParseUint(h.Dimes[1:], 10, 64)
 40@@ -234,6 +238,7 @@ func (h *ImgOptimizer) GetRatio() error {
 41 			return err
 42 		}
 43 		h.Height = uint(height)
 44+		return nil
 45 	}
 46 
 47 	// dimes = 250x -- width is 250 and height is auto scaled
 48@@ -243,6 +248,7 @@ func (h *ImgOptimizer) GetRatio() error {
 49 			return err
 50 		}
 51 		h.Width = uint(width)
 52+		return nil
 53 	}
 54 
 55 	res := strings.Split(h.Dimes, "x")
 56@@ -281,21 +287,26 @@ func (h *ImgOptimizer) Process(contents []byte, mimeType string) ([]byte, error)
 57 
 58 	nextImg := img
 59 	if h.Height > 0 || h.Width > 0 {
 60-		nextImg = resize.Resize(h.Width, h.Height, img, resize.NearestNeighbor)
 61+		nextImg = resize.Resize(h.Width, h.Height, img, resize.Bicubic)
 62 	}
 63 
 64-	encoder := webpbin.Encoder{
 65-		Quality: h.Quality,
 66+	options, err := encoder.NewLossyEncoderOptions(
 67+		encoder.PresetDefault,
 68+		h.Quality,
 69+	)
 70+	if err != nil {
 71+		return []byte{}, err
 72 	}
 73 
 74-	var output bytes.Buffer
 75-	w := bufio.NewWriter(&output)
 76-
 77-	err = encoder.Encode(w, nextImg)
 78+	output := &bytes.Buffer{}
 79+	err = webp.Encode(output, nextImg, options)
 80 	if err != nil {
 81 		return []byte{}, err
 82 	}
 83 
 84+	if mimeType == "image/png" {
 85+		fmt.Println(output)
 86+	}
 87 	return output.Bytes(), nil
 88 }
 89 
 90@@ -796,9 +807,9 @@ func createMainRoutes(staticRoutes []shared.Route) []shared.Route {
 91 		shared.NewRoute("GET", "/([^/]+)/rss.xml", rssBlogHandler),
 92 		shared.NewRoute("GET", "/([^/]+)/atom.xml", rssBlogHandler),
 93 		shared.NewRoute("GET", "/([^/]+)/feed.xml", rssBlogHandler),
 94-		shared.NewRoute("GET", "/([^/]+)/([^/]+)", imgRequest),
 95 		shared.NewRoute("GET", "/([^/]+)/o/([^/]+)", imgRequestOriginal),
 96 		shared.NewRoute("GET", "/([^/]+)/p/([^/]+)", postHandler),
 97+		shared.NewRoute("GET", "/([^/]+)/([^/]+)", imgRequest),
 98 	)
 99 
100 	return routes
101@@ -817,10 +828,10 @@ func createSubdomainRoutes(staticRoutes []shared.Route) []shared.Route {
102 
103 	routes = append(
104 		routes,
105-		shared.NewRoute("GET", "/([^/]+)", imgRequest),
106-		shared.NewRoute("GET", "/([^/]+)/([a-z0-9]+)", imgRequest),
107 		shared.NewRoute("GET", "/o/([^/]+)", imgRequestOriginal),
108 		shared.NewRoute("GET", "/p/([^/]+)", postHandler),
109+		shared.NewRoute("GET", "/([^/]+)", imgRequest),
110+		shared.NewRoute("GET", "/([^/]+)/([a-z0-9]+)", imgRequest),
111 	)
112 
113 	return routes
M imgs/public/imgs.css
+2, -16
 1@@ -32,26 +32,12 @@ img {
 2   width: 100%;
 3 }
 4 
 5-.tag-overlay {
 6-  width: 100%;
 7-  height: 100%;
 8-  position: absolute;
 9-  top: 0;
10-  left: 0;
11-  background: rgba(0, 0, 0, 0.4);
12-  z-index: 0;
13-  transition-duration: 0.2s;
14-}
15-
16-.tag-overlay:hover {
17-  background: rgba(0, 0, 0, 0.25);
18-}
19-
20 .thumbnail {
21   z-index: 1;
22-  object-fit: cover;
23+  object-fit: contain;
24   width: 300px;
25   height: 300px;
26+  background-color: #000;
27 }
28 
29 .thumbnail-link {