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 nRSLength;
64 : int nBurstNumber;
65 : public:
66 : COSARRasterBand(COSARDataset *, unsigned long nRTNB);
67 : virtual CPLErr IReadBlock(int, int, void *);
68 : };
69 :
70 : /*****************************************************************************
71 : * COSARRasterBand Implementation
72 : *****************************************************************************/
73 :
74 0 : COSARRasterBand::COSARRasterBand(COSARDataset *pDS, unsigned long nRTNB) {
75 0 : this->nRTNB = nRTNB;
76 0 : this->nRSLength = nRSLength;
77 0 : nBurstNumber = 1;
78 0 : nBlockXSize = pDS->GetRasterXSize();
79 0 : nBlockYSize = 1;
80 0 : eDataType = GDT_CInt16;
81 0 : }
82 :
83 0 : CPLErr COSARRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
84 : void *pImage) {
85 :
86 0 : unsigned long nRSFV = 0;
87 0 : unsigned long nRSLV = 0;
88 0 : COSARDataset *pCDS = (COSARDataset *) poDS;
89 :
90 : /* Find the line we want to be at */
91 : /* To explain some magic numbers:
92 : * 4 bytes for an entire sample (2 I, 2 Q)
93 : * nBlockYOff + 4 = Y offset + 4 annotation lines at beginning
94 : * of file
95 : */
96 :
97 0 : VSIFSeek(pCDS->fp,(this->nRTNB * (nBlockYOff + 4)), SEEK_SET);
98 :
99 :
100 : /* Read RSFV and RSLV (TX-GS-DD-3307) */
101 0 : VSIFRead(&nRSFV,1,4,pCDS->fp);
102 0 : VSIFRead(&nRSLV,1,4,pCDS->fp);
103 :
104 : #ifdef CPL_LSB
105 0 : nRSFV = CPL_SWAP32(nRSFV);
106 0 : nRSLV = CPL_SWAP32(nRSLV);
107 : #endif
108 :
109 0 : if (nRSLV < nRSFV || nRSFV == 0
110 : || nRSFV - 1 >= ((unsigned long) nBlockXSize)
111 : || nRSLV - nRSFV > ((unsigned long) nBlockXSize)
112 : || nRSFV >= this->nRTNB || nRSLV > this->nRTNB)
113 : {
114 : /* throw an error */
115 : CPLError(CE_Failure, CPLE_AppDefined,
116 0 : "RSLV/RSFV values are not sane... oh dear.\n");
117 0 : return CE_Failure;
118 : }
119 :
120 :
121 : /* zero out the range line */
122 0 : for (int i = 0; i < this->nRasterXSize; i++)
123 : {
124 0 : ((GUInt32 *)pImage)[i] = 0;
125 : }
126 :
127 : /* properly account for validity mask */
128 0 : if (nRSFV > 1)
129 : {
130 0 : VSIFSeek(pCDS->fp,(this->nRTNB*(nBlockYOff+4)+(nRSFV+1)*4), SEEK_SET);
131 : }
132 :
133 : /* Read the valid samples: */
134 0 : VSIFRead(((char *)pImage)+((nRSFV - 1)*4),1,((nRSLV-1)*4)-((nRSFV-1)*4),pCDS->fp);
135 :
136 : #ifdef CPL_LSB
137 : // GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
138 0 : GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
139 : #endif
140 :
141 :
142 0 : return CE_None;
143 : }
144 :
145 :
146 : /*****************************************************************************
147 : * COSARDataset Implementation
148 : *****************************************************************************/
149 :
150 8784 : GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
151 : long nRTNB;
152 : /* Check if we're actually a COSAR data set. */
153 8784 : if( pOpenInfo->nHeaderBytes < 4 )
154 8381 : return NULL;
155 :
156 403 : if (!EQUALN((char *)pOpenInfo->pabyHeader+MAGIC1_OFFSET, "CSAR",4))
157 403 : return NULL;
158 :
159 : /* -------------------------------------------------------------------- */
160 : /* Confirm the requested access is supported. */
161 : /* -------------------------------------------------------------------- */
162 0 : if( pOpenInfo->eAccess == GA_Update )
163 : {
164 : CPLError( CE_Failure, CPLE_NotSupported,
165 : "The COSAR driver does not support update access to existing"
166 0 : " datasets.\n" );
167 0 : return NULL;
168 : }
169 :
170 : /* this is a cosar dataset */
171 : COSARDataset *pDS;
172 0 : pDS = new COSARDataset();
173 :
174 : /* steal fp */
175 0 : pDS->fp = pOpenInfo->fp;
176 0 : pOpenInfo->fp = NULL;
177 :
178 : /* Calculate the file size */
179 0 : VSIFSeek(pDS->fp,0,SEEK_END);
180 0 : pDS->nSize = VSIFTell(pDS->fp);
181 :
182 0 : VSIFSeek(pDS->fp, RS_OFFSET, SEEK_SET);
183 0 : VSIFRead(&pDS->nRasterXSize, 1, 4, pDS->fp);
184 : #ifdef CPL_LSB
185 0 : pDS->nRasterXSize = CPL_SWAP32(pDS->nRasterXSize);
186 : #endif
187 :
188 :
189 0 : VSIFRead(&pDS->nRasterYSize, 1, 4, pDS->fp);
190 : #ifdef CPL_LSB
191 0 : pDS->nRasterYSize = CPL_SWAP32(pDS->nRasterYSize);
192 : #endif
193 :
194 0 : VSIFSeek(pDS->fp, RTNB_OFFSET, SEEK_SET);
195 0 : VSIFRead(&nRTNB, 1, 4, pDS->fp);
196 : #ifdef CPL_LSB
197 0 : nRTNB = CPL_SWAP32(nRTNB);
198 : #endif
199 :
200 : /* Add raster band */
201 0 : pDS->SetBand(1, new COSARRasterBand(pDS, nRTNB));
202 0 : return pDS;
203 : }
204 :
205 :
206 : /* register the driver with GDAL */
207 338 : void GDALRegister_COSAR() {
208 : GDALDriver *pDriver;
209 338 : if (GDALGetDriverByName("cosar") == NULL) {
210 336 : pDriver = new GDALDriver();
211 336 : pDriver->SetDescription("COSAR");
212 : pDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
213 336 : "COSAR Annotated Binary Matrix (TerraSAR-X)");
214 : pDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
215 336 : "frmt_cosar.html");
216 336 : pDriver->pfnOpen = COSARDataset::Open;
217 336 : GetGDALDriverManager()->RegisterDriver(pDriver);
218 : }
219 338 : }
220 :
|