1 /*
2  * Copyright 2014 The Android Open Source Project
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 <img_utils/TiffIfd.h>
18 #include <img_utils/TiffHelpers.h>
19 #include <img_utils/TiffEntry.h>
20 
21 #include <utils/Errors.h>
22 #include <utils/StrongPointer.h>
23 #include <utils/Vector.h>
24 
25 namespace android {
26 namespace img_utils {
27 
~TiffEntry()28 TiffEntry::~TiffEntry() {}
29 
30 /**
31  * Specialize for each valid type, including sub-IFDs.
32  *
33  * Values with types other than the ones given here should not compile.
34  */
35 
36 template<>
forceValidType(TagType type,const sp<TiffIfd> * value)37 const sp<TiffIfd>* TiffEntry::forceValidType<sp<TiffIfd> >(TagType type, const sp<TiffIfd>* value) {
38     if (type == LONG) {
39         return value;
40     }
41     ALOGE("%s: Value of type 'ifd' is not valid for tag with TIFF type %d.",
42             __FUNCTION__, type);
43     return NULL;
44 }
45 
46 template<>
forceValidType(TagType type,const uint8_t * value)47 const uint8_t* TiffEntry::forceValidType<uint8_t>(TagType type, const uint8_t* value) {
48     if (type == BYTE || type == ASCII || type == UNDEFINED) {
49         return value;
50     }
51     ALOGE("%s: Value of type 'uint8_t' is not valid for tag with TIFF type %d.",
52             __FUNCTION__, type);
53     return NULL;
54 }
55 
56 template<>
forceValidType(TagType type,const int8_t * value)57 const int8_t* TiffEntry::forceValidType<int8_t>(TagType type, const int8_t* value) {
58     if (type == SBYTE || type == ASCII || type == UNDEFINED) {
59         return value;
60     }
61     ALOGE("%s: Value of type 'int8_t' is not valid for tag with TIFF type %d.",
62             __FUNCTION__, type);
63     return NULL;
64 }
65 
66 template<>
forceValidType(TagType type,const uint16_t * value)67 const uint16_t* TiffEntry::forceValidType<uint16_t>(TagType type, const uint16_t* value) {
68     if (type == SHORT) {
69         return value;
70     }
71     ALOGE("%s: Value of type 'uint16_t' is not valid for tag with TIFF type %d.",
72             __FUNCTION__, type);
73     return NULL;
74 }
75 
76 template<>
forceValidType(TagType type,const int16_t * value)77 const int16_t* TiffEntry::forceValidType<int16_t>(TagType type, const int16_t* value) {
78     if (type == SSHORT) {
79         return value;
80     }
81     ALOGE("%s: Value of type 'int16_t' is not valid for tag with TIFF type %d.",
82             __FUNCTION__, type);
83     return NULL;
84 }
85 
86 template<>
forceValidType(TagType type,const uint32_t * value)87 const uint32_t* TiffEntry::forceValidType<uint32_t>(TagType type, const uint32_t* value) {
88     if (type == LONG || type == RATIONAL) {
89         return value;
90     }
91     ALOGE("%s: Value of type 'uint32_t' is not valid for tag with TIFF type %d.",
92             __FUNCTION__, type);
93     return NULL;
94 }
95 
96 template<>
forceValidType(TagType type,const int32_t * value)97 const int32_t* TiffEntry::forceValidType<int32_t>(TagType type, const int32_t* value) {
98     if (type == SLONG || type == SRATIONAL) {
99         return value;
100     }
101     ALOGE("%s: Value of type 'int32_t' is not valid for tag with TIFF type %d.",
102             __FUNCTION__, type);
103     return NULL;
104 }
105 
106 template<>
forceValidType(TagType type,const double * value)107 const double* TiffEntry::forceValidType<double>(TagType type, const double* value) {
108     if (type == DOUBLE) {
109         return value;
110     }
111     ALOGE("%s: Value of type 'double' is not valid for tag with TIFF type %d.",
112             __FUNCTION__, type);
113     return NULL;
114 }
115 
116 template<>
forceValidType(TagType type,const float * value)117 const float* TiffEntry::forceValidType<float>(TagType type, const float* value) {
118     if (type == FLOAT) {
119         return value;
120     }
121     ALOGE("%s: Value of type 'float' is not valid for tag with TIFF type %d.",
122             __FUNCTION__, type);
123     return NULL;
124 }
125 
toString() const126 String8 TiffEntry::toString() const {
127     String8 output;
128     uint32_t count = getCount();
129     output.appendFormat("[id: %x, type: %d, count: %u, value: '", getTag(), getType(), count);
130 
131     size_t cappedCount = count;
132     if (count > MAX_PRINT_STRING_LENGTH) {
133         cappedCount = MAX_PRINT_STRING_LENGTH;
134     }
135 
136     TagType type = getType();
137     switch (type) {
138         case UNDEFINED:
139         case BYTE: {
140             const uint8_t* typed_data = getData<uint8_t>();
141             for (size_t i = 0; i < cappedCount; ++i) {
142                 output.appendFormat("%u ", typed_data[i]);
143             }
144             break;
145         }
146         case ASCII: {
147             const char* typed_data = reinterpret_cast<const char*>(getData<uint8_t>());
148             size_t len = count;
149             if (count > MAX_PRINT_STRING_LENGTH) {
150                  len = MAX_PRINT_STRING_LENGTH;
151             }
152             output.append(typed_data, len);
153             break;
154         }
155         case SHORT: {
156             const uint16_t* typed_data = getData<uint16_t>();
157             for (size_t i = 0; i < cappedCount; ++i) {
158                 output.appendFormat("%u ", typed_data[i]);
159             }
160             break;
161         }
162         case LONG: {
163             const uint32_t* typed_data = getData<uint32_t>();
164             for (size_t i = 0; i < cappedCount; ++i) {
165                 output.appendFormat("%u ", typed_data[i]);
166             }
167             break;
168         }
169         case RATIONAL: {
170             const uint32_t* typed_data = getData<uint32_t>();
171             cappedCount <<= 1;
172             for (size_t i = 0; i < cappedCount; i+=2) {
173                 output.appendFormat("%u/%u ", typed_data[i], typed_data[i + 1]);
174             }
175             break;
176         }
177         case SBYTE: {
178             const int8_t* typed_data = getData<int8_t>();
179             for (size_t i = 0; i < cappedCount; ++i) {
180                 output.appendFormat("%d ", typed_data[i]);
181             }
182             break;
183         }
184         case SSHORT: {
185             const int16_t* typed_data = getData<int16_t>();
186             for (size_t i = 0; i < cappedCount; ++i) {
187                 output.appendFormat("%d ", typed_data[i]);
188             }
189             break;
190         }
191         case SLONG: {
192             const int32_t* typed_data = getData<int32_t>();
193             for (size_t i = 0; i < cappedCount; ++i) {
194                 output.appendFormat("%d ", typed_data[i]);
195             }
196             break;
197         }
198         case SRATIONAL: {
199             const int32_t* typed_data = getData<int32_t>();
200             cappedCount <<= 1;
201             for (size_t i = 0; i < cappedCount; i+=2) {
202                 output.appendFormat("%d/%d ", typed_data[i], typed_data[i + 1]);
203             }
204             break;
205         }
206         case FLOAT: {
207             const float* typed_data = getData<float>();
208             for (size_t i = 0; i < cappedCount; ++i) {
209                 output.appendFormat("%f ", typed_data[i]);
210             }
211             break;
212         }
213         case DOUBLE: {
214             const double* typed_data = getData<double>();
215             for (size_t i = 0; i < cappedCount; ++i) {
216                 output.appendFormat("%f ", typed_data[i]);
217             }
218             break;
219         }
220         default: {
221             output.append("unknown type ");
222             break;
223         }
224     }
225 
226     if (count > MAX_PRINT_STRING_LENGTH) {
227         output.append("...");
228     }
229     output.append("']");
230     return output;
231 }
232 
233 } /*namespace img_utils*/
234 } /*namespace android*/
235