root/tags/gdal_1_3_2/gcore/gdaljp2box.cpp

Revision 8991, 8.2 kB (checked in by fwarmerdam, 3 years ago)

Fixed bug in ReadBox?() with boxes where LBox is 1 and the length
is read from the XLBox (such as GeoJP2 UUID Boxes from Erdas Imagine).
http://bugzilla.remotesensing.org/show_bug.cgi?id=1032

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  GDAL
5  * Purpose:  GDALJP2Box Implementation - Low level JP2 box reader.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
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  * $Log$
31  * Revision 1.5  2006/01/11 06:30:18  fwarmerdam
32  * Fixed bug in ReadBox() with boxes where LBox is 1 and the length
33  * is read from the XLBox (such as GeoJP2 UUID Boxes from Erdas Imagine).
34  * http://bugzilla.remotesensing.org/show_bug.cgi?id=1032
35  *
36  * Revision 1.4  2005/09/14 19:26:50  fwarmerdam
37  * added better debug output
38  *
39  * Revision 1.3  2005/09/14 13:13:17  dron
40  * Avoid warnings in DumpReadable().
41  *
42  * Revision 1.2  2005/05/09 14:42:33  fwarmerdam
43  * Fixed to use VSFReadL() instead of VSIFRead().
44  *
45  * Revision 1.1  2005/05/03 21:10:59  fwarmerdam
46  * New
47  *
48  */
49
50 #include "gdaljp2metadata.h"
51 #include "cpl_string.h"
52
53 CPL_CVSID("$Id$");
54
55 /************************************************************************/
56 /*                             GDALJP2Box()                             */
57 /************************************************************************/
58
59 GDALJP2Box::GDALJP2Box( FILE *fpIn )
60
61 {
62     fpVSIL = fpIn;
63     szBoxType[0] = '\0';
64     nBoxOffset = -1;
65     nDataOffset = -1;
66     nBoxLength = 0;
67 }
68
69 /************************************************************************/
70 /*                            ~GDALJP2Box()                             */
71 /************************************************************************/
72
73 GDALJP2Box::~GDALJP2Box()
74
75 {
76 }
77
78 /************************************************************************/
79 /*                             SetOffset()                              */
80 /************************************************************************/
81
82 int  GDALJP2Box::SetOffset( GIntBig nNewOffset )
83
84 {
85     szBoxType[0] = '\0';
86     return VSIFSeekL( fpVSIL, nNewOffset, SEEK_SET ) == 0;
87 }
88
89 /************************************************************************/
90 /*                             ReadFirst()                              */
91 /************************************************************************/
92
93 int GDALJP2Box::ReadFirst()
94
95 {
96     return SetOffset(0) && ReadBox();
97 }
98
99 /************************************************************************/
100 /*                              ReadNext()                              */
101 /************************************************************************/
102
103 int GDALJP2Box::ReadNext()
104
105 {
106     return SetOffset( nBoxOffset + nBoxLength ) && ReadBox();
107 }
108
109 /************************************************************************/
110 /*                           ReadFirstChild()                           */
111 /************************************************************************/
112
113 int GDALJP2Box::ReadFirstChild( GDALJP2Box *poSuperBox )
114
115 {
116     if( !poSuperBox->IsSuperBox() )
117         return FALSE;
118
119     return SetOffset( poSuperBox->nDataOffset ) && ReadBox();
120 }
121
122 /************************************************************************/
123 /*                           ReadNextChild()                            */
124 /************************************************************************/
125
126 int GDALJP2Box::ReadNextChild( GDALJP2Box *poSuperBox )
127
128 {
129     if( !ReadNext() )
130         return FALSE;
131
132     if( nBoxOffset >= poSuperBox->nBoxOffset + poSuperBox->nBoxLength )
133     {
134         szBoxType[0] = '\0';
135         return FALSE;
136     }
137
138     return TRUE;
139 }
140
141 /************************************************************************/
142 /*                              ReadBox()                               */
143 /************************************************************************/
144
145 int GDALJP2Box::ReadBox()
146
147 {
148     GUInt32   nLBox;
149     GUInt32   nTBox;
150
151     nBoxOffset = VSIFTellL( fpVSIL );
152
153     if( VSIFReadL( &nLBox, 4, 1, fpVSIL ) != 1
154         || VSIFReadL( &nTBox, 4, 1, fpVSIL ) != 1 )
155     {
156         return FALSE;
157     }
158
159     memcpy( szBoxType, &nTBox, 4 );
160     szBoxType[4] = '\0';
161
162     nLBox = CPL_MSBWORD32( nLBox );
163
164     if( nLBox != 1 )
165     {
166         nBoxLength = nLBox;
167         nDataOffset = nBoxOffset + 8;
168     }
169     else
170     {
171         GByte abyXLBox[8];
172         if( VSIFReadL( abyXLBox, 8, 1, fpVSIL ) != 1 )
173             return FALSE;
174
175        
176         if( sizeof(nBoxLength) == 64 )
177         {
178             CPL_MSBPTR64( abyXLBox );
179             memcpy( &nBoxLength, abyXLBox, 8 );
180         }
181         else
182         {
183             CPL_MSBPTR32( abyXLBox+4 );
184             memcpy( &nBoxLength, abyXLBox+4, 4 );
185         }
186
187         nDataOffset = nBoxOffset + 16;
188     }
189
190     if( nBoxLength == 0 )
191     {
192         VSIFSeekL( fpVSIL, 0, SEEK_END );
193         nBoxLength = VSIFTellL( fpVSIL ) - nBoxOffset;
194     }
195
196     if( EQUAL(szBoxType,"uuid") )
197     {
198         VSIFReadL( abyUUID, 16, 1, fpVSIL );
199         nDataOffset += 16;
200     }
201
202     return TRUE;
203 }
204
205 /************************************************************************/
206 /*                             IsSuperBox()                             */
207 /************************************************************************/
208
209 int GDALJP2Box::IsSuperBox()
210
211 {
212     if( EQUAL(GetType(),"asoc") || EQUAL(GetType(),"jp2h") )
213         return TRUE;
214     else
215         return FALSE;
216 }
217
218 /************************************************************************/
219 /*                            ReadBoxData()                             */
220 /************************************************************************/
221
222 GByte *GDALJP2Box::ReadBoxData()
223
224 {
225     char *pszData = (char *) CPLMalloc(GetDataLength() + 1);
226
227     if( VSIFReadL( pszData, 1, GetDataLength(), fpVSIL ) != GetDataLength() )
228     {
229         CPLFree( pszData );
230         return NULL;
231     }
232
233     pszData[GetDataLength()] = '\0';
234
235     return (GByte *) pszData;
236 }
237
238 /************************************************************************/
239 /*                           GetDataLength()                            */
240 /************************************************************************/
241
242 GIntBig GDALJP2Box::GetDataLength()
243 {
244     return nBoxLength - (nDataOffset - nBoxOffset);
245 }
246
247 /************************************************************************/
248 /*                            DumpReadable()                            */
249 /************************************************************************/
250
251 int GDALJP2Box::DumpReadable( FILE *fpOut )
252
253 {
254     if( fpOut == NULL )
255         fpOut = stdout;
256
257     fprintf( fpOut, "  Type=%s, Offset=%d/%d, Data Size=%d",
258              szBoxType, (int) nBoxOffset, (int) nDataOffset,
259              (int)(nBoxLength - (nDataOffset - nBoxOffset)) );
260
261     if( IsSuperBox() )
262         fprintf( fpOut, " (super)" );
263
264     fprintf( fpOut, "\n" );
265     if( EQUAL(GetType(),"uuid") )
266     {
267         char *pszHex = CPLBinaryToHex( 16, GetUUID() );
268         fprintf( fpOut, "    UUID=%s", pszHex );
269
270         if( EQUAL(pszHex,"B14BF8BD083D4B43A5AE8CD7D5A6CE03") )
271             fprintf( fpOut, " (GeoTIFF)" );
272         if( EQUAL(pszHex,"96A9F1F1DC98402DA7AED68E34451809") )
273             fprintf( fpOut, " (MSI Worldfile)" );
274         CPLFree( pszHex );
275
276         fprintf( fpOut, "\n" );
277     }
278     return 0;
279 }
Note: See TracBrowser for help on using the browser.