AGB  ·  Datenschutz  ·  Impressum  







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

Memorystream vs TMemoryStream

Ein Thema von EWeiss · begonnen am 16. Apr 2015 · letzter Beitrag vom 18. Apr 2015
Antwort Antwort
EWeiss
(Gast)

n/a Beiträge
 
#1

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 08:14
Danke für deine Ausführung.. Werde das mal in ruhe durchgehen.
Hier nur noch als Info wie das im eigenen Sample von Delphi gehandhabt wird.
Auf der Basis wollte ich das auch machen (was aber nun mal nicht geht mit den Streams in .NET)

Delphi-Quellcode:
procedure TForm1.Button5Click(Sender: TObject);
var
    PictureStream: TMemoryStream;
    Description: String;
    MIMEType: String;
    JPEGPicture: TJPEGImage;
    PNGPicture: TPNGImage;
    GIFPicture: TGIFImage;
    BMPPicture: TBitmap;
    Width, Height: Integer;
    NoOfColors: Integer;
    ColorDepth: Integer;
    PictureMagic: Word;
    CoverArtPictureFormat: TTagPictureFormat;
    CoverArtData: TCoverArtData;
begin
    if NOT OpenDialog1.Execute then begin
        Exit;
    end;
    //* Clear the cover art data
    MIMEType := '';
    Description := '';
    Width := 0;
    Height := 0;
    ColorDepth := 0;
    NoOfColors := 0;
    CoverArtPictureFormat := TTagPictureFormat.tpfUnknown;
    if FileExists(OpenDialog1.FileName) then begin
        try
            PictureStream := TMemoryStream.Create;
            try
                PictureStream.LoadFromFile(OpenDialog1.FileName);
                PictureStream.Seek(0, soBeginning);
                Description := ExtractFileName(OpenDialog1.FileName);
                PictureStream.Read(PictureMagic, 2);
                PictureStream.Seek(0, soBeginning);
                if PictureMagic = MAGIC_JPG then begin
                    MIMEType := 'image/jpeg';
                    CoverArtPictureFormat := tpfJPEG;
                    JPEGPicture := TJPEGImage.Create;
                    try
                        JPEGPicture.LoadFromStream(PictureStream);
                        Width := JPEGPicture.Width;
                        Height := JPEGPicture.Height;
                        NoOfColors := 0;
                        ColorDepth := 24;
                    finally
                        FreeAndNil(JPEGPicture);
                    end;
                end;
                if PictureMagic = MAGIC_PNG then begin
                    MIMEType := 'image/png';
                    CoverArtPictureFormat := tpfPNG;
                    PNGPicture := TPNGImage.Create;
                    try
                        PNGPicture.LoadFromStream(PictureStream);
                        Width := PNGPicture.Width;
                        Height := PNGPicture.Height;
                        NoOfColors := 0;
                        ColorDepth := PNGPicture.PixelInformation.Header.BitDepth;
                    finally
                        FreeAndNil(PNGPicture);
                    end;
                end;
                if PictureMagic = MAGIC_GIF then begin
                    MIMEType := 'image/gif';
                    CoverArtPictureFormat := tpfGIF;
                    GIFPicture := TGIFImage.Create;
                    try
                        GIFPicture.LoadFromStream(PictureStream);
                        Width := GIFPicture.Width;
                        Height := GIFPicture.Height;
                        NoOfColors := 0; //GIFPicture.ColorResolution
                        ColorDepth := GIFPicture.BitsPerPixel;
                    finally
                        FreeAndNil(GIFPicture);
                    end;
                end;
                if PictureMagic = MAGIC_BMP then begin
                    MIMEType := 'image/bmp';
                    CoverArtPictureFormat := tpfBMP;
                    BMPPicture := TBitmap.Create;
                    try
                        BMPPicture.LoadFromStream(PictureStream);
                        Width := BMPPicture.Width;
                        Height := BMPPicture.Height;
                        NoOfColors := 0;
                        case BMPPicture.PixelFormat of
                            pfDevice: ColorDepth := 32;
                            pf1bit: ColorDepth := 1;
                            pf4bit: ColorDepth := 4;
                            pf8bit: ColorDepth := 8;
                            pf15bit: ColorDepth := 15;
                            pf16bit: ColorDepth := 16;
                            pf24bit: ColorDepth := 24;
                            pf32bit: ColorDepth := 32;
                            pfCustom: ColorDepth := 32;
                        end;
                    finally
                        FreeAndNil(BMPPicture);
                    end;
                end;
                PictureStream.Seek(0, soBeginning);
                //* Add the cover art
                CoverArtData.Name := PwideChar(Description);
                CoverArtData.CoverType := 3; //* ID3v2 cover type (3: front cover)
                CoverArtData.MIMEType := PwideChar(MIMEType);
                CoverArtData.Description := PwideChar(Description);
                CoverArtData.Width := Width;
                CoverArtData.Height := Height;
                CoverArtData.ColorDepth := ColorDepth;
                CoverArtData.NoOfColors := NoOfColors;
                CoverArtData.PictureFormat := CoverArtPictureFormat;
                CoverArtData.Data := PictureStream.Memory;
                CoverArtData.DataSize := PictureStream.Size;
                if TagsLibrary_AddCoverArt(Tags, ttAutomatic, CoverArtData) = - 1 then begin
                    MessageDlg('Error while adding cover art: ' + SaveDialog1.FileName, mtError, [mbCancel], 0);
                end;
            finally
                FreeAndNil(PictureStream);
            end;
        except
            MessageDlg('Error while adding cover art: ' + SaveDialog1.FileName, mtError, [mbCancel], 0);
        end;
    end;
    //* Display added cover art
    ListCoverArts;
