7

ユーザーが画像をアップロードできるアプリケーションがあります。私が使用するテストケースは、サイズが 3872 x 2592px の 1.6MB の jpeg です。バックエンドのアップロード スクリプトは、アップロードされた画像を 6 つの追加形式にサイズ変更します。

  • 正方形 (小 75 x 75)
  • 親指小(50×38)
  • 親指(100×76)
  • 小 (240×161)
  • 中 (500×378)
  • 大(1024×774)

私はそれがたくさんあることを知っていますが、私を信じてください、私はこれが必要です. GD、GD2、または ImageMagick のいずれかを使用してサイズ変更を行う Code Igniter の Image Manipulation クラスを使用してサイズ変更を行います。最初に GD2 を使用するように構成したところ、サイズ変更プロセスの合計に 11 秒かかることに気付きました。

ユーザーはこのプロセスを待たなければならないため、受け入れられません。たくさん読んだ後、ImageMagick がはるかに高速で効率的な操作ライブラリであることを知り、それに切り替えました。

$sourceimage = $data['filedata']['file_path'] . $data['imagedata']['user_id'] . "/" . $imageid . $data['filedata']['file_ext'];
$resize_settings['image_library'] = 'imagemagick';
$resize_settings['library_path'] = '/usr/bin';
$resize_settings['source_image'] = $sourceimage;
$resize_settings['maintain_ratio'] = false;
$resize_settings['quality'] = "100%";
$this->load->library('image_lib', $resize_settings);

驚いたことに、サイズ変更プロセスにかかる時間が長くなりました。具体的には 15 秒です。

ログを見ると、サイズ変更するファイル形式に関係なく、各サイズ変更アクションに 2 秒かかることがわかります。これは、非常に大きい元のサイズから常にサイズを変更しているためだと思います。

サイトの使いやすさが低下するため、サイズ変更プロセスをスケジュールされたプロセスにオフロードするのは嫌いです. これは、ユーザーが画像を見たり操作したりできるようになるまで数分待たなければならないことを意味します。

では、このサイズ変更プロセスを劇的にスピードアップして、リアルタイムで維持できるスマートな方法はありますか? これは私が構築している写真サイトであるため、解像度を下げることはできません。また、言及された6つのフォーマットが本当に必要です。

4

2 に答える 2

9

あなたはすでに答えを受け入れたようですが、私はまだ私の投稿をするつもりです。

まず、100%の品質を使用する必要はありません。処理時間と画像サイズを減らしながら、90%または85%の値で十分です(テストを実行するだけだと思わない場合)。

また、この画像とカスタムJPEG()関数を使用していくつかのベンチマークを実行しました。最初のテストケースは次のとおりです。

JPEG('./original.jpg', null, '1024*774', './output/large.jpg');
JPEG('./original.jpg', null, '500*378', './output/medium.jpg');
JPEG('./original.jpg', null, '240*161', './output/small.jpg');
JPEG('./original.jpg', null, '100*76', './output/thumb.jpg');
JPEG('./original.jpg', null, '50*38', './output/small_thumb.jpg');
JPEG('./original.jpg', null, '75*75', './output/square.jpg');

これは私の遅い遅いコンピュータで平均60秒かかります。


2番目のテストケース

JPEG('./original.jpg', null, '1024*774', './output/large.jpg');
JPEG('./output/large.jpg', null, '500*378', './output/medium.jpg');
JPEG('./output/medium.jpg', null, '240*161', './output/small.jpg');
JPEG('./output/medium.jpg', null, '100*76', './output/thumb.jpg');
JPEG('./output/medium.jpg', null, '50*38', './output/small_thumb.jpg');
JPEG('./output/medium.jpg', null, '75*75', './output/square.jpg');

これは「たった」16秒しかかかりません(私のコンピューターは本当に遅いATM :P)、ほぼ4倍高速です。


JPEG()独自のベンチマークを作成する場合の関数は次のとおりです。

function JPEG($source, $crop = null, $scale = null, $destination = null)
{
    $source = ImageCreateFromJPEG($source);

    if (is_resource($source) === true)
    {
        $size = array(ImageSX($source), ImageSY($source));

        if (isset($crop) === true)
        {
            $crop = array_filter(explode('/', $crop), 'is_numeric');

            if (count($crop) == 2)
            {
                $crop = array($size[0] / $size[1], $crop[0] / $crop[1]);

                if ($crop[0] > $crop[1])
                {
                    $size[0] = $size[1] * $crop[1];
                }

                else if ($crop[0] < $crop[1])
                {
                    $size[1] = $size[0] / $crop[1];
                }

                $crop = array(ImageSX($source) - $size[0], ImageSY($source) - $size[1]);
            }

            else
            {
                $crop = array(0, 0);
            }
        }

        else
        {
            $crop = array(0, 0);
        }

        if (isset($scale) === true)
        {
            $scale = array_filter(explode('*', $scale), 'is_numeric');

            if (count($scale) >= 1)
            {
                if (empty($scale[0]) === true)
                {
                    $scale[0] = $scale[1] * $size[0] / $size[1];
                }

                else if (empty($scale[1]) === true)
                {
                    $scale[1] = $scale[0] * $size[1] / $size[0];
                }
            }

            else
            {
                $scale = array($size[0], $size[1]);
            }
        }

        else
        {
            $scale = array($size[0], $size[1]);
        }

        $result = ImageCreateTrueColor($scale[0], $scale[1]);

        if (is_resource($result) === true)
        {
            if (ImageCopyResampled($result, $source, 0, 0, $crop[0] / 2, $crop[1] / 2, $scale[0], $scale[1], $size[0], $size[1]) === true)
            {
                return ImageJPEG($result, $destination, 90);
            }
        }
    }

    return false;
}
于 2009-12-30T18:29:16.677 に答える
7

アイデアとして、アップロードされたサイズからより適切な中間サイズにサイズ変更し、これを以降の操作の基礎として使用することができます。

別の方法として、ImageMagick のコマンド ライン バージョンを実行し、Asynchronous shell exec in PHP で説明されているプロセスを使用して、バックグラウンドで画像変換 (少なくとも大部分) を実行することもできます。

最後に、少し話が逸れましたが、縦向きを許可する予定ですか、それともこれが要因になる可能性はありませんか?

于 2009-12-30T16:55:58.257 に答える