Einzelnen Beitrag anzeigen

Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#32

AW: Nach CopyMemory werden Daten nicht übernommen

  Alt 7. Jan 2014, 10:43
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
Angehängte Dateien
Dateityp: rar AtmoWin.rar (89,3 KB, 5x aufgerufen)
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat