ISCE_INSAR/contrib/alos2proc/src/resamp.c

402 lines
11 KiB
C

//////////////////////////////////////
// Cunren Liang, NASA JPL/Caltech
// Copyright 2017
//////////////////////////////////////
//update: add default value azpos_off = 0.0; 12-DEC-2019
//update: normalization of resampling kernals. 12-DEC-2019
#include "resamp.h"
#define SWAP4(a) (*(unsigned int *)&(a) = (((*(unsigned int *)&(a) & 0x000000ff) << 24) | ((*(unsigned int *)&(a) & 0x0000ff00) << 8) | ((*(unsigned int *)&(a) >> 8) & 0x0000ff00) | ((*(unsigned int *)&(a) >> 24) & 0x000000ff)))
void normalize_kernel(float *kernel, long start_index, long end_index);
int resamp(char *slc2, char *rslc2, char *rgoff_file, char *azoff_file, int nrg1, int naz1, int nrg2, int naz2, float prf, float *dopcoeff, float *rgcoef, float *azcoef, float azpos_off, int byteorder, long imageoffset, long lineoffset, int verbose){
/*
mandatory:
slc2: secondary image
rslc2: resampled secondary image
rgoff_file: range offset file. if no range offset file, specify fake
azoff_file: azimuth offset file. if no azimuth offset file, specify fake
nrg1: number of columns in reference image
naz1: number of lines in reference image
nrg2: number of columns in secondary image
naz2: number of lines in secondary image
prf: PRF of secondary image
dopcoeff[0]-[3]: Doppler centroid frequency coefficents
optional:
rgcoef[0]-[9]: range offset polynomial coefficents. First of two fit results of resamp_roi
azcoef[0]-[9]: azimuth offset polynomial coefficents. First of two fit results of resamp_roi
azpos_off: azimuth position offset. Azimuth line number (column 3) of first offset in culled offset file
byteorder: (0) LSB, little endian; (1) MSB, big endian of intput file
imageoffset: offset from start of the image of input file
lineoffset: length of each line of input file
*/
FILE *slc2fp;
FILE *rslc2fp;
FILE *rgoffp;
FILE *azoffp;
int rgflag;
int azflag;
//int nrg1;
//int naz1;
//int nrg2;
//int naz2;
//float prf;
//float dopcoeff[4];
//float rgcoef[10];
//float azcoef[10];
//float azpos_off;
float beta;
int n;
int m;
int interp_method;
int edge_method;
float rgpos;
float azpos;
float rgoff;
float azoff;
float rgoff1;
float azoff1;
float *rgoff2;
float *azoff2;
float rg2;
float az2;
int rgi2;
int azi2;
float rgf;
float azf;
int rgfn;
int azfn;
int hnm;
int hn;
float *sincc;
float *kaiserc;
float *kernel;
float *rgkernel;
float *azkernel;
fcomplex *azkernel_fc;
fcomplex *rgrs;
fcomplex *azca;
fcomplex *rgrsb;
fcomplex *azrs;
float *dop;
float dopx;
fcomplex **inb;
int i, j, k, k1, k2;
int tmp1, tmp2;
int zero_flag;
float ftmp1, ftmp2;
fcomplex fctmp1, fctmp2;
beta = 2.5;
n = 9;
m = 10000;
interp_method = 0;
edge_method = 0;
slc2fp = openfile(slc2, "rb");
rslc2fp = openfile(rslc2, "wb");
rgflag = 0;
azflag = 0;
if (strcmp(rgoff_file, "fake") == 0){
rgflag = 0;
printf("range offset file not provided\n");
}
else{
rgflag = 1;
rgoffp = openfile(rgoff_file, "rb");
}
if (strcmp(azoff_file, "fake") == 0){
azflag = 0;
printf("azimuth offset file not provided\n");
}
else{
azflag = 1;
azoffp = openfile(azoff_file, "rb");
}
//nrg1 = atoi(argv[5]);
//naz1 = atoi(argv[6]);
//nrg2 = atoi(argv[7]);
//naz2 = atoi(argv[8]);
//prf = atof(argv[9]);
//for(i = 0; i < 4; i++){
// dopcoeff[i] = atof(argv[10+i]);
//}
//for(i = 0; i < 10; i++){
// if(argc > 14 + i)
// rgcoef[i] = atof(argv[14+i]);
// else
// rgcoef[i] = 0.0;
//}
//for(i = 0; i < 10; i++){
// if(argc > 24 + i)
// azcoef[i] = atof(argv[24+i]);
// else
// azcoef[i] = 0.0;
//}
//if(argc > 34)
// azpos_off = atof(argv[34]);
//else
// azpos_off = 0.0;
if(verbose != 0){
printf("\n\ninput parameters:\n");
printf("slc2: %s\n", slc2);
printf("rslc2: %s\n", rslc2);
printf("rgoff_file: %s\n", rgoff_file);
printf("azoff_file: %s\n\n", azoff_file);
printf("nrg1: %d\n", nrg1);
printf("naz1: %d\n", naz1);
printf("nrg2: %d\n", nrg2);
printf("naz2: %d\n\n", naz2);
printf("prf: %f\n\n", prf);
for(i = 0; i < 4; i++){
printf("dopcoeff[%d]: %e\n", i, dopcoeff[i]);
}
printf("\n");
for(i = 0; i < 10; i++){
printf("rgcoef[%d]: %e\n", i, rgcoef[i]);
}
printf("\n");
for(i = 0; i < 10; i++){
printf("azcoef[%d]: %e\n", i, azcoef[i]);
}
printf("\n");
printf("azpos_off: %f\n\n", azpos_off);
if(byteorder == 0){
printf("inputfile byte order: little endian\n");
}
else{
printf("inputfile byte order: big endian\n");
}
printf("input file image offset [byte]: %ld\n", imageoffset);
printf("input file line offset [byte]: %ld\n", lineoffset);
}
if(imageoffset < 0){
fprintf(stderr, "image offset must be >= 0\n");
exit(1);
}
if(lineoffset < 0){
fprintf(stderr, "lineoffset offset must be >= 0\n");
exit(1);
}
hn = n / 2;
hnm = n * m / 2;
rgoff2 = array1d_float(nrg1);
azoff2 = array1d_float(nrg1);
sincc = vector_float(-hnm, hnm);
kaiserc = vector_float(-hnm, hnm);
kernel = vector_float(-hnm, hnm);
rgkernel = vector_float(-hn, hn);
azkernel = vector_float(-hn, hn);
azkernel_fc = vector_fcomplex(-hn, hn);
rgrs = vector_fcomplex(-hn, hn);
azca = vector_fcomplex(-hn, hn);
rgrsb = vector_fcomplex(-hn, hn);
azrs = array1d_fcomplex(nrg1);
dop = array1d_float(nrg2);
inb = array2d_fcomplex(naz2, nrg2);
sinc(n, m, sincc);
kaiser(n, m, kaiserc, beta);
for(i = -hnm; i <= hnm; i++)
kernel[i] = kaiserc[i] * sincc[i];
if(verbose != 0)
printf("\n");
for(i = 0; i < nrg2; i++){
dop[i] = dopcoeff[0] + dopcoeff[1] * i + dopcoeff[2] * i * i + dopcoeff[3] * i * i * i;
//get rid of this bad convention from roi_pac
//dop[i] *= prf;
if(verbose != 0)
if(i % 500 == 0)
printf("range sample: %5d, doppler centroid frequency: %8.2f Hz\n", i, dop[i]);
}
if(verbose != 0)
printf("\n");
//////////////////////////////////////////////////////////////////////////////////////////////
//skip image header
fseek(slc2fp, imageoffset, SEEK_SET);
for(i = 0; i < naz2; i++){
if(i!=0)
fseek(slc2fp, lineoffset - (size_t)nrg2 * sizeof(fcomplex), SEEK_CUR);
readdata((fcomplex *)inb[i], (size_t)nrg2 * sizeof(fcomplex), slc2fp);
}
//read image data
//if(lineoffset == 0){
// readdata((fcomplex *)inb[0], (size_t)naz2 * (size_t)nrg2 * sizeof(fcomplex), slc2fp);
//}
//else{
// for(i = 0; i < naz2; i++){
// fseek(slc2fp, lineoffset, SEEK_CUR);
// readdata((fcomplex *)inb[i], (size_t)nrg2 * sizeof(fcomplex), slc2fp);
// }
//}
//swap bytes
if(byteorder!=0){
printf("swapping bytes...\n");
for(i = 0; i < naz2; i++)
for(j = 0; j < nrg2; j++){
SWAP4(inb[i][j].re);
SWAP4(inb[i][j].im);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
for(i = 0; i < naz1; i++){
if((i + 1) % 100 == 0)
fprintf(stderr,"processing line: %6d of %6d\r", i+1, naz1);
if (rgflag == 1){
readdata((float *)rgoff2, nrg1 * sizeof(float), rgoffp);
}
if (azflag == 1){
readdata((float *)azoff2, nrg1 * sizeof(float), azoffp);
}
for(j = 0; j < nrg1; j++){
azrs[j].re = 0.0;
azrs[j].im = 0.0;
}
for(j = 0; j < nrg1; j++){
rgpos = j;
azpos = i - azpos_off;
rgoff1 = rgcoef[0] + azpos*(rgcoef[2] + \
azpos*(rgcoef[5] + azpos*rgcoef[9])) + \
rgpos*(rgcoef[1] + rgpos*(rgcoef[4] + \
rgpos*rgcoef[8])) + \
rgpos*azpos*(rgcoef[3] + azpos*rgcoef[6] + \
rgpos*rgcoef[7]);
azoff1 = azcoef[0] + azpos*(azcoef[2] + \
azpos*(azcoef[5] + azpos*azcoef[9])) + \
rgpos*(azcoef[1] + rgpos*(azcoef[4] + \
rgpos*azcoef[8])) + \
rgpos*azpos*(azcoef[3] + azpos*azcoef[6] + \
rgpos*azcoef[7]);
if (rgflag == 1){
rgoff = rgoff1 + rgoff2[j];
}
else{
rgoff = rgoff1;
}
if (azflag == 1){
azoff = azoff1 + azoff2[j];
}
else{
azoff = azoff1;
}
rg2 = j + rgoff;
az2 = i + azoff;
rgi2 = roundfi(rg2);
azi2 = roundfi(az2);
rgf = rg2 - rgi2;
azf = az2 - azi2;
rgfn = roundfi(rgf * m);
azfn = roundfi(azf * m);
for(k = -hn; k <= hn; k++){
tmp1 = k * m - rgfn;
tmp2 = k * m - azfn;
if(tmp1 > hnm) tmp1 = hnm;
if(tmp2 > hnm) tmp2 = hnm;
if(tmp1 < -hnm) tmp1 = -hnm;
if(tmp2 < -hnm) tmp2 = -hnm;
rgkernel[k] = kernel[tmp1];
azkernel[k] = kernel[tmp2];
}
normalize_kernel(rgkernel, -hn, hn);
normalize_kernel(azkernel, -hn, hn);
for(k1 = -hn; k1 <= hn; k1++){
rgrs[k1].re = 0.0;
rgrs[k1].im = 0.0;
if(edge_method == 0){
if(azi2 < hn || azi2 > naz2 - 1 - hn || rgi2 < hn || rgi2 > nrg2 - 1 - hn){
continue;
}
}
else if(edge_method == 1){
if(azi2 < 0 || azi2 > naz2 - 1 || rgi2 < 0 || rgi2 > nrg2 - 1){
continue;
}
}
else{
if(azi2 < -hn || azi2 > naz2 - 1 + hn || rgi2 < -hn || rgi2 > nrg2 - 1 + hn){
continue;
}
}
for(k2 = -hn; k2 <= hn; k2++){
if(azi2 + k1 < 0 || azi2 + k1 > naz2 - 1 || rgi2 + k2 < 0 || rgi2 + k2 > nrg2 - 1)
continue;
rgrs[k1].re += inb[azi2 + k1][rgi2 + k2].re * rgkernel[k2];
rgrs[k1].im += inb[azi2 + k1][rgi2 + k2].im * rgkernel[k2];
}
}
for(k = -hn; k <= hn; k++){
if(rgrs[k].re == 0.0 && rgrs[k].im == 0.0)
continue;
dopx = dopcoeff[0] + dopcoeff[1] * rg2 + dopcoeff[2] * rg2 * rg2 + dopcoeff[3] * rg2 * rg2 * rg2;
//get rid of this bad convention from roi_pac
//dopx *= prf;
ftmp1 = 2.0 * PI * dopx * k / prf;
azca[k].re = cos(ftmp1);
azca[k].im = sin(ftmp1);
if(interp_method == 0){
rgrsb[k] = cmul(rgrs[k], cconj(azca[k]));
azrs[j].re += rgrsb[k].re * azkernel[k];
azrs[j].im += rgrsb[k].im * azkernel[k];
}
else{
azkernel_fc[k].re = azca[k].re * azkernel[k];
azkernel_fc[k].im = azca[k].im * azkernel[k];
azrs[j] = cadd(azrs[j], cmul(rgrs[k], azkernel_fc[k]));
}
}
if(interp_method == 0){
ftmp1 = 2.0 * PI * dopx * azf / prf;
fctmp1.re = cos(ftmp1);
fctmp1.im = sin(ftmp1);
azrs[j] = cmul(azrs[j], fctmp1);
}
}
writedata((fcomplex *)azrs, nrg1 * sizeof(fcomplex), rslc2fp);
}
fprintf(stderr,"processing line: %6d of %6d\n", naz1, naz1);
free_array1d_float(rgoff2);
free_array1d_float(azoff2);
free_vector_float(sincc, -hnm, hnm);
free_vector_float(kaiserc, -hnm, hnm);
free_vector_float(kernel, -hnm, hnm);
free_vector_float(rgkernel, -hn, hn);
free_vector_float(azkernel, -hn, hn);
free_vector_fcomplex(azkernel_fc, -hn, hn);
free_vector_fcomplex(rgrs, -hn, hn);
free_vector_fcomplex(azca, -hn, hn);
free_vector_fcomplex(rgrsb, -hn, hn);
free_array1d_fcomplex(azrs);
free_array1d_float(dop);
free_array2d_fcomplex(inb);
fclose(slc2fp);
fclose(rslc2fp);
if (rgflag == 1){
fclose(rgoffp);
}
if (azflag == 1){
fclose(azoffp);
}
return 0;
}
void normalize_kernel(float *kernel, long start_index, long end_index){
double sum;
long i;
sum = 0.0;
for(i = start_index; i <= end_index; i++)
sum += kernel[i];
if(sum!=0)
for(i = start_index; i <= end_index; i++)
kernel[i] /= sum;
}