Independent JPEG Group's JPEG software release 6b
  with x86 SIMD extension for IJG JPEG library version 1.02
    == INTERNAL ==
-----------------------------------------------------------

■このファイルは

  このファイルでは、SIMD 版 libjpeg ライブラリの、SIMD 拡張部分の詳細を
  解説します。SIMD 拡張部分に対して何らかの手を加えたい場合や、標準では
  対応していないプラットフォームに対応させたい場合などは、ここを読んで
  ください。

    ■ファイルフォーマット／呼び出し規約(ABI)の指定
    ■OS の SIMD サポートチェック (jsimdgcc.c / jsimddjg.asm / jsimdw32.asm)
    ■アセンブリ言語用設定ファイル jsimdcfg.inc の作成 (makecfg.c)
    ■SIMD 命令の実行時の選択／SIMD 動作モード情報
    ■そのほかの設定項目マクロ
      ○ RGB_RED / RGB_GREEN / RGB_BLUE / RGB_PIXELSIZE
      ○ RGBX_FILLER_0XFF
      ○ JFDCT_INT_QUANTIZE_WITH_DIVISION
      ○ UPSAMPLE_H1V2_SUPPORTED


■ファイルフォーマット／呼び出し規約(ABI)の指定

  アセンブリ言語で書かれたコードを、Ｃ言語などの高級言語で書かれたコード
  とリンクするには、オブジェクトファイルのフォーマットを一致させること、
  および、呼び出し規約などのバイナリコードの規約(ABI)を一致させることが
  必要です。このソフトでは、これらの指定を、アセンブラ nasm に与えるオプ
  ションで指定しています。

  ・nasm -fwin32 -DWIN32 ...

    Win32 の coff フォーマット。Microsoft Visual C++ や MinGW・CygWin
    など、Win32 コンパイラの大部分が該当。

  ・nasm -fobj -DOBJ32 ...

    Win32 の obj フォーマット。元々は MS-DOS で使われていた obj 形式
    (MSOMF)を 32bit に拡張したもの。Borland C++ Complier (Win32) など。

  ・nasm -felf -DELF ...

    各種の UNIX で広く採用されている ELF フォーマット。linux や xBSD
    ファミリなど、現在の UNIX の大部分が該当。

  ・nasm -faoutb -DAOUT ...

    以前の xBSD ファミリで使われていた a.out フォーマット。

  ・nasm -fmacho -DMACHO ...

    Darwin (MacOS X) などで採用されている Mach-O フォーマット。
    注）-fmacho オプションは nasm 0.98.40 以降でサポートされます。

  ・nasm -fcoff -DDJGPP ...

    MS-DOS の DJGPP コンパイラで使われる coff フォーマット。

  このうち、-f オプションは nasm が解釈するファイルフォーマットの指定子で、
  -D オプション(マクロの定義)は jsimdext.inc の中で解釈されるバイナリ規約
  (ABI)の指定子です。jsimdext.inc では、-D オプションでのマクロ定義に従って、
  セグメント(セクション)の定義や外部名名前装飾の定義を行なっています。
  詳しくは jsimdext.inc をご覧ください。

  ELF 形式 および a.out 形式 の場合、-DPIC を追加して指定するとコードが
  Position Independent Code (位置独立コード) になります。-DPIC は
  jsimdext.inc の中で解釈され、コードを PIC にするためのマクロを定義します。
  Mach-O 形式の場合は、コードは常に PIC である必要があるため、-DPIC を
  指定しなくても常に PIC 形式のコードを生成します。

  プラットフォームに応じて、これらの中から適切なものを選択する必要があり
  ます。同梱の makefile では、あらかじめ適切なものが指定されています。
  configure スクリプトでは、config.guess が出力するホスト情報を元に選択
  しています。


