iPhone で撮影した画像が意図した向きで表示されない件

iPhone で撮影した画像ですが、iOS 上の Safari や、facebook のリンクのプレビュー画面で意図した向きで表示されない件が気になっていたので、対策を考えてみました。

原因は、撮影した向きでは画像が保存されず、向きを補正する情報が保存されることに起因すると推定しているのですが、対策からすれば、向きを補正する情報を読み取り、正しい向きでシンプルがデータとして再構成すれば良い、ということになるかと思うわけです。

不用な Exif データなども削除すれば、多少なりともトラフィクの軽減にもなるわけですし、そういう部分も掘り下げたいところではあるんですが、それ以前に、iPhone で撮影する場合、画素数の調整なんかができない気がするので、アホのように巨大な画像ファイルになるので、それを手当しなければならず、現状は、Wordpress のプラグインで、imsanity というものを使って対策をしているのですが、これ自体は、リサイズしかしてくれないので、たたき台にするにしても、もっとマシなものがあるだろう、ということで探してみました。

そうしたところ、fix image rotation というものがあり、早速落としてみました。

動作的には、filter_wp_handle_upload_prefilter で、ファイルアップロード時にフックして、実処理は、fixImageOrientation でやっているわけですが、ここでは、WP_Image_Editor インスタンスが実際のイメージ処理を行っています。

調べてみたところ、あまり詳しいマニュアルはなかったのですが、

$image = wp_get_image_editor( 'cool_image.jpg' );
if ( ! is_wp_error( $image ) ) {
    $image->rotate( 90 );
    $image->resize( 300, 300, true );
    $image->save( 'new_image.jpg' );
}

ということで、リサイズと回転のサンプルコードがあり、つまり、リサイズ機能も有しているようなので、少し書き換えれば、サイズ調整も可能になりそうに思いました。

insanity にはすでにアップロード済みのファイルを修正する機能もあるんで、そっちをベースにした方がいいかもしれないし、あるいは、そのものずばりのプラグインもあるような予感もするんだけど、まあ、勉強も兼ねて、ちょっと作ってみました。

<?php

/**
 * @package Image Filter
 * @version 1.0
 */
/*
  Plugin Name: Image Filter
  Description: Image Filter plugin fixes image size and image orientation based on EXIF data.
  Author: Osamu Shigematsu
  Version: 1.0
  Author URI: http://shigematsu.org
 */

if (!defined('ABSPATH'))
    exit; // Exit if accessed directly

if (!class_exists('ImageFilter')) {
class ImageFilter {
    public function __construct() {
        add_filter('wp_handle_upload_prefilter',
            array($this, 'filter_wp_handle_upload_prefilter'), 10, 1);

        add_filter('wp_handle_upload',
            array($this, 'filter_wp_handle_upload'), 1, 3);
    }

    public function filter_wp_handle_upload($file) {
        $suffix = strtolower(substr($file['file'], strrpos($file['file'], '.', -1) + 1));
        if (in_array($suffix, array('jpg', 'jpeg', 'png', 'gif'))) {
            $this->fixImage($file['file']);
        }
        return $file;
    }

    public function filter_wp_handle_upload_prefilter($file) {
        $suffix = strtolower(substr($file['file'], strrpos($file['file'], '.', -1) + 1));
        if (in_array($suffix, array('jpg', 'jpeg', 'png', 'gif'))) {
            $this->fixImage($file['tmp_name']);
        }
        return $file;
    }

    public function fixImage($file) {
        $fixed = false;
        $editor = wp_get_image_editor($file);
        if (!is_wp_error($editor)) {
            // reize image (if needed)
            $MAX_WIDTH = $MAX_HEIGHT = 1600;
            $size = $editor->get_size();
            $width = $size['width'];
            $height = $size['height'];
            if ($width > $MAX_WIDTH ||
                $height > $MAX_HEIGHT) {
                $editor->resize($MAX_WIDTH, $MAX_HEIGHT, false);
                $fixed = true;
            }

            // fix orientation
            // http://dqn.sakusakutto.jp/2009/02/jpegexiforientaion.html
            $exif = @exif_read_data($file);
            if (isset($exif['Orientation'])) {
                switch ($exif['Orientation']) {
                case 1:
                    break;
                case 2:
                    $editor->filp(false, true);
                    $fixed = true;
                    break;
                case 3:
                    $editor->rotate(180);
                    $fixed = true;
                    break;
                case 4:
                    $editor->filp(true, false);
                    $fixed = true;
                    break;
                case 5:
                    $editor->rotate(270);
                    $editor->filp(false, true);
                    $fixed = true;
                    break;
                case 6:
                    $editor->rotate(270);
                    $fixed = true;
                    break;
                case 7:
                    $editor->filp(false, true);
                    $editor->rotate(90);
                    $fixed = true;
                    break;
                case 8:
                case 9:
                    $editor->rotate(90);
                    $fixed = true;
                    break;
                default:
                    $editor->rotate(0);
                    $fixed = true;
                    break;
                }
            }

            if ($fixed) $editor->save($file);
        }
    }
}

new ImageFilter();
}

動くかどうか、しばらく様子を見てみたいと思います。

原木の下見と、内職と

今日、見に来てと依頼されていた原木というか、伐採現場に下見に行ってきました。

進入路が狭すぎて、2t ダンプも入らない感じです。
搬出がかなり困難な予感がするのですが、まあ、軽トラックでボチボチ頑張るしかないですね。
まあ、350kg 積んだとしても、買うと 3,500 円ですから。

ちょっとこの現場は、薪集め会をするのは無理っぽい気がしますね。
道がありませんので。

もう一山伐るということですが、それまでにはポータブルウインチなどの装備を整えたほうがいいかもしれない気がします。

ただ、伐採などは、一人では危ないので、中途半端なことをやるのは事故や怪我のもとでもあるし、地元でのこういう以来が今後どこまで増えるのか、ということの様子を見ながら装備についても検討していこうと思います。

それはそうと、白ウッドバッグのスリングが切れるよ、という件。
まあ、うちはまだ 1 枚もそういうトラブルはないんですが、予防するに越したことはないので、ちょっと吊具を作ってみました。

久しぶりにカリオストロの城が見たくなって、見ながらぬるく作業をしていたのですが、アバウトな性格のため、同じ長さに編むのがけっこう大変でした。
何度か編み直したりしていたら、少し手先がすり減った感じがします。
まだまだ修行がたりない感じ。

今までだと、フォークを直接突っ込んで吊っていたので、中身が入っている場合、手前につけて、一旦降りて手前のスリングを通して、乗り込んで前進させて、後ろのスリングを通す、この時結構、通したスリングが外れてもう一度降りて手直しすることもある、というふうな、結構かったるい作業だったのですが、今回は、フックに外れ留があるのと、ロープの長さ分遊びがあるため、パツンパツンに入って傾いていて、フォークにとどかない、というようなケースでの作業性が改善されるのでは、という期待があります。

ロープの長さ分、吊り位置が高くなるわけで、吊り代が足りるのか、ということは心配だったりするのですが、まあ、試して様子を見てみたいと思います。

明日の薪集め会ですが、現在のところ、重松、S さん、M さん、O さん、今回初参加の I さん、5 名+Y さんが寄れたら寄る、という予定です。

事故や怪我のないように、ゆっくりと楽しめればと思います。
当日の飛び入りも歓迎ですし、途中で来て、途中で帰っても構いません。
原木の分配は適当ですので、作業時間、作業量に比例しないと思いますが、まあ、あまりガツガツせずにやっておりますので、その辺はお含みおきください。