2016-02-27 1 views
0

J'ai une classe avec une image qui doit être (parfois) sérialisée/désérialisée en fonction du fait que l'image est incorporée ou non.Sérialisation/sérialisation Datacontract avec images

[DataContract(IsReference = true)] 
public class Data 
{ 
    [DataContract(IsReference = true)] 
    public class MyImage 
    { 

    [DataMember] 
    int WidthStorage 
    [DataMember] 
    int HeightStorage; 

    [DataMember] 
    public string strImageLocation; 
    [DataMember] 
    public Image ImageEmbedded = new Image();<----- not working null 
    public bool GetImage(Image image, int width, int height) 
    { 
    ... 
    } 

    public void SetImageFSlocation(string _strImageLocation, int _widthStorage, int _heightStorage) 
    { 
    ...   
    } 

    public void SetImageEmbedded(string strPathFilename, int _widthStorage, int _heightStorage) 
    { 
    ... 
    } 

} 

Le problème est que, malgré la mise

public Image ImageEmbedded = new Image(); 

ImageEmbedded est toujours nulle. Je l'ai mis dans un constructeur comme

[DataContract(IsReference = true)] 
    public class MyImage 
    { 
    public MyImage() 
    { 
     ImageEmbedded = new Image(); 
    } 
    ... 

mais quand je fais ce que je reçois une erreur de sérialisation. Alors qu'est-ce que je dois faire? Je ne mettrais pas l'image en byte [] ou autre. J'ai choisi la sérialisation de Datacontract car je pensais que cela pourrait sérouiller les images. Merci

+0

Où est-il dire que DataContractSerializer peut sérialiser une image? –

+0

Alors, quel est l'avantage d'un sérialiseur de datacontract ??? – Luca

+0

Avantage sur quoi? –

Répondre

1

Il y a un problème majeur dans votre code: en WPF Si vous sérialisez une image, vous sérialiserez System.Windows.Controls.Image. Bref, cela n'a aucun sens de sérialiser un contrôle. Au lieu de cela, vous voudrez peut-être sérialiser un BitmapSource mais ici encore, ceux-ci ne peuvent pas être sérialisés, vous devez donc les tourner à byte[] comme déjà dit.

[DataMember] 
public byte[] bytesBitmapEmbedded; 

puis simplement changer à BitmapSource ou octet [] à ceci:

bytesBitmapEmbedded = Converter.BitmapSource2ByteArray(bitmapSource); 

ou

bitmapSource = Converter.ByteArray2BitmapSource(bytesBitmapEmbedded); 

avec

public static class Converter 
{ 
    public static byte[] BitmapSource2ByteArray(BitmapSource bitmap) 
    { 
     using (var stream = new MemoryStream()) 
     { 
      var encoder = new PngBitmapEncoder(); 
      encoder.Frames.Add(BitmapFrame.Create(bitmap)); 
      encoder.Save(stream); 
      return stream.ToArray(); 
     } 
    } 

    public static BitmapSource ByteArray2BitmapSource(byte[] buffer) 
    { 
     using (var stream = new MemoryStream(buffer)) 
     { 
      return BitmapFrame.Create(stream, 
       BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 
     } 
    } 
} 
+0

qui fonctionne merci !! Mais s'il vous plaît après la sérialisation/désérialisation, je perds la transparence de l'arrière-plan. – Luca

+1

Très facile: au lieu d'utiliser un BmpBitmapEncoder, utilisez un PngBitmapEncoder – Patrick

0

Si votre sérialiseur ne sait pas directement comment convertir le type d'un champ, alors vous allez vous battre contre le vent. La solution la plus facile est de revenir à des types plus primitifs qui sont dans la plupart des langues; créez un Data-Transfer Object. Par exemple, je stocke une quantité assez diversifiée de 1- 2 dimensions données avec protobuf.net en utilisant quelque chose de similaire à ce (modifié pour vos besoins):

[DataContract] 
class ImageDTO 
{ 
    [DataMember(Order = 1)] 
    public int Width { get; set; } 

    [DataMember(Order = 2)] 
    public int Height { get; set; } 

    [DataMember(Order = 3)] 
    public ImageFormat Format { get; set; } 

    [DataMember(Order = 4)] 
    public byte[] Data { get; set; } 

    [DataMember(Order = 5)] 
    public string AltUrl { get; set; } 
} 

Donc, dans votre cas, vous devez simplement traiter le format d'image enum code et obtenir les données binaires d'une image. Voir Fastest way to convert Image to Byte array OU WPF Image to byte[] OU https://github.com/teichgraf/WriteableBitmapEx/

alors vous pouvez simplement jeter une instance de ce ImageDTO à peu près la plupart des sérialiseur/désérialiseur à base de contrat. Par exemple, si vous choisissez des tampons de protocole, dans la terre .net vous pouvez serialise avec protobuf.net, alors que dans javascript terre, vous pouvez deserialise avec protobuf.js étant donné la .proto

message ImageDTO { 
    optional int32 Width = 1 [default = 0]; 
    optional int32 Height = 2 [default = 0]; 
    optional ImageFormat Format = 3 [default = RGB]; 
    optional bytes Data = 4; 
    optional string AltUrl = 5; 
} 
enum ImageFormat { 
    RGB = 0; 
    RGBA = 1; 
    PNG = 2; 
    JPEG = 3; 
} 
+0

Merci donc si je ne me trompe pas protobuf.net est un type différent de sérialisation de contrat de données? Si oui, je voudrais m'en tenir au contrat de données standard. En tout cas j'essaie de changer Image -> byte []. Et puis essayé le "moyen le plus rapide pour convertir l'image en tableau Byte" lien. Mais ce n'est pas pour WPF! – Luca

+0

J'ai ajouté plus de liens qui posent cette question WPF images> octets. Vous trouverez probablement que WriteableBitmapEx aura aussi des méthodes d'accès pour vous aider. 'protobuf.net' est un sérialiseur de contrat (qui peut utiliser les attributs de DataContract), mais il est sérialisé au format binaire de tampon de protocole. –