IMAGEFLUX EC CUBE 4

[EC-CUBE 4] ImageFlux 設定方法

「EC-CUBE Advent Calendar 2021」 24日目の投稿です。


先日、「 画像変換・配信エンジン ImageFlux 」が、小規模から利用しやすい4つの料金プランにリニューアルしました。
550円/月~と導入しやすい価格設定になりましたので、早速、EC-CUBE4で試してみました。



ImageFluxとは

さくらインターネットとピクシブで共同で開発、提供している画像変換・配信エンジンです。
1枚の画像をもとにデバイスに最適化された画像を簡単に生成し、高速かつ高品質で配信するすることができます。
リリースから5周年のサービスですが、料金プランが変わったのでより使いやすくなったと思います。


参考:ImageFlux

ImageFluxの導入で何ができるのかについて、少し説明します。

例えば、「コンバージョンを上げるために、よりきれいな商品画像にしたい。」「商品一覧で、快適に多くの商品を表示させたい。」と考えた場合。
EC-CUBE4系のデフォルトでは、解像度違いの画像が生成されませんので、登録側で解像度違いの画像を生成する機能をつくる必要があります。また、デザインの変更によって、新しい解像度の画像を作り直す必要がでるかもしれません。

ImageFluxは、それらを自動でやってくれるので、サーバリソース(CPU、ストレージ)、ネットワークリソース、開発リソースを使わずにすみます。画像関連の課題解決に役立つかもしれません。



ImageFluxの申し込みと設定

ImageFluxの申し込みには、さくらインターネットのアカウントが必要となります。


申し込み画面にアクセス、プランを選択し、次へ進みます。
次に、申込内容確認画面で内容を確認し、同意して次へ進みます。


アクティベート画面が出ましたら、アクテベートしてください。
申し込みは、以上です。



引き続き、設定を行います。
リジンサーバを設定へ進みます。

オリジン設定では、オリジンとなるサーバの情報を入力してください。

  • Type:HTTP
  • Scheme:https
  • Host:【EC-CUBEのドメイン名を入力してください。】

次にSigned URL

  • 「署名付きURLを使用する」にチェック
  • Signing Secret:【任意ですが、自動生成をクリックして生成します】

今回は、パスプレフィックス毎のパラメータ設定は行いませんので以上となります。
設定をクリックします。

状態が運用中に代わりましたら、設定完了となります。


2点情報が必要なので、控えておいてください。

  • Name:*******.imageflux.jp
  • Signing Secret:********


EC-CUBEの設定

ImageFluxの設定が完了しましたので、すぐにImageFlux経由で画像が変換配信可能な状態となります。
今回は、テンプレートエンジンのTwigの拡張機能を利用して実装していきます。


TwigExtensionのファイルを追加します。※文末にサンプルコード置いておきます。

app/Customize/Twig/Extension/ImageFluxExtension.php


<?php
namespace Customize\Twig\Extension;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Symfony\Component\Asset\Packages;


class ImageFluxExtension extends AbstractExtension
{
    protected $use_signate = true;
    protected $signing_secret = "********";
    protected $image_flux_url = "https://*********.imageflux.jp";


    protected $packages;

app/Customize/Twig/Extension/ImageFluxExtension.php#L12

protected $signing_secret = "********";

設定したSigning Secretに変更してください。


app/Customize/Twig/Extension/ImageFluxExtension.php#L13

protected $image_flux_url= "https://*********.imageflux.jp";

控えていたHostに変更してください。


以上で基本的な設定は完了となります。


ショップ画面で表示されている画像がImageFluxのURLになっていれば、成功です。



画像を最適化について

ImageFluxの機能でリサイズを行っていきます。

「商品一覧画面 – /products/list 」の画像を要素に近い250pxで指定していきます。

src/Eccube/Resource/template/default/Product/list.twig#152-


    <p class="ec-shelfGrid__item-image">
        <img src="{{ asset(Product.main_list_image|no_image_product, 'save_image') }}">
    </p>

    <p class="ec-shelfGrid__item-image">
        {% set imageflux_options = {'width': 250} %}
        <img src="{{ asset(Product.main_list_image|no_image_product, 'save_image' ,imageflux_options) }}">
    </p>

DevToolsで250pxの画像が配信されていることが確認できます。
あくまでリサイズの一例です。Retinaディスプレイ対応やサイト構成を考慮して試してみてください。




まとめ

今回は、ImageFluxについて紹介しましたが、ImageFluxには画像変換の機能が豊富にあります。
例えばオーバーレイ機能ですが、デジタルコンテンツを配信する場合や、画像にキャプションを入れる場合に画像を直接編集する必要がなくなりますので業務の効率化が可能だと思います。
Webp変換にも対応もしており、サイトパフォーマンスも向上することができると思います。


S3や独自ドメインも利用可能で、EC-CUBEに導入しやすいサービスだと感じました。ぜひトライアル期間もあるので試してみてください。



サンプルコード

  • サンプルプログラムは、あくまで検証用途なので、動作を保証するものではありません。
  • 公式が提供しているWordPress用のプラグインを、参考にさせていただいています。
  • Assetで呼ばれている画像のリソースに対してImageFluxのURLを返します。

src/Eccube/Resource/template/default/Block/new_item.twig


<?php
namespace Customize\Twig\Extension;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Symfony\Component\Asset\Packages;


class ImageFluxExtension extends AbstractExtension
{
    protected $use_signate = true;
    protected $signing_secret = "********";
    protected $image_flux_url = "https://*********.imageflux.jp";

    protected $packages;

    public function __construct(Packages $packages)
    {
        $this->packages = $packages;
    }

    public function getFunctions()
    {
        return [
            new TwigFunction('asset', [$this, 'getAsset']),
        ];
    }

    /**
     *
     * @path type: string
     * @packageName (optional) type: string | null default: null
     * @params type: array
     * @return type: string|NULL
     * 
     */
    public function getAsset($path, $packageName = null, $params = []) {
        $filepath = pathinfo($path);
        if (in_array($filepath['extension'],['jpeg','jpg','JPEG','JPG','png','PNG','gif','GIF'])) {
            return $this->image_flux_url . $this->addSignature("/c", self::genarateParams($params), $this->packages->getPackage($packageName)->getBasePath().$path);
        }
        return $this->packages->getUrl($path, $packageName);
    }

    protected function addSignature($prefix, $params, $file_path) {
        $path = $prefix . $params . $file_path;

        if ($this->use_signate) {
            $hash = hash_hmac("sha256", $path, $this->signing_secret, true);
            $params = substr_replace($params, ",", 0,1);
            return $prefix . "/sig=1." . rtrim(strtr(base64_encode($hash), "+/", "-_"), "="). $params . $file_path;
        }
        return $path;
    }
    /**
     * オプションの変換パラメータ生成
     *
     * @return string
     */
    public static function genarateParams($params)
    {
        $params_str = "/";

        // フォーマット
        $format = isset($params['format'])? $params['format']: "webp:auto";
        $params_str .= "f=" . $format . ",";

        // クオリティ
        $quality = isset($params['quality'])? $params['quality']: 70;
        $params_str .= "q=" . $quality . ",";

        // リサイズ
        isset($params['width']) &&  $params_str .= "w=" . $params['width'] . ",";
        isset($params['height']) &&  $params_str .= "h=" . $params['height'] . ",";
        
        // アスペクト
        // 0: 入力のアスペクト比に合わせ、出力の幅、高さにおさめる(scale)
        // 1: 入力のアスペクト比を無視し、出力の幅、高さに合わせる(force-scale)
        // 2: 出力を満たすように入力を拡大・縮小し、はみだした領域を切り取る(crop)
        // 3: 入力のアスペクト比に合わせ、埋まらない部分を背景色で埋める(pad)
        isset($params['aspect']) &&  $params_str .= "a=" . $params['aspect'] . ",";

        // Exif
        // 1: Exif情報を削除する(デフォルト)
        // 2: Exif情報のうち、Orientation以外を削除する
        $exif = isset($params['exif'])? $params['exif']: 1;
        $params_str .= "s=" . $exif . ",";

        // 画像フォーマットによる除外
        //  指定されたフォーマットは、変換しません。
        $extension_param = "";
        $through_jpeg = isset($params['through_jpeg']) && $params['through_jpeg']==1 ? true: false;
        $through_png = isset($params['through_png']) && $params['through_png']==1 ? true: false;
        $through_gif = isset($params['through_gif']) && $params['through_gif']==1 ? true: false;

        if ($through_jpeg) {
            $extension_param .= "jpeg";
        }
        if ($through_png) {
            $extension_param !== "" && $extension_param .=":";
            $extension_param .= "png";
        }
        if ($through_gif) {
            $extension_param !== "" && $extension_param .=":";
            $extension_param .= "gif";
        }

        $extension_param !== "" && $params_str .= "through=" . $extension_param;

        // 最後の文字列のカンマの削除
        mb_substr($params_str, -1) === ',' && $params_str = mb_substr($params_str, 0, -1);
        return $params_str;
    }
}

関連記事