1 : /******************************************************************************
2 : * $Id: hkvdataset.cpp 24590 2012-06-16 16:34:48Z rouault $
3 : *
4 : * Project: GView
5 : * Purpose: Implementation of Atlantis HKV labelled blob support
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, 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 <ctype.h>
33 : #include "ogr_spatialref.h"
34 : #include "atlsci_spheroid.h"
35 :
36 : CPL_CVSID("$Id: hkvdataset.cpp 24590 2012-06-16 16:34:48Z rouault $");
37 :
38 : CPL_C_START
39 : void GDALRegister_HKV(void);
40 : CPL_C_END
41 :
42 : /************************************************************************/
43 : /* ==================================================================== */
44 : /* HKVRasterBand */
45 : /* ==================================================================== */
46 : /************************************************************************/
47 :
48 : class HKVDataset;
49 :
50 : class HKVRasterBand : public RawRasterBand
51 : {
52 : friend class HKVDataset;
53 :
54 : public:
55 : HKVRasterBand( HKVDataset *poDS, int nBand, VSILFILE * fpRaw,
56 : unsigned int nImgOffset, int nPixelOffset,
57 : int nLineOffset,
58 : GDALDataType eDataType, int bNativeOrder );
59 : virtual ~HKVRasterBand();
60 :
61 : virtual CPLErr SetNoDataValue( double );
62 : };
63 :
64 : /************************************************************************/
65 : /* HKV Spheroids */
66 : /************************************************************************/
67 :
68 : class HKVSpheroidList : public SpheroidList
69 : {
70 :
71 : public:
72 :
73 : HKVSpheroidList();
74 : ~HKVSpheroidList();
75 :
76 : };
77 :
78 41 : HKVSpheroidList :: HKVSpheroidList()
79 : {
80 41 : num_spheroids = 58;
81 41 : epsilonR = 0.1;
82 41 : epsilonI = 0.000001;
83 :
84 41 : spheroids[0].SetValuesByEqRadiusAndInvFlattening("airy-1830",6377563.396,299.3249646);
85 41 : spheroids[1].SetValuesByEqRadiusAndInvFlattening("modified-airy",6377340.189,299.3249646);
86 41 : spheroids[2].SetValuesByEqRadiusAndInvFlattening("australian-national",6378160,298.25);
87 41 : spheroids[3].SetValuesByEqRadiusAndInvFlattening("bessel-1841-namibia",6377483.865,299.1528128);
88 41 : spheroids[4].SetValuesByEqRadiusAndInvFlattening("bessel-1841",6377397.155,299.1528128);
89 41 : spheroids[5].SetValuesByEqRadiusAndInvFlattening("clarke-1858",6378294.0,294.297);
90 41 : spheroids[6].SetValuesByEqRadiusAndInvFlattening("clarke-1866",6378206.4,294.9786982);
91 41 : spheroids[7].SetValuesByEqRadiusAndInvFlattening("clarke-1880",6378249.145,293.465);
92 41 : spheroids[8].SetValuesByEqRadiusAndInvFlattening("everest-india-1830",6377276.345,300.8017);
93 41 : spheroids[9].SetValuesByEqRadiusAndInvFlattening("everest-sabah-sarawak",6377298.556,300.8017);
94 41 : spheroids[10].SetValuesByEqRadiusAndInvFlattening("everest-india-1956",6377301.243,300.8017);
95 41 : spheroids[11].SetValuesByEqRadiusAndInvFlattening("everest-malaysia-1969",6377295.664,300.8017);
96 41 : spheroids[12].SetValuesByEqRadiusAndInvFlattening("everest-malay-sing",6377304.063,300.8017);
97 41 : spheroids[13].SetValuesByEqRadiusAndInvFlattening("everest-pakistan",6377309.613,300.8017);
98 41 : spheroids[14].SetValuesByEqRadiusAndInvFlattening("modified-fisher-1960",6378155,298.3);
99 41 : spheroids[15].SetValuesByEqRadiusAndInvFlattening("helmert-1906",6378200,298.3);
100 41 : spheroids[16].SetValuesByEqRadiusAndInvFlattening("hough-1960",6378270,297);
101 41 : spheroids[17].SetValuesByEqRadiusAndInvFlattening("hughes",6378273.0,298.279);
102 41 : spheroids[18].SetValuesByEqRadiusAndInvFlattening("indonesian-1974",6378160,298.247);
103 41 : spheroids[19].SetValuesByEqRadiusAndInvFlattening("international-1924",6378388,297);
104 41 : spheroids[20].SetValuesByEqRadiusAndInvFlattening("iugc-67",6378160.0,298.254);
105 41 : spheroids[21].SetValuesByEqRadiusAndInvFlattening("iugc-75",6378140.0,298.25298);
106 41 : spheroids[22].SetValuesByEqRadiusAndInvFlattening("krassovsky-1940",6378245,298.3);
107 41 : spheroids[23].SetValuesByEqRadiusAndInvFlattening("kaula",6378165.0,292.308);
108 41 : spheroids[24].SetValuesByEqRadiusAndInvFlattening("grs-80",6378137,298.257222101);
109 41 : spheroids[25].SetValuesByEqRadiusAndInvFlattening("south-american-1969",6378160,298.25);
110 41 : spheroids[26].SetValuesByEqRadiusAndInvFlattening("wgs-72",6378135,298.26);
111 41 : spheroids[27].SetValuesByEqRadiusAndInvFlattening("wgs-84",6378137,298.257223563);
112 41 : spheroids[28].SetValuesByEqRadiusAndInvFlattening("ev-wgs-84",6378137.0,298.252841);
113 41 : spheroids[29].SetValuesByEqRadiusAndInvFlattening("ev-bessel",6377397.0,299.1976073);
114 :
115 41 : spheroids[30].SetValuesByEqRadiusAndInvFlattening("airy_1830",6377563.396,299.3249646);
116 41 : spheroids[31].SetValuesByEqRadiusAndInvFlattening("modified_airy",6377340.189,299.3249646);
117 41 : spheroids[32].SetValuesByEqRadiusAndInvFlattening("australian_national",6378160,298.25);
118 41 : spheroids[33].SetValuesByEqRadiusAndInvFlattening("bessel_1841_namibia",6377483.865,299.1528128);
119 41 : spheroids[34].SetValuesByEqRadiusAndInvFlattening("bessel_1841",6377397.155,299.1528128);
120 41 : spheroids[35].SetValuesByEqRadiusAndInvFlattening("clarke_1858",6378294.0,294.297);
121 41 : spheroids[36].SetValuesByEqRadiusAndInvFlattening("clarke_1866",6378206.4,294.9786982);
122 41 : spheroids[37].SetValuesByEqRadiusAndInvFlattening("clarke_1880",6378249.145,293.465);
123 41 : spheroids[38].SetValuesByEqRadiusAndInvFlattening("everest_india_1830",6377276.345,300.8017);
124 41 : spheroids[39].SetValuesByEqRadiusAndInvFlattening("everest_sabah_sarawak",6377298.556,300.8017);
125 41 : spheroids[40].SetValuesByEqRadiusAndInvFlattening("everest_india_1956",6377301.243,300.8017);
126 41 : spheroids[41].SetValuesByEqRadiusAndInvFlattening("everest_malaysia_1969",6377295.664,300.8017);
127 41 : spheroids[42].SetValuesByEqRadiusAndInvFlattening("everest_malay_sing",6377304.063,300.8017);
128 41 : spheroids[43].SetValuesByEqRadiusAndInvFlattening("everest_pakistan",6377309.613,300.8017);
129 41 : spheroids[44].SetValuesByEqRadiusAndInvFlattening("modified_fisher_1960",6378155,298.3);
130 41 : spheroids[45].SetValuesByEqRadiusAndInvFlattening("helmert_1906",6378200,298.3);
131 41 : spheroids[46].SetValuesByEqRadiusAndInvFlattening("hough_1960",6378270,297);
132 41 : spheroids[47].SetValuesByEqRadiusAndInvFlattening("indonesian_1974",6378160,298.247);
133 41 : spheroids[48].SetValuesByEqRadiusAndInvFlattening("international_1924",6378388,297);
134 41 : spheroids[49].SetValuesByEqRadiusAndInvFlattening("iugc_67",6378160.0,298.254);
135 41 : spheroids[50].SetValuesByEqRadiusAndInvFlattening("iugc_75",6378140.0,298.25298);
136 41 : spheroids[51].SetValuesByEqRadiusAndInvFlattening("krassovsky_1940",6378245,298.3);
137 41 : spheroids[52].SetValuesByEqRadiusAndInvFlattening("grs_80",6378137,298.257222101);
138 41 : spheroids[53].SetValuesByEqRadiusAndInvFlattening("south_american_1969",6378160,298.25);
139 41 : spheroids[54].SetValuesByEqRadiusAndInvFlattening("wgs_72",6378135,298.26);
140 41 : spheroids[55].SetValuesByEqRadiusAndInvFlattening("wgs_84",6378137,298.257223563);
141 41 : spheroids[56].SetValuesByEqRadiusAndInvFlattening("ev_wgs_84",6378137.0,298.252841);
142 41 : spheroids[57].SetValuesByEqRadiusAndInvFlattening("ev_bessel",6377397.0,299.1976073);
143 :
144 41 : }
145 :
146 41 : HKVSpheroidList::~HKVSpheroidList()
147 :
148 : {
149 41 : }
150 :
151 : CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
152 : int nXSize, int nYSize, int nBands,
153 : GDALDataType eType, int bNoDataSet,
154 : double dfNoDataValue );
155 :
156 : /************************************************************************/
157 : /* ==================================================================== */
158 : /* HKVDataset */
159 : /* ==================================================================== */
160 : /************************************************************************/
161 :
162 : class HKVDataset : public RawDataset
163 : {
164 : friend class HKVRasterBand;
165 :
166 : char *pszPath;
167 : VSILFILE *fpBlob;
168 :
169 : int nGCPCount;
170 : GDAL_GCP *pasGCPList;
171 :
172 : void ProcessGeoref(const char *);
173 : void ProcessGeorefGCP(char **, const char *, double, double);
174 : void SetVersion( float version_number );
175 : float GetVersion();
176 : float MFF2version;
177 :
178 : CPLErr SetGCPProjection(const char *); /* for use in CreateCopy */
179 :
180 : GDALDataType eRasterType;
181 :
182 : void SetNoDataValue( double );
183 :
184 : char *pszProjection;
185 : char *pszGCPProjection;
186 : double adfGeoTransform[6];
187 :
188 : char **papszAttrib;
189 :
190 : int bGeorefChanged;
191 : char **papszGeoref;
192 :
193 : /* NOTE: The MFF2 format goes against GDAL's API in that nodata values are set
194 : * per-dataset rather than per-band. To compromise, for writing out, the
195 : * dataset's nodata value will be set to the last value set on any of the
196 : * raster bands.
197 : */
198 :
199 : int bNoDataSet;
200 : int bNoDataChanged;
201 : double dfNoDataValue;
202 :
203 : public:
204 : HKVDataset();
205 : virtual ~HKVDataset();
206 :
207 : virtual int GetGCPCount();
208 : virtual const char *GetGCPProjection();
209 : virtual const GDAL_GCP *GetGCPs();
210 :
211 : virtual const char *GetProjectionRef(void);
212 : virtual CPLErr GetGeoTransform( double * );
213 :
214 : virtual CPLErr SetGeoTransform( double * );
215 : virtual CPLErr SetProjection( const char * );
216 :
217 : static GDALDataset *Open( GDALOpenInfo * );
218 : static GDALDataset *Create( const char * pszFilename,
219 : int nXSize, int nYSize, int nBands,
220 : GDALDataType eType, char ** papszParmList );
221 : static GDALDataset *CreateCopy( const char * pszFilename,
222 : GDALDataset *poSrcDS,
223 : int bStrict, char ** papszOptions,
224 : GDALProgressFunc pfnProgress,
225 : void * pProgressData );
226 :
227 : static CPLErr Delete( const char * pszName );
228 : };
229 :
230 : /************************************************************************/
231 : /* ==================================================================== */
232 : /* HKVRasterBand */
233 : /* ==================================================================== */
234 : /************************************************************************/
235 :
236 : /************************************************************************/
237 : /* HKVRasterBand() */
238 : /************************************************************************/
239 :
240 91 : HKVRasterBand::HKVRasterBand( HKVDataset *poDS, int nBand, VSILFILE * fpRaw,
241 : unsigned int nImgOffset, int nPixelOffset,
242 : int nLineOffset,
243 : GDALDataType eDataType, int bNativeOrder )
244 : : RawRasterBand( (GDALDataset *) poDS, nBand,
245 : fpRaw, nImgOffset, nPixelOffset,
246 91 : nLineOffset, eDataType, bNativeOrder, TRUE )
247 :
248 : {
249 91 : this->poDS = poDS;
250 91 : this->nBand = nBand;
251 :
252 91 : nBlockXSize = poDS->GetRasterXSize();
253 91 : nBlockYSize = 1;
254 91 : }
255 :
256 : /************************************************************************/
257 : /* SetNoDataValue() */
258 : /************************************************************************/
259 :
260 0 : CPLErr HKVRasterBand::SetNoDataValue( double dfNewValue )
261 :
262 : {
263 0 : HKVDataset *poHKVDS = (HKVDataset *) poDS;
264 0 : this->RawRasterBand::SetNoDataValue( dfNewValue );
265 0 : poHKVDS->SetNoDataValue( dfNewValue );
266 :
267 0 : return CE_None;
268 : }
269 :
270 : /************************************************************************/
271 : /* ~HKVRasterBand() */
272 : /************************************************************************/
273 :
274 91 : HKVRasterBand::~HKVRasterBand()
275 :
276 : {
277 91 : }
278 :
279 : /************************************************************************/
280 : /* ==================================================================== */
281 : /* HKVDataset */
282 : /* ==================================================================== */
283 : /************************************************************************/
284 :
285 : /************************************************************************/
286 : /* HKVDataset() */
287 : /************************************************************************/
288 :
289 41 : HKVDataset::HKVDataset()
290 : {
291 41 : pszPath = NULL;
292 41 : papszAttrib = NULL;
293 41 : papszGeoref = NULL;
294 41 : bGeorefChanged = FALSE;
295 :
296 41 : nGCPCount = 0;
297 41 : pasGCPList = NULL;
298 41 : pszProjection = CPLStrdup("");
299 41 : pszGCPProjection = CPLStrdup("");
300 41 : adfGeoTransform[0] = 0.0;
301 41 : adfGeoTransform[1] = 1.0;
302 41 : adfGeoTransform[2] = 0.0;
303 41 : adfGeoTransform[3] = 0.0;
304 41 : adfGeoTransform[4] = 0.0;
305 41 : adfGeoTransform[5] = 1.0;
306 :
307 41 : bNoDataSet = FALSE;
308 41 : bNoDataChanged = FALSE;
309 :
310 : /* Initialize datasets to new version; change if necessary */
311 41 : MFF2version = (float) 1.1;
312 41 : }
313 :
314 : /************************************************************************/
315 : /* ~HKVDataset() */
316 : /************************************************************************/
317 :
318 41 : HKVDataset::~HKVDataset()
319 :
320 : {
321 41 : FlushCache();
322 41 : if( bGeorefChanged )
323 : {
324 : const char *pszFilename;
325 :
326 25 : pszFilename = CPLFormFilename(pszPath, "georef", NULL );
327 :
328 25 : CSLSave( papszGeoref, pszFilename );
329 : }
330 :
331 41 : if( bNoDataChanged )
332 : {
333 : SaveHKVAttribFile(pszPath,
334 : this->nRasterXSize,
335 : this->nRasterYSize,
336 : this->nBands,
337 : this->eRasterType,
338 : this->bNoDataSet,
339 0 : this->dfNoDataValue );
340 :
341 : }
342 :
343 41 : if( fpBlob != NULL )
344 41 : VSIFCloseL( fpBlob );
345 :
346 41 : if( nGCPCount > 0 )
347 : {
348 11 : GDALDeinitGCPs( nGCPCount, pasGCPList );
349 11 : CPLFree( pasGCPList );
350 : }
351 :
352 41 : CPLFree( pszProjection );
353 41 : CPLFree( pszGCPProjection );
354 41 : CPLFree( pszPath );
355 41 : CSLDestroy( papszGeoref );
356 41 : CSLDestroy( papszAttrib );
357 41 : }
358 :
359 : /************************************************************************/
360 : /* SetVersion() */
361 : /************************************************************************/
362 :
363 41 : void HKVDataset::SetVersion(float version_number)
364 :
365 : {
366 : //update stored info
367 41 : MFF2version = version_number;
368 41 : }
369 :
370 : /************************************************************************/
371 : /* GetVersion() */
372 : /************************************************************************/
373 :
374 0 : float HKVDataset::GetVersion()
375 :
376 : {
377 0 : return( MFF2version );
378 : }
379 :
380 : /************************************************************************/
381 : /* SetNoDataValue() */
382 : /************************************************************************/
383 :
384 0 : void HKVDataset::SetNoDataValue( double dfNewValue )
385 :
386 : {
387 :
388 0 : this->bNoDataSet = TRUE;
389 0 : this->bNoDataChanged = TRUE;
390 0 : this->dfNoDataValue = dfNewValue;
391 0 : }
392 :
393 : /************************************************************************/
394 : /* SaveHKVAttribFile() */
395 : /************************************************************************/
396 :
397 25 : CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
398 : int nXSize, int nYSize, int nBands,
399 : GDALDataType eType, int bNoDataSet,
400 : double dfNoDataValue )
401 :
402 : {
403 :
404 : FILE *fp;
405 : const char *pszFilename;
406 :
407 25 : pszFilename = CPLFormFilename( pszFilenameIn, "attrib", NULL );
408 :
409 25 : fp = VSIFOpen( pszFilename, "wt" );
410 25 : if( fp == NULL )
411 : {
412 : CPLError( CE_Failure, CPLE_OpenFailed,
413 0 : "Couldn't create %s.\n", pszFilename );
414 0 : return CE_Failure;
415 : }
416 :
417 25 : fprintf( fp, "channel.enumeration = %d\n", nBands );
418 25 : fprintf( fp, "channel.interleave = { *pixel tile sequential }\n" );
419 25 : fprintf( fp, "extent.cols = %d\n", nXSize );
420 25 : fprintf( fp, "extent.rows = %d\n", nYSize );
421 :
422 25 : switch( eType )
423 : {
424 : case GDT_Byte:
425 : fprintf( fp, "pixel.encoding = "
426 10 : "{ *unsigned twos-complement ieee-754 }\n" );
427 10 : break;
428 :
429 : case GDT_UInt16:
430 : fprintf( fp, "pixel.encoding = "
431 3 : "{ *unsigned twos-complement ieee-754 }\n" );
432 3 : break;
433 :
434 : case GDT_CInt16:
435 : case GDT_Int16:
436 : fprintf( fp, "pixel.encoding = "
437 6 : "{ unsigned *twos-complement ieee-754 }\n" );
438 6 : break;
439 :
440 : case GDT_CFloat32:
441 : case GDT_Float32:
442 : fprintf( fp, "pixel.encoding = "
443 6 : "{ unsigned twos-complement *ieee-754 }\n" );
444 6 : break;
445 :
446 : default:
447 0 : CPLAssert( FALSE );
448 : }
449 :
450 25 : fprintf( fp, "pixel.size = %d\n", GDALGetDataTypeSize(eType) );
451 25 : if( GDALDataTypeIsComplex( eType ) )
452 6 : fprintf( fp, "pixel.field = { real *complex }\n" );
453 : else
454 19 : fprintf( fp, "pixel.field = { *real complex }\n" );
455 :
456 : #ifdef CPL_MSB
457 : fprintf( fp, "pixel.order = { lsbf *msbf }\n" );
458 : #else
459 25 : fprintf( fp, "pixel.order = { *lsbf msbf }\n" );
460 : #endif
461 :
462 25 : if ( bNoDataSet )
463 0 : fprintf( fp, "pixel.no_data = %f\n", dfNoDataValue );
464 :
465 : /* version information- only create the new style */
466 25 : fprintf( fp, "version = 1.1");
467 :
468 :
469 25 : VSIFClose( fp );
470 25 : return CE_None;
471 : }
472 :
473 :
474 : /************************************************************************/
475 : /* GetProjectionRef() */
476 : /************************************************************************/
477 :
478 20 : const char *HKVDataset::GetProjectionRef()
479 :
480 : {
481 20 : return( pszProjection );
482 : }
483 :
484 : /************************************************************************/
485 : /* GetGeoTransform() */
486 : /************************************************************************/
487 :
488 25 : CPLErr HKVDataset::GetGeoTransform( double * padfTransform )
489 :
490 : {
491 25 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
492 25 : return( CE_None );
493 : }
494 :
495 : /************************************************************************/
496 : /* SetGeoTransform() */
497 : /************************************************************************/
498 :
499 25 : CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
500 :
501 : {
502 : char szValue[128];
503 :
504 : /* NOTE: Geotransform coordinates must match the current projection */
505 : /* of the dataset being changed (not the geotransform source). */
506 : /* ie. be in lat/longs for LL projected; UTM for UTM projected. */
507 : /* SET PROJECTION BEFORE SETTING GEOTRANSFORM TO AVOID SYNCHRONIZATION */
508 : /* PROBLEMS! */
509 :
510 : /* Update the geotransform itself */
511 25 : memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
512 :
513 : /* Clear previous gcps */
514 25 : if( nGCPCount > 0 )
515 : {
516 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
517 0 : CPLFree( pasGCPList );
518 : }
519 25 : nGCPCount = 0;
520 25 : pasGCPList = NULL;
521 :
522 : /* Return if the identity transform is set */
523 25 : if (adfGeoTransform[0] == 0.0 && adfGeoTransform[1] == 1.0
524 0 : && adfGeoTransform[2] == 0.0 && adfGeoTransform[3] == 0.0
525 0 : && adfGeoTransform[4] == 0.0 && adfGeoTransform[5] == 1.0 )
526 0 : return CE_None;
527 :
528 : /* Update georef text info for saving later, and */
529 : /* update GCPs to match geotransform. */
530 :
531 : double temp_lat, temp_long;
532 25 : OGRSpatialReference oUTM;
533 25 : OGRSpatialReference oLL;
534 25 : OGRCoordinateTransformation *poTransform = NULL;
535 25 : int bSuccess=TRUE;
536 : char *pszPtemp;
537 : char *pszGCPtemp;
538 :
539 : /* Projection parameter checking will have been done */
540 : /* in SetProjection. */
541 25 : if(( CSLFetchNameValue( papszGeoref, "projection.name" ) != NULL ) &&
542 : ( EQUAL(CSLFetchNameValue( papszGeoref, "projection.name" ),"UTM" )))
543 :
544 : {
545 : /* pass copies of projection info, not originals (pointers */
546 : /* get updated by importFromWkt) */
547 0 : pszPtemp = CPLStrdup(pszProjection);
548 0 : oUTM.importFromWkt(&pszPtemp);
549 0 : (oUTM.GetAttrNode("GEOGCS"))->exportToWkt(&pszGCPtemp);
550 0 : oLL.importFromWkt(&pszGCPtemp);
551 0 : poTransform = OGRCreateCoordinateTransformation( &oUTM, &oLL );
552 0 : if( poTransform == NULL )
553 : {
554 0 : bSuccess = FALSE;
555 0 : CPLErrorReset();
556 : }
557 : }
558 25 : else if ((( CSLFetchNameValue( papszGeoref, "projection.name" ) != NULL ) &&
559 : ( !EQUAL(CSLFetchNameValue( papszGeoref, "projection.name" ),"LL" ))) ||
560 : (CSLFetchNameValue( papszGeoref, "projection.name" ) == NULL ))
561 : {
562 15 : return CE_Failure;
563 : }
564 :
565 10 : nGCPCount = 0;
566 10 : pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),5);
567 :
568 : /* -------------------------------------------------------------------- */
569 : /* top left */
570 : /* -------------------------------------------------------------------- */
571 10 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
572 10 : CPLFree( pasGCPList[nGCPCount].pszId );
573 10 : pasGCPList[nGCPCount].pszId = CPLStrdup( "top_left" );
574 :
575 10 : if (MFF2version > 1.0)
576 : {
577 10 : temp_lat = padfTransform[3];
578 10 : temp_long = padfTransform[0];
579 10 : pasGCPList[nGCPCount].dfGCPPixel = 0.0;
580 10 : pasGCPList[nGCPCount].dfGCPLine = 0.0;
581 : }
582 : else
583 : {
584 0 : temp_lat = padfTransform[3] + 0.5 * padfTransform[4] + 0.5 * padfTransform[5];
585 0 : temp_long = padfTransform[0] + 0.5 * padfTransform[1]+ 0.5 * padfTransform[2];
586 0 : pasGCPList[nGCPCount].dfGCPPixel = 0.5;
587 0 : pasGCPList[nGCPCount].dfGCPLine = 0.5;
588 : }
589 10 : pasGCPList[nGCPCount].dfGCPX = temp_long;
590 10 : pasGCPList[nGCPCount].dfGCPY = temp_lat;
591 10 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
592 10 : nGCPCount++;
593 :
594 10 : if (poTransform != NULL)
595 : {
596 0 : if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
597 0 : bSuccess = FALSE;
598 : }
599 :
600 10 : if (bSuccess)
601 : {
602 10 : sprintf( szValue, "%.10f", temp_lat );
603 : papszGeoref = CSLSetNameValue( papszGeoref, "top_left.latitude",
604 10 : szValue );
605 :
606 10 : sprintf( szValue, "%.10f", temp_long );
607 : papszGeoref = CSLSetNameValue( papszGeoref, "top_left.longitude",
608 10 : szValue );
609 : }
610 :
611 : /* -------------------------------------------------------------------- */
612 : /* top_right */
613 : /* -------------------------------------------------------------------- */
614 10 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
615 10 : CPLFree( pasGCPList[nGCPCount].pszId );
616 10 : pasGCPList[nGCPCount].pszId = CPLStrdup( "top_right" );
617 :
618 10 : if (MFF2version > 1.0)
619 : {
620 10 : temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4];
621 10 : temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1];
622 10 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize();
623 10 : pasGCPList[nGCPCount].dfGCPLine = 0.0;
624 : }
625 : else
626 : {
627 0 : temp_lat = padfTransform[3] + (GetRasterXSize()-0.5) * padfTransform[4] + 0.5 * padfTransform[5];
628 0 : temp_long = padfTransform[0] + (GetRasterXSize()-0.5) * padfTransform[1] + 0.5 * padfTransform[2];
629 0 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()-0.5;
630 0 : pasGCPList[nGCPCount].dfGCPLine = 0.5;
631 : }
632 10 : pasGCPList[nGCPCount].dfGCPX = temp_long;
633 10 : pasGCPList[nGCPCount].dfGCPY = temp_lat;
634 10 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
635 10 : nGCPCount++;
636 :
637 10 : if (poTransform != NULL)
638 : {
639 0 : if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
640 0 : bSuccess = FALSE;
641 : }
642 :
643 10 : if (bSuccess)
644 : {
645 10 : sprintf( szValue, "%.10f", temp_lat );
646 : papszGeoref = CSLSetNameValue( papszGeoref, "top_right.latitude",
647 10 : szValue );
648 :
649 10 : sprintf( szValue, "%.10f", temp_long );
650 : papszGeoref = CSLSetNameValue( papszGeoref, "top_right.longitude",
651 10 : szValue );
652 : }
653 :
654 : /* -------------------------------------------------------------------- */
655 : /* bottom_left */
656 : /* -------------------------------------------------------------------- */
657 10 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
658 10 : CPLFree( pasGCPList[nGCPCount].pszId );
659 10 : pasGCPList[nGCPCount].pszId = CPLStrdup( "bottom_left" );
660 :
661 10 : if (MFF2version > 1.0)
662 : {
663 10 : temp_lat = padfTransform[3] + GetRasterYSize() * padfTransform[5];
664 10 : temp_long = padfTransform[0] + GetRasterYSize() * padfTransform[2];
665 10 : pasGCPList[nGCPCount].dfGCPPixel = 0.0;
666 10 : pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize();
667 : }
668 : else
669 : {
670 0 : temp_lat = padfTransform[3] + 0.5 * padfTransform[4] + (GetRasterYSize()-0.5) * padfTransform[5];
671 0 : temp_long = padfTransform[0] + 0.5 * padfTransform[1] + (GetRasterYSize()-0.5) * padfTransform[2];
672 0 : pasGCPList[nGCPCount].dfGCPPixel = 0.5;
673 0 : pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()-0.5;
674 : }
675 10 : pasGCPList[nGCPCount].dfGCPX = temp_long;
676 10 : pasGCPList[nGCPCount].dfGCPY = temp_lat;
677 10 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
678 10 : nGCPCount++;
679 :
680 10 : if (poTransform != NULL)
681 : {
682 0 : if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
683 0 : bSuccess = FALSE;
684 : }
685 :
686 10 : if (bSuccess)
687 : {
688 10 : sprintf( szValue, "%.10f", temp_lat );
689 : papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.latitude",
690 10 : szValue );
691 :
692 10 : sprintf( szValue, "%.10f", temp_long );
693 : papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.longitude",
694 10 : szValue );
695 : }
696 :
697 : /* -------------------------------------------------------------------- */
698 : /* bottom_right */
699 : /* -------------------------------------------------------------------- */
700 10 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
701 10 : CPLFree( pasGCPList[nGCPCount].pszId );
702 10 : pasGCPList[nGCPCount].pszId = CPLStrdup( "bottom_right" );
703 :
704 10 : if (MFF2version > 1.0)
705 : {
706 20 : temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] +
707 20 : GetRasterYSize() * padfTransform[5];
708 20 : temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] +
709 20 : GetRasterYSize() * padfTransform[2];
710 10 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize();
711 10 : pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize();
712 :
713 : }
714 : else
715 : {
716 0 : temp_lat = padfTransform[3] + (GetRasterXSize()-0.5) * padfTransform[4] +
717 0 : (GetRasterYSize()-0.5) * padfTransform[5];
718 0 : temp_long = padfTransform[0] + (GetRasterXSize()-0.5) * padfTransform[1] +
719 0 : (GetRasterYSize()-0.5) * padfTransform[2];
720 0 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()-0.5;
721 0 : pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()-0.5;
722 : }
723 10 : pasGCPList[nGCPCount].dfGCPX = temp_long;
724 10 : pasGCPList[nGCPCount].dfGCPY = temp_lat;
725 10 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
726 10 : nGCPCount++;
727 :
728 10 : if (poTransform != NULL)
729 : {
730 0 : if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
731 0 : bSuccess = FALSE;
732 : }
733 :
734 10 : if (bSuccess)
735 : {
736 10 : sprintf( szValue, "%.10f", temp_lat );
737 : papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.latitude",
738 10 : szValue );
739 :
740 10 : sprintf( szValue, "%.10f", temp_long );
741 : papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.longitude",
742 10 : szValue );
743 : }
744 :
745 : /* -------------------------------------------------------------------- */
746 : /* Center */
747 : /* -------------------------------------------------------------------- */
748 10 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
749 10 : CPLFree( pasGCPList[nGCPCount].pszId );
750 10 : pasGCPList[nGCPCount].pszId = CPLStrdup( "centre" );
751 :
752 10 : if (MFF2version > 1.0)
753 : {
754 20 : temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
755 20 : GetRasterYSize() * padfTransform[5] * 0.5;
756 20 : temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
757 20 : GetRasterYSize() * padfTransform[2] * 0.5;
758 10 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
759 10 : pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
760 : }
761 : else
762 : {
763 0 : temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
764 0 : GetRasterYSize() * padfTransform[5] * 0.5;
765 0 : temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
766 0 : GetRasterYSize() * padfTransform[2] * 0.5;
767 0 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
768 0 : pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
769 : }
770 10 : pasGCPList[nGCPCount].dfGCPX = temp_long;
771 10 : pasGCPList[nGCPCount].dfGCPY = temp_lat;
772 10 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
773 10 : nGCPCount++;
774 :
775 10 : if (poTransform != NULL)
776 : {
777 0 : if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
778 0 : bSuccess = FALSE;
779 : }
780 :
781 10 : if (bSuccess)
782 : {
783 10 : sprintf( szValue, "%.10f", temp_lat );
784 : papszGeoref = CSLSetNameValue( papszGeoref, "centre.latitude",
785 10 : szValue );
786 :
787 10 : sprintf( szValue, "%.10f", temp_long );
788 : papszGeoref = CSLSetNameValue( papszGeoref, "centre.longitude",
789 10 : szValue );
790 : }
791 :
792 10 : if (!bSuccess)
793 : {
794 : CPLError(CE_Warning,CPLE_AppDefined,
795 0 : "Warning- error setting header info in SetGeoTransform. Changes may not be saved properly.\n");
796 : }
797 :
798 10 : if (poTransform != NULL)
799 0 : delete poTransform;
800 :
801 :
802 :
803 10 : bGeorefChanged = TRUE;
804 :
805 10 : return( CE_None );
806 : }
807 :
808 10 : CPLErr HKVDataset::SetGCPProjection( const char *pszNewProjection )
809 : {
810 :
811 10 : CPLFree( pszGCPProjection );
812 10 : this->pszGCPProjection = CPLStrdup(pszNewProjection);
813 :
814 10 : return CE_None;
815 : }
816 :
817 : /************************************************************************/
818 : /* SetProjection() */
819 : /* */
820 : /* We provide very limited support for setting the projection. */
821 : /************************************************************************/
822 :
823 25 : CPLErr HKVDataset::SetProjection( const char * pszNewProjection )
824 :
825 : {
826 : HKVSpheroidList *hkvEllipsoids;
827 : double eq_radius, inv_flattening;
828 25 : OGRErr ogrerrorEq=OGRERR_NONE;
829 25 : OGRErr ogrerrorInvf=OGRERR_NONE;
830 25 : OGRErr ogrerrorOl=OGRERR_NONE;
831 :
832 25 : char *spheroid_name = NULL;
833 :
834 : /* This function is used to update a georef file */
835 :
836 :
837 : /* printf( "HKVDataset::SetProjection(%s)\n", pszNewProjection ); */
838 :
839 25 : if( !EQUALN(pszNewProjection,"GEOGCS",6)
840 : && !EQUALN(pszNewProjection,"PROJCS",6)
841 : && !EQUAL(pszNewProjection,"") )
842 : {
843 : CPLError( CE_Failure, CPLE_AppDefined,
844 : "Only OGC WKT Projections supported for writing to HKV.\n"
845 : "%s not supported.",
846 0 : pszNewProjection );
847 :
848 0 : return CE_Failure;
849 : }
850 25 : else if (EQUAL(pszNewProjection,""))
851 : {
852 0 : CPLFree( pszProjection );
853 0 : pszProjection = (char *) CPLStrdup(pszNewProjection);
854 :
855 0 : return CE_None;
856 : }
857 25 : CPLFree( pszProjection );
858 25 : pszProjection = (char *) CPLStrdup(pszNewProjection);
859 :
860 :
861 25 : OGRSpatialReference oSRS(pszNewProjection);
862 :
863 25 : if ((oSRS.GetAttrValue("PROJECTION") != NULL) &&
864 : (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
865 : {
866 : char *ol_txt;
867 0 : ol_txt=(char *) CPLMalloc(255);
868 0 : papszGeoref = CSLSetNameValue( papszGeoref, "projection.name", "utm" );
869 0 : sprintf(ol_txt,"%f",oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl));
870 : papszGeoref = CSLSetNameValue( papszGeoref, "projection.origin_longitude",
871 0 : ol_txt );
872 0 : CPLFree(ol_txt);
873 : }
874 25 : else if ((oSRS.GetAttrValue("PROJECTION") == NULL) && (oSRS.IsGeographic()))
875 : {
876 25 : papszGeoref = CSLSetNameValue( papszGeoref, "projection.name", "LL" );
877 : }
878 : else
879 : {
880 : CPLError( CE_Warning, CPLE_AppDefined,
881 0 : "Unrecognized projection.");
882 0 : return CE_Failure;
883 : }
884 25 : eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
885 25 : inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
886 50 : if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE))
887 : {
888 25 : hkvEllipsoids = new HKVSpheroidList;
889 50 : spheroid_name = hkvEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(eq_radius,inv_flattening);
890 25 : if (spheroid_name != NULL)
891 : {
892 : papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name",
893 25 : spheroid_name );
894 : }
895 25 : CPLFree(spheroid_name);
896 25 : delete hkvEllipsoids;
897 : }
898 : else
899 : {
900 : /* default to previous behaviour if spheroid not found by */
901 : /* radius and inverse flattening */
902 :
903 0 : if( strstr(pszNewProjection,"Bessel") != NULL )
904 : {
905 : papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name",
906 0 : "ev-bessel" );
907 : }
908 : else
909 : {
910 : papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name",
911 0 : "ev-wgs-84" );
912 : }
913 : }
914 25 : bGeorefChanged = TRUE;
915 25 : return CE_None;
916 : }
917 :
918 : /************************************************************************/
919 : /* GetGCPCount() */
920 : /************************************************************************/
921 :
922 0 : int HKVDataset::GetGCPCount()
923 :
924 : {
925 0 : return nGCPCount;
926 : }
927 :
928 : /************************************************************************/
929 : /* GetGCPProjection() */
930 : /************************************************************************/
931 :
932 0 : const char *HKVDataset::GetGCPProjection()
933 :
934 : {
935 0 : return pszGCPProjection;
936 : }
937 :
938 : /************************************************************************/
939 : /* GetGCP() */
940 : /************************************************************************/
941 :
942 0 : const GDAL_GCP *HKVDataset::GetGCPs()
943 :
944 : {
945 0 : return pasGCPList;
946 : }
947 :
948 : /************************************************************************/
949 : /* ProcessGeorefGCP() */
950 : /************************************************************************/
951 :
952 80 : void HKVDataset::ProcessGeorefGCP( char **papszGeoref, const char *pszBase,
953 : double dfRasterX, double dfRasterY )
954 :
955 : {
956 : char szFieldName[128];
957 : double dfLat, dfLong;
958 :
959 : /* -------------------------------------------------------------------- */
960 : /* Fetch the GCP from the string list. */
961 : /* -------------------------------------------------------------------- */
962 80 : sprintf( szFieldName, "%s.latitude", pszBase );
963 80 : if( CSLFetchNameValue(papszGeoref, szFieldName) == NULL )
964 75 : return;
965 : else
966 5 : dfLat = atof(CSLFetchNameValue(papszGeoref, szFieldName));
967 :
968 5 : sprintf( szFieldName, "%s.longitude", pszBase );
969 5 : if( CSLFetchNameValue(papszGeoref, szFieldName) == NULL )
970 0 : return;
971 : else
972 5 : dfLong = atof(CSLFetchNameValue(papszGeoref, szFieldName));
973 :
974 : /* -------------------------------------------------------------------- */
975 : /* Add the gcp to the internal list. */
976 : /* -------------------------------------------------------------------- */
977 5 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
978 :
979 5 : CPLFree( pasGCPList[nGCPCount].pszId );
980 :
981 5 : pasGCPList[nGCPCount].pszId = CPLStrdup( pszBase );
982 :
983 5 : pasGCPList[nGCPCount].dfGCPX = dfLong;
984 5 : pasGCPList[nGCPCount].dfGCPY = dfLat;
985 5 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
986 :
987 5 : pasGCPList[nGCPCount].dfGCPPixel = dfRasterX;
988 5 : pasGCPList[nGCPCount].dfGCPLine = dfRasterY;
989 :
990 5 : nGCPCount++;
991 : }
992 :
993 : /************************************************************************/
994 : /* ProcessGeoref() */
995 : /************************************************************************/
996 :
997 16 : void HKVDataset::ProcessGeoref( const char * pszFilename )
998 :
999 : {
1000 : int i;
1001 16 : HKVSpheroidList *hkvEllipsoids = NULL;
1002 :
1003 : /* -------------------------------------------------------------------- */
1004 : /* Load the georef file, and boil white space away from around */
1005 : /* the equal sign. */
1006 : /* -------------------------------------------------------------------- */
1007 16 : CSLDestroy( papszGeoref );
1008 16 : papszGeoref = CSLLoad( pszFilename );
1009 16 : if( papszGeoref == NULL )
1010 0 : return;
1011 :
1012 16 : hkvEllipsoids = new HKVSpheroidList;
1013 :
1014 59 : for( i = 0; papszGeoref[i] != NULL; i++ )
1015 : {
1016 43 : int bAfterEqual = FALSE;
1017 : int iSrc, iDst;
1018 43 : char *pszLine = papszGeoref[i];
1019 :
1020 1033 : for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
1021 : {
1022 990 : if( bAfterEqual || pszLine[iSrc] != ' ' )
1023 : {
1024 990 : pszLine[iDst++] = pszLine[iSrc];
1025 : }
1026 :
1027 990 : if( iDst > 0 && pszLine[iDst-1] == '=' )
1028 43 : bAfterEqual = FALSE;
1029 : }
1030 43 : pszLine[iDst] = '\0';
1031 : }
1032 :
1033 : /* -------------------------------------------------------------------- */
1034 : /* Try to get GCPs, in lat/longs . */
1035 : /* -------------------------------------------------------------------- */
1036 16 : nGCPCount = 0;
1037 16 : pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),5);
1038 :
1039 16 : if (MFF2version > 1.0)
1040 : {
1041 : ProcessGeorefGCP( papszGeoref, "top_left",
1042 16 : 0, 0 );
1043 : ProcessGeorefGCP( papszGeoref, "top_right",
1044 16 : GetRasterXSize(), 0 );
1045 : ProcessGeorefGCP( papszGeoref, "bottom_left",
1046 16 : 0, GetRasterYSize() );
1047 : ProcessGeorefGCP( papszGeoref, "bottom_right",
1048 16 : GetRasterXSize(), GetRasterYSize() );
1049 : ProcessGeorefGCP( papszGeoref, "centre",
1050 16 : GetRasterXSize()/2.0, GetRasterYSize()/2.0 );
1051 : }
1052 : else
1053 : {
1054 : ProcessGeorefGCP( papszGeoref, "top_left",
1055 0 : 0.5, 0.5 );
1056 : ProcessGeorefGCP( papszGeoref, "top_right",
1057 0 : GetRasterXSize()-0.5, 0.5 );
1058 : ProcessGeorefGCP( papszGeoref, "bottom_left",
1059 0 : 0.5, GetRasterYSize()-0.5 );
1060 : ProcessGeorefGCP( papszGeoref, "bottom_right",
1061 0 : GetRasterXSize()-0.5, GetRasterYSize()-0.5 );
1062 : ProcessGeorefGCP( papszGeoref, "centre",
1063 0 : GetRasterXSize()/2.0, GetRasterYSize()/2.0 );
1064 : }
1065 :
1066 16 : if (nGCPCount == 0)
1067 : {
1068 15 : CPLFree(pasGCPList);
1069 15 : pasGCPList = NULL;
1070 : }
1071 :
1072 : /* -------------------------------------------------------------------- */
1073 : /* Do we have a recognised projection? */
1074 : /* -------------------------------------------------------------------- */
1075 : const char *pszProjName, *pszOriginLong, *pszSpheroidName;
1076 : double eq_radius, inv_flattening;
1077 :
1078 : pszProjName = CSLFetchNameValue(papszGeoref,
1079 16 : "projection.name");
1080 : pszOriginLong = CSLFetchNameValue(papszGeoref,
1081 16 : "projection.origin_longitude");
1082 : pszSpheroidName = CSLFetchNameValue(papszGeoref,
1083 16 : "spheroid.name");
1084 :
1085 :
1086 16 : if ((pszSpheroidName != NULL) && (hkvEllipsoids->SpheroidInList(pszSpheroidName)))
1087 : {
1088 16 : eq_radius=hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName);
1089 16 : inv_flattening=hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName);
1090 : }
1091 0 : else if (pszProjName != NULL)
1092 : {
1093 0 : CPLError(CE_Warning,CPLE_AppDefined,"Warning- unrecognized ellipsoid. Using wgs-84 parameters.\n");
1094 0 : eq_radius=hkvEllipsoids->GetSpheroidEqRadius("wgs-84");
1095 0 : inv_flattening=hkvEllipsoids->GetSpheroidInverseFlattening("wgs-84");
1096 : }
1097 :
1098 17 : if( (pszProjName != NULL) && EQUAL(pszProjName,"utm") && (nGCPCount == 5) )
1099 : {
1100 : /*int nZone = (int)((atof(pszOriginLong)+184.5) / 6.0); */
1101 : int nZone;
1102 :
1103 1 : if (pszOriginLong == NULL)
1104 : {
1105 : /* If origin not specified, assume 0.0 */
1106 : CPLError(CE_Warning,CPLE_AppDefined,
1107 0 : "Warning- no projection origin longitude specified. Assuming 0.0.");
1108 0 : nZone = 31;
1109 : }
1110 : else
1111 1 : nZone = 31 + (int) floor(atof(pszOriginLong)/6.0);
1112 :
1113 1 : OGRSpatialReference oUTM;
1114 1 : OGRSpatialReference oLL;
1115 1 : OGRCoordinateTransformation *poTransform = NULL;
1116 : double dfUtmX[5], dfUtmY[5];
1117 : int gcp_index;
1118 :
1119 1 : int bSuccess = TRUE;
1120 :
1121 1 : if( pasGCPList[4].dfGCPY < 0 )
1122 0 : oUTM.SetUTM( nZone, 0 );
1123 : else
1124 1 : oUTM.SetUTM( nZone, 1 );
1125 :
1126 1 : if (pszOriginLong != NULL)
1127 : {
1128 1 : oUTM.SetProjParm(SRS_PP_CENTRAL_MERIDIAN,atof(pszOriginLong));
1129 1 : oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,atof(pszOriginLong));
1130 : }
1131 :
1132 1 : if ((pszSpheroidName == NULL) || (EQUAL(pszSpheroidName,"wgs-84")) ||
1133 : (EQUAL(pszSpheroidName,"wgs_84")))
1134 : {
1135 0 : oUTM.SetWellKnownGeogCS( "WGS84" );
1136 0 : oLL.SetWellKnownGeogCS( "WGS84" );
1137 : }
1138 : else
1139 : {
1140 1 : if (hkvEllipsoids->SpheroidInList(pszSpheroidName))
1141 : {
1142 : oUTM.SetGeogCS( "unknown","unknown",pszSpheroidName,
1143 : hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
1144 : hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
1145 1 : );
1146 : oLL.SetGeogCS( "unknown","unknown",pszSpheroidName,
1147 : hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
1148 : hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
1149 1 : );
1150 : }
1151 : else
1152 : {
1153 0 : CPLError(CE_Warning,CPLE_AppDefined,"Warning- unrecognized ellipsoid. Using wgs-84 parameters.\n");
1154 0 : oUTM.SetWellKnownGeogCS( "WGS84" );
1155 0 : oLL.SetWellKnownGeogCS( "WGS84" );
1156 : }
1157 : }
1158 :
1159 1 : poTransform = OGRCreateCoordinateTransformation( &oLL, &oUTM );
1160 1 : if( poTransform == NULL )
1161 : {
1162 0 : CPLErrorReset();
1163 0 : bSuccess = FALSE;
1164 : }
1165 :
1166 6 : for(gcp_index=0;gcp_index<5;gcp_index++)
1167 : {
1168 5 : dfUtmX[gcp_index] = pasGCPList[gcp_index].dfGCPX;
1169 5 : dfUtmY[gcp_index] = pasGCPList[gcp_index].dfGCPY;
1170 :
1171 5 : if( bSuccess && !poTransform->Transform( 1, &(dfUtmX[gcp_index]), &(dfUtmY[gcp_index]) ) )
1172 0 : bSuccess = FALSE;
1173 :
1174 : }
1175 :
1176 1 : if( bSuccess )
1177 : {
1178 1 : int transform_ok = FALSE;
1179 :
1180 : /* update GCPS to proper projection */
1181 6 : for(gcp_index=0;gcp_index<5;gcp_index++)
1182 : {
1183 5 : pasGCPList[gcp_index].dfGCPX = dfUtmX[gcp_index];
1184 5 : pasGCPList[gcp_index].dfGCPY = dfUtmY[gcp_index];
1185 : }
1186 :
1187 1 : CPLFree( pszGCPProjection );
1188 1 : pszGCPProjection = NULL;
1189 1 : oUTM.exportToWkt( &pszGCPProjection );
1190 :
1191 1 : transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
1192 :
1193 1 : CPLFree( pszProjection );
1194 1 : pszProjection = NULL;
1195 1 : if (transform_ok == FALSE)
1196 : {
1197 : /* transform may not be sufficient in all cases (slant range projection) */
1198 0 : adfGeoTransform[0] = 0.0;
1199 0 : adfGeoTransform[1] = 1.0;
1200 0 : adfGeoTransform[2] = 0.0;
1201 0 : adfGeoTransform[3] = 0.0;
1202 0 : adfGeoTransform[4] = 0.0;
1203 0 : adfGeoTransform[5] = 1.0;
1204 0 : pszProjection = CPLStrdup("");
1205 : }
1206 : else
1207 1 : oUTM.exportToWkt( &pszProjection );
1208 :
1209 : }
1210 :
1211 1 : if( poTransform != NULL )
1212 1 : delete poTransform;
1213 : }
1214 15 : else if ((pszProjName != NULL) && (nGCPCount == 5))
1215 : {
1216 0 : OGRSpatialReference oLL;
1217 0 : int transform_ok = FALSE;
1218 :
1219 :
1220 0 : if (pszOriginLong != NULL)
1221 : {
1222 0 : oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,atof(pszOriginLong));
1223 : }
1224 :
1225 0 : if ((pszSpheroidName == NULL) || (EQUAL(pszSpheroidName,"wgs-84")) ||
1226 : (EQUAL(pszSpheroidName,"wgs_84")))
1227 : {
1228 0 : oLL.SetWellKnownGeogCS( "WGS84" );
1229 : }
1230 : else
1231 : {
1232 0 : if (hkvEllipsoids->SpheroidInList(pszSpheroidName))
1233 : {
1234 : oLL.SetGeogCS( "","",pszSpheroidName,
1235 : hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
1236 : hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
1237 0 : );
1238 : }
1239 : else
1240 : {
1241 0 : CPLError(CE_Warning,CPLE_AppDefined,"Warning- unrecognized ellipsoid. Using wgs-84 parameters.\n");
1242 0 : oLL.SetWellKnownGeogCS( "WGS84" );
1243 : }
1244 : }
1245 :
1246 0 : transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
1247 :
1248 0 : CPLFree( pszProjection );
1249 0 : pszProjection = NULL;
1250 :
1251 0 : if (transform_ok == FALSE)
1252 : {
1253 0 : adfGeoTransform[0] = 0.0;
1254 0 : adfGeoTransform[1] = 1.0;
1255 0 : adfGeoTransform[2] = 0.0;
1256 0 : adfGeoTransform[3] = 0.0;
1257 0 : adfGeoTransform[4] = 0.0;
1258 0 : adfGeoTransform[5] = 1.0;
1259 : }
1260 : else
1261 : {
1262 0 : oLL.exportToWkt( &pszProjection );
1263 : }
1264 :
1265 0 : CPLFree( pszGCPProjection );
1266 0 : pszGCPProjection = NULL;
1267 0 : oLL.exportToWkt( &pszGCPProjection );
1268 :
1269 : }
1270 :
1271 16 : delete hkvEllipsoids;
1272 : }
1273 :
1274 : /************************************************************************/
1275 : /* Open() */
1276 : /************************************************************************/
1277 :
1278 12083 : GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
1279 :
1280 : {
1281 12083 : int i, bNoDataSet = FALSE;
1282 12083 : double dfNoDataValue = 0.0;
1283 : char **papszAttrib;
1284 : const char *pszFilename, *pszValue;
1285 : VSIStatBuf sStat;
1286 :
1287 : /* -------------------------------------------------------------------- */
1288 : /* We assume the dataset is passed as a directory. Check for */
1289 : /* an attrib and blob file as a minimum. */
1290 : /* -------------------------------------------------------------------- */
1291 12083 : if( !poOpenInfo->bIsDirectory )
1292 12041 : return NULL;
1293 :
1294 42 : pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "image_data", NULL);
1295 42 : if( VSIStat(pszFilename,&sStat) != 0 )
1296 1 : pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "blob", NULL );
1297 42 : if( VSIStat(pszFilename,&sStat) != 0 )
1298 1 : return NULL;
1299 :
1300 41 : pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "attrib", NULL );
1301 41 : if( VSIStat(pszFilename,&sStat) != 0 )
1302 0 : return NULL;
1303 :
1304 : /* -------------------------------------------------------------------- */
1305 : /* Load the attrib file, and boil white space away from around */
1306 : /* the equal sign. */
1307 : /* -------------------------------------------------------------------- */
1308 41 : papszAttrib = CSLLoad( pszFilename );
1309 41 : if( papszAttrib == NULL )
1310 0 : return NULL;
1311 :
1312 410 : for( i = 0; papszAttrib[i] != NULL; i++ )
1313 : {
1314 369 : int bAfterEqual = FALSE;
1315 : int iSrc, iDst;
1316 369 : char *pszLine = papszAttrib[i];
1317 :
1318 10417 : for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
1319 : {
1320 10048 : if( bAfterEqual || pszLine[iSrc] != ' ' )
1321 : {
1322 8736 : pszLine[iDst++] = pszLine[iSrc];
1323 : }
1324 :
1325 10048 : if( iDst > 0 && pszLine[iDst-1] == '=' )
1326 738 : bAfterEqual = FALSE;
1327 : }
1328 369 : pszLine[iDst] = '\0';
1329 : }
1330 :
1331 : /* -------------------------------------------------------------------- */
1332 : /* Create a corresponding GDALDataset. */
1333 : /* -------------------------------------------------------------------- */
1334 : HKVDataset *poDS;
1335 :
1336 41 : poDS = new HKVDataset();
1337 :
1338 41 : poDS->pszPath = CPLStrdup( poOpenInfo->pszFilename );
1339 41 : poDS->papszAttrib = papszAttrib;
1340 :
1341 41 : poDS->eAccess = poOpenInfo->eAccess;
1342 :
1343 : /* -------------------------------------------------------------------- */
1344 : /* Set some dataset wide information. */
1345 : /* -------------------------------------------------------------------- */
1346 : int bNative, bComplex;
1347 41 : int nRawBands = 0;
1348 :
1349 82 : if( CSLFetchNameValue( papszAttrib, "extent.cols" ) == NULL
1350 : || CSLFetchNameValue( papszAttrib, "extent.rows" ) == NULL )
1351 0 : return NULL;
1352 :
1353 41 : poDS->nRasterXSize = atoi(CSLFetchNameValue(papszAttrib,"extent.cols"));
1354 41 : poDS->nRasterYSize = atoi(CSLFetchNameValue(papszAttrib,"extent.rows"));
1355 :
1356 41 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
1357 : {
1358 0 : delete poDS;
1359 0 : return NULL;
1360 : }
1361 :
1362 41 : pszValue = CSLFetchNameValue(papszAttrib,"pixel.order");
1363 41 : if( pszValue == NULL )
1364 0 : bNative = TRUE;
1365 : else
1366 : {
1367 : #ifdef CPL_MSB
1368 : bNative = (strstr(pszValue,"*msbf") != NULL);
1369 : #else
1370 41 : bNative = (strstr(pszValue,"*lsbf") != NULL);
1371 : #endif
1372 : }
1373 :
1374 41 : pszValue = CSLFetchNameValue(papszAttrib,"pixel.no_data");
1375 41 : if( pszValue != NULL )
1376 : {
1377 0 : bNoDataSet = TRUE;
1378 0 : dfNoDataValue = atof(pszValue);
1379 : }
1380 :
1381 41 : pszValue = CSLFetchNameValue(papszAttrib,"channel.enumeration");
1382 41 : if( pszValue != NULL )
1383 41 : nRawBands = atoi(pszValue);
1384 : else
1385 0 : nRawBands = 1;
1386 :
1387 41 : if (!GDALCheckBandCount(nRawBands, TRUE))
1388 : {
1389 0 : delete poDS;
1390 0 : return NULL;
1391 : }
1392 :
1393 41 : pszValue = CSLFetchNameValue(papszAttrib,"pixel.field");
1394 51 : if( pszValue != NULL && strstr(pszValue,"*complex") != NULL )
1395 10 : bComplex = TRUE;
1396 : else
1397 31 : bComplex = FALSE;
1398 :
1399 : /* Get the version number, if present (if not, assume old version. */
1400 : /* Versions differ in their interpretation of corner coordinates. */
1401 :
1402 41 : if (CSLFetchNameValue( papszAttrib, "version" ) != NULL)
1403 : poDS->SetVersion((float)
1404 41 : atof(CSLFetchNameValue(papszAttrib, "version")));
1405 : else
1406 0 : poDS->SetVersion(1.0);
1407 :
1408 : /* -------------------------------------------------------------------- */
1409 : /* Figure out the datatype */
1410 : /* -------------------------------------------------------------------- */
1411 : const char * pszEncoding;
1412 41 : int nSize = 1;
1413 : int nPseudoBands;
1414 : GDALDataType eType;
1415 :
1416 41 : pszEncoding = CSLFetchNameValue(papszAttrib,"pixel.encoding");
1417 41 : if( pszEncoding == NULL )
1418 0 : pszEncoding = "{ *unsigned }";
1419 :
1420 41 : if( CSLFetchNameValue(papszAttrib,"pixel.size") != NULL )
1421 41 : nSize = atoi(CSLFetchNameValue(papszAttrib,"pixel.size"))/8;
1422 :
1423 41 : if( bComplex )
1424 10 : nPseudoBands = 2;
1425 : else
1426 31 : nPseudoBands = 1;
1427 :
1428 41 : if( nSize == 1 )
1429 16 : eType = GDT_Byte;
1430 30 : else if( nSize == 2 && strstr(pszEncoding,"*unsigned") != NULL )
1431 5 : eType = GDT_UInt16;
1432 25 : else if( nSize == 4 && bComplex )
1433 5 : eType = GDT_CInt16;
1434 15 : else if( nSize == 2 )
1435 5 : eType = GDT_Int16;
1436 10 : else if( nSize == 4 && strstr(pszEncoding,"*unsigned") != NULL )
1437 0 : eType = GDT_UInt32;
1438 10 : else if( nSize == 8 && strstr(pszEncoding,"*two") != NULL && bComplex )
1439 0 : eType = GDT_CInt32;
1440 10 : else if( nSize == 4 && strstr(pszEncoding,"*two") != NULL )
1441 0 : eType = GDT_Int32;
1442 15 : else if( nSize == 8 && bComplex )
1443 5 : eType = GDT_CFloat32;
1444 5 : else if( nSize == 4 )
1445 5 : eType = GDT_Float32;
1446 0 : else if( nSize == 16 && bComplex )
1447 0 : eType = GDT_CFloat64;
1448 0 : else if( nSize == 8 )
1449 0 : eType = GDT_Float64;
1450 : else
1451 : {
1452 : CPLError( CE_Failure, CPLE_AppDefined,
1453 : "Unsupported pixel data type in %s.\n"
1454 : "pixel.size=%d pixel.encoding=%s\n",
1455 0 : poDS->pszPath, nSize, pszEncoding );
1456 0 : delete poDS;
1457 0 : return NULL;
1458 : }
1459 :
1460 : /* -------------------------------------------------------------------- */
1461 : /* Open the blob file. */
1462 : /* -------------------------------------------------------------------- */
1463 41 : pszFilename = CPLFormFilename(poDS->pszPath, "image_data", NULL );
1464 41 : if( VSIStat(pszFilename,&sStat) != 0 )
1465 0 : pszFilename = CPLFormFilename(poDS->pszPath, "blob", NULL );
1466 41 : if( poOpenInfo->eAccess == GA_ReadOnly )
1467 : {
1468 16 : poDS->fpBlob = VSIFOpenL( pszFilename, "rb" );
1469 16 : if( poDS->fpBlob == NULL )
1470 : {
1471 : CPLError( CE_Failure, CPLE_OpenFailed,
1472 : "Unable to open file %s for read access.\n",
1473 0 : pszFilename );
1474 0 : delete poDS;
1475 0 : return NULL;
1476 : }
1477 : }
1478 : else
1479 : {
1480 25 : poDS->fpBlob = VSIFOpenL( pszFilename, "rb+" );
1481 25 : if( poDS->fpBlob == NULL )
1482 : {
1483 : CPLError( CE_Failure, CPLE_OpenFailed,
1484 : "Unable to open file %s for update access.\n",
1485 0 : pszFilename );
1486 0 : delete poDS;
1487 0 : return NULL;
1488 : }
1489 : }
1490 :
1491 : /* -------------------------------------------------------------------- */
1492 : /* Build the overview filename, as blob file = "_ovr". */
1493 : /* -------------------------------------------------------------------- */
1494 41 : char *pszOvrFilename = (char *) CPLMalloc(strlen(pszFilename)+5);
1495 :
1496 41 : sprintf( pszOvrFilename, "%s_ovr", pszFilename );
1497 :
1498 : /* -------------------------------------------------------------------- */
1499 : /* Define the bands. */
1500 : /* -------------------------------------------------------------------- */
1501 : int nPixelOffset, nLineOffset, nOffset;
1502 :
1503 41 : nPixelOffset = nRawBands * nSize;
1504 41 : nLineOffset = nPixelOffset * poDS->GetRasterXSize();
1505 41 : nOffset = 0;
1506 :
1507 132 : for( int iRawBand=0; iRawBand < nRawBands; iRawBand++ )
1508 : {
1509 : HKVRasterBand *poBand;
1510 :
1511 : poBand =
1512 : new HKVRasterBand( poDS, poDS->GetRasterCount()+1, poDS->fpBlob,
1513 : nOffset, nPixelOffset, nLineOffset,
1514 91 : eType, bNative );
1515 91 : poDS->SetBand( poDS->GetRasterCount()+1, poBand );
1516 91 : nOffset += GDALGetDataTypeSize( eType ) / 8;
1517 :
1518 91 : if( bNoDataSet )
1519 0 : poBand->SetNoDataValue( dfNoDataValue );
1520 : }
1521 :
1522 41 : poDS->eRasterType = eType;
1523 :
1524 : /* -------------------------------------------------------------------- */
1525 : /* Process the georef file if there is one. */
1526 : /* -------------------------------------------------------------------- */
1527 41 : pszFilename = CPLFormFilename(poDS->pszPath, "georef", NULL );
1528 41 : if( VSIStat(pszFilename,&sStat) == 0 )
1529 16 : poDS->ProcessGeoref(pszFilename);
1530 :
1531 : /* -------------------------------------------------------------------- */
1532 : /* Initialize any PAM information. */
1533 : /* -------------------------------------------------------------------- */
1534 41 : poDS->SetDescription( pszOvrFilename );
1535 41 : poDS->TryLoadXML();
1536 :
1537 : /* -------------------------------------------------------------------- */
1538 : /* Handle overviews. */
1539 : /* -------------------------------------------------------------------- */
1540 41 : poDS->oOvManager.Initialize( poDS, pszOvrFilename, NULL, TRUE );
1541 :
1542 41 : CPLFree( pszOvrFilename );
1543 :
1544 41 : return( poDS );
1545 : }
1546 :
1547 : /************************************************************************/
1548 : /* Create() */
1549 : /************************************************************************/
1550 :
1551 53 : GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
1552 : int nXSize, int nYSize, int nBands,
1553 : GDALDataType eType,
1554 : char ** /* papszParmList */ )
1555 :
1556 : {
1557 : /* -------------------------------------------------------------------- */
1558 : /* Verify input options. */
1559 : /* -------------------------------------------------------------------- */
1560 53 : if (nBands <= 0)
1561 : {
1562 : CPLError( CE_Failure, CPLE_NotSupported,
1563 1 : "HKV driver does not support %d bands.\n", nBands);
1564 1 : return NULL;
1565 : }
1566 :
1567 52 : if( eType != GDT_Byte
1568 : && eType != GDT_UInt16 && eType != GDT_Int16
1569 : && eType != GDT_CInt16 && eType != GDT_Float32
1570 : && eType != GDT_CFloat32 )
1571 : {
1572 : CPLError( CE_Failure, CPLE_AppDefined,
1573 : "Attempt to create HKV file with currently unsupported\n"
1574 : "data type (%s).\n",
1575 15 : GDALGetDataTypeName(eType) );
1576 :
1577 15 : return NULL;
1578 : }
1579 :
1580 : /* -------------------------------------------------------------------- */
1581 : /* Establish the name of the directory we will be creating the */
1582 : /* new HKV directory in. Verify that this is a directory. */
1583 : /* -------------------------------------------------------------------- */
1584 : char *pszBaseDir;
1585 : VSIStatBuf sStat;
1586 :
1587 37 : if( strlen(CPLGetPath(pszFilenameIn)) == 0 )
1588 0 : pszBaseDir = CPLStrdup(".");
1589 : else
1590 37 : pszBaseDir = CPLStrdup(CPLGetPath(pszFilenameIn));
1591 :
1592 37 : if( CPLStat( pszBaseDir, &sStat ) != 0 || !VSI_ISDIR( sStat.st_mode ) )
1593 : {
1594 : CPLError( CE_Failure, CPLE_AppDefined,
1595 : "Attempt to create HKV dataset under %s,\n"
1596 : "but this is not a valid directory.\n",
1597 12 : pszBaseDir);
1598 12 : CPLFree( pszBaseDir );
1599 12 : return NULL;
1600 : }
1601 :
1602 25 : CPLFree( pszBaseDir );
1603 25 : pszBaseDir = NULL;
1604 :
1605 25 : if( VSIMkdir( pszFilenameIn, 0755 ) != 0 )
1606 : {
1607 : CPLError( CE_Failure, CPLE_AppDefined,
1608 : "Unable to create directory %s.\n",
1609 0 : pszFilenameIn );
1610 0 : return NULL;
1611 : }
1612 :
1613 : /* -------------------------------------------------------------------- */
1614 : /* Create the header file. */
1615 : /* -------------------------------------------------------------------- */
1616 : CPLErr CEHeaderCreated;
1617 :
1618 : CEHeaderCreated = SaveHKVAttribFile( pszFilenameIn, nXSize, nYSize,
1619 25 : nBands, eType, FALSE, 0.0 );
1620 :
1621 25 : if (CEHeaderCreated != CE_None )
1622 0 : return NULL;
1623 :
1624 : /* -------------------------------------------------------------------- */
1625 : /* Create the blob file. */
1626 : /* -------------------------------------------------------------------- */
1627 :
1628 : FILE *fp;
1629 : const char *pszFilename;
1630 :
1631 25 : pszFilename = CPLFormFilename( pszFilenameIn, "image_data", NULL );
1632 25 : fp = VSIFOpen( pszFilename, "wb" );
1633 25 : if( fp == NULL )
1634 : {
1635 : CPLError( CE_Failure, CPLE_OpenFailed,
1636 0 : "Couldn't create %s.\n", pszFilename );
1637 0 : return NULL;
1638 : }
1639 :
1640 25 : VSIFWrite( (void*)"", 1, 1, fp );
1641 25 : VSIFClose( fp );
1642 :
1643 : /* -------------------------------------------------------------------- */
1644 : /* Open the dataset normally. */
1645 : /* -------------------------------------------------------------------- */
1646 25 : return (GDALDataset *) GDALOpen( pszFilenameIn, GA_Update );
1647 : }
1648 :
1649 : /************************************************************************/
1650 : /* Delete() */
1651 : /* */
1652 : /* An HKV Blob dataset consists of a bunch of files in a */
1653 : /* directory. Try to delete all the files, then the */
1654 : /* directory. */
1655 : /************************************************************************/
1656 :
1657 0 : CPLErr HKVDataset::Delete( const char * pszName )
1658 :
1659 : {
1660 : VSIStatBuf sStat;
1661 : char **papszFiles;
1662 : int i;
1663 :
1664 0 : if( CPLStat( pszName, &sStat ) != 0
1665 : || !VSI_ISDIR(sStat.st_mode) )
1666 : {
1667 : CPLError( CE_Failure, CPLE_AppDefined,
1668 : "%s does not appear to be an HKV Dataset, as it is not\n"
1669 : "a path to a directory.",
1670 0 : pszName );
1671 0 : return CE_Failure;
1672 : }
1673 :
1674 0 : papszFiles = CPLReadDir( pszName );
1675 0 : for( i = 0; i < CSLCount(papszFiles); i++ )
1676 : {
1677 : const char *pszTarget;
1678 :
1679 0 : if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
1680 0 : continue;
1681 :
1682 0 : pszTarget = CPLFormFilename(pszName, papszFiles[i], NULL );
1683 0 : if( VSIUnlink(pszTarget) != 0 )
1684 : {
1685 : CPLError( CE_Failure, CPLE_AppDefined,
1686 : "Unable to delete file %s,\n"
1687 : "HKVDataset Delete(%s) failed.\n",
1688 : pszTarget,
1689 0 : pszName );
1690 0 : CSLDestroy( papszFiles );
1691 0 : return CE_Failure;
1692 : }
1693 : }
1694 :
1695 0 : CSLDestroy( papszFiles );
1696 :
1697 0 : if( VSIRmdir( pszName ) != 0 )
1698 : {
1699 : CPLError( CE_Failure, CPLE_AppDefined,
1700 : "Unable to delete directory %s,\n"
1701 : "HKVDataset Delete() failed.\n",
1702 0 : pszName );
1703 0 : return CE_Failure;
1704 : }
1705 :
1706 0 : return CE_None;
1707 : }
1708 :
1709 : /************************************************************************/
1710 : /* CreateCopy() */
1711 : /************************************************************************/
1712 :
1713 : GDALDataset *
1714 28 : HKVDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
1715 : int bStrict, char ** papszOptions,
1716 : GDALProgressFunc pfnProgress, void * pProgressData )
1717 :
1718 : {
1719 : HKVDataset *poDS;
1720 : GDALDataType eType;
1721 : int iBand;
1722 :
1723 28 : int nBands = poSrcDS->GetRasterCount();
1724 28 : if (nBands == 0)
1725 : {
1726 : CPLError( CE_Failure, CPLE_NotSupported,
1727 1 : "HKV driver does not support source dataset with zero band.\n");
1728 1 : return NULL;
1729 : }
1730 :
1731 27 : eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
1732 :
1733 27 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
1734 0 : return NULL;
1735 :
1736 : /* check that other bands match type- sets type */
1737 : /* to unknown if they differ. */
1738 47 : for( iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
1739 : {
1740 20 : GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
1741 20 : eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
1742 : }
1743 :
1744 : poDS = (HKVDataset *) Create( pszFilename,
1745 : poSrcDS->GetRasterXSize(),
1746 : poSrcDS->GetRasterYSize(),
1747 : poSrcDS->GetRasterCount(),
1748 27 : eType, papszOptions );
1749 :
1750 : /* Check that Create worked- return Null if it didn't */
1751 27 : if (poDS == NULL)
1752 17 : return NULL;
1753 :
1754 : /* -------------------------------------------------------------------- */
1755 : /* Copy the image data. */
1756 : /* -------------------------------------------------------------------- */
1757 10 : int nXSize = poDS->GetRasterXSize();
1758 10 : int nYSize = poDS->GetRasterYSize();
1759 : int nBlockXSize, nBlockYSize, nBlockTotal, nBlocksDone;
1760 :
1761 10 : poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
1762 :
1763 : nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
1764 : * ((nYSize + nBlockYSize - 1) / nBlockYSize)
1765 10 : * poSrcDS->GetRasterCount();
1766 :
1767 10 : nBlocksDone = 0;
1768 30 : for( iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
1769 : {
1770 20 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
1771 20 : GDALRasterBand *poDstBand = poDS->GetRasterBand( iBand+1 );
1772 : int iYOffset, iXOffset;
1773 : void *pData;
1774 : CPLErr eErr;
1775 : int pbSuccess;
1776 20 : double dfSrcNoDataValue =0.0;
1777 :
1778 : /* Get nodata value, if relevant */
1779 20 : dfSrcNoDataValue = poSrcBand->GetNoDataValue( &pbSuccess );
1780 20 : if ( pbSuccess )
1781 0 : poDS->SetNoDataValue( dfSrcNoDataValue );
1782 :
1783 : pData = CPLMalloc(nBlockXSize * nBlockYSize
1784 20 : * GDALGetDataTypeSize(eType) / 8);
1785 :
1786 220 : for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
1787 : {
1788 400 : for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
1789 : {
1790 : int nTBXSize, nTBYSize;
1791 :
1792 200 : if( !pfnProgress( (nBlocksDone++) / (float) nBlockTotal,
1793 : NULL, pProgressData ) )
1794 : {
1795 : CPLError( CE_Failure, CPLE_UserInterrupt,
1796 0 : "User terminated" );
1797 0 : delete poDS;
1798 0 : CPLFree(pData);
1799 :
1800 : GDALDriver *poHKVDriver =
1801 0 : (GDALDriver *) GDALGetDriverByName( "MFF2" );
1802 0 : poHKVDriver->Delete( pszFilename );
1803 0 : return NULL;
1804 : }
1805 :
1806 200 : nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
1807 200 : nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
1808 :
1809 : eErr = poSrcBand->RasterIO( GF_Read,
1810 : iXOffset, iYOffset,
1811 : nTBXSize, nTBYSize,
1812 : pData, nTBXSize, nTBYSize,
1813 200 : eType, 0, 0 );
1814 200 : if( eErr != CE_None )
1815 : {
1816 0 : delete poDS;
1817 0 : CPLFree(pData);
1818 0 : return NULL;
1819 : }
1820 :
1821 : eErr = poDstBand->RasterIO( GF_Write,
1822 : iXOffset, iYOffset,
1823 : nTBXSize, nTBYSize,
1824 : pData, nTBXSize, nTBYSize,
1825 200 : eType, 0, 0 );
1826 :
1827 200 : if( eErr != CE_None )
1828 : {
1829 0 : delete poDS;
1830 0 : CPLFree(pData);
1831 0 : return NULL;
1832 : }
1833 : }
1834 : }
1835 :
1836 20 : CPLFree( pData );
1837 : }
1838 :
1839 : /* -------------------------------------------------------------------- */
1840 : /* Copy georeferencing information, if enough is available. */
1841 : /* Only copy geotransform-style info (won't work for slant range). */
1842 : /* -------------------------------------------------------------------- */
1843 :
1844 10 : double *tempGeoTransform=NULL;
1845 :
1846 10 : tempGeoTransform = (double *) CPLMalloc(6*sizeof(double));
1847 :
1848 20 : if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
1849 10 : && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
1850 0 : || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
1851 0 : || tempGeoTransform[4] != 0.0 || ABS(tempGeoTransform[5]) != 1.0 ))
1852 : {
1853 :
1854 10 : poDS->SetGCPProjection(poSrcDS->GetProjectionRef());
1855 10 : poDS->SetProjection(poSrcDS->GetProjectionRef());
1856 10 : poDS->SetGeoTransform(tempGeoTransform);
1857 :
1858 10 : CPLFree(tempGeoTransform);
1859 :
1860 : /* georef file will be saved automatically when dataset is deleted */
1861 : /* because SetProjection sets a flag to indicate it's necessary. */
1862 :
1863 : }
1864 : else
1865 : {
1866 0 : CPLFree(tempGeoTransform);
1867 : }
1868 :
1869 : /* Make sure image data gets flushed */
1870 30 : for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
1871 : {
1872 20 : RawRasterBand *poDstBand = (RawRasterBand *) poDS->GetRasterBand( iBand+1 );
1873 20 : poDstBand->FlushCache();
1874 : }
1875 :
1876 :
1877 10 : if( !pfnProgress( 1.0, NULL, pProgressData ) )
1878 : {
1879 : CPLError( CE_Failure, CPLE_UserInterrupt,
1880 0 : "User terminated" );
1881 0 : delete poDS;
1882 :
1883 : GDALDriver *poHKVDriver =
1884 0 : (GDALDriver *) GDALGetDriverByName( "MFF2" );
1885 0 : poHKVDriver->Delete( pszFilename );
1886 0 : return NULL;
1887 : }
1888 :
1889 10 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
1890 :
1891 10 : return poDS;
1892 : }
1893 :
1894 :
1895 : /************************************************************************/
1896 : /* GDALRegister_HKV() */
1897 : /************************************************************************/
1898 :
1899 582 : void GDALRegister_HKV()
1900 :
1901 : {
1902 : GDALDriver *poDriver;
1903 :
1904 582 : if( GDALGetDriverByName( "MFF2" ) == NULL )
1905 : {
1906 561 : poDriver = new GDALDriver();
1907 :
1908 561 : poDriver->SetDescription( "MFF2" );
1909 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1910 561 : "Vexcel MFF2 (HKV) Raster" );
1911 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1912 561 : "frmt_mff2.html" );
1913 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1914 561 : "Byte Int16 UInt16 Int32 UInt32 CInt16 CInt32 Float32 Float64 CFloat32 CFloat64" );
1915 :
1916 561 : poDriver->pfnOpen = HKVDataset::Open;
1917 561 : poDriver->pfnCreate = HKVDataset::Create;
1918 561 : poDriver->pfnDelete = HKVDataset::Delete;
1919 561 : poDriver->pfnCreateCopy = HKVDataset::CreateCopy;
1920 :
1921 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
1922 : }
1923 582 : }
|