From c44f3dd9743819bb018f961b08169b3d457ff2c7 Mon Sep 17 00:00:00 2001 From: Tyler Date: Wed, 3 Jul 2024 22:26:02 +0100 Subject: Ignore binary after compile --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 118bd8f..417659a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .env # Binary file: /penchan.club +paperchan.club \ No newline at end of file -- cgit v1.2.3 From abb174ae9bf4d6d77ff6fd78d1e72fe891495bf8 Mon Sep 17 00:00:00 2001 From: Tyler Date: Wed, 3 Jul 2024 23:55:30 +0100 Subject: Inline ImageMagick logic (C bindings) --- go.mod | 17 +++++++++------- go.sum | 17 ++++++++++++---- themagicpipe/imageconverter.go | 45 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index b2f8c3d..2072978 100644 --- a/go.mod +++ b/go.mod @@ -2,23 +2,26 @@ module paperchan.club go 1.21.10 +require ( + github.com/gofiber/fiber/v2 v2.52.4 + github.com/gofiber/template/html/v2 v2.1.1 + github.com/jmoiron/sqlx v1.4.0 + github.com/joho/godotenv v1.5.1 + github.com/lib/pq v1.10.9 + gopkg.in/gographics/imagick.v3 v3.7.0 +) + require ( github.com/andybalholm/brotli v1.1.0 // indirect - github.com/gofiber/fiber/v2 v2.52.4 // indirect - github.com/gofiber/fiber/v3 v3.0.0-beta.2 // indirect github.com/gofiber/template v1.8.3 // indirect - github.com/gofiber/template/html/v2 v2.1.1 // indirect github.com/gofiber/utils v1.1.0 // indirect - github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/jmoiron/sqlx v1.4.0 // indirect - github.com/joho/godotenv v1.5.1 // indirect github.com/klauspost/compress v1.17.8 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.54.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect diff --git a/go.sum b/go.sum index 9403fff..684c0c9 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,19 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= -github.com/gofiber/fiber/v3 v3.0.0-beta.2 h1:mVVgt8PTaHGup3NGl/+7U7nEoZaXJ5OComV4E+HpAao= -github.com/gofiber/fiber/v3 v3.0.0-beta.2/go.mod h1:w7sdfTY0okjZ1oVH6rSOGvuACUIt0By1iK0HKUb3uqM= github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc= github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= github.com/gofiber/template/html/v2 v2.1.1 h1:QEy3O3EBkvwDthy5bXVGUseOyO6ldJoiDxlF4+MJiV8= github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQbNa4x1CVNFW0wju0= github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= -github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co= -github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= @@ -31,9 +31,14 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.54.0 h1:cCL+ZZR3z3HPLMVfEYVUMtJqVaui0+gu7Lx63unHwS0= @@ -44,3 +49,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/gographics/imagick.v3 v3.7.0 h1:w8iQa58ikuqjX4l2OVML3pgqFcDMD8ywXJ9/cXa33fk= +gopkg.in/gographics/imagick.v3 v3.7.0/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/themagicpipe/imageconverter.go b/themagicpipe/imageconverter.go index 5e5738e..9dc8d6e 100644 --- a/themagicpipe/imageconverter.go +++ b/themagicpipe/imageconverter.go @@ -1,8 +1,10 @@ package themagicpipe + import ( - "os/exec" - "strings" + "encoding/base64" "errors" + "gopkg.in/gographics/imagick.v3/imagick" + "strings" ) // Where the magic happens, the base64 data url image is sent through Imagemagick @@ -11,13 +13,40 @@ func DataURLConverter(dataURL string) (string, error) { if !strings.HasPrefix(dataURL, "data:image/png;base64,") { return "", errors.New("invalid dataURL") } - cmd := "base64 -d | convert - -background white -flatten -resize 400x200! -colors 4 PNG8:- | base64 -w0" - converter := exec.Command("sh","-c",cmd) - converter.Stdin = strings.NewReader(strings.TrimPrefix(dataURL, "data:image/png;base64,")) - output, err := converter.Output() + imageBase64 := strings.TrimPrefix(dataURL, "data:image/png;base64,") + imageRaw, err := base64.StdEncoding.DecodeString(imageBase64) + if err != nil { + return "", err + } + // doing conversion inline soothes the soul + imagick.Initialize() + defer imagick.Terminate() + magick := imagick.NewMagickWand() + defer magick.Destroy() + // read in from base64 + err = magick.ReadImageBlob(imageRaw) + if err != nil { + return "", err + } + // swap all transparent pixels with white + transparent := imagick.NewPixelWand() + defer transparent.Destroy() + transparent.SetColor("none") + whiteFill := imagick.NewPixelWand() + defer whiteFill.Destroy() + whiteFill.SetColor("#ffffff") + err = magick.OpaquePaintImage(transparent, whiteFill, 5, false) + if err != nil { + return "", err + } + err = magick.ResizeImage(400, 200, imagick.FILTER_POINT) if err != nil { return "", err } - return "data:image/png;base64,"+string(output), nil + imageBytesProcessed, err := magick.GetImageBlob() + if err != nil { + return "", err + } + imageBase64Processed := base64.StdEncoding.EncodeToString(imageBytesProcessed) + return "data:image/png;base64," + imageBase64Processed, nil } - -- cgit v1.2.3 From 8c3b917f5e96430627ff94f5a96e7d30deb571d5 Mon Sep 17 00:00:00 2001 From: Tyler Date: Thu, 4 Jul 2024 16:56:44 +0100 Subject: Further compression and optimization --- themagicpipe/imageconverter.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/themagicpipe/imageconverter.go b/themagicpipe/imageconverter.go index 9dc8d6e..7e70df6 100644 --- a/themagicpipe/imageconverter.go +++ b/themagicpipe/imageconverter.go @@ -43,6 +43,18 @@ func DataURLConverter(dataURL string) (string, error) { if err != nil { return "", err } + err = magick.SetCompression(imagick.COMPRESSION_LZMA) + if err != nil { + return "", err + } + err = magick.StripImage() + if err != nil { + return "", err + } + err = magick.SetDepth(8) + if err != nil { + return "", err + } imageBytesProcessed, err := magick.GetImageBlob() if err != nil { return "", err -- cgit v1.2.3 From e4eb4be4e258512fa2ae1d34e126bcff194a6db6 Mon Sep 17 00:00:00 2001 From: Tyler Date: Thu, 4 Jul 2024 17:24:29 +0100 Subject: Implement quantization changes --- themagicpipe/imageconverter.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/themagicpipe/imageconverter.go b/themagicpipe/imageconverter.go index 7e70df6..07ce826 100644 --- a/themagicpipe/imageconverter.go +++ b/themagicpipe/imageconverter.go @@ -55,6 +55,10 @@ func DataURLConverter(dataURL string) (string, error) { if err != nil { return "", err } + err = magick.QuantizeImage(4, imagick.COLORSPACE_UNDEFINED, 0, imagick.DITHER_METHOD_RIEMERSMA, false) + if err != nil { + return "", err + } imageBytesProcessed, err := magick.GetImageBlob() if err != nil { return "", err -- cgit v1.2.3