繁体   English   中英

在C#中将原始字节转换为gif文件图像

[英]Convert raw bytes to a gif file image in c#

我有原始字节数组数据,并且想将其转换为c#上的.gif图像。 我尝试过这种方法,如下所示。 我想问一下如何在C#中执行此操作。

我试过的方法:从byte[]构造MemoryStream并使用Image.FromStream :它不起作用,因为我只有原始字节数组,要显示图像的像素以及将字节作为参数的构造函数数组想要的也是图像的元数据。

public static Image ConvertByteArraytoBitmap(byte[] bytes)
        {
            using (MemoryStream ms = new MemoryStream(bytes))
                return Image.FromStream(ms);
        }

编辑:对于约翰,原始字节数组(此图像我较小,并且字节数组只有100个字节):

 woDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoDCgMKAwoA=

.Net中处理8位图像的方法不是很简单。 您需要使用(width, height, pixelformat) LockBits (width, height, pixelformat)构造函数制作一个新的Bitmap ,然后使用LockBits打开其后备字节数组,并使用Marshal.Copy将图像数据复制到其中。

请注意,此后备数据数组中一行的字节长度(称为“跨度”)始终四舍五入为四个字节的倍数,因此必须逐行复制数据,然后跳到下一行位置使用跨步,而不仅仅是(图像宽度*每像素位数)值。

但是,就图像宽度而言……您的字节数组仅是图像的一部分。 如果仅仅是像素数据,则将丢失所有常用的图像标头信息,例如图像尺寸,并且假设像素格式为8位索引(如gif),则为调色板。 这些数据不是可选的 没有它,就无法重建图像。

如果图像是灰度图像,并且每个字节仅表示亮度,则可以使用简单的for循环轻松生成调色板,但是:

Color[] palette = new Color[256];
for (Int32 i = 0; i < palette.Length; i++)
    palette[i] = Color.FromArgb(i, i, i);

一旦(以某种方式)获得了丢失的信息,就可以通过bytes数组制作图像:

/// <summary>
/// Creates a bitmap based on data, width, height, stride and pixel format.
/// </summary>
/// <param name="sourceData">Byte array of raw source data</param>
/// <param name="width">Width of the image</param>
/// <param name="height">Height of the image</param>
/// <param name="stride">Scanline length inside the data</param>
/// <param name="pixelFormat">Pixel format</param>
/// <param name="palette">Color palette</param>
/// <param name="defaultColor">Default color to fill in on the palette if the given colors don't fully fill it.</param>
/// <returns>The new image</returns>
public static Bitmap BuildImage(Byte[] sourceData, Int32 width, Int32 height, Int32 stride, PixelFormat pixelFormat, Color[] palette, Color? defaultColor)
{
    Bitmap newImage = new Bitmap(width, height, pixelFormat);
    BitmapData targetData = newImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, pixelFormat);
    //If the input stride is larger than the width, this calculates the actual amount of bytes to copy for each line.
    Int32 newDataWidth = ((Image.GetPixelFormatSize(pixelFormat) * width) + 7) / 8;
    // Compensate for possible negative stride on BMP format data.
    Boolean isFlipped = stride < 0;
    stride = Math.Abs(stride);
    // Cache these to avoid unnecessary getter calls.
    Int32 targetStride = targetData.Stride;
    Int64 scan0 = targetData.Scan0.ToInt64();
    for (Int32 y = 0; y < height; y++)
        Marshal.Copy(sourceData, y * stride, new IntPtr(scan0 + y * targetStride), newDataWidth);
    newImage.UnlockBits(targetData);
    // Fix negative stride on BMP format.
    if (isFlipped)
        newImage.RotateFlip(RotateFlipType.Rotate180FlipX);
    // For indexed images, set the palette.
    if ((pixelFormat & PixelFormat.Indexed) != 0 && palette != null)
    {
        ColorPalette pal = newImage.Palette;
        for (Int32 i = 0; i < pal.Entries.Length; i++)
        {
            if (i < palette.Length)
                pal.Entries[i] = palette[i];
            else if (defaultColor.HasValue)
                pal.Entries[i] = defaultColor.Value;
            else
                break;
        }
        newImage.Palette = pal;
    }
    return newImage;
}

对于8位图像的紧凑字节数组,宽度和步幅应相同。 但是,如果没有调色板或尺寸,则无法实现。

为了记录,您上面的重复小小的{0xC2,0x80}字节数组被加载为10×20灰度图像(200字节,而不是您所说的100字节),得到的结果(放大到x20):

字节数组作为8位灰度图像加载 它只是2个重复的字节,宽度相等,所以您得到的只是垂直线...

暂无
暂无

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

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