• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2020 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "minddata/dataset/kernels/image/exif_utils.h"
18 
19 #include <algorithm>
20 #include <cstdint>
21 
22 #define UNKNOW_ORIENTATION 0
23 
24 namespace mindspore {
25 namespace dataset {
26 
27 template <typename T>
28 T parse_bytes(const uint8_t *buf, bool intel_align);
29 
30 template <>
parse_bytes(const uint8_t * buf,bool intel_align)31 uint8_t parse_bytes(const uint8_t *buf, bool intel_align) {
32   return *buf;
33 }
34 
35 template <>
parse_bytes(const uint8_t * buf,bool intel_align)36 uint16_t parse_bytes(const uint8_t *buf, bool intel_align) {
37   if (buf == nullptr) {
38     return 0;
39   }
40 
41   uint16_t res = 0;
42   if (intel_align) {
43     res = (static_cast<uint16_t>(buf[1]) << 8) | buf[0];
44   } else {
45     res = (static_cast<uint16_t>(buf[0]) << 8) | buf[1];
46   }
47   return res;
48 }
49 
50 template <>
parse_bytes(const uint8_t * buf,bool intel_align)51 uint32_t parse_bytes(const uint8_t *buf, bool intel_align) {
52   if (buf == nullptr) {
53     return 0;
54   }
55 
56   uint32_t res = 0;
57   if (intel_align) {
58     res = (static_cast<uint32_t>(buf[3]) << 24) | (static_cast<uint32_t>(buf[2]) << 16) |
59           (static_cast<uint32_t>(buf[1]) << 8) | buf[0];
60   } else {
61     res = (static_cast<uint32_t>(buf[0]) << 24) | (static_cast<uint32_t>(buf[1]) << 16) |
62           (static_cast<uint32_t>(buf[2]) << 8) | buf[3];
63   }
64   return res;
65 }
66 
parseExif(const uint8_t * buf,uint32_t len)67 int parseExif(const uint8_t *buf, uint32_t len) {
68   bool intel_align = true;
69   uint32_t offset = 0;
70   if (!buf || len < 6) {
71     return UNKNOW_ORIENTATION;
72   }
73 
74   if (!std::equal(buf, buf + 6, "Exif\0\0")) {
75     return UNKNOW_ORIENTATION;
76   }
77   offset += 6;
78 
79   if (offset + 8 > len) {
80     return UNKNOW_ORIENTATION;
81   }
82   if (buf[offset] == 'I' && buf[offset + 1] == 'I') {
83     intel_align = true;
84   } else if (buf[offset] == 'M' && buf[offset + 1] == 'M') {
85     intel_align = false;
86   } else {
87     return UNKNOW_ORIENTATION;
88   }
89 
90   offset += 2;
91   if (parse_bytes<uint16_t>(buf + offset, intel_align) != 0x2a) {
92     return UNKNOW_ORIENTATION;
93   }
94   offset += 2;
95   uint32_t first_ifd_offset = parse_bytes<uint32_t>(buf + offset, intel_align);
96   offset += first_ifd_offset - 4;
97   if (offset >= len || offset + 2 > len) {
98     return UNKNOW_ORIENTATION;
99   }
100 
101   int num_entries = parse_bytes<uint16_t>(buf + offset, intel_align);
102   if (offset + 6 + 12 * num_entries > len) {
103     return UNKNOW_ORIENTATION;
104   }
105   offset += 2;
106   while (num_entries > 0) {
107     uint16_t tag = parse_bytes<uint16_t>(buf + offset, intel_align);
108     if (tag == 0x112) {
109       uint16_t format = parse_bytes<uint16_t>(buf + offset + 2, intel_align);
110       uint32_t length = parse_bytes<uint32_t>(buf + offset + 4, intel_align);
111       if (format == 3 && length) {
112         uint16_t orient = parse_bytes<uint16_t>(buf + offset + 8, intel_align);
113         return static_cast<int>(orient);
114       }
115     }
116     offset += 12;
117     num_entries--;
118   }
119   return UNKNOW_ORIENTATION;
120 }
121 
parseOrientation(const unsigned char * data,unsigned len)122 int ExifInfo::parseOrientation(const unsigned char *data, unsigned len) {
123   if (!data || len < 4) return UNKNOW_ORIENTATION;
124 
125   if (data[0] != 0xFF || data[1] != 0xD8) return UNKNOW_ORIENTATION;
126 
127   while (len > 2) {
128     if (data[len - 1] == 0xD9 && data[len - 2] == 0xFF) break;
129     len--;
130   }
131   if (len <= 2) return UNKNOW_ORIENTATION;
132 
133   unsigned int offset = 0;
134   for (; offset < len - 1; offset++) {
135     if (data[offset] == 0xFF && data[offset + 1] == 0xE1) break;
136   }
137   if (offset + 4 > len) return UNKNOW_ORIENTATION;
138   offset += 2;
139   uint16_t section_length = parse_bytes<uint16_t>(data + offset, false);
140   if (offset + section_length > len || section_length < 16) return UNKNOW_ORIENTATION;
141   offset += 2;
142 
143   return parseExif(data + offset, len - offset);
144 }
145 }  // namespace dataset
146 }  // namespace mindspore
147