1 /******************************************************************************
2  * $Id: xritheaderparser.cpp 15066 2008-07-28 20:21:59Z mloskot $
3  *
4  * Purpose:  Implementation of XRITHeaderParser class. Parse the header
5  *           of the combined XRIT header/data files.
6  * Author:   Bas Retsios, retsios@itc.nl
7  *
8  ******************************************************************************
9  * Copyright (c) 2007, ITC
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ******************************************************************************/
29 
30 #include "xritheaderparser.h"
31 #include <cstdlib> // malloc, free
32 #include <cstring> // memcpy
33 
34 //////////////////////////////////////////////////////////////////////
35 // Construction/Destruction
36 //
37 // Upon successful parsing of a header in ifile, isValid() returns true
38 // and ifile is seeked to the beginning of the image data
39 //////////////////////////////////////////////////////////////////////
40 
XRITHeaderParser(std::ifstream & ifile)41 XRITHeaderParser::XRITHeaderParser(std::ifstream & ifile)
42 : m_isValid(false)
43 , m_isPrologue(false)
44 , m_dataSize(0)
45 , m_nrBitsPerPixel(0)
46 , m_nrColumns(0)
47 , m_nrRows(0)
48 , m_scanNorth(false)
49 {
50   const unsigned int probeSize = 8;
51 
52   unsigned char probeBuf[probeSize];
53   ifile.read((char*)probeBuf, probeSize); // Probe file by reading first 8 bytes
54 
55   if (probeBuf[0] == 0 && probeBuf[1] == 0 && probeBuf[2] == 16) // Check for primary header record
56   {
57     long totalHeaderLength = parseInt32(&probeBuf[4]);
58     if ((totalHeaderLength >= 10) && (totalHeaderLength <= 10000)) // Check for valid header length
59     {
60       unsigned char * buf = (unsigned char*)std::malloc(totalHeaderLength);
61       std::memcpy(buf, probeBuf, probeSize); // save what we have already read when probing
62       ifile.read((char*)buf + probeSize, totalHeaderLength - probeSize); // read the rest of the header section
63       parseHeader(buf, totalHeaderLength);
64       std::free(buf);
65 
66       m_isValid = true;
67     }
68   }
69 
70   if (!m_isValid) // seek back to original position
71   {
72 #if _MSC_VER > 1000 && _MSC_VER < 1300
73     ifile.seekg(-probeSize, std::ios_base::seekdir::cur);
74 #else
75     ifile.seekg(-probeSize, std::ios_base::cur);
76 #endif
77   }
78 }
79 
~XRITHeaderParser()80 XRITHeaderParser::~XRITHeaderParser()
81 {
82 
83 }
84 
parseInt16(unsigned char * num)85 int XRITHeaderParser::parseInt16(unsigned char * num)
86 {
87   return (num[0]<<8) | num[1];
88 }
89 
parseInt32(unsigned char * num)90 long XRITHeaderParser::parseInt32(unsigned char * num)
91 {
92   return (num[0]<<24) | (num[1]<<16) | (num[2]<<8) | num[3];
93 }
94 
parseHeader(unsigned char * buf,long totalHeaderLength)95 void XRITHeaderParser::parseHeader(unsigned char * buf, long totalHeaderLength)
96 {
97   int remainingHeaderLength = totalHeaderLength;
98 
99   while (remainingHeaderLength > 0)
100   {
101     int headerType = buf[0];
102     int headerRecordLength = parseInt16(&buf[1]);
103     if (headerRecordLength > remainingHeaderLength)
104       break;
105 
106     switch(headerType)
107     {
108       case 0: // primary header
109         {
110           int fileTypeCode = buf[3]; // 0 = image data file, 128 = prologue
111           if (fileTypeCode == 128)
112             m_isPrologue = true;
113 
114           long dataFieldLengthH = parseInt32(&buf[8]); // length of data field in bits (High DWORD)
115           long dataFieldLengthL = parseInt32(&buf[12]); // length of data field in bits (Low DWORD)
116           m_dataSize = (dataFieldLengthH << 5) + (dataFieldLengthL >> 3); // combine and convert bits to bytes
117         }
118         break;
119       case 1: // image structure
120         m_nrBitsPerPixel = buf[3]; // NB, number of bits per pixel
121         m_nrColumns = parseInt16(&buf[4]); // NC, number of columns
122         m_nrRows = parseInt16(&buf[6]); // NL, number of lines
123         break;
124       case 2: // image navigation
125         {
126           long cfac = parseInt32(&buf[35]); // column scaling factor
127           long lfac = parseInt32(&buf[39]); // line scaling factor
128           long coff = parseInt32(&buf[43]); // column offset
129           long loff = parseInt32(&buf[47]); // line offset
130           if (lfac >= 0)
131             m_scanNorth = true;
132           else
133             m_scanNorth = false;
134         }
135         break;
136       case 3: // image data function
137       case 4: // annotation
138       case 5: // time stamp
139       case 6: // ancillary text
140       case 7: // key header
141       case 128: // image segment identification
142       case 129: // encryption key message header
143       case 130: // image compensation information header
144       case 131: // image observation time header
145       case 132: // image quality information header
146         break;
147       default: // ignore unknown header type
148         break;
149     }
150 
151     buf += headerRecordLength;
152     remainingHeaderLength -= headerRecordLength;
153   }
154 }
155