【问题标题】:C# - Base64 byte array to Image FAILS no matter what I tryC# - 无论我尝试什么,Base64 字节数组都会导致图像失败
【发布时间】:2012-07-26 21:43:23
【问题描述】:

我在 C# 中从 base64 编码的字节数组创建图像/位图对象时遇到问题。

这是我正在处理的问题:


我有一个用户可以裁剪图像的前端。当用户通过input[type=file] 选择图像时,我的 javascript 代码使用 HTML5 的 FileReader 将DataUrl(base64 字符串)保存到hidden field,与裁剪坐标和尺寸以及其中的所有其他内容一起发布form.

本质:

base64 数据,如果你想自己测试:

http://kristianbak.com/test_image.txt

  1. base64 字符串发布到操作,并作为参数imageData 接收
  2. 该操作将字符串转换为 base64 字节数组,如下所示:
  3. byte[] imageBytes = Convert.FromBase64String(imageData.EncodeTo64());

EncodeTo64 扩展方法:

public static string EncodeTo64(this String toEncode)
{
    var toEncodeAsBytes = Encoding.ASCII.GetBytes(toEncode);
    var returnValue = Convert.ToBase64String(toEncodeAsBytes);
    return returnValue;
}

base64 字符串转换为字节数组后,我使用MemoryStream 将字节读入内存:

using (var imageStream = new MemoryStream(imageBytes, false))
{
    Image image = Image.FromStream(imageStream); //ArgumentException: Parameter is not valid.
}

我也尝试了以下变体:

a)

using (var imageStream = new MemoryStream(imageBytes))
{
    Bitmap image = new Bitmap(imageStream); //ArgumentException: Parameter is not valid.
}

b)

using (var imageStream = new MemoryStream(imageBytes))
{
    imageStream.Position = 0;
    Image image = Image.FromStream(imageStream); //ArgumentException: Parameter is not valid.
}

c)

TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap image = (Bitmap)typeConverter.ConvertFrom(imageBytes);

d)

使用这种方法:

private Bitmap GetBitmap(byte[] buf)
{
    Int16 width = BitConverter.ToInt16(buf, 18);
    Int16 height = BitConverter.ToInt16(buf, 22);

    Bitmap bitmap = new Bitmap(width, height); //ArgumentException: Parameter is not valid.

    int imageSize = width * height * 4;
    int headerSize = BitConverter.ToInt16(buf, 10);

    System.Diagnostics.Debug.Assert(imageSize == buf.Length - headerSize);

    int offset = headerSize;
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            bitmap.SetPixel(x, height - y - 1, Color.FromArgb(buf[offset + 3], buf[offset], buf[offset + 1], buf[offset + 2]));
            offset += 4;
        }
    }
    return bitmap;
}

结论:

我觉得还有什么地方不对劲,希望你能回答这个问题。

编辑:

前端代码示例:

<script>
    $(function() {
        var reader = new window.FileReader();

        function readImage(file, callBack) {
            reader.onload = function (e) {
                var image = new Image();
                image.onload = function (imageEvt) {
                    if (typeof callBack == "function") {
                        callBack(e.target.result);
                    }
                };
                image.src = e.target.result;
            };
            reader.readAsDataURL(file);
        }

        $j('#file').change(function (e) {
            var file = e.target.files[0];

            readImage(file, function(imageData) {
                $('#imageData').val(imageData);
            });
        });
    });
</script>

@using (Html.BeginForm("UploadImage", "Images", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(true)
    <input name="PostedImage.ImageData" type="hidden" id="imageData" value="" />

    @* REST OF THE HTML CODE HERE *@

    <p>Choose an image:</p>
    <input type="file" name="file" id="file" />

    <input type="submit" value="Upload" />
}

控制器/动作示例:

[HttpPost]
public ActionResult Opret(PostedImage postedImage)
{
    String imageData = PostedImage.ImageData;

    byte[] imageBytes = Convert.FromBase64String(imageData.EncodeTo64());

    using (var imageStream = new MemoryStream(imageBytes, false))
    {
        Image image = Image.FromStream(imageStream);
    }
}

【问题讨论】:

    标签: c# image bitmap system.drawing


    【解决方案1】:

    我认为您的问题是您正在获取发布到控制器的 base64 字符串,将其视为 ASCII,然后再次将其转换为 base64。

    我认为您需要更改此行

    byte[] imageBytes = Convert.FromBase64String(imageData.EncodeTo64());
    

    byte[] imageBytes = Convert.FromBase64String(imageData);
    

    从那里你的字节应该是正确的,你应该能够创建你的图像

    --编辑--

    我获取了您在文本文档中提供的示例数据,并在将其加载到位图中之前对其进行了解析。我能够将图像保存到我的硬盘驱动器并受到斯巴达人的欢迎(Go Green!)

    试试这段代码,看看会发生什么。

    请注意 imageData 正是 http://kristianbak.com/test_image.txt 上公开的内容。我会提供初始化,但它是一个相当大的字符串,可能会破坏。

    string imageDataParsed = imageData.Substring( imageData.IndexOf( ',' ) + 1 );
    byte[] imageBytes = Convert.FromBase64String( imageDataParsed );
    using ( var imageStream = new MemoryStream( imageBytes, false ) )
    {
       Bitmap image = new Bitmap( imageStream );
    }
    

    【讨论】:

    • 感谢您的回答。我在解决我的地狱之路之前尝试过这个,并尝试你的建议会产生这个错误:i.imgur.com/tWEzH.png
    • 您能否发布代码以显示表单的外观以及您如何从中读取数据?
    • 太棒了!那一行string imageDataParsed = imageData.Substring( imageData.IndexOf( ',' ) + 1 ); 解决了问题,我也可以将图像保存在本地,然后确认它是相同的图像。非常感谢! :D 附言。以 base64 的形式提供小彩蛋总是很有趣!
    • 很高兴你能成功!您可能还需要从该字符串中解析出 mime 类型(图像/jpeg),以便知道将图像存储在什么格式中。
    • 啊,是的,不管 base64 是由什么类型的图像制成的,我都有字符串的第一段? :)
    猜你喜欢
    • 2017-10-27
    • 2017-01-12
    • 1970-01-01
    • 2017-04-21
    • 2017-11-26
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    相关资源
    最近更新 更多