AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Surface Stream

Ein Thema von EWeiss · begonnen am 28. Dez 2013 · letzter Beitrag vom 30. Dez 2013
Antwort Antwort
EWeiss
(Gast)

n/a Beiträge
 
#1

AW: Surface Stream

  Alt 29. Dez 2013, 08:40
Danke

ich vermisse die Funktion DirectX GraphicsStream man mag es nicht glauben scheint aber unter Delphi nicht zu existieren.

Zitat:
Keine Ahnung, was bei dem originalen Read der zweite Parameter ist (vermutlich der Anfang im ZielArray), aber im Delphi ist es die Länge, was im Original ganz bestimmt der 3. Parameter war.
JO den ich eigentlich (was meine Lösung war) mit GraphicsStream auslesen wollte.

Zitat:
aber im Delphi ist es die Länge, was im Original ganz bestimmt der 3. Parameter war
gs.ReadBuffer(bu, sizeof(bu)); Aber alle meine Farben sind falsch.

Aber die gibt es wieder nicht.
Dann wäre auch das schreiben auf die Platte hinfällig gewesen.

Delphi-Quellcode:
gs: GraphicsStream; // <<< Direct3D9?? nix
gs.Read(bu, 0, sizeof(bu));
Jetzt kann ich beides nicht verwenden
DirectX > GraphicsStream (DataStream in SlimDX)


gruss

