简体   繁体   中英

Cannot read a Bitmap image that I just saved in Base64

I try to load a picture (PNG), save-it in Base64 in a text file and reload it, but I only see gliberish pictures (black and white, very ugly, far from original!) after I load the picture from the text file. Where's my problem?

BTW all examples (load the picture from image file, save to base64, load from base64) are all taken from SO questions.

First it's how a load the pictures from the PNG file:

try
        {
            var openFileDialog = new OpenFileDialog
                                     {
                                         CheckFileExists = true,
                                         Multiselect = false,
                                         DefaultExt = "png",
                                         InitialDirectory =
                                             Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
                                     };
            if (openFileDialog.ShowDialog() == true)
            {
                Bitmap img;
                using (var stream = File.Open(openFileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    img = new Bitmap(stream);
                }
                Logo.Source = BitmapToImageSource(img);
            }
        }
        catch (Exception exception)
        {
            MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
        }

Save it to base64:

try
        {
            Bitmap img = BitmapSourceToBitmap2((BitmapSource) Logo.Source);

            string base64String;

            using (var stream = new MemoryStream())
            {
                img.Save(stream, ImageFormat.Png);
                byte[] imageBytes = stream.ToArray();
                base64String = Convert.ToBase64String(imageBytes);
            }

            string fileName = string.Format(CultureInfo.InvariantCulture, "image{0:yyyyMMddHHmmss}.txt",
                                            DateTime.Now);
            string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);

            using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None))
            {
                using (var writer = new StreamWriter(stream, System.Text.Encoding.UTF8))
                {
                    writer.Write(base64String);
                    writer.Flush();
                }
            }
        }
        catch (Exception exception)
        {
            MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
        }

BitmapSourceToBitmap2:

int width = srs.PixelWidth;
        int height = srs.PixelHeight;
        int stride = width*((srs.Format.BitsPerPixel + 7)/8);
        IntPtr ptr = IntPtr.Zero;
        try
        {
            ptr = Marshal.AllocHGlobal(height*stride);
            srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height*stride, stride);
            using (var btm = new Bitmap(width, height, stride, PixelFormat.Format1bppIndexed, ptr))
            {
                // Clone the bitmap so that we can dispose it and
                // release the unmanaged memory at ptr
                return new Bitmap(btm);
            }
        }
        finally
        {
            if (ptr != IntPtr.Zero)
                Marshal.FreeHGlobal(ptr);
        }

And load it back from the file:

try
        {
            var openFileDialog = new OpenFileDialog
                                     {
                                         CheckFileExists = true,
                                         Multiselect = false,
                                         DefaultExt = "txt",
                                         InitialDirectory =
                                             Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
                                     };
            if (openFileDialog.ShowDialog() == true)
            {
                string base64String;
                using (FileStream stream = File.Open(openFileDialog.FileName, FileMode.Open))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        base64String = reader.ReadToEnd();
                    }
                }

                byte[] binaryData = Convert.FromBase64String(base64String);

                var bi = new BitmapImage();

                bi.BeginInit();
                bi.StreamSource = new MemoryStream(binaryData);
                bi.EndInit();

                Logo.Source = bi;
            }
        }
        catch (Exception exception)
        {
            MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
        }

Here is a short code sequence that reads a JPG file into a byte array, creates a BitmapSource from it, then encodes it into a base64 string and writes that to file.

In a second step, the base64 string is read back from the file, decoded and a second BitmapSource is created.

The sample assumes that there is some XAML with two Image elements named image1 and image2 .

Step 1:

var imageFile = @"C:\Users\Clemens\Pictures\DSC06449.JPG";
var buffer = File.ReadAllBytes(imageFile);

using (var stream = new MemoryStream(buffer))
{
    image1.Source = BitmapFrame.Create(
        stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}

var base64File = @"C:\Users\Clemens\Pictures\DSC06449.b64";
var base64String = System.Convert.ToBase64String(buffer);

File.WriteAllText(base64File, base64String);

Step 2:

base64String = File.ReadAllText(base64File);
buffer = System.Convert.FromBase64String(base64String);

using (var stream = new MemoryStream(buffer))
{
    image2.Source = BitmapFrame.Create(
        stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}

In case you need to encode an already existing BitmapSource into a byte array, use code like this:

var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));

using (var stream = new MemoryStream())
{
    encoder.Save(stream);
    buffer = stream.ToArray();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM