ダークモードで透過画像が見辛い問題を解決する拡張機能を作りました!

筆者はダークモードが好きで, 以前紹介した Dark Reader というChrome拡張を入れてダークモード化させています.

tjmtmmnk.hatenablog.com

ただ,ダークモードにすると透過pngで黒文字が見辛いという問題をずっと感じていました.

このためにダークモードをオフにしたりしていましたが,面倒 & 目がつらい ということで解決しようと今回の拡張機能を作りました!

chrome.google.com

f:id:tjmtmmnk:20200624163212p:plain
見辛い透過png (https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)


ここからはどのような仕組みで動いているかを解説しようと思います.

ImageMagickとの出会い

透過pngがなぜ見づらくなっているかを考えると,背景がなく,背景が黒くなる(ブラウザがダークモードなので)ことが原因だと考えられます.つまり,対象となる画像の背景を白色に設定してあげれば今回の問題は大方解決しそうです(白文字の場合は見えなくなりますが...).

今回はImageMagickを使って画像変換することにしました.

今回やりたいことはconvert input.png -background white -alpha deactivate -flatten output.pngとしてあげれば実現できそうです.

「透過をオフにして,背景は白色でレイヤーを重ねる」といった意味になります.(ImageMagickではデフォルトは背景白色だったので指定しなくてもよかったです)

有志の方がImageMagickをWebAssembly化してくださっていたので今回はこれを利用することにしました.

github.com

WASM-ImageMagickを使う

はじめ,npmでインストールしてwebpackでバンドルさせて使おうと思ったのですが,Issueに上がっているエラーと同じエラーに出会ってしまいました.

github.com

そこで,Issueにある解決策と同様に,<script type="module">とすることでimportが使えるようにして,import * as Magick from "https://knicknic.github.io/wasm-imagemagick/magickApi.js"; を記述することでAPIを叩けるようになりました.

CORS問題

ImageMagickを使って変換することが出来るようになったので,変換対象となる画像のURLを拾ってきて変換したら終了!? と思っていましたがそんなことはありませんでした.CORSの問題がありました.

画像のURLを叩いたときにAccess-Control-Allow-Origin: *が設定されていないとCORSで弾かれてしまいます.そこで,MDNの記事を参考に画像を取得して,Access-Control-Allow-Origin: *をヘッダに設定して返してくれるサーバを立てることにしました. 

developer.mozilla.org

コードはとてもシンプルでこんな感じです.画像URLにはクエリパラメータも含まれたりしたので簡単のためPOSTメソッドを使っています.

type Data struct {
    Url string `json:"url"`
}

func getImage(c echo.Context) error {
    data := new(Data)
    err := c.Bind(data)
    response, err := http.Get(data.Url)
    body, err := ioutil.ReadAll(response.Body)
    return c.Blob(http.StatusOK, "image/png", body)
}

func main() {
    e := echo.New()
    e.Use(middleware.CORS())
    e.POST("/image", getImage)
    e.Logger.Fatal(e.Start(":8080"))
}

どこにデプロイするか

普段はHerokuを使ったりしていたのですが,無料枠が別のアプリケーションで埋まってしまっていたのでAWSを使ってみることにしました.

Mixed content問題

AWSにデプロイして完成や!! と思っていたらHTTPを使っていたので,HTTPSのサイトからこのAPIを叩くと Mixed content エラーが起きました.

そこで,ELBを立ててELBをSSL終端にするHTTPS化をすることにしました.AWSを触るのは初めてに近い状態だったのですが,コンソールをポチポチやっていくとどんどんとリソースが揃っていって数時間でHTTPS化までできたのでスゴイとなりました.

完成

これでめでたく透過画像を見やすい画像に置き換えることに成功しました!

f:id:tjmtmmnk:20200624172206p:plain
見やすくなった!

見やすくなった反面,ちょっとダサくなるところもあるのはご承知ください...

f:id:tjmtmmnk:20200624173256p:plain
ダサくなったGoogleアイコン