|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "ifdgeneral.h" |
|
17 #include "ifdgeneralentry.h" |
|
18 #include "ExifTagDescriptions.h" |
|
19 #include "exifreaderwriter.h" |
|
20 #include "ExifTagHelper.h" |
|
21 #include <bafl/sysutil.h> |
|
22 |
|
23 // Number of consecutive invalid IFD entries that may appear before the whole IFD is considered corrupt |
|
24 // This value is set in the ExifLibStatic.mmp file, the default is 7. |
|
25 const TUint KMaxNumberOfConsecInvalidEntries = SYMBIAN_ICL_EXIF_CONSEC_INVALID_TAGS; |
|
26 |
|
27 CIfdGeneral::CIfdGeneral(const TInt aIfdNumber, const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
28 : iIfdNumber(aIfdNumber) |
|
29 , iIntel(aIntel) |
|
30 , iOffsetToIfd(aOffsetToIfd) |
|
31 , iBase(aBase) |
|
32 , iExifDataLength(aExifDataLength) |
|
33 { |
|
34 } |
|
35 |
|
36 CIfdGeneral::~CIfdGeneral() |
|
37 { |
|
38 iIfdEntries.ResetAndDestroy(); |
|
39 } |
|
40 |
|
41 void CIfdGeneral::ConstructL() |
|
42 { |
|
43 if(iBase) |
|
44 { |
|
45 // read the entries from the data block |
|
46 AddAllIfdEntriesL(); |
|
47 } |
|
48 else |
|
49 { |
|
50 // create default entries |
|
51 SetupDirectoryEntriesL(); |
|
52 } |
|
53 } |
|
54 |
|
55 // Alters a directory in a given IFD - used when the directory is known to exist |
|
56 // (i.e. for mandatory entries) which are set/created upon initialisation. |
|
57 TInt CIfdGeneral::SetParam8(const TUint aTag, HBufC8* aParam) |
|
58 { |
|
59 ASSERT(aParam!=NULL); |
|
60 |
|
61 // find the entry with the required tag. |
|
62 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
63 { |
|
64 if(aTag == iIfdEntries[i]->Tag()) |
|
65 { |
|
66 // Found the tag. |
|
67 // May be undefined type or ascii type. |
|
68 if(iIfdEntries[i]->IsStringFormat()) |
|
69 { |
|
70 //pass in ifd number as the same ascii tag may be in more than one ifd |
|
71 return iIfdEntries[i]->UpdateString(aParam); |
|
72 } |
|
73 else if(iIfdEntries[i]->IsUndefinedFormat()) |
|
74 { |
|
75 return iIfdEntries[i]->UpdateData(aParam->Length(), aParam->Des().Ptr()); |
|
76 } |
|
77 else if (iIfdEntries[i]->Format()==EByte) |
|
78 { |
|
79 //we need to support byte entries too as they are Param8 |
|
80 return iIfdEntries[i]->UpdateData(aParam->Length(), aParam->Des().Ptr()); |
|
81 } |
|
82 } |
|
83 } |
|
84 return KErrNotSupported; |
|
85 } |
|
86 |
|
87 TInt CIfdGeneral::SetParam16(const TUint aTag, HBufC16* aParam) |
|
88 { |
|
89 ASSERT(aParam!=NULL); |
|
90 |
|
91 // find the entry with the required tag. |
|
92 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
93 { |
|
94 if(aTag == iIfdEntries[i]->Tag()) |
|
95 { |
|
96 // Found the tag. |
|
97 HBufC8* extendedData=NULL; |
|
98 TRAPD(err, extendedData=TExifTagHelper::CreateUnicodePrefixedBufferL(*aParam)); |
|
99 if(err!=KErrNone) |
|
100 { |
|
101 return KErrNoMemory; |
|
102 } |
|
103 TInt componentCount=extendedData->Length(); |
|
104 TInt updateErr = iIfdEntries[i]->UpdateData(componentCount, extendedData->Des().Ptr()); |
|
105 delete extendedData; |
|
106 return updateErr; |
|
107 } |
|
108 } |
|
109 return KErrNotSupported; |
|
110 } |
|
111 |
|
112 TInt CIfdGeneral::SetIntegerParam(const TUint aTag, const TInt aParam) |
|
113 { |
|
114 // find the entry with the required tag. |
|
115 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
116 { |
|
117 if(aTag == iIfdEntries[i]->Tag()) |
|
118 { |
|
119 // Found the tag. |
|
120 return iIfdEntries[i]->UpdateInteger(aParam); |
|
121 } |
|
122 } |
|
123 return KErrNotSupported; |
|
124 } |
|
125 |
|
126 TInt CIfdGeneral::SetShortParam(const TUint aTag, const TUint16 aParam) |
|
127 { |
|
128 // find the entry with the required tag. |
|
129 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
130 { |
|
131 if(aTag == iIfdEntries[i]->Tag()) |
|
132 { |
|
133 // Found the tag. |
|
134 return iIfdEntries[i]->UpdateShort(aParam); |
|
135 } |
|
136 } |
|
137 return KErrNotSupported; |
|
138 } |
|
139 |
|
140 TInt CIfdGeneral::SetRationalParam(const TUint aTag, const TInt aNumerator, const TInt aDenominator) |
|
141 { |
|
142 // find the entry with the required tag. |
|
143 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
144 { |
|
145 if(aTag == iIfdEntries[i]->Tag()) |
|
146 { |
|
147 // Found the tag. |
|
148 return iIfdEntries[i]->UpdateRational(aNumerator, aDenominator); |
|
149 } |
|
150 } |
|
151 return KErrNotSupported; |
|
152 } |
|
153 |
|
154 |
|
155 /* |
|
156 Add a directory in a given IFD - used for the optional directories, since these are not |
|
157 set/created upon initialisation. Must check for existence of the tag along with validity |
|
158 of adding the tag to this particular IFD. |
|
159 */ |
|
160 void CIfdGeneral::AddParam8L(const TUint aTag, const TUint aFormat, const TUint aComponentCount, HBufC8* aParam) |
|
161 { |
|
162 ASSERT(aParam!=NULL); |
|
163 |
|
164 TInt err = KErrNotSupported; |
|
165 |
|
166 // Check that aTag belongs in this IFD. |
|
167 TInt index = GetTagIndex(aTag); |
|
168 if(index != KErrNotFound) |
|
169 { |
|
170 //The length is checked, but really it should be done in the IfdEntry |
|
171 TUint paramLength=aParam->Length(); |
|
172 const TUint* tag = GetTagInformation(index); |
|
173 TUint requiredComponentCount=tag[EComponentCountValue]; |
|
174 TBool legal=EFalse; |
|
175 if((requiredComponentCount==0) || (aFormat!=EAscii)) |
|
176 { |
|
177 //Either this tag can be of any length (so no further length checks needed) |
|
178 //or it is not ASCII, which means it simply has to be at least as long |
|
179 //as the required length |
|
180 legal=(paramLength >= requiredComponentCount * KDataFormatSize[aFormat]); |
|
181 } |
|
182 else |
|
183 { |
|
184 //We have a fixed length ASCII string. For such strings we must |
|
185 //consider NULL termination. Considering that we add the NULL if the |
|
186 //user forgets to add it for other tags, we should do it here as well |
|
187 //to be consistent. |
|
188 if (paramLength==requiredComponentCount) |
|
189 { |
|
190 //The string is already of the max length so it is only legal if it is NULL |
|
191 //terminated |
|
192 legal=((*aParam)[paramLength-1] == KNullCharacter); |
|
193 } |
|
194 else if (paramLength==requiredComponentCount-1) |
|
195 { |
|
196 //The string is one less than the required length. If it is NULL terminated already, |
|
197 //then the string is too short (illegal). If it is not NULL terminated, we let it |
|
198 //pass anyway and CEncoderIfdEntry software will add the NULL. |
|
199 legal=((*aParam)[paramLength-1] != KNullCharacter); |
|
200 } |
|
201 else |
|
202 { |
|
203 //Strings that pass the first two checks are only legal if exactly the |
|
204 //required length. |
|
205 legal=(paramLength == requiredComponentCount); |
|
206 } |
|
207 } |
|
208 if (legal) |
|
209 { |
|
210 // Entry is legal, so add entry. |
|
211 const TUint8* valueOffset = aParam->Des().Ptr(); |
|
212 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, valueOffset, this); |
|
213 iIfdEntries.AppendL(entry); |
|
214 CleanupStack::Pop(entry); |
|
215 err = KErrNone; |
|
216 } |
|
217 else |
|
218 { |
|
219 err = KErrNotSupported; |
|
220 } |
|
221 } |
|
222 User::LeaveIfError(err); |
|
223 } |
|
224 |
|
225 void CIfdGeneral::AddParam16L(const TUint aTag, const TUint aFormat, const TUint /*aComponentCount*/, HBufC16* aParam) |
|
226 { |
|
227 ASSERT(aParam!=NULL); |
|
228 |
|
229 TInt err = KErrNotSupported; |
|
230 |
|
231 // Check that aTag belongs in this IFD. |
|
232 TInt index = GetTagIndex(aTag); |
|
233 if(index != KErrNotFound) |
|
234 { |
|
235 TUint paramLength=aParam->Length(); |
|
236 const TUint* tag = GetTagInformation(index); |
|
237 if( (paramLength >= tag[EComponentCountValue] * KDataFormatSize[aFormat])) |
|
238 { |
|
239 |
|
240 // Entry is legal, so add entry. |
|
241 // Must add UNICODE\0 to start of data. |
|
242 TInt size = aParam->Length()*2 + KUnicode().Length(); |
|
243 TUint8* data = static_cast<TUint8*>(User::AllocL(size)); |
|
244 CleanupStack::PushL(data); |
|
245 |
|
246 Mem::Copy(data, KUnicode().Ptr(), KUnicode().Length()); |
|
247 Mem::Copy(data+KUnicode().Length(), aParam->Des().Ptr(), aParam->Length()*2); |
|
248 |
|
249 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, size, data, this); |
|
250 iIfdEntries.AppendL(entry); |
|
251 CleanupStack::Pop(entry); |
|
252 CleanupStack::PopAndDestroy(data); |
|
253 err = KErrNone; |
|
254 } |
|
255 } |
|
256 User::LeaveIfError(err); |
|
257 } |
|
258 |
|
259 |
|
260 void CIfdGeneral::AddIntegerParamL(const TUint aTag, const TUint aFormat, const TUint aComponentCount, TInt aParam) |
|
261 { |
|
262 TInt err = KErrNotSupported; |
|
263 |
|
264 // Check that aTag belongs in this IFD. |
|
265 if(FindTag(aTag)) |
|
266 { |
|
267 // Entry is legal, so add entry. |
|
268 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, reinterpret_cast<const TUint8*>(&aParam), this); |
|
269 iIfdEntries.AppendL(entry); |
|
270 CleanupStack::Pop(entry); |
|
271 err = KErrNone; |
|
272 } |
|
273 User::LeaveIfError(err); |
|
274 } |
|
275 |
|
276 void CIfdGeneral::AddShortParamL(const TUint aTag, const TUint aFormat, const TUint aComponentCount, TUint16 aParam) |
|
277 { |
|
278 TInt err = KErrNotSupported; |
|
279 |
|
280 // Check that aTag belongs in this IFD. |
|
281 if(FindTag(aTag)) |
|
282 { |
|
283 // Entry is legal, so add entry. |
|
284 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, reinterpret_cast<const TUint8*>(&aParam),this); |
|
285 iIfdEntries.AppendL(entry); |
|
286 CleanupStack::Pop(entry); |
|
287 err = KErrNone; |
|
288 } |
|
289 User::LeaveIfError(err); |
|
290 } |
|
291 |
|
292 void CIfdGeneral::AddRationalParamL(const TUint aTag, const TUint aFormat, const TUint aComponentCount, const TInt aNumerator, const TInt aDenominator) |
|
293 { |
|
294 TInt err = KErrNotSupported; |
|
295 |
|
296 // Check that aTag belongs in this IFD. |
|
297 if(FindTag(aTag)) |
|
298 { |
|
299 TUint8* valueOffset = static_cast<TUint8*>(User::AllocL(KSizeOfRational)); |
|
300 CleanupStack::PushL(valueOffset); |
|
301 |
|
302 // Entry is legal, so add entry. |
|
303 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, valueOffset, this); |
|
304 User::LeaveIfError(entry->UpdateRational(aNumerator, aDenominator)); |
|
305 iIfdEntries.AppendL(entry); |
|
306 CleanupStack::Pop(entry); |
|
307 CleanupStack::PopAndDestroy(valueOffset); |
|
308 |
|
309 err = KErrNone; |
|
310 } |
|
311 if(err != KErrNone) |
|
312 { |
|
313 User::LeaveIfError(err); |
|
314 } |
|
315 return; |
|
316 } |
|
317 |
|
318 |
|
319 |
|
320 void CIfdGeneral::SetIntegerArrayParamL(const TUint aTag, const CArrayFix<TInt>& aParam) |
|
321 { |
|
322 TInt err = KErrNotSupported; |
|
323 |
|
324 // find the entry with the required tag. |
|
325 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
326 { |
|
327 if(aTag == iIfdEntries[i]->Tag()) |
|
328 { |
|
329 // Found the tag. |
|
330 HBufC8* ptr = HBufC8::NewL(aParam.Count()*K32BitIntegerByteCount/K8BitIntegerByteCount); |
|
331 CleanupStack::PushL(ptr); |
|
332 const TUint8* bytePtr = ptr->Des().Ptr(); |
|
333 TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr)); |
|
334 for(TInt j = 0; j < aParam.Count(); j++) |
|
335 { |
|
336 TInt value = aParam.At(j); |
|
337 dataPtr[j] = value; |
|
338 } |
|
339 User::LeaveIfError(iIfdEntries[i]->UpdateData(aParam.Count(), bytePtr)); |
|
340 CleanupStack::PopAndDestroy(ptr); |
|
341 err = KErrNone; |
|
342 } |
|
343 } |
|
344 User::LeaveIfError(err); |
|
345 } |
|
346 |
|
347 void CIfdGeneral::AddIntegerArrayParamL(const TUint aTag, const TUint aFormat, const CArrayFix<TInt>& aParam) |
|
348 { |
|
349 TInt err = KErrNotSupported; |
|
350 |
|
351 // Check that aTag belongs in this IFD. |
|
352 if(FindTag(aTag)) |
|
353 { |
|
354 // Entry is legal, so add entry. |
|
355 HBufC8* ptr = HBufC8::NewL(aParam.Count()*K32BitIntegerByteCount/K8BitIntegerByteCount); |
|
356 CleanupStack::PushL(ptr); |
|
357 const TUint8* bytePtr = ptr->Des().Ptr(); |
|
358 TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr)); |
|
359 for(TInt i = 0; i < aParam.Count(); i++) |
|
360 { |
|
361 TInt value = aParam.At(i); |
|
362 dataPtr[i] = value; |
|
363 } |
|
364 |
|
365 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aParam.Count(), bytePtr, this); |
|
366 iIfdEntries.AppendL(entry); |
|
367 CleanupStack::Pop(entry); |
|
368 CleanupStack::PopAndDestroy(ptr); |
|
369 err = KErrNone; |
|
370 } |
|
371 User::LeaveIfError(err); |
|
372 } |
|
373 |
|
374 void CIfdGeneral::AddRationalArrayParamL(const TUint aTag, const TUint aFormat, const CArrayFix<TRational>& aParam) |
|
375 { |
|
376 TInt err = KErrNotSupported; |
|
377 // Check that aTag belongs in this IFD. |
|
378 if(FindTag(aTag)) |
|
379 { |
|
380 // Entry is legal, so add entry. |
|
381 HBufC8* ptr = HBufC8::NewL((aParam.Count()*2) * K32BitIntegerByteCount); |
|
382 CleanupStack::PushL(ptr); |
|
383 const TUint8* bytePtr = ptr->Des().Ptr(); |
|
384 TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr)); |
|
385 TInt ptrInc = 0; |
|
386 for(TInt i = 0; i < aParam.Count(); i++) |
|
387 { |
|
388 TInt numer = (aParam.At(i)).iNumerator; |
|
389 TInt denom = (aParam.At(i)).iDenominator; |
|
390 dataPtr[ptrInc++] = numer; |
|
391 dataPtr[ptrInc++] = denom; |
|
392 } |
|
393 |
|
394 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aParam.Count(), bytePtr, this); |
|
395 iIfdEntries.AppendL(entry); |
|
396 CleanupStack::Pop(entry); |
|
397 CleanupStack::PopAndDestroy(ptr); |
|
398 err = KErrNone; |
|
399 } |
|
400 User::LeaveIfError(err); |
|
401 } |
|
402 |
|
403 void CIfdGeneral::SetRationalArrayParamL(const TUint aTag, const CArrayFix<TRational>& aParam) |
|
404 { |
|
405 TInt err = KErrNotSupported; |
|
406 // find the entry with the required tag. |
|
407 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
408 { |
|
409 if(aTag == iIfdEntries[i]->Tag()) |
|
410 { |
|
411 // Found the tag. |
|
412 HBufC8* ptr = HBufC8::NewL((aParam.Count()*2) * K32BitIntegerByteCount); |
|
413 CleanupStack::PushL(ptr); |
|
414 const TUint8* bytePtr = ptr->Des().Ptr(); |
|
415 TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr)); |
|
416 TInt ptrInc = 0; |
|
417 for(TInt j = 0; j < aParam.Count(); j++) |
|
418 { |
|
419 TInt numer = (aParam.At(j)).iNumerator; |
|
420 TInt denom = (aParam.At(j)).iDenominator; |
|
421 dataPtr[ptrInc++] = numer; |
|
422 dataPtr[ptrInc++] = denom; |
|
423 } |
|
424 User::LeaveIfError(iIfdEntries[i]->UpdateData(aParam.Count(), bytePtr)); |
|
425 CleanupStack::PopAndDestroy(ptr); |
|
426 err = KErrNone; |
|
427 } |
|
428 } |
|
429 User::LeaveIfError(err); |
|
430 } |
|
431 |
|
432 |
|
433 void CIfdGeneral::AddShortArrayParamL(const TUint aTag, const TUint aFormat, const CArrayFix<TUint16>& aParam) |
|
434 { |
|
435 TInt err = KErrNotSupported; |
|
436 // Check that aTag belongs in this IFD. |
|
437 if(FindTag(aTag)) |
|
438 { |
|
439 // Entry is legal, so add entry. |
|
440 HBufC8* ptr = HBufC8::NewL(aParam.Count()*K16BitIntegerByteCount/K8BitIntegerByteCount); |
|
441 CleanupStack::PushL(ptr); |
|
442 const TUint8* bytePtr = ptr->Des().Ptr(); |
|
443 TInt16* dataPtr = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(bytePtr)); |
|
444 for(TInt i = 0; i < aParam.Count(); i++) |
|
445 { |
|
446 TInt value = aParam.At(i); |
|
447 dataPtr[i] = value; |
|
448 } |
|
449 |
|
450 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aParam.Count(), bytePtr, this); |
|
451 iIfdEntries.AppendL(entry); |
|
452 CleanupStack::Pop(entry); |
|
453 CleanupStack::PopAndDestroy(ptr); |
|
454 err = KErrNone; |
|
455 } |
|
456 User::LeaveIfError(err); |
|
457 } |
|
458 |
|
459 void CIfdGeneral::SetShortArrayParamL(const TUint aTag, const CArrayFix<TUint16>& aParam) |
|
460 { |
|
461 TInt err = KErrNotSupported; |
|
462 // Find the entry with the required tag. |
|
463 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
464 { |
|
465 if(aTag == iIfdEntries[i]->Tag()) |
|
466 { |
|
467 HBufC8* ptr = HBufC8::NewL(aParam.Count()*K16BitIntegerByteCount/K8BitIntegerByteCount); |
|
468 CleanupStack::PushL(ptr); |
|
469 const TUint8* bytePtr = ptr->Des().Ptr(); |
|
470 TInt16* dataPtr = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(bytePtr)); |
|
471 for(TInt j = 0; j < aParam.Count(); j++) |
|
472 { |
|
473 TInt value = aParam.At(j); |
|
474 dataPtr[j] = value; |
|
475 } |
|
476 User::LeaveIfError(iIfdEntries[i]->UpdateData(aParam.Count(), bytePtr)); |
|
477 CleanupStack::PopAndDestroy(ptr); |
|
478 err = KErrNone; |
|
479 } |
|
480 } |
|
481 User::LeaveIfError(err); |
|
482 } |
|
483 |
|
484 TInt CIfdGeneral::GetIntegerParam(const TUint aTag, TInt& aParam) const |
|
485 { |
|
486 TInt entry = LocateEntry(aTag); |
|
487 if(entry == KErrNotFound) |
|
488 { |
|
489 return KErrNotFound; |
|
490 } |
|
491 |
|
492 // Check that we are dealing with an Integer format. |
|
493 switch(iIfdEntries[entry]->Format()) |
|
494 { |
|
495 case (EUnsignedLong): |
|
496 case (ESignedLong): |
|
497 break; |
|
498 default: |
|
499 return KErrArgument; |
|
500 } |
|
501 |
|
502 // Check the size. |
|
503 TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
504 if(totalSize > KSizeOfValueOffsetField) |
|
505 { |
|
506 // Data is offset, so we are dealing with more than one integer, so this function cannot deal with it. |
|
507 return KErrArgument; |
|
508 } |
|
509 |
|
510 aParam = iIfdEntries[entry]->ValueOffset(); |
|
511 return KErrNone; |
|
512 } |
|
513 |
|
514 |
|
515 |
|
516 |
|
517 TInt CIfdGeneral::GetShortParam(const TUint aTag, TUint16& aParam) const |
|
518 { |
|
519 TInt entry = LocateEntry(aTag); |
|
520 if(entry == KErrNotFound) |
|
521 { |
|
522 return KErrNotFound; |
|
523 } |
|
524 |
|
525 // Check that we are dealing with an short format. |
|
526 if(iIfdEntries[entry]->Format() != EUnsignedShort) |
|
527 { |
|
528 return KErrArgument; |
|
529 } |
|
530 |
|
531 // Check the size. |
|
532 TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
533 |
|
534 // Since 2 shorts could be in 4 byte field, we only return one! |
|
535 if(totalSize > KSizeOfValueOffsetField / 2) |
|
536 { |
|
537 // Data is offset, so we are dealing with more than one integer, so this function cannot deal with it. |
|
538 return KErrArgument; |
|
539 } |
|
540 |
|
541 aParam = iIfdEntries[entry]->ValueOffset(); |
|
542 |
|
543 return KErrNone; |
|
544 } |
|
545 |
|
546 TInt CIfdGeneral::GetRationalParam(const TUint aTag, TInt& aNumer, TInt& aDenom) const |
|
547 { |
|
548 TInt entry = LocateEntry(aTag); |
|
549 if(entry == KErrNotFound) |
|
550 { |
|
551 return KErrNotFound; |
|
552 } |
|
553 |
|
554 // Check that we are dealing with an rational format. |
|
555 switch(iIfdEntries[entry]->Format()) |
|
556 { |
|
557 case (EUnsignedRational): |
|
558 case (ESignedRational): |
|
559 break; |
|
560 default: |
|
561 return KErrArgument; |
|
562 } |
|
563 |
|
564 // Check the size. |
|
565 TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
566 |
|
567 // A single rational datum is 8 bytes, so we only deal with single values here. |
|
568 if(totalSize > KSizeOfValueOffsetField * 2) |
|
569 { |
|
570 return KErrArgument; |
|
571 } |
|
572 |
|
573 const TUint8* rationalData = iIfdEntries[entry]->ActualValue(); |
|
574 if(!rationalData) |
|
575 { |
|
576 return KErrArgument; |
|
577 } |
|
578 Mem::Copy(&aNumer, rationalData, sizeof(aNumer)); |
|
579 Mem::Copy(&aDenom, rationalData+sizeof(aNumer), sizeof(aDenom)); |
|
580 return KErrNone; |
|
581 } |
|
582 |
|
583 TInt CIfdGeneral::GetParam8(const TUint aTag, HBufC8*& aParam) const |
|
584 { |
|
585 TInt entry = LocateEntry(aTag); |
|
586 if(entry == KErrNotFound) |
|
587 { |
|
588 return KErrNotFound; |
|
589 } |
|
590 |
|
591 // Check that we are dealing with correct format. |
|
592 TUint format = iIfdEntries[entry]->Format(); |
|
593 switch(format) |
|
594 { |
|
595 case (EByte): |
|
596 case (EAscii): |
|
597 case (EUndefined): |
|
598 break; |
|
599 default: |
|
600 return KErrArgument; |
|
601 } |
|
602 |
|
603 // Check the size. |
|
604 TUint totalSize = iIfdEntries[entry]->ComponentCount(); |
|
605 |
|
606 delete aParam; |
|
607 aParam = HBufC8::New(totalSize); |
|
608 if(aParam == NULL) |
|
609 { |
|
610 return KErrNoMemory; |
|
611 } |
|
612 |
|
613 _LIT8(KStringFormat, "%s"); |
|
614 if(totalSize > KSizeOfValueOffsetField) |
|
615 { |
|
616 const TUint8* theData=iIfdEntries[entry]->ActualValue(); |
|
617 if(!theData) |
|
618 { |
|
619 return KErrArgument; |
|
620 } |
|
621 |
|
622 if (aTag == KTag8298[ETagValue]) |
|
623 { |
|
624 //the copyright tag is a special case as it can have null mid string |
|
625 if (*(theData+totalSize-1) == NULL) |
|
626 { |
|
627 //we remove null at the end for consistency |
|
628 totalSize--; |
|
629 } |
|
630 aParam->Des().Copy(theData, totalSize); |
|
631 } |
|
632 else if (format == EAscii) |
|
633 { |
|
634 aParam->Des().Format(KStringFormat, theData); |
|
635 } |
|
636 else |
|
637 { |
|
638 aParam->Des().Copy(theData, totalSize); |
|
639 } |
|
640 } |
|
641 else if (totalSize>0) |
|
642 { |
|
643 // Get data from value/offset field. |
|
644 TInt value = iIfdEntries[entry]->ValueOffset(); |
|
645 |
|
646 if (aTag == KTag8298[ETagValue]) |
|
647 { |
|
648 //the copyright tag is a special case as it can have null mid string |
|
649 //note we would only get here if the copyright was <= 4 bytes |
|
650 if (*(reinterpret_cast<TUint8*>(&value)+totalSize-1) == NULL) |
|
651 { |
|
652 //we remove null at the end for consistency |
|
653 totalSize--; |
|
654 } |
|
655 aParam->Des().Copy(reinterpret_cast<TUint8*> (&value), totalSize); |
|
656 } |
|
657 else if (format == EAscii) |
|
658 { |
|
659 aParam->Des().Format(KStringFormat, reinterpret_cast<TUint8*> (&value)); |
|
660 } |
|
661 else |
|
662 { |
|
663 aParam->Des().Copy(reinterpret_cast<TUint8*> (&value), totalSize); |
|
664 } |
|
665 } |
|
666 return KErrNone; |
|
667 } |
|
668 |
|
669 TInt CIfdGeneral::GetParam16(const TUint aTag, HBufC16*& aParam) const |
|
670 { |
|
671 TInt entry = LocateEntry(aTag); |
|
672 if(entry == KErrNotFound) |
|
673 { |
|
674 return KErrNotFound; |
|
675 } |
|
676 |
|
677 // Check that we are dealing with the undefined format. |
|
678 switch(iIfdEntries[entry]->Format()) |
|
679 { |
|
680 case (EUndefined): |
|
681 break; |
|
682 default: |
|
683 return KErrArgument; |
|
684 } |
|
685 |
|
686 // Check the size. |
|
687 const TInt totalByteSize = iIfdEntries[entry]->ComponentCount(); |
|
688 |
|
689 delete aParam; |
|
690 aParam = HBufC16::NewMax((totalByteSize+1)>>1); |
|
691 if(aParam == NULL) |
|
692 { |
|
693 return KErrNoMemory; |
|
694 } |
|
695 |
|
696 TPtr ptr(aParam->Des()); |
|
697 Mem::Copy(reinterpret_cast<TText8*>(&ptr[0]), iIfdEntries[entry]->ActualValue(), totalByteSize); |
|
698 |
|
699 return KErrNone; |
|
700 } |
|
701 |
|
702 void CIfdGeneral::GetIntegerArrayParamL(const TUint aTag, CArrayFix<TInt>& aParam) const |
|
703 { |
|
704 TInt entry = LocateEntry(aTag); |
|
705 if(entry == KErrNotFound) |
|
706 { |
|
707 User::Leave(KErrNotFound); |
|
708 } |
|
709 |
|
710 // Check that we are dealing with an Integer format. |
|
711 switch(iIfdEntries[entry]->Format()) |
|
712 { |
|
713 case (EUnsignedLong): |
|
714 case (ESignedLong): |
|
715 break; |
|
716 default: |
|
717 User::Leave(KErrArgument); |
|
718 } |
|
719 |
|
720 // Check the size. |
|
721 TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
722 if(totalSize > KSizeOfValueOffsetField) |
|
723 { |
|
724 // Obviously have multiple entries. |
|
725 // However, as of Exif 2.2 there are no Integer Array tags defined that have |
|
726 // more than one entry. |
|
727 TInt numberOfInts = totalSize / KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
728 aParam.ResizeL(numberOfInts); |
|
729 const TUint8* dataStream = iIfdEntries[entry]->ActualValue(); |
|
730 if(!dataStream) |
|
731 { |
|
732 User::Leave(KErrArgument); |
|
733 } |
|
734 |
|
735 TInt value = 0; |
|
736 for(TInt i = 0; i < numberOfInts; i++) |
|
737 { |
|
738 Mem::Copy(&value, dataStream, sizeof(value)); |
|
739 aParam[i] = value; |
|
740 dataStream += sizeof(value); |
|
741 } |
|
742 } |
|
743 else |
|
744 { |
|
745 // A single entry |
|
746 aParam.ResizeL(1); |
|
747 aParam[0] = iIfdEntries[entry]->ValueOffset(); |
|
748 } |
|
749 } |
|
750 |
|
751 void CIfdGeneral::GetShortArrayParamL(const TUint aTag, CArrayFix<TUint16>& aParam) const |
|
752 { |
|
753 TInt entry = LocateEntry(aTag); |
|
754 if(entry == KErrNotFound) |
|
755 { |
|
756 User::Leave(KErrNotFound); |
|
757 } |
|
758 |
|
759 // Check that we are dealing with an Short format. |
|
760 TUint format = iIfdEntries[entry]->Format(); |
|
761 if(format != EUnsignedShort) |
|
762 { |
|
763 User::Leave(KErrArgument); |
|
764 } |
|
765 |
|
766 // Check the size. |
|
767 TUint componentCount = iIfdEntries[entry]->ComponentCount(); |
|
768 TUint dataSize = KDataFormatSize[format]; |
|
769 TUint totalSize = componentCount * dataSize; |
|
770 if(totalSize > KSizeOfValueOffsetField) |
|
771 { |
|
772 // Obviously have multiple entries. |
|
773 aParam.ResizeL(componentCount); |
|
774 const TUint8* dataStream = iIfdEntries[entry]->ActualValue(); |
|
775 if(dataStream==NULL) |
|
776 { |
|
777 User::Leave(KErrArgument); |
|
778 } |
|
779 |
|
780 TUint16 value = 0; |
|
781 for(TInt i = 0; i < componentCount; i++) |
|
782 { |
|
783 Mem::Copy(&value, dataStream, sizeof(value)); |
|
784 aParam[i] = value; |
|
785 dataStream += sizeof(value); |
|
786 } |
|
787 } |
|
788 else |
|
789 { |
|
790 // Either one or two entries |
|
791 ASSERT((componentCount==1) || (componentCount==2)); |
|
792 aParam.ResizeL(componentCount); |
|
793 TUint value = iIfdEntries[entry]->ValueOffset(); |
|
794 |
|
795 // When component count is 1, we read a UShort as a UShort, |
|
796 // so the byte order is correct on return. |
|
797 // |
|
798 // When component count is 2, we read the UShorts as a UInt. |
|
799 // i.e. Data is stored on DISK as TWO Shorts but read as ONE TUint32. |
|
800 // |
|
801 // Example representation of data on Disk: |
|
802 // 0x0300 0x0500 (Intel II LittleEndian) - 0x0003 & 0x0005 (Motorola MM BigEndian) |
|
803 // |
|
804 // For Intel data, it is read in as an Intel UInt and the bytes reversed. |
|
805 // This is important as a pointer is usually stored here: |
|
806 // 0x0300 0500 becomes 0x0005 0003 |
|
807 // |
|
808 |
|
809 // For Big-endian formatted files |
|
810 TUint32 highOrderShortMask = 0xFFFF0000; |
|
811 TUint32 lowOrderShortMask = 0x0000FFFF; |
|
812 |
|
813 if (componentCount==1) |
|
814 { |
|
815 aParam[0] = (value & lowOrderShortMask); |
|
816 } |
|
817 else |
|
818 { |
|
819 if(iIntel) |
|
820 { // II format |
|
821 aParam[0] = (value & lowOrderShortMask); |
|
822 aParam[1] = (value & highOrderShortMask) >> 16; |
|
823 } |
|
824 else |
|
825 { // MM format |
|
826 aParam[0] = (value & highOrderShortMask) >> 16; |
|
827 aParam[1] = (value & lowOrderShortMask); |
|
828 } |
|
829 } |
|
830 } |
|
831 } |
|
832 |
|
833 void CIfdGeneral::GetRationalArrayParamL(const TUint aTag, CArrayFix<TRational>& aParam) const |
|
834 { |
|
835 TInt entry = LocateEntry(aTag); |
|
836 if(entry == KErrNotFound) |
|
837 { |
|
838 User::Leave(KErrNotFound); |
|
839 } |
|
840 |
|
841 // Check that we are dealing with an Rational format. |
|
842 switch(iIfdEntries[entry]->Format()) |
|
843 { |
|
844 case (EUnsignedRational): |
|
845 case (ESignedRational): |
|
846 break; |
|
847 default: |
|
848 User::Leave(KErrArgument); |
|
849 } |
|
850 |
|
851 // Check the size. |
|
852 TInt totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
853 // Obviously have multiple entries. |
|
854 TInt numberOfRationalValues = totalSize / KDataFormatSize[iIfdEntries[entry]->Format()]; |
|
855 aParam.ResizeL(numberOfRationalValues); |
|
856 const TUint8* dataStream = iIfdEntries[entry]->ActualValue(); |
|
857 if(!dataStream) |
|
858 { |
|
859 User::Leave(KErrArgument); |
|
860 } |
|
861 |
|
862 TRational rational; |
|
863 for(TInt i = 0; i < numberOfRationalValues; i++) |
|
864 { |
|
865 Mem::Copy(&rational.iNumerator, dataStream, sizeof(rational.iNumerator)); |
|
866 Mem::Copy(&rational.iDenominator, dataStream+sizeof(rational.iNumerator), sizeof(rational.iDenominator)); |
|
867 aParam[i] = rational; |
|
868 dataStream += sizeof(rational.iNumerator) + sizeof(rational.iDenominator); // Move pointer on 8 bytes. |
|
869 } |
|
870 } |
|
871 |
|
872 TInt CIfdGeneral::Size() const |
|
873 { |
|
874 TUint totalSize = 0; |
|
875 // Get the size of each directory entry. |
|
876 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
877 { |
|
878 TInt size = iIfdEntries[i]->TotalSize(); |
|
879 totalSize+=size; |
|
880 } |
|
881 return totalSize; |
|
882 } |
|
883 |
|
884 |
|
885 |
|
886 // Can only be called by the 0th Ifd (otherwise returns KErrNotSupported). |
|
887 TInt CIfdGeneral::GetOffsetToFirstIfd(TUint& aOffset) const |
|
888 { |
|
889 if(iIfdNumber == 0) |
|
890 { |
|
891 aOffset = CExifReaderWriter::ReadUint32(iIntel, iBase + |
|
892 (iIfdEntryCount * KMinimumIfdEntrySize)+ |
|
893 sizeof(TUint16)+ |
|
894 iOffsetToIfd); |
|
895 return KErrNone; |
|
896 } |
|
897 return KErrNotSupported; |
|
898 } |
|
899 |
|
900 /** |
|
901 Parses the buffer, extracting the data. |
|
902 Ignores corrupt IFD entries (e.g. one with a value offset that is beyond the buffer's boundaries) |
|
903 unless more than KMaxNumberOfConsecInvalidEntries invalid entries appear in succession. In that case |
|
904 the whole IFD is considered corrupt. |
|
905 |
|
906 @leave KErrNoMemory If there is insufficient memory to process the data |
|
907 @leave KErrCorrupt If there are more than KMaxNumberOfConsecInvalidEntries consecutive |
|
908 corrupt entries |
|
909 */ |
|
910 void CIfdGeneral::AddAllIfdEntriesL() |
|
911 { |
|
912 // Set the Ifd entry count. |
|
913 iIfdEntryCount = CExifReaderWriter::ReadUint16(iIntel, iBase + iOffsetToIfd); |
|
914 |
|
915 const TUint8* ifdPtr = iBase + iOffsetToIfd + sizeof(iIfdEntryCount); |
|
916 |
|
917 //check for the validity of the iIfdEntryCount |
|
918 if(!IsValidIfdEntryCount(iIfdEntryCount)) |
|
919 {//most likely an invalid exif header |
|
920 User::Leave(KErrCorrupt); |
|
921 } |
|
922 |
|
923 // records if an entry is corrupt |
|
924 TBool ifdEntryIsCorrupt = EFalse; |
|
925 |
|
926 // counter to track the number of consec corrupt ifd entries |
|
927 // if more than KMaxNumberOfConsecInvalidEntries corrupt ifd entries occurr in a |
|
928 // row then the entire IFD is deemed to be corrupt and all the iIfdEntries are to |
|
929 // be deleted |
|
930 TUint numberOfConsecutiveCorruptIfdEntries = 0; |
|
931 |
|
932 // initialise the offset, which acts as a pointer increment. |
|
933 TInt offset = 0; |
|
934 for(TInt ifdEntry = 0; ifdEntry < iIfdEntryCount; ifdEntry++) |
|
935 { |
|
936 ifdEntryIsCorrupt = EFalse; |
|
937 |
|
938 // Create the new CIfdEntry to populate. |
|
939 |
|
940 // Set the general data of the Ifd entry. |
|
941 TUint16 tag = CExifReaderWriter::ReadUint16(iIntel, ifdPtr + offset+KTagFieldPosition); |
|
942 TUint16 format = CExifReaderWriter::ReadUint16(iIntel, ifdPtr + offset+KFormatFieldPosition); |
|
943 TUint componentCount = CExifReaderWriter::ReadUint32(iIntel, ifdPtr + offset+KComponentCountFieldPosition); |
|
944 |
|
945 // Determine if the data is held in the value/offset or if it is pointed to. |
|
946 TUint totalSize = 0; |
|
947 |
|
948 TUint valueOffset; |
|
949 TBool endianess = iIntel; |
|
950 const TUint8* valuePtr = NULL; |
|
951 |
|
952 if (!(format < KDataFormatSizeLength) || |
|
953 ((totalSize = componentCount * KDataFormatSize[format]) > iExifDataLength) || |
|
954 (totalSize == 0) || |
|
955 (tag == NULL && !AllowNullTags())) //null tag is valid for GPS IFD |
|
956 { |
|
957 // if invalid format or size is unreasonable this IFD entry is corrupt |
|
958 // (second check is a bit crude but worthwhile since it |
|
959 // can catch some obviously invalid entries early on) |
|
960 ifdEntryIsCorrupt = ETrue; |
|
961 } |
|
962 else |
|
963 { |
|
964 if (((format == EAscii)||(format == EByte)||(format == EUndefined)) && (totalSize <= KSizeOfValueOffsetField)) |
|
965 { |
|
966 //If the above condition is true then the data is such that it needs to |
|
967 //keep the byte order as is ie an ASCII field, a byte field or an undefined field |
|
968 //if this is the case we do not want to invert the bytes for big endian/motorola |
|
969 //ie order is unchanged |
|
970 //if the data is greater than 4 bytes then it should be copied across as is |
|
971 endianess = ETrue; //so set endianess to Intel even if the file is motorola |
|
972 } |
|
973 if(totalSize <= sizeof(TUint16)) |
|
974 { |
|
975 valueOffset = CExifReaderWriter::ReadUint16(endianess, ifdPtr + offset+KValueOffsetFieldPosition); |
|
976 } |
|
977 else |
|
978 { |
|
979 valueOffset = CExifReaderWriter::ReadUint32(endianess, ifdPtr + offset+KValueOffsetFieldPosition); |
|
980 } |
|
981 |
|
982 if (totalSize>KSizeOfValueOffsetField) |
|
983 { |
|
984 if((valueOffset) && ((valueOffset + totalSize) <= iExifDataLength)) |
|
985 { |
|
986 valuePtr = iBase+valueOffset; |
|
987 } |
|
988 else |
|
989 { |
|
990 // the offset is either null, pointing beyond the length of the exif data or |
|
991 // pointing to a value which goes beyond the length of the exif data |
|
992 // ie we are dealing with a corrupt entry |
|
993 ifdEntryIsCorrupt = ETrue; |
|
994 } |
|
995 } |
|
996 else |
|
997 { |
|
998 valuePtr = reinterpret_cast<const TUint8*> (&valueOffset); |
|
999 } |
|
1000 } |
|
1001 |
|
1002 // try to make the entry |
|
1003 CIfdGeneralEntry* entry = NULL; |
|
1004 if(!ifdEntryIsCorrupt) |
|
1005 { |
|
1006 // entries with unknown tags are created but count towards corrupt entries |
|
1007 // so that if many appear in succession we assume the IFD is corrupt |
|
1008 entry = CreateIfdEntryLC(tag, format, componentCount, valuePtr, valueOffset, totalSize, ifdEntryIsCorrupt); |
|
1009 |
|
1010 if(!entry) |
|
1011 { |
|
1012 ifdEntryIsCorrupt = ETrue; |
|
1013 } |
|
1014 } |
|
1015 |
|
1016 //an entry of all 0's could be padding so don't count it as corrupt |
|
1017 if ((ifdEntryIsCorrupt) && !((tag == 0)&&(format == 0)&&(componentCount == 0))) |
|
1018 { |
|
1019 numberOfConsecutiveCorruptIfdEntries++; |
|
1020 if ((numberOfConsecutiveCorruptIfdEntries == iIfdEntryCount)||(numberOfConsecutiveCorruptIfdEntries > KMaxNumberOfConsecInvalidEntries)) |
|
1021 { |
|
1022 //if the above condition is true then it is likely that we are scanning the IFD from the offset |
|
1023 //or that the data is non IFD |
|
1024 //so we will skip further processing of the IFD and abandon |
|
1025 User::Leave(KErrCorrupt); |
|
1026 } |
|
1027 } |
|
1028 else |
|
1029 { |
|
1030 numberOfConsecutiveCorruptIfdEntries = 0; //reset |
|
1031 } |
|
1032 |
|
1033 if (entry) |
|
1034 {//always ensure entry is valid before appending - might not be if we have a null tag |
|
1035 iIfdEntries.AppendL(entry); |
|
1036 CleanupStack::Pop(entry); |
|
1037 } |
|
1038 |
|
1039 offset += KMinimumIfdEntrySize; |
|
1040 } |
|
1041 |
|
1042 // All entries have now been added. |
|
1043 } |
|
1044 |
|
1045 /** |
|
1046 Creates an IFD entry and pushes it onto the cleanup stack. |
|
1047 If the entry cannot be created (most likely due to some |
|
1048 corrupt data) NULL will be returned. |
|
1049 |
|
1050 @param aTag EXIF tag number for this entry |
|
1051 @param aFormat Format of this entry's data |
|
1052 @param aComponentCount Number of values in the data |
|
1053 @param aValuePtr Pointer to the start of the data |
|
1054 @param aValueOffset Offset from start of EXIF data to start of entry data |
|
1055 @param aTotalSize Length of the data |
|
1056 @param aUnknownTag Set to ETrue if the entry's tag is unknown (for this IFD), |
|
1057 EFalse otherwise. |
|
1058 |
|
1059 @return The newly created entry or NULL if it could not be created. |
|
1060 |
|
1061 @leave KErrNoMemory If there wasn't sufficient memory to create entry. This |
|
1062 is the only type of leave this function can make. |
|
1063 |
|
1064 */ |
|
1065 CIfdGeneralEntry* CIfdGeneral::CreateIfdEntryLC(const TUint& aTag, const TUint& aFormat, const TUint& aComponentCount, const TUint8* aValuePtr, TUint aValueOffset, TUint aTotalSize, TBool& aUnknownTag) |
|
1066 { |
|
1067 CIfdGeneralEntry* entry= NULL; |
|
1068 |
|
1069 TRAPD(err, entry = CIfdGeneralEntry::NewL(aTag, aFormat, aComponentCount, aValuePtr, this, aUnknownTag)); |
|
1070 if (err != KErrNone) |
|
1071 { |
|
1072 if (err == KErrNoMemory) |
|
1073 { |
|
1074 User::Leave(err); //only leave if no memory |
|
1075 } |
|
1076 } |
|
1077 else |
|
1078 { |
|
1079 CleanupStack::PushL( entry ); |
|
1080 // no errors so far, so read the entry's values |
|
1081 if(aTotalSize > KSizeOfValueOffsetField) |
|
1082 { |
|
1083 // Byte swap each component, if necessary. |
|
1084 TUint8* byteSwappedDataBuffer = static_cast<TUint8*>(User::AllocL(aTotalSize)); |
|
1085 TUint8* tempPtr = byteSwappedDataBuffer; |
|
1086 TInt updateErr=KErrNone; |
|
1087 TInt i; |
|
1088 switch(aFormat) |
|
1089 { |
|
1090 case(EByte): |
|
1091 case(EAscii): |
|
1092 case(EUndefined): |
|
1093 updateErr = entry->SetActualData(iBase+aValueOffset, aComponentCount, KDataFormatSize[aFormat]); |
|
1094 break; |
|
1095 case(EUnsignedRational): |
|
1096 case(ESignedRational): |
|
1097 // Comprised of 2 * 4-byte integers. |
|
1098 { |
|
1099 for(i = 0; i < aComponentCount; i++) |
|
1100 { |
|
1101 TUint numer = CExifReaderWriter::ReadUint32(iIntel, iBase + aValueOffset + 8*i); |
|
1102 TUint denom = CExifReaderWriter::ReadUint32(iIntel, iBase + aValueOffset + 8*i + 4); |
|
1103 tempPtr = Mem::Copy(tempPtr, &numer, sizeof(numer)); |
|
1104 tempPtr = Mem::Copy(tempPtr, &denom, sizeof(denom)); |
|
1105 } |
|
1106 updateErr = entry->SetActualData(byteSwappedDataBuffer, aComponentCount, KDataFormatSize[aFormat]); |
|
1107 } |
|
1108 break; |
|
1109 case(EUnsignedLong): |
|
1110 case(ESignedLong): |
|
1111 { |
|
1112 for(i = 0; i < aComponentCount; i++) |
|
1113 { |
|
1114 TUint value = CExifReaderWriter::ReadUint32(iIntel, iBase + aValueOffset+(i*sizeof(value))); |
|
1115 tempPtr = Mem::Copy(tempPtr, &value, sizeof(value)); |
|
1116 } |
|
1117 updateErr = entry->SetActualData(byteSwappedDataBuffer, aComponentCount, KDataFormatSize[aFormat]); |
|
1118 } |
|
1119 break; |
|
1120 case(EUnsignedShort): |
|
1121 { |
|
1122 for(i = 0; i < aComponentCount; i++) |
|
1123 { |
|
1124 TUint16 value = CExifReaderWriter::ReadUint16(iIntel, iBase + aValueOffset+(i*sizeof(value))); |
|
1125 tempPtr = Mem::Copy(tempPtr, &value, sizeof(value)); |
|
1126 } |
|
1127 updateErr = entry->SetActualData(byteSwappedDataBuffer, aComponentCount, KDataFormatSize[aFormat]); |
|
1128 } |
|
1129 break; |
|
1130 default: |
|
1131 break; |
|
1132 } |
|
1133 User::Free(byteSwappedDataBuffer); |
|
1134 if(updateErr) |
|
1135 { |
|
1136 if(updateErr == KErrNoMemory) |
|
1137 { |
|
1138 User::Leave(KErrNoMemory); |
|
1139 } |
|
1140 else |
|
1141 { |
|
1142 // if we get here entry object was made, but data could not be set |
|
1143 // so we remove the entry object |
|
1144 CleanupStack::PopAndDestroy( entry ); |
|
1145 entry = NULL; |
|
1146 } |
|
1147 } |
|
1148 } // end if(aTotalSize > KSizeOfValueOffsetField) |
|
1149 } |
|
1150 |
|
1151 return entry; |
|
1152 } |
|
1153 |
|
1154 |
|
1155 void CIfdGeneral::SetupDirectoryEntriesL() |
|
1156 { |
|
1157 // Loop through all legal tags. |
|
1158 for(TInt i = 0; i < GetNumberOfValidTags(); i++) |
|
1159 { |
|
1160 const TUint* tagInfo = GetTagInformation(i); |
|
1161 // Only initialise the default Ifd with Mandatory tags. |
|
1162 if (tagInfo[ESupportLevelValue] == EMandatory) |
|
1163 { |
|
1164 TUint temp = tagInfo[EValueOffsetValue]; |
|
1165 TUint8* valueOffset = reinterpret_cast<TUint8*>(&temp); |
|
1166 |
|
1167 TUint format = tagInfo[EFormatValue]; |
|
1168 TUint componentCount = tagInfo[EComponentCountValue]; |
|
1169 if (format == EAscii) |
|
1170 { |
|
1171 valueOffset = reinterpret_cast<TUint8*> (temp); |
|
1172 componentCount = 0; |
|
1173 |
|
1174 TUint8* strPtr = valueOffset; |
|
1175 while(*strPtr++) |
|
1176 componentCount++; |
|
1177 } |
|
1178 |
|
1179 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(tagInfo[ETagValue], format, componentCount, valueOffset, this); |
|
1180 iIfdEntries.AppendL(entry); |
|
1181 CleanupStack::Pop(entry); |
|
1182 } |
|
1183 } |
|
1184 } |
|
1185 |
|
1186 TInt CIfdGeneral::LocateEntry(const TUint16 aTag) const |
|
1187 { |
|
1188 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
1189 { |
|
1190 if(aTag == iIfdEntries[i]->Tag()) |
|
1191 { |
|
1192 return i; |
|
1193 } |
|
1194 } |
|
1195 return KErrNotFound; |
|
1196 } |
|
1197 |
|
1198 TInt CIfdGeneral::Ifd() const |
|
1199 { |
|
1200 return iIfdNumber; |
|
1201 } |
|
1202 |
|
1203 TUint CIfdGeneral::EntryCount() const |
|
1204 { |
|
1205 return iIfdEntries.Count(); |
|
1206 } |
|
1207 |
|
1208 TUint8* CIfdGeneral::CreateIfdBlockL(TUint aOffset) |
|
1209 { |
|
1210 TUint allocSize = Size() + KIfdOffsetByteCount; |
|
1211 aOffset += KIfdOffsetByteCount; |
|
1212 TUint8* ifdBlock = static_cast<TUint8*>(User::AllocLC(allocSize)); // Allocate buffer for all IFD data. |
|
1213 WriteIfdDirEntriesL(ifdBlock, aOffset); |
|
1214 TUint8* tempPtr = ifdBlock + EntryCount() * KMinimumIfdEntrySize; |
|
1215 |
|
1216 TInt temporary = 0; |
|
1217 // The pointer to the next Ifd is temporarily zero-filled, and the actual value filled later. |
|
1218 tempPtr = Mem::Copy(tempPtr, &temporary, sizeof(temporary)); |
|
1219 |
|
1220 WriteIfdData(tempPtr); |
|
1221 CleanupStack::Pop(); |
|
1222 return ifdBlock; |
|
1223 } |
|
1224 |
|
1225 TBool CIfdGeneral::AllowNullTags() |
|
1226 { |
|
1227 // The general case |
|
1228 return EFalse; |
|
1229 } |
|
1230 |
|
1231 TBool CIfdGeneral::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const |
|
1232 { |
|
1233 // Check that aIfdEntryCount is reasonable |
|
1234 // The check is fairly basic but we will check that the minimum size of the ifd entry |
|
1235 // based on the aIfdEntryCount does not exceed the exif data length |
|
1236 // no check for minimum number of mandatory entries is done |
|
1237 if ( (iOffsetToIfd + sizeof(aIfdEntryCount) + (aIfdEntryCount * KMinimumIfdEntrySize)) > iExifDataLength) |
|
1238 { |
|
1239 return EFalse; |
|
1240 } |
|
1241 else |
|
1242 { |
|
1243 return ETrue; |
|
1244 } |
|
1245 } |
|
1246 |
|
1247 |
|
1248 void CIfdGeneral::WriteIfdDirEntriesL(TUint8* aBlock, TUint aOffset) |
|
1249 { |
|
1250 TUint16 dirCount = EntryCount(); |
|
1251 |
|
1252 //Address where data pointed to by offset values, starts. |
|
1253 TUint offsetDataAddress = aOffset + sizeof(dirCount) + (dirCount * KMinimumIfdEntrySize); |
|
1254 |
|
1255 // Copy each stored directory entry into the buffer. |
|
1256 TInt i; |
|
1257 TUint tag; |
|
1258 TUint format; |
|
1259 TUint sizeOfData; |
|
1260 for(i = 0; i < dirCount; i++) |
|
1261 { |
|
1262 tag = iIfdEntries[i]->Tag(); |
|
1263 format = iIfdEntries[i]->Format(); |
|
1264 |
|
1265 |
|
1266 TUint compCount = iIfdEntries[i]->ComponentCount(); |
|
1267 TBool unicode = iIfdEntries[i]->IsUnicodeData(); |
|
1268 |
|
1269 aBlock = Mem::Copy(aBlock, &tag, KSizeOfTagField); // Write tag. |
|
1270 aBlock = Mem::Copy(aBlock, &format, KSizeOfFormatField); // Write format |
|
1271 aBlock = Mem::Copy(aBlock, &compCount, KSizeOfComponentCountField); // Write component count. |
|
1272 // tempPtr now points to the value/offset field. |
|
1273 |
|
1274 sizeOfData = iIfdEntries[i]->ExtraSize(); |
|
1275 |
|
1276 // Here we must check as to whether we are writing an offset to an IFD, since |
|
1277 // its component count is 1 and it is a long - thus check explicitly for tag number 0x8769 |
|
1278 // (Exif Sub Ifd), or 0xA005 (Interoperability Ifd), and write the offset. |
|
1279 |
|
1280 if((iIfdEntries[i]->Tag() == KTag8769[ETagValue]) || |
|
1281 (iIfdEntries[i]->Tag() == KTagA005[ETagValue]) || |
|
1282 (iIfdEntries[i]->Tag() == KThumbTag8769[ETagValue]) || |
|
1283 (iIfdEntries[i]->Tag() == KThumbTag0201[ETagValue])) |
|
1284 { |
|
1285 TUint address = Size() + aOffset + sizeof(dirCount); |
|
1286 // Write offset value. The value to which this points will be written later. |
|
1287 aBlock = Mem::Copy(aBlock, &address, KSizeOfValueOffsetField); |
|
1288 } |
|
1289 //Must check if we are writing an offset or an actual value. |
|
1290 else if(sizeOfData > 0) |
|
1291 { |
|
1292 // Write offset value. The value to which this points will be written later. |
|
1293 aBlock = Mem::Copy(aBlock, &offsetDataAddress, KSizeOfValueOffsetField); |
|
1294 // Move the offset address onward, ready for next time. |
|
1295 offsetDataAddress += sizeOfData; |
|
1296 } |
|
1297 else |
|
1298 { |
|
1299 TUint valueOffset = iIfdEntries[i]->ValueOffset(); |
|
1300 aBlock = Mem::Copy(aBlock, &valueOffset, sizeof(valueOffset)); // Write actual value. |
|
1301 } |
|
1302 // tempPtr now points to position after the value/offset field. |
|
1303 } |
|
1304 |
|
1305 } |
|
1306 |
|
1307 void CIfdGeneral::WriteIfdData(TUint8* aBlock) |
|
1308 { |
|
1309 TUint16 dirCount = EntryCount(); |
|
1310 |
|
1311 TInt i; |
|
1312 TUint format; |
|
1313 TUint sizeOfData; |
|
1314 |
|
1315 // We have written the main blocks of data, so now need to write out the values that any offsets point to. |
|
1316 for(i = 0; i < dirCount; i++) |
|
1317 { |
|
1318 format = iIfdEntries[i]->Format(); |
|
1319 sizeOfData = KDataFormatSize[format] * iIfdEntries[i]->ComponentCount(); |
|
1320 if(sizeOfData > KSizeOfValueOffsetField) |
|
1321 { |
|
1322 if(iIfdEntries[i]->ActualValue() != NULL) |
|
1323 { |
|
1324 aBlock = Mem::Copy(aBlock, iIfdEntries[i]->ActualValue(), sizeOfData); |
|
1325 if ((sizeOfData%2) == 1) |
|
1326 { |
|
1327 (*aBlock++) = '\0'; |
|
1328 } |
|
1329 } |
|
1330 } |
|
1331 } |
|
1332 } |
|
1333 |
|
1334 |
|
1335 // Does the given tag exist in this Ifd? |
|
1336 TBool CIfdGeneral::EntryExists(const TUint aTag) const |
|
1337 { |
|
1338 for(TInt i = 0; i < iIfdEntries.Count(); i++) |
|
1339 { |
|
1340 if(aTag == iIfdEntries[i]->Tag()) |
|
1341 { |
|
1342 return ETrue; |
|
1343 } |
|
1344 } |
|
1345 return EFalse; |
|
1346 } |
|
1347 |
|
1348 TBool CIfdGeneral::FindTag(const TUint aTag) |
|
1349 { |
|
1350 return GetTagIndex(aTag)!=KErrNotFound; |
|
1351 } |
|
1352 |
|
1353 |
|
1354 TInt CIfdGeneral::GetFormat(TUint aTag, TUint& aFormat) |
|
1355 { |
|
1356 TInt index = GetTagIndex(aTag); |
|
1357 if (index != KErrNotFound) |
|
1358 { |
|
1359 const TUint* tag = GetTagInformation(index); |
|
1360 aFormat = tag[EFormatValue]; |
|
1361 return KErrNone; |
|
1362 } |
|
1363 return KErrNotFound; |
|
1364 } |
|
1365 |
|
1366 TInt CIfdGeneral::GetComponentCount(TUint aTag, TUint& aComponentCount) |
|
1367 { |
|
1368 TInt index = GetTagIndex(aTag); |
|
1369 if (index != KErrNotFound) |
|
1370 { |
|
1371 const TUint* tag = GetTagInformation(index); |
|
1372 aComponentCount = tag[EComponentCountValue]; |
|
1373 return KErrNone; |
|
1374 } |
|
1375 return KErrNotFound; |
|
1376 } |
|
1377 |
|
1378 TInt CIfdGeneral::GetTagIndex(const TUint aTag) |
|
1379 { |
|
1380 for (TInt i = 0 ; i< GetNumberOfValidTags(); i++ ) |
|
1381 { |
|
1382 if (GetTagInformation(i)[ETagValue] == aTag) |
|
1383 { |
|
1384 return i; |
|
1385 } |
|
1386 } |
|
1387 return KErrNotFound; |
|
1388 } |
|
1389 |
|
1390 void CIfdGeneral::RemoveEntryL(const TUint aTag) |
|
1391 { |
|
1392 TInt entry=LocateEntry(aTag); |
|
1393 if(entry==KErrNotFound) |
|
1394 { |
|
1395 User::Leave(entry); |
|
1396 } |
|
1397 delete iIfdEntries[entry]; |
|
1398 iIfdEntries.Remove(entry); |
|
1399 } |
|
1400 |
|
1401 void CIfdGeneral::CheckMandatoryEntriesL() |
|
1402 { |
|
1403 } |
|
1404 |
|
1405 // class CIfd0 |
|
1406 CIfd0* CIfd0::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1407 { |
|
1408 CIfd0* self = new (ELeave) CIfd0(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1409 CleanupStack::PushL(self); |
|
1410 self->ConstructL(); |
|
1411 return self; |
|
1412 } |
|
1413 |
|
1414 |
|
1415 TInt CIfd0::GetNumberOfValidTags() |
|
1416 { |
|
1417 return KIfd0NumberTags; |
|
1418 } |
|
1419 |
|
1420 const TUint* CIfd0::GetTagInformation(TInt aIndex) |
|
1421 { |
|
1422 if((aIndex < 0) || (aIndex >= KIfd0NumberTags)) |
|
1423 {//invalid argument |
|
1424 return NULL; |
|
1425 } |
|
1426 else |
|
1427 { |
|
1428 TUint tagValue = KIfd0TagArray[aIndex][ETagValue]; |
|
1429 if(tagValue == KTag010F[ETagValue]) |
|
1430 { |
|
1431 return iTag010F; |
|
1432 } |
|
1433 else if(tagValue == KTag0110[ETagValue]) |
|
1434 { |
|
1435 return iTag0110; |
|
1436 } |
|
1437 else if(tagValue == KTag0131[ETagValue]) |
|
1438 { |
|
1439 return iTag0131; |
|
1440 } |
|
1441 else |
|
1442 { |
|
1443 return KIfd0TagArray[aIndex]; |
|
1444 } |
|
1445 } |
|
1446 } |
|
1447 |
|
1448 void CIfd0::ConstructL() |
|
1449 { |
|
1450 //For Device information tags - copy the contents from the constants and |
|
1451 //overwrite only the - EValueOffsetValue. |
|
1452 Mem::Copy(iTag010F, KTag010F, sizeof(KTag010F)); |
|
1453 Mem::Copy(iTag0110, KTag0110, sizeof(KTag0110)); |
|
1454 Mem::Copy(iTag0131, KTag0131, sizeof(KTag0131)); |
|
1455 //get the device information from SysUtil API. |
|
1456 iManufacturerName = GetDeviceInfo(KTag010F[ETagValue]); |
|
1457 iModelName = GetDeviceInfo(KTag0110[ETagValue]); |
|
1458 iUIPlatform = GetDeviceInfo(KTag0131[ETagValue]); |
|
1459 TUint8* data = NULL; |
|
1460 //If reading from SysUtil API is not successful, let the tags carry the values from the constants. |
|
1461 //Moreover, the tags manufacturer and model are mandatory. They should have non-NULL value for EValueOffsetValue. |
|
1462 if(iManufacturerName != NULL) |
|
1463 { |
|
1464 data = const_cast<TUint8*>(iManufacturerName->Des().PtrZ()); |
|
1465 iTag010F[EValueOffsetValue] = reinterpret_cast<TUint>(data); |
|
1466 } |
|
1467 if(iModelName != NULL) |
|
1468 { |
|
1469 data = const_cast<TUint8*>(iModelName->Des().PtrZ()); |
|
1470 iTag0110[EValueOffsetValue] = reinterpret_cast<TUint>(data); |
|
1471 } |
|
1472 if(iUIPlatform != NULL) |
|
1473 { |
|
1474 data = const_cast<TUint8*>(iUIPlatform->Des().PtrZ()); |
|
1475 iTag0131[EValueOffsetValue] = reinterpret_cast<TUint>(data); |
|
1476 } |
|
1477 |
|
1478 CIfdGeneral::ConstructL(); |
|
1479 } |
|
1480 |
|
1481 //Reads device information from SysUtil API and makes a copy and returns the value. |
|
1482 //On failure returns NULL.If the tag aTagValue, does not belong to device information returns NULL. |
|
1483 HBufC8* CIfd0::GetDeviceInfo(TUint aTagValue) |
|
1484 { |
|
1485 HBufC8* buff = NULL; |
|
1486 //if the tag is one of - manufacturer name, device model name and UI Platform - get |
|
1487 //the values from SysUtil. |
|
1488 if((aTagValue == KTag010F[ETagValue]) || (aTagValue == KTag0110[ETagValue]) || (aTagValue == KTag0131[ETagValue])) |
|
1489 { |
|
1490 CDeviceTypeInformation* deviceAtts = NULL; |
|
1491 TInt err = KErrNone; |
|
1492 //Get device type information |
|
1493 TRAP(err, deviceAtts = SysUtil::GetDeviceTypeInfoL()); |
|
1494 if(err == KErrNone && deviceAtts != NULL) |
|
1495 { |
|
1496 TPtrC16 ptr; |
|
1497 if(aTagValue == KTag010F[ETagValue]) |
|
1498 {//manufacturer name |
|
1499 err = deviceAtts->GetManufacturerName(ptr); |
|
1500 } |
|
1501 else if(aTagValue == KTag0110[ETagValue]) |
|
1502 {//model name |
|
1503 err = deviceAtts->GetModelName(ptr); |
|
1504 } |
|
1505 else if(aTagValue == KTag0131[ETagValue]) |
|
1506 {//UI platform |
|
1507 err = deviceAtts->GetUIPlatformName(ptr); |
|
1508 } |
|
1509 delete deviceAtts; |
|
1510 //error code should be one of - KErrNone, KDefaultValue and KErrOverflow |
|
1511 if((err == KErrNone) || (err == CDeviceTypeInformation::KDefaultValue) || (err == KErrOverflow)) |
|
1512 { |
|
1513 buff = HBufC8::NewMax(ptr.Length() + 1); |
|
1514 if(buff != NULL) |
|
1515 { |
|
1516 TPtr8 ptr8 = buff->Des(); |
|
1517 ptr8.Copy(ptr); |
|
1518 } |
|
1519 } |
|
1520 } |
|
1521 } |
|
1522 return buff; |
|
1523 } |
|
1524 |
|
1525 CIfd0::~CIfd0() |
|
1526 { |
|
1527 delete iManufacturerName; |
|
1528 delete iModelName; |
|
1529 delete iUIPlatform; |
|
1530 } |
|
1531 |
|
1532 TBool CIfd0::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const |
|
1533 { |
|
1534 //should have atleast one mandatory entry |
|
1535 if(aIfdEntryCount >= 1) |
|
1536 { |
|
1537 return CIfdGeneral::IsValidIfdEntryCount(aIfdEntryCount); |
|
1538 } |
|
1539 else |
|
1540 { |
|
1541 return EFalse; |
|
1542 } |
|
1543 } |
|
1544 |
|
1545 CIfd0::CIfd0(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1546 : CIfdGeneral(EZeroth, aOffsetToIfd, aBase, aIntel, aExifDataLength) |
|
1547 { |
|
1548 } |
|
1549 |
|
1550 //class CExifIfd |
|
1551 CExifIfd* CExifIfd::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1552 { |
|
1553 CExifIfd* self = new (ELeave) CExifIfd(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1554 CleanupStack::PushL(self); |
|
1555 self->ConstructL(); |
|
1556 return self; |
|
1557 } |
|
1558 |
|
1559 CExifIfd* CExifIfd::NewL(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1560 { |
|
1561 CExifIfd* self = NewLC(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1562 CleanupStack::Pop(self); |
|
1563 return self; |
|
1564 } |
|
1565 |
|
1566 TInt CExifIfd::GetNumberOfValidTags() |
|
1567 { |
|
1568 return KExifSubNumberTags; |
|
1569 } |
|
1570 |
|
1571 const TUint* CExifIfd::GetTagInformation(TInt aIndex) |
|
1572 { |
|
1573 return KExifSubTagArray[aIndex]; |
|
1574 } |
|
1575 |
|
1576 void CExifIfd::CheckMandatoryEntriesL() |
|
1577 { |
|
1578 HBufC8* buffer = NULL; |
|
1579 TInt err = GetParam8(KTag9000[ETagValue], buffer); |
|
1580 if (err == KErrNotFound) |
|
1581 { |
|
1582 TUint temp = KTag9000[EValueOffsetValue]; |
|
1583 TUint8* valueOffset = reinterpret_cast<TUint8*>(&temp); |
|
1584 TUint format = KTag9000[EFormatValue]; |
|
1585 TUint componentCount = KTag9000[EComponentCountValue]; |
|
1586 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(KTag9000[ETagValue], format, componentCount, valueOffset, this); |
|
1587 iIfdEntries.AppendL(entry); |
|
1588 CleanupStack::Pop(entry); |
|
1589 } |
|
1590 delete buffer; |
|
1591 buffer = NULL; |
|
1592 |
|
1593 err = GetParam8(KTag9101[ETagValue], buffer); |
|
1594 if (err == KErrNotFound) |
|
1595 { |
|
1596 _LIT8(KComponentsConfigurationDefault, "1230"); |
|
1597 buffer = KComponentsConfigurationDefault().AllocL(); |
|
1598 CleanupStack::PushL(buffer); |
|
1599 TUint format = 0; |
|
1600 err = GetFormat(KTag9101[ETagValue], format); |
|
1601 if (err == KErrNone) |
|
1602 { |
|
1603 AddParam8L(KTag9101[ETagValue], format, buffer->Length(), buffer); |
|
1604 } |
|
1605 CleanupStack::Pop(); |
|
1606 } |
|
1607 delete buffer; |
|
1608 buffer = NULL; |
|
1609 |
|
1610 err = GetParam8(KTagA000[ETagValue], buffer); |
|
1611 if (err == KErrNotFound) |
|
1612 { |
|
1613 TUint temp = KTagA000[EValueOffsetValue]; |
|
1614 TUint8* valueOffset = reinterpret_cast<TUint8*>(&temp); |
|
1615 TUint format = KTagA000[EFormatValue]; |
|
1616 TUint componentCount = KTagA000[EComponentCountValue]; |
|
1617 CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(KTagA000[ETagValue], format, componentCount, valueOffset, this); |
|
1618 iIfdEntries.AppendL(entry); |
|
1619 CleanupStack::Pop(entry); |
|
1620 } |
|
1621 delete buffer; |
|
1622 buffer = NULL; |
|
1623 |
|
1624 TUint16 buffer16 = 0; |
|
1625 err = GetShortParam(KTagA001[ETagValue], buffer16); |
|
1626 if (err == KErrNotFound) |
|
1627 { |
|
1628 const TUint KColorSpaceDefault = 0xFFFF; |
|
1629 TUint format = 0; |
|
1630 err = GetFormat(KTagA001[ETagValue], format); |
|
1631 if (err == KErrNone) |
|
1632 { |
|
1633 AddShortParamL(KTagA001[ETagValue], format, 1, KColorSpaceDefault); |
|
1634 } |
|
1635 } |
|
1636 } |
|
1637 |
|
1638 TBool CExifIfd::CheckImageSizeTags() |
|
1639 { |
|
1640 TUint16 buffer16 = NULL; |
|
1641 TInt err = GetShortParam(KTagA002[ETagValue], buffer16); |
|
1642 if (err == KErrNotFound) |
|
1643 { |
|
1644 return EFalse; |
|
1645 } |
|
1646 err = GetShortParam(KTagA003[ETagValue], buffer16); |
|
1647 if (err == KErrNotFound) |
|
1648 { |
|
1649 return EFalse; |
|
1650 } |
|
1651 return ETrue; |
|
1652 } |
|
1653 |
|
1654 void CExifIfd::UpdateImageSizeTagsL(const TSize& aSize) |
|
1655 { |
|
1656 TUint16 value = NULL; |
|
1657 TInt err = GetShortParam(KTagA002[ETagValue], value); |
|
1658 if (err == KErrNotFound) |
|
1659 { |
|
1660 TUint format = 0; |
|
1661 err = GetFormat(KTagA002[ETagValue], format); |
|
1662 if (err == KErrNone) |
|
1663 { |
|
1664 AddShortParamL(KTagA002[ETagValue], format, 1, aSize.iWidth); |
|
1665 } |
|
1666 } |
|
1667 else |
|
1668 { |
|
1669 if (value != aSize.iWidth) |
|
1670 { |
|
1671 SetShortParam(KTagA002[ETagValue], aSize.iWidth); |
|
1672 } |
|
1673 } |
|
1674 err = GetShortParam(KTagA003[ETagValue], value); |
|
1675 if (err == KErrNotFound) |
|
1676 { |
|
1677 TUint format = 0; |
|
1678 err = GetFormat(KTagA003[ETagValue], format); |
|
1679 if (err == KErrNone) |
|
1680 { |
|
1681 AddShortParamL(KTagA003[ETagValue], format, 1, aSize.iHeight); |
|
1682 } |
|
1683 } |
|
1684 else |
|
1685 { |
|
1686 if (value != aSize.iHeight) |
|
1687 { |
|
1688 SetShortParam(KTagA003[ETagValue], aSize.iHeight); |
|
1689 } |
|
1690 } |
|
1691 } |
|
1692 |
|
1693 CExifIfd::CExifIfd(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1694 : CIfdGeneral(EExifSub, aOffsetToIfd, aBase, aIntel, aExifDataLength) |
|
1695 { |
|
1696 } |
|
1697 |
|
1698 |
|
1699 //class CInteropIfd |
|
1700 CInteropIfd* CInteropIfd::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1701 { |
|
1702 CInteropIfd* self = new (ELeave) CInteropIfd(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1703 CleanupStack::PushL(self); |
|
1704 self->ConstructL(); |
|
1705 return self; |
|
1706 } |
|
1707 |
|
1708 CInteropIfd* CInteropIfd::NewL(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1709 { |
|
1710 CInteropIfd* self = NewLC(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1711 CleanupStack::Pop(self); |
|
1712 return self; |
|
1713 } |
|
1714 |
|
1715 TInt CInteropIfd::GetNumberOfValidTags() |
|
1716 { |
|
1717 return KInteropNumberTags; |
|
1718 } |
|
1719 |
|
1720 const TUint* CInteropIfd::GetTagInformation(TInt aIndex) |
|
1721 { |
|
1722 return KInteropTagArray[aIndex]; |
|
1723 } |
|
1724 |
|
1725 TBool CInteropIfd::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const |
|
1726 { |
|
1727 //should have atleast one mandatory entry |
|
1728 if(aIfdEntryCount >= 1) |
|
1729 { |
|
1730 return CIfdGeneral::IsValidIfdEntryCount(aIfdEntryCount); |
|
1731 } |
|
1732 else |
|
1733 { |
|
1734 return EFalse; |
|
1735 } |
|
1736 } |
|
1737 |
|
1738 CInteropIfd::CInteropIfd(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1739 : CIfdGeneral(EInterop, aOffsetToIfd, aBase, aIntel, aExifDataLength) |
|
1740 { |
|
1741 } |
|
1742 |
|
1743 //class CIfd1 |
|
1744 CIfd1* CIfd1::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1745 { |
|
1746 CIfd1* self = new (ELeave) CIfd1(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1747 CleanupStack::PushL(self); |
|
1748 self->ConstructL(); |
|
1749 return self; |
|
1750 } |
|
1751 |
|
1752 |
|
1753 TInt CIfd1::GetNumberOfValidTags() |
|
1754 { |
|
1755 return KIfd1NumberTags; |
|
1756 } |
|
1757 |
|
1758 const TUint* CIfd1::GetTagInformation(TInt aIndex) |
|
1759 { |
|
1760 return KIfd1TagArray[aIndex]; |
|
1761 } |
|
1762 |
|
1763 CIfd1::CIfd1(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1764 : CIfdGeneral(EFirst, aOffsetToIfd, aBase, aIntel, aExifDataLength) |
|
1765 { |
|
1766 } |
|
1767 |
|
1768 //class CGpsIfd |
|
1769 CGpsIfd* CGpsIfd::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1770 { |
|
1771 CGpsIfd* self = new (ELeave) CGpsIfd(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1772 CleanupStack::PushL(self); |
|
1773 self->ConstructL(); |
|
1774 return self; |
|
1775 } |
|
1776 |
|
1777 CGpsIfd* CGpsIfd::NewL(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1778 { |
|
1779 CGpsIfd* self = NewLC(aOffsetToIfd, aBase, aIntel, aExifDataLength); |
|
1780 CleanupStack::Pop(self); |
|
1781 return self; |
|
1782 } |
|
1783 |
|
1784 TInt CGpsIfd::GetNumberOfValidTags() |
|
1785 { |
|
1786 return KGpsSubNumberTags; |
|
1787 } |
|
1788 |
|
1789 const TUint* CGpsIfd::GetTagInformation(TInt aIndex) |
|
1790 { |
|
1791 return KGpsSubTagArray[aIndex]; |
|
1792 } |
|
1793 |
|
1794 TBool CGpsIfd::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const |
|
1795 { |
|
1796 //should have atleast one mandatory entry |
|
1797 if(aIfdEntryCount >= 1) |
|
1798 { |
|
1799 return CIfdGeneral::IsValidIfdEntryCount(aIfdEntryCount); |
|
1800 } |
|
1801 else |
|
1802 { |
|
1803 return EFalse; |
|
1804 } |
|
1805 } |
|
1806 |
|
1807 CGpsIfd::CGpsIfd(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength) |
|
1808 : CIfdGeneral(EGpsSub, aOffsetToIfd, aBase, aIntel, aExifDataLength) |
|
1809 { |
|
1810 } |
|
1811 |
|
1812 TBool CGpsIfd::AllowNullTags() |
|
1813 { |
|
1814 // Null tags are allowed for GPS |
|
1815 return ETrue; |
|
1816 } |
|
1817 |