将字节数组转换为Base64时,得到了反向的图像。

3

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

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

“reversed”是什么意思?你能举个例子说明一下bytes的内容和生成的base64吗?你确定第二种情况不只是与保存bmp文件的方式有关吗? - Qortex
好的,"with the code" 和 "with the bytes" 是什么意思?在这两种情况下你使用的是什么代码? - Qortex
“With the code” 意思是上面使用的代码。“With the bytes” 意思是仅使用上述创建的字节。我使用这些字节生成 base64 字符串,可以通过任何在线 base64 测试工具解析结果。但在我的情况下,我需要将 base64 保存到 XML 文件中,然后由第三方读取。似乎字节顺序不正确。 - vikasde
3个回答

0

我遇到了同样的问题,但仍需要一个base64字符串(用于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());

0
我找到了解决方案。我不是创建新的位图,而是跳过了前54个字节的头信息,然后存储了字节数组。
MemoryStream memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Bmp);

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

0

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

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

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

  • 如果Height > 0,则您处于您期望的情况,即像素按照“正常”顺序从上到下排列。

我想说,在您的情况下发生的是,您从使用负Height头存储的图像开始(SVG对象出于某种原因必须这样做)。但是您没有进行检查,因此将像素按照从底部到顶部的顺序存储。

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

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

编辑:

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

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

  2. 如果(a):将图像的高度作为正值放入BMP头中

  3. 如果(b):将-height作为负值放入BMP头中。这样显示您的图像的第三方程序就知道它是反转的。


如果 BMP 文件存储顺序是反向的,我该怎么办?我能把它放回正确的顺序吗? - vikasde
你只需要按照写入的字节顺序编写最终BMP文件,并使其height与之匹配即可。 - Qortex
抱歉,我没有示例代码,但我已经编辑了我的答案。 - Qortex
但是当我保存它时,写入的bmp文件看起来很好。它的“字节”是错误的。此外,我不能在第三方应用程序中使用标题,只需要位图数据。 - vikasde
我不知道你的具体情况,但底线是:你写入文件的字节顺序与BMP头部宣布的顺序不同。因此,无论你使用什么方式来编写所有内容,都必须解决这个问题。只需使字节的顺序与header.height的符号相同即可。然后根据你的实现找出具体细节。如果你不是自己编写头文件,那么某个库/函数会编写它,否则它将是一个无效的BMP文件。因此,找出在哪里,并为高度给出正确的符号。 - Qortex
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接