ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Printer Canvas / TMetafileCanvas - Transparent Bitmaps & Fills
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

Fellafoo

USA
52 Posts

Posted - May 04 2022 :  09:18:48  Show Profile  Reply
In our existing graphics pipeline we call our own procedure 'OutputDC' to get a handle to various canvases such as the main drawing form or the memory bitmap that is blitted to this form. Other destinations are the Printer (or a TMetafileCanvas used for print preview) and the Windows clipboard.

Now that I've got TIEBitmap.RenderToCanvasWithAlpha and TIECanvas.Rectangle (over clipping region) working for the drawing form I'm hoping I can leverage similar logic for the printer, etc.

If I have a handle (HDC) to Printer.Handle, should I be able to render/draw to this canvas in a similar way? For example...

  ieCnv := TIECanvas.Create(Printer.Handle);
  with ieCnv do begin
    Pen.Color := BrClr;
    Pen.Transparency := BrOp;
    Pen.Width := 0;

    { Set unique brush property for ieCanvas }
    Brush.Color := BrClr;
    Brush.Transparency := BrOp; { 0 - 255 }
    Brush.Style := bsSolid;

    Rectangle(ClipRect);

    Free;
  end;


I've experimented with this a bit but I've been unable to get the transparent fills or bitmaps with an alpha channel to appear on the Printer canvas. Any insight would be greatly appreciated.

Thank You,

MFM

xequte

38610 Posts

Posted - May 04 2022 :  14:30:26  Show Profile  Reply
Hi

When the destination canvas does not support alpha transparency, alpha objects will be downgraded to something that the destination understands.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

Fellafoo

USA
52 Posts

Posted - May 05 2022 :  06:34:51  Show Profile  Reply
I've made some progress with bitmaps rendering to a TMetafileCanvas. Render to canvas works (without transparency of course). The transparent areas will 'match' the paper color if I set the transparent color to white. RenderToCanvas accepts a negative value for the destination height.
ieBmp.RenderToCanvas(ieCnv.GDICanvas, xDst, yDst, dxDst, -dyDst, xSrc, ySrc, dxSrc, dySrc, rfFastLinear, 0, clWhite, True);

When I use RenderToCanvasWithAlpha, transparent areas render in black. How do I get them to render in white?
The RenderToCanvasWithAlpha procedure does not accept a negative value for the destination height, so I must subtract it from yDst instead.
ieBmp.RenderToCanvasWithAlpha(ieCnv.GDICanvas, xDst, yDst - dyDst, dxDst, {-}dyDst, xSrc, ySrc, dxSrc, dySrc, 0, 0, ieBmp.Width, ieBmp.Height, 255, rfFastLinear, ielNormal, 1);

Since the transparent areas are currently rendering in white, I cannot tell if transparency is working. If it's not, is there a way to merge the bitmap with a copy of the canvas before I render it to the destination? Since this occurs during the print preview process, speed is not as critical.
Go to Top of Page

xequte

38610 Posts

Posted - May 08 2022 :  16:10:18  Show Profile  Reply
Well, for destinations that do not support alpha, you might want to dispense with it before drawing, e.g. by parsing the AlphaChannel scanline or merging with a color:

https://www.imageen.com/help/TIEBitmap.RemoveAlphaChannel.html


Nigel
Xequte Software
www.imageen.com
Go to Top of Page

Fellafoo

USA
52 Posts

Posted - May 09 2022 :  05:03:59  Show Profile  Reply
I've not been able to find any way to reliably determine whether a canvas supports alphablending. I created the following test program. When I print to 'Microsoft Print to PDF' the blending works as expected. However, if I print to 'CutePDF Writer' Alphablend returns True but the image is rendered with an opaque background. Printing to 'Canon MF4500 Series UFRII LT' fails outright and Alphalend returns false.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Printers, WinSpool, CommDlg;

type
  TForm1 = class(TForm)
    BtnPrint: TButton;
    procedure BtnPrintClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  iegdiplus, iexbitmaps, hyieutils, hyiedefs;

procedure DrawRectangles(aDC: HDC; PageRect: TRect);
var
  R1, R2, R3: TRect;
  PrintCnv: TCanvas; { For ImageEN to render to }
  ieBmp: TIEBitmap; { ImageEN Bitmap }
  ieCnv: TIECanvas; { ImageEN Canvas }

begin
  PrintCnv := TCanvas.Create;
  PrintCnv.Handle := aDC;

  ieCnv := TIECanvas.Create(PrintCnv);
  ieCnv.SetCompositingMode(ieCompositingModeSourceOver, ieCompositingQualityDefault);

  { Create bitmap same size as page }
  ieBmp := TIEBitmap.Create(PageRect.Right, PageRect.Bottom, ie32RGB);
  ieBmp.Fill(clWhite); { Paper Color }
  ieBmp.AlphaFill(0); { Clear Alpha Channel }

  R1 := PageRect;
  { Shrink Rectangle }
  InflateRect(R1, -PageRect.Right div 4, -PageRect.Bottom div 4);
  R2 := R1;
  R3 := R2;

  { Move Rectangles }
  OffSetRect(R1, MulDiv(-R1.Left, 5, 10), MulDiv(-R1.Top, 5, 10));
  OffSetRect(R2, MulDiv(R2.Left, 5, 10), MulDiv(R2.Top, 5, 10));

  { Draw Rectangles }
  with ieBmp.IECanvas do begin
    Pen.Color := clBlack;
    Pen.Width := 3;
    Brush.Style := bsSolid;
    Brush.Transparency := 128;
    Brush.Color := RGB(192, 0, 192);
    Rectangle(R1);
    Brush.Color := RGB(0, 192, 0);
    Rectangle(R2);
    Brush.Color := RGB(192, 192, 0);
    Rectangle(R3);
  end;

  ieBmp.DrawToCanvas(ieCnv.GDICanvas, PageRect.Left, PageRect.Top);

  ieBmp.Free;
  ieCnv.Free;
  PrintCnv.Free;
