Coverage Report

Created: 2025-12-03 08:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/ceos2/ceosrecipe.c
Line
Count
Source
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 Default 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 Default 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
void RegisterRecipes(void)
255
24
{
256
257
24
    AddRecipe(SIRCRecipeFCN, SIRCRecipe, "SIR-C");
258
24
    AddRecipe(ScanSARRecipeFCN, ScanSARRecipe, "ScanSAR");
259
24
    AddRecipe(CeosDefaultRecipe, RadarSatRecipe, "RadarSat");
260
24
    AddRecipe(CeosDefaultRecipe, JersRecipe, "Jers");
261
24
    AddRecipe(PALSARRecipeFCN, RadarSatRecipe, "PALSAR-ALOS");
262
    /*  AddRecipe( CeosDefaultRecipe, AtlantisRecipe ); */
263
24
}
264
265
void FreeRecipes(void)
266
267
35
{
268
35
    Link_t *l_link;
269
270
155
    for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
271
120
        HFree(l_link->object);
272
273
35
    DestroyList(RecipeFunctions);
274
35
    RecipeFunctions = NULL;
275
35
}
276
277
void AddRecipe(int (*function)(CeosSARVolume_t *volume, const void *token),
278
               const void *token, const char *name)
279
120
{
280
281
120
    RecipeFunctionData_t *TempData;
282
283
120
    Link_t *Link;
284
285
120
    TempData = HMalloc(sizeof(RecipeFunctionData_t));
286
287
120
    TempData->function = function;
288
120
    TempData->token = token;
289
120
    TempData->name = name;
290
291
120
    Link = ceos2CreateLink(TempData);
292
293
120
    if (RecipeFunctions == NULL)
294
24
    {
295
24
        RecipeFunctions = Link;
296
24
    }
297
96
    else
298
96
    {
299
96
        RecipeFunctions = InsertLink(RecipeFunctions, Link);
300
96
    }
301
120
}
302
303
int CeosDefaultRecipe(CeosSARVolume_t *volume, const void *token)
304
57
{
305
57
    const CeosRecipeType_t *recipe;
306
57
    CeosRecord_t *record;
307
57
    CeosTypeCode_t TypeCode = {0};
308
57
    struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
309
57
    char temp_str[1024];
310
57
    int i /*, temp_int */;
311
312
57
#define DoExtractInt(a)                                                        \
313
363
    ExtractInt(record, recipe[i].Type, recipe[i].Offset, recipe[i].Length, &a)
314
315
57
    if (token == NULL)
316
0
    {
317
0
        return 0;
318
0
    }
319
320
57
    memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
321
322
    /*    temp_imagerecipe = (CeosSARImageDescRecipe_t *) token;
323
        recipe = temp_imagerecipe->Recipe; */
324
325
57
    recipe = token;
326
327
1.21k
    for (i = 0; recipe[i].ImageDescValue != 0; i++)
328
1.15k
    {
329
1.15k
        if (recipe[i].Override)
330
771
        {
331
771
            TypeCode.UCharCode.Subtype1 = recipe[i].TypeCode.Subtype1;
332
771
            TypeCode.UCharCode.Type = recipe[i].TypeCode.Type;
333
771
            TypeCode.UCharCode.Subtype2 = recipe[i].TypeCode.Subtype2;
334
771
            TypeCode.UCharCode.Subtype3 = recipe[i].TypeCode.Subtype3;
335
336
771
            record = FindCeosRecord(volume->RecordList, TypeCode,
337
771
                                    recipe[i].FileId, -1, -1);
338
339
771
            if (record == NULL)
340
342
            {
341
                /* temp_int = 0; */
342
342
            }
343
429
            else
344
429
            {
345
346
429
                switch (recipe[i].ImageDescValue)
347
429
                {
348
33
                    case CEOS_REC_NUMCHANS:
349
33
                        DoExtractInt(ImageDesc->NumChannels);
350
33
                        break;
351
24
                    case CEOS_REC_LINES:
352
24
                        DoExtractInt(ImageDesc->Lines);
353
24
                        break;
354
33
                    case CEOS_REC_BPP:
355
33
                        DoExtractInt(ImageDesc->BytesPerPixel);
356
33
                        break;
357
33
                    case CEOS_REC_RPL:
358
33
                        DoExtractInt(ImageDesc->RecordsPerLine);
359
33
                        break;
360
24
                    case CEOS_REC_PDBPR:
361
24
                        DoExtractInt(ImageDesc->PixelDataBytesPerRecord);
362
24
                        break;
363
33
                    case CEOS_REC_FDL:
364
33
                        DoExtractInt(ImageDesc->FileDescriptorLength);
365
33
                        break;
366
33
                    case CEOS_REC_IDS:
367
33
                        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
33
                        if (ImageDesc->ImageDataStart != 192)
381
21
                            ImageDesc->ImageDataStart += 12;
382
33
                        break;
383
33
                    case CEOS_REC_SUFFIX_SIZE:
384
33
                        DoExtractInt(ImageDesc->ImageSuffixData);
385
33
                        break;
386
36
                    case CEOS_REC_RECORDSIZE:
387
36
                        DoExtractInt(ImageDesc->BytesPerRecord);
388
36
                        break;
389
33
                    case CEOS_REC_PPL:
390
33
                        DoExtractInt(ImageDesc->PixelsPerLine);
391
33
                        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
24
                    case CEOS_REC_LBP:
399
24
                        DoExtractInt(ImageDesc->LeftBorderPixels);
400
24
                        break;
401
24
                    case CEOS_REC_RBP:
402
24
                        DoExtractInt(ImageDesc->RightBorderPixels);
403
24
                        break;
404
33
                    case CEOS_REC_INTERLEAVE:
405
33
                        ExtractString(record, recipe[i].Offset,
406
33
                                      recipe[i].Length, temp_str);
407
408
33
                        ImageDesc->ChannelInterleaving =
409
33
                            GetCeosStringType(CeosInterleaveType, temp_str);
410
33
                        break;
411
33
                    case CEOS_REC_DATATYPE:
412
33
                        ExtractString(record, recipe[i].Offset,
413
33
                                      recipe[i].Length, temp_str);
414
415
33
                        ImageDesc->DataType =
416
33
                            GetCeosStringType(CeosDataType, temp_str);
417
33
                        break;
418
429
                }
419
429
            }
420
771
        }
421
1.15k
    }
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
57
    if (ImageDesc->PixelsPerLine == 0 &&
429
38
        ImageDesc->PixelDataBytesPerRecord != 0 &&
430
7
        ImageDesc->BytesPerPixel != 0)
431
6
    {
432
6
        ImageDesc->PixelsPerLine =
433
6
            ImageDesc->PixelDataBytesPerRecord / ImageDesc->BytesPerPixel;
434
6
        CPLDebug("SAR_CEOS", "Guessing PixelPerLine to be %d\n",
435
6
                 ImageDesc->PixelsPerLine);
436
6
    }
437
438
    /* Some files don't have the BytesPerRecord stuff, so we calculate it if
439
     * possible */
440
441
57
    if (ImageDesc->BytesPerRecord == 0 && ImageDesc->RecordsPerLine == 1 &&
442
0
        ImageDesc->PixelsPerLine > 0 && ImageDesc->BytesPerPixel > 0)
443
0
    {
444
0
        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
0
                                 CEOS_IMAGRY_OPT_FILE, -1, -1);
457
0
        if (img_rec == NULL)
458
0
        {
459
0
            CPLDebug("SAR_CEOS",
460
0
                     "Unable to find imagery rec to check record length.");
461
0
            return 0;
462
0
        }
463
464
0
        if (img_rec->Length != ImageDesc->BytesPerRecord)
465
0
        {
466
0
            CPLDebug("SAR_CEOS",
467
0
                     "Guessed record length (%d) did not match\n"
468
0
                     "actual imagery record length (%d), recipe fails.",
469
0
                     ImageDesc->BytesPerRecord, img_rec->Length);
470
0
            return 0;
471
0
        }
472
0
    }
