简体   繁体   English

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

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

I need to get the raw bitmap data only (no header, or other information).我只需要获取原始位图数据(无标题或其他信息)。 I used the following code to get the bitmap data:我使用以下代码来获取位图数据:

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. 
}

When I save the bitmap, everything looks fine.当我保存位图时,一切看起来都很好。 The image is not reversed.图像没有反转。 However when I use the bytes only to convert the data to Base64, then the image is reversed.但是,当我仅使用字节将数据转换为 Base64 时,图像就会反转。

Edit 1:编辑1:

I think this has nothing to do with the Base64 conversion.我认为这与 Base64 转换无关。 It seems that the bytes are in reversed order.似乎字节顺序相反。

When I save the image using the code, the image looks like this:当我使用代码保存图像时,图像如下所示:

在此处输入图片说明

When I use the bytes, then I see this:当我使用字节时,我会看到:

在此处输入图片说明

Solution:解决方案:

I found the solution.我找到了解决方案。 Instead of creating a new bitmap, I just skipped the first 54 bytes of header information and then stored the byte array.我没有创建新的位图,而是跳过了头信息的前 54 个字节,然后存储了字节数组。

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

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

The standard BMP format allows to store bytes of the image either in classical top/down order or in reverse order.标准 BMP 格式允许以经典的上/下顺序或相反的顺序存储图像的字节。

The way to tell whether your image is stored this way is to check the value of the Height parameter in the BMP header:判断你的图像是否以这种方式存储的方法是检查 BMP 标头中的Height参数的值:

  • If Height < 0 , then the height of your image is abs(Height) and the pixels are stored in reverse (bottom / top) order.如果Height < 0 ,则图像的高度为abs(Height)并且像素以反向(底部/顶部)顺序存储。

  • If Height > 0 , then you are in the case you expect, where pixels are in 'normal' order, top to bottom.如果Height > 0 ,那么您就是您所期望的情况,其中像素按“正常”顺序排列,从上到下。

I would say that what happens in your case is that you are starting from an image stored with a negative Height header (the SVG object must do that for some reason).我会说,在您的情况下发生的情况是您从存储有负Height标头的图像开始( SVG对象出于某种原因必须这样做)。 But you do not check it, so you store the pixels in bottom to top order.但是您没有检查它,因此您按从下到上的顺序存储像素。

When you store with the BMP object, it figures that out for you from the context.当您使用BMP对象进行存储时,它会根据上下文为您计算出这一点。 But when you export just the pixels, then the third party application that loads your image sees positive Height and thus shows your image upside down.但是,当您仅导出像素时,加载图像的第三方应用程序会看到正Height并因此颠倒显示您的图像。

You can find details about this pixel ordering in the Wikipedia page for BMP file format .您可以在BMP 文件格式Wikipedia 页面中找到有关此像素排序的详细信息。

Edit:编辑:

So, when you write a BMP file to your disk, you have to do the following:因此,当您将 BMP 文件写入磁盘时,您必须执行以下操作:

  1. Check whether your bytes are in top to bottom order (a) or in bottom to top order (b)检查您的字节是按从上到下的顺序 (a) 还是按从下到上的顺序 (b)

  2. If (a): put the height of your image as a positive value in the BMP header如果(a):将图像的height作为 BMP 标题中的正值

  3. If (b): put - height as a negative value in the BMP header. If (b): put - height作为 BMP 标头中的负值。 So that the third party program that shows your image knows that it's reversed.以便显示您的图像的第三方程序知道它已反转。

I found the solution.我找到了解决方案。 Instead of creating a new bitmap, I just skipped the first 54 bytes of header information and then stored the byte array.我没有创建新的位图,而是跳过了头信息的前 54 个字节,然后存储了字节数组。

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

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

I ran into the same problem but still needed a base 64 string (for HTML5 canvas).我遇到了同样的问题,但仍然需要一个 base 64 字符串(对于 HTML5 画布)。 So I used the Image class to rotate the image, stored in a new stream, then convert to base64 string.所以我使用 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