1 : /******************************************************************************
2 : * $Id: jdemdataset.cpp 25143 2012-10-16 18:49:32Z rouault $
3 : *
4 : * Project: JDEM Reader
5 : * Purpose: All code for Japanese DEM Reader
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, 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 : #include "gdal_pam.h"
31 :
32 : CPL_CVSID("$Id: jdemdataset.cpp 25143 2012-10-16 18:49:32Z rouault $");
33 :
34 : CPL_C_START
35 : void GDALRegister_JDEM(void);
36 : CPL_C_END
37 :
38 : /************************************************************************/
39 : /* JDEMGetField() */
40 : /************************************************************************/
41 :
42 8 : static int JDEMGetField( char *pszField, int nWidth )
43 :
44 : {
45 : char szWork[32];
46 :
47 8 : CPLAssert( nWidth < (int) sizeof(szWork) );
48 :
49 8 : strncpy( szWork, pszField, nWidth );
50 8 : szWork[nWidth] = '\0';
51 :
52 8 : return atoi(szWork);
53 : }
54 :
55 : /************************************************************************/
56 : /* JDEMGetAngle() */
57 : /************************************************************************/
58 :
59 0 : static double JDEMGetAngle( char *pszField )
60 :
61 : {
62 0 : int nAngle = JDEMGetField( pszField, 7 );
63 : int nDegree, nMin, nSec;
64 :
65 : // Note, this isn't very general purpose, but it would appear
66 : // from the field widths that angles are never negative. Nice
67 : // to be a country in the "first quadrant".
68 :
69 0 : nDegree = nAngle / 10000;
70 0 : nMin = (nAngle / 100) % 100;
71 0 : nSec = nAngle % 100;
72 :
73 0 : return nDegree + nMin / 60.0 + nSec / 3600.0;
74 : }
75 :
76 : /************************************************************************/
77 : /* ==================================================================== */
78 : /* JDEMDataset */
79 : /* ==================================================================== */
80 : /************************************************************************/
81 :
82 : class JDEMRasterBand;
83 :
84 : class JDEMDataset : public GDALPamDataset
85 : {
86 : friend class JDEMRasterBand;
87 :
88 : VSILFILE *fp;
89 : GByte abyHeader[1012];
90 :
91 : public:
92 : JDEMDataset();
93 : ~JDEMDataset();
94 :
95 : static GDALDataset *Open( GDALOpenInfo * );
96 : static int Identify( GDALOpenInfo * );
97 :
98 : CPLErr GetGeoTransform( double * padfTransform );
99 : const char *GetProjectionRef();
100 : };
101 :
102 : /************************************************************************/
103 : /* ==================================================================== */
104 : /* JDEMRasterBand */
105 : /* ==================================================================== */
106 : /************************************************************************/
107 :
108 : class JDEMRasterBand : public GDALPamRasterBand
109 : {
110 : friend class JDEMDataset;
111 :
112 : int nRecordSize;
113 : char* pszRecord;
114 : int bBufferAllocFailed;
115 :
116 : public:
117 :
118 : JDEMRasterBand( JDEMDataset *, int );
119 : ~JDEMRasterBand();
120 :
121 : virtual CPLErr IReadBlock( int, int, void * );
122 : };
123 :
124 :
125 : /************************************************************************/
126 : /* JDEMRasterBand() */
127 : /************************************************************************/
128 :
129 1 : JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, int nBand )
130 :
131 : {
132 1 : this->poDS = poDS;
133 1 : this->nBand = nBand;
134 :
135 1 : eDataType = GDT_Float32;
136 :
137 1 : nBlockXSize = poDS->GetRasterXSize();
138 1 : nBlockYSize = 1;
139 :
140 : /* Cannot overflow as nBlockXSize <= 999 */
141 1 : nRecordSize = nBlockXSize*5 + 9 + 2;
142 1 : pszRecord = NULL;
143 1 : bBufferAllocFailed = FALSE;
144 1 : }
145 :
146 : /************************************************************************/
147 : /* ~JDEMRasterBand() */
148 : /************************************************************************/
149 :
150 1 : JDEMRasterBand::~JDEMRasterBand()
151 : {
152 1 : VSIFree(pszRecord);
153 1 : }
154 :
155 : /************************************************************************/
156 : /* IReadBlock() */
157 : /************************************************************************/
158 :
159 2 : CPLErr JDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
160 : void * pImage )
161 :
162 : {
163 2 : JDEMDataset *poGDS = (JDEMDataset *) poDS;
164 : int i;
165 :
166 2 : if (pszRecord == NULL)
167 : {
168 1 : if (bBufferAllocFailed)
169 0 : return CE_Failure;
170 :
171 1 : pszRecord = (char *) VSIMalloc(nRecordSize);
172 1 : if (pszRecord == NULL)
173 : {
174 : CPLError(CE_Failure, CPLE_OutOfMemory,
175 0 : "Cannot allocate scanline buffer");
176 0 : bBufferAllocFailed = TRUE;
177 0 : return CE_Failure;
178 : }
179 : }
180 :
181 2 : VSIFSeekL( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET );
182 :
183 2 : VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp );
184 :
185 2 : if( !EQUALN((char *) poGDS->abyHeader,pszRecord,6) )
186 : {
187 : CPLError( CE_Failure, CPLE_AppDefined,
188 : "JDEM Scanline corrupt. Perhaps file was not transferred\n"
189 0 : "in binary mode?" );
190 0 : return CE_Failure;
191 : }
192 :
193 2 : if( JDEMGetField( pszRecord + 6, 3 ) != nBlockYOff + 1 )
194 : {
195 : CPLError( CE_Failure, CPLE_AppDefined,
196 : "JDEM scanline out of order, JDEM driver does not\n"
197 0 : "currently support partial datasets." );
198 0 : return CE_Failure;
199 : }
200 :
201 6 : for( i = 0; i < nBlockXSize; i++ )
202 4 : ((float *) pImage)[i] = (float)
203 4 : (JDEMGetField( pszRecord + 9 + 5 * i, 5) * 0.1);
204 :
205 2 : return CE_None;
206 : }
207 :
208 : /************************************************************************/
209 : /* ==================================================================== */
210 : /* JDEMDataset */
211 : /* ==================================================================== */
212 : /************************************************************************/
213 :
214 : /************************************************************************/
215 : /* JDEMDataset() */
216 : /************************************************************************/
217 :
218 1 : JDEMDataset::JDEMDataset() : fp(NULL)
219 :
220 : {
221 1 : fp = NULL;
222 1 : }
223 :
224 : /************************************************************************/
225 : /* ~JDEMDataset() */
226 : /************************************************************************/
227 :
228 1 : JDEMDataset::~JDEMDataset()
229 :
230 : {
231 1 : FlushCache();
232 1 : if( fp != NULL )
233 1 : VSIFCloseL( fp );
234 1 : }
235 :
236 : /************************************************************************/
237 : /* GetGeoTransform() */
238 : /************************************************************************/
239 :
240 0 : CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
241 :
242 : {
243 : double dfLLLat, dfLLLong, dfURLat, dfURLong;
244 :
245 0 : dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 );
246 0 : dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 );
247 0 : dfURLat = JDEMGetAngle( (char *) abyHeader + 43 );
248 0 : dfURLong = JDEMGetAngle( (char *) abyHeader + 50 );
249 :
250 0 : padfTransform[0] = dfLLLong;
251 0 : padfTransform[3] = dfURLat;
252 0 : padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize();
253 0 : padfTransform[2] = 0.0;
254 :
255 0 : padfTransform[4] = 0.0;
256 0 : padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize();
257 :
258 :
259 0 : return CE_None;
260 : }
261 :
262 : /************************************************************************/
263 : /* GetProjectionRef() */
264 : /************************************************************************/
265 :
266 0 : const char *JDEMDataset::GetProjectionRef()
267 :
268 : {
269 0 : return( "GEOGCS[\"Tokyo\",DATUM[\"Tokyo\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,507,685,0,0,0,0],AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4301]]" );
270 : }
271 :
272 : /************************************************************************/
273 : /* Identify() */
274 : /************************************************************************/
275 :
276 13726 : int JDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
277 :
278 : {
279 : /* -------------------------------------------------------------------- */
280 : /* Confirm that the header has what appears to be dates in the */
281 : /* expected locations. Sadly this is a relatively weak test. */
282 : /* -------------------------------------------------------------------- */
283 13726 : if( poOpenInfo->nHeaderBytes < 50 )
284 11906 : return FALSE;
285 :
286 : /* check if century values seem reasonable */
287 1820 : if( (!EQUALN((char *)poOpenInfo->pabyHeader+11,"19",2)
288 : && !EQUALN((char *)poOpenInfo->pabyHeader+11,"20",2))
289 : || (!EQUALN((char *)poOpenInfo->pabyHeader+15,"19",2)
290 : && !EQUALN((char *)poOpenInfo->pabyHeader+15,"20",2))
291 : || (!EQUALN((char *)poOpenInfo->pabyHeader+19,"19",2)
292 : && !EQUALN((char *)poOpenInfo->pabyHeader+19,"20",2)) )
293 : {
294 1819 : return FALSE;
295 : }
296 :
297 1 : return TRUE;
298 : }
299 :
300 : /************************************************************************/
301 : /* Open() */
302 : /************************************************************************/
303 :
304 3632 : GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
305 :
306 : {
307 3632 : if (!Identify(poOpenInfo))
308 3631 : return NULL;
309 :
310 : /* -------------------------------------------------------------------- */
311 : /* Confirm the requested access is supported. */
312 : /* -------------------------------------------------------------------- */
313 1 : if( poOpenInfo->eAccess == GA_Update )
314 : {
315 : CPLError( CE_Failure, CPLE_NotSupported,
316 : "The JDEM driver does not support update access to existing"
317 0 : " datasets.\n" );
318 0 : return NULL;
319 : }
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* Create a corresponding GDALDataset. */
323 : /* -------------------------------------------------------------------- */
324 : JDEMDataset *poDS;
325 :
326 1 : poDS = new JDEMDataset();
327 :
328 1 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
329 1 : if (poDS->fp == NULL)
330 : {
331 0 : delete poDS;
332 0 : return NULL;
333 : }
334 :
335 : /* -------------------------------------------------------------------- */
336 : /* Read the header. */
337 : /* -------------------------------------------------------------------- */
338 1 : VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp );
339 :
340 1 : poDS->nRasterXSize = JDEMGetField( (char *) poDS->abyHeader + 23, 3 );
341 1 : poDS->nRasterYSize = JDEMGetField( (char *) poDS->abyHeader + 26, 3 );
342 1 : if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
343 : {
344 : CPLError( CE_Failure, CPLE_AppDefined,
345 : "Invalid dimensions : %d x %d",
346 0 : poDS->nRasterXSize, poDS->nRasterYSize);
347 0 : delete poDS;
348 0 : return NULL;
349 : }
350 :
351 : /* -------------------------------------------------------------------- */
352 : /* Create band information objects. */
353 : /* -------------------------------------------------------------------- */
354 1 : poDS->SetBand( 1, new JDEMRasterBand( poDS, 1 ));
355 :
356 : /* -------------------------------------------------------------------- */
357 : /* Initialize any PAM information. */
358 : /* -------------------------------------------------------------------- */
359 1 : poDS->SetDescription( poOpenInfo->pszFilename );
360 1 : poDS->TryLoadXML();
361 :
362 : /* -------------------------------------------------------------------- */
363 : /* Check for overviews. */
364 : /* -------------------------------------------------------------------- */
365 1 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
366 :
367 1 : return( poDS );
368 : }
369 :
370 : /************************************************************************/
371 : /* GDALRegister_JDEM() */
372 : /************************************************************************/
373 :
374 582 : void GDALRegister_JDEM()
375 :
376 : {
377 : GDALDriver *poDriver;
378 :
379 582 : if( GDALGetDriverByName( "JDEM" ) == NULL )
380 : {
381 561 : poDriver = new GDALDriver();
382 :
383 561 : poDriver->SetDescription( "JDEM" );
384 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
385 561 : "Japanese DEM (.mem)" );
386 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
387 561 : "frmt_various.html#JDEM" );
388 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
389 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
390 :
391 561 : poDriver->pfnOpen = JDEMDataset::Open;
392 561 : poDriver->pfnIdentify = JDEMDataset::Identify;
393 :
394 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
395 : }
396 582 : }
|