■OS の SIMD サポートチェック (jsimdgcc.c / jsimddjg.asm / jsimdw32.asm)

  SIMD 命令を実行するには、事前の CPU のサポートチェックだけではなく、
  OS のサポートチェックも必要です。特に SSE/SSE2 については、OS 側で
  SSE/SSE2 命令を実行できるように事前にCPUを設定する必要があり、それを
  行なっていない OS では、OS がシングルタスクかマルチタスクかに関わらず、
  SSE/SSE2 は実行できません。さらに、あまり知られていませんが、CPU に
  内蔵された FPU (数値演算プロセッサ) を使用しない(エミュレートする)設定
  になっていると、MMX や 3DNow! も含めすべての SIMD 命令は全く実行でき
  ません。要するに、SIMD 命令を実行できるかどうかを調べるには、CPUID の
  フラグを調べるだけでは不十分ということです。

  SIMD 命令の OS サポートチェックといっても、保護モードで動いている
  プログラムの場合、CPU の設定フラグの状態を直接ユーザ・プログラムから
  読みとることができないため、SIMD 命令を試しに実行してみて無効命令例外が
  発生するかどうかを確かめるという、移植性の悪い間接的な方法を採らざるを
  得ないのが現状です。

  この SIMD 命令の OS サポートチェックをやっているのが、jsimdgcc.c /
  jsimddjg.asm / jsimdw32.asm の３つのソースファイルです。それぞれ、
  UNIX/gcc用、DJGPP用、Win32用です。jsimdgcc.c では、例外の発生を
  signal() 関数のシグナルハンドラで捕まえています。コードの一部に gcc の
  インラインアセンブラを使っているため、gcc 専用です。gcc 以外でも
  コンパイルはできますが、この場合は SIMD 命令のサポートチェックは
  行なわれません。jsimddjg.asm は DPMI の例外処理機構を直接利用した
  方法で、jsimdw32.asm は Win32 の例外処理機構を直接利用した方法です。

  プラットフォームに応じて、この３種類の中から適切なものを選択する必要が
  あります。同梱の makefile では、あらかじめ適切なものが指定されています。
  configure スクリプトでは、config.guess が出力するホスト情報を元に選択
  しています。

  この３種類のどれとも適合しないプラットフォームの場合は、新たなチェック
  関数を書く必要があります。ですが、その OS が全ての SIMD 命令をサポート
  している OS であることがわかっている場合は、この OS サポートチェックは
  省略することも可能です。以下のような空の関数のみのソースファイルを
  作って上記の３つのファイルの代わりに使用するか、もしくは jcomapi.c を
  改変して jpeg_simd_os_support の呼び出しをバイパスするようにすればＯＫ
  です。

    GLOBAL(unsigned int)
    jpeg_simd_os_support (unsigned int simd)
    {
      return simd;
    }


■アセンブリ言語用設定ファイル jsimdcfg.inc の作成 (makecfg.c)

  当ソフトの場合、アセンブリ言語のソースコード中からＣ言語のヘッダファイル
  にある情報、たとえば、プリプロセッサマクロの値や構造体の中にある変数の
  オフセットなど、を知る必要があります。makecfg.c は、JPEG ライブラリの
  コンパイルに先立ってコンパイル・リンク・実行され、アセンブリ言語側の
  ソースコードで必要となる情報をアセンブリ言語用設定ファイル jsimdcfg.inc
  として出力する働きをしています。

  注意点として、makecfg.c は JPEG ライブラリのソースコードと同じコンパイル
  オプションでコンパイルされる必要があります。特に、構造体の解釈(サイズ
  など)が JPEG ライブラリ本体のものと異なってしまうと、JPEG ライブラリが
  クラッシュします。


