xref: /haiku/src/tests/add-ons/translators/exif/dump_exif.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "exif_parser.h"
8 
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include <BufferIO.h>
13 #include <Entry.h>
14 #include <File.h>
15 #include <Message.h>
16 
17 #include "ReadHelper.h"
18 #include "TIFF.h"
19 
20 
21 static status_t
22 process_exif(uint8* data, uint32 length)
23 {
24 	if (memcmp(data + 2, "Exif", 4))
25 		return B_BAD_TYPE;
26 
27 	BMemoryIO source(data + 8, length - 8);
28 	BMessage exif;
29 	status_t status = convert_exif_to_message(source, exif);
30 
31 	exif.PrintToStream();
32 		// even if it failed, some data might end up in the message
33 
34 	return status;
35 }
36 
37 
38 static status_t
39 process_jpeg(BPositionIO& stream)
40 {
41 	enum {
42 		START_OF_IMAGE_MARKER = 0xd8,
43 		EXIF_MARKER = 0xe1
44 	};
45 
46 	uint8 header[2];
47 	if (stream.Read(&header, 2) != 2)
48 		return B_IO_ERROR;
49 	if (header[0] != 0xff || header[1] != START_OF_IMAGE_MARKER)
50 		return B_BAD_TYPE;
51 
52 	while (true) {
53 		// read marker
54 		uint8 marker;
55 		for (int32 i = 0; i < 7; i++) {
56 			if (stream.Read(&marker, 1) != 1)
57 				return B_BAD_TYPE;
58 
59 			if (marker != 0xff)
60 				break;
61 		}
62 
63 		if (marker == 0xff)
64 			return B_BAD_TYPE;
65 
66 		// get length of section
67 
68 		uint16 length;
69 		if (stream.Read(&length, 2) != 2)
70 			return B_BAD_TYPE;
71 
72 		swap_data(B_UINT16_TYPE, &length, 2, B_SWAP_BENDIAN_TO_HOST);
73 
74 		if (marker == EXIF_MARKER) {
75 			// read in section
76 			stream.Seek(-2, SEEK_CUR);
77 
78 			uint8 exifData[length];
79 			if (stream.Read(exifData, length) == length
80 				&& process_exif(exifData, length) == B_OK)
81 				return B_OK;
82 		} else {
83 			// ignore section
84 			stream.Seek(length - 2, SEEK_CUR);
85 		}
86 	}
87 
88 	return B_BAD_VALUE;
89 }
90 
91 
92 static status_t
93 process_file(entry_ref& ref)
94 {
95 	BFile file(&ref, B_READ_WRITE);
96 	status_t status = file.InitCheck();
97 	if (status != B_OK)
98 		return status;
99 
100 	// read EXIF
101 
102 	BBufferIO stream(&file, 65536, false);
103 	status = process_jpeg(file);
104 	if (status < B_OK) {
105 		fprintf(stderr, "%s: processing JPEG file failed: %s\n", ref.name,
106 			strerror(status));
107 		return status;
108 	}
109 
110 	return B_OK;
111 }
112 
113 
114 int
115 main(int argc, char **argv)
116 {
117 	for (int i = 1; i < argc; i++) {
118 		BEntry entry(argv[i]);
119 		entry_ref ref;
120 		if (entry.InitCheck() != B_OK || entry.GetRef(&ref) != B_OK)
121 			continue;
122 
123 		process_file(ref);
124 	}
125 	return -1;
126 }
127