LoginSignup
9
2

More than 3 years have passed since last update.

sipsを使ってHEICファイルをJPEGファイルに変換する。かつ、EXIF情報も削除する【mac環境のみ・Python使用】

Last updated at Posted at 2019-09-05

HEICファイルとは

HEICファイル(High Efficiency Image File Format)とは新しい画像形式で、iOS 11から採用されている、ファイル形式です。
画質はそのままにJPEGファイルの半分くらいのファイルサイズとなるように設計されているようです。

HEICファイルの説明についての日本語の記事だと、下記のポストが分かりやすそうでしたので貼っておきます。

WindowsでHEICファイルを開く方法

sipsを使ってHEICファイルをJPEGファイルに変換する

macには標準でsipsというコマンドがついています。
使い方については

sips --help

で見るのが手っ取り早いです。

また、使い方の例として記事下部の参照欄にsipsコマンドについて書かれている方の記事を貼らせていただきました。

このsipsを使って、HEICからjpegに変換していきます
コマンドライン上で実行するなら、下記でOKです。

sips --setProperty format jpeg hogehoge.HEIC --out hogehoge.jpeg

これでhogehoge.HEIChogehoge.jpegに変換できます。

今回は、ディレクトリ単位でまとめてHEICからjpegに変換するPythonスクリプトを書いてみました。

from os import path
from glob import glob
import subprocess

CURRENT_PATH = path.dirname(path.abspath(__file__))
WORK_DIR = 'work' # 変換対象のディレクトリ
RESULT_DIR = 'result' # JPEGに変換したファイルを格納するディレクトリ

files = [r.split('/')[-1] for r in glob(path.join(CURRENT_PATH, WORK_DIR,'*.HEIC'))]

for f in files:
    inputFile = path.join(CURRENT_PATH, WORK_DIR, f)
    outputFile = path.join(CURRENT_PATH, RESULT_DIR, f.replace('.HEIC','.jpeg'))

    command = 'sips --setProperty format jpeg ' + inputFile +  ' --out ' + outputFile
    print(command)
    subprocess.call(command, shell=True)

やはりJPEGに変換するとファイル容量も2倍近くに増えるようです。

画像をリサイズしながら、jpegに変換する

sipsコマンドの中でアスペクト比を変えずにリサイズする方法がありましたので、今回はそれをそのままに使います。
オプションで -Z {リサイズ値} でアスペクト比を保ったまま、リサイズしてくれるようです。

先程のPythonスクリプトを修正します。
横が 1024px になるようにリサイズしたいので、下記のように修正します。

from os import path
from glob import glob
import subprocess

CURRENT_PATH = path.dirname(path.abspath(__file__))
WORK_DIR = 'work' # 変換対象のディレクトリ
RESULT_DIR = 'result' # JPEGに変換したファイルを格納するディレクトリ

files = [r.split('/')[-1] for r in glob(path.join(CURRENT_PATH, WORK_DIR,'*.HEIC'))]

for f in files:
    inputFile = path.join(CURRENT_PATH, WORK_DIR, f)
    outputFile = path.join(CURRENT_PATH, RESULT_DIR, f.replace('.HEIC','.jpeg'))

    command = 'sips -Z 1024 --setProperty format jpeg ' + inputFile +  ' --out ' + outputFile
    print(command)
    subprocess.call(command, shell=True)

画像を収縮させると、一気にファイルサイズも減ります。

JPEGに変換した上でEXIF情報も削除したい

sipsコマンドの中でEXIF情報も併せて削除できないものかと思い、調べてみましたが、できなそうでした。
大変ありがたいことにコメントを頂き、sipsコマンドの中で完結できることができました!!
https://qiita.com/shinshin86/items/ae896113e97a0b8e4f94#comment-16864547d761e2ed88b3

sipsコマンドで完結させるやり方は、下記のsipsコマンドだけを用いて、JPEGに変換した上でEXIF情報も削除したいに書きましたので、そちらをご参照ください

そのため、Exif情報の削除についてはPythonのライブラリであるPillowを使って処理を書いていくことにしました。

下記のスクリプトを実行することで、以下3つの処理を実施します

  • sipsからjpegへの変換
  • 画像を幅1024pxにリサイズ
  • Exif情報を削除
from os import path
from glob import glob
import subprocess
from PIL import Image
from PIL.ExifTags import TAGS

CURRENT_PATH = path.dirname(path.abspath(__file__))
WORK_DIR = 'work' # 変換対象のディレクトリ
RESULT_DIR = 'result' # JPEGに変換したファイルを格納するディレクトリ

files = [r.split('/')[-1] for r in glob(path.join(CURRENT_PATH, WORK_DIR,'*.HEIC'))]