■SIMD 命令の実行時の選択／SIMD 動作モード情報

  この SIMD 拡張版 JPEG ライブラリでは、プログラムの実行時に特定の SIMD
  命令を使用しないようにしたり、各処理段階でどの SIMD 命令を使用して動作
  するのかを把握できる仕組みが用意されています。

  jpeg_simd_mask() を使うと、特定の SIMD 命令を実行時に使用しないように
  できます。

    GLOBAL(unsigned)
    jpeg_simd_mask (j_common_ptr cinfo, unsigned remove, unsigned add);

  この関数は、各 SIMD 命令セットに対応するマスクビットを設定・変更します。
  remove, add そして戻り値は、各 SIMD 命令に対応するビット値 (JSIMD_MMX,
  JSIMD_3DNOW, JSIMD_SSE, JSIMD_SSE2) を OR 演算で組み合わせたものです。

  "マスクビット" は、構造体 cinfo に保持される値で、その初期値は 0 です。
  そしてこの関数は、このマスクビットを以下のように更新(操作)します。

    (新しいマスクビット) = ((古いマスクビット) & ~remove) | add;

  そして、このマスクビットが 1 にされた SIMD 命令セットは、たとえ CPU/OS
  で対応していても使用されません。この関数は、この関数を呼ぶ直前まで設定
  されていたマスクビットを返します。なので、remove, add 共に 0 を与えて
  関数を呼べば、現在設定されているマスクビットを取得できます。この関数の
  使用例は、cjpeg.c, djpeg.c, jcomapi.c にあります。

  このマスクビットの値は、実際には構造体 cinfo の output_gamma もしくは
  input_gamma 変数の下位ビットの保存されています(詳しくは jcomapi.c を
  参照)。これは、構造体 cinfo に新たな変数を追加してしまうとバイナリ互換
  が崩れてしまうためで、現状では未使用と思われる上記の変数を「間借り」
  しています。

  また、以下の関数群を使うと、ライブラリ内部の各処理段階でどの SIMD 命令
  を使用して動作するのかを把握できます。

    jpeg_simd_color_converter();   -> 色空間変換(RGB->YCbCr)
    jpeg_simd_downsampler();       -> ダウンサンプリング
    jpeg_simd_forward_dct();       -> DCT順変換
    jpeg_simd_color_deconverter(); -> 色空間変換(YCbCr->RGB)
    jpeg_simd_upsampler();         -> アップサンプリング
    jpeg_simd_inverse_dct();       -> DCT逆変換

  返す値は、浮動小数点DCT順変換/逆変換 の場合は JSIMD_3DNOW か JSIMD_SSE、
  それ以外の場合は JSIMD_MMX か JSIMD_SSE2 を返します。また、0 が返って
  きた場合は SIMD 命令セットは使われず、従来のルーチンが使われることを
  意味します。

  これらの関数の詳しい使い方については、cjpeg.c, djpeg.c (使用例) をご覧
  ください。

  なお、これらの SIMD マスク関数／SIMD モード情報関数 が必要ない場合は、
  以下のマクロを jconfig.h などに含めることで、僅かですがコードサイズが
  節約できます。

    #define JSIMD_MASKFUNC_NOT_SUPPORTED
    #define JSIMD_MODEINFO_NOT_SUPPORTED


