4

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. アクションは、次のように文字列を 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);
    }
}
4

1 に答える 1

5

あなたの問題は、コントローラーに投稿された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 );
}
于 2012-07-28T12:58:02.977 に答える