문제

이 질문은 이전 질문에서 비롯되었습니다.대부분의 코드는 이후 버전의 Delphi에서 작동했을 수도 있는 제안된 답변에서 나온 것입니다.D2006에서는 불투명도의 전체 범위를 얻지 못하고 이미지의 투명한 부분이 흰색으로 표시됩니다.

이미지 출처: http://upload.wikimedia.org/wikipedia/commons/6/61/Icon_attention_s.png.
DFM이 저장된 후 이미지가 그대로 유지되지 않기 때문에 이 작업을 수행해야 한다는 것을 알았기 때문에 런타임 시 PNGImageCollection에서 TImage로 로드됩니다.동작을 시연하기 위해 PNGImageCollection이 필요하지 않을 수 있으며 디자인 타임에 PNG 이미지를 TImage에 로드한 다음 IDE에서 실행할 수 있습니다.

양식에는 4개의 버튼이 있습니다. 각 버튼은 서로 다른 불투명도 값을 설정합니다.불투명도=0은 잘 작동합니다. (페인트박스 이미지는 보이지 않습니다. 불투명도=16은 흰색 배경을 제외하면 괜찮아 보입니다. 불투명도=64, 255는 비슷합니다. 불투명도는 약 10%로 포화된 것으로 보입니다.

무슨 일인지 아이디어가 있나요?

unit Unit18;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, pngimage, StdCtrls, Spin, PngImageList;

type
  TAlphaBlendForm = class(TForm)
    PaintBox1: TPaintBox;
    Image1: TImage;
    PngImageCollection1: TPngImageCollection;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    FOpacity : Integer ;
    FBitmap  : TBitmap ;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  AlphaBlendForm: TAlphaBlendForm;

implementation

{$R *.dfm}

procedure TAlphaBlendForm.Button1Click(Sender: TObject);
begin
FOpacity:= 0 ;
PaintBox1.Invalidate;
end;

procedure TAlphaBlendForm.Button2Click(Sender: TObject);
begin
FOpacity:= 16 ;
PaintBox1.Invalidate;
end;

procedure TAlphaBlendForm.Button3Click(Sender: TObject);
begin
FOpacity:= 64 ;
PaintBox1.Invalidate;
end;

procedure TAlphaBlendForm.Button4Click(Sender: TObject);
begin
FOpacity:= 255 ;
PaintBox1.Invalidate;
end;

procedure TAlphaBlendForm.FormCreate(Sender: TObject);
begin
  Image1.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ;
  FBitmap := TBitmap.Create;
  FBitmap.Assign(Image1.Picture.Graphic);//Image1 contains a transparent PNG
  FBitmap.PixelFormat := pf32bit ;
  PaintBox1.Width := FBitmap.Width;
  PaintBox1.Height := FBitmap.Height;
end;

procedure TAlphaBlendForm.PaintBox1Paint(Sender: TObject);

var
  fn: TBlendFunction;
begin
  fn.BlendOp := AC_SRC_OVER;
  fn.BlendFlags := 0;
  fn.SourceConstantAlpha := FOpacity;
  fn.AlphaFormat := AC_SRC_ALPHA;
  Windows.AlphaBlend(
    PaintBox1.Canvas.Handle,
    0,
    0,
    PaintBox1.Width,
    PaintBox1.Height,
    FBitmap.Canvas.Handle,
    0,
    0,
    FBitmap.Width,
    FBitmap.Height,
    fn
  );
end;

end.

** 이 코드(graphics32 TImage32 사용)는 거의 작동합니다 **

unit Unit18;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, pngimage, StdCtrls, Spin, PngImageList, GR32_Image;

type
  TAlphaBlendForm = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Image321: TImage32;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  AlphaBlendForm: TAlphaBlendForm;

implementation

{$R *.dfm}

procedure TAlphaBlendForm.Button1Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 0 ;
end;

procedure TAlphaBlendForm.Button2Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 16 ;
end;

procedure TAlphaBlendForm.Button3Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 64 ;
end;

procedure TAlphaBlendForm.Button4Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 255 ;
end;

end.

** (업데이트) 이 코드(graphics32 TImage32 사용)가 작동합니다 **

다음 코드는 런타임에 Graphics32.TImage32에 PNG 이미지를 할당하는 데 성공했습니다.알파 채널이 있는 PNG 이미지는 디자인 타임에 TPNGImageCollection(임의 크기의 이미지 혼합을 허용하므로 매우 유용한 구성 요소)에 로드됩니다.양식 생성 시 스트림에 기록된 다음 다음을 사용하여 스트림에서 Image32로 읽혀집니다. PNG를 Bitmap32로 로드.이 작업이 완료되면 TImage32.Bitmap.MasterAlpha에 할당하여 불투명도를 제어할 수 있습니다.OnPaint 처리기를 사용하면 걱정할 필요가 없습니다.

procedure TAlphaBlendForm.FormCreate(Sender: TObject);

var
  FStream          : TMemoryStream ;
  AlphaChannelUsed : boolean ;

begin
  FStream := TMemoryStream.Create ;

  try
    PngImageCollection1.Items [0].PngImage.SaveToStream (FStream) ;
    FStream.Position := 0 ;
    LoadPNGintoBitmap32 (Image321.Bitmap, FStream, AlphaChannelUsed) ;
  finally
    FStream.Free ;
    end;

end ;
도움이 되었습니까?

해결책

David가 질문에 대해 언급한 것처럼 비트맵에 그래픽을 할당하면 알파 채널 정보가 손실됩니다.따라서 픽셀 형식을 다음과 같이 설정하는 것은 의미가 없습니다. pf32bit 방지하는 것 외에도 할당 후 AlphaBlend 호출이 실패하면 어쨌든 비트맵에는 픽셀당 알파가 없습니다.

그러나 png 객체는 투명도 정보를 고려하여 캔버스에 그리는 방법을 알고 있습니다.따라서 해결 방법은 그래픽을 할당하는 대신 비트맵 캔버스에 그리는 것입니다. 그런 다음 알파 채널이 없으므로 AC_SRC_ALPHA 에서 플래그 BLENDFUNCTION.

다음은 D2007의 작업 코드입니다.

procedure TAlphaBlendForm.FormCreate(Sender: TObject);
begin
  Image1.Picture.LoadFromFile(
      ExtractFilePath(Application.ExeName) + 'Icon_attention_s.png');

  FBitmap := TBitmap.Create;
  FBitmap.Width := Image1.Picture.Graphic.Width;
  FBitmap.Height := Image1.Picture.Graphic.Height;

  FBitmap.Canvas.Brush.Color := Color;      // background color for the image
  FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);

  FBitmap.Canvas.Draw(0, 0, Image1.Picture.Graphic);

  PaintBox1.Width := FBitmap.Width;
  PaintBox1.Height := FBitmap.Height;
