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