end;
Von Delphi zu Delphi sollte das kein Problem sein.
Während das im .NET schon anders aussieht.

gruss
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#2

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 09:17
Hab es jetzt mal so versucht direkt die Image Daten zu übergeben.
hab noch keinen UnmanagedMemoryStream erzeugt.

Die Delphi Seite mag das anscheinend nicht.

Code:
IntPtr pval = IntPtr.Zero;

var BitmapStream = new MemoryStream();

using (var fs = System.IO.File.Open(OpenFileDialog1.FileName, System.IO.FileMode.Open))
{
  fs.CopyTo(BitmapStream);
  BitmapStream.Position = 0;

  Bitmap bmp = (Bitmap)Bitmap.FromStream(BitmapStream);

  System.Drawing.Imaging.BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
    ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
  try
  {
    pval = bd.Scan0;
  }
  finally
  {
    bmp.UnlockBits(bd);
  }
  //....
  CoverArtData.Data = pval;

  if (TagsLib.TagsLibrary_AddCoverArt(Tags, TTagType.ttAutomatic, CoverArtData) != 0)
  {
    MessageBox.Show("Error while adding cover art: ", OpenFileDialog1.FileName, MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
  }
Zitat:
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
wenn es langsam nicht hinhaut muss er selbst sehen wie er das macht.

gruss

Geändert von EWeiss (17. Apr 2015 um 09:24 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 10:18
Der Müll kommt bei ihm an.
Deshalb kracht es.

Kann mir da jemand helfen ?
Bei bedarf häng ich das Projekt mal an.

gruss

Geändert von EWeiss (11. Jul 2019 um 15:43 Uhr)
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.395 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 11:09
warum eigentlich nicht "einfach" MemoryMappedFiles verwenden?
https://msdn.microsoft.com/de-de/lib...vs.110%29.aspx

sind doch genau dafür da.. Gut bisher habe ich da auch "nur" Daten zwischen Delphi-Prozessen ausgetauscht, aber damit sollte das doch problemlos auch nach .net gehen solange die komplette Bilddatei dort abgelegt wird...
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 11:19
warum eigentlich nicht "einfach" MemoryMappedFiles verwenden?
https://msdn.microsoft.com/de-de/lib...vs.110%29.aspx

sind doch genau dafür da.. Gut bisher habe ich da auch "nur" Daten zwischen Delphi-Prozessen ausgetauscht, aber damit sollte das doch problemlos auch nach .net gehen solange die komplette Bilddatei dort abgelegt wird...
Danke.
Es geht nicht alleine nur um die Bitmap die ich an CoverArtData.Data übergeben muss
sondern um die struct TCoverArtData.

So wie im Bild ersichtlich kommt auf der Delphi Seite nur Müll an.
Bin wohl damit überfordert

gruss
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.395 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 11:35
So wie im Bild ersichtlich kommt auf der Delphi Seite nur Müll an.
Bin wohl damit überfordert
ist doch logisch.. das Objektmodell von Delphi entspricht halt nicht dem von .NET. Jemand der sich damit auskennt kann dir das erklären wo die Unterschiede in der Speicherverwaltung von Delphi und .net liegen (wo sind virtuelle Methoden definiert, wo die Eigenschaften....) wenn das nicht zusammen passt, dann kann bei der Interpretation auch nur Müll raus kommen.

Lösung:
Das Objekt/Record in eine XML-Datei speichern, das Bitmap dazu (mime), ggf. zippen und die komplette XML dann ins MMF. Das kannst Du dann mit jeder bel. Programmiersprache auswerten, die MMF unterstützt...

Nachtrag: Die Größe des MMF kannst Du dann per Windows-Message "herum reichen" auf die dann das andere Programm reagieren kann - das weiß dann ab wann die Infos komplett bereit stehen und auch wie groß die MMF ist in der die Daten stehen...


Grüße
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 11:47
So wie im Bild ersichtlich kommt auf der Delphi Seite nur Müll an.
Bin wohl damit überfordert
ist doch logisch.. das Objektmodell von Delphi entspricht halt nicht dem von .NET. Jemand der sich damit auskennt kann dir das erklären wo die Unterschiede in der Speicherverwaltung von Delphi und .net liegen (wo sind virtuelle Methoden definiert, wo die Eigenschaften....) wenn das nicht zusammen passt, dann kann bei der Interpretation auch nur Müll raus kommen.

Lösung:
Das Objekt/Record in eine XML-Datei speichern, das Bitmap dazu (mime), ggf. zippen und die komplette XML dann ins MMF. Das kannst Du dann mit jeder bel. Programmiersprache auswerten, die MMF unterstützt...

Nachtrag: Die Größe des MMF kannst Du dann per Windows-Message "herum reichen" auf die dann das andere Programm reagieren kann - das weiß dann ab wann die Infos komplett bereit stehen und auch wie groß die MMF ist in der die Daten stehen...


Grüße
Das macht keinen Sinn sorry.
Ich habe selbst eine DLL in Delphi geschrieben und einen Wrapper dazu.
Bei mir ist es nur so das ich weis welche Dateien bzw. DataTypen in Delphi deklariert werden müssen
damit eine Zusammenarbeit beider Sprachen ohne große Probleme funktioniert.

Aber wie gesagt darauf habe ich kleinen Einfluss was oder wie er seine Daten verwaltet/übergibt.
Zudem macht es absolut keinen sinn irgendetwas in ZIP Dateien zu packen denn ich lese den TAG einer X-Beliebigen MP3 Datei aus
und die Bilddatei ist im Tag enthalten.
Soll ich das dann zippen ?

gruss

Geändert von EWeiss (17. Apr 2015 um 11:52 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.643 Beiträge
 
#8

AW: Memorystream vs TMemoryStream

  Alt 17. Apr 2015, 11:45
Uh. Es ist nahezu ein Ding der Unmöglichkeit, ein Struct in .NET so zu layouten, das die Datenstruktur so aussieht, wie sie bei Delphi aussieht.

Insbesondere, wenn Du hier Strings (die sind komplett inkompatibel, weil die in .NET immer immutable Objekte sind) und eben größere Binärdaten hin- und herschieben willst.

Nur ein Beispiel: In .NET ist ein String ein Objekt, und die Daten werden geshared. Will heissen, wenn Du 15 Strings hast, und 13 davon identischen Inhalt haben, hast Du im Endeffekt 15 Objekte (also eine Komplexe Datenstruktur), und 13 davon haben intern irgendwo einen Pointer auf den selben Datenbereich mit dem Inhalt des Strings und 2 zeigen woanders hin. Wenn Du den Inhalt eines der 13 Strings jetzt änderst, dann wird geschaut, ob es den Inhalt schonmal gibt, wenn ja, wird einfach nur der Pointer verbogen, wenn nein, wird der Inhalt halt irgendwo neu angelegt und dann der Zeiger darauf hin verbogen. Das .NET Managed ist, bekommst Du ohne ganz hartes natives Debugging auch nicht raus, an welcher Speicherstelle der String jetzt eigentlich wirklich liegt.

Das, was Du machen willst, involviert sehr viel unsafe Code.

Ich würde ernsthaft vorschlagen, die Herangehensweise zu überdenken. Es wäre besser, die ganze Funktionalität in einer komplett nativen Delphi-DLL zu verpacken, nur die Methoden zu exposen, und ausschliesslich primitive Datentypen zwischendrin auszutauschen. Oder, Du nimmst sowas wie Hydra, das Dir dann wirklich erlaubt komplette Interfaces zwischen .NET und Delphi hin- und her zu schieben, und das ganze Plugin-Framework kümmert sich für Dich dann um das ganze richtige Konvertieren etc.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  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 20:49 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