end;

procedure AlphaBlendBitmapToCanvas(aDC: HDC; PageRect: TRect);
{ 'Transfer' TIEBitmap Bitmap/Alpha to TBitmap and Alphablend to Canvas }
type
  TQuadColor = packed record
    case Boolean of
      True: (Blue, Green, Red, Alpha: Byte);
      False: (Quad: Cardinal);
  end;
  pQuadColor = ^TQuadColor;

var
  aBmpToBlend: TBitmap;
  BmpWithAlpha: TIEBitmap; { 32Bit ImageEN Bitmap }

  RowY,
  ColX: Integer;
  Alpha: Byte;
  Pixel: PQuadColor;
  bf: BLENDFUNCTION;

begin
  BmpWithAlpha := TIEBitmap.Create('SomePngWithTransparentPixels.png');

  aBmpToBlend := TBitmap.Create;
  BmpWithAlpha.CopyToTBitmap(aBmpToBlend);
  aBmpToBlend.PixelFormat := pf32Bit;

  { Transfer values from TIEBitmap to TBitmap }
  for RowY := 0 to aBmpToBlend.Height - 1 do begin
    Pixel := aBmpToBlend.Scanline[RowY];
    for ColX := 0 to aBmpToBlend.Width - 1 do begin
      Pixel.Alpha := BmpWithAlpha.Alpha[ColX, RowY];
      Pixel.Red := BmpWithAlpha.Pixels[ColX, RowY].r;
      Pixel.Green := BmpWithAlpha.Pixels[ColX, RowY].g;
      Pixel.Blue := BmpWithAlpha.Pixels[ColX, RowY].b;
      Inc(Pixel);
    end;
  end;

  { Blend using Alpha values in aBmpToBlend }
  with bf do begin
    BlendOp := AC_SRC_OVER;
    BlendFlags := 0;
    SourceConstantAlpha := 255;
    AlphaFormat := AC_SRC_ALPHA;
  end;

  if not AlphaBlend(
                    aDC,
                    (PageRect.Right - aBmpToBlend.Width * 2) div 2,
                    (PageRect.Bottom - aBmpToBlend.Height * 2) div 2,
                    aBmpToBlend.Width * 2,
                    aBmpToBlend.Height * 2,
                    aBmpToBlend.Canvas.Handle,
                    0,
                    0,
                    aBmpToBlend.Width,
                    aBmpToBlend.Height,
                    bf
                    ) then
    ShowMessage('Alphablend Failed!');

  aBmpToBlend.Free;
  BmpWithAlpha.Free;
end;

procedure TForm1.BtnPrintClick(Sender: TObject);
var
  pd: TPrintDlg;
  ps: TPageSetupDlg;
  DocInfo: TDocInfo;
  PageRect: TRect;
  PrintArea: TRect;
  MaxPrintArea: TRect;

  aDC: HDC;

begin
  FillChar(ps, SizeOf(ps), #0);
  ps.lStructSize := SizeOf(ps);
  ps.hwndOwner := Form1.Handle;
  //ps.Flags :=
  (*
  if PageSetupDlg(ps) then begin
    PageRect := Rect(0, 0, ps.ptPaperSize.X, ps.ptPaperSize.Y);
    PrintArea := ps.rtMargin;
    MaxPrintArea := ps.rtMinMargin;
  end;
  *)
  FillChar(pd, SizeOf(pd), #0);
  pd.lStructSize := SizeOf(pd);
  pd.hWndOwner := Form1.Handle;
  pd.Flags := {PD_PRINTSETUP} PD_RETURNDC;

  if PrintDlg(pd) then begin
    FillChar(DocInfo, SizeOf(DocInfo), #0);
    DocInfo.cbSize := SizeOf(DocInfo);
    GetMem(DocInfo.lpszDocName, 32);
    GetMem(DocInfo.lpszOutput, MAX_PATH);
    lStrCpy(DocInfo.lpszDocName, 'Alphablend to Canvas');

    StartDoc(pd.hDC, DocInfo);

    DrawRectangles(pd.hDC, Rect(0, 0, Printer.PageWidth, Printer.PageHeight));

    AlphaBlendBitmapToCanvas(pd.hDC, Rect(0, 0, Printer.PageWidth, Printer.PageHeight));

    EndDoc(pd.hDC);

    FreeMem(DocInfo.lpszDocName, 32);
    FreeMem(DocInfo.lpszOutput, MAX_PATH);
  end;
end;

end.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: