@@ -51,8 +51,12 @@ direct,
51
51
// https://github.com/opencv/opencv/blob/097891e311fae1d8354eb092a0fd0171e630d78c/modules/imgcodecs/src/exif.cpp
52
52
53
53
#if JPEG_FOUND
54
-
55
54
#include < jpeglib.h>
55
+ #endif
56
+ #if PNG_FOUND
57
+ #include < png.h>
58
+ #endif
59
+
56
60
#include < torch/types.h>
57
61
58
62
namespace vision {
@@ -125,8 +129,48 @@ inline uint32_t get_uint32(
125
129
(exif_data[offset + 2 ] << 8 ) + exif_data[offset + 3 ];
126
130
}
127
131
128
- inline int fetch_exif_orientation (j_decompress_ptr cinfo ) {
132
+ inline int fetch_exif_orientation (unsigned char * exif_data_ptr, size_t size ) {
129
133
int exif_orientation = -1 ;
134
+
135
+ // Exif binary structure looks like this
136
+ // First 6 bytes: [E, x, i, f, 0, 0]
137
+ // Endianness, 2 bytes : [M, M] or [I, I]
138
+ // Tag mark, 2 bytes: [0, 0x2a]
139
+ // Offset, 4 bytes
140
+ // Num entries, 2 bytes
141
+ // Tag entries and data, tag has 2 bytes and its data has 10 bytes
142
+ // For more details:
143
+ // http://www.media.mit.edu/pia/Research/deepview/exif.html
144
+
145
+ ExifDataReader exif_data (exif_data_ptr, size);
146
+ auto endianness = get_endianness (exif_data);
147
+
148
+ // Checking whether Tag Mark (0x002A) correspond to one contained in the
149
+ // Jpeg file
150
+ uint16_t tag_mark = get_uint16 (exif_data, endianness, 2 );
151
+ if (tag_mark == REQ_EXIF_TAG_MARK) {
152
+ auto offset = get_uint32 (exif_data, endianness, 4 );
153
+ size_t num_entry = get_uint16 (exif_data, endianness, offset);
154
+ offset += 2 ; // go to start of tag fields
155
+ constexpr size_t tiff_field_size = 12 ;
156
+ for (size_t entry = 0 ; entry < num_entry; entry++) {
157
+ // Here we just search for orientation tag and parse it
158
+ auto tag_num = get_uint16 (exif_data, endianness, offset);
159
+ if (tag_num == INCORRECT_TAG) {
160
+ break ;
161
+ }
162
+ if (tag_num == ORIENTATION_EXIF_TAG) {
163
+ exif_orientation = get_uint16 (exif_data, endianness, offset + 8 );
164
+ break ;
165
+ }
166
+ offset += tiff_field_size;
167
+ }
168
+ }
169
+ return exif_orientation;
170
+ }
171
+
172
+ #if JPEG_FOUND
173
+ inline int fetch_jpeg_exif_orientation (j_decompress_ptr cinfo) {
130
174
// Check for Exif marker APP1
131
175
jpeg_saved_marker_ptr exif_marker = 0 ;
132
176
jpeg_saved_marker_ptr cmarker = cinfo->marker_list ;
@@ -137,51 +181,48 @@ inline int fetch_exif_orientation(j_decompress_ptr cinfo) {
137
181
cmarker = cmarker->next ;
138
182
}
139
183
140
- if (exif_marker) {
141
- // Exif binary structure looks like this
142
- // First 6 bytes: [E, x, i, f, 0, 0]
143
- // Endianness, 2 bytes : [M, M] or [I, I]
144
- // Tag mark, 2 bytes: [0, 0x2a]
145
- // Offset, 4 bytes
146
- // Num entries, 2 bytes
147
- // Tag entries and data, tag has 2 bytes and its data has 10 bytes
148
- // For more details:
149
- // http://www.media.mit.edu/pia/Research/deepview/exif.html
150
-
151
- // Bytes from Exif size field to the first TIFF header
152
- constexpr size_t start_offset = 6 ;
153
- if (exif_marker->data_length > start_offset) {
154
- auto * exif_data_ptr = exif_marker->data + start_offset;
155
- auto size = exif_marker->data_length - start_offset;
156
-
157
- ExifDataReader exif_data (exif_data_ptr, size);
158
- auto endianness = get_endianness (exif_data);
159
-
160
- // Checking whether Tag Mark (0x002A) correspond to one contained in the
161
- // Jpeg file
162
- uint16_t tag_mark = get_uint16 (exif_data, endianness, 2 );
163
- if (tag_mark == REQ_EXIF_TAG_MARK) {
164
- auto offset = get_uint32 (exif_data, endianness, 4 );
165
- size_t num_entry = get_uint16 (exif_data, endianness, offset);
166
- offset += 2 ; // go to start of tag fields
167
- constexpr size_t tiff_field_size = 12 ;
168
- for (size_t entry = 0 ; entry < num_entry; entry++) {
169
- // Here we just search for orientation tag and parse it
170
- auto tag_num = get_uint16 (exif_data, endianness, offset);
171
- if (tag_num == INCORRECT_TAG) {
172
- break ;
173
- }
174
- if (tag_num == ORIENTATION_EXIF_TAG) {
175
- exif_orientation = get_uint16 (exif_data, endianness, offset + 8 );
176
- break ;
177
- }
178
- offset += tiff_field_size;
179
- }
180
- }
181
- }
184
+ if (!exif_marker) {
185
+ return -1 ;
182
186
}
183
- return exif_orientation;
187
+
188
+ constexpr size_t start_offset = 6 ;
189
+ if (exif_marker->data_length <= start_offset) {
190
+ return -1 ;
191
+ }
192
+
193
+ auto * exif_data_ptr = exif_marker->data + start_offset;
194
+ auto size = exif_marker->data_length - start_offset;
195
+
196
+ return fetch_exif_orientation (exif_data_ptr, size);
197
+ }
198
+ #else
199
+ inline int fetch_jpeg_exif_orientation (j_decompress_ptr cinfo) {
200
+ return -1 ;
201
+ }
202
+ #endif // #if JPEG_FOUND
203
+
204
+ #if PNG_FOUND
205
+ inline int fetch_png_exif_orientation (png_structp png_ptr, png_infop info_ptr) {
206
+ #ifdef PNG_eXIf_SUPPORTED
207
+ png_uint_32 num_exif = 0 ;
208
+ png_bytep exif = 0 ;
209
+
210
+ // Exif info could be in info_ptr
211
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_eXIf)) {
212
+ png_get_eXIf_1 (png_ptr, info_ptr, &num_exif, &exif);
213
+ }
214
+
215
+ if (exif && num_exif > 0 ) {
216
+ return fetch_exif_orientation (exif, num_exif);
217
+ }
218
+ #endif // #ifdef PNG_eXIf_SUPPORTED
219
+ return -1 ;
220
+ }
221
+ #else
222
+ inline int fetch_png_exif_orientation (j_decompress_ptr cinfo) {
223
+ return -1 ;
184
224
}
225
+ #endif // #if PNG_FOUND
185
226
186
227
constexpr uint16_t IMAGE_ORIENTATION_TL = 1 ; // normal orientation
187
228
constexpr uint16_t IMAGE_ORIENTATION_TR = 2 ; // needs horizontal flip
@@ -222,5 +263,3 @@ inline torch::Tensor exif_orientation_transform(
222
263
} // namespace exif_private
223
264
} // namespace image
224
265
} // namespace vision
225
-
226
- #endif
0 commit comments