787 строки
31 KiB
C
787 строки
31 KiB
C
/******************************************************************************
|
|
* $Id$
|
|
*
|
|
* Project: ASI CEOS Translator
|
|
* Purpose: CEOS field layout recipes.
|
|
* Author: Paul Lahaie, pjlahaie@atlsci.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2000, Atlantis Scientific Inc
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "ceos.h"
|
|
|
|
/* Array of Datatypes and their names/values */
|
|
|
|
typedef struct
|
|
{
|
|
const char *String;
|
|
int Type;
|
|
} CeosStringType_t;
|
|
|
|
typedef struct
|
|
{
|
|
int (*function)(CeosSARVolume_t *volume, const void *token);
|
|
const void *token;
|
|
const char *name;
|
|
} RecipeFunctionData_t;
|
|
|
|
static const CeosStringType_t CeosDataType[] = {
|
|
{"IU1", CEOS_TYP_UCHAR},
|
|
{"IU2", CEOS_TYP_USHORT},
|
|
{"UI1", CEOS_TYP_UCHAR},
|
|
{"UI2", CEOS_TYP_USHORT},
|
|
{"CI*2", CEOS_TYP_COMPLEX_CHAR},
|
|
{"CI*4", CEOS_TYP_COMPLEX_SHORT},
|
|
{"CIS4", CEOS_TYP_COMPLEX_SHORT},
|
|
{"CI*8", CEOS_TYP_COMPLEX_LONG},
|
|
{"C*8", CEOS_TYP_COMPLEX_FLOAT},
|
|
{"R*4", CEOS_TYP_FLOAT},
|
|
{NULL, 0}};
|
|
|
|
static const CeosStringType_t CeosInterleaveType[] = {{"BSQ", CEOS_IL_BAND},
|
|
{" BSQ", CEOS_IL_BAND},
|
|
{"BIL", CEOS_IL_LINE},
|
|
{" BIL", CEOS_IL_LINE},
|
|
{NULL, 0}};
|
|
|
|
#define IMAGE_OPT \
|
|
{ \
|
|
63, 192, 18, 18 \
|
|
}
|
|
#define IMAGE_JERS_OPT \
|
|
{ \
|
|
50, 192, 18, 18 \
|
|
} /* Some JERS data uses this instead of IMAGE_OPT */
|
|
#define PROC_DATA_REC \
|
|
{ \
|
|
50, 11, 18, 20 \
|
|
}
|
|
#define PROC_DATA_REC_ALT \
|
|
{ \
|
|
50, 11, 31, 20 \
|
|
}
|
|
#define PROC_DATA_REC_ALT2 \
|
|
{ \
|
|
50, 11, 31, 50 \
|
|
} /* Some cases of ERS 1, 2 */
|
|
#define DATA_SET_SUMMARY \
|
|
{ \
|
|
18, 10, 18, 20 \
|
|
}
|
|
|
|
/* NOTE: This seems to be the generic recipe used for most things */
|
|
static const CeosRecipeType_t RadarSatRecipe[] = {
|
|
{CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
|
|
CEOS_REC_TYP_I}, /* Number of channels */
|
|
{CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
|
|
CEOS_REC_TYP_A}, /* Interleaving type */
|
|
{CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
|
|
CEOS_REC_TYP_A}, /* Data type */
|
|
{CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
|
|
CEOS_REC_TYP_A}, /* For Defeault CEOS, this is done using other vals */
|
|
{CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 237, 8,
|
|
CEOS_REC_TYP_I}, /* How many lines */
|
|
{CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 261, 4, CEOS_REC_TYP_I},
|
|
{CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 265, 4,
|
|
CEOS_REC_TYP_I}, /* Bottom border pixels */
|
|
{CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
|
|
CEOS_REC_TYP_I}, /* Pixels per line */
|
|
{CEOS_REC_LBP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 245, 4,
|
|
CEOS_REC_TYP_I}, /* Left Border Pixels */
|
|
{CEOS_REC_RBP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 257, 4,
|
|
CEOS_REC_TYP_I}, /* Right Border Pixels */
|
|
{CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
|
|
CEOS_REC_TYP_I}, /* Bytes Per Pixel */
|
|
{CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
|
|
CEOS_REC_TYP_I}, /* Records per line */
|
|
{CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
|
|
CEOS_REC_TYP_I}, /* Pixels Per Record -- need to fill record type */
|
|
{CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 281, 8,
|
|
CEOS_REC_TYP_I}, /* pixel data bytes per record */
|
|
{CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
|
|
CEOS_REC_TYP_I}, /* Prefix data per record */
|
|
{CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
|
|
CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
|
|
{CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
|
|
CEOS_REC_TYP_I}, /* Must be calculated */
|
|
{CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
|
|
CEOS_REC_TYP_I}, /* Must be calculated */
|
|
{CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 0, 0,
|
|
CEOS_REC_TYP_I},
|
|
|
|
{CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
|
|
CEOS_REC_TYP_B}, /* The processed image record size */
|
|
|
|
/* Some ERS-1 products use an alternate data record subtype2. */
|
|
{CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT, 9, 4,
|
|
CEOS_REC_TYP_B}, /* The processed image record size */
|
|
|
|
/* Yet another ERS-1 and ERS-2 alternate data record subtype2. */
|
|
{CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT2, 9, 4,
|
|
CEOS_REC_TYP_B}, /* The processed image record size */
|
|
|
|
{CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
|
|
CEOS_REC_TYP_I}, /* Suffix data per record */
|
|
{0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
|
|
};
|
|
|
|
static const CeosRecipeType_t JersRecipe[] = {
|
|
{CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 233, 4,
|
|
CEOS_REC_TYP_I}, /* Number of channels */
|
|
{CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 269, 4,
|
|
CEOS_REC_TYP_A}, /* Interleaving type */
|
|
{CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 429, 4,
|
|
CEOS_REC_TYP_A}, /* Data type */
|
|
{CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
|
|
CEOS_REC_TYP_A}, /* For Defeault CEOS, this is done using other vals */
|
|
{CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 237, 8,
|
|
CEOS_REC_TYP_I}, /* How many lines */
|
|
{CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 261, 4,
|
|
CEOS_REC_TYP_I},
|
|
{CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 265, 4,
|
|
CEOS_REC_TYP_I}, /* Bottom border pixels */
|
|
{CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 249, 8,
|
|
CEOS_REC_TYP_I}, /* Pixels per line */
|
|
{CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 245, 4,
|
|
CEOS_REC_TYP_I}, /* Left Border Pixels */
|
|
{CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 257, 4,
|
|
CEOS_REC_TYP_I}, /* Isn't available for RadarSAT */
|
|
{CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 225, 4,
|
|
CEOS_REC_TYP_I}, /* Bytes Per Pixel */
|
|
{CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 273, 2,
|
|
CEOS_REC_TYP_I}, /* Records per line */
|
|
{CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
|
|
CEOS_REC_TYP_I}, /* Pixels Per Record -- need to fill record type */
|
|
{CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 281, 8,
|
|
CEOS_REC_TYP_I}, /* pixel data bytes per record */
|
|
{CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 277, 4,
|
|
CEOS_REC_TYP_I}, /* Prefix data per record */
|
|
{CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 9, 4,
|
|
CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
|
|
{CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
|
|
CEOS_REC_TYP_I}, /* Must be calculated */
|
|
{CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
|
|
CEOS_REC_TYP_I}, /* Must be calculated */
|
|
{CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 0, 0,
|
|
CEOS_REC_TYP_I},
|
|
|
|
{CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
|
|
CEOS_REC_TYP_B}, /* The processed image record size */
|
|
|
|
{CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT, 289, 4,
|
|
CEOS_REC_TYP_I}, /* Suffix data per record */
|
|
{0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
|
|
};
|
|
|
|
static const CeosRecipeType_t ScanSARRecipe[] = {
|
|
{CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
|
|
CEOS_REC_TYP_I}, /* Number of channels */
|
|
{CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
|
|
CEOS_REC_TYP_A}, /* Interleaving type */
|
|
{CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
|
|
CEOS_REC_TYP_A}, /* Data type */
|
|
{CEOS_REC_LINES, 1, CEOS_ANY_FILE, DATA_SET_SUMMARY, 325, 8,
|
|
CEOS_REC_TYP_I}, /* How many lines */
|
|
{CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
|
|
CEOS_REC_TYP_I}, /* Pixels per line */
|
|
{CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
|
|
CEOS_REC_TYP_I}, /* Bytes Per Pixel */
|
|
{CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
|
|
CEOS_REC_TYP_I}, /* Records per line */
|
|
{CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
|
|
CEOS_REC_TYP_I}, /* Prefix data per record */
|
|
{CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
|
|
CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
|
|
{CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
|
|
CEOS_REC_TYP_B}, /* The processed image record size */
|
|
{CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
|
|
CEOS_REC_TYP_I}, /* Suffix data per record */
|
|
{0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
|
|
};
|
|
|
|
static const CeosRecipeType_t SIRCRecipe[] = {
|
|
{CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 233, 4,
|
|
CEOS_REC_TYP_I}, /* Number of channels */
|
|
{CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 269, 4,
|
|
CEOS_REC_TYP_A}, /* Interleaving type */
|
|
{CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 429, 4,
|
|
CEOS_REC_TYP_A}, /* Data type */
|
|
{CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 237, 8,
|
|
CEOS_REC_TYP_I}, /* How many lines */
|
|
{CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 261, 4, CEOS_REC_TYP_I},
|
|
{CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 265, 4,
|
|
CEOS_REC_TYP_I}, /* Bottom border pixels */
|
|
{CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 249, 8,
|
|
CEOS_REC_TYP_I}, /* Pixels per line */
|
|
{CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 245, 4,
|
|
CEOS_REC_TYP_I}, /* Left Border Pixels */
|
|
{CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 257, 4,
|
|
CEOS_REC_TYP_I}, /* Right Border Pixels */
|
|
{CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 225, 4,
|
|
CEOS_REC_TYP_I}, /* Bytes Per Pixel */
|
|
{CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 273, 2,
|
|
CEOS_REC_TYP_I}, /* Records per line */
|
|
{CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 277, 4,
|
|
CEOS_REC_TYP_I}, /* Prefix data per record */
|
|
{CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 9, 4,
|
|
CEOS_REC_TYP_B}, /* Length of Imagry Options Header */
|
|
{CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC, 9, 4,
|
|
CEOS_REC_TYP_B}, /* The processed image record size */
|
|
{CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT, 289, 4,
|
|
CEOS_REC_TYP_I}, /* Suffix data per record */
|
|
|
|
{0, 0, 0, {0, 0, 0, 0}, 0, 0, 0} /* Last record is Zero */
|
|
};
|
|
|
|
#undef PROC_DATA_REC
|
|
|
|
static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
|
|
unsigned int length, int *value);
|
|
|
|
static char *ExtractString(CeosRecord_t *record, unsigned int offset,
|
|
unsigned int length, char *string);
|
|
|
|
static int GetCeosStringType(const CeosStringType_t *CeosType,
|
|
const char *string);
|
|
|
|
static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token);
|
|
static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token);
|
|
|
|
Link_t *RecipeFunctions = NULL;
|
|
|
|
void RegisterRecipes(void)
|
|
{
|
|
|
|
AddRecipe(SIRCRecipeFCN, SIRCRecipe, "SIR-C");
|
|
AddRecipe(ScanSARRecipeFCN, ScanSARRecipe, "ScanSAR");
|
|
AddRecipe(CeosDefaultRecipe, RadarSatRecipe, "RadarSat");
|
|
AddRecipe(CeosDefaultRecipe, JersRecipe, "Jers");
|
|
AddRecipe(PALSARRecipeFCN, RadarSatRecipe, "PALSAR-ALOS");
|
|
/* AddRecipe( CeosDefaultRecipe, AtlantisRecipe ); */
|
|
}
|
|
|
|
void FreeRecipes(void)
|
|
|
|
{
|
|
Link_t *l_link;
|
|
|
|
for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
|
|
HFree(l_link->object);
|
|
|
|
DestroyList(RecipeFunctions);
|
|
RecipeFunctions = NULL;
|
|
}
|
|
|
|
void AddRecipe(int (*function)(CeosSARVolume_t *volume, const void *token),
|
|
const void *token, const char *name)
|
|
{
|
|
|
|
RecipeFunctionData_t *TempData;
|
|
|
|
Link_t *Link;
|
|
|
|
TempData = HMalloc(sizeof(RecipeFunctionData_t));
|
|
|
|
TempData->function = function;
|
|
TempData->token = token;
|
|
TempData->name = name;
|
|
|
|
Link = ceos2CreateLink(TempData);
|
|
|
|
if (RecipeFunctions == NULL)
|
|
{
|
|
RecipeFunctions = Link;
|
|
}
|
|
else
|
|
{
|
|
RecipeFunctions = InsertLink(RecipeFunctions, Link);
|
|
}
|
|
}
|
|
|
|
int CeosDefaultRecipe(CeosSARVolume_t *volume, const void *token)
|
|
{
|
|
const CeosRecipeType_t *recipe;
|
|
CeosRecord_t *record;
|
|
CeosTypeCode_t TypeCode = {0};
|
|
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
|
char temp_str[1024];
|
|
int i /*, temp_int */;
|
|
|
|
#define DoExtractInt(a) \
|
|
ExtractInt(record, recipe[i].Type, recipe[i].Offset, recipe[i].Length, &a)
|
|
|
|
if (token == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
|
|
|
|
/* temp_imagerecipe = (CeosSARImageDescRecipe_t *) token;
|
|
recipe = temp_imagerecipe->Recipe; */
|
|
|
|
recipe = token;
|
|
|
|
for (i = 0; recipe[i].ImageDescValue != 0; i++)
|
|
{
|
|
if (recipe[i].Override)
|
|
{
|
|
TypeCode.UCharCode.Subtype1 = recipe[i].TypeCode.Subtype1;
|
|
TypeCode.UCharCode.Type = recipe[i].TypeCode.Type;
|
|
TypeCode.UCharCode.Subtype2 = recipe[i].TypeCode.Subtype2;
|
|
TypeCode.UCharCode.Subtype3 = recipe[i].TypeCode.Subtype3;
|
|
|
|
record = FindCeosRecord(volume->RecordList, TypeCode,
|
|
recipe[i].FileId, -1, -1);
|
|
|
|
if (record == NULL)
|
|
{
|
|
/* temp_int = 0; */
|
|
}
|
|
else
|
|
{
|
|
|
|
switch (recipe[i].ImageDescValue)
|
|
{
|
|
case CEOS_REC_NUMCHANS:
|
|
DoExtractInt(ImageDesc->NumChannels);
|
|
break;
|
|
case CEOS_REC_LINES:
|
|
DoExtractInt(ImageDesc->Lines);
|
|
break;
|
|
case CEOS_REC_BPP:
|
|
DoExtractInt(ImageDesc->BytesPerPixel);
|
|
break;
|
|
case CEOS_REC_RPL:
|
|
DoExtractInt(ImageDesc->RecordsPerLine);
|
|
break;
|
|
case CEOS_REC_PDBPR:
|
|
DoExtractInt(ImageDesc->PixelDataBytesPerRecord);
|
|
break;
|
|
case CEOS_REC_FDL:
|
|
DoExtractInt(ImageDesc->FileDescriptorLength);
|
|
break;
|
|
case CEOS_REC_IDS:
|
|
DoExtractInt(ImageDesc->ImageDataStart);
|
|
/*
|
|
** This is really reading the quantity of prefix data
|
|
** per data record. We want the offset from the very
|
|
** beginning of the record to the data, so we add
|
|
*another
|
|
** 12 to that. I think some products incorrectly
|
|
*indicate
|
|
** 192 (prefix+12) instead of 180 so if we see 192
|
|
*assume
|
|
** the 12 bytes of record start data has already been
|
|
** added. Frank Warmerdam.
|
|
*/
|
|
if (ImageDesc->ImageDataStart != 192)
|
|
ImageDesc->ImageDataStart += 12;
|
|
break;
|
|
case CEOS_REC_SUFFIX_SIZE:
|
|
DoExtractInt(ImageDesc->ImageSuffixData);
|
|
break;
|
|
case CEOS_REC_RECORDSIZE:
|
|
DoExtractInt(ImageDesc->BytesPerRecord);
|
|
break;
|
|
case CEOS_REC_PPL:
|
|
DoExtractInt(ImageDesc->PixelsPerLine);
|
|
break;
|
|
case CEOS_REC_TBP:
|
|
DoExtractInt(ImageDesc->TopBorderPixels);
|
|
break;
|
|
case CEOS_REC_BBP:
|
|
DoExtractInt(ImageDesc->BottomBorderPixels);
|
|
break;
|
|
case CEOS_REC_LBP:
|
|
DoExtractInt(ImageDesc->LeftBorderPixels);
|
|
break;
|
|
case CEOS_REC_RBP:
|
|
DoExtractInt(ImageDesc->RightBorderPixels);
|
|
break;
|
|
case CEOS_REC_INTERLEAVE:
|
|
ExtractString(record, recipe[i].Offset,
|
|
recipe[i].Length, temp_str);
|
|
|
|
ImageDesc->ChannelInterleaving =
|
|
GetCeosStringType(CeosInterleaveType, temp_str);
|
|
break;
|
|
case CEOS_REC_DATATYPE:
|
|
ExtractString(record, recipe[i].Offset,
|
|
recipe[i].Length, temp_str);
|
|
|
|
ImageDesc->DataType =
|
|
GetCeosStringType(CeosDataType, temp_str);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Some files (Telaviv) don't record the number of pixel groups per line.
|
|
* Try to derive it from the size of a data group, and the number of
|
|
* bytes of pixel data if necessary.
|
|
*/
|
|
|
|
if (ImageDesc->PixelsPerLine == 0 &&
|
|
ImageDesc->PixelDataBytesPerRecord != 0 &&
|
|
ImageDesc->BytesPerPixel != 0)
|
|
{
|
|
ImageDesc->PixelsPerLine =
|
|
ImageDesc->PixelDataBytesPerRecord / ImageDesc->BytesPerPixel;
|
|
CPLDebug("SAR_CEOS", "Guessing PixelPerLine to be %d\n",
|
|
ImageDesc->PixelsPerLine);
|
|
}
|
|
|
|
/* Some files don't have the BytesPerRecord stuff, so we calculate it if
|
|
* possible */
|
|
|
|
if (ImageDesc->BytesPerRecord == 0 && ImageDesc->RecordsPerLine == 1 &&
|
|
ImageDesc->PixelsPerLine > 0 && ImageDesc->BytesPerPixel > 0)
|
|
{
|
|
CeosRecord_t *img_rec;
|
|
|
|
ImageDesc->BytesPerRecord =
|
|
ImageDesc->PixelsPerLine * ImageDesc->BytesPerPixel +
|
|
ImageDesc->ImageDataStart + ImageDesc->ImageSuffixData;
|
|
|
|
TypeCode.UCharCode.Subtype1 = 0xed;
|
|
TypeCode.UCharCode.Type = 0xed;
|
|
TypeCode.UCharCode.Subtype2 = 0x12;
|
|
TypeCode.UCharCode.Subtype3 = 0x12;
|
|
|
|
img_rec = FindCeosRecord(volume->RecordList, TypeCode,
|
|
CEOS_IMAGRY_OPT_FILE, -1, -1);
|
|
if (img_rec == NULL)
|
|
{
|
|
CPLDebug("SAR_CEOS",
|
|
"Unable to find imagery rec to check record length.");
|
|
return 0;
|
|
}
|
|
|
|
if (img_rec->Length != ImageDesc->BytesPerRecord)
|
|
{
|
|
CPLDebug("SAR_CEOS",
|
|
"Guessed record length (%d) did not match\n"
|
|
"actual imagery record length (%d), recipe fails.",
|
|
ImageDesc->BytesPerRecord, img_rec->Length);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (ImageDesc->PixelsPerRecord == 0 && ImageDesc->BytesPerRecord != 0 &&
|
|
ImageDesc->BytesPerPixel != 0)
|
|
{
|
|
ImageDesc->PixelsPerRecord =
|
|
((ImageDesc->BytesPerRecord -
|
|
(ImageDesc->ImageSuffixData + ImageDesc->ImageDataStart)) /
|
|
ImageDesc->BytesPerPixel);
|
|
|
|
if (ImageDesc->PixelsPerRecord > ImageDesc->PixelsPerLine)
|
|
ImageDesc->PixelsPerRecord = ImageDesc->PixelsPerLine;
|
|
}
|
|
|
|
/* If we didn't get a data type, try guessing. */
|
|
if (ImageDesc->DataType == 0 && ImageDesc->BytesPerPixel != 0 &&
|
|
ImageDesc->NumChannels != 0)
|
|
{
|
|
int nDataTypeSize = ImageDesc->BytesPerPixel / ImageDesc->NumChannels;
|
|
|
|
if (nDataTypeSize == 1)
|
|
ImageDesc->DataType = CEOS_TYP_UCHAR;
|
|
else if (nDataTypeSize == 2)
|
|
ImageDesc->DataType = CEOS_TYP_USHORT;
|
|
}
|
|
|
|
/* Sanity checking */
|
|
|
|
if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
|
|
ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
|
|
ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
|
|
ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
|
|
ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
|
|
ImageDesc->ImageDescValid = TRUE;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int ScanSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
|
|
{
|
|
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
|
|
|
memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
|
|
|
|
if (CeosDefaultRecipe(volume, token))
|
|
{
|
|
ImageDesc->Lines *= 2;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int SIRCRecipeFCN(CeosSARVolume_t *volume, const void *token)
|
|
{
|
|
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
|
CeosTypeCode_t TypeCode = {0};
|
|
CeosRecord_t *record;
|
|
char szSARDataFormat[29];
|
|
|
|
memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* First, we need to check if the "SAR Data Format Type */
|
|
/* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
|
|
/* pretty idiosyncratic to SIRC products. It might also appear */
|
|
/* for some other similarly encoded Polarimetric data I suppose. */
|
|
/* -------------------------------------------------------------------- */
|
|
/* IMAGE_OPT */
|
|
TypeCode.UCharCode.Subtype1 = 63;
|
|
TypeCode.UCharCode.Type = 192;
|
|
TypeCode.UCharCode.Subtype2 = 18;
|
|
TypeCode.UCharCode.Subtype3 = 18;
|
|
|
|
record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
|
|
-1, -1);
|
|
if (record == NULL)
|
|
return 0;
|
|
|
|
ExtractString(record, 401, 28, szSARDataFormat);
|
|
if (!STARTS_WITH_CI(szSARDataFormat, "COMPRESSED CROSS-PRODUCTS"))
|
|
return 0;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Apply normal handling... */
|
|
/* -------------------------------------------------------------------- */
|
|
CeosDefaultRecipe(volume, token);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Make sure this looks like the SIRC product we are expecting. */
|
|
/* -------------------------------------------------------------------- */
|
|
if (ImageDesc->BytesPerPixel != 10)
|
|
return 0;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Then fix up a few values. */
|
|
/* -------------------------------------------------------------------- */
|
|
/* It seems the bytes of pixel data per record is just wrong. Fix. */
|
|
ImageDesc->PixelDataBytesPerRecord =
|
|
ImageDesc->BytesPerPixel * ImageDesc->PixelsPerLine;
|
|
|
|
ImageDesc->DataType = CEOS_TYP_CCP_COMPLEX_FLOAT;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Sanity checking */
|
|
/* -------------------------------------------------------------------- */
|
|
if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
|
|
ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
|
|
ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
|
|
ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
|
|
ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
ImageDesc->ImageDescValid = TRUE;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static int PALSARRecipeFCN(CeosSARVolume_t *volume, const void *token)
|
|
{
|
|
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
|
CeosTypeCode_t TypeCode = {0};
|
|
CeosRecord_t *record;
|
|
char szSARDataFormat[29], szProduct[32];
|
|
|
|
memset(ImageDesc, 0, sizeof(struct CeosSARImageDesc));
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* First, we need to check if the "SAR Data Format Type */
|
|
/* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
|
|
/* pretty idiosyncratic to SIRC products. It might also appear */
|
|
/* for some other similarly encoded Polarimetric data I suppose. */
|
|
/* -------------------------------------------------------------------- */
|
|
/* IMAGE_OPT */
|
|
TypeCode.UCharCode.Subtype1 = 63;
|
|
TypeCode.UCharCode.Type = 192;
|
|
TypeCode.UCharCode.Subtype2 = 18;
|
|
TypeCode.UCharCode.Subtype3 = 18;
|
|
|
|
record = FindCeosRecord(volume->RecordList, TypeCode, CEOS_IMAGRY_OPT_FILE,
|
|
-1, -1);
|
|
if (record == NULL)
|
|
return 0;
|
|
|
|
ExtractString(record, 401, 28, szSARDataFormat);
|
|
if (!STARTS_WITH_CI(szSARDataFormat, "INTEGER*18 "))
|
|
return 0;
|
|
|
|
ExtractString(record, 49, 16, szProduct);
|
|
if (!STARTS_WITH_CI(szProduct, "ALOS-"))
|
|
return 0;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Apply normal handling... */
|
|
/* -------------------------------------------------------------------- */
|
|
CeosDefaultRecipe(volume, token);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Make sure this looks like the SIRC product we are expecting. */
|
|
/* -------------------------------------------------------------------- */
|
|
if (ImageDesc->BytesPerPixel != 18)
|
|
return 0;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Then fix up a few values. */
|
|
/* -------------------------------------------------------------------- */
|
|
ImageDesc->DataType = CEOS_TYP_PALSAR_COMPLEX_SHORT;
|
|
ImageDesc->NumChannels = 6;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Sanity checking */
|
|
/* -------------------------------------------------------------------- */
|
|
if (ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
|
|
ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
|
|
ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
|
|
ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
|
|
ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
ImageDesc->ImageDescValid = TRUE;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void GetCeosSARImageDesc(CeosSARVolume_t *volume)
|
|
{
|
|
Link_t *l_link;
|
|
RecipeFunctionData_t *rec_data;
|
|
int (*function)(CeosSARVolume_t * volume, const void *token);
|
|
|
|
if (RecipeFunctions == NULL)
|
|
{
|
|
RegisterRecipes();
|
|
}
|
|
|
|
if (RecipeFunctions == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
|
|
{
|
|
if (l_link->object)
|
|
{
|
|
rec_data = l_link->object;
|
|
function = rec_data->function;
|
|
if ((*function)(volume, rec_data->token))
|
|
{
|
|
CPLDebug("CEOS", "Using recipe '%s'.", rec_data->name);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset,
|
|
unsigned int length, int *value)
|
|
{
|
|
void *buffer;
|
|
char format[32];
|
|
|
|
buffer = HMalloc(length + 1);
|
|
|
|
switch (type)
|
|
{
|
|
case CEOS_REC_TYP_A:
|
|
snprintf(format, sizeof(format), "A%u", length);
|
|
GetCeosField(record, offset, format, buffer);
|
|
*value = atoi(buffer);
|
|
break;
|
|
case CEOS_REC_TYP_B:
|
|
snprintf(format, sizeof(format), "B%u", length);
|
|
#ifdef notdef
|
|
GetCeosField(record, offset, format, buffer);
|
|
if (length <= 4)
|
|
CeosToNative(value, buffer, length, length);
|
|
else
|
|
*value = 0;
|
|
#else
|
|
GetCeosField(record, offset, format, value);
|
|
#endif
|
|
break;
|
|
case CEOS_REC_TYP_I:
|
|
snprintf(format, sizeof(format), "I%u", length);
|
|
GetCeosField(record, offset, format, value);
|
|
break;
|
|
}
|
|
|
|
HFree(buffer);
|
|
}
|
|
|
|
static char *ExtractString(CeosRecord_t *record, unsigned int offset,
|
|
unsigned int length, char *string)
|
|
{
|
|
char format[12];
|
|
|
|
if (string == NULL)
|
|
{
|
|
string = HMalloc(length + 1);
|
|
}
|
|
|
|
snprintf(format, sizeof(format), "A%u", length);
|
|
|
|
GetCeosField(record, offset, format, string);
|
|
|
|
return string;
|
|
}
|
|
|
|
static int GetCeosStringType(const CeosStringType_t *CeosStringType,
|
|
const char *string)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; CeosStringType[i].String != NULL; i++)
|
|
{
|
|
if (strncmp(CeosStringType[i].String, string,
|
|
strlen(CeosStringType[i].String)) == 0)
|
|
{
|
|
return CeosStringType[i].Type;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|