1 /* Copyright (c) MediaArea.net SARL. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the License.html file in the root of the source tree.
5 */
6
7 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 //
9 // TIFF Format
10 //
11 // From
12 // http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
13 // http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf
14 // http://www.fileformat.info/format/tiff/
15 // http://en.wikipedia.org/wiki/Tagged_Image_File_Format
16 //
17 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
18
19 //---------------------------------------------------------------------------
20 // Pre-compilation
21 #include "MediaInfo/PreComp.h"
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25 //---------------------------------------------------------------------------
26
27 //---------------------------------------------------------------------------
28 #include "MediaInfo/Setup.h"
29 //---------------------------------------------------------------------------
30
31 //---------------------------------------------------------------------------
32 #if defined(MEDIAINFO_TIFF_YES)
33 //---------------------------------------------------------------------------
34
35 //---------------------------------------------------------------------------
36 #include "MediaInfo/Image/File_Tiff.h"
37 #include "ZenLib/Utils.h"
38 using namespace ZenLib;
39 //---------------------------------------------------------------------------
40
41 namespace MediaInfoLib
42 {
43
44 //***************************************************************************
45 // Info
46 //***************************************************************************
47
48 //---------------------------------------------------------------------------
49 namespace Tiff_Tag
50 {
51 const int16u ImageWidth = 256;
52 const int16u ImageLength = 257;
53 const int16u BitsPerSample = 258;
54 const int16u Compression = 259;
55 const int16u PhotometricInterpretation = 262;
56 const int16u ImageDescription = 270;
57 const int16u Make = 271;
58 const int16u Model = 272;
59 const int16u StripOffsets = 273;
60 const int16u SamplesPerPixel = 277;
61 const int16u RowsPerStrip = 278;
62 const int16u StripByteCounts = 279;
63 const int16u XResolution = 282;
64 const int16u YResolution = 283;
65 const int16u PlanarConfiguration = 284;
66 const int16u ResolutionUnit = 296;
67 const int16u Software = 305;
68 const int16u DateTime = 306;
69 const int16u ExtraSamples = 338;
70 }
71
72 //---------------------------------------------------------------------------
Tiff_Tag_Name(int32u Tag)73 static const char* Tiff_Tag_Name(int32u Tag)
74 {
75 switch (Tag)
76 {
77 case Tiff_Tag::ImageWidth : return "ImageWidth";
78 case Tiff_Tag::ImageLength : return "ImageLength";
79 case Tiff_Tag::BitsPerSample : return "BitsPerSample";
80 case Tiff_Tag::Compression : return "Compression";
81 case Tiff_Tag::PhotometricInterpretation : return "PhotometricInterpretation";
82 case Tiff_Tag::ImageDescription : return "ImageDescription";
83 case Tiff_Tag::Make : return "Make";
84 case Tiff_Tag::Model : return "Model";
85 case Tiff_Tag::StripOffsets : return "StripOffsets";
86 case Tiff_Tag::SamplesPerPixel : return "SamplesPerPixel";
87 case Tiff_Tag::RowsPerStrip : return "RowsPerStrip";
88 case Tiff_Tag::StripByteCounts : return "StripByteCounts";
89 case Tiff_Tag::XResolution : return "XResolution";
90 case Tiff_Tag::YResolution : return "YResolution";
91 case Tiff_Tag::PlanarConfiguration : return "PlanarConfiguration";
92 case Tiff_Tag::ResolutionUnit : return "ResolutionUnit";
93 case Tiff_Tag::Software : return "Software";
94 case Tiff_Tag::DateTime : return "DateTime";
95 case Tiff_Tag::ExtraSamples : return "ExtraSamples";
96 default : return "";
97 }
98 }
99
100 //---------------------------------------------------------------------------
101 namespace Tiff_Type
102 {
103 const int16u Byte = 1;
104 const int16u ASCII = 2;
105 const int16u Short = 3;
106 const int16u Long = 4;
107 const int16u Rational = 5;
108 }
109
110 //---------------------------------------------------------------------------
Tiff_Type_Name(int32u Type)111 static const char* Tiff_Type_Name(int32u Type)
112 {
113 switch (Type)
114 {
115 case Tiff_Type::Byte : return "Byte";
116 case Tiff_Type::ASCII : return "ASCII";
117 case Tiff_Type::Short : return "Short";
118 case Tiff_Type::Long : return "Long";
119 case Tiff_Type::Rational : return "Rational";
120 default : return ""; //Unknown
121 }
122 }
123
124 //---------------------------------------------------------------------------
Tiff_Type_Size(int32u Type)125 static const int8u Tiff_Type_Size(int32u Type)
126 {
127 switch (Type)
128 {
129 case Tiff_Type::Byte : return 1;
130 case Tiff_Type::ASCII : return 1;
131 case Tiff_Type::Short : return 2;
132 case Tiff_Type::Long : return 4;
133 case Tiff_Type::Rational : return 8;
134 default : return 0; //Unknown
135 }
136 }
137
138 //---------------------------------------------------------------------------
Tiff_Compression(int32u Compression)139 static const char* Tiff_Compression(int32u Compression)
140 {
141 switch (Compression)
142 {
143 case 1 : return "Raw";
144 case 2 : return "CCITT Group 3";
145 case 3 : return "CCITT T.4";
146 case 5 : return "LZW";
147 case 6 : return "JPEG (TIFF v6)";
148 case 7 : return "JPEG (ISO)";
149 case 8 : return "Deflate";
150 case 32773 : return "PackBits";
151 default : return ""; //Unknown
152 }
153 }
154
155 //---------------------------------------------------------------------------
Tiff_Compression_Mode(int32u Compression)156 static const char* Tiff_Compression_Mode(int32u Compression)
157 {
158 switch (Compression)
159 {
160 case 1 :
161 case 2 :
162 case 3 :
163 case 5 :
164 case 8 :
165 case 32773 : return "Lossless";
166 default : return ""; //Unknown or depends of the compresser (e.g. JPEG can be lossless or lossy)
167 }
168 }
169
170 //---------------------------------------------------------------------------
Tiff_PhotometricInterpretation(int32u PhotometricInterpretation)171 static const char* Tiff_PhotometricInterpretation(int32u PhotometricInterpretation)
172 {
173 switch (PhotometricInterpretation)
174 {
175 case 0 :
176 case 1 : return "B/W or Grey scale";
177 case 2 : return "RGB";
178 case 3 : return "Palette";
179 case 4 : return "Transparency mask";
180 case 5 : return "CMYK";
181 case 6 : return "YCbCr";
182 case 8 : return "CIELAB";
183 default : return ""; //Unknown
184 }
185 }
186
187 //---------------------------------------------------------------------------
Tiff_PhotometricInterpretation_ColorSpace(int32u PhotometricInterpretation)188 static const char* Tiff_PhotometricInterpretation_ColorSpace (int32u PhotometricInterpretation)
189 {
190 switch (PhotometricInterpretation)
191 {
192 case 0 :
193 case 1 : return "Y";
194 case 2 : return "RGB";
195 case 3 : return "RGB"; //Palette
196 case 4 : return "A"; //Transparency mask;
197 case 5 : return "CMYK";
198 case 6 : return "YUV"; //YCbCr
199 case 8 : return "CIELAB"; //What is it?
200 default : return ""; //Unknown
201 }
202 }
203
Tiff_ExtraSamples_ColorSpace(int32u ExtraSamples)204 static const char* Tiff_ExtraSamples_ColorSpace(int32u ExtraSamples)
205 {
206 switch (ExtraSamples)
207 {
208 case 1 : return "A";
209 default : return ""; //Unknown
210 }
211 }
212
213 //***************************************************************************
214 // Constructor/Destructor
215 //***************************************************************************
216
217 //---------------------------------------------------------------------------
File_Tiff()218 File_Tiff::File_Tiff()
219 {
220 }
221
222 //***************************************************************************
223 // Buffer - File header
224 //***************************************************************************
225
226 //---------------------------------------------------------------------------
FileHeader_Begin()227 bool File_Tiff::FileHeader_Begin()
228 {
229 //Element_Size
230 /* Minimum header for a tiff file is 8 byte */
231 if (Buffer_Size<8)
232 return false; //Must wait for more data
233 if (CC4(Buffer)==0x49492A00)
234 LittleEndian = true;
235 else if (CC4(Buffer)==0x4D4D002A)
236 LittleEndian = false;
237 else
238 {
239 Reject("TIFF");
240 return false;
241 }
242
243 //All should be OK...
244 Accept("TIFF");
245 Fill(Stream_General, 0, General_Format, "TIFF");
246 return true;
247 }
248
249 //---------------------------------------------------------------------------
FileHeader_Parse()250 void File_Tiff::FileHeader_Parse()
251 {
252 //The only IFD that is known at forehand is the first one, it's offset is placed byte 4-7 in the file.
253 int32u FirstIFDOffset;
254 Skip_B4( "Magic");
255 Get_X4 (FirstIFDOffset, "FirstIFDOffset");
256
257 FILLING_BEGIN();
258 //Initial IFD
259 GoTo_IfNeeded(FirstIFDOffset);
260 FILLING_END();
261 }
262
263 //***************************************************************************
264 // Buffer - Per element
265 //***************************************************************************
266
267 //---------------------------------------------------------------------------
Header_Parse()268 void File_Tiff::Header_Parse()
269 {
270 //Handling remaining IFD data
271 if (!IfdItems.empty())
272 {
273 if (File_Offset+Buffer_Offset!=IfdItems.begin()->first)
274 IfdItems.clear(); //There was a problem during the seek, trashing remaining positions from last IFD
275 else
276 {
277 #ifdef MEDIAINFO_TRACE
278 const char* Name=Tiff_Tag_Name(IfdItems.begin()->second.Tag);
279 if (!Name[0]) //Unknown
280 Header_Fill_Code(IfdItems.begin()->second.Tag, Ztring::ToZtring(IfdItems.begin()->second.Tag));
281 else
282 Header_Fill_Code(IfdItems.begin()->second.Tag, Name);
283 #else //MEDIAINFO_TRACE
284 Header_Fill_Code(IfdItems.begin()->second.Tag);
285 #endif //MEDIAINFO_TRACE
286 Header_Fill_Size(Tiff_Type_Size(IfdItems.begin()->second.Type)*IfdItems.begin()->second.Count);
287 return;
288 }
289 }
290
291 /* A tiff images consist in principle of two types of blocks, IFD's and data blocks */
292 /* Each datablock, which could be a image, tiles, transperancy filter is described by one IFD. */
293 /* These IFD's can be placed at any offset in the file and are linked in a chain fashion way. */
294 /* where one IFD points out where the next IFD is placed */
295 /* */
296 /* A creator of a tiff file must describe the "main image" in the first IFD, this means that a */
297 /* reader, such this one, only need to read the first IFD in order to get the bitdepth, resolution etc. */
298 /* of the main image. */
299
300 /* Read one IFD and print out the result */
301
302 /* Scan the tiff file for the IFD's (Image File Directory) */
303 /* As long as the IFD offset to the next IFD in the file is not 0 */
304
305 /* Get number of directories for this IFD */
306 int16u NrOfDirectories;
307 Get_X2 (NrOfDirectories, "NrOfDirectories");
308
309 //Filling
310 Header_Fill_Code(0xFFFFFFFF, "IFD"); //OxFFFFFFFF can not be a Tag, so using it as a magic value
311 Header_Fill_Size(2+12*((int64u)NrOfDirectories)+4); //2 for header + 12 per directory + 4 for next IFD offset
312 }
313
314 //---------------------------------------------------------------------------
Data_Parse()315 void File_Tiff::Data_Parse()
316 {
317 int32u IFDOffset=0;
318 if (IfdItems.empty())
319 {
320 //Default values
321 Infos.clear();
322 Infos[Tiff_Tag::BitsPerSample]=__T("1");
323
324 //Parsing new IFD
325 while (Element_Offset+8+4<Element_Size)
326 Read_Directory();
327 Get_X4 (IFDOffset, "IFDOffset");
328 }
329 else
330 {
331 //Handling remaining IFD data from a previous IFD
332 GetValueOffsetu(IfdItems.begin()->second); //Parsing the IFD item
333 IfdItems.erase(IfdItems.begin()->first); //Removing IFD item from the list of IFD items to parse
334 }
335
336 //Some items are not inside the directory, jumping to the offset
337 if (!IfdItems.empty())
338 GoTo_IfNeeded(IfdItems.begin()->first);
339 else
340 {
341 //This IFD is finished, filling data then going to next IFD
342 Data_Parse_Fill();
343 if (IFDOffset)
344 GoTo_IfNeeded(IFDOffset);
345 else
346 {
347 Finish(); //No more IFDs
348 GoToFromEnd(0);
349 }
350 }
351 }
352
353 //---------------------------------------------------------------------------
Data_Parse_Fill()354 void File_Tiff::Data_Parse_Fill()
355 {
356 Stream_Prepare(Stream_Image);
357 Fill(Stream_Image, 0, Image_Format_Settings, LittleEndian?"Little":"Big");
358 Fill(Stream_Image, 0, Image_Format_Settings_Endianness, LittleEndian?"Little":"Big");
359
360 infos::iterator Info;
361
362 //Width
363 Info=Infos.find(Tiff_Tag::ImageWidth);
364 if (Info!=Infos.end())
365 Fill(Stream_Image, StreamPos_Last, Image_Width, Info->second.Read());
366
367 //Height
368 Info=Infos.find(Tiff_Tag::ImageLength);
369 if (Info!=Infos.end())
370 Fill(Stream_Image, StreamPos_Last, Image_Height, Info->second.Read());
371
372 //BitsPerSample
373 Info=Infos.find(Tiff_Tag::BitsPerSample);
374 if (Info!=Infos.end())
375 {
376 if (Info->second.size()>1)
377 {
378 bool IsOk=true;
379 for (size_t Pos=1; Pos<Info->second.size(); ++Pos)
380 if (Info->second[Pos]!=Info->second[0])
381 IsOk=false;
382 if (IsOk)
383 Info->second.resize(1); //They are all same, we display 1 piece of information
384 }
385
386 Fill(Stream_Image, StreamPos_Last, Image_BitDepth, Info->second.Read());
387 }
388
389 //Compression
390 Info=Infos.find(Tiff_Tag::Compression);
391 if (Info!=Infos.end())
392 {
393 int32u Value=Info->second.Read().To_int32u();
394 Fill(Stream_Image, StreamPos_Last, Image_Format, Tiff_Compression(Value));
395 Fill(Stream_Image, StreamPos_Last, Image_Codec, Tiff_Compression(Value));
396 Fill(Stream_Image, StreamPos_Last, Image_Compression_Mode, Tiff_Compression_Mode(Value));
397 }
398
399 //PhotometricInterpretation
400 Info=Infos.find(Tiff_Tag::PhotometricInterpretation);
401 if (Info!=Infos.end())
402 {
403 int32u Value=Info->second.Read().To_int32u();
404 Fill(Stream_Image, StreamPos_Last, Image_ColorSpace, Tiff_PhotometricInterpretation_ColorSpace(Value));
405 //Note: should we differeniate between raw RGB and palette (also RGB actually...)
406 }
407
408 //ImageDescription
409 Info=Infos.find(Tiff_Tag::ImageDescription);
410 if (Info!=Infos.end())
411 Fill(Stream_Image, StreamPos_Last, Image_Title, Info->second.Read());
412
413 //Make
414 Info=Infos.find(Tiff_Tag::Make);
415 if (Info!=Infos.end())
416 Fill(Stream_General, StreamPos_Last, General_Encoded_Application_CompanyName, Info->second.Read());
417
418 //Model
419 Info=Infos.find(Tiff_Tag::Model);
420 if (Info!=Infos.end())
421 Fill(Stream_General, StreamPos_Last, General_Encoded_Library_Name, Info->second.Read());
422
423 //XResolution
424 Info=Infos.find(Tiff_Tag::XResolution);
425 if (Info!=Infos.end())
426 {
427 Fill(Stream_Image, StreamPos_Last, "Density_X", Info->second.Read());
428 Fill_SetOptions(Stream_Image, StreamPos_Last, "Density_X", "N NT");
429 }
430
431 //YResolution
432 Info=Infos.find(Tiff_Tag::YResolution);
433 if (Info!=Infos.end())
434 {
435 Fill(Stream_Image, StreamPos_Last, "Density_Y", Info->second.Read());
436 Fill_SetOptions(Stream_Image, StreamPos_Last, "Density_Y", "N NT");
437 }
438
439 //ResolutionUnit
440 Info=Infos.find(Tiff_Tag::ResolutionUnit);
441 if (Info!=Infos.end())
442 {
443 switch (Info->second.Read().To_int32u())
444 {
445 case 0 : break;
446 case 1 : Fill(Stream_Image, StreamPos_Last, "Density_Unit", "dpcm"); Fill_SetOptions(Stream_Image, StreamPos_Last, "Density_Unit", "N NT"); break;
447 case 2 : Fill(Stream_Image, StreamPos_Last, "Density_Unit", "dpi"); Fill_SetOptions(Stream_Image, StreamPos_Last, "Density_Unit", "N NT"); break;
448 default: Fill(Stream_Image, StreamPos_Last, "Density_Unit", Info->second.Read()); Fill_SetOptions(Stream_Image, StreamPos_Last, "Density_Unit", "N NT");
449 }
450 }
451 else if (Infos.find(Tiff_Tag::XResolution)!=Infos.end() || Infos.find(Tiff_Tag::YResolution)!=Infos.end())
452 {
453 Fill(Stream_Image, StreamPos_Last, "Density_Unit", "dpi");
454 Fill_SetOptions(Stream_Image, StreamPos_Last, "Density_Unit", "N NT");
455 }
456
457 //XResolution or YResolution
458 if (Infos.find(Tiff_Tag::XResolution)!=Infos.end() || Infos.find(Tiff_Tag::YResolution)!=Infos.end())
459 {
460 Ztring X=Retrieve(Stream_Image, StreamPos_Last, "Density_X");
461 if (X.empty())
462 X.assign(1, __T('?'));
463 Ztring Y=Retrieve(Stream_Image, StreamPos_Last, "Density_Y");
464 if (Y.empty())
465 Y.assign(1, __T('?'));
466 if (X!=Y)
467 {
468 X+=__T('x');
469 X+=Y;
470 }
471 Y=Retrieve(Stream_Image, StreamPos_Last, "Density_Unit");
472 if (!Y.empty())
473 {
474 X+=__T(' ');
475 X+=Y;
476 Fill(Stream_Image, StreamPos_Last, "Density/String", X);
477 }
478 }
479
480 //Software
481 Info=Infos.find(Tiff_Tag::Software);
482 if (Info!=Infos.end())
483 Fill(Stream_General, StreamPos_Last, General_Encoded_Application_Name, Info->second.Read());
484
485 //DateTime
486 Info=Infos.find(Tiff_Tag::DateTime);
487 if (Info!=Infos.end())
488 Fill(Stream_Image, StreamPos_Last, Image_Encoded_Date, Info->second.Read());
489
490 //ExtraSamples
491 Info=Infos.find(Tiff_Tag::ExtraSamples);
492 if (Info!=Infos.end())
493 {
494 Ztring ColorSpace=Retrieve(Stream_Image, StreamPos_Last, Image_ColorSpace);
495 ColorSpace+=Ztring().From_UTF8(Tiff_ExtraSamples_ColorSpace(Info->second.Read().To_int32u()));
496 Fill(Stream_Image, StreamPos_Last, Image_ColorSpace, ColorSpace, true);
497 }
498 }
499
500 //***************************************************************************
501 // Elements
502 //***************************************************************************
503
504 //---------------------------------------------------------------------------
Read_Directory()505 void File_Tiff::Read_Directory()
506 {
507 /* Each directory consist of 4 fields */
508 /* Get information for this directory */
509 Element_Begin0();
510 ifditem IfdItem;
511 Get_X2 (IfdItem.Tag, "Tag"); Param_Info1(Tiff_Tag_Name(IfdItem.Tag));
512 Get_X2 (IfdItem.Type, "Type"); Param_Info1(Tiff_Type_Name(IfdItem.Type));
513 Get_X4 (IfdItem.Count, "Count");
514 #ifdef MEDIAINFO_TRACE
515 const char* Name=Tiff_Tag_Name(IfdItem.Tag);
516 if (!Name[0]) //Unknown
517 Element_Name(Ztring::ToZtring(IfdItem.Tag));
518 else
519 Element_Name(Name);
520 #endif //MEDIAINFO_TRACE
521
522 int32u Size=Tiff_Type_Size(IfdItem.Type)*IfdItem.Count;
523 if (Size<=4)
524 {
525 GetValueOffsetu(IfdItem);
526
527 //Padding up, skip dummy bytes
528 if (Size<4)
529 Skip_XX(4-Size, "Padding");
530 }
531 else
532 {
533 int32u IFDOffset;
534 Get_X4 (IFDOffset, "IFDOffset");
535 IfdItems[IFDOffset]=IfdItem;
536 }
537 Element_End0();
538 }
539
540 //***************************************************************************
541 // Helpers
542 //***************************************************************************
543
544 //---------------------------------------------------------------------------
Get_X2(int16u & Info,const char * Name)545 void File_Tiff::Get_X2(int16u &Info, const char* Name)
546 {
547 if (LittleEndian)
548 Get_L2 (Info, Name);
549 else
550 Get_B2 (Info, Name);
551 }
552
553 //---------------------------------------------------------------------------
Get_X4(int32u & Info,const char * Name)554 void File_Tiff::Get_X4(int32u &Info, const char* Name)
555 {
556 if (LittleEndian)
557 Get_L4 (Info, Name);
558 else
559 Get_B4 (Info, Name);
560 }
561
562 //---------------------------------------------------------------------------
GetValueOffsetu(ifditem & IfdItem)563 void File_Tiff::GetValueOffsetu(ifditem &IfdItem)
564 {
565 ZtringList &Info=Infos[IfdItem.Tag]; Info.clear(); Info.Separator_Set(0, __T(" / "));
566
567 if (IfdItem.Type!=Tiff_Type::ASCII && IfdItem.Count>=1000)
568 {
569 //Too many data, we don't currently need it and we skip it
570 Skip_XX(Tiff_Type_Size(IfdItem.Type)*IfdItem.Count, "Data");
571 return;
572 }
573
574 switch (IfdItem.Type)
575 {
576 case 1: /* 8-bit unsigned integer. */
577 for (int16u Pos=0; Pos<IfdItem.Count; Pos++)
578 {
579 int8u Ret8;
580 #if MEDIAINFO_TRACE
581 Get_B1 (Ret8, "Data"); //L1 and B1 are same
582 Element_Info1(Ztring::ToZtring(Ret8));
583 #else //MEDIAINFO_TRACE
584 if (Element_Offset+1>Element_Size)
585 {
586 Trusted_IsNot();
587 break;
588 }
589 Ret8=BigEndian2int8u(Buffer+Buffer_Offset+(size_t)Element_Offset); //LittleEndian2int8u and BigEndian2int8u are same
590 Element_Offset++;
591 #endif //MEDIAINFO_TRACE
592 Info.push_back(Ztring::ToZtring(Ret8));
593 }
594 break;
595 case 2: /* ASCII */
596 {
597 string Data;
598 Get_String(IfdItem.Count, Data, "Data"); Element_Info1(Data.c_str()); //TODO: multiple strings separated by NULL
599 Info.push_back(Ztring().From_UTF8(Data.c_str()));
600 }
601 break;
602 case 3: /* 16-bit (2-byte) unsigned integer. */
603 for (int16u Pos=0; Pos<IfdItem.Count; Pos++)
604 {
605 int16u Ret16;
606 #if MEDIAINFO_TRACE
607 if (LittleEndian)
608 Get_L2 (Ret16, "Data");
609 else
610 Get_B2 (Ret16, "Data");
611 switch (IfdItem.Tag)
612 {
613 case Tiff_Tag::Compression : Element_Info1(Tiff_Compression(Ret16)); break;
614 case Tiff_Tag::PhotometricInterpretation : Element_Info1(Tiff_PhotometricInterpretation(Ret16)); break;
615 default : Element_Info1(Ztring::ToZtring(Ret16));
616 }
617 #else //MEDIAINFO_TRACE
618 if (Element_Offset+2>Element_Size)
619 {
620 Trusted_IsNot();
621 break;
622 }
623 if (LittleEndian)
624 Ret16=LittleEndian2int16u(Buffer+Buffer_Offset+(size_t)Element_Offset);
625 else
626 Ret16=BigEndian2int16u(Buffer+Buffer_Offset+(size_t)Element_Offset);
627 Element_Offset+=2;
628 #endif //MEDIAINFO_TRACE
629 Info.push_back(Ztring::ToZtring(Ret16));
630 }
631 break;
632
633 case 4: /* 32-bit (4-byte) unsigned integer */
634 for (int16u Pos=0; Pos<IfdItem.Count; Pos++)
635 {
636 int32u Ret32;
637 #if MEDIAINFO_TRACE
638 if (LittleEndian)
639 Get_L4 (Ret32, "Data");
640 else
641 Get_B4 (Ret32, "Data");
642 Element_Info1(Ztring::ToZtring(Ret32));
643 #else //MEDIAINFO_TRACE
644 if (Element_Offset+4>Element_Size)
645 {
646 Trusted_IsNot();
647 break;
648 }
649 if (LittleEndian)
650 Ret32=LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset);
651 else
652 Ret32=BigEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset);
653 Element_Offset+=4;
654 #endif //MEDIAINFO_TRACE
655 Info.push_back(Ztring::ToZtring(Ret32));
656 }
657 break;
658
659 case 5: /* 2x32-bit (2x4-byte) unsigned integers */
660 for (int16u Pos=0; Pos<IfdItem.Count; Pos++)
661 {
662 int32u N, D;
663 #if MEDIAINFO_TRACE
664 if (LittleEndian)
665 {
666 Get_L4 (N, "Numerator");
667 Get_L4 (D, "Denominator");
668 }
669 else
670 {
671 Get_B4 (N, "Numerator");
672 Get_B4 (D, "Denominator");
673 }
674 if (D)
675 Element_Info1(Ztring::ToZtring(((float64)N)/D));
676 #else //MEDIAINFO_TRACE
677 if (Element_Offset+8>Element_Size)
678 {
679 Trusted_IsNot();
680 break;
681 }
682 if (LittleEndian)
683 {
684 N=LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset);
685 D=LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset);
686 }
687 else
688 {
689 N=BigEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset);
690 D=BigEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset);
691 }
692 Element_Offset+=8;
693 #endif //MEDIAINFO_TRACE
694 if (D)
695 Info.push_back(Ztring::ToZtring(((float64)N)/D, D==1?0:3));
696 else
697 Info.push_back(Ztring()); // Division by zero, undefined
698 }
699 break;
700
701 default: //Unknown
702 Skip_XX(Tiff_Type_Size(IfdItem.Type)*IfdItem.Count, "Data");
703 }
704 }
705
706 //---------------------------------------------------------------------------
GoTo_IfNeeded(int64u GoTo_)707 void File_Tiff::GoTo_IfNeeded(int64u GoTo_) //TODO: move that in a generic section, but tests showed regressions, for later (main difference is text trace, info part)
708 {
709 if (File_Offset+Buffer_Offset+Element_Offset==GoTo_)
710 return; //Useless
711
712 GoTo(GoTo_);
713 }
714
715
716 } //NameSpace
717
718 #endif
719
720