favicon 変換・作成サービスを作りました
favicon (ファビコン)を簡単に作ることができる Favicon ジェネレーター というウェブサービスを作りました。
作った際の利用技術やライブラリ、実装などを紹介していきます。
目次
Favicon ジェネレーター
favicon(ファビコン)を簡単に作ることができる Favicon ジェネレーター というウェブサービスを作りました。
Favicon ジェネレーター の特徴
- WebAssemblyを使うことで、アップロードすることなく、全てローカルで完結
- アップロードの待ち時間がなく、高速な変換が可能
- マルチアイコンに対応
- 様々なファイルサイズに変換可能
- 透過に対応
作成した動機
以前、こちらの記事で、 ImageMagick を使って favicon を作成する方法について記載しました。 実際に自分はいつもこの方法でやっていたのですが、やはりコマンドを打つのが面倒だったり、コマンドを覚えきっておらず、そらで書けるわけではないので、多少面倒くささを感じていました。
ImageMagickでfaviconを作成する | mintsu's blog
そこで、ブラウザ上で変換できるツールがあったらいいなと思い、ブラウザで favicon を自動生成できるツールが作成できたらいいなと思いました。
利用技術
- React.js
- WebAssembly
- WASM ImageMagick
方向性
こういった画像を扱うウェブサービスを使うとき、ほとんどのサービスでは画像のアップロードが必要になりますが、できれば画像をインターネットに上げたくないと思う人なので、できればローカルで完結できるようにできないかと思いました。
普通にネットワークを介するものであれば、AWS Lambda を使って変換する、というのも考えましたが、上記の理由から今回はAWS Lambda 等のFaaSの利用は見送りました。
今回は WASM ImageMagick という Webassembly でImageMagickを使えるようにしたライブラリを利用することで、アップロードせずに、ローカルで完結するようにしました。
JavaScript で ImageMagick を使う
ImageMagick を Webassembly で使えるようにしたライブラリがあるのでこちらを利用します。
KnicKnic/WASM-ImageMagick: Webassembly compilation of https://github.com/ImageMagick/ImageMagick & samples
WASM ImageMagick のインストール
npm もしくは yarn で追加します。
yarn add wasm-imagemagick
実装
変換処理を行うReact Componentの処理イメージです
import React from 'react'
import { call } from 'wasm-imagemagick'
class Converter extends React.Component {
constructor(props) {
super(props)
this.state = {
outputImage: '',
}
}
readFileAsync(file) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
})
}
handleChangeFile = async (e) => {
var files = e.target.files;
const buffer = await this.readFileAsync(files[0])
const uint8ArrayBuffer = new Uint8Array(buffer)
const command = ["convert", files[0].name, "-define", "icon:auto-resize", "favicon.ico"]
const result = await call([{content:uint8ArrayBuffer, name: files[0].name}], command);
if(result.exitCode !== 0) {
alert('変換に失敗しました')
return
}
this.setState({outputImage: URL.createObjectURL(result.outputFiles[0].blob)});
}
render() {
return(
<div>
<input type="file" rel="file" onChange={this.handleChangeFile} />
<p>変換後画像</p>
<img src={this.state.outputImage} />
</div>
)
}
}
export default Converter
ファイルを選択すると onChange
で指定している handleChangeFile
が呼ばれます。
handleChangeFile の中で選択したファイルのデータを読み込み、ImageMagick の関数を呼び出し変換をかけています。
実際に変換をかける処理は下記の call関数を呼び出す部分です。
commandはImageMagickのコマンドと一緒ですね。
const command = ["convert", files[0].name, "-define", "icon:auto-resize", "favicon.ico"]
const result = await call([{content:uint8ArrayBuffer, name: files[0].name}], command);
最後に
今回ImageMagickをJavaScriptで使う方法を書きました。 WebAssembly のおかげでJavascriptからImageMagickのコマンドが呼び出せるのは非常に便利ですね。 今回はFaviconを作る用途で使いましたが、他にもいろいろ応用ができそうです。
また、WebAssembly 自体についても興味が湧いてきたので、今後触ってみたいと思います。
今回は ImageMagick の話が主でしたが、実は React.js を使ったアプリ開発は今回が初めてでした。
あまりReactの作法を知らず、動けばいいや程度なコードになってしまいましたが、React Component の基本的なところについては学ぶことができ、Reactの最初の学び・導入としては良かったなと思います。