如何使用标头字节确定图像的编码

Posted

技术标签:

【中文标题】如何使用标头字节确定图像的编码【英文标题】:How to determine encoding of image using header bytes 【发布时间】:2016-06-10 23:19:48 【问题描述】:

所以我使用的是 c#,我需要确定图像文件的实际编码。大多数图像可以采用一种格式,同时具有不同的扩展名,并且仍然可以正常工作。

我需要准确了解图像格式。

还有另一个线程处理这个问题:Determine Image Encoding of Image File

这个节目是如何在你获得图像的标题信息后找到实际的编码。 我需要打开图片并提取此标题信息。

FileStream imageFile = new FileStream("myImage.gif", FileMode.Open);

在此位之后,我如何只打开包含标头的字节?

谢谢。

【问题讨论】:

【参考方案1】:

除非你知道它的大小,否则你不能真正阅读“只是标题”。

相反,确定您需要能够区分您需要支持的格式的最小字节数,并且只读取这些字节。您需要的所有格式很可能都有一个唯一的标题。

例如,如果您需要支持 png 和 jpeg,这些格式以:

  PNG: 89 50 4E 47 0D 0A 1A 0A
 JPEG: FF D8 FF E0

因此,在这种情况下,您只需读取一个字节即可区分两者。实际上我会说多使用几个字节,以防万一您遇到其他文件格式。

从文件开头读取,比如说 8 个字节:

using( var sr = new FileStream( "file", FileMode.Open ) )

    var data = new byte[8];
    int numRead = sr.Read( data, 0, data.Length );
    // numRead gives you the number of bytes read

【讨论】:

这不是我要问的。我在问如何在 C# 中实际读取这些字节。 SO上有另一个相关线程处理每种图像中的字节数:***.com/questions/10423942/…我需要 C# 代码来打开图像,提取 (x) 字节,然后将这些 (x) 字节传递给函数。上面的链接包含每种类型的图像使用的字节数。 PNG(8bytes), (JPG 2bytes 后跟 10bytes 标识符), BMP(14bytes), GIF(14bytes) 我在读取 8 个字节时遇到的主要问题是,我用来确定实际编码的代码需要一个图像对象,并附有一个有效的图像文件。因此,如果您尝试仅使用标头字节创建图像对象,它将引发错误。 @Jscix Image.FromStream 的目的是加载图像,因此您无法有效地将其用于图像格式识别。它当然没有办法只读取标题。我添加了基本代码来从文件中读取一些字节。【参考方案2】:

好吧,我最终想通了。所以我要更新线程并关闭它。我的解决方案的唯一问题是它需要打开整个图像文件,而不仅仅是所需的字节。 这会使用更多的内存,并且需要更长的时间。因此,当速度受到关注时,它不是最佳解决方案。

只是为了给予应有的荣誉,此代码是从 这里有几个关于 stack-overflow 的来源,你可以找到链接 OP 和更早的 cmets。剩下的代码都是我写的。

如果有人想修改代码以仅打开正确数量的字节,请随意。

TextWriterTraceListener writer = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(writer);

// PNG file contains 8 - bytes header.

// JPEG file contains 2 - bytes header(SOI) followed by series of markers,
// some markers can be followed by data array. Each type of marker has different header format.
// The bytes where the image is stored follows SOF0 marker(10 - bytes length).
// However, between JPEG header and SOF0 marker there can be other segments.

// BMP file contains 14 - bytes header.

// GIF file contains at least 14 bytes in its header.

FileStream memStream = new FileStream(@"C:\\a.png", FileMode.Open);

Image fileImage = Image.FromStream(memStream);
    
//get image format
var fileImageFormat = typeof(System.Drawing.Imaging.ImageFormat).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).ToList().ConvertAll(property => property.GetValue(null, null)).Single(image_format => image_format.Equals(fileImage.RawFormat));

MessageBox.Show("File Format: " + fileImageFormat);


//get image codec
var fileImageFormatCodec = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList().Single(image_codec => image_codec.FormatID == fileImage.RawFormat.Guid);

MessageBox.Show("MimeType: " + fileImageFormatCodec.MimeType + " \n" + "Extension: " + fileImageFormatCodec.FilenameExtension + "\n" + "Actual Codec: " + fileImageFormatCodec.CodecName);

输出如预期:

文件图像格式:PNG

内置PNG编解码器,mime:image/png,扩展名:*.PNG

【讨论】:

以上是关于如何使用标头字节确定图像的编码的主要内容,如果未能解决你的问题,请参考以下文章

如何确定图像的编码

使用带有表单编码参数和标头的 C# httpclient 发布

如何通过使用 ByteBuffer 查看标头偏移量来制作字节数组?

如何将图像的字节数组转换为表示 jpg 的 base64 编码字符串

我有很多字节数组;每个都是一个字符串。我如何找到每个使用的编码?

如何使用 Apache 在代理设置中重写位置响应标头?