CImageのAlphaBlendの結果の疑問


ryo  2007-10-12 01:27:10  No: 66551

(XP・VC2005・MFC)

以下のソースで処理を行ったところ、結果のResult.bmpは、全部RGB(4,4,4)になってしまいました。
透明度をいじっても同じ結果になりました(ただ、255のときだけRGB(0,0,0)になりました)。

黒地に、黒色の半透明を重ねても、結果は黒になると思っていたのですが、これは何故なのでしょうか?

#include "atlimage.h"
void CimagetestDlg::OnBnClickedButton1()
{
  // GryaScaleパレット
  RGBQUAD  rgb[256];
  for( int i = 0 ; i < 256 ; i ++ ){
    rgb[i].rgbBlue  = i;
    rgb[i].rgbGreen = i;
    rgb[i].rgbRed  = i;
    rgb[i].rgbReserved= 0;
  }

  CImage Img1,Img2;

  Img1.Create( 1024,100,8);  Img1.SetColorTable(0,256,rgb);
  Img2.Create( 1024,100,8);  Img2.SetColorTable(0,256,rgb);

  CRect rec;    rec.SetRect(0,0,1024,100);

  HDC hdc1 = Img1.GetDC();
  HDC hdc2 = Img2.GetDC();
  
  FillRect( hdc1 ,&rec , (HBRUSH)GetStockObject(BLACK_BRUSH));
  FillRect( hdc2 ,&rec , (HBRUSH)GetStockObject(BLACK_BRUSH));

  Img2.ReleaseDC();      // Img2のDC開放

  Img2.AlphaBlend( hdc1 , 0 , 0 , 128 , AC_SRC_OVER );

  Img1.ReleaseDC();

  Img1.Save("c:\\Result.bmp");

  Img1.Destroy();
  Img2.Destroy();

}


gak  2007-10-13 01:40:15  No: 66552

> 結果は黒になると思っていたのですが、これは何故なのでしょうか?
CImage::AlphaBlend()の内部で使用しているであろう(2005のソースが無いので予想だが)
AlphaBlend()API関数の仕様のような気がする。

AlphaBlend()API関数は、色深度が256以下のケースでは思い切った減色処理をしてからBlendをしている模様。
RGB の要素値が、0-7 は [4]、8-15 は [12]、...という感じに。

数式で示すと、
  color.red = (color.red & 0xf8) + 4;
  color.green = (color.green & 0xf8) + 4;
  color.blue = (color.blue & 0xf8) + 4;
という感じかな。

で、今回の「RGB(0, 0, 0)」の場合だと
1、paletteから RGB(0, 0, 0) の近似色取得 = 「rgb[0](提示ソースから)」 = RGB(0, 0, 0)
2、RGB(0, 0, 0)を上記減色処理で「RGB(4, 4, 4)」に置換。
3、RGB(4, 4, 4) と RGB(4, 4, 4) をblend = 同値のblendなのでalpha値に関わらずRGB(4, 4, 4)
4、palatte内から RGB(4, 4, 4) の近似色を取得 = rgb[4]の色
5、結果Result.bmpは、全部「RGB(4, 4, 4) == rgb[4]」
となる。
まぁ、palette使うような状況でAlphablendなんて無茶言われても…、って事かな。

> ただ、255のときだけRGB(0,0,0)になりました
255の時だけは処理方法が異なるためと思われる。
http://msdn2.microsoft.com/en-us/library/ms532306.aspx

ちなみに上記記述内容は公式資料から得たものでは無いので注意。
+調査環境は「OS:WinXP, VC++6.0sp6, PFSDK:Feb/2003」で、環境に依っては結果が異なる可能性有。


ryo  2007-10-13 03:14:55  No: 66553

返答ありがとうございます

>まぁ、palette使うような状況でAlphablendなんて無茶言われても…、って事かな。
無茶に近いことなんですね

8ビットのままで透過色指定と全体の透明度の変更の両方を使いたくて迷っていたのですが
踏ん切りつけて、32ビット+createAlphaChannelの組み合わせを利用する方法を選択することにしました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加