Laden...

Jpeg in String wandeln und zurück

Erstellt von Taladan vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.710 Views
Taladan Themenstarter:in
582 Beiträge seit 2008
vor 12 Jahren
Jpeg in String wandeln und zurück

Hallo, versuche jetzt schon seit geraumer Zeit, ein Bitmap (JPEG) in einen String zu wandeln und dann auch wieder zurück zu wandeln. Ziel soll es sein, den String in einem XML-Dokument mit ab zu speichern und über Socket auf das WP7 zu übertragen. Auf den WP7 soll der String wieder in ein Image zurück gewandelt werden, so das ich dieses dort anzeigen kann.

Aber ich habe irgendwo einen Verlust von Daten ab //Save. Und zwar wird das Bitmap wohl auf irgend eine Ecke (vermutlich oben links) ausgerichtet und nur ein paar Pixel in beide Richtungen verwendet.

Was mache ich hier falsch?

Wie kann ich ein JPG in einen String umwandeln und mit in einem XML Dokument speichern?

// screenshot from frameworkelement
            RenderTargetBitmap rtb = QuestionRichTextEditor.GetDocumentAsImage();

            MemoryStream stream = new MemoryStream();
             //Save
            JpegBitmapEncoder encoder;
            encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(rtb));
            encoder.QualityLevel = 70;
            encoder.Save(stream);
            stream.Flush();
            stream.Position = 0;
            BitmapImage imageSource = new BitmapImage();
            imageSource.BeginInit();
            imageSource.StreamSource = stream;
            imageSource.EndInit();
            stream.Position = 0;
            this.TestImage.Source = imageSource;

            App.Model.SelectedMemoCard.QuestionImageString = ByteArrayToString(stream);

Gruß dat Tala

C
2.121 Beiträge seit 2010
vor 12 Jahren

Die Magie deiner Vorgehensweise liegt in ByteArrayToString und die zeigst du bisher ja nicht.
stream ist übrigens kein ByteArray, vielleicht liegts schon mal daran?

771 Beiträge seit 2009
vor 12 Jahren

Hi,

wie sieht denn die ByteArrayToString()-Methode aus?
Die übliche Vorgehensweise zum Abspeichern von Binärdaten als String ist das Base64-Format, d.h. mittels der Convert.ToBase64String()-Methode (und zurück mit Convert.FromBase64String()).

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 12 Jahren

Ich lasse mir das Image hier ausgeben
this.TestImage.Source = imageSource;
und schon hier das Problem, das das Image "viel zu klein ist".

Ist nicht viel Magie drin, alles nur Code...



private string ByteArrayToString(MemoryStream ms)
        {
            ms.Seek(0, SeekOrigin.Begin);
            byte[] jsonBytes = new byte[ms.Length];
            ms.Read(jsonBytes, 0, (int)ms.Length);
            return Encoding.Default.GetString(jsonBytes);
        }

Gruß dat Tala

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 12 Jahren

Hier ein mein Problem mit dem Images. Die untere Reihe ist links das was ich aus

QuestionRichTextEditor.GetDocumentAsImage();

heraus bekomme. So weit annehmbar (auch wenn ich der Rahmen stört).

Und rechts dann das was als imageSource heraus kommt. Nicht gerade das, was hinein gepackt wurde 😦.

Gruß dat Tala

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

das Umwandeln von Binärdaten in Strings kann nur schiefgehen wenn man nicht gerade Methoden wie von Cat vorgeschlagen, verwendet. Der Grund liegt einfach daran, dass nicht alle Binärdaten in dem Encoding als Zeichen ausgedrückt werden können. Und sobald die erste Bitfolge im Bild kommt wo nicht als Zeichen dargestellt werden kann, schlägt die Umwandlung fehl.

Wenn du Sockets verwendest, kannst du es doch gleich als Binärdaten schicken, warum umwandeln in den String?

Baka wa shinanakya naoranai.

Mein XING Profil.

P
157 Beiträge seit 2010
vor 12 Jahren

Es ist gut möglich, dass du ein 0-Zeichen umwandelst, also das byte 0 ist. Dann wird beim Umwandeln daraus ein '\0', welches für das ende des Strings steht, weshalb Daten verloren gehen.

