画像処理

【Node.js】 Webまたはローカルの画像からサイズ(幅高さ)取得

更新日:2021/10/07

最近サイトのAMP化を始めたのですが、imgタグをamp-imgに変換する際に幅と高さが必要になりました。
しかしimgタグで指定されたいないため、画像ファイルから取得する必要があります。

そこでローカルまたはWebサーバーの画像から、幅と高さを取得するコードを作成しました。

 

requestとimage-sizeを使用

当初は標準モジュールのみで実現しようと思いましたが、非常にめんどうなので他のモジュールに頼ることにしました。

今回使用するのは、URLからコンテンツを取得するrequestモジュールと、画像サイズを取得するimage-sizeです。

しかし完成後にrequestは作成者により非推奨となっていることが判明しました。
対応策を検討した結果、標準モジュールのみでWebから画像を取得することにしました。

image-sizeは標準モジュールではないので、インストールします。

image-sizeのインストール

npm install image-size

今回作成したのが次のコードです。

Webまたはローカルの画像サイズを取得する関数


const http  = require('http');
const https = require('https');
const imageSize = require('image-size');

const sizeGet =  path =>
    new Promise( resolve => {

        if( !path.startsWith("http://") && !path.startsWith("https://") )
            imageSize(path,  (error, dimensions)=>
                 resolve(error ? {error:error.message} : dimensions)
            );
        else{
            const request = path.startsWith("http://") ? http : https;

            request.get( path ,
                 response => {
                            if( response.statusCode !== 200 ){
                                resolve( {error:response.statusCode});return;
                            }
                            const chunks = [];
                            response.on("data", chunk => chunks.push( chunk ) );
                            response.on('end', ()=>{
                                try{
                                    resolve( imageSize( Buffer.concat(chunks) ) );
                                }catch(error){
                                    resolve( {error:error.message});
                                }
                            });
                        }
                );
        }
    });

Webから画像を取得するのは標準モジュールのみではめんどうだと思いましたが、やってみたら簡単でした(汗

この関数はPromiseを返すので、結果はthenやawaitで取得します。

thenで取得

sizeGet(urlOrPath).then( result=>{
    if( result.error ) { console.log( `error:${ result.error }` ) ;}
    else{ console.log( result ); }
} );

awaitで取得

(async ()=>{
    const result = await sizeGet(url);
    if( result.error ) { console.log( `error:${ result.error }` ) }
    else{ console.log( result );}
})();

サイズの取得に成功すると、次のようなオブジェクトが結果として返ります。

{ 
    height: 高さ ,
    width: 幅 ,
    type: 画像のタイプ
}

 

簡単な解説

指定されたパスが"http://"または"https://"で始まらない場合、ローカルパスとみなして、image-sizeを実行します。

パスをURLとみなした場合、Webから画像データを取得します。
その際、"http://""https://"で使用するモジュールが異なります。
ですが使用法は同じなので、次のコードで選択しています。

const request = path.startsWith("http://") ? http : https;

getメソッドはデータが細切れに送られてきます。
送られてくるたびに連結するのは非効率なので、配列に追加しておきます。

データをすべて受け取ったら連結をするのですが、image-sizeはBufferを受け付けるので、Buffer.concatで連結しています。
なおimage-sizeはBufferを指定した場合、コールバック関数を指定できません。
そのため”データが画像出なかった”などのエラーは、tryで捕捉します。

更新日:2021/10/07

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。