for f in files:
    inputFile = path.join(CURRENT_PATH, WORK_DIR, f)
    outputFile = path.join(CURRENT_PATH, RESULT_DIR, f.replace('.HEIC','.jpeg'))

    try:
        command = 'sips -Z 1024 --setProperty format jpeg ' + inputFile  +  ' --out ' + outputFile
        print(command)
        subprocess.call(command, shell=True)

        ret = {}
        targetFile = Image.open(outputFile)
        info = targetFile._getexif()

        if(info == None):
            print("This file does not process : " + file)
            continue

        for tag, value in info.items():
            decoded = TAGS.get(tag, tag)
            ret[decoded] = value
        ret['XResolution'] = 0
        ret['WhiteBalance'] = 0
        ret['ResolutionUnit'] = 0
        ret['SubsecTimeOriginal'] = 0
        ret['Model'] = 0
        ret['Orientation'] = 0
        ret['DateTimeDigitized'] = 0
        ret['ExposureMode'] = 0
        ret['DateTime'] = 0
        ret['YResolution'] = 0
        ret['Make'] = 0
        ret['ComponentsConfiguration'] = 0
        ret['ApertureValue'] = 0
        ret['ColorSpace'] = 0
        ret['ExposureProgram'] = 0
        ret['FNumber'] = 0
        ret['ShutterSpeedValue'] = 0
        ret['MeteringMode'] = 0
        ret['LensModel'] = 0
        ret['LensMake'] = 0
        ret['ExifVersion'] = 0
        ret['FlashPixVersion'] = 0
        ret['FocalLength'] = 0
        ret['ExposureTime'] = 0
        ret['SensingMethod'] = 0
        ret['MakerNote'] = 0
        ret['ExifOffset'] = 0
        ret['SubjectLocation'] = 0
        ret['FocalLengthIn35mmFilm'] = 0
        ret['Software'] = 0
        ret['Flash'] = 0
        ret['ISOSpeedRatings'] = 0
        ret['SubsecTimeDigitized'] = 0

        targetFile.save(outputFile)
        targetFile.close()
        print("=== SUCCESS => ", outputFile)
    except Exception as ex:
        print("=== ERROR => This file cannot be processed!! ===")
        print("FILE NAME : " + f)
        print(ex)
        print("================================================")

ちなみに、EXIF情報の削除部分については、手前味噌ですが、自身で元々書いていたEXIF削除用のPythonスクリプト内での処理をほぼほぼそのまま流用しています。

shinshin86/Delete-Exif(Github)

(cliweb、2つのバージョンがこのリポジトリにはあるのですが、わかりにくいので、後々リポジトリ内の構成を整理しようかと思っています。)

sipsコマンドだけを用いて、JPEGに変換した上でEXIF情報も削除したい

コメント頂きました @KEINOS さんに感謝です!
https://qiita.com/shinshin86/items/ae896113e97a0b8e4f94#comment-16864547d761e2ed88b3

一旦 EXIF を持たないロスレス画像(PNG や BMP など)に変換してから JPEG にしてはどうでしょう?

EXIFを持たない画像を経由してからJPEGに変換することで、EXIF情報の削除が行えるのは、目からウロコでした。とても勉強になりました。

というわけで、sipsコマンドのみを用いてjpeg変換&exif削除を実現したコードは下記となります。

#!/bin/bash
WORKDIR='work'
RESULTDIR='result'

for heicfile in $(ls $WORKDIR/*.HEIC); do
    bmpfile=${heicfile%.HEIC}.bmp
    jpegfile=${heicfile%.HEIC}.jpeg
    bmpfile_path=$RESULTDIR/${bmpfile##*/}
    jpegfile_path=$RESULTDIR/${jpegfile##*/}
    sips --setProperty format bmp $heicfile --out $bmpfile_path && sips --setProperty format jpeg $_ --out $jpegfile_path && rm $bmpfile_path
done

ちなみにリサイズを行いたいときは-Z {リサイズしたい幅}sipsコマンドのオプションとして渡せばよいだけなので、下記のようになりますね!
(幅を1024pxにリサイズしたいとき)

#!/bin/bash
WORKDIR='work'
RESULTDIR='result'

for heicfile in $(ls $WORKDIR/*.HEIC); do
    bmpfile=${heicfile%.HEIC}.bmp
    jpegfile=${heicfile%.HEIC}.jpeg
    bmpfile_path=$RESULTDIR/${bmpfile##*/}
    jpegfile_path=$RESULTDIR/${jpegfile##*/}
    sips -Z 1024 --setProperty format bmp $heicfile --out $bmpfile_path && sips --setProperty format jpeg $_ --out $jpegfile_path && rm $bmpfile_path
done

まとめ: sipsコマンド便利、Linuxだとimagemagick?

sipsはmac環境でしか使えないコマンドですが、かなり便利なコマンドですね。
Linux環境になると、sipsの代替コマンドはimagemagickとかになるのでしょうか?

imagemagickの様々な使い方が書かれているポストを見つけたので、こちらを最後に貼っておきます。

How to Quickly Resize, Convert & Modify Images from the Linux Terminal

参照

WindowsでHEICファイルを開く方法

Macのターミナルで簡単に画像処理できるsipsの使い方

macOS Mojave の標準コマンドで Jpeg 画像を PNG に変換するワンライナー

Pythonを使ってHEICファイルをjpegに変換する

shinshin86/Delete-Exif(Github)

How to Quickly Resize, Convert & Modify Images from the Linux Terminal

9
2
2

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
9
2