interface
uses
Winapi.Windows,
Winapi.D2D1,
Winapi.DXGI,
Winapi.DxgiFormat,
System.SysUtils, System.Classes,
Vcl.Graphics,
Vcl.Direct2D;
type
// This describes how the individual mapping operation should be performed.
PD2D1_MAP_OPTIONS = ^D2D1_MAP_OPTIONS;
D2D1_MAP_OPTIONS = DWord;
{$EXTERNALSYM D2D1_MAP_OPTIONS}
const
// The mapped pointer has undefined behavior.
D2D1_MAP_OPTIONS_NONE = D2D1_MAP_OPTIONS(0);
{$EXTERNALSYM D2D1_MAP_OPTIONS_NONE} // The mapped pointer can be read from.
D2D1_MAP_OPTIONS_READ = D2D1_MAP_OPTIONS(1);
{$EXTERNALSYM D2D1_MAP_OPTIONS_READ} // The mapped pointer can be written to.
D2D1_MAP_OPTIONS_WRITE = D2D1_MAP_OPTIONS(2);
{$EXTERNALSYM D2D1_MAP_OPTIONS_WRITE} // The previous contents of the bitmap are discarded when it is mapped.
D2D1_MAP_OPTIONS_DISCARD = D2D1_MAP_OPTIONS(4);
{$EXTERNALSYM D2D1_MAP_OPTIONS_DISCARD} // D2D1_MAP_OPTIONS_FORCE_DWORD = FORCEDWORD;
type
// Specifies how the bitmap can be used.
PD2D1_BITMAP_OPTIONS = ^D2D1_BITMAP_OPTIONS;
D2D1_BITMAP_OPTIONS = DWord;
{$EXTERNALSYM D2D1_BITMAP_OPTIONS}
const
// The bitmap is created with default properties.
D2D1_BITMAP_OPTIONS_NONE = D2D1_BITMAP_OPTIONS($00000000);
// The bitmap can be specified as a target in ID2D1DeviceContext.SetTarget
D2D1_BITMAP_OPTIONS_TARGET = D2D1_BITMAP_OPTIONS($00000001);
// The bitmap cannot be used as an input to DrawBitmap, DrawImage, in a bitmap
// brush or as an input to an effect.
D2D1_BITMAP_OPTIONS_CANNOT_DRAW = D2D1_BITMAP_OPTIONS($00000002);
// The bitmap can be read from the CPU.
D2D1_BITMAP_OPTIONS_CPU_READ = D2D1_BITMAP_OPTIONS($00000004);
// The bitmap works with the ID2D1GdiInteropRenderTarget.GetDC API.
D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE = D2D1_BITMAP_OPTIONS($00000008);
// D2D1_BITMAP_OPTIONS_FORCE_DWORD = FORCEDWORD;
type
// Describes mapped memory from the ID2D1Bitmap1.Map API.
PD2D1_MAPPED_RECT = ^D2D1_MAPPED_RECT;
D2D1_MAPPED_RECT =
record
pitch : UINT32;
bits : PByte;
end;
ID2D1Bitmap1 =
interface(ID2D1Bitmap)
['
{a898a84c-3873-4588-b08b-ebbf978df041}']
// Retrieves the color context information associated with the bitmap.
procedure GetColorContext(
out colorContext : IInterface);
stdcall;
// Retrieves the bitmap options used when creating the API.
function GetOptions() : D2D1_BITMAP_OPTIONS;
stdcall;
// Retrieves the DXGI surface from the corresponding bitmap, if the bitmap was
// created from a device derived from a D3D device.
function GetSurface(
out dxgiSurface : IDXGISurface) : HResult;
stdcall;
// Maps the given bitmap into memory. The bitmap must have been created with the
// D2D1_BITMAP_OPTIONS_CPU_READ flag.
function Map(options : D2D1_MAP_OPTIONS;
out mappedRect : D2D1_MAPPED_RECT) : HResult;
stdcall;
// Unmaps the given bitmap from memory.
function Unmap() : HResult;
stdcall;
end;
IID_ID2D1Bitmap1 = ID2D1Bitmap1;
// Extended bitmap properties.
PD2D1_BITMAP_PROPERTIES1 = ^D2D1_BITMAP_PROPERTIES1;
D2D1_BITMAP_PROPERTIES1 =
record
_pixelFormat : D2D1_PIXEL_FORMAT;
dpiX : Single;
dpiY : Single;
// Specifies how the bitmap can be used.
bitmapOptions : D2D1_BITMAP_OPTIONS;
colorContext : IInterface;
end;
{$EXTERNALSYM D2D1_BITMAP_PROPERTIES1}
// Interface ID2D1DeviceContext
// ============================
// The device context represents a set of state and a command buffer that is used
// to render to a target bitmap.
//
{$HPPEMIT 'DECLARE_DINTERFACE_TYPE(ID2D1DeviceContext);'}
{$EXTERNALSYM ID2D1DeviceContext}
ID2D1DeviceContext =
interface(ID2D1RenderTarget)
['
{e8f7fe7a-191c-466d-ad95-975678bda998}']
// Creates a bitmap with extended bitmap properties, potentially from a block of
// memory.
function CreateBitmap(size : D2D1_SIZE_U; sourceData : Pointer; pitch : UINT32;
bitmapProperties : PD2D1_BITMAP_PROPERTIES1;
out bitmap : ID2D1Bitmap1) : HResult;
stdcall;
end;
function DoSaveAsBitmap(
const ARenderTarget : ID2D1RenderTarget;
out ResBmp : TBitmap) : Boolean;
implementation
function DoSaveAsBitmap(
const ARenderTarget : ID2D1RenderTarget;
out ResBmp : TBitmap) : Boolean;
var
HR : HResult;
DeviceContext : ID2D1DeviceContext;
CopyBmp : ID2D1Bitmap1;
mappedRect : D2D1_MAPPED_RECT;
SizeU : D2D1_SIZE_U;
destPoint : D2D1_POINT_2U;
srcRect : D2D1_RECT_U;
BmpProps : D2D1_BITMAP_PROPERTIES1;
BmpInfo : TBitmapInfo;
begin
Result := false;
ResBmp := TBitmap.Create;
// create vcl.bitmap
if Supports(ARenderTarget, ID2D1DeviceContext, DeviceContext)
then
begin
DeviceContext.GetPixelFormat(BmpProps._pixelFormat);
DeviceContext.GetDpi(BmpProps.dpiX, BmpProps.dpiY);
DeviceContext.GetPixelSize(SizeU);
BmpProps.bitmapOptions := D2D1_BITMAP_OPTIONS_CPU_READ
or D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
HR := DeviceContext.CreateBitmap(SizeU,
nil, 0, @BmpProps, CopyBmp);
// create CopyBmp : ID2D1Bitmap1
if Succeeded(HR)
then
begin
srcRect.left := 0;
srcRect.top := 0;
srcRect.right := SizeU.Width;
srcRect.bottom := SizeU.Height;
destPoint.X := 0;
destPoint.Y := 0;
HR := CopyBmp.CopyFromRenderTarget(destPoint, DeviceContext, srcRect);
// copy pixel to CopyBmp
if Succeeded(HR)
then
begin
HR := CopyBmp.Map(D2D1_MAP_OPTIONS_READ, mappedRect);
if Succeeded(HR)
then
begin
FillChar(BmpInfo, SizeOf(BmpInfo), 0);
SizeU.Width := mappedRect.pitch
div 4;
BmpInfo.bmiHeader.biSize := SizeOf(BmpInfo.bmiHeader);
BmpInfo.bmiHeader.biHeight := -SizeU.Height;
BmpInfo.bmiHeader.biWidth := SizeU.Width;
BmpInfo.bmiHeader.biPlanes := 1;
BmpInfo.bmiHeader.biBitCount := 32;
ResBmp.SetSize(SizeU.Width, SizeU.Height);
ResBmp.PixelFormat := TPixelFormat.pf32bit;
const _DC = CreateCompatibleDC(0);
Result := SetDIBits(_DC, ResBmp.Handle, 0, ResBmp.Height, mappedRect.bits, BmpInfo, DIB_RGB_COLORS) > 0;
CopyBmp.Unmap;
end;
end;
end;
end;
if not Result
then
FreeAndNil(ResBmp);
end;
end.