我搜索了所有关于字节数组的问题,但总是失败。我从未编写过C#代码,我是这方面的新手。您能帮助我如何从字节数组创建图像文件吗?
这是我的函数,它将字节存储在名为imageData
的数组中。
public void imageReady( byte[] imageData, int fWidth, int fHeight))
你需要将那些 字节
放入一个 MemoryStream
中:
Bitmap bmp;
using (var ms = new MemoryStream(imageData))
{
bmp = new Bitmap(ms);
}
使用Bitmap(Stream stream)
构造函数的重载。
更新:请注意,根据文档和我一直在阅读的源代码,在以下情况下会抛出ArgumentException
:
stream does not contain image data or is null.
-or-
stream contains a PNG image file with a single dimension greater than 65,535 pixels.
ByteArray
包含原始字节。所以那些解决方案对我的代码没有起作用。static byte[] PadLines(byte[] bytes, int rows, int columns) {
int currentStride = columns; // 3
int newStride = columns; // 4
byte[] newBytes = new byte[newStride * rows];
for (int i = 0; i < rows; i++)
Buffer.BlockCopy(bytes, currentStride * i, newBytes, newStride * i, currentStride);
return newBytes;
}
int columns = imageWidth;
int rows = imageHeight;
int stride = columns;
byte[] newbytes = PadLines(imageData, rows, columns);
Bitmap im = new Bitmap(columns, rows, stride,
PixelFormat.Format8bppIndexed,
Marshal.UnsafeAddrOfPinnedArrayElement(newbytes, 0));
im.Save("C:\\Users\\musa\\Documents\\Hobby\\image21.bmp");
PixelFormat
。public void SaveBitmap(string fileName, int width, int height, byte[] imageData)
{
byte[] data = new byte[width * height * 4];
int o = 0;
for (int i = 0; i < width * height; i++)
{
byte value = imageData[i];
data[o++] = value;
data[o++] = value;
data[o++] = value;
data[o++] = 0;
}
unsafe
{
fixed (byte* ptr = data)
{
using (Bitmap image = new Bitmap(width, height, width * 4,
PixelFormat.Format32bppRgb, new IntPtr(ptr)))
{
image.Save(Path.ChangeExtension(fileName, ".jpg"));
}
}
}
}
:无法从具有索引像素格式的图像创建Graphics对象。 (参数'image') 在System.Drawing.Graphics.FromImage(Image image)处
。 - john k可以很容易:
var ms = new MemoryStream(imageData);
System.Drawing.Image image = Image.FromStream(ms);
image.Save("c:\\image.jpg");
测试一下:
byte[] imageData;
// Create the byte array.
var originalImage = Image.FromFile(@"C:\original.jpg");
using (var ms = new MemoryStream())
{
originalImage.Save(ms, ImageFormat.Jpeg);
imageData = ms.ToArray();
}
// Convert back to image.
using (var ms = new MemoryStream(imageData))
{
Image image = Image.FromStream(ms);
image.Save(@"C:\newImage.jpg");
}
static
访问器的另一种方法,但是是的,您需要将 MemoryStream
包装在 using
中。 - Mike PerrenoudSystem.Windows.Controls.Image
是用来显示图像的控件。在这里,使用的是 System.Drawing.Image
类。 - Mario SImage.FromStream
方法中的字节数组并不是一张有效的图像。 - Mario S字节数组
简单地转换为位图
。var bmp = new Bitmap(new MemoryStream(imgByte));
您也可以直接从文件路径获取Bitmap
。
Bitmap bmp = new Bitmap(Image.FromFile(filePath));
ArgumentException:参数无效。
- john k这对我很有帮助:https://www.tek-tips.com/viewthread.cfm?qid=1264492(参考答案)
我的理解是:
这段代码对我有用:
int width = ...;
int height = ...;
byte[] pixelArray = new byte[] {
// Creation of the actual data is not in the scope of this answer
};
Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
// Create a BitmapData and lock all pixels to be written
BitmapData bmpData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.WriteOnly, bmp.PixelFormat);
// Copy the data from the byte array into BitmapData.Scan0
Marshal.Copy(pixelArray, 0, bmpData.Scan0, pixelArray.Length);
// Unlock the pixels
bmp.UnlockBits(bmpData);
// Do something with your image, e.g. save it to disc
bmp.Save("c:\\temp\\mybmp.bmp", ImageFormat.Bmp);
根据被接受的答案,OP想要将imageData
字节数组解释为像素缓冲区,而不是最受欢迎的答案建议的已编码位图流。虽然它能够运行,但其中包含了许多副本,以及调色板问题("现在颜色有问题")。
实际上,我恰好有一个绘画库专门用于此目的(还有其他用途)。平台无关的核心库允许您将任何原始类型数组解释为位图数据:interpret
// Unlike in the accepted answer, no extra buffer allocation or
// array copy happens in the background. Note that we can specify
// a palette for the indexed format so the colors will be interpreted correctly
using var myBitmap = BitmapDataFactory.CreateBitmapData(imageData, new Size(fWidth, fHeight),
stride: fWidth, // stride is same as width because of the 8bpp pixel format
pixelFormat: KnownPixelFormat.Format8bppIndexed,
palette: Palette.Grayscale256());
myBitmap
现在是一个IReadWriteBitmapData
实例,允许进行许多操作(只需查看可用的扩展方法)。它还提供了一个相当快速的SetPixel
方法,它尊重调色板,因此在这种特定情况下将任何颜色转换为灰度。但如果您知道实际的像素格式,还可以使用WriteRaw<T>
方法直接访问像素。
System.Drawing.Bitmap
或 System.Windows.Media.WriteableBitmap
:// the accepted answer creates two bitmaps due to the color problems where
// the 2nd one is a 32 bpp image. This solution is much faster, simpler, it avoids
// unnecessary allocations and uses parallel processing internally if possible
var systemBitmap = myBitmap.ToBitmap(); // or ToBitmapAsync, ToWriteableBitmap, etc.
Bitmap(Stream)
中得知:"必须在Bitmap
对象的生命周期内保持该流处于打开状态。" - piedarMemoryStream
,那么你不必担心关闭它,因为MemoryStream
在被销毁时实际上并不会执行任何操作。System.Drawing.ImageConverter.ConvertFrom
方法利用了这个事实,所以似乎可以做出这样的推断。因此,只需使用var bmp = new Bitmap(new MemoryStream(imageData));
即可。 - Steven Doggart