【问题标题】:Got Reversed Image from Byte Array when converting to Base64转换为 Base64 时从字节数组中得到反转图像
【发布时间】:2013-03-21 12:23:09
【问题描述】:

我只需要获取原始位图数据(无需标题或其他信息)。我使用以下代码获取位图数据:

using (Bitmap bitmap = svgDocument.Draw())
{
  Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
  BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
  var length = Math.Abs(bitmapData.Stride) * bitmapData.Height;

  byte[] bytes = new byte[length];
  Marshal.Copy(bitmapData.Scan0, bytes, 0, length);
  bitmap.UnlockBits(bitmapData);

  MemoryStream memoryStream = new MemoryStream();
  string filename = DateTime.Now.Ticks.ToString() + ".bmp"; // this works fine
  bitmap.Save(filename, ImageFormat.Bmp);

  string base64 = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks); // the base64 is reversed. 
}

当我保存位图时,一切看起来都很好。图像没有反转。但是,当我仅使用字节将数据转换为 Base64 时,图像会反转。

编辑 1:

我认为这与 Base64 转换无关。似乎字节的顺序相反。

当我使用代码保存图像时,图像如下所示:

当我使用字节时,我会看到:

解决方案:

我找到了解决方案。我没有创建新的位图,而是跳过了头信息的前 54 个字节,然后存储了字节数组。

MemoryStream memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Bmp);

// Skip header
IEnumerable<byte> bytes = memoryStream.ToArray().Skip(54);

【问题讨论】:

  • 你所说的“反转”是什么意思?你能举例说明bytes 的内容和生成的base64 吗?您确定这不仅仅是您在第二种情况下保存 bmp 文件的方式的问题吗?
  • @Mic:请看我的编辑
  • 好的,你说的“用代码”和“用字节”是什么意思?您在这两种情况下使用的代码是什么?
  • “有代码”,我指的是上面使用的代码。 “使用字节”,我的意思是仅使用上面创建的字节。我使用字节生成base64字符串,任何在线测试的base64都可以解析该字符串以查看结果。在我的情况下,虽然我需要将 base64 保存到一个 xml 文件中,然后由第三方读取。好像字节顺序不对。

标签: c# image bytearray reverse


【解决方案1】:

标准 BMP 格式允许以经典的自上/下顺序或反向顺序存储图像的字节。

判断你的图片是否以这种方式存储的方法是检查BMP头中Height参数的值:

  • 如果Height &lt; 0,则图像的高度为abs(Height),并且像素以相反的(底部/顶部)顺序存储。

  • 如果Height &gt; 0,那么您就是您所期望的情况,其中像素处于“正常”顺序,从上到下。

我会说,在您的情况下发生的情况是您从存储有负 Height 标头的图像开始(SVG 对象出于某种原因必须这样做)。但是你不检查它,所以你按从下到上的顺序存储像素。

当您使用 BMP 对象进行存储时,它会根据上下文为您计算出来。但是,当您只导出像素时,加载您的图像的第三方应用程序会看到正面的Height,从而将您的图像颠倒显示。

您可以在Wikipedia page for BMP file format 中找到有关此像素排序的详细信息。

编辑:

因此,当您将 BMP 文件写入磁盘时,您必须执行以下操作:

  1. 检查您的字节是从上到下的顺序 (a) 还是从下到上的顺序 (b)

  2. If (a): 把你图片的height作为一个正值放在BMP header中

  3. If (b):将- height 作为负值放入 BMP 标头中。以便显示您的图像的第三方程序知道它被反转了。

【讨论】:

  • bmp存储顺序倒序怎么办?我可以把它放回正确的顺序吗?
  • 我检查了 bitmap.Height 及其 > 0。
  • 您只需使用与您写入的字节顺序相匹配的height 编写最终的BMP。
  • 因此您不必自己反转字节,只需根据需要确保height&gt; 0&lt; 0
  • 对不起,我没有示例代码,但我编辑了答案。
【解决方案2】:

我找到了解决方案。我没有创建新的位图,而是跳过了头信息的前 54 个字节,然后存储了字节数组。

MemoryStream memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Bmp);

// Skip header
IEnumerable<byte> bytes = memoryStream.ToArray().Skip(54);

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,但仍然需要一个 base 64 字符串(用于 HTML5 画布)。所以我使用Image类来旋转图像,存储在一个新的流中,然后转换为base64字符串。

    var image = System.Drawing.Image.FromStream(new MemoryStream(bytes));
    
    //Rotate and save to new stream
    image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
    MemoryStream streamOut = new MemoryStream();
    image.Save(streamOut, System.Drawing.Imaging.ImageFormat.Jpeg);
    
    //Convert to base64 string
    string base64String = Convert.ToBase64String(streamOut.ToArray());
    

    【讨论】:

      猜你喜欢
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2013-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多