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