end;

procedure TAlphaBlendForm.PaintBox1Paint(Sender: TObject);
var
  fn: TBlendFunction;
begin
  fn.BlendOp := AC_SRC_OVER;
  fn.BlendFlags := 0;
  fn.SourceConstantAlpha := FOpacity;
  fn.AlphaFormat := 0;
  Windows.AlphaBlend(
    PaintBox1.Canvas.Handle,
    0,
    0,
    PaintBox1.Width,
    PaintBox1.Height,
    FBitmap.Canvas.Handle,
    0,
    0,
    FBitmap.Width,
    FBitmap.Height,
    fn
  );
end;

아니면 중간체를 사용하지 않고 TImage:

procedure TAlphaBlendForm.FormCreate(Sender: TObject);
var
  PNG: TPNGObject;
begin
  PNG := TPNGObject.Create;
  try
    PNG.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Icon_attention_s.png');

    FBitmap := TBitmap.Create;
    FBitmap.Width := PNG.Width;
    FBitmap.Height := PNG.Height;

    FBitmap.Canvas.Brush.Color := Color;
    FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);

    PNG.Draw(FBitmap.Canvas, FBitmap.Canvas.ClipRect);

    PaintBox1.Width := FBitmap.Width;
    PaintBox1.Height := FBitmap.Height;
  finally
    PNG.Free;
  end;
end;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top