Da ich den Source nicht mehr wirklich durchblicke, habe ich mir schnell mal ein eigenes Testprogramm angelegt, welches soweit zu meiner Zufriedenheit funktioniert
Der Start des Live Bildes sieht etwa so aus:
Delphi-Quellcode:
procedure TAtmoWinLive.Start(Format: TPixelFormat);
begin
if (
not (Format
in [pf16Bit, pf24Bit, pf32Bit]))
then
begin
raise Exception.Create('
Unsupported pixel format.');
end;
FFormat := Format;
FAtmoWin.SetEffect(cemLivePicture, FOldEffect);
FOldLiveViewSource := FAtmoWin.GetLiveViewSource;
FAtmoWin.SetLiveViewSource(lvsExternal);
CreateTransferBuffers;
FInitialized := true;
end;
Die Transfer Buffer werden, wie schon von jaenicke korrekt vorgeschlagen, nur einmal pro "Session" erstellt und für jeden Frame wiederverwendet. Ebenfalls initialisiere ich hier ein internes Bitmap mit der von AtmoWin gelieferten Zielgröße:
Delphi-Quellcode:
procedure TAtmoWinLive.CreateTransferBuffers;
var
W, H, ImageSize: Integer;
Header: PBitmapInfoHeader;
begin
FAtmoWin.GetLiveViewResolution(W, H);
FBitmapHeader := SafeArrayCreateVector(VT_UI1, 0, SizeOf(TBitmapInfoHeader));
if (
not Assigned(FBitmapHeader))
then
begin
raise Exception.Create('
Failed to create bitmap header buffer.');
end;
OleCheck(SafeArrayAccessData(FBitmapHeader, Pointer(Header)));
try
ZeroMemory(Header, SizeOf(Header));
Header^.biSize := SizeOf(TBitmapInfoHeader);
Header^.biWidth := W;
Header^.biHeight := H;
Header^.biPlanes := 1;
case FFormat
of
pf16bit: Header^.biBitCount := 16;
pf24bit: Header^.biBitCount := 24;
pf32bit: Header^.biBitCount := 32;
end;
Header^.biCompression := BI_RGB;
ImageSize := W * H * Header^.biBitCount;
finally
OleCheck(SafeArrayUnaccessData(FBitmapHeader));
end;
FBitmapData := SafeArrayCreateVector(VT_UI1, 0, ImageSize);
if (
not Assigned(FBitmapData))
then
begin
DestroyTransferBuffers;
raise Exception.Create('
Failed to create bitmap data buffer.');
end;
FBitmap := TBitmap.Create;
FBitmap.PixelFormat := FFormat;
FBitmap.Width := W;
FBitmap.Height := H;
end;
Die eigentlichen Farbwerte sende ich mit folgender Funktion. Hierbei mache ich mir zu nutzen, dass die Berechnung der AmbiLight Farben im Grunde genommen ja nur auf der Berechnung des Durchschnittsfarbwertes für einen bestimmten Quadranten des Bildschirms beruht. Diese Berechnung nehme ich nicht per Hand vor, sondern benutze ein einfaches
GDI StretchBlt im HALFTONE Mode. Danach werden die Pixel Daten in das entsprechende Array kopiert und an AtmoWin gesendet:
Delphi-Quellcode:
procedure TAtmoWinLive.Update(B: TBitmap);
var
Data: Pointer;
BPP, H: Integer;
begin
if (
not FInitialized)
then Exit;
if (B.PixelFormat <> FFormat)
then
begin
raise Exception.Create('
Invalid pixel format.');
end;
SetStretchBltMode(FBitmap.Canvas.Handle, HALFTONE);
StretchBlt(FBitmap.Canvas.Handle, 0, 0, FBitmap.Width, FBitmap.Height, B.Canvas.Handle,
0, 0, B.Width, B.Height, SRCCOPY);
OleCheck(SafeArrayAccessData(FBitmapData, Data));
try
BPP := 2;
case FFormat
of
pf24bit: BPP := 3;
pf32bit: BPP := 4;
end;
for H := 0
to FBitmap.Height - 1
do
begin
{$WARNINGS OFF}
CopyMemory(Pointer(NativeUInt(Data) + H * FBitmap.Width * BPP),
FBitmap.ScanLine[H], FBitmap.Width * BPP);
{$WARNINGS ON}
end;
finally
OleCheck(SafeArrayUnaccessData(FBitmapData));
end;
FAtmoWin.SetLiveViewPixelData(FBitmapHeader, FBitmapData);
end;
Und schließlich wird beim Beenden des Live Bilds noch der vorher gesicherte Modus wiederhergestellt:
Delphi-Quellcode:
procedure TAtmoWinLive.Stop;
begin
FInitialized := false;
DestroyTransferBuffers;
if (FOldLiveViewSource <> lvsExternal) then
begin
FAtmoWin.SetLiveViewSource(FOldLiveViewSource);
end;
if (FOldEffect <> cemLivePicture) then
begin
FAtmoWin.SetEffect(FOldEffect);
end;
end;
@Emil: Wenn du magst, kannst du meine Klassen gerne für dein Projekt übernehmen. Im Grunde musst du nur die Update Funktion mit deinem
DirectX Screenshot füttern
Viele Grüße
Zacherl