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

Generated by: LCOV version 1.14