1 /******************************************************************************
2  *
3  * Project:  CEOS Translator
4  * Purpose:  GDALDataset driver for CEOS translator.
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 1999, Frank Warmerdam
9  * Copyright (c) 2009-2010, 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 "ceosopen.h"
31 #include "gdal_frmts.h"
32 #include "gdal_pam.h"
33 
34 CPL_CVSID("$Id: ceosdataset.cpp f6099e5ed704166bf5cc113a053dd1b2725cb391 2020-03-22 11:20:10 +0100 Kai Pastor $")
35 
36 /************************************************************************/
37 /* ==================================================================== */
38 /*                              CEOSDataset                             */
39 /* ==================================================================== */
40 /************************************************************************/
41 
42 class CEOSRasterBand;
43 
44 class CEOSDataset final: public GDALPamDataset
45 {
46     friend class CEOSRasterBand;
47 
48     CEOSImage   *psCEOS;
49 
50   public:
51                  CEOSDataset();
52                 ~CEOSDataset();
53     static GDALDataset *Open( GDALOpenInfo * );
54 };
55 
56 /************************************************************************/
57 /* ==================================================================== */
58 /*                            CEOSRasterBand                             */
59 /* ==================================================================== */
60 /************************************************************************/
61 
62 class CEOSRasterBand final: public GDALPamRasterBand
63 {
64     friend class CEOSDataset;
65 
66   public:
67     CEOSRasterBand( CEOSDataset *, int );
68 
69     CPLErr IReadBlock( int, int, void * ) override;
70 };
71 
72 /************************************************************************/
73 /*                           CEOSRasterBand()                            */
74 /************************************************************************/
75 
CEOSRasterBand(CEOSDataset * poDSIn,int nBandIn)76 CEOSRasterBand::CEOSRasterBand( CEOSDataset *poDSIn, int nBandIn )
77 
78 {
79     poDS = poDSIn;
80     nBand = nBandIn;
81 
82     eDataType = GDT_Byte;
83 
84     nBlockXSize = poDS->GetRasterXSize();
85     nBlockYSize = 1;
86 }
87 
88 /************************************************************************/
89 /*                             IReadBlock()                             */
90 /************************************************************************/
91 
IReadBlock(CPL_UNUSED int nBlockXOff,int nBlockYOff,void * pImage)92 CPLErr CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
93                                    int nBlockYOff,
94                                    void * pImage )
95 {
96     CEOSDataset *poCEOS_DS = (CEOSDataset *) poDS;
97 
98     CPLAssert( nBlockXOff == 0 );
99 
100     return CEOSReadScanline(poCEOS_DS->psCEOS, nBand, nBlockYOff+1, pImage);
101 }
102 
103 /************************************************************************/
104 /* ==================================================================== */
105 /*                             CEOSDataset                              */
106 /* ==================================================================== */
107 /************************************************************************/
108 
109 /************************************************************************/
110 /*                            CEOSDataset()                             */
111 /************************************************************************/
112 
CEOSDataset()113 CEOSDataset::CEOSDataset() :
114     psCEOS(nullptr)
115 {}
116 
117 /************************************************************************/
118 /*                            ~CEOSDataset()                            */
119 /************************************************************************/
120 
~CEOSDataset()121 CEOSDataset::~CEOSDataset()
122 
123 {
124     FlushCache();
125     if( psCEOS )
126         CEOSClose( psCEOS );
127 }
128 
129 /************************************************************************/
130 /*                                Open()                                */
131 /************************************************************************/
132 
Open(GDALOpenInfo * poOpenInfo)133 GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
134 
135 {
136 /* -------------------------------------------------------------------- */
137 /*      Before trying CEOSOpen() we first verify that the first         */
138 /*      record is in fact a CEOS file descriptor record.                */
139 /* -------------------------------------------------------------------- */
140     if( poOpenInfo->nHeaderBytes < 100 )
141         return nullptr;
142 
143     if( poOpenInfo->pabyHeader[4] != 0x3f
144         || poOpenInfo->pabyHeader[5] != 0xc0
145         || poOpenInfo->pabyHeader[6] != 0x12
146         || poOpenInfo->pabyHeader[7] != 0x12 )
147         return nullptr;
148 
149 /* -------------------------------------------------------------------- */
150 /*      Try opening the dataset.                                        */
151 /* -------------------------------------------------------------------- */
152     CEOSImage *psCEOS = CEOSOpen( poOpenInfo->pszFilename, "rb" );
153     if( psCEOS == nullptr )
154         return nullptr;
155 
156     if( psCEOS->nBitsPerPixel != 8 )
157     {
158         CPLError( CE_Failure, CPLE_NotSupported,
159                   "The CEOS driver cannot handle nBitsPerPixel = %d",
160                   psCEOS->nBitsPerPixel );
161         CEOSClose(psCEOS);
162         return nullptr;
163     }
164 
165     if( !GDALCheckDatasetDimensions(psCEOS->nPixels, psCEOS->nBands) ||
166         !GDALCheckBandCount(psCEOS->nBands, FALSE) )
167     {
168         CEOSClose( psCEOS );
169         return nullptr;
170     }
171 
172 /* -------------------------------------------------------------------- */
173 /*      Confirm the requested access is supported.                      */
174 /* -------------------------------------------------------------------- */
175     if( poOpenInfo->eAccess == GA_Update )
176     {
177         CEOSClose(psCEOS);
178         CPLError( CE_Failure, CPLE_NotSupported,
179                   "The CEOS driver does not support update access to existing"
180                   " datasets.\n" );
181         return nullptr;
182     }
183 /* -------------------------------------------------------------------- */
184 /*      Create a corresponding GDALDataset.                             */
185 /* -------------------------------------------------------------------- */
186     CEOSDataset *poDS = new CEOSDataset();
187 
188     poDS->psCEOS = psCEOS;
189 
190 /* -------------------------------------------------------------------- */
191 /*      Capture some information from the file that is of interest.     */
192 /* -------------------------------------------------------------------- */
193     poDS->nRasterXSize = psCEOS->nPixels;
194     poDS->nRasterYSize = psCEOS->nLines;
195 
196 /* -------------------------------------------------------------------- */
197 /*      Create band information objects.                                */
198 /* -------------------------------------------------------------------- */
199     poDS->nBands = psCEOS->nBands;
200 
201     for( int i = 0; i < poDS->nBands; i++ )
202         poDS->SetBand( i+1, new CEOSRasterBand( poDS, i+1 ) );
203 
204 /* -------------------------------------------------------------------- */
205 /*      Initialize any PAM information.                                 */
206 /* -------------------------------------------------------------------- */
207     poDS->SetDescription( poOpenInfo->pszFilename );
208     poDS->TryLoadXML();
209 
210 /* -------------------------------------------------------------------- */
211 /*      Check for overviews.                                            */
212 /* -------------------------------------------------------------------- */
213     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
214 
215     return poDS;
216 }
217 
218 /************************************************************************/
219 /*                          GDALRegister_GTiff()                        */
220 /************************************************************************/
221 
GDALRegister_CEOS()222 void GDALRegister_CEOS()
223 
224 {
225     if( GDALGetDriverByName( "CEOS" ) != nullptr )
226         return;
227 
228     GDALDriver *poDriver = new GDALDriver();
229 
230     poDriver->SetDescription( "CEOS" );
231     poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
232     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
233                                "CEOS Image" );
234     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
235                                "drivers/raster/ceos.html" );
236     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
237 
238     poDriver->pfnOpen = CEOSDataset::Open;
239 
240     GetGDALDriverManager()->RegisterDriver( poDriver );
241 }
242