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

时间:2013-03-31 04:23:04

标签: c# image bytearray reverse

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

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转换无关。看起来字节的顺序是相反的。

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

enter image description here

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

enter image description here

解决方案:

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

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

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

3 个答案:

答案 0 :(得分:0)

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

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

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

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

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

当您使用BMP对象存储时,它会从上下文中为您找出。但是,当您仅导出像素时,加载图像的第三方应用程序会看到正Height,从而将图像颠倒显示。

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

修改

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

  1. 检查您的字节是从上到下排列(a)还是从下到上依次排列(b)

  2. 如果(a):将图片的height作为正值放入BMP标题

  3. 如果(b):将- height作为负值放在BMP标题中。因此,显示图像的第三方程序知道它已被颠倒过来。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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