I'm creating a program which reads and prints out metadata from an image, but I'm struggling to get my head around the JFIF and EXIF marker structures.
According to the wikipedia page for JFIF, the JFIF marker should be as follows:
FF E0 s1 s2 4A 46 49 46 00 ii ii jj XX XX YY YY xx yy
Where:
FF E0 is the start of the JFIF marker
s1 and s2 combined give the size of the segment (excluding the APP0 marker)
4A 46 49 46 00 is the identifier (literally JFIF in ascii)
i is the version of JFIF (2 bytes)
j is the density uni for DPI measurement
X is the Horizontal DPI
Y is the Vertical DPI
x is the Horizontal THUMBNAIL DPI
y is the Vertical THUMBNAIL DPI
However, when running an image through my program, I get this:
ff e0 20 10 4a 46 49 46 20 1 1 20 20 48 20 48 20 20 ff e1
The marker start is there, but the segment size looks well off (0x2010??) seeing as the next Marker for EXIF data starts just 15 bytes later! (FF E1) I think that hex values of 0x00 aren't being printed (hence why my image prints the JFIF identifier without the zeros) which may be adding to the confusion, but even then, how is the JFIF version 20 20?
If anyone on here has any experience looking at image metadata, I'd really appreciate your help! There's not a lot of resources that I can find that break down JFIF/EXIF data very clearly.
If you need me to post any code in here then I can, though apart from not printing 0x00 values to the console, it seems to being working as expected, so I think my main issue is actually understanding the meta data
Here is the code for taking the byte stream and then converting it into hex:
fileLocation = Console.ReadLine();
var fileDataAsBytes = File.ReadAllBytes(fileLocation);
var headers = fileDataAsBytes
.Select((b, i) => (b, i))
.Where(tuple => tuple.b == 0xFF
&& fileDataAsBytes[tuple.i + 1] == 0xE1)
.Select(tuple => $"{tuple.i}: {tuple.b:x}
{fileDataAsBytes[tuple.i + 1]:x}");
Console.WriteLine(String.Join(",", headers));
DealWithMarkers(fileDataAsBytes);
DisplayAllConversions(fileDataAsBytes);
public static void DisplayAllConversions(byte[] fileDataAsBytes)
{
DisplayBytes(fileDataAsBytes);
DisplayHex(fileDataAsBytes);
DisplayString(fileDataAsBytes);
}
public static void DisplayHex(byte[] fileDataAsBytes)
{
Console.WriteLine($"\n\n\n\t*\t*\t*\t(As Hex)\t*\t*\t*\n");
for (int i = 0; (i < 1000) && (i < fileDataAsBytes.Length); i++)
{
Console.Write($"{fileDataAsBytes[i]:x} ");
}
}
I tried this with a different image and it actually prints out the 0 value bytes correctly, so there must be something weird with the image file I was analyzing!