float cal2amp(meta_parameters *meta, float incid, int sample, char *bandExt, float calValue) { double scaledPower, ampValue, invIncAngle; radiometry_t radiometry = meta->general->radiometry; if (radiometry >= r_SIGMA_DB && radiometry <= r_BETA_DB) scaledPower = pow(10, calValue/10.0); else if (radiometry >= r_SIGMA && radiometry <= r_BETA) scaledPower = calValue; else asfPrintError("Conversion requires radiometric values in input image.\n" "Radiometry: %s", radiometry2str(radiometry)); // Calculate according to the calibration data type if (meta->calibration->type == asf_cal) { // ASF style data (PP and SSP) if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) invIncAngle = 1.0; else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) invIncAngle = 1/cos(incid); else if (radiometry == r_BETA || radiometry == r_BETA_DB) invIncAngle = 1/sin(incid); asf_cal_params *p = meta->calibration->asf; double index = (double)sample*256./(double)(p->sample_count); int base = (int) index; double frac = index - base; double *noise = p->noise; double noiseValue = noise[base] + frac*(noise[base+1] - noise[base]); // Convert (amplitude) data number to scaled, noise-removed power //scaledPower = (p->a1*(inDn*inDn-p->a0*noiseValue) + p->a2)*invIncAngle; ampValue = sqrt((scaledPower/invIncAngle - p->a2)/p->a1 + p->a0*noiseValue); } else if (meta->calibration->type == asf_scansar_cal) { // ASF style ScanSar asf_scansar_cal_params *p = meta->calibration->asf_scansar; if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) invIncAngle = 1.0; else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) invIncAngle = 1/cos(incid); else if (radiometry == r_BETA || radiometry == r_BETA_DB) invIncAngle = 1/sin(incid); double look = 25.0; // FIXME: hack to get things compiled double index = (look-16.3)*10.0; double noiseValue; double *noise = p->noise; if (index <= 0) noiseValue = noise[0]; else if (index >= 255) noiseValue = noise[255]; else { // Use linear interpolation on noise array int base = (int)index; double frac = index - base; noiseValue = noise[base] + frac*(noise[base+1] - noise[base]); } // Convert (amplitude) data number to scaled, noise-removed power //scaledPower = (p->a1*(inDn*inDn-p->a0*noiseValue) + p->a2)*invIncAngle; ampValue = sqrt((scaledPower/invIncAngle - p->a2)/p->a1 + p->a0*noiseValue); } else if (meta->calibration->type == esa_cal) { // ESA style ERS and JERS data esa_cal_params *p = meta->calibration->esa; if (radiometry == r_BETA || radiometry == r_BETA_DB) { //scaledPower = inDn*inDn/p->k; ampValue = sqrt(scaledPower*p->k); } else if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) //scaledPower = inDn*inDn/p->k*sin(p->ref_incid*D2R)/sin(incidence_angle); ampValue = sqrt(scaledPower * p->k*sin(p->ref_incid*D2R)*sin(incid)); else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) { invIncAngle = 1/cos(incid); //scaledPower = //inDn*inDn/p->k*sin(p->ref_incid*D2R)/sin(incidence_angle)/invIncAngle; ampValue = sqrt(scaledPower*invIncAngle*sin(incid)*p->k/sin(p->ref_incid*D2R)); } } else if (meta->calibration->type == rsat_cal) { // CDPF style Radarsat data if (radiometry == r_BETA || radiometry == r_BETA_DB) invIncAngle = 1.0; if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) invIncAngle = 1/tan(incid); else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) invIncAngle = tan(incid); rsat_cal_params *p = meta->calibration->rsat; double a2; if (meta->calibration->rsat->focus) a2 = p->lut[0]; else if (sample < (p->samp_inc*(p->n-1))) { int i_low = sample/p->samp_inc; int i_up = i_low + 1; a2 = p->lut[i_low] + ((p->lut[i_up] - p->lut[i_low])*((sample/p->samp_inc) - i_low)); } else a2 = p->lut[p->n-1] + ((p->lut[p->n-1] - p->lut[p->n-2])*((sample/p->samp_inc) - p->n-1)); if (p->slc) //scaledPower = (inDn*inDn)/(a2*a2)*invIncAngle; ampValue = sqrt(scaledPower *a2*a2/invIncAngle); else //scaledPower = (inDn*inDn + p->a3)/a2*invIncAngle; ampValue = sqrt((scaledPower *a2/invIncAngle) - p->a3); } else if (meta->calibration->type == alos_cal) { // ALOS data if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) invIncAngle = 1.0; else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) invIncAngle = 1/cos(incid); else if (radiometry == r_BETA || radiometry == r_BETA_DB) invIncAngle = 1/sin(incid); alos_cal_params *p = meta->calibration->alos; double cf; if (strstr(bandExt, "HH")) cf = p->cf_hh; else if (strstr(bandExt, "HV")) cf = p->cf_hv; else if (strstr(bandExt, "VH")) cf = p->cf_vh; else if (strstr(bandExt, "VV")) cf = p->cf_vv; //scaledPower = pow(10, cf/10.0)*inDn*inDn*invIncAngle; ampValue = sqrt(scaledPower / invIncAngle / pow(10, cf/10.0)); } else if (meta->calibration->type == tsx_cal) { // TerraSAR-X if (radiometry == r_BETA || radiometry == r_BETA_DB) invIncAngle = 1.0; if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) invIncAngle = 1/tan(incid); else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) invIncAngle = tan(incid); double cf = meta->calibration->tsx->k; //scaledPower = cf*inDn*inDn*invIncAngle; ampValue = sqrt(scaledPower / (cf*invIncAngle)); } else // should never get here asfPrintError("Unknown calibration data type!\n"); return ampValue; }
int asf_calibrate(const char *inFile, const char *outFile, radiometry_t outRadiometry, int wh_scaleFlag) { meta_parameters *metaIn = meta_read(inFile); meta_parameters *metaOut = meta_read(inFile); if (!metaIn->calibration) { asfPrintError("This data cannot be calibrated, missing calibration block.\n"); } // Check for valid output radiometry if (outRadiometry == r_AMP || outRadiometry == r_POWER) asfPrintError("Invalid radiometry (%s) passed into calibration function!\n", radiometry2str(outRadiometry)); // Check whether output radiometry fits with Woods Hole scaling flag if (wh_scaleFlag && outRadiometry >= r_SIGMA && outRadiometry <= r_GAMMA) outRadiometry += 3; // This can only work if the image is in some SAR geometry if (metaIn->projection && metaIn->projection->type != SCANSAR_PROJECTION) asfPrintError("Can't apply calibration factors to map projected images\n" "(Amplitude or Power only)\n"); radiometry_t inRadiometry = metaIn->general->radiometry; asfPrintStatus("Calibrating %s image to %s image\n\n", radiometry2str(inRadiometry), radiometry2str(outRadiometry)); // FIXME: This function should be able to remap between different // radiometry projections. if (metaIn->general->radiometry != r_AMP) asfPrintError("Currently only AMPLITUDE as radiometry is supported!\n"); metaOut->general->radiometry = outRadiometry; int dbFlag = FALSE; if (outRadiometry >= r_SIGMA && outRadiometry <= r_GAMMA) metaOut->general->no_data = 0.0001; if (outRadiometry >= r_SIGMA_DB && outRadiometry <= r_GAMMA_DB) { metaOut->general->no_data = -40.0; dbFlag = TRUE; } if (metaIn->general->image_data_type != POLARIMETRIC_IMAGE) { if (outRadiometry == r_SIGMA || outRadiometry == r_SIGMA_DB) metaOut->general->image_data_type = SIGMA_IMAGE; else if (outRadiometry == r_BETA || outRadiometry == r_BETA_DB) metaOut->general->image_data_type = BETA_IMAGE; else if (outRadiometry == r_GAMMA || outRadiometry == r_GAMMA_DB) metaOut->general->image_data_type = GAMMA_IMAGE; } if (wh_scaleFlag) metaOut->general->data_type = ASF_BYTE; char *input = appendExt(inFile, ".img"); char *output = appendExt(outFile, ".img"); FILE *fpIn = FOPEN(input, "rb"); FILE *fpOut = FOPEN(output, "wb"); int dualpol = strncmp_case(metaIn->general->mode, "FBD", 3) == 0 ? 1 : 0; int band_count = metaIn->general->band_count; int sample_count = metaIn->general->sample_count; int line_count = metaIn->general->line_count; char **bands = extract_band_names(metaIn->general->bands, band_count); float *bufIn = (float *) MALLOC(sizeof(float)*sample_count); float *bufOut = (float *) MALLOC(sizeof(float)*sample_count); float *bufIn2 = NULL, *bufOut2 = NULL, *bufOut3 = NULL; if (dualpol && wh_scaleFlag) { bufIn2 = (float *) MALLOC(sizeof(float)*sample_count); bufOut2 = (float *) MALLOC(sizeof(float)*sample_count); bufOut3 = (float *) MALLOC(sizeof(float)*sample_count); metaOut->general->band_count = 3; sprintf(metaOut->general->bands, "%s,%s,%s-%s", bands[0], bands[1], bands[0], bands[1]); } int ii, jj, kk; float cal_dn, cal_dn2; double incid; if (dualpol && wh_scaleFlag) { metaOut->general->image_data_type = RGB_STACK; for (ii=0; ii<line_count; ii++) { get_band_float_line(fpIn, metaIn, 0, ii, bufIn); get_band_float_line(fpIn, metaIn, 1, ii, bufIn2); for (jj=0; jj<sample_count; jj++) { // Taking the remapping of other radiometries out for the moment //if (inRadiometry >= r_SIGMA && inRadiometry <= r_BETA_DB) //bufIn[jj] = cal2amp(metaIn, incid, jj, bands[kk], bufIn[jj]); incid = meta_incid(metaIn, ii, jj); cal_dn = get_cal_dn(metaOut, incid, jj, bufIn[jj], bands[0], dbFlag); cal_dn2 = get_cal_dn(metaOut, incid, jj, bufIn2[jj], bands[1], dbFlag); if (FLOAT_EQUIVALENT(cal_dn, metaIn->general->no_data) || cal_dn == cal_dn2) { bufOut[jj] = 0; bufOut2[jj] = 0; bufOut3[jj] = 0; } else { bufOut[jj] = (cal_dn + 31) / 0.15 + 1.5; bufOut2[jj] = (cal_dn2 + 31) / 0.15 + 1.5; bufOut3[jj] = bufOut[jj] - bufOut2[jj]; } } put_band_float_line(fpOut, metaOut, 0, ii, bufOut); put_band_float_line(fpOut, metaOut, 1, ii, bufOut2); put_band_float_line(fpOut, metaOut, 2, ii, bufOut3); asfLineMeter(ii, line_count); } } else { for (kk=0; kk<band_count; kk++) { for (ii=0; ii<line_count; ii++) { get_band_float_line(fpIn, metaIn, kk, ii, bufIn); for (jj=0; jj<sample_count; jj++) { // Taking the remapping of other radiometries out for the moment //if (inRadiometry >= r_SIGMA && inRadiometry <= r_BETA_DB) //bufIn[jj] = cal2amp(metaIn, incid, jj, bands[kk], bufIn[jj]); if (strstr(bands[kk], "PHASE") == NULL) { incid = meta_incid(metaIn, ii, jj); cal_dn = get_cal_dn(metaOut, incid, jj, bufIn[jj], bands[kk], dbFlag); if (wh_scaleFlag) { if (FLOAT_EQUIVALENT(cal_dn, metaIn->general->no_data)) bufOut[jj] = 0; else bufOut[jj] = (cal_dn + 31) / 0.15 + 1.5; } else bufOut[jj] = cal_dn; } else // PHASE band, do nothing bufOut[jj] = bufIn[jj]; } put_band_float_line(fpOut, metaOut, kk, ii, bufOut); asfLineMeter(ii, line_count); } if (kk==0) sprintf(metaOut->general->bands, "%s-%s", radiometry2str(outRadiometry), bands[kk]); else { char tmp[255]; sprintf(tmp, ",%s-%s", radiometry2str(outRadiometry), bands[kk]); strcat(metaOut->general->bands, tmp); } } } meta_write(metaOut, outFile); meta_free(metaIn); meta_free(metaOut); FREE(bufIn); FREE(bufOut); if (dualpol) { FREE(bufIn2); FREE(bufOut2); FREE(bufOut3); } for (kk=0; kk<band_count; ++kk) FREE(bands[kk]); FREE(bands); FCLOSE(fpIn); FCLOSE(fpOut); FREE(input); FREE(output); return FALSE; }