6

画像 (Jpg、Bmp)、または透明なテキスト (背景画像と同じ色) に半透明のテキストを書き込むにはどうすればよいですか。

Delphi win32 を使用してそれを達成したいと考えています。

4

6 に答える 6

7

1 つのオプションは、Windows.pas ユニットで AlphaBlend 関数を使用することです。このようなものは、画像にオーバーレイされた半透明のテキスト (ドロップ シャドウ付き - Jim McKeeth の応答に基づく) を生成します。

  
uses Windows, Graphics;
.
.
.
var
  BackgroundImage: Graphics.TBitmap; { need to call out specifically for Graphics.TBitmap
                                       because the Windows unit also has a TBitmap
                                       declaration }
  TextImage: Graphics.TBitmap;
  BlendFunc: BLENDFUNCTION;
begin
  BlendFunc.BlendOp := AC_SRC_OVER;
  BlendFunc.BlendFlags := 0;
  BlendFunc.SourceConstantAlpha := $C0; { a hex value from $00-$FF (0-255).
                                          Represents the percent of opaqueness:
                                          $00 is completely transparent, 
                                          $FF is completely opaque.
                                          $C0 is 75% opaque }
  BlendFunc.AlphaFormat := AC_SRC_ALPHA;

    { BackgroundImage is for holding the image you want to overlay text onto }
    BackgroundImage := Graphics.TBitmap.Create;
    try
      BackgroundImage.LoadFromFile('yourimagehere.bmp');

      { Create another TBitmap to hold the text you want to overlay }
      TextImage := Graphics.TBitmap.Create;
      try
        { Set this bitmap to have the same dimensions as the
          background image you want the text to appear on. }
        TextImage.Height := BackgroundImage.Height;
        TextImage.Width := BackgroundImage.Width;

        { In my limited experience with AlphaBlend, Black is always 100%
          transparent. So, paint TextImage completely Black. Play around
          with this to see the effect it has on the final outcome. }
        TextImage.Canvas.Brush.Color := clBlack;
        TextImage.Canvas.FloodFill(0, 0, clNone, fsBorder);

        TextImage.Canvas.Font.Style := [fsBold];

        { Write the shadow first }
        TextImage.Canvas.Brush.Style := bsClear;
        TextImage.Canvas.Font.Color  := clDkGray;
        TextImage.Canvas.TextOut(11, 11, 'Test');

        { Then put the text on top (slightly offset) }
        TextImage.Canvas.Brush.Style := bsClear;
        TextImage.Canvas.Font.Color  := clMaroon;
        TextImage.Canvas.TextOut(10, 10, 'Test');

        { Use the AlphaBlend function to overlay the bitmap holding the text
          on top of the bitmap holding the original image. }
        Windows.AlphaBlend(BackgroundImage.Canvas.Handle, 0, 0,
                           TextImage.Width, TextImage.Height,
                           TextImage.Canvas.Handle, 0, 0, TextImage.Width,
                           TextImage.Height, BlendFunc);

        { Assign the now updated BackgroundImage to a TImage control for display }  
        Image1.Picture.Bitmap.Assign(BackgroundImage);
      finally
        TextImage.Free;
      end;
    finally
      BackgroundImage.Free;
    end;
  end;
于 2008-12-12T15:48:17.423 に答える
3

あなたが達成しようとしていることは、単純に透明な背景でテキストを書くよりも少し複雑だと思います。つまり、画像上に何らかの形式のアルファ混合テキストを書き込もうとしています。
最も簡単な方法は、GDI+ ルーチンを利用することです。これらは Delphi 用にカプセル化されており、http://www.progdigy.com/からダウンロードできます。例として使用できるはずの多くの例があります。

于 2008-12-11T21:03:18.843 に答える
3

影は簡単です:

// Bold shows up better when over an image
image1.Canvas.Font.Style := [fsBold]; 
// Write the shadow first
image1.Canvas.Brush.Style:=bsClear;
image1.Canvas.Font.Color := clGrayText;
image1.Canvas.TextOut(1, 1, 'hi there');
// Then put the text on top (slightly offset)
image1.Canvas.Brush.Style:=bsClear;
image1.Canvas.Font.Color :=clBlack;
image1.Canvas.TextOut(0, 0, 'hi there');

これは、背景が透明なテキストです。それとも、テキスト自体を半透明にしたかったのですか? それは少しトリッキーです。手動で描画する必要があります。代わりに、画像に書いている領域の色の平均をサンプリングするのが簡単な方法です。次に、フォントの色を少し明るく、影を少し暗く設定します。すると、なんとなく溶け込みます。

