|
1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "CExifParser.h" |
|
21 #include <e32svr.h> // for debug |
|
22 |
|
23 |
|
24 |
|
25 enum TExifType |
|
26 { |
|
27 EByte = 1, |
|
28 EAscii, |
|
29 EShort, |
|
30 ELong, |
|
31 ERational, |
|
32 EUndefined = 7, |
|
33 ESLong = 9, |
|
34 ESRational |
|
35 }; |
|
36 |
|
37 |
|
38 |
|
39 const char* KTypeName[] = |
|
40 { |
|
41 "Byte", |
|
42 "Ascii", |
|
43 "Short", |
|
44 "Long", |
|
45 "Rational", |
|
46 "Undefined", |
|
47 "SLong", |
|
48 "SRational" |
|
49 }; |
|
50 |
|
51 |
|
52 |
|
53 const char KTypeLength[] = |
|
54 { |
|
55 0, |
|
56 1, |
|
57 1, |
|
58 2, |
|
59 4, |
|
60 8, |
|
61 0, |
|
62 1, |
|
63 0, |
|
64 4, |
|
65 8 |
|
66 }; |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 CExifParser* CExifParser::NewL() |
|
75 { |
|
76 CExifParser* self = NewLC(); |
|
77 CleanupStack::Pop( self ); |
|
78 return self; |
|
79 } |
|
80 |
|
81 |
|
82 |
|
83 CExifParser* CExifParser::NewLC() |
|
84 { |
|
85 CExifParser* self = new( ELeave )CExifParser(); |
|
86 CleanupStack::PushL( self ); |
|
87 self->ConstructL(); |
|
88 return self; |
|
89 } |
|
90 |
|
91 |
|
92 |
|
93 CExifParser::~CExifParser() |
|
94 { |
|
95 iEntry.ResetAndDestroy(); |
|
96 iParseStack.Reset(); |
|
97 |
|
98 delete[] iSaveBuf; |
|
99 delete[] iSaveDataBuf; |
|
100 |
|
101 iThumbData = NULL; |
|
102 } |
|
103 |
|
104 |
|
105 |
|
106 CExifParser::CExifParser() |
|
107 { |
|
108 |
|
109 } |
|
110 |
|
111 |
|
112 |
|
113 void CExifParser::ConstructL() |
|
114 { |
|
115 iIntelByteOrder = true; |
|
116 } |
|
117 |
|
118 |
|
119 |
|
120 void CExifParser::ParseL( const TPtrC8& aData ) |
|
121 { |
|
122 if( aData.Length() < (8+2+12) ) return; // header + 1 tag length |
|
123 |
|
124 iData.Set( aData ); |
|
125 iThumbData = 0; |
|
126 iThumbLen = 0; |
|
127 |
|
128 if( iData[ 0 ] == 0x49 && iData[ 1 ] == 0x49 ) |
|
129 { |
|
130 // intel byte order |
|
131 iIntelByteOrder = ETrue; |
|
132 //RDebug::Print( _L("Intel byte order selected") ); |
|
133 } |
|
134 else |
|
135 { |
|
136 //RDebug::Print( _L("Motorola byte order selected") ); |
|
137 } |
|
138 |
|
139 iPosition = 2; |
|
140 TUint16 v = Get16(); |
|
141 if( v != 0x002a ) |
|
142 { |
|
143 // must be 2a 00 in EXIF |
|
144 User::Leave( KErrNotSupported ); |
|
145 } |
|
146 |
|
147 iPosition = 4; |
|
148 iParseStack.Append( TParseStack( Get32(), EIfd0 ) ); |
|
149 |
|
150 while( iParseStack.Count() ) |
|
151 { |
|
152 iPosition = iParseStack[ 0 ].iPosition; |
|
153 TUint8 currentIfd = iParseStack[ 0 ].iIfd; |
|
154 iParseStack.Remove( 0 ); |
|
155 TInt i; |
|
156 TInt c = Get16(); |
|
157 for( i=0; i<c; i++ ) |
|
158 { |
|
159 ParseIfdL( currentIfd ); |
|
160 } |
|
161 TUint32 link = NULL; |
|
162 if (iPosition + 3 < iData.Length()) |
|
163 { |
|
164 link = Get32(); |
|
165 } |
|
166 |
|
167 if( link ) |
|
168 { |
|
169 //RDebug::Print( _L(" --Link (IFD1?) %d,%d"), link, iPosition ); |
|
170 iParseStack.Append( TParseStack( link, EIfd1 ) ); |
|
171 } |
|
172 else |
|
173 { |
|
174 //RDebug::Print( _L(" -- NULL Link after IFD") ); |
|
175 } |
|
176 } |
|
177 iParseStack.Reset(); |
|
178 |
|
179 //RDebug::Print( _L(" -- Parse Complete") ); |
|
180 iIntelByteOrder = true; |
|
181 } |
|
182 |
|
183 |
|
184 |
|
185 TBool CExifParser::TagExist( TInt aIfd, TUint16 aTag ) |
|
186 { |
|
187 if( FindTag( aIfd, aTag ) >= 0 ) return ETrue; |
|
188 return EFalse; |
|
189 } |
|
190 |
|
191 |
|
192 |
|
193 void CExifParser::DeleteTag( TInt aIfd, TUint16 aTag ) |
|
194 { |
|
195 TInt i = FindTag( aIfd, aTag ); |
|
196 if( i >= 0 ) |
|
197 { |
|
198 delete iEntry[ i ]; |
|
199 iEntry.Remove( i ); |
|
200 } |
|
201 } |
|
202 |
|
203 |
|
204 |
|
205 TUint32 CExifParser::TagValue( TInt aIfd, TUint16 aTag ) |
|
206 { |
|
207 TInt value = 0; |
|
208 TInt n = FindTag( aIfd, aTag ); |
|
209 if( n<0 ) return 0; |
|
210 TExifEntry* e = iEntry[ n ]; |
|
211 TUint8* valData = e->iData; |
|
212 switch( e->iType ) |
|
213 { |
|
214 case EByte: |
|
215 { |
|
216 value = Get8( valData ); |
|
217 break; |
|
218 } |
|
219 case EAscii: |
|
220 { |
|
221 /* |
|
222 TBuf< 256 >str; |
|
223 str.Copy( _L("value:") ); |
|
224 const TUint8* p = valData; |
|
225 while( *p != 0 ) |
|
226 { |
|
227 str.Append( *p ); |
|
228 p++; |
|
229 } |
|
230 */ |
|
231 // not supported |
|
232 value = 0; |
|
233 break; |
|
234 } |
|
235 case EShort: |
|
236 { |
|
237 value = Get16( valData ); |
|
238 ////RDebug::Print( _L("value:%d"), value ); |
|
239 break; |
|
240 } |
|
241 case ELong: |
|
242 { |
|
243 value = Get32( valData ); |
|
244 ////RDebug::Print( _L("value:%d"), value ); |
|
245 break; |
|
246 } |
|
247 case ERational: |
|
248 { |
|
249 TInt nominator = Get32( valData ); |
|
250 TInt denominator = Get32( valData+4 ); |
|
251 ////RDebug::Print( _L("value:%d/%d"), nominator, denominator ); |
|
252 if( denominator != 0 ) |
|
253 { |
|
254 value = nominator / denominator; |
|
255 } |
|
256 else |
|
257 { |
|
258 value = 0; |
|
259 } |
|
260 break; |
|
261 } |
|
262 case EUndefined: |
|
263 { |
|
264 |
|
265 break; |
|
266 } |
|
267 case ESLong: |
|
268 { |
|
269 TUint32 val = Get32( valData ); |
|
270 value = *(TInt*)(&val); |
|
271 ////RDebug::Print( _L("value:%d"), svalue ); |
|
272 |
|
273 break; |
|
274 } |
|
275 case ESRational: |
|
276 { |
|
277 TUint32 uval = Get32( valData ); |
|
278 TInt nominator = *(TInt*)(&uval); |
|
279 uval = Get32( valData+4 ); |
|
280 TInt denominator = *(TInt*)(&uval); |
|
281 |
|
282 if( denominator != 0 ) |
|
283 { |
|
284 value = nominator / denominator; |
|
285 } |
|
286 else |
|
287 { |
|
288 value = 0; |
|
289 } |
|
290 ////RDebug::Print( _L("value:%d/%d"), nominator, denominator ); |
|
291 break; |
|
292 } |
|
293 default: |
|
294 { |
|
295 break; |
|
296 } |
|
297 } |
|
298 |
|
299 return value; |
|
300 } |
|
301 |
|
302 TPtrC8 CExifParser::ThumbData() |
|
303 { |
|
304 return TPtrC8( iThumbData, iThumbLen ); |
|
305 } |
|
306 |
|
307 |
|
308 TPtr8 CExifParser::SaveL( const TPtrC8& aThumbData ) |
|
309 { |
|
310 iIntelByteOrder = true; |
|
311 // |
|
312 // Exif data cannot take more than 64KBytes |
|
313 // |
|
314 if (iSaveBuf) |
|
315 { |
|
316 delete[] iSaveBuf; |
|
317 iSaveBuf = NULL; |
|
318 } |
|
319 |
|
320 iSaveBuf = new( ELeave )TUint8[ 0x10000 ]; |
|
321 iSaveBufPos = 0; |
|
322 |
|
323 if (iSaveDataBuf) |
|
324 { |
|
325 delete[] iSaveDataBuf; |
|
326 iSaveDataBuf = NULL; |
|
327 } |
|
328 |
|
329 iSaveDataBuf = new( ELeave )TUint8[ 0x10000 ]; |
|
330 iSaveDataBufPos = 0; |
|
331 |
|
332 // |
|
333 // header |
|
334 // |
|
335 Put8( 0x49 ); |
|
336 Put8( 0x49 ); |
|
337 Put8( 0x2a ); |
|
338 Put8( 0x00 ); |
|
339 Put32( 8 ); |
|
340 |
|
341 // |
|
342 // Remove IFD0 SubIfd tag, will be regenerated |
|
343 // |
|
344 DeleteTag( EIfd0, 0x8769 ); |
|
345 |
|
346 // |
|
347 // Save IFD0 |
|
348 // |
|
349 Put16( IfdCount( EIfd0 ) + 1 ); |
|
350 TInt c = iEntry.Count(); |
|
351 TInt i; |
|
352 for( i=0; i<c; i++ ) |
|
353 { |
|
354 TExifEntry* e = iEntry[ i ]; |
|
355 if( e->iIfd == EIfd0 ) |
|
356 { |
|
357 StoreEntry( i ); |
|
358 } |
|
359 } |
|
360 |
|
361 // |
|
362 // Save link to SubIfd ( this is a tag ) |
|
363 // |
|
364 TExifEntry* tagsub = new( ELeave )TExifEntry; |
|
365 CleanupStack::PushL(tagsub); |
|
366 tagsub->iTag = 0x8769; |
|
367 tagsub->iIfd = EIfd0; |
|
368 tagsub->iType = ELong; |
|
369 tagsub->iCount = 1; |
|
370 tagsub->iData = new( ELeave )TUint8[ 4 ]; |
|
371 TUint8* dat = tagsub->iData; |
|
372 TUint32 offset = iSaveBufPos + 12 + 4; // just after IFD1 link |
|
373 if( iIntelByteOrder ) |
|
374 { |
|
375 dat[ 0 ] = offset & 255; offset >>= 8; |
|
376 dat[ 1 ] = offset & 255; offset >>= 8; |
|
377 dat[ 2 ] = offset & 255; offset >>= 8; |
|
378 dat[ 3 ] = offset & 255; |
|
379 } |
|
380 else |
|
381 { |
|
382 dat[ 3 ] = offset & 255; offset >>= 8; |
|
383 dat[ 2 ] = offset & 255; offset >>= 8; |
|
384 dat[ 1 ] = offset & 255; offset >>= 8; |
|
385 dat[ 0 ] = offset & 255; |
|
386 } |
|
387 iEntry.Append( tagsub ); |
|
388 CleanupStack::Pop(); |
|
389 StoreEntry( iEntry.Count()-1 ); |
|
390 |
|
391 // |
|
392 // Save link to IFD1 ( not a tag, just pointer ) |
|
393 // |
|
394 TInt IFD1LinkPos = iSaveBufPos; |
|
395 Put32( 0 ); |
|
396 |
|
397 // |
|
398 // Remove Interoperability tag, will be regenerated |
|
399 // |
|
400 DeleteTag( ESubIfd, 0xa005 ); |
|
401 c = iEntry.Count(); |
|
402 |
|
403 // |
|
404 // Save SubIfd |
|
405 // |
|
406 Put16( IfdCount( ESubIfd ) ); |
|
407 //RDebug::Print( _L(" SUBIFD count %x"), IfdCount( ESubIfd ) ); |
|
408 for( i=0; i<c; i++ ) |
|
409 { |
|
410 TExifEntry* e = iEntry[ i ]; |
|
411 if( e->iIfd == ESubIfd ) |
|
412 { |
|
413 //RDebug::Print( _L(" SUBIFD %x"), e->iTag ); |
|
414 StoreEntry( i ); |
|
415 } |
|
416 } |
|
417 /* |
|
418 TExifEntry* tagint = new( ELeave )TExifEntry; |
|
419 tagint->iTag = 0xa005; |
|
420 tagint->iIfd = ESubIfd; |
|
421 tagint->iType = ELong; |
|
422 tagint->iCount = 1; |
|
423 tagint->iData = new( ELeave )TUint8[ 4 ]; |
|
424 TUint8* dat2 = tagint->iData; |
|
425 TUint32 offset2 = iSaveBufPos + 12 + 4; // just after IFD link |
|
426 if( iIntelByteOrder ) |
|
427 { |
|
428 dat2[ 0 ] = offset2 & 255; offset2 >>= 8; |
|
429 dat2[ 1 ] = offset2 & 255; offset2 >>= 8; |
|
430 dat2[ 2 ] = offset2 & 255; offset2 >>= 8; |
|
431 dat2[ 3 ] = offset2 & 255; |
|
432 } |
|
433 else |
|
434 { |
|
435 dat2[ 3 ] = offset2 & 255; offset2 >>= 8; |
|
436 dat2[ 2 ] = offset2 & 255; offset2 >>= 8; |
|
437 dat2[ 1 ] = offset2 & 255; offset2 >>= 8; |
|
438 dat2[ 0 ] = offset2 & 255; |
|
439 } |
|
440 iEntry.Append( tagint ); |
|
441 StoreEntry( iEntry.Count()-1 ); |
|
442 */ |
|
443 Put32( 0 ); // IFD link |
|
444 |
|
445 /* |
|
446 // |
|
447 // Save Interoperability |
|
448 // |
|
449 Put16( IfdCount( EInteroperability ) ); |
|
450 c = iEntry.Count(); |
|
451 for( i=0; i<c; i++ ) |
|
452 { |
|
453 TExifEntry* e = iEntry[ i ]; |
|
454 if( e->iIfd == EInteroperability ) |
|
455 { |
|
456 StoreEntry( i ); |
|
457 } |
|
458 } |
|
459 Put32( 0 ); // IFD link |
|
460 */ |
|
461 // |
|
462 // Save IFD1 ( thumbnail ) if new thumbnail given |
|
463 // |
|
464 if( aThumbData.Ptr() ) |
|
465 { |
|
466 TUint32 temp = iSaveBufPos; |
|
467 iSaveBufPos = IFD1LinkPos; |
|
468 Put32( temp ); |
|
469 iSaveBufPos = temp; |
|
470 } |
|
471 |
|
472 // |
|
473 // Remove old thumbnail tags |
|
474 // |
|
475 c = iEntry.Count(); |
|
476 i = 0; |
|
477 while( i < iEntry.Count() ) |
|
478 { |
|
479 TExifEntry* e = iEntry[ i ]; |
|
480 if( e->iIfd == EIfd1 ) |
|
481 { |
|
482 delete e; |
|
483 iEntry.Remove( i ); |
|
484 } |
|
485 else |
|
486 { |
|
487 i++; |
|
488 } |
|
489 } |
|
490 |
|
491 // |
|
492 // Add newe thumbnail tags ( if thumbnail given ) |
|
493 // |
|
494 TInt thumbData = 0; |
|
495 if( aThumbData.Ptr() ) |
|
496 { |
|
497 AddTagL( EIfd1, 0x0103, (TUint16)6 ); // thumbnail = jpeg |
|
498 |
|
499 // thumbnail X-resolution 180/1 |
|
500 AddTagL( EIfd1, 0x011a, (TUint32)180, (TUint32)1 ); |
|
501 |
|
502 // thumbnail Y-resolution 180/1 |
|
503 AddTagL( EIfd1, 0x011b, (TUint32)180, (TUint32)1 ); |
|
504 |
|
505 // thumbnail resolution unit = inch |
|
506 AddTagL( EIfd1, 0x0128, (TUint16)2 ); |
|
507 |
|
508 AddTagL( EIfd1, 0x0201, (TUint32)0 ); // thumb offset |
|
509 AddTagL( EIfd1, 0x0202, (TUint32)aThumbData.Length() ); // thumb length |
|
510 |
|
511 |
|
512 Put16( IfdCount( EIfd1 ) ); |
|
513 c = iEntry.Count(); |
|
514 for( i=0; i<c; i++ ) |
|
515 { |
|
516 TExifEntry* e = iEntry[ i ]; |
|
517 if( e->iIfd == EIfd1 ) |
|
518 { |
|
519 StoreEntry( i ); |
|
520 } |
|
521 } |
|
522 |
|
523 |
|
524 thumbData = iSaveBufPos - 12 - 4; // tag 0x0201 data position |
|
525 |
|
526 Put32( 0 ); // IFD link |
|
527 } |
|
528 |
|
529 // |
|
530 // Copy tag data to same buffer with tags |
|
531 // |
|
532 Mem::Copy( iSaveBuf + iSaveBufPos, iSaveDataBuf, iSaveDataBufPos ); |
|
533 TInt totalLength = iSaveBufPos + iSaveDataBufPos; |
|
534 |
|
535 // |
|
536 // Copy thumbnail data to same buffer |
|
537 // |
|
538 if( thumbData ) |
|
539 { |
|
540 TInt temp = iSaveBufPos; |
|
541 iSaveBufPos = thumbData; |
|
542 Put32( totalLength ); |
|
543 iSaveBufPos = temp; |
|
544 |
|
545 Mem::Copy( iSaveBuf + totalLength, aThumbData.Ptr(), aThumbData.Length() ); |
|
546 totalLength += aThumbData.Length(); |
|
547 } |
|
548 // |
|
549 // update data pointers |
|
550 // |
|
551 if( iSaveBufPos & 1 ) iSaveBufPos++; // data must be in even address |
|
552 TInt doffset = iSaveBufPos; |
|
553 c = iDataEntry.Count(); |
|
554 for( i=0; i<c; i++ ) |
|
555 { |
|
556 iSaveBufPos = iDataEntry[ i ]; |
|
557 TUint32 ptr = Get32( iSaveBuf + iSaveBufPos ); |
|
558 ptr += doffset; |
|
559 Put32( ptr ); |
|
560 } |
|
561 |
|
562 delete[] iSaveDataBuf; |
|
563 iSaveDataBuf = NULL; |
|
564 iDataEntry.Reset(); |
|
565 |
|
566 TPtr8 buffer( iSaveBuf, totalLength ); |
|
567 buffer.SetLength( totalLength ); |
|
568 return buffer; |
|
569 } |
|
570 |
|
571 |
|
572 |
|
573 TUint32 CExifParser::Get8() |
|
574 { |
|
575 return iData[ iPosition++ ]; |
|
576 |
|
577 } |
|
578 |
|
579 |
|
580 |
|
581 TUint32 CExifParser::Get16() |
|
582 { |
|
583 TUint32 value; |
|
584 if( iIntelByteOrder ) |
|
585 { |
|
586 value = 256 * iData[ iPosition + 1 ] + iData[ iPosition ]; |
|
587 } |
|
588 else |
|
589 { |
|
590 value = 256 * iData[ iPosition ] + iData[ iPosition + 1 ]; |
|
591 } |
|
592 iPosition += 2; |
|
593 return value; |
|
594 } |
|
595 |
|
596 |
|
597 |
|
598 TUint32 CExifParser::Get32() |
|
599 { |
|
600 TUint32 value; |
|
601 if( iIntelByteOrder ) |
|
602 { |
|
603 value = iData[ iPosition + 3 ]; |
|
604 value <<= 8; |
|
605 value |= iData[ iPosition + 2 ]; |
|
606 value <<= 8; |
|
607 value |= iData[ iPosition + 1 ]; |
|
608 value <<= 8; |
|
609 value |= iData[ iPosition + 0 ]; |
|
610 } |
|
611 else |
|
612 { |
|
613 value = iData[ iPosition + 0 ]; |
|
614 value <<= 8; |
|
615 value |= iData[ iPosition + 1 ]; |
|
616 value <<= 8; |
|
617 value |= iData[ iPosition + 2 ]; |
|
618 value <<= 8; |
|
619 value |= iData[ iPosition + 3 ]; |
|
620 } |
|
621 iPosition += 4; |
|
622 return value; |
|
623 } |
|
624 |
|
625 |
|
626 |
|
627 TUint32 CExifParser::Get8( const TUint8* aData ) |
|
628 { |
|
629 return *aData; |
|
630 } |
|
631 |
|
632 |
|
633 |
|
634 TUint32 CExifParser::Get16( const TUint8* aData ) |
|
635 { |
|
636 TUint32 value; |
|
637 if( iIntelByteOrder ) |
|
638 { |
|
639 value = 256 * aData[ 1 ] + aData[ 0 ]; |
|
640 } |
|
641 else |
|
642 { |
|
643 value = 256 * aData[ 0 ] + aData[ 1 ]; |
|
644 } |
|
645 return value; |
|
646 } |
|
647 |
|
648 |
|
649 |
|
650 TUint32 CExifParser::Get32( const TUint8* aData ) |
|
651 { |
|
652 TUint32 value; |
|
653 if( iIntelByteOrder ) |
|
654 { |
|
655 value = aData[ 3 ]; |
|
656 value <<= 8; |
|
657 value |= aData[ 2 ]; |
|
658 value <<= 8; |
|
659 value |= aData[ 1 ]; |
|
660 value <<= 8; |
|
661 value |= aData[ 0 ]; |
|
662 } |
|
663 else |
|
664 { |
|
665 value = aData[ 0 ]; |
|
666 value <<= 8; |
|
667 value |= aData[ 1 ]; |
|
668 value <<= 8; |
|
669 value |= aData[ 2 ]; |
|
670 value <<= 8; |
|
671 value |= aData[ 3 ]; |
|
672 } |
|
673 return value; |
|
674 } |
|
675 |
|
676 |
|
677 |
|
678 void CExifParser::ParseIfdL( TUint8 aIfd ) |
|
679 { |
|
680 TUint32 tag = Get16(); |
|
681 TUint32 type = Get16(); |
|
682 TUint32 count = Get32(); |
|
683 TUint32 offset = Get32(); |
|
684 TUint32 revOffset = ( ( offset & 0xff ) << 24 ) + ( ( offset & 0xff00 ) << 8 ) + ( ( offset & 0xff0000 ) >> 8 ) + ( ( offset & 0xff000000 ) >> 24 ); |
|
685 |
|
686 RDebug::Print( _L("Pos %d, Tag %x, type %d, count %d, offset %d, ifd %d"), iPosition-14, tag, type, count, offset, aIfd ); |
|
687 |
|
688 const TUint8* valData = NULL; |
|
689 |
|
690 TInt bytes = KTypeLength[ type ] * count; |
|
691 |
|
692 if( bytes > 4 ) |
|
693 { |
|
694 valData = &iData[ offset ]; |
|
695 } |
|
696 else |
|
697 { |
|
698 if( iIntelByteOrder ) |
|
699 { |
|
700 valData = (const TUint8*)(&offset); |
|
701 } |
|
702 else |
|
703 { |
|
704 // offset already reversed |
|
705 // must use reversed offset |
|
706 valData = (const TUint8*)(&revOffset); |
|
707 } |
|
708 } |
|
709 |
|
710 |
|
711 TExifEntry* entry = new( ELeave )TExifEntry; |
|
712 CleanupStack::PushL(entry); |
|
713 entry->iIfd = aIfd; |
|
714 entry->iTag = tag; |
|
715 entry->iType = type; |
|
716 entry->iCount = count; |
|
717 |
|
718 TUint32 value = 0; |
|
719 |
|
720 entry->iData = new( ELeave )TUint8[ bytes ]; |
|
721 if( iIntelByteOrder ) |
|
722 { |
|
723 Mem::Copy( entry->iData, valData, bytes ); |
|
724 switch( type ) |
|
725 { |
|
726 case EByte: |
|
727 { |
|
728 value = Get8( valData ); |
|
729 break; |
|
730 } |
|
731 case EShort: |
|
732 { |
|
733 value = Get16( valData ); |
|
734 break; |
|
735 } |
|
736 case ELong: |
|
737 case ESLong: |
|
738 { |
|
739 value = Get32( valData ); |
|
740 break; |
|
741 } |
|
742 default: |
|
743 break; |
|
744 } |
|
745 } |
|
746 else |
|
747 { |
|
748 |
|
749 switch( type ) |
|
750 { |
|
751 case EByte: |
|
752 { |
|
753 value = Get8( valData ); |
|
754 entry->iData[ 0 ] = value; |
|
755 break; |
|
756 } |
|
757 case EAscii: |
|
758 { |
|
759 Mem::Copy( entry->iData, valData, bytes ); |
|
760 //RDebug::Print( str ); |
|
761 break; |
|
762 } |
|
763 case EShort: |
|
764 { |
|
765 entry->iData[ 1 ] = Get8( valData ); |
|
766 entry->iData[ 0 ] = Get8( valData+1 ); |
|
767 value = Get16( valData ); |
|
768 break; |
|
769 } |
|
770 case ELong: |
|
771 case ESLong: |
|
772 { |
|
773 entry->iData[ 3 ] = Get8( valData ); |
|
774 entry->iData[ 2 ] = Get8( valData+1 ); |
|
775 entry->iData[ 1 ] = Get8( valData+2 ); |
|
776 entry->iData[ 0 ] = Get8( valData+3 ); |
|
777 value = Get32( valData ); |
|
778 break; |
|
779 } |
|
780 case ERational: |
|
781 case ESRational: |
|
782 { |
|
783 entry->iData[ 3 ] = Get8( valData ); |
|
784 entry->iData[ 2 ] = Get8( valData+1 ); |
|
785 entry->iData[ 1 ] = Get8( valData+2 ); |
|
786 entry->iData[ 0 ] = Get8( valData+3 ); |
|
787 |
|
788 entry->iData[ 7 ] = Get8( valData+4 ); |
|
789 entry->iData[ 6 ] = Get8( valData+5 ); |
|
790 entry->iData[ 5 ] = Get8( valData+6 ); |
|
791 entry->iData[ 4 ] = Get8( valData+7 ); |
|
792 break; |
|
793 } |
|
794 case EUndefined: |
|
795 default: |
|
796 { |
|
797 Mem::Copy( entry->iData, valData, bytes ); |
|
798 break; |
|
799 } |
|
800 } |
|
801 } |
|
802 //RDebug::Print( _L("value=%d"), value ); |
|
803 |
|
804 iEntry.Append( entry ); |
|
805 CleanupStack::Pop(); |
|
806 |
|
807 |
|
808 if( tag == 0x927c ) |
|
809 { |
|
810 //RDebug::Print( _L(" --MakerNote") ); |
|
811 } |
|
812 |
|
813 if( tag == 0x8769 ) |
|
814 { |
|
815 iParseStack.Append( TParseStack( value, ESubIfd ) ); |
|
816 //RDebug::Print( _L(" --SubIfd %d, %d"), value, iPosition ); |
|
817 } |
|
818 |
|
819 if( tag == 0xa005 ) |
|
820 { |
|
821 iParseStack.Append( TParseStack( value, EInteroperability ) ); |
|
822 //RDebug::Print( _L(" --Interoperability, %d, %d"), value, iPosition ); |
|
823 } |
|
824 |
|
825 if( aIfd == EIfd1 ) |
|
826 { |
|
827 if( tag == 0x0201 ) |
|
828 { |
|
829 iThumbData = ((TUint8*)iData.Ptr()) + value; |
|
830 } |
|
831 if( tag == 0x0202 ) |
|
832 { |
|
833 iThumbLen = value; |
|
834 } |
|
835 } |
|
836 } |
|
837 |
|
838 |
|
839 |
|
840 TInt CExifParser::FindTag( TInt aIfd, TUint16 aTag ) |
|
841 { |
|
842 TInt i; |
|
843 TInt c = iEntry.Count(); |
|
844 for( i=0; i<c; i++ ) |
|
845 { |
|
846 if( iEntry[ i ]->iIfd == aIfd ) |
|
847 { |
|
848 if( iEntry[ i ]->iTag == aTag ) return i; |
|
849 } |
|
850 } |
|
851 return -1; |
|
852 } |
|
853 |
|
854 |
|
855 |
|
856 void CExifParser::StoreEntry( TInt aIndex ) |
|
857 { |
|
858 TExifEntry* e = iEntry[ aIndex ]; |
|
859 |
|
860 TUint32 count = e->iCount; |
|
861 TUint32 data = 0; |
|
862 TInt bytes = KTypeLength[ e->iType ] * count; |
|
863 TUint8* d = e->iData; |
|
864 |
|
865 bool realData = false; |
|
866 |
|
867 if( bytes <= 4 ) |
|
868 { |
|
869 // store data to offset |
|
870 TInt i; |
|
871 TInt shift = 0; |
|
872 for( i=0; i<bytes; i++ ) |
|
873 { |
|
874 data |= ( d[ i ] << shift ); |
|
875 shift += 8; |
|
876 } |
|
877 } |
|
878 else |
|
879 { |
|
880 // more than 4 bytes, store in data section |
|
881 data = StoreData( d, bytes ); |
|
882 realData = true; |
|
883 } |
|
884 |
|
885 Put16( e->iTag ); |
|
886 Put16( e->iType ); |
|
887 Put32( count ); |
|
888 if( realData ) |
|
889 { |
|
890 iDataEntry.Append( iSaveBufPos ); |
|
891 } |
|
892 Put32( data ); |
|
893 } |
|
894 |
|
895 |
|
896 |
|
897 void CExifParser::Put8( TUint8 aData ) |
|
898 { |
|
899 iSaveBuf[ iSaveBufPos++ ] = aData; |
|
900 } |
|
901 |
|
902 |
|
903 |
|
904 void CExifParser::Put16( TUint16 aData ) |
|
905 { |
|
906 Put8( aData & 255 ); |
|
907 Put8( aData / 256 ); |
|
908 /* |
|
909 if( iIntelByteOrder ) |
|
910 { |
|
911 Put8( aData & 255 ); |
|
912 Put8( aData / 256 ); |
|
913 } |
|
914 else |
|
915 { |
|
916 Put8( aData / 256 ); |
|
917 Put8( aData & 255 ); |
|
918 } |
|
919 */ |
|
920 } |
|
921 |
|
922 |
|
923 |
|
924 void CExifParser::Put32( TUint32 aData ) |
|
925 { |
|
926 Put16( aData & 65535 ); |
|
927 Put16( aData / 65536 ); |
|
928 /* |
|
929 if( iIntelByteOrder ) |
|
930 { |
|
931 Put16( aData & 65535 ); |
|
932 Put16( aData / 65536 ); |
|
933 } |
|
934 else |
|
935 { |
|
936 Put16( aData / 65536 ); |
|
937 Put16( aData & 65535 ); |
|
938 } |
|
939 */ |
|
940 } |
|
941 |
|
942 |
|
943 TUint32 CExifParser::StoreData( TUint8* aData, TInt aCount ) |
|
944 { |
|
945 if( iSaveDataBufPos & 1 ) iSaveDataBufPos++; // must be even offset |
|
946 TUint32 pos = iSaveDataBufPos; |
|
947 TInt i; |
|
948 for( i=0; i<aCount; i++ ) |
|
949 { |
|
950 iSaveDataBuf[ iSaveDataBufPos++ ] = aData[ i ]; |
|
951 } |
|
952 return pos; |
|
953 } |
|
954 |
|
955 |
|
956 TInt CExifParser::IfdCount( TInt aIfd ) |
|
957 { |
|
958 TInt count = 0; |
|
959 TInt c = iEntry.Count(); |
|
960 TInt i; |
|
961 for( i=0; i<c; i++ ) |
|
962 { |
|
963 TExifEntry* e = iEntry[ i ]; |
|
964 if( e->iIfd == aIfd ) |
|
965 { |
|
966 count++; |
|
967 } |
|
968 } |
|
969 return count; |
|
970 } |
|
971 |
|
972 |
|
973 |
|
974 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TInt32 aValue ) |
|
975 { |
|
976 TUint32 uvalue = *( TUint32* )( &aValue ); |
|
977 |
|
978 TUint8* data = new( ELeave )TUint8[ 4 ]; |
|
979 CleanupStack::PushL(data); |
|
980 if( iIntelByteOrder ) |
|
981 { |
|
982 data[ 0 ] = uvalue & 255; |
|
983 data[ 1 ] = ( uvalue >> 8 ) & 255; |
|
984 data[ 2 ] = ( uvalue >> 16 ) & 255; |
|
985 data[ 3 ] = ( uvalue >> 24 ) & 255; |
|
986 } |
|
987 else |
|
988 { |
|
989 data[ 3 ] = uvalue & 255; |
|
990 data[ 2 ] = ( uvalue >> 8 ) & 255; |
|
991 data[ 1 ] = ( uvalue >> 16 ) & 255; |
|
992 data[ 0 ] = ( uvalue >> 24 ) & 255; |
|
993 } |
|
994 AddTagL( aIfd, aTag, ESLong, data, 4 ); |
|
995 CleanupStack::Pop(); |
|
996 } |
|
997 |
|
998 |
|
999 |
|
1000 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TUint32 aValue ) |
|
1001 { |
|
1002 TUint8* data = new( ELeave )TUint8[ 4 ]; |
|
1003 CleanupStack::PushL(data); |
|
1004 if( iIntelByteOrder ) |
|
1005 { |
|
1006 data[ 0 ] = aValue & 255; |
|
1007 data[ 1 ] = ( aValue >> 8 ) & 255; |
|
1008 data[ 2 ] = ( aValue >> 16 ) & 255; |
|
1009 data[ 3 ] = ( aValue >> 24 ) & 255; |
|
1010 } |
|
1011 else |
|
1012 { |
|
1013 data[ 3 ] = aValue & 255; |
|
1014 data[ 2 ] = ( aValue >> 8 ) & 255; |
|
1015 data[ 1 ] = ( aValue >> 16 ) & 255; |
|
1016 data[ 0 ] = ( aValue >> 24 ) & 255; |
|
1017 } |
|
1018 AddTagL( aIfd, aTag, ELong, data, 4 ); |
|
1019 CleanupStack::Pop(); |
|
1020 } |
|
1021 |
|
1022 |
|
1023 |
|
1024 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TUint16 aValue ) |
|
1025 { |
|
1026 TUint8* data = new( ELeave )TUint8[ 2 ]; |
|
1027 CleanupStack::PushL(data); |
|
1028 if( iIntelByteOrder ) |
|
1029 { |
|
1030 data[ 0 ] = aValue & 255; |
|
1031 data[ 1 ] = aValue / 256; |
|
1032 } |
|
1033 else |
|
1034 { |
|
1035 data[ 1 ] = aValue & 255; |
|
1036 data[ 0 ] = aValue / 256; |
|
1037 } |
|
1038 AddTagL( aIfd, aTag, EShort, data, 2 ); |
|
1039 CleanupStack::Pop(); |
|
1040 } |
|
1041 |
|
1042 |
|
1043 |
|
1044 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TUint8 aValue ) |
|
1045 { |
|
1046 TUint8* data = new( ELeave )TUint8[ 1 ]; |
|
1047 CleanupStack::PushL(data); |
|
1048 *data = aValue; |
|
1049 AddTagL( aIfd, aTag, EByte, data, 1 ); |
|
1050 CleanupStack::Pop(); |
|
1051 } |
|
1052 |
|
1053 |
|
1054 |
|
1055 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TPtrC8 aData ) |
|
1056 { |
|
1057 TUint8* data = new( ELeave )TUint8[ aData.Length() ]; |
|
1058 CleanupStack::PushL(data); |
|
1059 Mem::Copy( data, aData.Ptr(), aData.Length() ); |
|
1060 AddTagL( aIfd, aTag, EUndefined, data, aData.Length() ); |
|
1061 CleanupStack::Pop(); |
|
1062 } |
|
1063 |
|
1064 |
|
1065 |
|
1066 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, const TUint8* aValue ) |
|
1067 { |
|
1068 TInt l = User::StringLength( aValue ) + 1; |
|
1069 TUint8* data = new( ELeave )TUint8[ l ]; |
|
1070 CleanupStack::PushL(data); |
|
1071 Mem::Copy( data, aValue, l ); |
|
1072 AddTagL( aIfd, aTag, EAscii, data, l ); |
|
1073 CleanupStack::Pop(); |
|
1074 } |
|
1075 |
|
1076 |
|
1077 |
|
1078 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TUint32 aNominator, TUint32 aDenominator ) |
|
1079 { |
|
1080 TUint8* data = new( ELeave )TUint8[ 8 ]; |
|
1081 CleanupStack::PushL(data); |
|
1082 if( iIntelByteOrder ) |
|
1083 { |
|
1084 data[ 0 ] = aNominator & 255; |
|
1085 data[ 1 ] = ( aNominator >> 8 ) & 255; |
|
1086 data[ 2 ] = ( aNominator >> 16 ) & 255; |
|
1087 data[ 3 ] = ( aNominator >> 24 ) & 255; |
|
1088 data[ 4 ] = aDenominator & 255; |
|
1089 data[ 5 ] = ( aDenominator >> 8 ) & 255; |
|
1090 data[ 6 ] = ( aDenominator >> 16 ) & 255; |
|
1091 data[ 7 ] = ( aDenominator >> 24 ) & 255; |
|
1092 } |
|
1093 else |
|
1094 { |
|
1095 data[ 3 ] = aNominator & 255; |
|
1096 data[ 2 ] = ( aNominator >> 8 ) & 255; |
|
1097 data[ 1 ] = ( aNominator >> 16 ) & 255; |
|
1098 data[ 0 ] = ( aNominator >> 24 ) & 255; |
|
1099 data[ 7 ] = aDenominator & 255; |
|
1100 data[ 6 ] = ( aDenominator >> 8 ) & 255; |
|
1101 data[ 5 ] = ( aDenominator >> 16 ) & 255; |
|
1102 data[ 4 ] = ( aDenominator >> 24 ) & 255; |
|
1103 } |
|
1104 AddTagL( aIfd, aTag, ERational, data, 8 ); |
|
1105 |
|
1106 CleanupStack::Pop(); |
|
1107 } |
|
1108 |
|
1109 |
|
1110 |
|
1111 void CExifParser::AddTagL( TInt aIfd, TUint16 aTag, TInt aType, TUint8* aData, TInt aDataLen ) |
|
1112 { |
|
1113 TExifEntry* e = new( ELeave )TExifEntry; |
|
1114 e->iIfd = aIfd; |
|
1115 e->iTag = aTag; |
|
1116 e->iType = aType; |
|
1117 e->iData = aData; |
|
1118 e->iCount = aDataLen / KTypeLength[ aType ]; |
|
1119 iEntry.Append( e ); |
|
1120 } |
|
1121 |
|
1122 |