![]() |
AW: Surface Stream
Um jetzt vielleicht die
Delphi-Quellcode:
versus
Read()
Delphi-Quellcode:
Diskussion abzuschliesen:
ReadBuffer()
Delphi-Quellcode:
Wie man sieht, wird eine Exception geworfen wenn man mehr Bytes lesen möchte als der Stream liefern kann.
// Das ist der Sourcecode von ReadBuffer
procedure TStream.ReadBuffer(var Buffer; Count: Longint); begin if (Count <> 0) and (Read(Buffer, Count) <> Count) then raise EReadError.CreateRes(@SReadError); end; Das ist ein äusserst nützliches Sicherheitsfeature. :thumb: Wenn ein Programmierer z.B. eine Struktur aus einer Datei liest aber die Datei nicht genügend Bytes dafür hat dann hat das sehr unangenehme Folgen. Die fehlenden Bytes sind dann einfach undefiniert was zu extrem schwer zu findenden Bugs führt. Wann immer man die Funktionen
Delphi-Quellcode:
oder
Read()
Delphi-Quellcode:
benützt ist man verpflichtet den Returnwert auszuwerten.
Write()
Tut man das nicht handelt man grob fahrlässig. Das ist vergleichbar mit einem PKW-Fahrer der seinen Sicherheitsgurt nicht benützt obwohl er direkt neben seiner Schulter hängt. Ich habe hier auf der DP noch nie Sourcecode gesehen, der den Returnwert von Read() oder Write() korrekt auswertet. Diese Leute möchte ich am liebsten durchschütteln und zurufen "Anschnallen! Nehmt den Sicherheitsgurt!". :wall: Bleibt vielleicht noch eine Frage offen: Warum hat Borland die Funktionen
Delphi-Quellcode:
und
Read()
Delphi-Quellcode:
dann überhaupt
Write()
Delphi-Quellcode:
gemacht,
public
Delphi-Quellcode:
hätte ja auch gereicht ?
protected
Nun, neben dem häufig verwendeten
Delphi-Quellcode:
gibt es auch Streams, bei denen man nicht im Vorraus weiss oder erwartet wieviele Bytes denn noch vorhanden sind.
TFileStream
Man liest auf Verdacht einen grossen Block (z.B. 4kB) und wertet dann den Returncode aus weil man sich im Klaren darüber ist dass auch 0 Bytes gelesen worden sein könnten. |
AW: Surface Stream
Keine Ahnung, was du bisher hast, aber zum Auslesen der Bildinformationen kannst du
![]() Um jetzt an die einzelnen Pixel zu kommen, berechnest du erstmal die Position des Pixels: Stream.Position := (YPos * Surface.Width + XPos) * 4; Danach liest du ein komplettes DWord aus: Stream.ReadBuffer(Pixel, 4); Und schließlich decodierst du den Pixel folgendermaßen über eine simple Bitmaske:
Delphi-Quellcode:
procedure COLOR_DECODE_ARGB(Color: DWord; var A, R, G, B: Byte); inline;
begin A := (Color and $FF000000) shr 24; R := (Color and $00FF0000) shr 16; G := (Color and $0000FF00) shr 8; B := (Color and $000000FF); end; |
AW: Surface Stream
Zitat:
Ich speichere das Bitmap
Delphi-Quellcode:
D3DXSaveSurfaceToFileW('D:\paper.bmp', D3DXIFF_BMP, scrSurface, nil, @ARect);
lade es zurück.. in den Stream
Delphi-Quellcode:
gs := TFileStream.Create('D:\paper.bmp', fmOpenRead or fmShareDenyNone);
und werte es mit meiner function GetColor aus. Das Ergebnis ist aber nicht das was auf die Platte geschrieben wurde denn dann müßten die Farben stimmen.
Delphi-Quellcode:
pos := (y * Screen.PrimaryMonitor.BoundsRect.Right + x) * 4;
Stream.Position := pos
Delphi-Quellcode:
bu : Array[0..3] of byte;
gs.Read(bu, sizeof(bu));
Delphi-Quellcode:
IDirect3DSurface9::LockRect brauche ich nicht da die Daten über D3DXSaveSurfaceToFileW abgespeichert werden.
function ColorARGB(AlphaChannel: byte; ColrRGB: COLORREF): COLORREF;
var bytestruct: COLORBYTES; begin bytestruct.A := AlphaChannel; bytestruct.R := GetRValue(ColrRGB); bytestruct.G := GetGValue(ColrRGB); bytestruct.B := GetBValue(ColrRGB); Result := MakeColor(bytestruct.A, bytestruct.R, bytestruct.G, bytestruct.B); end; Aber auch damit habe ich es versucht.
Delphi-Quellcode:
Und dann das BMP in eine Datei geschrieben.
p := Cardinal(LockedRect.pBits);
for i := 0 to Screen.Height - 1 do begin CopyMemory(BMP.ScanLine[i], Ptr(p), Screen.Width * BitsPerPixel div 8); p := p + LockedRect.Pitch; end; Wie ich das jetzt direct in den Stream schreibe ist mir noch nicht klar. (so das ich sie im Speicher habe) aber alle Versuche schlagen fehl die Farben stimmen nicht. Sobald ich diese wieder einlade. gruss |
AW: Surface Stream
Versuche mal bitte die Daten wirklich per LockRect in den Stream zu schreiben und nicht den Umweg über das Bitmap zu nehmen. Hierbei lädst du dir nämlich zusätzlich den Bitmap Header in deinen Stream. Wenn die Länge des Bitmap Headers nicht durch 4 teilbar ist, sorgt das dafür, dass sämtliche Pixelinformationen verschoben werden. Desweiteren bin ich mir nicht sicher, ob die D3DX... Funktion das Bitmap nicht einfach (ohne Alpha Channel) als 24-Bit Bitmap speichert.
|
AW: Surface Stream
Zitat:
Würde ich gerne tun nur habe ich mit streams noch nicht die Erfahrung.. Wie kann ich die Daten direkt da reinschreiben ohne Umweg auf die Platte? Zitat:
da mein Bitmap ansich richtig dargestellt wird. gruss |
AW: Surface Stream
Nur auf die Schnelle geschrieben und ungetestet. Sollte aber so in der Art funktionieren:
Delphi-Quellcode:
var
LockedRect: TD3DLockedRect; MS: TMemoryStream; I: Integer; Color: DWord; A, R, G, B: Byte; begin MS := TMemoryStream.Create; try if (Surface.LockRect(LockedRect, nil, D3DLOCK_READONLY) = D3D_OK) then try for I := 0 to SurfaceHeight - 1 do begin // Pitch = Anzahl Bytes per "Zeile", also SurfaceWidth * SizeOf(Pixel) MS.WriteBuffer(Pointer(NativeUInt(LockedRect.pBits) + I * LockedRect.Pitch)^, LockedRect.Pitch); end; finally Surface.UnlockRect; end; // Pixel (24,6) auslesen [*4 ausgehend davon, dass das PixelFormat = ARGB ist] MS.Position := (6 * SurfaceWidth + 24) * 4; MS.ReadBuffer(Color, SizeOf(Color)); COLOR_DECODE_ARGB(Color, A, R, G, B); // .. finally MS.Free; end; end; |
AW: Surface Stream
Das ist nett von dir werde es mal testen.
gruss |
AW: Surface Stream
Danke für deine Hilfe
Hmmm... jetzt geht's nach einer kleinen Anpassung der Farbkonvertierung. Jetzt muss ich mal sehen was da mit meiner Funktion im argen ist. gruss |
AW: Surface Stream
Zitat:
Es wird nichts auf die platte geschaufelt. das Teil emuliert Ambilight und soll nachher in meiner Lib als Dummy Window arbeiten. PS: Man sollte schon einen bewegten Desktop haben.. Also Winamp starten Milkdrop im Desktop Modus verwenden und das Teil hier starten. Ob man da an der Auslastung noch was Kitzeln kann? gruss |
AW: Surface Stream
Das Problem mit deiner Funktion ist einfach, dass du das Bild als Windows-Bitmap speicherst, aber beim laden davon ausgehst, dass in der Datei die Rohdaten der Quell-Streams stehen. Tun sie aber nicht, da das Bitmap-Format zum einen einen eigenen Header (Meta-Daten vor den eigentlichen Bilddaten) in die Datei bringt, und zudem der Standard nicht alle Pixelformate vorsieht, die ein DX Surface haben könnte, weshalb da im schlimmsten Fall sogar noch konvertiert wird. Der Dateiinhalt hat nachher also potenziell kaum noch etwas mit den ursprünglichen Rohdaten im Surface-Buffer gemein.
Wenn du mittels eines Filestreams die Datei liest, und darin gerne genau die Rohdaten des Surfaces haben willst, musst du diese auch genau so in die Datei schreiben - nicht in ein Windows-Bitmap umgewandelt. Entsprechende Stream-Klassen gibt es in C#, und die arbeiten sehr ähnlich wie in Delphi. Da gibt es also einigen Wiedererkennungswert im Umgang. Praktischerweise ist das was SlimDX da liefert ja schon ein Stream :) Edit: Eventuell ließe sich die IPC hier am besten mit einer ![]() Edit2: Ich hatte es bis gerade so verstanden, dass du ein Surface aus einer C#-Anwendung in eine Delphi-Anwendung schaufeln willst. Ich glaube, da habe ich geirrt :stupid:. Vergiss in diesem Fall mein Edit einfach. Ich war von der Nutzung einer Datei für den Datenaustausch innerhalb ein und des selben Prozesses und dem ganzen geposteten C#-Code ggf. verwirrt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:05 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz