Загрузка изображения из строки - PullRequest
2 голосов
/ 18 мая 2011

Из-за некоторых ограничений хранилища данных (noSQL) мне нужно хранить изображения в виде строк. Как я могу сериализовать растровое изображение в строку и обратно. Вот как я это делаю:


Uri testImageUri = new Uri("/DictionaryBasedVM;component/test.jpg", UriKind.Relative);
StreamResourceInfo sri = Application.GetResourceStream(testImageUri);            
var stringData = GetString(sri.Stream);
ImageSource = stringData;           

Где

ImageControl
- просто элемент управления изображением silverlight, определенный в xaml.
Я использую следующие служебные функции:

        //For testing 
        public static string GetString(Stream stream)
        {
            byte[] byteArray = ReadFully(stream);   
            return Encoding.Unicode.GetString(byteArray,0,byteArray.Length);
        }
        public static byte[] ReadFully(Stream input)
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }

И следующее свойство:


        private string _ImageSource = "";
        public string ImageSource
        {
            set
            {
                _ImageSource = value;
                byte[] byteArray = Encoding.Unicode.GetBytes(value);
                MemoryStream imageStream = new MemoryStream(byteArray);
                BitmapImage imageSource = new BitmapImage();
                imageSource.SetSource(imageStream);
                ImageControl.Source = imageSource;
            }
            get
            {
                return _ImageSource;
            }
        }

Я получаю сообщение об ошибке: «Катастрофический сбой (Исключение из HRESULT: 0x8000FFFF (E_UNEXPECTED)))» как показано enter image description here

Даже если я не храню это как строку, мне все равно любопытно, почему я не могу этого сделать.

Ответы [ 3 ]

2 голосов
/ 18 мая 2011

Unicode, вероятно, не самая лучшая кодировка для этой цели. Вам лучше использовать Base64 с кодировкой byte[] и ее хранением.

1 голос
/ 18 мая 2011

Base64 добавит 30% размера к строке. Я не думаю, что это необходимо здесь. Вы можете безопасно «приводить» байты к символам и наоборот для этой конкретной двоичной потребности, если вы ничего не делаете со строкой. Вот код, который, кажется, работает:

    // usage example
    string encoded = FileToString("myimage.png");
    Console.WriteLine(s.Length);
    FileFromString(encoded, "copy.png");

    public static void FileFromString(string input, string filePath)
    {
        if (input == null)
            throw new ArgumentNullException("input");

        if (filePath == null)
            throw new ArgumentNullException("filePath");

        using (FileStream stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
        {
            byte[] buffer = FromString(input);
            stream.Write(buffer, 0, buffer.Length);
        }
    }

    public static byte[] FromString(string input)
    {
        if (input == null)
            throw new ArgumentNullException("input");

        char[] cbuffer = input.ToCharArray();
        byte[] buffer = new byte[cbuffer.Length];
        for (int i = 0; i < buffer.Length; i++)
        {
            buffer[i] = (byte)cbuffer[i];
        }
        return buffer;
    }

    public static string FileToString(string filePath)
    {
        if (filePath == null)
            throw new ArgumentNullException("filePath");

        using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Write))
        {
            return ToString(stream);
        }
    }

    public static string ToString(Stream input)
    {
        if (input == null)
            throw new ArgumentNullException("input");

        StringBuilder sb = new StringBuilder();
        byte[] buffer = new byte[4096];
        char[] cbuffer = new char[4096];
        int read;
        do
        {
            read = input.Read(buffer, 0, buffer.Length);
            for (int i = 0; i < read; i++)
            {
                cbuffer[i] = (char)buffer[i];
            }
            sb.Append(new string(cbuffer, 0, read));
        }
        while (read > 0);
        return sb.ToString();
    }

Однако, возможно, системе, в которой вы храните строки, могут не нравиться строки, содержащие 0 или другие специальные числа. В этом случае base64 все еще является опцией.

1 голос
/ 18 мая 2011

Вы пытались использовать методы Convert.ToBase64String и Convert.FromBase64String ?Я предполагаю, что Unicode GetString / GetBytes не работает, так как ваши байтовые массивы не совпадают с «известными символами».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...