■そのほかの設定項目マクロ

  ○ RGB_RED / RGB_GREEN / RGB_BLUE / RGB_PIXELSIZE

    これは、jmorecfg.h の中にある設定項目マクロで、取り扱う RGB 形式画像
    データの RGB の並び順やピクセルサイズを設定します。この SIMD 拡張版
    でも変更できるようにしてありますが、RGB_PIXELSIZE が 3 か 4 の場合のみ、
    SIMD 版の色空間変換ルーチンが有効になります。それ以外の値にした場合は、
    SIMD 版の色空間変換ルーチンは自動的に無効化されて、従来の色空間変換
    ルーチンが使われます(やや低速になります)。

    これらの値を変更することで、出力を 32bit/pixel 形式にしたり、BMP 形式に
    合わせてピクセルを BGR 順にしたりすることが可能になります。なお、
    これらの値を矛盾する値に #define した場合はコンパイルできないようにして
    ありますので、注意してください。

  ○ RGBX_FILLER_0XFF

    これも jmorecfg.h の中にある設定項目マクロです。デフォルトでは #undef
    になっています。上の RGB_PIXELSIZE を 4 にした場合、１つのピクセル
    データ中に(RGBの３バイトの他に)余計な１バイトが存在することになります。
    デフォルトでは、この余計な１バイト(filler byte)には 0x00 が埋められて
    出力されますが、この RGBX_FILLER_0XFF を #define すると 0x00 の代わり
    に 0xFF が filler byte に埋められて出力されます。

    出力を 32bit/pixel 形式にした場合で、filler byte をアルファチャネル
    として扱いたい場合などは、RGBX_FILLER_0XFF を #define すると都合が良い
    場合があるでしょう。

    なお、オリジナル版の JPEG ライブラリでは、この filler byte には何も
    詰められず、元の値がそのまま保持されます。ですが、SIMD 版の色空間変換
    ルーチンでは元の値を保持するには手間がかかるため、常に 0x00 か 0xFF
    で埋めて出力するように仕様変更を行ないました。

  ○ JFDCT_INT_QUANTIZE_WITH_DIVISION

    これは、jmorecfg.h の中にある設定項目マクロで、圧縮処理での DCT係数の
    量子化処理の方法を変更します。デフォルトでは #undef で、#undef の状態の
    方が高速なので、特に理由のない限り #undef で使用することをお薦めいたし
    ます。

    DCT係数の量子化処理というのは、端的に言えば画像データに対して一つ一つ
    割り算(整数除算)を実行することです。ですが、除算は原理的に高速化が
    不可能なので、この SIMD 拡張版では整数除算の代わりに整数乗算を使用して
    量子化処理を実行しています。

    この整数乗算を代用する方法でも、高精度整数DCT/高速整数DCTを使った場合で、
    かつ、0〜100 のすべての圧縮クオリティ設定でオリジナル版と全く同じ結果を
    出すことを確認しています。ですが、圧縮画質を "クオリティ" の指標で設定
    せず、クオリティ 0 よりも低画質の量子化テーブルを直接与えて圧縮した場合
    などは、演算途中の数値範囲の関係で、オリジナル版とは異なる結果が出ること
    も否定できません。そういった特殊な境界条件下でもオリジナル版との互換度が
    高くならなければならない場合などには、この項目を #define にして使用して
    ください。若干速度は落ちますが、従来どおり、一つ一つ除算を行って量子化
    処理を行います。

    もっとも、クオリティ 0 よりも低画質の設定で圧縮しても、ほとんど実用に
    なりませんので、この整数乗算を代用する方法でも、問題になることはないと
    思います。

  ○ UPSAMPLE_H1V2_SUPPORTED

    これは、jmorecfg.h の中にある、オリジナル版の IJG JPEG library には
    存在しない設定項目マクロです。これは、Y:1x2 Cb:1x1 Cr:1x1 (4:2:2) の
    サブサンプリング比を持つ JPEG ファイルを、オリジナル版の IJG JPEG
    library よりも高速／高画質に展開できるようにするものです。

    サブサンプリング比 Y:1x2 Cb:1x1 Cr:1x1 (4:2:2) を持つ JPEG ファイルは、
    オリジナルの IJG JPEG Library でも展開できますが、このサブサンプリング
    比に対応するアップサンプリング・ルーチンが簡単なものしか用意されて
    いないため、展開速度も遅く、また、色の境目がはっきりしているＣＧ画像
    などの場合はジャギーが目立ってしまうことがあります。この項目を有効に
    することで、このようなサブサンプリング比 Y:1x2 Cb:1x1 Cr:1x1 を持つ
    JPEG ファイルを高速に、また、ジャギーが目立たないように高画質に展開
    できるようにします。

    この、サブサンプリング比 Y:1x2 Cb:1x1 Cr:1x1 の JPEG ファイルは、あまり
    一般的なものではありませんが、ディジタルカメラなどが出力することの多い、
    サブサンプリング比 Y:2x1 Cb:1x1 Cr:1x1 (4:2:2) の JPEG ファイルに対して
    「JPEG ロスレス回転」処理を行なうと、この Y:1x2 Cb:1x1 Cr:1x1 の JPEG
    ファイルになります。ディジタルカメラで、カメラを縦にして（縦位置で）撮影
    した画像を「JPEG ロスレス回転」して正常な向きに直す、などということは、
    よくやることだと思います。ですが、このような「JPEG ロスレス回転」された
    JPEG ファイルをオリジナルの IJG JPEG Library で展開すると、上記の理由から、
    JPEG ファイルを展開してから画像処理ソフトで回転させた画像に比べて画質が
    劣ってしまいます。この項目を有効にすることで、画像処理ソフトで回転させた
    画像とほぼ同じクオリティで画像を展開することが可能になります。

    この項目は、特に理由のない限り、#define の状態にしておくことをお薦め
    いたします。オリジナルの IJG JPEG Library と完全に同一の結果が必要な
    場合のみ #undef にしてコンパイルしてください。



[EOF]
