gdal/frmts/ceos2/ceosrecipe.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;
}