Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GSC Geogrid format driver.
4 : * Purpose: Implements support for reading and writing GSC Geogrid format.
5 : * Author: Frank Warmerdam <warmerdam@pobox.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2009-2011, Even Rouault <even dot rouault at spatialys.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 "cpl_string.h"
31 : #include "gdal_frmts.h"
32 : #include "rawdataset.h"
33 :
34 : #include <algorithm>
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* GSCDataset */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : class GSCDataset final : public RawDataset
43 : {
44 : VSILFILE *fpImage; // image data file.
45 :
46 : double adfGeoTransform[6];
47 :
48 : CPL_DISALLOW_COPY_ASSIGN(GSCDataset)
49 :
50 : CPLErr Close() override;
51 :
52 : public:
53 : GSCDataset();
54 : ~GSCDataset();
55 :
56 : CPLErr GetGeoTransform(double *padfTransform) override;
57 :
58 : static GDALDataset *Open(GDALOpenInfo *);
59 : };
60 :
61 : /************************************************************************/
62 : /* GSCDataset() */
63 : /************************************************************************/
64 :
65 2 : GSCDataset::GSCDataset() : fpImage(nullptr)
66 : {
67 2 : adfGeoTransform[0] = 0.0;
68 2 : adfGeoTransform[1] = 1.0;
69 2 : adfGeoTransform[2] = 0.0;
70 2 : adfGeoTransform[3] = 0.0;
71 2 : adfGeoTransform[4] = 0.0;
72 2 : adfGeoTransform[5] = 1.0;
73 2 : }
74 :
75 : /************************************************************************/
76 : /* ~GSCDataset() */
77 : /************************************************************************/
78 :
79 4 : GSCDataset::~GSCDataset()
80 :
81 : {
82 2 : GSCDataset::Close();
83 4 : }
84 :
85 : /************************************************************************/
86 : /* Close() */
87 : /************************************************************************/
88 :
89 4 : CPLErr GSCDataset::Close()
90 : {
91 4 : CPLErr eErr = CE_None;
92 4 : if (nOpenFlags != OPEN_FLAGS_CLOSED)
93 : {
94 2 : if (GSCDataset::FlushCache(true) != CE_None)
95 0 : eErr = CE_Failure;
96 :
97 2 : if (fpImage)
98 : {
99 2 : if (VSIFCloseL(fpImage) != 0)
100 : {
101 0 : CPLError(CE_Failure, CPLE_FileIO, "I/O error");
102 0 : eErr = CE_Failure;
103 : }
104 : }
105 :
106 2 : if (GDALPamDataset::Close() != CE_None)
107 0 : eErr = CE_Failure;
108 : }
109 4 : return eErr;
110 : }
111 :
112 : /************************************************************************/
113 : /* GetGeoTransform() */
114 : /************************************************************************/
115 :
116 0 : CPLErr GSCDataset::GetGeoTransform(double *padfTransform)
117 :
118 : {
119 0 : memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
120 :
121 0 : return CE_None;
122 : }
123 :
124 : /************************************************************************/
125 : /* Open() */
126 : /************************************************************************/
127 :
128 29191 : GDALDataset *GSCDataset::Open(GDALOpenInfo *poOpenInfo)
129 :
130 : {
131 :
132 : /* -------------------------------------------------------------------- */
133 : /* Does this plausible look like a GSC Geogrid file? */
134 : /* -------------------------------------------------------------------- */
135 29191 : if (poOpenInfo->nHeaderBytes < 20)
136 25994 : return nullptr;
137 :
138 3197 : if (poOpenInfo->pabyHeader[12] != 0x02 ||
139 21 : poOpenInfo->pabyHeader[13] != 0x00 ||
140 3 : poOpenInfo->pabyHeader[14] != 0x00 ||
141 3 : poOpenInfo->pabyHeader[15] != 0x00)
142 3195 : return nullptr;
143 :
144 2 : int nRecordLen =
145 2 : CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[0]);
146 2 : const int nPixels =
147 2 : CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[1]);
148 2 : const int nLines =
149 2 : CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[2]);
150 :
151 2 : if (nPixels < 1 || nLines < 1 || nPixels > 100000 || nLines > 100000)
152 0 : return nullptr;
153 :
154 2 : if (nRecordLen != nPixels * 4)
155 0 : return nullptr;
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Confirm the requested access is supported. */
159 : /* -------------------------------------------------------------------- */
160 2 : if (poOpenInfo->eAccess == GA_Update)
161 : {
162 0 : CPLError(CE_Failure, CPLE_NotSupported,
163 : "The GSC driver does not support update access to existing "
164 : "datasets.");
165 0 : return nullptr;
166 : }
167 :
168 2 : nRecordLen += 8; // For record length markers.
169 :
170 : /* -------------------------------------------------------------------- */
171 : /* Create a corresponding GDALDataset. */
172 : /* -------------------------------------------------------------------- */
173 4 : auto poDS = std::make_unique<GSCDataset>();
174 :
175 2 : poDS->nRasterXSize = nPixels;
176 2 : poDS->nRasterYSize = nLines;
177 2 : std::swap(poDS->fpImage, poOpenInfo->fpL);
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Read the header information in the second record. */
181 : /* -------------------------------------------------------------------- */
182 2 : float afHeaderInfo[8] = {0.0};
183 :
184 4 : if (VSIFSeekL(poDS->fpImage, nRecordLen + 12, SEEK_SET) != 0 ||
185 2 : VSIFReadL(afHeaderInfo, sizeof(float), 8, poDS->fpImage) != 8)
186 : {
187 0 : CPLError(
188 : CE_Failure, CPLE_FileIO,
189 : "Failure reading second record of GSC file with %d record length.",
190 : nRecordLen);
191 0 : return nullptr;
192 : }
193 :
194 18 : for (int i = 0; i < 8; i++)
195 : {
196 16 : CPL_LSBPTR32(afHeaderInfo + i);
197 : }
198 :
199 2 : poDS->adfGeoTransform[0] = afHeaderInfo[2];
200 2 : poDS->adfGeoTransform[1] = afHeaderInfo[0];
201 2 : poDS->adfGeoTransform[2] = 0.0;
202 2 : poDS->adfGeoTransform[3] = afHeaderInfo[5];
203 2 : poDS->adfGeoTransform[4] = 0.0;
204 2 : poDS->adfGeoTransform[5] = -afHeaderInfo[1];
205 :
206 : /* -------------------------------------------------------------------- */
207 : /* Create band information objects. */
208 : /* -------------------------------------------------------------------- */
209 : auto poBand = RawRasterBand::Create(
210 4 : poDS.get(), 1, poDS->fpImage, nRecordLen * 2 + 4, sizeof(float),
211 : nRecordLen, GDT_Float32, RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN,
212 4 : RawRasterBand::OwnFP::NO);
213 2 : if (!poBand)
214 0 : return nullptr;
215 2 : poBand->SetNoDataValue(-1.0000000150474662199e+30);
216 2 : poDS->SetBand(1, std::move(poBand));
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Initialize any PAM information. */
220 : /* -------------------------------------------------------------------- */
221 2 : poDS->SetDescription(poOpenInfo->pszFilename);
222 2 : poDS->TryLoadXML();
223 :
224 : /* -------------------------------------------------------------------- */
225 : /* Check for overviews. */
226 : /* -------------------------------------------------------------------- */
227 2 : poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
228 :
229 2 : return poDS.release();
230 : }
231 :
232 : /************************************************************************/
233 : /* GDALRegister_GSC() */
234 : /************************************************************************/
235 :
236 1511 : void GDALRegister_GSC()
237 :
238 : {
239 1511 : if (GDALGetDriverByName("GSC") != nullptr)
240 295 : return;
241 :
242 1216 : GDALDriver *poDriver = new GDALDriver();
243 :
244 1216 : poDriver->SetDescription("GSC");
245 1216 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
246 1216 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GSC Geogrid");
247 1216 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gsc.html");
248 1216 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
249 :
250 1216 : poDriver->pfnOpen = GSCDataset::Open;
251 :
252 1216 : GetGDALDriverManager()->RegisterDriver(poDriver);
253 : }
|