1 : /******************************************************************************
2 : * $Id: jdemdataset.cpp 16706 2009-04-02 03:44:07Z warmerdam $
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 16706 2009-04-02 03:44:07Z warmerdam $");
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 : 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 1 : {
86 : friend class JDEMRasterBand;
87 :
88 : FILE *fp;
89 : GByte abyHeader[1012];
90 :
91 : public:
92 : ~JDEMDataset();
93 :
94 : static GDALDataset *Open( GDALOpenInfo * );
95 :
96 : CPLErr GetGeoTransform( double * padfTransform );
97 : const char *GetProjectionRef();
98 : };
99 :
100 : /************************************************************************/
101 : /* ==================================================================== */
102 : /* JDEMRasterBand */
103 : /* ==================================================================== */
104 : /************************************************************************/
105 :
106 : class JDEMRasterBand : public GDALPamRasterBand
107 : {
108 : friend class JDEMDataset;
109 :
110 : int nRecordSize;
111 : char* pszRecord;
112 :
113 : public:
114 :
115 : JDEMRasterBand( JDEMDataset *, int );
116 : ~JDEMRasterBand();
117 :
118 : virtual CPLErr IReadBlock( int, int, void * );
119 : };
120 :
121 :
122 : /************************************************************************/
123 : /* JDEMRasterBand() */
124 : /************************************************************************/
125 :
126 1 : JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, int nBand )
127 :
128 : {
129 1 : this->poDS = poDS;
130 1 : this->nBand = nBand;
131 :
132 1 : eDataType = GDT_Float32;
133 :
134 1 : nBlockXSize = poDS->GetRasterXSize();
135 1 : nBlockYSize = 1;
136 :
137 : /* Cannot overflow as nBlockXSize <= 999 */
138 1 : nRecordSize = nBlockXSize*5 + 9 + 2;
139 1 : pszRecord = NULL;
140 1 : }
141 :
142 : /************************************************************************/
143 : /* ~JDEMRasterBand() */
144 : /************************************************************************/
145 :
146 2 : JDEMRasterBand::~JDEMRasterBand()
147 : {
148 1 : VSIFree(pszRecord);
149 2 : }
150 :
151 : /************************************************************************/
152 : /* IReadBlock() */
153 : /************************************************************************/
154 :
155 2 : CPLErr JDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
156 : void * pImage )
157 :
158 : {
159 2 : JDEMDataset *poGDS = (JDEMDataset *) poDS;
160 : int i;
161 :
162 2 : if (pszRecord == NULL)
163 : {
164 1 : if (nRecordSize < 0)
165 0 : return CE_Failure;
166 :
167 1 : pszRecord = (char *) VSIMalloc(nRecordSize);
168 1 : if (pszRecord == NULL)
169 : {
170 : CPLError(CE_Failure, CPLE_OutOfMemory,
171 0 : "Cannot allocate scanline buffer");
172 0 : nRecordSize = -1;
173 0 : return CE_Failure;
174 : }
175 : }
176 :
177 2 : VSIFSeekL( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET );
178 :
179 2 : VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp );
180 :
181 2 : if( !EQUALN((char *) poGDS->abyHeader,pszRecord,6) )
182 : {
183 : CPLError( CE_Failure, CPLE_AppDefined,
184 : "JDEM Scanline corrupt. Perhaps file was not transferred\n"
185 0 : "in binary mode?" );
186 0 : return CE_Failure;
187 : }
188 :
189 2 : if( JDEMGetField( pszRecord + 6, 3 ) != nBlockYOff + 1 )
190 : {
191 : CPLError( CE_Failure, CPLE_AppDefined,
192 : "JDEM scanline out of order, JDEM driver does not\n"
193 0 : "currently support partial datasets." );
194 0 : return CE_Failure;
195 : }
196 :
197 6 : for( i = 0; i < nBlockXSize; i++ )
198 4 : ((float *) pImage)[i] = (float)
199 4 : (JDEMGetField( pszRecord + 9 + 5 * i, 5) * 0.1);
200 :
201 2 : return CE_None;
202 : }
203 :
204 : /************************************************************************/
205 : /* ==================================================================== */
206 : /* JDEMDataset */
207 : /* ==================================================================== */
208 : /************************************************************************/
209 :
210 : /************************************************************************/
211 : /* ~JDEMDataset() */
212 : /************************************************************************/
213 :
214 2 : JDEMDataset::~JDEMDataset()
215 :
216 : {
217 1 : FlushCache();
218 1 : if( fp != NULL )
219 1 : VSIFCloseL( fp );
220 2 : }
221 :
222 : /************************************************************************/
223 : /* GetGeoTransform() */
224 : /************************************************************************/
225 :
226 0 : CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
227 :
228 : {
229 : double dfLLLat, dfLLLong, dfURLat, dfURLong;
230 :
231 0 : dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 );
232 0 : dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 );
233 0 : dfURLat = JDEMGetAngle( (char *) abyHeader + 43 );
234 0 : dfURLong = JDEMGetAngle( (char *) abyHeader + 50 );
235 :
236 0 : padfTransform[0] = dfLLLong;
237 0 : padfTransform[3] = dfURLat;
238 0 : padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize();
239 0 : padfTransform[2] = 0.0;
240 :
241 0 : padfTransform[4] = 0.0;
242 0 : padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize();
243 :
244 :
245 0 : return CE_None;
246 : }
247 :
248 : /************************************************************************/
249 : /* GetProjectionRef() */
250 : /************************************************************************/
251 :
252 0 : const char *JDEMDataset::GetProjectionRef()
253 :
254 : {
255 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]]" );
256 : }
257 :
258 : /************************************************************************/
259 : /* Open() */
260 : /************************************************************************/
261 :
262 9661 : GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
263 :
264 : {
265 : /* -------------------------------------------------------------------- */
266 : /* Confirm that the header has what appears to be dates in the */
267 : /* expected locations. Sadly this is a relatively weak test. */
268 : /* -------------------------------------------------------------------- */
269 9661 : if( poOpenInfo->nHeaderBytes < 50 )
270 8663 : return NULL;
271 :
272 : /* check if century values seem reasonable */
273 998 : if( (!EQUALN((char *)poOpenInfo->pabyHeader+11,"19",2)
274 : && !EQUALN((char *)poOpenInfo->pabyHeader+11,"20",2))
275 : || (!EQUALN((char *)poOpenInfo->pabyHeader+15,"19",2)
276 : && !EQUALN((char *)poOpenInfo->pabyHeader+15,"20",2))
277 : || (!EQUALN((char *)poOpenInfo->pabyHeader+19,"19",2)
278 : && !EQUALN((char *)poOpenInfo->pabyHeader+19,"20",2)) )
279 : {
280 997 : return NULL;
281 : }
282 :
283 : /* -------------------------------------------------------------------- */
284 : /* Confirm the requested access is supported. */
285 : /* -------------------------------------------------------------------- */
286 1 : if( poOpenInfo->eAccess == GA_Update )
287 : {
288 : CPLError( CE_Failure, CPLE_NotSupported,
289 : "The JDEM driver does not support update access to existing"
290 0 : " datasets.\n" );
291 0 : return NULL;
292 : }
293 :
294 : /* -------------------------------------------------------------------- */
295 : /* Create a corresponding GDALDataset. */
296 : /* -------------------------------------------------------------------- */
297 : JDEMDataset *poDS;
298 :
299 1 : poDS = new JDEMDataset();
300 :
301 1 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Read the header. */
305 : /* -------------------------------------------------------------------- */
306 1 : VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp );
307 :
308 1 : poDS->nRasterXSize = JDEMGetField( (char *) poDS->abyHeader + 23, 3 );
309 1 : poDS->nRasterYSize = JDEMGetField( (char *) poDS->abyHeader + 26, 3 );
310 2 : if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
311 : {
312 : CPLError( CE_Failure, CPLE_AppDefined,
313 : "Invalid dimensions : %d x %d",
314 0 : poDS->nRasterXSize, poDS->nRasterYSize);
315 0 : delete poDS;
316 0 : return NULL;
317 : }
318 :
319 : /* -------------------------------------------------------------------- */
320 : /* Create band information objects. */
321 : /* -------------------------------------------------------------------- */
322 1 : poDS->SetBand( 1, new JDEMRasterBand( poDS, 1 ));
323 :
324 : /* -------------------------------------------------------------------- */
325 : /* Initialize any PAM information. */
326 : /* -------------------------------------------------------------------- */
327 1 : poDS->SetDescription( poOpenInfo->pszFilename );
328 1 : poDS->TryLoadXML();
329 :
330 : /* -------------------------------------------------------------------- */
331 : /* Check for overviews. */
332 : /* -------------------------------------------------------------------- */
333 1 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
334 :
335 1 : return( poDS );
336 : }
337 :
338 : /************************************************************************/
339 : /* GDALRegister_JDEM() */
340 : /************************************************************************/
341 :
342 338 : void GDALRegister_JDEM()
343 :
344 : {
345 : GDALDriver *poDriver;
346 :
347 338 : if( GDALGetDriverByName( "JDEM" ) == NULL )
348 : {
349 336 : poDriver = new GDALDriver();
350 :
351 336 : poDriver->SetDescription( "JDEM" );
352 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
353 336 : "Japanese DEM (.mem)" );
354 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
355 336 : "frmt_various.html#JDEM" );
356 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
357 :
358 336 : poDriver->pfnOpen = JDEMDataset::Open;
359 :
360 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
361 : }
362 338 : }
|