于 2008-12-11T20:54:46.580 に答える
2

私はそれをテストしていませんが、どこに行けばよいかがわかります。重要なのはブラシ スタイルです。

このようなもの:

img.Canvas.Brush.Style:=bsClear;
img.Canvas.Font.Color:=clBlack;
img.Canvas.TextOut(0, 0, 'hi there');
于 2008-12-11T19:04:42.810 に答える
2

この関数は Dave Elsberry のアイデアに基づいています。

違い:

  • 影だけを透明に描く
  • 使用する RAM はほぼ 2 分の 1 です
  • パラメーター

{-------------------------------------------------------------------------------------------------------------
  DrawTextShadowBox
    Draws text in a semi-transparent rectangle with shadow text.
    The shadow text is blended to the background and then blurred.

  Variant:
     1: Draws text in a box that is as wide as the BMP and can be aligned to top or bottom
     2: Draws text in a box that is as wide as text and is placed into the image at coordinates x,y

  Parameters:
     Opacity a value from 0-255. 0 => Shadow is completelly transparent
     To set the Font color/size, the caller should do: aCanvas.Font.Size:= x

  Issues:
     The blurring function cuts too suddenly. The rectangle that was blurred is too visible. Do a blur that slowly fades at the edges.
     Might be slow becuase of the alpha blending and because of the blur.

 Important!
     The input img must be pf24bit.
     When the AlphaFormat member is AC_SRC_ALPHA, the source bitmap must be 32 bpp. If it is not, the AlphaBlend function will fail.
-------------------------------------------------------------------------------------------------------------}
procedure DrawTextShadowBox(BMP: TBitmap; CONST Text: string; AlignTop: Boolean; ShadowColor: TColor= clTextShadow; ShadowOpacity: Byte= 20; Blur: Byte= 2);
VAR
   Shadow: Vcl.Graphics.TBitmap;
   BlendFunc: BLENDFUNCTION;
   x, y: Integer;
   BmpRect: TRect; { Rectangle in the original bitmap where we want to draw the shadowed text }
   ShadowRect: TRect;
   TextWidth, TextHeight: Integer;
   OriginalColor: TColor;
begin
  Assert(BMP.PixelFormat= pf24bit, 'Wrong pixel format!!');
  OriginalColor:= bmp.Canvas.Font.Color;
  TextWidth := BMP.Canvas.TextWidth (Text);
  TextHeight:= BMP.Canvas.TextHeight(Text);

  { Write the shadow on a separate bitmap (overlay) }
  Shadow := TBitmap.Create;
  TRY
    { Bitmap setup }
    Shadow.Canvas.Font.Assign(BMP.Canvas.Font);
    Shadow.PixelFormat:= pf24bit;
    Shadow.SetSize(BMP.Width, TextHeight);

    { Bitmap rectangle as big as ShadowBMP }
    ShadowRect.Left:= 0;
    ShadowRect.Top := 0;
    ShadowRect.Right := Shadow.Width;
    ShadowRect.Bottom:= Shadow.Height;

    { Fill shadow rectangle }
    Shadow.Canvas.Brush.Color := clBlack;                                        { In AlphaBlend, Black is always 100% transparent. So, paint Shadow completely Black. }
    Shadow.Canvas.FillRect(ShadowRect);

    BmpRect.Left  := 0;
    BmpRect.Right := Shadow.Width;
    if AlignTop
    then BmpRect.Top := 0
    else BmpRect.Top := BMP.Height- TextHeight;
    BmpRect.Bottom:= BmpRect.Top+ TextHeight;

    { Blend rectangle with orig image }                                          { Use the AlphaBlend function to overlay the bitmap holding the text on top of the bitmap holding the original image. }
    BlendFunc.BlendOp    := AC_SRC_OVER;
    BlendFunc.BlendFlags := 0;
    BlendFunc.SourceConstantAlpha := ShadowOpacity;
    BlendFunc.AlphaFormat         := 0;                                          //AC_SRC_ALPHA; //  if I put this back, the shadow will be completly invisible when merged with a white source image
    WinApi.Windows.AlphaBlend(BMP.Canvas.Handle, BmpRect.Left, BmpRect.Top, BmpRect.Right, TextHeight, Shadow.Canvas.Handle, 0, 0, Shadow.Width, Shadow.Height, BlendFunc);

    { Copy the blended area back to the Shadow bmp }
    Shadow.Canvas.CopyRect(ShadowRect, BMP.Canvas, BmpRect);

    { Diagonal shadow }
    x:= (BMP.Width  - TextWidth) DIV 2;   // Find center
    Shadow.Canvas.Brush.Style:= bsClear;
    Shadow.Canvas.Font.Color := ShadowColor;
    Shadow.Canvas.TextOut(x, 0, Text);

    { Blur the shadow }
    janFX.GaussianBlur(Shadow, Blur, 1);

    { Paste it back }
    BMP.Canvas.CopyRect(BmpRect, Shadow.Canvas, ShadowRect);
  FINALLY
    FreeAndNil(Shadow);
  END;

  { Draw actual text at 100% opacity }
  if AlignTop
  then y := 0
  else y := BMP.Height- TextHeight;
  BMP.Canvas.Brush.Style:= bsClear;
  BMP.Canvas.Font.Color := OriginalColor;
  BMP.Canvas.TextOut(x, y, Text);
