Symfoware

Symfowareについての考察blog

(修正版)JavaScriptで選択されたjpgのサイズ(高さ、幅)をSOFマーカーから取得する

JavaScriptで画像のバイナリデータを解析し、画像のサイズを取得してみました。
JavaScriptで選択されたjpgのサイズ(高さ、幅)をSOFマーカーから取得する

一部、うまくサイズを取得できないjpegファイルがあったので、修正箇所を記載しておきます。


3、4バイト目のチェック



jpeg画像であるかのチェックとして、まず1、2バイト目が0xffと0xd8で始まっているかチェック。
続いて、3、4バイト目がAPP領域を示す0xffと0xe0から0xefの領域であるかチェックしていました。


  1. if((int32View[2] !== 0xff) || (int32View[3] < 0xe0) || (int32View[3] > 0xef) ) { //check APP0..APP15 marker




・APP0マーカーが保存されている(APP0より先に、APP1などが来ることはなさそう)
・APP0マーカーではなく、DQTマーカーが保存されていることがある。

このDQTマーカーが3、4バイト目に記載されている時エラーで終了していました。

そのため、このチェック領域を以下のように変更しています。


  1. if((int32View[2] !== 0xff) && ((int32View[3] !== 0xdb) || (int32View[3] !== 0xe0))) {





SOFマーカーのチェック



画像の縦横サイズが保存されているSOFマーカーを取得する箇所。


  1. //check SOF0...SOF15 segment marker
  2. if(int32View[offset+1] >= 0xc0 && int32View[offset+1] <= 0xcf) {




・実際に画像サイズが保存されているのはSOF0マーカーのみ
・画像によってはSOF2マーカーに保存されている模様

http://www.wdic.org/w/TECH/JFIF


SOFxマーカー
マーカーによって書式は異なる可能性があるが、判明している範囲では、SOF0とSOF2は同じ。
パラメーターの値は一例である。




ここのチェックも以下のように修正しました。


  1. //check SOF0 SOF2 segment marker
  2. if((int32View[offset+1] === 0xc0) || (int32View[offset+1] === 0xc2)) {







修正版



修正後のプログラムは以下のようになりました。


  1. <!doctype html>
  2. <html lang="ja">
  3. <head>
  4.     <meta charset="utf-8">
  5.     <title>Sample</title>
  6. <script type='text/javascript'>
  7. function test_click() {
  8.     var file_input = document.querySelector('#file-input');
  9.     var file = file_input.files[0];
  10.     
  11.     var fileReader = new FileReader();
  12.     fileReader.onload = function(e) {
  13.         // https://gist.github.com/lucianogiuseppe/b9e6d1ede2671405fcf3680e96dda84e
  14.         var bytes = e.target.result;
  15.         var int32View = new Uint8Array(bytes);
  16.         
  17.         if ((int32View[0] != 0xff) || (int32View[1] != 0xd8)) {
  18.             console.log('Not a valid JPEG');
  19.             return false;
  20.         }
  21.         // check APP0 DQT
  22.         if((int32View[2] !== 0xff) && ((int32View[3] !== 0xdb) || (int32View[3] !== 0xe0))) {
  23.             console.log('Bad APPX or DQT');
  24.             return false;
  25.         }
  26.         
  27.         var sizeSeg = 0, offset=0;
  28.         sizeSeg = (int32View[4]*256) + int32View[5]; //segment size
  29.         offset = 4 + sizeSeg;
  30.         //while EOF
  31.         while(offset < int32View.length ) {
  32.             if(int32View[offset] != 0xff) {
  33.                 console.log('bad segment');
  34.                 break;
  35.             }
  36.             if(int32View[offset+1] == 0xd9) {
  37.                 console.log('JPEG EOI!');
  38.                 break;
  39.             }
  40.         
  41.             //check SOF0 SOF2 segment marker
  42.             // http://www.wdic.org/w/TECH/JFIF
  43.             // マーカーによって書式は異なる可能性があるが、判明している範囲では、SOF0とSOF2は同じ
  44.             if((int32View[offset+1] === 0xc0) || (int32View[offset+1] === 0xc2)) {
  45.                 //get image information
  46.                 var imgH = (int32View[offset+5]*256) + int32View[offset+6];
  47.                 var imgW = (int32View[offset+7]*256) + int32View[offset+8];
  48.                 var result = '';
  49.                 result += 'width:' + imgW;
  50.                 result += "\n";
  51.                 result += 'height:' + imgH;
  52.                 
  53.                 document.querySelector('#result').innerText = result;
  54.                 return true;
  55.             } else {
  56.                 //go to next segment
  57.                 sizeSeg = (int32View[offset+2]*256) + int32View[offset+3];
  58.                 offset += 2 + sizeSeg;
  59.             }
  60.         }
  61.         console.log('End of File');
  62.         return false;
  63.     };
  64.     fileReader.readAsArrayBuffer(file);
  65.     
  66. };
  67. </script>
  68. </head>
  69. <body>
  70.     <h3>jpegテスト</h3>
  71.     <input id="file-input" type="file" />
  72.     <div>
  73.         <input type="button" id="test" onclick="test_click()" value="実行" />
  74.     </div>
  75.     <div id="result"></div>
  76. </body>
  77. </html>




サンプルはここにおいておきます。
画像サイズ取得修正版(SOF領域読み取り)
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/08/11(金) 13:39:33|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Python3 subprocess + ImageMagick identifyで画像のexif情報を取得する | ホーム | Android ListViewにリソースとして追加した画像を表示する>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/2018-4f11c796
この記事にトラックバックする(FC2ブログユーザー)