Delphi-PRAXiS
Seite 4 von 4   « Erste     234   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Nach CopyMemory werden Daten nicht übernommen (https://www.delphipraxis.net/178391-nach-copymemory-werden-daten-nicht-uebernommen.html)

EWeiss 7. Jan 2014 08:12

AW: Nach CopyMemory werden Daten nicht übernommen
 
Zitat:

Wo du das Array überhaupt mit der AtmoCtrlLib in Verbindung bringst, ist mir aus deinem letzten Quelltext auch nicht klar.
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:
// *********************************************************************//
//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;
gruss

Zacherl 7. Jan 2014 09:43

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:
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

EWeiss 7. Jan 2014 16:46

AW: Nach CopyMemory werden Daten nicht übernommen
 
@Zacherl

Zitat:

@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
Aber gerne doch wenn Sie Vorteile für (mein) das Programm bringt ;)

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:46 Uhr.
Seite 4 von 4   « Erste     234   

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