1 : /******************************************************************************
2 : * $Id: dipxdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
3 : *
4 : * Project: GDAL
5 : * Purpose: Implementation for ELAS DIPEx format variant.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2006, Frank Warmerdam
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 "rawdataset.h"
31 : #include "cpl_string.h"
32 : #include "ogr_spatialref.h"
33 :
34 : CPL_CVSID("$Id: dipxdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
35 :
36 : CPL_C_START
37 : void GDALRegister_DIPEx(void);
38 : CPL_C_END
39 :
40 : typedef struct {
41 : GInt32 NBIH; /* bytes in header, normaly 1024 */
42 : GInt32 NBPR; /* bytes per data record (all bands of scanline) */
43 : GInt32 IL; /* initial line - normally 1 */
44 : GInt32 LL; /* last line */
45 : GInt32 IE; /* initial element (pixel), normally 1 */
46 : GInt32 LE; /* last element (pixel) */
47 : GInt32 NC; /* number of channels (bands) */
48 : GInt32 H4322; /* header record identifier - always 4322. */
49 : char unused1[40];
50 : GByte IH19[4];/* data type, and size flags */
51 : GInt32 IH20; /* number of secondary headers */
52 : GInt32 SRID;
53 : char unused2[12];
54 : double YOffset;
55 : double XOffset;
56 : double YPixSize;
57 : double XPixSize;
58 : double Matrix[4];
59 : char unused3[344];
60 : GUInt16 ColorTable[256]; /* RGB packed with 4 bits each */
61 : char unused4[32];
62 : } DIPExHeader;
63 :
64 : /************************************************************************/
65 : /* ==================================================================== */
66 : /* DIPExDataset */
67 : /* ==================================================================== */
68 : /************************************************************************/
69 :
70 : class DIPExRasterBand;
71 :
72 : class DIPExDataset : public GDALPamDataset
73 : {
74 : friend class DIPExRasterBand;
75 :
76 : VSILFILE *fp;
77 : CPLString osSRS;
78 :
79 : DIPExHeader sHeader;
80 :
81 : GDALDataType eRasterDataType;
82 :
83 : double adfGeoTransform[6];
84 :
85 : public:
86 : DIPExDataset();
87 : ~DIPExDataset();
88 :
89 : virtual CPLErr GetGeoTransform( double * );
90 :
91 : virtual const char *GetProjectionRef( void );
92 : static GDALDataset *Open( GDALOpenInfo * );
93 : };
94 :
95 : /************************************************************************/
96 : /* ==================================================================== */
97 : /* DIPExDataset */
98 : /* ==================================================================== */
99 : /************************************************************************/
100 :
101 :
102 : /************************************************************************/
103 : /* DIPExDataset() */
104 : /************************************************************************/
105 :
106 1 : DIPExDataset::DIPExDataset()
107 :
108 : {
109 1 : fp = NULL;
110 :
111 1 : adfGeoTransform[0] = 0.0;
112 1 : adfGeoTransform[1] = 1.0;
113 1 : adfGeoTransform[2] = 0.0;
114 1 : adfGeoTransform[3] = 0.0;
115 1 : adfGeoTransform[4] = 0.0;
116 1 : adfGeoTransform[5] = 1.0;
117 1 : }
118 :
119 : /************************************************************************/
120 : /* ~DIPExDataset() */
121 : /************************************************************************/
122 :
123 1 : DIPExDataset::~DIPExDataset()
124 :
125 : {
126 1 : if (fp)
127 1 : VSIFCloseL( fp );
128 1 : fp = NULL;
129 1 : }
130 :
131 : /************************************************************************/
132 : /* Open() */
133 : /************************************************************************/
134 :
135 11954 : GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
136 :
137 : {
138 : /* -------------------------------------------------------------------- */
139 : /* First we check to see if the file has the expected header */
140 : /* bytes. */
141 : /* -------------------------------------------------------------------- */
142 11954 : if( poOpenInfo->nHeaderBytes < 256 )
143 11404 : return NULL;
144 :
145 550 : if( CPL_LSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+0))) != 1024 )
146 549 : return NULL;
147 :
148 1 : if( CPL_LSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+28))) != 4322 )
149 0 : return NULL;
150 :
151 : /* -------------------------------------------------------------------- */
152 : /* Create a corresponding GDALDataset. */
153 : /* -------------------------------------------------------------------- */
154 : DIPExDataset *poDS;
155 : const char *pszAccess;
156 :
157 1 : if( poOpenInfo->eAccess == GA_Update )
158 0 : pszAccess = "r+b";
159 : else
160 1 : pszAccess = "rb";
161 :
162 1 : poDS = new DIPExDataset();
163 :
164 1 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, pszAccess );
165 1 : if( poDS->fp == NULL )
166 : {
167 : CPLError( CE_Failure, CPLE_OpenFailed,
168 : "Attempt to open `%s' with acces `%s' failed.\n",
169 0 : poOpenInfo->pszFilename, pszAccess );
170 0 : delete poDS;
171 0 : return NULL;
172 : }
173 :
174 1 : poDS->eAccess = poOpenInfo->eAccess;
175 :
176 : /* -------------------------------------------------------------------- */
177 : /* Read the header information. */
178 : /* -------------------------------------------------------------------- */
179 1 : if( VSIFReadL( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 )
180 : {
181 : CPLError( CE_Failure, CPLE_FileIO,
182 : "Attempt to read 1024 byte header filed on file %s\n",
183 0 : poOpenInfo->pszFilename );
184 0 : delete poDS;
185 0 : return NULL;
186 : }
187 :
188 : /* -------------------------------------------------------------------- */
189 : /* Extract information of interest from the header. */
190 : /* -------------------------------------------------------------------- */
191 : int nStart, nEnd, nDIPExDataType, nBytesPerSample;
192 : int nLineOffset;
193 :
194 1 : nLineOffset = CPL_LSBWORD32( poDS->sHeader.NBPR );
195 :
196 1 : nStart = CPL_LSBWORD32( poDS->sHeader.IL );
197 1 : nEnd = CPL_LSBWORD32( poDS->sHeader.LL );
198 1 : poDS->nRasterYSize = nEnd - nStart + 1;
199 :
200 1 : nStart = CPL_LSBWORD32( poDS->sHeader.IE );
201 1 : nEnd = CPL_LSBWORD32( poDS->sHeader.LE );
202 1 : poDS->nRasterXSize = nEnd - nStart + 1;
203 :
204 1 : poDS->nBands = CPL_LSBWORD32( poDS->sHeader.NC );
205 :
206 1 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
207 : !GDALCheckBandCount(poDS->nBands, FALSE))
208 : {
209 0 : delete poDS;
210 0 : return NULL;
211 : }
212 :
213 1 : nDIPExDataType = (poDS->sHeader.IH19[1] & 0x7e) >> 2;
214 1 : nBytesPerSample = poDS->sHeader.IH19[0];
215 :
216 2 : if( nDIPExDataType == 0 && nBytesPerSample == 1 )
217 1 : poDS->eRasterDataType = GDT_Byte;
218 0 : else if( nDIPExDataType == 1 && nBytesPerSample == 1 )
219 0 : poDS->eRasterDataType = GDT_Byte;
220 0 : else if( nDIPExDataType == 16 && nBytesPerSample == 4 )
221 0 : poDS->eRasterDataType = GDT_Float32;
222 0 : else if( nDIPExDataType == 17 && nBytesPerSample == 8 )
223 0 : poDS->eRasterDataType = GDT_Float64;
224 : else
225 : {
226 0 : delete poDS;
227 : CPLError( CE_Failure, CPLE_AppDefined,
228 : "Unrecognised image data type %d, with BytesPerSample=%d.\n",
229 0 : nDIPExDataType, nBytesPerSample );
230 0 : return NULL;
231 : }
232 :
233 : /* -------------------------------------------------------------------- */
234 : /* Create band information objects. */
235 : /* -------------------------------------------------------------------- */
236 : int iBand;
237 :
238 4 : for( iBand = 0; iBand < poDS->nBands; iBand++ )
239 : {
240 : poDS->SetBand( iBand+1,
241 : new RawRasterBand( poDS, iBand+1, poDS->fp,
242 : 1024 + iBand * nLineOffset,
243 : nBytesPerSample,
244 : nLineOffset * poDS->nBands,
245 : poDS->eRasterDataType,
246 1 : CPL_IS_LSB, TRUE ) );
247 : }
248 :
249 : /* -------------------------------------------------------------------- */
250 : /* Extract the projection coordinates, if present. */
251 : /* -------------------------------------------------------------------- */
252 : CPL_LSBPTR64(&(poDS->sHeader.XPixSize));
253 : CPL_LSBPTR64(&(poDS->sHeader.YPixSize));
254 : CPL_LSBPTR64(&(poDS->sHeader.XOffset));
255 : CPL_LSBPTR64(&(poDS->sHeader.YOffset));
256 :
257 1 : if( poDS->sHeader.XOffset != 0 )
258 : {
259 0 : poDS->adfGeoTransform[0] = poDS->sHeader.XOffset;
260 0 : poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize;
261 0 : poDS->adfGeoTransform[2] = 0.0;
262 0 : poDS->adfGeoTransform[3] = poDS->sHeader.YOffset;
263 0 : poDS->adfGeoTransform[4] = 0.0;
264 0 : poDS->adfGeoTransform[5] = -1.0 * ABS(poDS->sHeader.YPixSize);
265 :
266 0 : poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
267 0 : poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5;
268 : }
269 : else
270 : {
271 1 : poDS->adfGeoTransform[0] = 0.0;
272 1 : poDS->adfGeoTransform[1] = 1.0;
273 1 : poDS->adfGeoTransform[2] = 0.0;
274 1 : poDS->adfGeoTransform[3] = 0.0;
275 1 : poDS->adfGeoTransform[4] = 0.0;
276 1 : poDS->adfGeoTransform[5] = 1.0;
277 : }
278 :
279 : /* -------------------------------------------------------------------- */
280 : /* Look for SRID. */
281 : /* -------------------------------------------------------------------- */
282 : CPL_LSBPTR32( &(poDS->sHeader.SRID) );
283 :
284 1 : if( poDS->sHeader.SRID > 0 && poDS->sHeader.SRID < 33000 )
285 : {
286 1 : OGRSpatialReference oSR;
287 :
288 1 : if( oSR.importFromEPSG( poDS->sHeader.SRID ) == OGRERR_NONE )
289 : {
290 1 : char *pszWKT = NULL;
291 1 : oSR.exportToWkt( &pszWKT );
292 1 : poDS->osSRS = pszWKT;
293 1 : CPLFree( pszWKT );
294 1 : }
295 : }
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* Initialize any PAM information. */
299 : /* -------------------------------------------------------------------- */
300 1 : poDS->SetDescription( poOpenInfo->pszFilename );
301 1 : poDS->TryLoadXML();
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Check for external overviews. */
305 : /* -------------------------------------------------------------------- */
306 1 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
307 :
308 1 : return( poDS );
309 : }
310 :
311 : /************************************************************************/
312 : /* GetProjectionRef() */
313 : /************************************************************************/
314 :
315 0 : const char *DIPExDataset::GetProjectionRef()
316 :
317 : {
318 0 : return osSRS.c_str();
319 : }
320 :
321 : /************************************************************************/
322 : /* GetGeoTransform() */
323 : /************************************************************************/
324 :
325 0 : CPLErr DIPExDataset::GetGeoTransform( double * padfTransform )
326 :
327 : {
328 0 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
329 :
330 0 : return( CE_None );
331 : }
332 :
333 : /************************************************************************/
334 : /* GDALRegister_DIPEx() */
335 : /************************************************************************/
336 :
337 582 : void GDALRegister_DIPEx()
338 :
339 : {
340 : GDALDriver *poDriver;
341 :
342 582 : if( GDALGetDriverByName( "DIPEx" ) == NULL )
343 : {
344 561 : poDriver = new GDALDriver();
345 :
346 561 : poDriver->SetDescription( "DIPEx" );
347 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
348 561 : "DIPEx" );
349 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
350 :
351 561 : poDriver->pfnOpen = DIPExDataset::Open;
352 :
353 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
354 : }
355 582 : }
|