Geändert von EWeiss (29. Dez 2013 um 08:51 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#2

AW: Surface Stream

  Alt 29. Dez 2013, 14:08
Sind nur die Farben falsch? Also eigentlich schon das richtige Bild? Dann hat dein Surface vermutlich nicht das Format ABGR wie es für die GDI üblich ist. Gängig wäre noch ARGB, da würde einfach B und R tauschen genügen. Da DX aber ja eine ganze Fülle an Farbformaten unterstützt, kommt es darauf an, wie du dein Surface angelegt hast.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: Surface Stream

  Alt 29. Dez 2013, 17:33
Sind nur die Farben falsch? Also eigentlich schon das richtige Bild? Dann hat dein Surface vermutlich nicht das Format ABGR wie es für die GDI üblich ist. Gängig wäre noch ARGB, da würde einfach B und R tauschen genügen. Da DX aber ja eine ganze Fülle an Farbformaten unterstützt, kommt es darauf an, wie du dein Surface angelegt hast.
Das Bild ist einwandfrei wenn ich es abspeichere
Das Problem ist die Farben zu ermitteln.

TFileStream und TMemoryStream stellen nur zwei Parameter zur Verfügung.

Delphi-Quellcode:
function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
property Position: Int64 read GetPosition write SetPosition;
Ich benötige aber 3 zum lesen
Code:
int DataStream::Read( array<Byte>^ buffer, int offset, int count )
{
   return ReadRange<Byte>( buffer, offset, count );
}

generic<typename T> where T : value class
int DataStream::ReadRange( array<T>^ buffer, int offset, int count )
{
   if( !m_CanRead )
      throw gcnew NotSupportedException();
   
   Utilities::CheckArrayBounds( buffer, offset, count );

   //Truncate the count to the end of the stream
   Int64 elementSize = static_cast<Int64>( sizeof(T) );
   size_t actualCount = min( static_cast<size_t>((Length - m_Position) / elementSize), static_cast<size_t>( count ) );

   pin_ptr<T> pinnedBuffer = &buffer[offset];
   memcpy( pinnedBuffer, m_Buffer + m_Position, static_cast<size_t>( actualCount * elementSize ) );
   m_Position += actualCount * elementSize;
   return static_cast<int>( actualCount );
}
   
Int64 DataStream::Position::get()
{
  return m_Position;
}

void DataStream::Position::set( System::Int64 value )
{
  Seek( value, System::IO::SeekOrigin::Begin );
}
Der DataStream kann nur unter .NET SlimDX benutzt werden.
GraphicsStream gibt es unter Delphi nicht auch dieser hat 3 Parameter.

Deshalb habe ich auch mit Seek versucht auf die richtige Position zu kommen
aber ohne ansprechendes Ergebnis.

Zitat:
//Truncate the count to the end of the stream
Hmm Das macht mich etwas stutzig.
Wird hier der Stream von hinten gelesen?

Eine andere Variante mit "pos in posin"

Delphi-Quellcode:
function TCapX.GetColor(gs: TFileStream; List: TStrings): COLORREF;
var
  bu : Array[0..3] of byte;
  i, n: Integer;
  pos: Integer;
  posin: Array of Integer;
begin

  i := 0;
  r := 0;
  g := 0;
  b := 0;

  SetLength(posin, List.Count);
  for n := 0 to List.Count - 1 do
    posin[n] := StrToInt(List.Strings[n]);

  for pos in posin do
  begin
    gs.Position := pos; //StrToInt(List.Strings[pos]);
    gs.Read(bu, sizeof(bu));
    r := r + bu[2];
    g := g + bu[1];
    b := b + bu[0];
    inc(I);
  end;

  Result := ColorARGB(255, RGB(r div i , g div i , b div i));
  FillChar(posin, SizeOf(posin), 0);

end;
Macht aber keinen unterschied..
Ich glaube langsam das die Streams hier das Problem verursachen.
Normalerweise müsste das letzte Byte bu[3] immer 255 sein da es den AlphaChannel repräsentiert.
Ist es aber nicht.

gruss

Geändert von EWeiss (29. Dez 2013 um 18:20 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#4

AW: Surface Stream

  Alt 29. Dez 2013, 20:10
Um jetzt vielleicht die Read() versus ReadBuffer() Diskussion abzuschliesen:
Delphi-Quellcode:
// 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;
Wie man sieht, wird eine Exception geworfen wenn man mehr Bytes lesen möchte als der Stream liefern kann.
Das ist ein äusserst nützliches Sicherheitsfeature.
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 Read() oder Write() benützt ist man verpflichtet den Returnwert auszuwerten.
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!".


Bleibt vielleicht noch eine Frage offen:
Warum hat Borland die Funktionen Read() und Write() dann überhaupt public gemacht, protected hätte ja auch gereicht ?
Nun, neben dem häufig verwendeten TFileStream gibt es auch Streams, bei denen man nicht im Vorraus weiss oder erwartet wieviele Bytes denn noch vorhanden sind.
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.
fork me on Github
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

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

AW: Surface Stream

  Alt 29. Dez 2013, 20:40
Keine Ahnung, was du bisher hast, aber zum Auslesen der Bildinformationen kannst du IDirect3DSurface9::LockRect verwenden. Dann schreibst du den Wert aus LockedRect.Bits komplett in den Stream (Gröse = Surface.Width * Surface.Height * BytesPerPixel). Bei ARGB (oder jedem anderen "4 Byte per Pixel" Format) musst du den zum padden verwendeten Pitch Wert nicht beachten.

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;
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: Surface Stream

  Alt 29. Dez 2013, 20:55
Keine Ahnung, was du bisher hast, aber zum Auslesen der Bildinformationen kannst du IDirect3DSurface9::LockRect verwenden. Dann schreibst du den Wert aus LockedRect.Bits komplett in den Stream (Gröse = Surface.Width * Surface.Height * BytesPerPixel). Bei ARGB (oder jedem anderen "4 Byte per Pixel" Format) musst du den zum padden verwendeten Pitch Wert nicht beachten.

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;
Danke .. Hab ich alles schon

Ich speichere das Bitmap
D3DXSaveSurfaceToFileW('D:\paper.bmp', D3DXIFF_BMP, scrSurface, nil, @ARect);

lade es zurück.. in den Stream
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:
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;
IDirect3DSurface9::LockRect brauche ich nicht da die Daten über D3DXSaveSurfaceToFileW abgespeichert werden.
Aber auch damit habe ich es versucht.
Delphi-Quellcode:
  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;
Und dann das BMP in eine Datei geschrieben.
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

Geändert von EWeiss (29. Dez 2013 um 21:03 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

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

AW: Surface Stream

  Alt 29. Dez 2013, 21:01
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.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

AW: Surface Stream

  Alt 29. Dez 2013, 21:04
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.
Danke..

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:
dass sämtliche Pixelinformationen verschoben werden.
Davon muss ich mittlerweile ausgehen denn ansonsten müßten die Daten ja stimmen
da mein Bitmap ansich richtig dargestellt wird.


gruss
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:11 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