473
474
57
    if (ImageDesc->PixelsPerRecord == 0 && ImageDesc->BytesPerRecord != 0 &&
475
36
        ImageDesc->BytesPerPixel != 0)
476
19
    {
477
19
        ImageDesc->PixelsPerRecord =
478
19
            ((ImageDesc->BytesPerRecord -
479
19
              (ImageDesc->ImageSuffixData + ImageDesc->ImageDataStart)) /
480
19
             ImageDesc->BytesPerPixel);
481
482
19
        if (ImageDesc->PixelsPerRecord > ImageDesc->PixelsPerLine)
483
3
            ImageDesc->PixelsPerRecord = ImageDesc->PixelsPerLine;
484
19
    }
485
486
    /* If we didn't get a data type, try guessing. */
487
57
    if (ImageDesc->DataType == 0 && ImageDesc->BytesPerPixel != 0 &&
488
15
        ImageDesc->NumChannels != 0)
489
15
    {
490
15
        int nDataTypeSize = ImageDesc->BytesPerPixel / ImageDesc->NumChannels;
491
492
15
        if (nDataTypeSize == 1)
493
5
            ImageDesc->DataType = CEOS_TYP_UCHAR;
494
10
        else if (nDataTypeSize == 2)
495
0
            ImageDesc->DataType = CEOS_TYP_USHORT;
496
15
    }
497
498
    /* Sanity checking */
499
500
57
    if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
501
18
        ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
502
17
        ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
503
17
        ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
504
16
        ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
505
42
    {
506
42
        return 0;
507
42
    }
508
15
    else
509
15
    {
510
511
15
        ImageDesc->ImageDescValid = TRUE;
512
15
        return 1;
513
15
    }
514
57
}
515
516
int ScanSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
517
9
{
518
9
    struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
519
520
9
    memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
521
522
9
    if (CeosDefaultRecipe(volume, token))
523
0
    {
524
0
        ImageDesc->Lines *= 2;
525
0
        return 1;
526
0
    }
527
528
9
    return 0;
529
9
}
530
531
static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token)
532
9
{
533
9
    struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
534
9
    CeosTypeCode_t TypeCode = {0};
535
9
    CeosRecord_t *record;
536
9
    char szSARDataFormat[29];
537
538
9
    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
9
    TypeCode.UCharCode.Subtype1 = 63;
548
9
    TypeCode.UCharCode.Type = 192;
549
9
    TypeCode.UCharCode.Subtype2 = 18;
550
9
    TypeCode.UCharCode.Subtype3 = 18;
551
552
9
    record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
553
9
                            -1, -1);
554
9
    if (record == NULL)
555
0
        return 0;
556
557
9
    ExtractString(record, 401, 28, szSARDataFormat);
558
9
    if (!STARTS_WITH_CI(szSARDataFormat, "COMPRESSED CROSS-PRODUCTS"))
559
9
        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
0
    {
590
0
        return 0;
591
0
    }
592
0
    else
593
0
    {
594
0
        ImageDesc->ImageDescValid = TRUE;
595
0
        return 1;
596
0
    }
597
0
}
598
599
static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
600
24
{
601
24
    struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
602
24
    CeosTypeCode_t TypeCode = {0};
603
24
    CeosRecord_t *record;
604
24
    char szSARDataFormat[29], szProduct[32];
605
606
24
    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
24
    TypeCode.UCharCode.Subtype1 = 63;
616
24
    TypeCode.UCharCode.Type = 192;
617
24
    TypeCode.UCharCode.Subtype2 = 18;
618
24
    TypeCode.UCharCode.Subtype3 = 18;
619
620
24
    record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
621
24
                            -1, -1);
622
24
    if (record == NULL)
623
0
        return 0;
624
625
24
    ExtractString(record, 401, 28, szSARDataFormat);
626
24
    if (!STARTS_WITH_CI(szSARDataFormat, "INTEGER*18                 "))
627
24
        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
0
    {
659
0
        return 0;
660
0
    }
661
0
    else
662
0
    {
663
0
        ImageDesc->ImageDescValid = TRUE;
664
0
        return 1;
665
0
    }
666
0
}
667
668
void GetCeosSARImageDesc(CeosSARVolume_t *volume)
669
24
{
670
24
    Link_t *l_link;
671
24
    RecipeFunctionData_t *rec_data;
672
24
    int (*function)(CeosSARVolume_t * volume, const void *token);
673
674
24
    if (RecipeFunctions == NULL)
675
24
    {
676
24
        RegisterRecipes();
677
24
    }
678
679
24
    if (RecipeFunctions == NULL)
680
0
    {
681
0
        return;
682
0
    }
683
684
99
    for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
685
90
    {
686
90
        if (l_link->object)
687
90
        {
688
90
            rec_data = l_link->object;
689
90
            function = rec_data->function;
690
90
            if ((*function)(volume, rec_data->token))
691
15
            {
692
15
                CPLDebug("CEOS", "Using recipe '%s'.", rec_data->name);
693
15
                return;
694
15
            }
695
90
        }
696
90
    }
697
698
9
    return;
699
24
}
700
701
static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
702
                       unsigned int length, int *value)
703
363
{
704
363
    void *buffer;
705
363
    char format[32];
706
707
363
    buffer = HMalloc(length + 1);
708
709
363
    switch (type)
710
363
    {
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
69
        case CEOS_REC_TYP_B:
717
69
            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
69
            GetCeosField(record, offset, format, value);
726
69
#endif
727
69
            break;
728
294
        case CEOS_REC_TYP_I:
729
294
            snprintf(format, sizeof(format), "I%u", length);
730
294
            GetCeosField(record, offset, format, value);
731
294
            break;
732
363
    }
733
734
363
    HFree(buffer);
735
363
}
736
737
static char *ExtractString(CeosRecord_t *record, unsigned int offset,
738
                           unsigned int length, char *string)
739
99
{
740
99
    char format[12];
741
742
99
    if (string == NULL)
743
0
    {
744
0
        string = HMalloc(length + 1);
745
0
    }
746
747
99
    snprintf(format, sizeof(format), "A%u", length);
748
749
99
    GetCeosField(record, offset, format, string);
750
751
99
    return string;
752
99
}
753
754
static int GetCeosStringType(const CeosStringType_t *CeosStringType,
755
                             const char *string)
756
66
{
757
66
    int i;
758
759
297
    for (i = 0; CeosStringType[i].String != NULL; i++)
760
266
    {
761
266
        if (strncmp(CeosStringType[i].String, string,
762
266
                    strlen(CeosStringType[i].String)) == 0)
763
35
        {
764
35
            return CeosStringType[i].Type;
765
35
        }
766
266
    }
767
768
31
    return 0;
769
66
}