C
2.121 Beiträge seit 2010
vor 12 Jahren

Man könnt HEX draus machen, oder noch besser Base64.
Dann kann man es in XML verpacken. Da die Umwandlung nach String überhaupt erfolgen sollte, bin ich davon ausgegangen dass auch ein Format mit ausschließlich lesbaren Zeichen verwendet wird.

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 12 Jahren

@talla.

Also, ich möchte gerne beim erstellen einer Memocard (mein gespeichertes Object) ein Screenshot von dem optischen Objekt machen, was ganz gut funktioniert. Dieses Objekt soll dann aber mit der Memocard zusammen gespeichert werden. Problem ist, das bereits 3000 und mehr davon exisiterien, daher bin ich auf einfache Datentypen wie string angewiesen, da es hier bei einem Serialize und Deserialize zu keinen Fehler kommt. Zudem die beiden Images, die erzeugt werden, mit in die gleiche Datei wie die Memocard soll.

Daher muß ich wohl oder übel, das image was mir als Byte[] vor liegt, in einen String umwandeln und umgekehrt. Es sei denn ihr habt eine bessere Idee. Der Versuch, das ganze in einem Byte64 zu wandeln schlug komplett fehl, da hier bei der Deserialisierung nur noch eine lange Reihe von "AA" raus kam. 😦.

Bevor wer fragt, was aus der funktion GetJpgImage heraus kommt, funktioniert auch.



private void Test()
{
 byte[] screenshot = QuestionRichTextEditor.GetJpgImage(1, 90);
            MemoryStream stream = new MemoryStream(screenshot);
            stream.Flush();
            stream.Position = 0;

            App.Model.SelectedMemoCard.QuestionImageString = EncodeTo64(stream);

            byte[] screenshot2 = DecodeFrom64(App.Model.SelectedMemoCard.QuestionImageString); 
            MemoryStream stream2 = new MemoryStream(screenshot2);
            stream2.Flush();
            stream2.Position = 0;

            BitmapImage imageSource = new BitmapImage();
            imageSource.BeginInit();
            imageSource.StreamSource = stream2;
            imageSource.EndInit();

            this.TestImage.Source = imageSource;
}


static public byte[] DecodeFrom64(string b64)
        {
            byte[] encodedDataAsBytes = System.Convert.FromBase64String(b64);
            return encodedDataAsBytes;
        }

        static public string EncodeTo64(MemoryStream ms)
        {
            ms.Seek(0, SeekOrigin.Begin);
            byte[] toEncodeAsBytes = new byte[ms.Length];
            string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
            return returnValue;
        }

Gruß dat Tala

6.862 Beiträge seit 2003
vor 12 Jahren

Problem ist, das bereits 3000 und mehr davon exisiterien, daher bin ich auf einfache Datentypen wie string angewiesen, da es hier bei einem Serialize und Deserialize zu keinen Fehler kommt.

Von was für einem Fehler sprichst du?

Baka wa shinanakya naoranai.

Mein XING Profil.

771 Beiträge seit 2009
vor 12 Jahren

Hi Taladan,

dir scheinen noch einige Grundlagen zu fehlen. Deine Methode EncodeTo64 liest ja gar nicht aus dem Stream, sondern erstellt nur ein leeres byte-Array (und dann ist ja klar, dass da nur "Müll" rauskommt).
Es fehlt also noch


ms.Read(toEncodeAsBytes, 0, ms.Length);

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 12 Jahren

Hab die lösung des Problems gefunden. Ich kann ja auch direkt das ByteArray verwenden und muss es nicht erst in einen Memorystream umwandeln.

@Talla: Das Problem welches ein automatisch generierter XMLSerializer hat, wenn ein neues Object hinzu kommt, aber dieses in der XML-Datei nicht vorfindet.

Gruß dat Tala

C
2.121 Beiträge seit 2010
vor 12 Jahren

@Talla: Das Problem welches ein automatisch generierter XMLSerializer hat, wenn ein neues Object hinzu kommt, aber dieses in der XML-Datei nicht vorfindet.

Deswegen mache ich mit meine Serialisierung und Deserialisierung gern selber, statt mich auf was automatisch generiertes zu verlassen. Da hab ich selber in der Hand was passiert.