16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【HEIC AWS Mac】tifigを使ってHEICをJPEGに変換する

Last updated at Posted at 2019-01-17

背景

iOS11から、写真がHEIC形式で保存されるようになりました。

そこで、HEIC形式の写真を弊社のサービスサイトにアップロードできるように、「.heic」に対応できるAPIをつくることになりました。

ついでに、iPhoneで撮影した写真をアップロードするとなぜか画像が横になってしまう現象もあったので、同時に対応します。

参考:https://qiita.com/RichardImaokaJP/items/385beb77eb39243e50a6

環境(ざっくり)

[ローカル]
mac, node
[本番]
AWS Linux

外部ライブラリ

・heicをjpegに変換するコマンド
[tifig] https://github.com/monostream/tifig
・画像の向きを正面にするために利用したライブラリ
[sharp] https://github.com/lovell/sharp
・shellコマンドを実行するライブラリ
[child_process] https://github.com/npm/security-holder

tifigコマンドにPATHを通す

まずは、ローカル環境と本番環境それぞれでtifigコマンドをたたけるようにしなければなりません。

[Mac(ローカル環境)]
下記のURLの【macOS aka OSX】を参考に、コマンドを叩けるようになります。
https://github.com/monostream/tifig

[AWS Linux(本番環境)]
下記のURLからバイナリファイルを取得。
https://github.com/monostream/tifig/releases
(現在最新:https://github.com/monostream/tifig/releases/download/0.2.2/tifig-static-0.2.2.tar.gz)

PATHが通ったかどうかは--versionで確認できます。

terminal
tifig --version
tifig 0.2.2

heicの変換

では実際に変換していきます。

処理の大きな流れとしては

1. アップロードされたheicを一時フォルダに保存する
2. 保存されたheicをtifigコマンドでjpegに変換する
3. iPhoneの写真なので、横向きを縦向きになおす

です。

1の「一時フォルダに保存」された状態からの処理を書いていくので、
以下、2と3の処理を書いていきます。

heicをjpegに変換

HeicConverter.js
const { execSync } = require('child_process');
const { unlinkSync } = require('fs');

const REGEX = /\.[^\.]+$/;
const TYPES = [
  'image/heif',
  'image/heic',
  'image/heif-sequence',
  'image/heic-sequence',
];

class HeicConverter {
  convert(path, name) {
    const oldFilePath = `${path}${name}`;
    const newName = name.replace(REGEX, '.jpg');
    const newFilePath = `${path}${newName}`;

    // ここにセキュリティを入れて!!!!!!!!!!!
    const command = `tifig ${oldFilePath} ${newFilePath}`;

    try {
      execSync(command);
      unlinkSync(path);
      return Promise.resolve();
    } catch (err) {
      return Promise.reject(new Error(err));
    }
  }

  isHeicFile(type) {
    return TYPES.includes(type);
  }
}

module.exports = HeicConverter;

こんな感じのHeicConverterクラスを作成しました。
isHeicFileでHEIC形式のイメージかどうかを判定するメソッドと、
JPEG形式に変換するconvertメソッドを用意しています。

convertメソッドでやっていることはシンプルで、
heicファイルの場所と新しいイメージのpathとnameを指定してあげるだけです。
あとはtifigがよしなにやってくれます。

結果、こんなコマンドが叩かれています。

tifig ***/***/test.heic ***/***/test.jpeg

ここで注意してほしいのは、

const command = `tifig ${oldFilePath} ${newFilePath}`;

ここの部分なのですが、
newFilePathにパイプでつないでshellを叩くことができてしまうので、
しっかりセキュリティをいれてください!!

参考:https://github.com/boutell/heic-to-jpeg-middleware

横向きを縦向きになおす

Format.js
const sharp = require('sharp');
const fs = require('fs');

class Format {
  // 画像の向きを正面にする
  async toValidPosition(filePath) {
    try {
      // 正面画像のBufferを取得
      const outputBuffer = await this._getValidPositionImageBuffer(filePath)

      // Bufferを元画像に上書きする
      fs.writeFileSync(filePath, outputBuffer);

    } catch (err) {
      throw err;
    }
  }

  _getValidPositionImageBuffer(filePath) {
    return new Promise((resolve, reject) => {
      sharp(filePath)
      .rotate()
      .toBuffer((err, outputBuffer) => {
        if (err) {
          return reject(new Error(err));
        }
        return resolve(outputBuffer);
      });
    });
  }
}

module.exports = Format;

正面にするのは、これもよしなにsharp.reotate()でやってもらってます。
最後に.toBufferでBufferを返してもらい、
fsでもとのBufferを上書きします。

これで正面向きの画像に変換されます。

まとめ

やっている内容は結構シンプルなんですが、ここまでheicについての調査や画像を正面にするためのライブラリを見つけるのに結構時間がかかりました。。。

tifigじゃなくて、npmで簡単に変換してくれるようなライブラリ出てきてくれないかな。。。

16
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?