LCOV - code coverage report
Current view: top level - frmts/ceos2 - ceosrecipe.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 156 250 62.4 %
Date: 2026-02-12 23:49:34 Functions: 9 11 81.8 %

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

Generated by: LCOV version 1.14