1 : /* TerraSAR-X COSAR Format Driver
2 : * (C)2007 Philippe P. Vachon <philippe@cowpig.ca>
3 : * ---------------------------------------------------------------------------
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the "Software"),
6 : * to deal in the Software without restriction, including without limitation
7 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : * and/or sell copies of the Software, and to permit persons to whom the
9 : * Software is furnished to do so, subject to the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included
12 : * in all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 : * DEALINGS IN THE SOFTWARE.
21 : */
22 :
23 :
24 : #include "gdal_priv.h"
25 : #include "cpl_port.h"
26 : #include "cpl_conv.h"
27 : #include "cpl_vsi.h"
28 : #include "cpl_string.h"
29 : #include <string.h>
30 :
31 : /* Various offsets, in bytes */
32 : #define BIB_OFFSET 0 /* Bytes in burst, valid only for ScanSAR */
33 : #define RSRI_OFFSET 4 /* Range Sample Relative Index */
34 : #define RS_OFFSET 8 /* Range Samples, the length of a range line */
35 : #define AS_OFFSET 12 /* Azimuth Samples, the length of an azimth column */
36 : #define BI_OFFSET 16 /* Burst Index, the index number of the burst */
37 : #define RTNB_OFFSET 20 /* Rangeline total number of bytes, incl. annot. */
38 : #define TNL_OFFSET 24 /* Total Number of Lines */
39 : #define MAGIC1_OFFSET 28 /* Magic number 1: 0x43534152 */
40 : #define MAGIC2_OFFSET 32 /* Magic number 2: Version number */
41 :
42 : #define COSAR_MAGIC 0x43534152 /* String CSAR */
43 : #define FILLER_MAGIC 0x7F7F7F7F /* Filler value, we'll use this for a test */
44 :
45 : CPL_C_START
46 : void GDALRegister_COSAR(void);
47 : CPL_C_END
48 :
49 : class COSARDataset : public GDALDataset
50 0 : {
51 : long nSize;
52 : public:
53 : FILE *fp;
54 : /* ~COSARDataset(); */
55 :
56 : static GDALDataset *Open( GDALOpenInfo * );
57 : long GetSizeInBytes() { return nSize; }
58 : };
59 :
60 : class COSARRasterBand : public GDALRasterBand
61 0 : {
62 : unsigned long nRTNB;
63 : int nBurstNumber;
64 : public:
65 : COSARRasterBand(COSARDataset *, unsigned long nRTNB);
66 : virtual CPLErr IReadBlock(int, int, void *);
67 : };
68 :
69 : /*****************************************************************************
70 : * COSARRasterBand Implementation
71 : *****************************************************************************/
72 :
73 0 : COSARRasterBand::COSARRasterBand(COSARDataset *pDS, unsigned long nRTNB) {
74 0 : this->nRTNB = nRTNB;
75 0 : nBurstNumber = 1;
76 0 : nBlockXSize = pDS->GetRasterXSize();
77 0 : nBlockYSize = 1;
78 0 : eDataType = GDT_CInt16;
79 0 : }
80 :
81 0 : CPLErr COSARRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
82 : void *pImage) {
83 :
84 0 : unsigned long nRSFV = 0;
85 0 : unsigned long nRSLV = 0;
86 0 : COSARDataset *pCDS = (COSARDataset *) poDS;
87 :
88 : /* Find the line we want to be at */
89 : /* To explain some magic numbers:
90 : * 4 bytes for an entire sample (2 I, 2 Q)
91 : * nBlockYOff + 4 = Y offset + 4 annotation lines at beginning
92 : * of file
93 : */
94 :
95 0 : VSIFSeek(pCDS->fp,(this->nRTNB * (nBlockYOff + 4)), SEEK_SET);
96 :
97 :
98 : /* Read RSFV and RSLV (TX-GS-DD-3307) */
99 0 : VSIFRead(&nRSFV,1,4,pCDS->fp);
100 0 : VSIFRead(&nRSLV,1,4,pCDS->fp);
101 :
102 : #ifdef CPL_LSB
103 0 : nRSFV = CPL_SWAP32(nRSFV);
104 0 : nRSLV = CPL_SWAP32(nRSLV);
105 : #endif
106 :
107 0 : if (nRSLV < nRSFV || nRSFV == 0
108 : || nRSFV - 1 >= ((unsigned long) nBlockXSize)
109 : || nRSLV - nRSFV > ((unsigned long) nBlockXSize)
110 : || nRSFV >= this->nRTNB || nRSLV > this->nRTNB)
111 : {
112 : /* throw an error */
113 : CPLError(CE_Failure, CPLE_AppDefined,
114 0 : "RSLV/RSFV values are not sane... oh dear.\n");
115 0 : return CE_Failure;
116 : }
117 :
118 :
119 : /* zero out the range line */
120 0 : for (int i = 0; i < this->nRasterXSize; i++)
121 : {
122 0 : ((GUInt32 *)pImage)[i] = 0;
123 : }
124 :
125 : /* properly account for validity mask */
126 0 : if (nRSFV > 1)
127 : {
128 0 : VSIFSeek(pCDS->fp,(this->nRTNB*(nBlockYOff+4)+(nRSFV+1)*4), SEEK_SET);
129 : }
130 :
131 : /* Read the valid samples: */
132 0 : VSIFRead(((char *)pImage)+((nRSFV - 1)*4),1,((nRSLV-1)*4)-((nRSFV-1)*4),pCDS->fp);
133 :
134 : #ifdef CPL_LSB
135 : // GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
136 0 : GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
137 : #endif
138 :
139 :
140 0 : return CE_None;
141 : }
142 :
143 :
144 : /*****************************************************************************
145 : * COSARDataset Implementation
146 : *****************************************************************************/
147 :
148 12398 : GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
149 : long nRTNB;
150 : /* Check if we're actually a COSAR data set. */
151 12398 : if( pOpenInfo->nHeaderBytes < 4 )
152 11493 : return NULL;
153 :
154 905 : if (!EQUALN((char *)pOpenInfo->pabyHeader+MAGIC1_OFFSET, "CSAR",4))
155 905 : return NULL;
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Confirm the requested access is supported. */
159 : /* -------------------------------------------------------------------- */
160 0 : if( pOpenInfo->eAccess == GA_Update )
161 : {
162 : CPLError( CE_Failure, CPLE_NotSupported,
163 : "The COSAR driver does not support update access to existing"
164 0 : " datasets.\n" );
165 0 : return NULL;
166 : }
167 :
168 : /* this is a cosar dataset */
169 : COSARDataset *pDS;
170 0 : pDS = new COSARDataset();
171 :
172 : /* steal fp */
173 0 : pDS->fp = pOpenInfo->fp;
174 0 : pOpenInfo->fp = NULL;
175 :
176 : /* Calculate the file size */
177 0 : VSIFSeek(pDS->fp,0,SEEK_END);
178 0 : pDS->nSize = VSIFTell(pDS->fp);
179 :
180 0 : VSIFSeek(pDS->fp, RS_OFFSET, SEEK_SET);
181 0 : VSIFRead(&pDS->nRasterXSize, 1, 4, pDS->fp);
182 : #ifdef CPL_LSB
183 0 : pDS->nRasterXSize = CPL_SWAP32(pDS->nRasterXSize);
184 : #endif
185 :
186 :
187 0 : VSIFRead(&pDS->nRasterYSize, 1, 4, pDS->fp);
188 : #ifdef CPL_LSB
189 0 : pDS->nRasterYSize = CPL_SWAP32(pDS->nRasterYSize);
190 : #endif
191 :
192 0 : VSIFSeek(pDS->fp, RTNB_OFFSET, SEEK_SET);
193 0 : VSIFRead(&nRTNB, 1, 4, pDS->fp);
194 : #ifdef CPL_LSB
195 0 : nRTNB = CPL_SWAP32(nRTNB);
196 : #endif
197 :
198 : /* Add raster band */
199 0 : pDS->SetBand(1, new COSARRasterBand(pDS, nRTNB));
200 0 : return pDS;
201 : }
202 :
203 :
204 : /* register the driver with GDAL */
205 582 : void GDALRegister_COSAR() {
206 : GDALDriver *pDriver;
207 582 : if (GDALGetDriverByName("cosar") == NULL) {
208 561 : pDriver = new GDALDriver();
209 561 : pDriver->SetDescription("COSAR");
210 : pDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
211 561 : "COSAR Annotated Binary Matrix (TerraSAR-X)");
212 : pDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
213 561 : "frmt_cosar.html");
214 561 : pDriver->pfnOpen = COSARDataset::Open;
215 561 : GetGDALDriverManager()->RegisterDriver(pDriver);
216 : }
217 582 : }
218 :
|