C# - Base64字节数组到Image FAILS无论我尝试什么

时间:2012-07-28 12:09:44

标签: c# image bitmap system.drawing

我在使用base64编码的字节数组在C#中创建一个Image / Bitmap对象时遇到了问题。

以下是我正在处理的内容:


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

本质:

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

http://kristianbak.com/test_image.txt

  1. base64字符串已发布到操作,并作为参数imageData
  2. 收到
  3. 该操作将字符串转换为base64字节数组,如下所示:
  4. byte[] imageBytes = Convert.FromBase64String(imageData.EncodeTo64());
  5. 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" />
    }
    

    Controller / Action示例:

    [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);
        }
    }
    

1 个答案:

答案 0 :(得分:5)

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

我认为您需要更改此行

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

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

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

- 编辑 -

我获取了您在文本文档中提供的示例数据,并在将其加载到Bitmap之前对其进行了解析。我能够将图像保存到我的硬盘上并受到Spartan(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 );
}