5

I have a C++ application that has a very straightforward requirement of extracting some meta-data from a JPEG file.

There are various libraries to do this, but initially when prototyping I simply wanted to get things done fast, and since I knew the anatomy of a JPEG file was conveniently delineated by a series of markers, (i.e. {0xFF, 0xXX} tuples with a corresponding length field), I thought it would be easy enough to just iterate over the sections of a JPEG file by starting from the first marker, and iterating from marker to marker until I hit the End-Of-Image marker.

This was easy to implement by simply reading in the JPEG data into an std::vector<unsigned char>, and then just iterating over it, finding marker sections. I eventually abstracted this logic into a "marker-iterator" class that made it even easier to work with.

Generally this works great. In fact, usually the meta-data I'm interested in appears in the first marker after the SOI marker (i.e. the APP0 marker, beginning with { 0xF0, 0xE0 }). So, for the most part I don't even NEED to actually write logic to iterate over the whole JPEG file - I can just check the header which always contains the APP0 marker.

Except then I discovered my assumption was wrong. Apparently, the 0xF0, 0xE0 marker doesn't ALWAYS have to be the first segment.

Okay, no problem - iterating over all the markers is easy enough anyway. Except, then I ran into another problem. For the most part, finding the next marker is as easy as adding a length field to the current index position into the JPEG data buffer. But apparently some length fields don't actually indicate the entire length of a particular segment. For example, the "Start-Of-Scan" segment in a JPEG file is followed by "entropy-coded data". The size of the "entropy-coded data" is not included in the length field.

So ... if you hit a "Start-Of-Scan" marker while iterating over a JPEG file, how do you know where the next marker begins? Do you simply have to do a linear search, byte-by-byte, to find the next 0xFF character?

Actually, that wouldn't work either, because the entropy-coded data itself may contain 0xFF characters. However, apparently it is required by the JPEG standard that any 0xFF byte that appears in the entropy-coded data must be followed by a 0x00 byte to differentiate it from an actual marker.

Okay, so that still doesn't give me any way to find the next marker after the "Start-Of-Scan" section without doing a brute force linear search. Is that the only possible way to do it (without complex parsing logic that is specific for the "Start-Of-Scan" section?)

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Siler
  • 8,976
  • 11
  • 64
  • 124
  • You could probably just search for your metadata from the beginning and end of your image file, in the hopes that no sane peice of software would jam metadata between image data in the middle of a file. – Louis Ricci Sep 30 '15 at 19:28
  • All meta-data should be defined BEFORE you hit the SOS tag. – BitBank Oct 01 '15 at 09:03
  • You can use https://www.exiv2.org/ to extract metadata. – Mihai8 Jun 29 '19 at 01:03

2 Answers2

1

So ... if you hit a "Start-Of-Scan" marker while iterating over a JPEG file, how do you know where the next marker begins? Do you simply have to do a linear search, byte-by-byte, to find the next 0xFF character?

In a scan you can have FF00 or a restart marker. Any other FFxx sequence should be the start of the next block.

Also, a JPEG image does not have to have an APP0 marker.

user3344003
  • 20,574
  • 3
  • 26
  • 62
-1

Maybe visit http://www.ijg.org/, download the C code and check how they do on the lib?

I think djpeg.c has a parser for the markers.

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43