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