* Copyright 2008, Axel DΓΆrfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "exif_parser.h"
#include <stdio.h>
#include <string.h>
#include <BufferIO.h>
#include <Entry.h>
#include <File.h>
#include <Message.h>
#include "ReadHelper.h"
#include "TIFF.h"
static status_t
process_exif(uint8* data, uint32 length)
{
if (memcmp(data + 2, "Exif", 4))
return B_BAD_TYPE;
BMemoryIO source(data + 8, length - 8);
BMessage exif;
status_t status = convert_exif_to_message(source, exif);
exif.PrintToStream();
return status;
}
static status_t
process_jpeg(BPositionIO& stream)
{
enum {
START_OF_IMAGE_MARKER = 0xd8,
EXIF_MARKER = 0xe1
};
uint8 header[2];
if (stream.Read(&header, 2) != 2)
return B_IO_ERROR;
if (header[0] != 0xff || header[1] != START_OF_IMAGE_MARKER)
return B_BAD_TYPE;
while (true) {
uint8 marker;
for (int32 i = 0; i < 7; i++) {
if (stream.Read(&marker, 1) != 1)
return B_BAD_TYPE;
if (marker != 0xff)
break;
}
if (marker == 0xff)
return B_BAD_TYPE;
uint16 length;
if (stream.Read(&length, 2) != 2)
return B_BAD_TYPE;
swap_data(B_UINT16_TYPE, &length, 2, B_SWAP_BENDIAN_TO_HOST);
if (marker == EXIF_MARKER) {
stream.Seek(-2, SEEK_CUR);
uint8 exifData[length];
if (stream.Read(exifData, length) == length
&& process_exif(exifData, length) == B_OK)
return B_OK;
} else {
stream.Seek(length - 2, SEEK_CUR);
}
}
return B_BAD_VALUE;
}
static status_t
process_file(entry_ref& ref)
{
BFile file(&ref, B_READ_WRITE);
status_t status = file.InitCheck();
if (status != B_OK)
return status;
BBufferIO stream(&file, 65536, false);
status = process_jpeg(file);
if (status < B_OK) {
fprintf(stderr, "%s: processing JPEG file failed: %s\n", ref.name,
strerror(status));
return status;
}
return B_OK;
}
int
main(int argc, char **argv)
{
for (int i = 1; i < argc; i++) {
BEntry entry(argv[i]);
entry_ref ref;
if (entry.InitCheck() != B_OK || entry.GetRef(&ref) != B_OK)
continue;
process_file(ref);
}
return -1;
}