繁体   English   中英

转换为 Base64 时从字节数组获得反转图像

[英]Got Reversed Image from Byte Array when converting to Base64

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

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

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

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

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

  • 如果Height > 0 ,那么您就是您所期望的情况,其中像素按“正常”顺序排列,从上到下。

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

当您使用BMP对象进行存储时,它会根据上下文为您计算出这一点。 但是,当您仅导出像素时,加载图像的第三方应用程序会看到正Height并因此颠倒显示您的图像。

您可以在BMP 文件格式Wikipedia 页面中找到有关此像素排序的详细信息。

编辑:

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

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

  2. 如果(a):将图像的height作为 BMP 标题中的正值

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

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

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

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

我遇到了同样的问题,但仍然需要一个 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());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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