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