チラシ裏日記上等!!新館

Webアプリケーションエンジニアの雑記帳。映画とかアニメとかの記事も書きます。

go-sixelを使ってTwitterクライアントに画像表示機能をつける

これは Go5 Advent Calendar 2019 - Qiita 25日目の記事です。 25日に間に合わず埋まってしまいました・・・。

golangを使って趣味でTwitterクライアントを作っています。

www.chirashiura.com

文字だけでもTwitterは楽しいですが、自分がフォローしているアカウントは絵師が多いため画像を表示したくなります。今回はgo-sixelを使用してターミナルに画像を表示したいと思います。

go-sixelは画像をsixelのフォーマットに変換し、ターミナルに画像を表示できるライブラリです。

github.com

sixelとはターミナル上で画像を表示するためのフォーマットです。sixel graphicsに対応している端末で画像を表示できます。

en.wikipedia.org

go-sixelは画像ファイルをエンコードしてターミナルに出力します。URLから画像を取得しターミナルに出力するコードを次に示します。

package lib

import (
    "bytes"
    "fmt"
    "image"
    _ "image/gif"
    _ "image/jpeg"
    _ "image/png"
    "io/ioutil"
    "net/http"
    "os"

    "github.com/mattn/go-sixel"
)

// Media is display media lib
type Media struct{}

// ShowImage is display image
func (m *Media) ShowImage(url string) error {
    res, err := http.Get(url)
    if err != nil {
        fmt.Errorf("cannot get image: %v: %v", err, res.Status)
    }
    defer res.Body.Close()

    buf, err := ioutil.ReadAll(res.Body)

    if err != nil {
        return fmt.Errorf("cannot read body %v", err)
    }

    img, _, err := image.Decode(bytes.NewReader(buf))

    if err != nil {
        return fmt.Errorf("cannot decode image %v", err)
    }

    enc := sixel.NewEncoder(os.Stdout)
    return enc.Encode(img)
}

URLを指定してbyte形式からまず画像をデコードし、その結果をgo-sixelでエンコードしてターミナルに出力しています。

これを自作のTwitterクライアントに組み込むと次のように表示されます。

f:id:Tomato-360:20191226001318p:plain

TwitterAPIではサムネイルサイズの画像のURLが取得できるのでそれを使用してターミナル上に画像を表示します。使用しているターミナルにもよりますがかなりキレイに出力できることがわかります。

sixel graphicsに対応しているターミナルであればgo-sixelでターミナル上に画像を描画できます。tmuxを使っているとsixel graphicsをうまく表示できないのですが、次のissueで活発に議論されているようなのでそのうちtmuxでもsixelの表示ができるようになるのではないかと期待しています。

github.com

細く長く続けているTwitterクライアントの開発ですが、画像が表示できるようになってからぐっと楽しみが増えました。また来年も新機能を携えてアドベントカレンダーに投稿できればと思います。 間に合わないとお互い悲しいのでアドベントカレンダーはいったんやめておこうと思います。