Writing Transparent Text on Image

前端 未结 7 1011
名媛妹妹
名媛妹妹 2020-12-16 05:54

How can I write a semi transparent text on an Image (Jpg,Bmp), or a transparent text (color as same background Image) but with a shadow, something I want to do to watermark

相关标签:
7条回答
  • 2020-12-16 06:10

    One option is to use the AlphaBlend function in Windows.pas unit. Something like this will produce semi-transparent text (with a drop shadow - building on Jim McKeeth's response) overlayed on an image:

      
    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;
    
    0 讨论(0)
  • 2020-12-16 06:10

    You could use the bitblt routines to merge an image to a common canvas, then save the image again.

    0 讨论(0)
  • 2020-12-16 06:12

    The shadow is easy:

    // 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');
    

    This is text with a transparent background. Or did you want the text itself to be simi-transparent? That is a little trickier. You would need to draw it manually. An easy way to do it instead would be to sample the average of the color of the area you are writing on the image. Then set your font color to be a little lighter and your shadow to be a little darker. Then it kind of blends in.

    0 讨论(0)
  • 2020-12-16 06:13

    This function is based on Dave Elsberry's idea.

    What's different:

    • Draws only the shadow transparently
    • It uses almost 2 times less RAM
    • Parameters

    procedure DrawShadowText(aCanvas: TCanvas; CONST Text: string; CONST X, Y, Opacity: Integer; TextColor, ShadowColor: TColor);    
    { Opacity a value from 0-255:
         $00 is completely transparent,
         $FF is completely opaque.
         $C0 is 75% opaque }
    CONST ShadowSize= 1;
    VAR
       TempBMP: TBitmap;
       BlendFunc: BLENDFUNCTION;
       H, W: Integer;
    begin
     BlendFunc.BlendOp := AC_SRC_OVER;
     BlendFunc.BlendFlags := 0;
     BlendFunc.SourceConstantAlpha := Opacity;
     BlendFunc.AlphaFormat := AC_SRC_ALPHA;
    
     { Create another TBitmap to hold the text you want to overlay }
     TempBMP := Graphics.TBitmap.Create;
     TRY
       TempBMP.Canvas.Font.Style  := [fsBold];
       TempBMP.Canvas.Brush.Style := bsClear;
    
       W:= TempBMP.Canvas.TextWidth(Text);
       H:= TempBMP.Canvas.TextHeight(Text);
    
       TempBMP.SetSize(W+ShadowSize, H+ShadowSize);
    
       { In AlphaBlend, Black is always 100% transparent. So, paint TempBMP completely Black. }
       TempBMP.Canvas.Brush.Color := clBlack;
       TempBMP.Canvas.FloodFill(0, 0, clNone, fsBorder);
    
       { Write the shadow first }
       TempBMP.Canvas.Font.Color  := ShadowColor;
       TempBMP.Canvas.TextOut(ShadowSize, ShadowSize, Text);     { Diagonal left shadow }
       TempBMP.Canvas.TextOut(ShadowSize, 0,          Text);     { Left shadow }
    
       { Draw the text with transparency:
       TempBMP.Canvas.Brush.Style := bsClear;
       TempBMP.Canvas.Font.Color  := TextColor;
       TempBMP.Canvas.TextOut(0, 0, Text);   }
    
       { Use the AlphaBlend function to overlay the bitmap holding the text on top of the bitmap holding the original image. }
       Windows.AlphaBlend(aCanvas.Handle,
                          x, y, TempBMP.Width, TempBMP.Height,
                          TempBMP.Canvas.Handle, 0, 0, TempBMP.Width, TempBMP.Height,
                          BlendFunc);
    
       { Draw the text at 100% opacity }
       aCanvas.Font.Style  := [fsBold];
       aCanvas.Brush.Style := bsClear;
       aCanvas.Font.Color  := TextColor;
       aCanvas.TextOut(x, y-1, Text);
     FINALLY
       FreeAndNil(TempBMP);
     END;
    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;
    
    0 讨论(0)
  • 2020-12-16 06:16

    I presume what you're trying to accomplish is a little more complicated than simply writing text with a transparent background; i.e. you are trying to get some form of alpha-blended text written on the image.
    The simplest method would be to make use of the GDI+ routines. They are encapsulated for delphi and available for download from http://www.progdigy.com/. There are many examples there which should be usable as an example.

    0 讨论(0)
  • 2020-12-16 06:17

    Improved version. Could be slower than the previous one but it looks MUCH better:

    {-------------------------------------------------------------------------------------------------------------
       Text shadows
    -------------------------------------------------------------------------------------------------------------}
    
    { Draws text in a semi-transparent rectangle with shadow text.
      The shadow text is blended to the background and then blurred.
    
      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 to 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.}
    
    procedure DrawTextShadowRect(aCanvas: TCanvas; CONST Text: string;  X, Y: Integer; ShadowColor: TColor; ShadowOpacity: Byte);
    { Important! When the AlphaFormat member is AC_SRC_ALPHA, the source bitmap must be 32 bpp. If it is not, the AlphaBlend function will fail. }
    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; 
       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.SplitBlur(Shadow, 1);
       janFX.SplitBlur(Shadow, 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;
    
    0 讨论(0)
提交回复
热议问题