end;



procedure DrawTextShadowBox(aCanvas: TCanvas; CONST Text: string;  X, Y: Integer; ShadowColor: TColor= clTextShadow; ShadowOpacity: Byte= 20; Blur: Byte= 2);
VAR
   Shadow: Vcl.Graphics.TBitmap;
   BlendFunc: BLENDFUNCTION;
   H, W: Integer;
   OriginalColor: TColor;
   R, R2: TRect;
CONST Edge= 5;
begin
 OriginalColor:= aCanvas.Font.Color;

 { Write the shadow on a separate bitmap (overlay) }
 Shadow := TBitmap.Create;
 TRY
   { Assign font }
   Shadow.Canvas.Font.Assign(aCanvas.Font);
   Shadow.PixelFormat:= pf24bit;

   { Compute overlay size }
   W:= Shadow.Canvas.TextWidth (Text);
   H:= Shadow.Canvas.TextHeight(Text);
   Shadow.SetSize(W, H);

   { Fill shadow rectangle }
   R:= Rect(0, 0, Shadow.Width, Shadow.Height);
   Shadow.Canvas.Brush.Color := clBlack;                               { In AlphaBlend, Black is always 100% transparent. So, paint Shadow completely Black. }
   Shadow.Canvas.FillRect(R);

   { Blend rectangle with orig image }                                 { Use the AlphaBlend function to overlay the bitmap holding the text on top of the bitmap holding the original image. }
   BlendFunc.BlendOp := AC_SRC_OVER;
   BlendFunc.BlendFlags := 0;
   BlendFunc.SourceConstantAlpha := ShadowOpacity;
   BlendFunc.AlphaFormat := 0;                                         //AC_SRC_ALPHA; //  if I put this back, the shadow will be completly invisible when merged with a white source image
   WinApi.Windows.AlphaBlend(aCanvas.Handle, x, y, Shadow.Width, Shadow.Height, Shadow.Canvas.Handle, 0, 0, Shadow.Width, Shadow.Height, BlendFunc);

   { Copy the blended area back to the Shadow bmp }
   R2:= rect(x, y, x+Shadow.Width, y+Shadow.Height);
   Shadow.Canvas.CopyRect(R, aCanvas, R2);

   { Diagonal shadow }
   Shadow.Canvas.Brush.Style:= bsClear;
   Shadow.Canvas.Font.Color := ShadowColor;
   Shadow.Canvas.TextOut(0, 0, Text);

   { Blur the shadow }
   janFX.GaussianBlur(Shadow, blur, 1);

   { Paste it back }
   aCanvas.CopyRect(R2, Shadow.Canvas, R);
 FINALLY
   FreeAndNil(Shadow);
 END;

 { Draw actual text at 100% opacity }
 aCanvas.Brush.Style:= bsClear;
 aCanvas.Font.Color := OriginalColor;
 aCanvas.TextOut(x, y, Text);
end;


procedure TfrmTest.UseIt;
VAR BackgroundImage: tbitmap;
begin
 BackgroundImage := Graphics.TBitmap.Create;   
 try
   BackgroundImage.LoadFromFile('c:\test.bmp');
   DrawShadowText (BackgroundImage.Canvas, 'This is some demo text', 20, 40, 140, clRed, clSilver);
   Image1.Picture.Bitmap.Assign(BackgroundImage);
 FINALLY
   BackgroundImage.Free;
 end;
end;
于 2014-04-06T12:45:06.303 に答える
1

bitbltルーチンを使用して画像を共通のキャンバスにマージし、画像を再度保存することができます。

于 2008-12-11T23:17:53.780 に答える