というわけで、さらにテストで関数丸ごとで出してみます。
MMXを使って画像を線形拡大する
BOOL StretchBitmapMMX(void *lpDest,long lDestWidth,long lDestHeight,long lDestPitch,const void *lpSrc,long lSrcWidth,long lSrcHeight,long lSrcPitch)
{
__m64 mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7;
unsigned char *dst,*src,*buf,*spn; int *ptr1,*ptr2;
long sx,sy,sw,sh,dx,dy; long x,y,ddx,ddy;
MMVAL _mmalpha; MMVAL _mmalphac(0x0100010001000100ull);
dst = (unsigned char *)lpDest; src = (unsigned char *)lpSrc;
ddx = (lSrcWidth 0;dy–,sy += ddy,dst += lDestPitch){
buf = dst; src = (unsigned char *)lpSrc + lSrcPitch * y;
if(y 0;dx–,sx += ddx,buf += sizeof(unsigned long)){
x = sx >> 8; _mmalpha.setu16((unsigned short)(sx & 0x000000ff));
ptr1 = (int *)(src + sizeof(unsigned long) * x);
ptr2 = (int *)(spn + sizeof(unsigned long) * x);
mm0 = _mm_cvtsi32_si64(*ptr1);
mm2 = _mm_cvtsi32_si64(*ptr2);
if(x さっと解説すると、sxとsyは24.8の固定小数点でSourceの位置、dyとdyはDestのループカウンタ、ddxとddyはDest1PixelあたりのSourceの移動量です。
mm0~mm7はMMXのレジスタを模しています。MMVALは64bitの構造体の変数で、各ワード(16bit)や各ダブルワード(32bit)に同じ値を設定できるようにしたヘルパ構造体です。
引数やらそれ以外は意味に合うように推察してください。一応名前そのまんまのつもりです。
元々は全部をx86のアセンブラコードで組もうかと思っていたコードでしたが、ループ制御の部分がややこしすぎたのでmmintrinでの実装に切り替えました。
計算のやり方はほかの線形補間のページで解説されているとおりのことしかやっていない(1Pixelの幅を256分割してそれをα乗算することで4点の補間処理を行っている)です。
一応MMX命令を使用しているのである程度の高速化の効果が期待できるルーチンになっています。
もちろん、このままでは無駄がいろいろとありますので、実際に実装しているものはもう少し高速化を図ってあります。
目安としては、
- 256分割ではなく、16分割にしてPixel一回分のx乗算+シフトの演算を削除する
- 計算が不要なコードを削る(終端部のポインタが一致する部分など)
があります。
さて、このコードは私が作成したプログラムに実装されていますが・・・。
それはとりあえず明日の話ということで。それでは。
・・・やっぱりはてなの方がプログラムコードの表示がきれいですね。
しばらく使ってみて乗り換えか併用か考えてみたいと思います。