views:

306

answers:

1

I've got raw data streams from image files, like:

vector<char> rawData(fileSize);
ifstream inFile("image.jpg");
inFile.read(&rawData[0]);

I want to parse the headers of different image formats for height and width. Is there a portable library that can can read ints, longs, shorts, etc. from the buffer/stream, converting for endianess as specified?

I'd like to be able to do something like: short x = rawData.readLeShort(offset); or long y = rawData.readBeLong(offset)

An even better option would be a lightweight & portable image metadata library (without the extra weight of an image manipulation library) that can work on raw image data. I've found that Exif libraries out there don't support png and gif.

A: 

It's not that hard to do yourself. Here's how you can read a little endian 32 bit number:

unsigned char buffer[4];
inFile.read(buffer, sizeof(buffer));

unsigned int number = buffer[0] +
                      (buffer[1] << 8) +
                      (buffer[2] << 16) +
                      (buffer[3] << 24);

and to read a big endian 32 bit number:

unsigned char buffer[4];
inFile.read(buffer, sizeof(buffer));

unsigned int number = buffer[3] +
                      (buffer[2] << 8) +
                      (buffer[1] << 16) +
                      (buffer[0] << 24);
R Samuel Klatchko
I generalized that to this:`template<class T> T Magic::getLE(const char* data) const { T value = 0; int bytes = sizeof(T); for (int i = 0; i < bytes; i++) { value += data[i] << CHAR_BIT * i; } return value; }`Should work, right?
Kache4
Actually, code above has a bug. Instead of shifting `chars` over one at a time, it shifts `T` one over at a time. This fixes that: `template<class T> T Magic::getLE(const char* data) const { T value = 0; int bytes = sizeof(T); unsigned char c; for (int i = 0; i < bytes; i++) { c = data[i]; value += c << CHAR_BIT * i; } return value; }`
Kache4