Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: ASI CEOS Translator
5 : * Purpose: CEOS field layout recipes.
6 : * Author: Paul Lahaie, pjlahaie@atlsci.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, Atlantis Scientific Inc
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 "ceos.h"
31 :
32 : /* Array of Datatypes and their names/values */
33 :
34 : typedef struct
35 : {
36 : const char *String;
37 : int Type;
38 : } CeosStringType_t;
39 :
40 : typedef struct
41 : {
42 : int (*function)(CeosSARVolume_t *volume, const void *token);
43 : const void *token;
44 : const char *name;
45 : } RecipeFunctionData_t;
46 :
47 : static const CeosStringType_t CeosDataType[] = {
48 : {"IU1", CEOS_TYP_UCHAR},
49 : {"IU2", CEOS_TYP_USHORT},
50 : {"UI1", CEOS_TYP_UCHAR},
51 : {"UI2", CEOS_TYP_USHORT},
52 : {"CI*2", CEOS_TYP_COMPLEX_CHAR},
53 : {"CI*4", CEOS_TYP_COMPLEX_SHORT},
54 : {"CIS4", CEOS_TYP_COMPLEX_SHORT},
55 : {"CI*8", CEOS_TYP_COMPLEX_LONG},
56 : {"C*8", CEOS_TYP_COMPLEX_FLOAT},
57 : {"R*4", CEOS_TYP_FLOAT},
58 : {NULL, 0}};
59 :
60 : static const CeosStringType_t CeosInterleaveType[] = {{"BSQ", CEOS_IL_BAND},
61 : {" BSQ", CEOS_IL_BAND},
62 : {"BIL", CEOS_IL_LINE},
63 : {" BIL", CEOS_IL_LINE},
64 : {NULL, 0}};
65 :
66 : #define IMAGE_OPT \
67 : { \
68 : 63, 192, 18, 18 \
69 : }
70 : #define IMAGE_JERS_OPT \
71 : { \
72 : 50, 192, 18, 18 \
73 : } /* Some JERS data uses this instead of IMAGE_OPT */
74 : #define PROC_DATA_REC \
75 : { \
76 : 50, 11, 18, 20 \
77 : }
78 : #define PROC_DATA_REC_ALT \
79 : { \
80 : 50, 11, 31, 20 \
81 : }
82 : #define PROC_DATA_REC_ALT2 \
83 : { \
84 : 50, 11, 31, 50 \
85 : } /* Some cases of ERS 1, 2 */
86 : #define DATA_SET_SUMMARY \
87 : { \
88 : 18, 10, 18, 20 \
89 : }
90 :
91 : /* NOTE: This seems to be the generic recipe used for most things */
92 : static const CeosRecipeType_t RadarSatRecipe[] = {
93 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
94 : CEOS_REC_TYP_I}, /* Number of channels */
95 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
96 : CEOS_REC_TYP_A}, /* Interleaving type */
97 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
98 : CEOS_REC_TYP_A}, /* Data type */
99 : {CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
100 : CEOS_REC_TYP_A}, /* For Defeault CEOS, this is done using other vals */
101 : {CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 237, 8,
102 : CEOS_REC_TYP_I}, /* How many lines */
103 : {CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 261, 4, CEOS_REC_TYP_I},
104 : {CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 265, 4,
105 : CEOS_REC_TYP_I}, /* Bottom border pixels */
106 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
107 : CEOS_REC_TYP_I}, /* Pixels per line */
108 : {CEOS_REC_LBP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 245, 4,
109 : CEOS_REC_TYP_I}, /* Left Border Pixels */
110 : {CEOS_REC_RBP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 257, 4,
111 : CEOS_REC_TYP_I}, /* Right Border Pixels */
112 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
113 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
114 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
115 : CEOS_REC_TYP_I}, /* Records per line */
116 : {CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
117 : CEOS_REC_TYP_I}, /* Pixels Per Record -- need to fill record type */
118 : {CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 281, 8,
119 : CEOS_REC_TYP_I}, /* pixel data bytes per record */
120 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
121 : CEOS_REC_TYP_I}, /* Prefix data per record */
122 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
123 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
124 : {CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
125 : CEOS_REC_TYP_I}, /* Must be calculated */
126 : {CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
127 : CEOS_REC_TYP_I}, /* Must be calculated */
128 : {CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
129 : CEOS_REC_TYP_I},
130 :
131 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
132 : CEOS_REC_TYP_B}, /* The processed image record size */
133 :
134 : /* Some ERS-1 products use an alternate data record subtype2. */
135 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT, 9, 4,
136 : CEOS_REC_TYP_B}, /* The processed image record size */
137 :
138 : /* Yet another ERS-1 and ERS-2 alternate data record subtype2. */
139 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT2, 9, 4,
140 : CEOS_REC_TYP_B}, /* The processed image record size */
141 :
142 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
143 : CEOS_REC_TYP_I}, /* Suffix data per record */
144 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
145 : };
146 :
147 : static const CeosRecipeType_t JersRecipe[] = {
148 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 233, 4,
149 : CEOS_REC_TYP_I}, /* Number of channels */
150 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 269, 4,
151 : CEOS_REC_TYP_A}, /* Interleaving type */
152 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 429, 4,
153 : CEOS_REC_TYP_A}, /* Data type */
154 : {CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
155 : CEOS_REC_TYP_A}, /* For Defeault CEOS, this is done using other vals */
156 : {CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 237, 8,
157 : CEOS_REC_TYP_I}, /* How many lines */
158 : {CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 261, 4,
159 : CEOS_REC_TYP_I},
160 : {CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 265, 4,
161 : CEOS_REC_TYP_I}, /* Bottom border pixels */
162 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 249, 8,
163 : CEOS_REC_TYP_I}, /* Pixels per line */
164 : {CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 245, 4,
165 : CEOS_REC_TYP_I}, /* Left Border Pixels */
166 : {CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 257, 4,
167 : CEOS_REC_TYP_I}, /* Isn't available for RadarSAT */
168 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 225, 4,
169 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
170 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 273, 2,
171 : CEOS_REC_TYP_I}, /* Records per line */
172 : {CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
173 : CEOS_REC_TYP_I}, /* Pixels Per Record -- need to fill record type */
174 : {CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 281, 8,
175 : CEOS_REC_TYP_I}, /* pixel data bytes per record */
176 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 277, 4,
177 : CEOS_REC_TYP_I}, /* Prefix data per record */
178 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 9, 4,
179 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
180 : {CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
181 : CEOS_REC_TYP_I}, /* Must be calculated */
182 : {CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
183 : CEOS_REC_TYP_I}, /* Must be calculated */
184 : {CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
185 : CEOS_REC_TYP_I},
186 :
187 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
188 : CEOS_REC_TYP_B}, /* The processed image record size */
189 :
190 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 289, 4,
191 : CEOS_REC_TYP_I}, /* Suffix data per record */
192 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
193 : };
194 :
195 : static const CeosRecipeType_t ScanSARRecipe[] = {
196 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
197 : CEOS_REC_TYP_I}, /* Number of channels */
198 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
199 : CEOS_REC_TYP_A}, /* Interleaving type */
200 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
201 : CEOS_REC_TYP_A}, /* Data type */
202 : {CEOS_REC_LINES, 1, CEOS_ANY_FILE, DATA_SET_SUMMARY, 325, 8,
203 : CEOS_REC_TYP_I}, /* How many lines */
204 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
205 : CEOS_REC_TYP_I}, /* Pixels per line */
206 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
207 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
208 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
209 : CEOS_REC_TYP_I}, /* Records per line */
210 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
211 : CEOS_REC_TYP_I}, /* Prefix data per record */
212 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
213 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
214 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
215 : CEOS_REC_TYP_B}, /* The processed image record size */
216 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
217 : CEOS_REC_TYP_I}, /* Suffix data per record */
218 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
219 : };
220 :
221 : static const CeosRecipeType_t SIRCRecipe[] = {
222 : {CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
223 : CEOS_REC_TYP_I}, /* Number of channels */
224 : {CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
225 : CEOS_REC_TYP_A}, /* Interleaving type */
226 : {CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
227 : CEOS_REC_TYP_A}, /* Data type */
228 : {CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 237, 8,
229 : CEOS_REC_TYP_I}, /* How many lines */
230 : {CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 261, 4, CEOS_REC_TYP_I},
231 : {CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 265, 4,
232 : CEOS_REC_TYP_I}, /* Bottom border pixels */
233 : {CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
234 : CEOS_REC_TYP_I}, /* Pixels per line */
235 : {CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 245, 4,
236 : CEOS_REC_TYP_I}, /* Left Border Pixels */
237 : {CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 257, 4,
238 : CEOS_REC_TYP_I}, /* Right Border Pixels */
239 : {CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
240 : CEOS_REC_TYP_I}, /* Bytes Per Pixel */
241 : {CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
242 : CEOS_REC_TYP_I}, /* Records per line */
243 : {CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
244 : CEOS_REC_TYP_I}, /* Prefix data per record */
245 : {CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
246 : CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
247 : {CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
248 : CEOS_REC_TYP_B}, /* The processed image record size */
249 : {CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
250 : CEOS_REC_TYP_I}, /* Suffix data per record */
251 :
252 : {0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
253 : };
254 :
255 : #undef PROC_DATA_REC
256 :
257 : static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
258 : unsigned int length, int *value);
259 :
260 : static char *ExtractString(CeosRecord_t *record, unsigned int offset,
261 : unsigned int length, char *string);
262 :
263 : static int GetCeosStringType(const CeosStringType_t *CeosType,
264 : const char *string);
265 :
266 : static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token);
267 : static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token);
268 :
269 : Link_t *RecipeFunctions = NULL;
270 :
271 2 : void RegisterRecipes(void)
272 : {
273 :
274 2 : AddRecipe(SIRCRecipeFCN, SIRCRecipe, "SIR-C");
275 2 : AddRecipe(ScanSARRecipeFCN, ScanSARRecipe, "ScanSAR");
276 2 : AddRecipe(CeosDefaultRecipe, RadarSatRecipe, "RadarSat");
277 2 : AddRecipe(CeosDefaultRecipe, JersRecipe, "Jers");
278 2 : AddRecipe(PALSARRecipeFCN, RadarSatRecipe, "PALSAR-ALOS");
279 : /* AddRecipe( CeosDefaultRecipe, AtlantisRecipe ); */
280 2 : }
281 :
282 4 : void FreeRecipes(void)
283 :
284 : {
285 : Link_t *l_link;
286 :
287 14 : for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
288 10 : HFree(l_link->object);
289 :
290 4 : DestroyList(RecipeFunctions);
291 4 : RecipeFunctions = NULL;
292 4 : }
293 :
294 10 : void AddRecipe(int (*function)(CeosSARVolume_t *volume, const void *token),
295 : const void *token, const char *name)
296 : {
297 :
298 : RecipeFunctionData_t *TempData;
299 :
300 : Link_t *Link;
301 :
302 10 : TempData = HMalloc(sizeof(RecipeFunctionData_t));
303 :
304 10 : TempData->function = function;
305 10 : TempData->token = token;
306 10 : TempData->name = name;
307 :
308 10 : Link = ceos2CreateLink(TempData);
309 :
310 10 : if (RecipeFunctions == NULL)
311 : {
312 2 : RecipeFunctions = Link;
313 : }
314 : else
315 : {
316 8 : RecipeFunctions = InsertLink(RecipeFunctions, Link);
317 : }
318 10 : }
319 :
320 8 : int CeosDefaultRecipe(CeosSARVolume_t *volume, const void *token)
321 : {
322 : const CeosRecipeType_t *recipe;
323 : CeosRecord_t *record;
324 8 : CeosTypeCode_t TypeCode = {0};
325 8 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
326 : char temp_str[1024];
327 : int i /*, temp_int */;
328 :
329 : #define DoExtractInt(a) \
330 : ExtractInt(record, recipe[i].Type, recipe[i].Offset, recipe[i].Length, &a)
331 :
332 8 : if (token == NULL)
333 : {
334 0 : return 0;
335 : }
336 :
337 8 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
338 :
339 : /* temp_imagerecipe = (CeosSARImageDescRecipe_t *) token;
340 : recipe = temp_imagerecipe->Recipe; */
341 :
342 8 : recipe = token;
343 :
344 184 : for (i = 0; recipe[i].ImageDescValue != 0; i++)
345 : {
346 176 : if (recipe[i].Override)
347 : {
348 112 : TypeCode.UCharCode.Subtype1 = recipe[i].TypeCode.Subtype1;
349 112 : TypeCode.UCharCode.Type = recipe[i].TypeCode.Type;
350 112 : TypeCode.UCharCode.Subtype2 = recipe[i].TypeCode.Subtype2;
351 112 : TypeCode.UCharCode.Subtype3 = recipe[i].TypeCode.Subtype3;
352 :
353 112 : record = FindCeosRecord(volume->RecordList, TypeCode,
354 112 : recipe[i].FileId, -1, -1);
355 :
356 112 : if (record == NULL)
357 : {
358 : /* temp_int = 0; */
359 : }
360 : else
361 : {
362 :
363 60 : switch (recipe[i].ImageDescValue)
364 : {
365 4 : case CEOS_REC_NUMCHANS:
366 4 : DoExtractInt(ImageDesc->NumChannels);
367 4 : break;
368 4 : case CEOS_REC_LINES:
369 4 : DoExtractInt(ImageDesc->Lines);
370 4 : break;
371 4 : case CEOS_REC_BPP:
372 4 : DoExtractInt(ImageDesc->BytesPerPixel);
373 4 : break;
374 4 : case CEOS_REC_RPL:
375 4 : DoExtractInt(ImageDesc->RecordsPerLine);
376 4 : break;
377 4 : case CEOS_REC_PDBPR:
378 4 : DoExtractInt(ImageDesc->PixelDataBytesPerRecord);
379 4 : break;
380 4 : case CEOS_REC_FDL:
381 4 : DoExtractInt(ImageDesc->FileDescriptorLength);
382 4 : break;
383 4 : case CEOS_REC_IDS:
384 4 : DoExtractInt(ImageDesc->ImageDataStart);
385 : /*
386 : ** This is really reading the quantity of prefix data
387 : ** per data record. We want the offset from the very
388 : ** beginning of the record to the data, so we add
389 : *another
390 : ** 12 to that. I think some products incorrectly
391 : *indicate
392 : ** 192 (prefix+12) instead of 180 so if we see 192
393 : *assume
394 : ** the 12 bytes of record start data has already been
395 : ** added. Frank Warmerdam.
396 : */
397 4 : if (ImageDesc->ImageDataStart != 192)
398 2 : ImageDesc->ImageDataStart += 12;
399 4 : break;
400 4 : case CEOS_REC_SUFFIX_SIZE:
401 4 : DoExtractInt(ImageDesc->ImageSuffixData);
402 4 : break;
403 8 : case CEOS_REC_RECORDSIZE:
404 8 : DoExtractInt(ImageDesc->BytesPerRecord);
405 8 : break;
406 4 : case CEOS_REC_PPL:
407 4 : DoExtractInt(ImageDesc->PixelsPerLine);
408 4 : break;
409 0 : case CEOS_REC_TBP:
410 0 : DoExtractInt(ImageDesc->TopBorderPixels);
411 0 : break;
412 0 : case CEOS_REC_BBP:
413 0 : DoExtractInt(ImageDesc->BottomBorderPixels);
414 0 : break;
415 4 : case CEOS_REC_LBP:
416 4 : DoExtractInt(ImageDesc->LeftBorderPixels);
417 4 : break;
418 4 : case CEOS_REC_RBP:
419 4 : DoExtractInt(ImageDesc->RightBorderPixels);
420 4 : break;
421 4 : case CEOS_REC_INTERLEAVE:
422 4 : ExtractString(record, recipe[i].Offset,
423 4 : recipe[i].Length, temp_str);
424 :
425 4 : ImageDesc->ChannelInterleaving =
426 4 : GetCeosStringType(CeosInterleaveType, temp_str);
427 4 : break;
428 4 : case CEOS_REC_DATATYPE:
429 4 : ExtractString(record, recipe[i].Offset,
430 4 : recipe[i].Length, temp_str);
431 :
432 4 : ImageDesc->DataType =
433 4 : GetCeosStringType(CeosDataType, temp_str);
434 4 : break;
435 : }
436 176 : }
437 : }
438 : }
439 :
440 : /* Some files (Telaviv) don't record the number of pixel groups per line.
441 : * Try to derive it from the size of a data group, and the number of
442 : * bytes of pixel data if necessary.
443 : */
444 :
445 8 : if (ImageDesc->PixelsPerLine == 0 &&
446 4 : ImageDesc->PixelDataBytesPerRecord != 0 &&
447 0 : ImageDesc->BytesPerPixel != 0)
448 : {
449 0 : ImageDesc->PixelsPerLine =
450 0 : ImageDesc->PixelDataBytesPerRecord / ImageDesc->BytesPerPixel;
451 0 : CPLDebug("SAR_CEOS", "Guessing PixelPerLine to be %d\n",
452 : ImageDesc->PixelsPerLine);
453 : }
454 :
455 : /* Some files don't have the BytesPerRecord stuff, so we calculate it if
456 : * possible */
457 :
458 8 : if (ImageDesc->BytesPerRecord == 0 && ImageDesc->RecordsPerLine == 1 &&
459 0 : ImageDesc->PixelsPerLine > 0 && ImageDesc->BytesPerPixel > 0)
460 : {
461 : CeosRecord_t *img_rec;
462 :
463 0 : ImageDesc->BytesPerRecord =
464 0 : ImageDesc->PixelsPerLine * ImageDesc->BytesPerPixel +
465 0 : ImageDesc->ImageDataStart + ImageDesc->ImageSuffixData;
466 :
467 0 : TypeCode.UCharCode.Subtype1 = 0xed;
468 0 : TypeCode.UCharCode.Type = 0xed;
469 0 : TypeCode.UCharCode.Subtype2 = 0x12;
470 0 : TypeCode.UCharCode.Subtype3 = 0x12;
471 :
472 0 : img_rec = FindCeosRecord(volume->RecordList, TypeCode,
473 : CEOS_IMAGRY_OPT_FILE, -1, -1);
474 0 : if (img_rec == NULL)
475 : {
476 0 : CPLDebug("SAR_CEOS",
477 : "Unable to find imagery rec to check record length.");
478 0 : return 0;
479 : }
480 :
481 0 : if (img_rec->Length != ImageDesc->BytesPerRecord)
482 : {
483 0 : CPLDebug("SAR_CEOS",
484 : "Guessed record length (%d) did not match\n"
485 : "actual imagery record length (%d), recipe fails.",
486 : ImageDesc->BytesPerRecord, img_rec->Length);
487 0 : return 0;
488 : }
489 : }
490 :
491 8 : if (ImageDesc->PixelsPerRecord == 0 && ImageDesc->BytesPerRecord != 0 &&
492 8 : ImageDesc->BytesPerPixel != 0)
493 : {
494 4 : ImageDesc->PixelsPerRecord =
495 4 : ((ImageDesc->BytesPerRecord -
496 4 : (ImageDesc->ImageSuffixData + ImageDesc->ImageDataStart)) /
497 4 : ImageDesc->BytesPerPixel);
498 :
499 4 : if (ImageDesc->PixelsPerRecord > ImageDesc->PixelsPerLine)
500 0 : ImageDesc->PixelsPerRecord = ImageDesc->PixelsPerLine;
501 : }
502 :
503 : /* If we didn't get a data type, try guessing. */
504 8 : if (ImageDesc->DataType == 0 && ImageDesc->BytesPerPixel != 0 &&
505 0 : ImageDesc->NumChannels != 0)
506 : {
507 0 : int nDataTypeSize = ImageDesc->BytesPerPixel / ImageDesc->NumChannels;
508 :
509 0 : if (nDataTypeSize == 1)
510 0 : ImageDesc->DataType = CEOS_TYP_UCHAR;
511 0 : else if (nDataTypeSize == 2)
512 0 : ImageDesc->DataType = CEOS_TYP_USHORT;
513 : }
514 :
515 : /* Sanity checking */
516 :
517 8 : if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
518 4 : ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
519 4 : ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
520 4 : ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
521 4 : ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
522 : {
523 4 : return 0;
524 : }
525 : else
526 : {
527 :
528 4 : ImageDesc->ImageDescValid = TRUE;
529 4 : return 1;
530 : }
531 : }
532 :
533 0 : int ScanSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
534 : {
535 0 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
536 :
537 0 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
538 :
539 0 : if (CeosDefaultRecipe(volume, token))
540 : {
541 0 : ImageDesc->Lines *= 2;
542 0 : return 1;
543 : }
544 :
545 0 : return 0;
546 : }
547 :
548 0 : static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token)
549 : {
550 0 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
551 0 : CeosTypeCode_t TypeCode = {0};
552 : CeosRecord_t *record;
553 : char szSARDataFormat[29];
554 :
555 0 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
556 :
557 : /* -------------------------------------------------------------------- */
558 : /* First, we need to check if the "SAR Data Format Type */
559 : /* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
560 : /* pretty idiosyncratic to SIRC products. It might also appear */
561 : /* for some other similarly encoded Polarimetric data I suppose. */
562 : /* -------------------------------------------------------------------- */
563 : /* IMAGE_OPT */
564 0 : TypeCode.UCharCode.Subtype1 = 63;
565 0 : TypeCode.UCharCode.Type = 192;
566 0 : TypeCode.UCharCode.Subtype2 = 18;
567 0 : TypeCode.UCharCode.Subtype3 = 18;
568 :
569 0 : record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
570 : -1, -1);
571 0 : if (record == NULL)
572 0 : return 0;
573 :
574 0 : ExtractString(record, 401, 28, szSARDataFormat);
575 0 : if (!STARTS_WITH_CI(szSARDataFormat, "COMPRESSED CROSS-PRODUCTS"))
576 0 : return 0;
577 :
578 : /* -------------------------------------------------------------------- */
579 : /* Apply normal handling... */
580 : /* -------------------------------------------------------------------- */
581 0 : CeosDefaultRecipe(volume, token);
582 :
583 : /* -------------------------------------------------------------------- */
584 : /* Make sure this looks like the SIRC product we are expecting. */
585 : /* -------------------------------------------------------------------- */
586 0 : if (ImageDesc->BytesPerPixel != 10)
587 0 : return 0;
588 :
589 : /* -------------------------------------------------------------------- */
590 : /* Then fix up a few values. */
591 : /* -------------------------------------------------------------------- */
592 : /* It seems the bytes of pixel data per record is just wrong. Fix. */
593 0 : ImageDesc->PixelDataBytesPerRecord =
594 0 : ImageDesc->BytesPerPixel * ImageDesc->PixelsPerLine;
595 :
596 0 : ImageDesc->DataType = CEOS_TYP_CCP_COMPLEX_FLOAT;
597 :
598 : /* -------------------------------------------------------------------- */
599 : /* Sanity checking */
600 : /* -------------------------------------------------------------------- */
601 0 : if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
602 0 : ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
603 0 : ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
604 0 : ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
605 0 : ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
606 : {
607 0 : return 0;
608 : }
609 : else
610 : {
611 0 : ImageDesc->ImageDescValid = TRUE;
612 0 : return 1;
613 : }
614 : }
615 :
616 4 : static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
617 : {
618 4 : struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
619 4 : CeosTypeCode_t TypeCode = {0};
620 : CeosRecord_t *record;
621 : char szSARDataFormat[29], szProduct[32];
622 :
623 4 : memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
624 :
625 : /* -------------------------------------------------------------------- */
626 : /* First, we need to check if the "SAR Data Format Type */
627 : /* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
628 : /* pretty idiosyncratic to SIRC products. It might also appear */
629 : /* for some other similarly encoded Polarimetric data I suppose. */
630 : /* -------------------------------------------------------------------- */
631 : /* IMAGE_OPT */
632 4 : TypeCode.UCharCode.Subtype1 = 63;
633 4 : TypeCode.UCharCode.Type = 192;
634 4 : TypeCode.UCharCode.Subtype2 = 18;
635 4 : TypeCode.UCharCode.Subtype3 = 18;
636 :
637 4 : record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
638 : -1, -1);
639 4 : if (record == NULL)
640 0 : return 0;
641 :
642 4 : ExtractString(record, 401, 28, szSARDataFormat);
643 4 : if (!STARTS_WITH_CI(szSARDataFormat, "INTEGER*18 "))
644 4 : return 0;
645 :
646 0 : ExtractString(record, 49, 16, szProduct);
647 0 : if (!STARTS_WITH_CI(szProduct, "ALOS-"))
648 0 : return 0;
649 :
650 : /* -------------------------------------------------------------------- */
651 : /* Apply normal handling... */
652 : /* -------------------------------------------------------------------- */
653 0 : CeosDefaultRecipe(volume, token);
654 :
655 : /* -------------------------------------------------------------------- */
656 : /* Make sure this looks like the SIRC product we are expecting. */
657 : /* -------------------------------------------------------------------- */
658 0 : if (ImageDesc->BytesPerPixel != 18)
659 0 : return 0;
660 :
661 : /* -------------------------------------------------------------------- */
662 : /* Then fix up a few values. */
663 : /* -------------------------------------------------------------------- */
664 0 : ImageDesc->DataType = CEOS_TYP_PALSAR_COMPLEX_SHORT;
665 0 : ImageDesc->NumChannels = 6;
666 :
667 : /* -------------------------------------------------------------------- */
668 : /* Sanity checking */
669 : /* -------------------------------------------------------------------- */
670 0 : if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
671 0 : ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
672 0 : ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
673 0 : ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
674 0 : ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
675 : {
676 0 : return 0;
677 : }
678 : else
679 : {
680 0 : ImageDesc->ImageDescValid = TRUE;
681 0 : return 1;
682 : }
683 : }
684 :
685 4 : void GetCeosSARImageDesc(CeosSARVolume_t *volume)
686 : {
687 : Link_t *l_link;
688 : RecipeFunctionData_t *rec_data;
689 : int (*function)(CeosSARVolume_t * volume, const void *token);
690 :
691 4 : if (RecipeFunctions == NULL)
692 : {
693 2 : RegisterRecipes();
694 : }
695 :
696 4 : if (RecipeFunctions == NULL)
697 : {
698 0 : return;
699 : }
700 :
701 12 : for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
702 : {
703 12 : if (l_link->object)
704 : {
705 12 : rec_data = l_link->object;
706 12 : function = rec_data->function;
707 12 : if ((*function)(volume, rec_data->token))
708 : {
709 4 : CPLDebug("CEOS", "Using recipe '%s'.", rec_data->name);
710 4 : return;
711 : }
712 : }
713 : }
714 :
715 0 : return;
716 : }
717 :
718 52 : static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
719 : unsigned int length, int *value)
720 : {
721 : void *buffer;
722 : char format[32];
723 :
724 52 : buffer = HMalloc(length + 1);
725 :
726 52 : switch (type)
727 : {
728 0 : case CEOS_REC_TYP_A:
729 0 : snprintf(format, sizeof(format), "A%u", length);
730 0 : GetCeosField(record, offset, format, buffer);
731 0 : *value = atoi(buffer);
732 0 : break;
733 12 : case CEOS_REC_TYP_B:
734 12 : snprintf(format, sizeof(format), "B%u", length);
735 : #ifdef notdef
736 : GetCeosField(record, offset, format, buffer);
737 : if (length <= 4)
738 : CeosToNative(value, buffer, length, length);
739 : else
740 : *value = 0;
741 : #else
742 12 : GetCeosField(record, offset, format, value);
743 : #endif
744 12 : break;
745 40 : case CEOS_REC_TYP_I:
746 40 : snprintf(format, sizeof(format), "I%u", length);
747 40 : GetCeosField(record, offset, format, value);
748 40 : break;
749 : }
750 :
751 52 : HFree(buffer);
752 52 : }
753 :
754 12 : static char *ExtractString(CeosRecord_t *record, unsigned int offset,
755 : unsigned int length, char *string)
756 : {
757 : char format[12];
758 :
759 12 : if (string == NULL)
760 : {
761 0 : string = HMalloc(length + 1);
762 : }
763 :
764 12 : snprintf(format, sizeof(format), "A%u", length);
765 :
766 12 : GetCeosField(record, offset, format, string);
767 :
768 12 : return string;
769 : }
770 :
771 8 : static int GetCeosStringType(const CeosStringType_t *CeosStringType,
772 : const char *string)
773 : {
774 : int i;
775 :
776 10 : for (i = 0; CeosStringType[i].String != NULL; i++)
777 : {
778 10 : if (strncmp(CeosStringType[i].String, string,
779 10 : strlen(CeosStringType[i].String)) == 0)
780 : {
781 8 : return CeosStringType[i].Type;
782 : }
783 : }
784 :
785 0 : return 0;
786 : }
|