AW: Nach CopyMemory werden Daten nicht übernommen
Zitat:
Delphi-Quellcode:
PpixelDataArr: PSafeArray = nil;
Ist global in der AtmoCtrl Unit definiert.
Delphi-Quellcode:
// *********************************************************************//
// schickt den Inhalt des Buffers an den COM Server der AtmoWinA.exe und hebt die Sperre // des Buffers auf. // *********************************************************************// procedure TAtmoCtrlLib.AtmoSendPixelData; stdcall; var pALVC: IAtmoLiveViewControl; begin pALVC := getAtmoLiveViewControl; if Assigned(PpixelDataArr) and Assigned(pALVC) then begin SafeArrayUnaccessData(PpixelDataArr); pALVC.setPixelData(PbitmapInfoArr, PpixelDataArr); end; if Assigned(pALVC) then begin if Assigned(PpixelDataArr) then begin SafeArrayDestroy(PpixelDataArr); PpixelDataArr := nil; end; if Assigned(PbitmapInfoArr) then begin SafeArrayDestroy(PbitmapInfoArr); PbitmapInfoArr := nil; end; pALVC := nil; end; end;
Delphi-Quellcode:
gruss
// *********************************************************************//
//sperrt den Transferbuffer für den aktuellen Thread und liefert einen Zeiger auf den //Speicherblock zurück. //Sollte die DLL noch nicht initialisiert oder kein Aufruf von AtmoCreateTransferBuffers //im voraus erfolgt sein - liefert die Funktion "NULL"! // *********************************************************************// function TAtmoCtrlLib.AtmoLockTransferBuffer: Pointer; stdcall; var pixelData: pByte; begin if Assigned(PpixelDataArr) then SafeArrayAccessData(PpixelDataArr, Pointer(pixelData)); result := pixelData; end; |
AW: Nach CopyMemory werden Daten nicht übernommen
Liste der Anhänge anzeigen (Anzahl: 1)
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:
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:
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;
Delphi-Quellcode:
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:
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;
Delphi-Quellcode:
Und schließlich wird beim Beenden des Live Bilds noch der vorher gesicherte Modus wiederhergestellt:
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;
Delphi-Quellcode:
@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 :)
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; Viele Grüße Zacherl |
AW: Nach CopyMemory werden Daten nicht übernommen
@Zacherl
Zitat:
gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz