0

So I am using c#, and I need to determine the actual encoding of an image-file. Most images can be in one format while simultaneously having a different extension and still work in general.

My need's require precise knowledge of the image format.

There is one other thread that deals with this: Determine Image Encoding of Image File

This show's how to find the actual encoding once you have the image's header information. I need to open the image and extract this header information.

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

After this bit, how do I open only the bytes which contain the header?

Thank you.

Community
  • 1
  • 1
Jscix
  • 86
  • 1
  • 6

2 Answers2

1

You can't really read "just the header" unless you know it's size.

Instead, determine the minimum amount of bytes you need to be able to distinguish between the formats you need to support, and read only those bytes. Most likely all of the formats you need will have a unique header.

For example, if you need to support png & jpeg, those formats start with:

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

So in that case you'd only have to read a single byte to differ between the two. In reality I'd say use a few more bytes, just in case you encounter other file formats.

To read, say 8 bytes, from the beginning of a file:

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
}
Chris
  • 5,442
  • 17
  • 30
  • That isn't what I was asking. I am asking how to actually read these bytes in C#. There is another related thread on SO dealing with the amount of bytes in each type of image: http://stackoverflow.com/questions/10423942/what-is-the-header-size-of-png-jpg-jpeg-bmp-gif-and-other-common-graphics-for I need the C# code to open the image, extract (x) bytes, then pass those (x) bytes into a function. The link above contains the number of bytes each type of image uses. PNG(8bytes), (JPG 2bytes Followed by 10 bytes of identifiers), BMP(14bytes), GIF(14bytes) – Jscix Feb 28 '16 at 20:44
  • The main issue I run into when reading just the 8 byes, is that the code im using to determine the actual encoding requires an Image Object, with a valid Image File attached. So if you try to create an Image Object with just the header bytes, it will throw an error. – Jscix Feb 28 '16 at 22:01
  • @Jscix Well the purpose of `Image.FromStream` is to load an image, so you cannot efficiently use that for the purpose of image format identification. And it certainly doesn't have a way of reading just the header. I've added basic code to read some bytes from a file. – Chris Feb 29 '16 at 17:28
1

Well I figured it out in the end. So im going to update the thread and close it. The only issue with my solution is that it requires opening the entire image file, rather than just the required bytes. This uses alot more memory, and takes longer. So it isn't the optimal solution when speed is a concern.

Just to give credit where it's due, this code was created from a couple of sources here on stack-overflow, you can find the link's in the OP and earlier comments. The rest of the code was written by me.

If anyone feels like modifying the code to only open the correct amount of bytes, feel free.

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);

Output is as Expected:

file_image_format: Png

Built-in PNG Codec, mime: image/png, extension: *.PNG

Community
  • 1
  • 1
Jscix
  • 86
  • 1
  • 6