void deskew(const char *infile, const char *outfile) { meta_parameters *meta = meta_read(infile); int nl = meta->general->line_count; int np = meta->general->sample_count; int nb = meta->general->band_count; char **band_name = extract_band_names(meta->general->bands, nb); int band, line, samp, deskewed = meta->sar->deskewed != 0; if (!meta->sar) asfPrintError("Cannot deskew data without a sar block!\n"); char *tmp_outfile; int do_rename = FALSE; if (strcmp(infile, outfile) == 0 && nb>1) { // user wants to deskew in-place // we can't actually do that on multi-band data, too much to keep in memory // use a temporary file, then clobber input file tmp_outfile = appendToBasename(outfile, "_tmp"); do_rename = TRUE; } else { // normal case: either // 1) single-band in-place deskew // 2) not in-place deskew (single or multi) tmp_outfile = STRDUP(outfile); } // calculate the amount of shift necessary double fac = calc_shift(meta, 0, 0); // Not sure if we need this or not... //fac *= meta->general->x_pixel_size / meta->general->y_pixel_size; // the "lower" array stores the required shifts, indexed by column // (the amount of shift is row-independent) int *lower = MALLOC(np * sizeof(int)); for (samp=0; samp<np; ++samp) lower[samp] = (int) floor(fac*(double)samp); if (meta->sar->deskewed) { asfPrintStatus("Data is already deskewed.\n"); } else { asfPrintStatus("Far-range shift amount: "); if (lower[np-1] > 0) asfPrintStatus("%d pixels down.\n", lower[np-1]); else asfPrintStatus("%d pixels up.\n", -lower[np-1]); } float *ibuf = MALLOC(np * sizeof(float)); float *obuf = CALLOC(np*nl, sizeof(float)); FILE *fpi = fopenImage(infile, "rb"); for (band=0; band<nb; ++band) { if (nb>1) asfPrintStatus("Deskewing band: %s\n", band_name[band]); // apply deskewing to this band for (line=0; line<nl; ++line) { get_float_line(fpi, meta, line + nl*band, ibuf); for (samp=0; samp<np; ++samp) { int out_line = deskewed ? line : line + lower[samp]; if (out_line >= 0 && out_line < nl) obuf[out_line*np+samp] = ibuf[samp]; } asfLineMeter(line,nl); } // write out this band FILE *fpo = fopenImage(tmp_outfile, band>0 ? "ab" : "wb"); put_float_lines(fpo, meta, band*nl, nl, obuf); FCLOSE(fpo); } FCLOSE(fpi); FREE(obuf); FREE(ibuf); FREE(lower); // if we output to a temporary file, clobber the input if (do_rename) { char *tmp_outfile_img = appendExt(tmp_outfile, ".img"); char *outfile_img = appendExt(outfile, ".img"); //printf("Renaming: %s -> %s\n", tmp_outfile_img, outfile_img); rename(tmp_outfile_img, outfile_img); FREE(tmp_outfile_img); FREE(outfile_img); } FREE(tmp_outfile); // only need to update the deskewed flag in the metadata meta->sar->deskewed = 1; meta_write(meta, outfile); meta_free(meta); }
int main(int argc, char **argv) { double min, max; /* Minimum & maximum sample values */ double sum_of_samples=0.0; /* Sum of all samples accounted for */ double sum_of_squared_samples=0.0; /* Sum of all squared samples accounted for*/ double trim_fraction; /* Fraction used to trim the histogram */ int ii; /* Loop index */ long samples_counted=0; /* Number of all samples accounted for */ float *data_line; /* Buffer for a line of samples */ long line, sample; /* Line and sample indices */ long num_lines, num_samples; /* Number of lines and samples */ int percent_complete=0; /* Percent of data sweep completed */ int overmeta_flag=FALSE; /* If TRUE write over current .meta file */ int overstat_flag=FALSE; /* If TRUE write over current .stat file */ int nometa_flag=FALSE; /* If TRUE do not write .meta file */ int nostat_flag=FALSE; /* If TRUE do not write .stat file */ int mask_flag=FALSE; /* TRUE if user specifies a mask value */ int trim_flag=FALSE; /* If TRUE trim histogram */ double mask=NAN; /* Value to ignore while caculating stats*/ char meta_name[261]; /* Meta file name */ meta_parameters *meta; /* SAR meta data structure */ char sar_name[256]; /* SAR file name WITH extention */ FILE *sar_file; /* SAR data file pointer to take stats on*/ stat_parameters *stats; /* Statistics structure */ char stat_name[261]; /* Stats file name */ extern int currArg; /* Pre-initialized to 1 */ /* We initialize these to a magic number for checking. */ long start_line = -1; /* Window starting line. */ long start_sample = -1; /* Window starting sample. */ long window_height = -1; /* Window height in lines. */ long window_width = -1; /* Window width in samples. */ /* parse command line */ handle_license_and_version_args(argc, argv, "stats"); logflag=quietflag=FALSE; while (currArg < (argc-1)) { char *key = argv[currArg++]; if (strmatch(key,"-quiet")) { quietflag=TRUE; } else if (strmatch(key,"-log")) { CHECK_ARG(1); strcpy(logFile,GET_ARG(1)); fLog = FOPEN(logFile, "a"); logflag=TRUE; } else if (strmatch(key,"-mask")) { CHECK_ARG(1); mask = atof(GET_ARG(1)); mask_flag=TRUE; } else if (strmatch(key,"-overmeta")) { overmeta_flag=TRUE; } else if (strmatch(key,"-overstat")) { overstat_flag=TRUE; } else if (strmatch(key,"-nometa")) { nometa_flag=TRUE; } else if (strmatch(key,"-nostat")) { nostat_flag=TRUE; } else if (strmatch(key,"-startline")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ start_line = atol(GET_ARG(1)); if ( start_line < 0 ) { printf("error: -startline argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-startsample")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ start_sample = atol(GET_ARG(1)); if ( start_sample < 0 ) { printf("error: -startsample argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-width")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ window_width = atol(GET_ARG(1)); if ( window_width < 0 ) { printf("error: -width argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-height")) { CHECK_ARG(1); nometa_flag=TRUE; /* Implied. */ window_height = atol(GET_ARG(1)); if ( window_height < 0 ) { printf("error: -height argument must be greater than or equal to zero\n"); usage(argv[0]); } } else if (strmatch(key,"-trim")) { CHECK_ARG(1); trim_flag=TRUE; /* Implied. */ trim_fraction = atof(GET_ARG(1)); } else {printf( "\n**Invalid option: %s\n",argv[currArg-1]); usage(argv[0]);} } if ((argc-currArg)<1) {printf("Insufficient arguments.\n"); usage(argv[0]);} strcpy (sar_name, argv[currArg]); char *ext = findExt(sar_name); if (ext == NULL || strcmp("IMG", uc(ext)) != 0) { strcpy(sar_name, appendExt(sar_name, ".img")); } create_name(meta_name, sar_name, ".meta"); create_name(stat_name, sar_name, ".stat"); printf("\nProgram: stats\n\n"); if (logflag) { fprintf(fLog, "\nProgram: stats\n\n"); } printf("\nCalculating statistics for %s\n\n", sar_name); if (logflag) { fprintf(fLog,"\nCalculating statistics for %s\n\n", sar_name); } meta = meta_read(meta_name); num_lines = meta->general->line_count; num_samples = meta->general->sample_count; if ( start_line == -1 ) start_line = 0; if ( start_line > num_lines ) { printf("error: -startline argument is larger than index of last line in image\n"); exit(EXIT_FAILURE); } if ( start_sample == -1 ) start_sample = 0; if ( start_sample > num_samples ) { printf("error: -startsample argument is larger than index of last sample in image\n"); exit(EXIT_FAILURE); } if ( window_height == -1 ) window_height = num_lines; if ( start_line + window_height > num_lines ) { printf("warning: window specified with -startline, -height options doesn't fit in image\n"); } if ( window_width == -1 ) window_width = num_samples; if ( start_sample + window_width > num_samples ) { printf("warning: window specified with -startsample, -width options doesn't fit in image\n"); } /* Make sure we don't over write any files that we don't want to */ if (meta->stats && !overmeta_flag && !nometa_flag) { printf(" ** The meta file already has a populated statistics structure.\n" " ** If you want to run this program and replace that structure,\n" " ** then use the -overmeta option to do so. If you want to run\n" " ** this program, but don't want to replace the structure, use\n" " ** the -nometa option.\n"); if (logflag) { fprintf(fLog, " ** The meta file already has a populated statistics structure.\n" " ** If you want to run this program and replace that structure,\n" " ** then use the -overmeta option to do so. If you want to run\n" " ** this program, but don't want to replace the structure, use\n" " ** the -nometa option.\n"); } exit(EXIT_FAILURE); } if (fileExists(stat_name) && !overstat_flag && !nostat_flag) { printf(" ** The file, %s, already exists. If you want to\n" " ** overwrite it, then use the -overstat option to do so.\n" " ** If you want to run the progam but don't want to write\n" " ** over the current file, then use the -nostat option.\n", stat_name); if (logflag) { fprintf(fLog, " ** The file, %s, already exists. If you want to\n" " ** overwrite it, then use the -overstat option to do so.\n" " ** If you want to run the progam but don't want to write\n" " ** over the current file, then use the -nostat option.\n", stat_name); } exit(EXIT_FAILURE); } /* Let user know the window in which the stats will be taken */ if ((start_line!=0) || (start_sample!=0) || (window_height!=num_lines) || (window_width!=num_samples)) { if (!quietflag) { printf("Taking statistics on a window with upper left corner (%ld,%ld)\n" " and lower right corner (%ld,%ld)\n", start_sample, start_line, window_width+start_sample, window_height+start_line); } if (logflag && !quietflag) { fprintf(fLog, "Taking statistics on a window with upper left corner (%ld,%ld)\n" " and lower right corner (%ld,%ld)\n", start_sample, start_line, window_width+start_sample, window_height+start_line); } } /* Allocate line buffer */ data_line = (float *)MALLOC(sizeof(float)*num_samples); if (meta->stats) FREE(meta->stats); if (meta->general->band_count <= 0) { printf(" ** Band count in the existing data is missing or less than zero.\nDefaulting to one band.\n"); if (logflag) { fprintf(fLog, " ** Band count in the existing data is missing or less than zero.\nDefaulting to one band.\n"); } meta->general->band_count = 1; } meta->stats = meta_statistics_init(meta->general->band_count); if (!meta->stats) { printf(" ** Cannot allocate memory for statistics data structures.\n"); if (logflag) { fprintf(fLog, " ** Cannot allocate memory for statistics data structures.\n"); } exit(EXIT_FAILURE); } stats = (stat_parameters *)MALLOC(sizeof(stat_parameters) * meta->stats->band_count); if (!stats) { printf(" ** Cannot allocate memory for statistics data structures.\n"); if (logflag) { fprintf(fLog, " ** Cannot allocate memory for statistics data structures.\n"); } exit(EXIT_FAILURE); } int band; long band_offset; for (band = 0; band < meta->stats->band_count; band++) { /* Find min, max, and mean values */ if (!quietflag) printf("\n"); if (logflag && !quietflag) fprintf(fLog,"\n"); min = 100000000; max = -100000000; sum_of_samples=0.0; sum_of_squared_samples=0.0; percent_complete=0; band_offset = band * meta->general->line_count; sar_file = FOPEN(sar_name, "r"); for (line=start_line+band_offset; line<start_line+window_height+band_offset; line++) { if (!quietflag) asfPercentMeter((float)(line-start_line-band_offset)/(float)(window_height-start_line)); get_float_line(sar_file, meta, line, data_line); for (sample=start_sample; sample<start_sample+window_width; sample++) { if ( mask_flag && FLOAT_EQUIVALENT(data_line[sample],mask) ) continue; if (data_line[sample] < min) min=data_line[sample]; if (data_line[sample] > max) max=data_line[sample]; sum_of_samples += data_line[sample]; sum_of_squared_samples += SQR(data_line[sample]); samples_counted++; } } if (!quietflag) asfPercentMeter(1.0); // if (!quietflag) printf("\rFirst data sweep: 100%% complete.\n"); FCLOSE(sar_file); stats[band].min = min; stats[band].max = max; stats[band].upper_left_line = start_line; stats[band].upper_left_samp = start_sample; stats[band].lower_right_line = start_line + window_height; stats[band].lower_right_samp = start_sample + window_width; stats[band].mask = mask; stats[band] = calc_hist(stats[band], sar_name, band, meta, sum_of_samples, samples_counted, mask_flag); /* Remove outliers and trim the histogram by resetting the minimum and and maximum */ if (trim_flag) { register int sum=0, num_pixels, minDex=0, maxDex=255; double overshoot, width; num_pixels = (int)(samples_counted*trim_fraction); minDex = 0; while (sum < num_pixels) sum += stats[band].histogram[minDex++]; if (minDex-1>=0) overshoot = (double)(num_pixels-sum)/stats[band].histogram[minDex-1]; else overshoot = 0; stats[band].min = (minDex-overshoot-stats[band].offset)/stats[band].slope; sum=0; while (sum < num_pixels) sum += stats[band].histogram[maxDex--]; if (maxDex+1<256) overshoot = (double)(num_pixels-sum)/stats[band].histogram[maxDex+1]; else overshoot = 0; stats[band].max = (maxDex+1+overshoot-stats[band].offset)/stats[band].slope; /* Widening the range for better visual effect */ width = (stats[band].max-stats[band].min)*(1/(1.0-2*trim_fraction)-1); stats[band].min -= width/2; stats[band].max += width/2; /* Couple useful corrections borrowed from SARview */ if ((stats[band].max-stats[band].min) < 0.01*(max-min)) { stats[band].max = max; stats[band].min = min; } if (min == 0.0) stats[band].min=0.0; if (stats[band].min == stats[band].max) stats[band].max = stats[band].min + MICRON; stats[band].slope = 255.0/(stats[band].max-stats[band].min); stats[band].offset = -stats[band].slope*stats[band].min; stats[band] = calc_hist(stats[band], sar_name, band, meta, sum_of_samples, samples_counted, mask_flag); } } if(data_line)FREE(data_line); /* Populate meta->stats structure */ char **band_names = NULL; if (meta_is_valid_string(meta->general->bands) && strlen(meta->general->bands) && meta->general->band_count > 0) { band_names = extract_band_names(meta->general->bands, meta->general->band_count); } else { if (meta->general->band_count <= 0) meta->general->band_count = 1; band_names = (char **) MALLOC (meta->general->band_count * sizeof(char *)); int i; for (i=0; i<meta->general->band_count; i++) { band_names[i] = (char *) MALLOC (64 * sizeof(char)); sprintf(band_names[i], "%02d", i); } } int band_no; for (band_no = 0; band_no < meta->stats->band_count; band_no++) { strcpy(meta->stats->band_stats[band_no].band_id, band_names[band_no]); meta->stats->band_stats[band_no].min = stats[band_no].min; meta->stats->band_stats[band_no].max = stats[band_no].max; meta->stats->band_stats[band_no].mean = stats[band_no].mean; meta->stats->band_stats[band_no].rmse = stats[band_no].rmse; meta->stats->band_stats[band_no].std_deviation = stats[band_no].std_deviation; meta->stats->band_stats[band_no].mask = stats[band_no].mask; } if (band_names) { int i; for (i=0; i<meta->general->band_count; i++) { if (band_names[i]) FREE (band_names[i]); } FREE(band_names); } /* Print findings to the screen (and log file if applicable)*/ if (!quietflag) { printf("\n"); printf("Statistics found:\n"); if (mask_flag) { printf("Used mask %-16.11g\n",mask); } printf("Number of bands: %d\n", meta->stats->band_count); for (band=0; band<meta->stats->band_count; band++) { printf("\n\nBand name = \"%s\"\n", meta->stats->band_stats[band].band_id); printf("Minimum = %-16.11g\n",stats[band].min); printf("Maximum = %-16.11g\n",stats[band].max); printf("Mean = %-16.11g\n",stats[band].mean); printf("Root mean squared error = %-16.11g\n", stats[band].rmse); printf("Standard deviation = %-16.11g\n", stats[band].std_deviation); printf("\n"); printf("Data fit to [0..255] using equation: byte = %g * sample + %g\n", stats[band].slope, stats[band].offset); if (trim_flag) printf("Trimming fraction = %.3g\n", trim_fraction); printf("\n"); printf("Histogram:\n"); for (ii=0; ii<256; ii++) { if (ii%8 == 0) { printf("%s%3i-%3i:", (ii==0) ? "" : "\n", ii, ii+7); } printf(" %8i", stats[band].histogram[ii]); } printf("\n"); } } if (logflag && !quietflag) { fprintf(fLog,"Statistics found:\n"); if (mask_flag) { fprintf(fLog,"Used mask %-16.11g\n",mask); } fprintf(fLog,"Number of bands: %d\n", meta->stats->band_count); for (band=0; band<meta->stats->band_count; band++) { fprintf(fLog,"\n\nBand name = \"%s\"\n", meta->stats->band_stats[band].band_id); fprintf(fLog,"Minimum = %-16.11g\n",stats[band].min); fprintf(fLog,"Maximum = %-16.11g\n",stats[band].max); fprintf(fLog,"Mean = %-16.11g\n",stats[band].mean); fprintf(fLog,"Root mean squared error = %-16.11g\n", stats[band].rmse); fprintf(fLog,"Standard deviation = %-16.11g\n", stats[band].std_deviation); fprintf(fLog,"\n"); fprintf(fLog,"Data fit to [0..255] using equation: byte = %g * sample + %g\n", stats[band].slope, stats[band].offset); if (trim_flag) fprintf(fLog,"Trimming fraction = %.3g\n", trim_fraction); fprintf(fLog,"\n"); fprintf(fLog,"Histogram:\n"); for (ii=0; ii<256; ii++) { if (ii%8 == 0) { fprintf(fLog,"%s%3i-%3i:", (ii==0) ? "" : "\n", ii, ii+7); } fprintf(fLog," %8i", stats[band].histogram[ii]); } fprintf(fLog,"\n"); } } /* Write out .meta and .stat files */ if (!nometa_flag) meta_write(meta, meta_name); if (!nostat_flag) stat_write(stats, stat_name, meta->stats->band_count); /* Free the metadata structure */ meta_free(meta); /* Report */ if (!quietflag) { printf("\n"); printf("Statistics taken on image file %s.\n",sar_name); if (!nometa_flag) printf("Statistics written to the stats block in %s.\n", meta_name); if (!nostat_flag) printf("Statistics plus histogram written to %s.\n", stat_name); printf("\n"); } if (logflag && !quietflag) { fprintf(fLog,"\n"); fprintf(fLog,"Statistics taken on image file '%s'\n",sar_name); if (!nometa_flag) fprintf(fLog,"Statistics written to the stats block in %s\n", meta_name); if (!nostat_flag) fprintf(fLog,"Statistics plus histogram written to %s\n", stat_name); fprintf(fLog,"\n"); } if (fLog) FCLOSE(fLog); return 0; }
int sr2gr_pixsiz(const char *infile, const char *outfile, float grPixSize) { int in_np, in_nl; /* input number of pixels,lines */ int out_np, out_nl; /* output number of pixels,lines */ int ii,line,band; float oldX,oldY; float sr2gr[MAX_IMG_SIZE]; float ml2gr[MAX_IMG_SIZE]; int a_lower[MAX_IMG_SIZE]; int lower[MAX_IMG_SIZE], upper[MAX_IMG_SIZE]; float a_ufrac[MAX_IMG_SIZE], a_lfrac[MAX_IMG_SIZE]; float ufrac[MAX_IMG_SIZE], lfrac[MAX_IMG_SIZE]; float *ibuf1,*ibuf2,*obuf; char infile_name[512],inmeta_name[512]; char outfile_name[512],outmeta_name[512]; FILE *fpi, *fpo; meta_parameters *in_meta; meta_parameters *out_meta; create_name (infile_name, infile, ".img"); create_name (outfile_name, outfile, ".img"); create_name (inmeta_name, infile, ".meta"); create_name (outmeta_name, outfile, ".meta"); in_meta = meta_read(inmeta_name); out_meta = meta_copy(in_meta); in_nl = in_meta->general->line_count; in_np = in_meta->general->sample_count; if (in_meta->sar->image_type != 'S') { asfPrintError("sr2gr only works with slant range images!\n"); } oldX = in_meta->general->x_pixel_size * in_meta->sar->sample_increment; oldY = in_meta->general->y_pixel_size * in_meta->sar->line_increment; /* If user didn't specify a pixel size, make the pixels square & leave the y pixel size unchanged */ if (grPixSize < 0) grPixSize = oldY; /*Update metadata for new pixel size*/ out_meta->sar->time_shift += ((in_meta->general->start_line) * in_meta->sar->azimuth_time_per_pixel); out_meta->sar->slant_shift -= ((in_meta->general->start_sample) * in_meta->general->x_pixel_size); out_meta->general->start_line = 0.0; out_meta->general->start_sample = 0.0; out_meta->sar->azimuth_time_per_pixel *= grPixSize / in_meta->general->y_pixel_size; out_meta->sar->line_increment = 1.0; out_meta->sar->sample_increment = 1.0; if (out_meta->transform) out_meta->transform->target_pixel_size = grPixSize; /*Create ground/slant and azimuth conversion vectors*/ out_meta->sar->image_type = 'G'; out_meta->general->x_pixel_size = grPixSize; out_meta->general->y_pixel_size = grPixSize; sr2gr_vec(out_meta,oldX,grPixSize,sr2gr); ml_vec(oldY,grPixSize,ml2gr); out_np = MAX_IMG_SIZE; out_nl = MAX_IMG_SIZE; for (ii=MAX_IMG_SIZE-1; ii>0; ii--) if ((int)sr2gr[ii] > in_np) out_np = ii; for (ii=MAX_IMG_SIZE-1; ii>0; ii--) if ((int)ml2gr[ii] > in_nl) out_nl = ii; out_meta->general->line_count = out_nl; out_meta->general->line_scaling *= (double)in_nl/(double)out_nl; out_meta->general->sample_scaling = 1; out_meta->general->sample_count = out_np; if (out_meta->projection) { out_meta->projection->perX = grPixSize; out_meta->projection->perY = grPixSize; } meta_write(out_meta,outmeta_name); fpi = fopenImage(infile_name,"rb"); fpo = fopenImage(outfile_name,"wb"); for (ii=0; ii<MAX_IMG_SIZE; ii++) { lower[ii] = (int) sr2gr[ii]; upper[ii] = lower[ii] + 1; ufrac[ii] = sr2gr[ii] - (float) lower[ii]; lfrac[ii] = 1.0 - ufrac[ii]; a_lower[ii] = (int) ml2gr[ii]; a_ufrac[ii] = ml2gr[ii] - (float) a_lower[ii]; a_lfrac[ii] = 1.0 - a_ufrac[ii]; } ibuf1 = (float *) MALLOC ((in_np+FUDGE_FACTOR)*sizeof(float)); ibuf2 = (float *) MALLOC ((in_np+FUDGE_FACTOR)*sizeof(float)); obuf = (float *) MALLOC (out_np*sizeof(float)); /* Initialize input arrays to 0 */ for (ii=0;ii<in_np+FUDGE_FACTOR;ii++) { ibuf1[ii]=ibuf2[ii]=0.0; } /* Get the band info */ int bc = in_meta->general->band_count; char **band_name = extract_band_names(in_meta->general->bands, bc); /* Work dat magic! */ for (band=0; band<bc; ++band) { asfPrintStatus("Working on band: %s\n", band_name[band]); for (line=0; line<out_nl; line++) { if (a_lower[line]+1 < in_nl) { get_band_float_line(fpi,in_meta,band,a_lower[line], ibuf1); get_band_float_line(fpi,in_meta,band,a_lower[line]+1,ibuf2); } for (ii=0; ii<out_np; ii++) { int val00,val01,val10,val11,tmp1,tmp2; val00 = ibuf1[lower[ii]]; val01 = ibuf1[upper[ii]]; val10 = ibuf2[lower[ii]]; val11 = ibuf2[upper[ii]]; tmp1 = val00*lfrac[ii] + val01*ufrac[ii]; tmp2 = val10*lfrac[ii] + val11*ufrac[ii]; obuf[ii] = tmp1*a_lfrac[line] + tmp2*a_ufrac[line]; } put_band_float_line(fpo,out_meta,band,line,obuf); asfLineMeter(line, out_nl); } } for (band=0; band<bc; ++band) FREE(band_name[band]); FREE(band_name); meta_free(in_meta); meta_free(out_meta); FCLOSE(fpi); FCLOSE(fpo); return TRUE; }
static void add_pixels(BandedFloatImage *out, char *file, int size_x, int size_y, double start_x, double start_y, double per_x, double per_y) { meta_parameters *meta = meta_read(file); if (!meta) { asfPrintError("Couldn't read metadata for: %s!\n", file); } // figure out where in the giant image these pixels will go int start_line, start_sample; // this should work even if per_x / per_y are negative... start_sample = (int) ((meta->projection->startX - start_x) / per_x + .5); start_line = (int) ((meta->projection->startY - start_y) / per_y + .5); int ns = meta->general->sample_count; int nl = meta->general->line_count; int nb = meta->general->band_count; char **bands = extract_band_names(meta->general->bands, nb); asfPrintStatus(" Location in combined is S:%d-%d, L:%d-%d\n", start_sample, start_sample + ns, start_line, start_line + nl); if (start_sample + ns > out->images[0]->size_x || start_line + nl > out->images[0]->size_y) { asfPrintError("Image extents were not calculated correctly!\n"); } FILE *img = fopenImage(file, "rb"); if (!img) { asfPrintError("Couldn't open image file: %s!\n", file); } float *line = MALLOC(sizeof(float)*ns); int z; for (z=0; z<nb; ++z) { asfPrintStatus(" Band: %s\n", bands[z]); int y; for (y=0; y<nl; ++y) { get_band_float_line(img, meta, z, y, line); int x; for (x=0; x<ns; ++x) { float v = line[x]; // don't write out "no data" values if (v != meta->general->no_data) banded_float_image_set_pixel(out, z, x+start_sample, y+start_line, v); } asfLineMeter(y, nl); } } fclose(img); free(line); meta_free(meta); }
int clip(char *inFile, char *maskFile, char *outFile) { meta_parameters *metaIn, *metaMask; metaIn = meta_read(inFile); metaMask = meta_read(maskFile); // Check whether mask file looks legitimate. The only indication that we // have is that it should be BYTE and have one band. if (metaMask->general->data_type != ASF_BYTE) asfPrintStatus("Mask image does not have data type 'BYTE'!\n"); if (metaMask->general->band_count != 1) asfPrintStatus("Mask image should have only one band!\n"); // Check whether input and mask file have the same projection parameters if (metaIn->projection && metaMask->projection) { // Create temporary processing directory (move outside this loop once // we have non-projected case covered) char *tmpDir = (char *) MALLOC(sizeof(char)*(strlen(outFile)+25)); sprintf(tmpDir, "%s-", outFile); strcat(tmpDir, time_stamp_dir()); create_clean_dir(tmpDir); char *mask = (char *) MALLOC(sizeof(char)*(strlen(tmpDir)+20)); sprintf(mask, "%s/mask", tmpDir); // Check whether mask needs to be re-projected if (metaIn->projection->type != metaMask->projection->type) { asfPrintWarning("Mask needs to be re-projected!\n"); project_parameters_t *pp = (project_parameters_t *) MALLOC(sizeof(project_parameters_t)); *pp = metaIn->projection->param; /* asf_geocode(pp, metaIn->projection->type, FALSE, RESAMPLE_NEAREST_NEIGHBOR, metaIn->projection->height, metaIn->projection->datum, metaIn->projection->perX, NULL, inFile, mask, metaIn->general->no_data, FALSE); */ FREE(pp); } else { // Check whether mask needs to be resampled if ((metaIn->projection->perX != metaMask->projection->perX || metaIn->projection->perY != metaMask->projection->perY) && proj_params_match(metaIn, metaMask)) { asfPrintWarning("Mask needs to be resampled!\n"); resample(inFile, mask, metaIn->projection->perX, fabs(metaIn->projection->perY)); } else if (!proj_params_match(metaIn, metaMask)) { asfPrintWarning("Mask needs to be re-projected!\n"); project_parameters_t *pp = (project_parameters_t *) MALLOC(sizeof(project_parameters_t)); *pp = metaIn->projection->param; /* asf_geocode(pp, metaIn->projection->type, FALSE, RESAMPLE_NEAREST_NEIGHBOR, metaIn->projection->height, metaIn->projection->datum, metaIn->projection->perX, NULL, inFile, mask, metaIn->general->no_data, FALSE); */ FREE(pp); } else copyImgAndMeta(maskFile, mask); } meta_free(metaMask); // Now we should have matching projections in both input files // Let's figure out the overlapping part of the two input files metaMask = meta_read(mask); int nl = metaMask->general->line_count; int ns = metaMask->general->sample_count; int startLine = (int) ((metaMask->projection->startY - metaIn->projection->startY + 0.5) / metaMask->projection->perY) - metaMask->general->start_line; int startSample = (int) ((metaMask->projection->startX - metaIn->projection->startX + 0.5) / metaMask->projection->perX) - metaMask->general->start_sample; int endLine = startLine + metaMask->general->line_count; int endSample = startSample + metaMask->general->sample_count; double coverage = (endLine-startLine) * (endSample-startSample) * 100.0 / (ns*nl); printf("startLine: %i, startSample: %i\n", startLine, startSample); printf("endLine: %i, endSample: %i\n", endLine, endSample); printf("Converage: %.1f %%\n", coverage); // Fail when there is no overlap if (startLine > metaIn->general->line_count || endLine < 0 || startSample > metaIn->general->sample_count || endSample < 0) { asfPrintStatus("Mask image does not cover the input image!\n"); return (1); } // Setup files and memory char *inImg = appendExt(inFile, ".img"); char *maskImg = appendExt(maskFile, ".img"); char *outImg = appendExt(outFile, ".img"); float *inBuf = (float *) MALLOC(sizeof(float)*metaIn->general->sample_count); unsigned char *maskBuf = (unsigned char *) MALLOC(sizeof(char)*ns); float *outBuf = (float *) MALLOC(sizeof(float)*ns); char **band_name = extract_band_names(metaIn->general->bands, metaIn->general->band_count); FILE *fpIn = FOPEN(inImg, "rb"); FILE *fpMask = FOPEN(maskImg, "rb"); FILE *fpOut = FOPEN(outImg, "wb"); // Write metadata for output meta_parameters *metaOut = meta_read(maskFile); metaOut->general->band_count = metaIn->general->band_count; metaOut->general->data_type = metaIn->general->data_type; meta_write(metaOut, outFile); // Rock and roll int ii, jj, kk; for (ii=0; ii<nl; ii++) { get_byte_line(fpMask, metaMask, ii, maskBuf); for (kk=0; kk<metaIn->general->band_count; kk++) { if ((startLine+ii) >= 0 && ii < endLine) get_band_float_line(fpIn, metaIn, kk, startLine+ii, inBuf); else for (jj=0; jj<ns; jj++) inBuf[jj] = 0.0; for (jj=0; jj<ns; jj++) { if (maskBuf[jj] == 0 || inBuf[startSample+jj] == 0 || (startSample+jj) < 0 || jj > endSample) outBuf[jj] = metaIn->general->no_data; else outBuf[jj] = inBuf[startSample+jj]*maskBuf[jj]; } put_band_float_line(fpOut, metaOut, kk, ii, outBuf); } asfLineMeter(ii, nl); } FCLOSE(fpIn); FCLOSE(fpMask); FCLOSE(fpOut); // Clean up for (ii=0; ii<metaIn->general->band_count; ii++) FREE(band_name[ii]); FREE(band_name); FREE(inBuf); FREE(maskBuf); FREE(outBuf); meta_free(metaIn); meta_free(metaMask); meta_free(metaOut); remove_dir(tmpDir); FREE(tmpDir); } else asfPrintError("Non-projected case not covered yet!\n"); return 0; }
// Main program body. int main (int argc, char *argv[]) { output_format_t format = 0; meta_parameters *md; char *in_base_name, *output_name; char **band_names=NULL; int rgb=0; int true_color; int false_color; int num_bands_found; int ignored[3] = {0, 0, 0}; int num_ignored = 0; in_base_name = (char *) MALLOC(sizeof(char)*255); output_name = (char *) MALLOC(sizeof(char)*255); /**********************BEGIN COMMAND LINE PARSING STUFF**********************/ // Command line input goes in it's own structure. command_line_parameters_t command_line; strcpy (command_line.format, ""); command_line.size = NO_MAXIMUM_OUTPUT_SIZE; strcpy (command_line.in_data_name, ""); strcpy (command_line.in_meta_name, ""); strcpy (command_line.output_name, ""); command_line.verbose = FALSE; command_line.quiet = FALSE; strcpy (command_line.leader_name, ""); strcpy (command_line.cal_params_file, ""); strcpy (command_line.cal_comment, ""); command_line.sample_mapping = 0; strcpy(command_line.red_channel, ""); strcpy(command_line.green_channel, ""); strcpy(command_line.blue_channel, ""); strcpy(command_line.band, ""); strcpy(command_line.look_up_table_name, ""); int formatFlag, logFlag, quietFlag, byteFlag, rgbFlag, bandFlag, lutFlag; int truecolorFlag, falsecolorFlag; int needed_args = 3; //command & argument & argument int ii; char sample_mapping_string[25]; //Check to see which options were specified if ( (checkForOption("--help", argc, argv) != FLAG_NOT_SET) || (checkForOption("-h", argc, argv) != FLAG_NOT_SET) || (checkForOption("-help", argc, argv) != FLAG_NOT_SET) ) { print_help(); } get_asf_share_dir_with_argv0(argv[0]); handle_license_and_version_args(argc, argv, ASF_NAME_STRING); formatFlag = checkForOption ("-format", argc, argv); logFlag = checkForOption ("-log", argc, argv); quietFlag = checkForOption ("-quiet", argc, argv); byteFlag = checkForOption ("-byte", argc, argv); rgbFlag = checkForOption ("-rgb", argc, argv); bandFlag = checkForOption ("-band", argc, argv); lutFlag = checkForOption ("-lut", argc, argv); truecolorFlag = checkForOption("-truecolor", argc, argv); falsecolorFlag = checkForOption("-falsecolor", argc, argv); if ( formatFlag != FLAG_NOT_SET ) { needed_args += 2; // Option & parameter. } if ( quietFlag != FLAG_NOT_SET ) { needed_args += 1; // Option & parameter. } if ( logFlag != FLAG_NOT_SET ) { needed_args += 2; // Option & parameter. } if ( byteFlag != FLAG_NOT_SET ) { needed_args += 2; // Option & parameter. } if ( rgbFlag != FLAG_NOT_SET ) { needed_args += 4; // Option & 3 parameters. } if ( bandFlag != FLAG_NOT_SET ) { needed_args += 2; // Option & parameter. } if ( lutFlag != FLAG_NOT_SET ) { needed_args += 2; // Option & parameter. } if ( truecolorFlag != FLAG_NOT_SET ) { needed_args += 1; // Option only } if ( falsecolorFlag != FLAG_NOT_SET ) { needed_args += 1; // Option only } if ( argc != needed_args ) { print_usage (); // This exits with a failure. } // We also need to make sure the last three options are close to // what we expect. if ( argv[argc - 1][0] == '-' || argv[argc - 2][0] == '-' ) { print_usage (); // This exits with a failure. } // Make sure any options that have parameters are followed by // parameters (and not other options) Also make sure options' // parameters don't bleed into required arguments. if ( formatFlag != FLAG_NOT_SET ) { if ( argv[formatFlag + 1][0] == '-' || formatFlag >= argc - 3 ) { print_usage (); } } if ( byteFlag != FLAG_NOT_SET ) { if ( argv[byteFlag + 1][0] == '-' || byteFlag >= argc - 3 ) { print_usage (); } } if ( rgbFlag != FLAG_NOT_SET ) { if (( argv[rgbFlag + 1][0] == '-' && argv[rgbFlag + 2][0] == '-' && argv[rgbFlag + 3][0] == '-' ) || rgbFlag >= argc - 5 ) { print_usage (); } } if ( bandFlag != FLAG_NOT_SET ) { if ( argv[bandFlag + 1][0] == '-' || bandFlag >= argc - 3 ) { print_usage (); } } if ( lutFlag != FLAG_NOT_SET ) { if ( argv[lutFlag + 1][0] == '-' || lutFlag >= argc - 3 ) { print_usage (); } } if ( logFlag != FLAG_NOT_SET ) { if ( argv[logFlag + 1][0] == '-' || logFlag >= argc - 3 ) { print_usage (); } } // Make sure there are no flag incompatibilities if ( (rgbFlag != FLAG_NOT_SET && (bandFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET)) || (bandFlag != FLAG_NOT_SET && (rgbFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET)) || (truecolorFlag != FLAG_NOT_SET && (bandFlag != FLAG_NOT_SET || rgbFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET)) || (falsecolorFlag != FLAG_NOT_SET && (bandFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || rgbFlag != FLAG_NOT_SET)) ) { asfPrintWarning("The following options may only be used one at a time:\n" " %s\n %s\n %s\n %s\n %s\n %s\n", "-rgb", "-truecolor", "-falsecolor", "-band"); print_help(); } if ( (rgbFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET) && lutFlag != FLAG_NOT_SET ) asfPrintError("Look up table option can only be used on single-band " "images.\n"); if( logFlag != FLAG_NOT_SET ) { strcpy(logFile, argv[logFlag+1]); } else { sprintf(logFile, "tmp%i.log", (int)getpid()); } logflag = TRUE; // Since we always log, set the old school logflag to true fLog = FOPEN (logFile, "a"); // Set old school quiet flag (for use in our libraries) quietflag = ( quietFlag != FLAG_NOT_SET ) ? TRUE : FALSE; // We're good enough at this point... print the splash screen. asfSplashScreen (argc, argv); // Grab the input and output name strcpy (in_base_name, argv[argc - 2]); strcpy (output_name, argv[argc - 1]); strcpy (command_line.output_name, output_name); // If user added ".img", strip it. char *ext = findExt(in_base_name); if (ext && strcmp(ext, ".img") == 0) *ext = '\0'; // Set default output type if( formatFlag != FLAG_NOT_SET ) { strcpy (command_line.format, argv[formatFlag + 1]); } else { // Default behavior: produce a geotiff. strcpy (command_line.format, "geotiff"); } // Compose input metadata name strcpy (command_line.in_meta_name, in_base_name); strcat (command_line.in_meta_name, ".meta"); // for some validation, need the metadata md = meta_read (command_line.in_meta_name); // Convert the string to upper case. for ( ii = 0 ; ii < strlen (command_line.format) ; ++ii ) { command_line.format[ii] = toupper (command_line.format[ii]); } if (strcmp (command_line.format, "PGM") == 0 && (rgbFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET) ) { asfPrintWarning("Greyscale PGM output is not compatible with color options:\n" "(RGB, True Color, False Color, color look-up tables, etc\n)" "...Defaulting to producing separate greyscale PGM files for available band.\n"); rgbFlag = FLAG_NOT_SET; truecolorFlag = FLAG_NOT_SET; falsecolorFlag = FLAG_NOT_SET; } // Set the default byte scaling mechanisms if (md->optical) { // for optical data, default sample mapping is NONE command_line.sample_mapping = NONE; } // for other data, default is based on the output type else if (strcmp (command_line.format, "TIFF") == 0 || strcmp (command_line.format, "TIF") == 0 || strcmp (command_line.format, "JPEG") == 0 || strcmp (command_line.format, "JPG") == 0 || strcmp (command_line.format, "PNG") == 0 || strcmp (command_line.format, "PGM") == 0 || strcmp (command_line.format, "PNG_ALPHA") == 0 || strcmp (command_line.format, "PNG_GE") == 0) { command_line.sample_mapping = SIGMA; } else if (strcmp (command_line.format, "GEOTIFF") == 0) { command_line.sample_mapping = NONE; } if ( quietFlag != FLAG_NOT_SET ) command_line.quiet = TRUE; else command_line.quiet = FALSE; // Set rgb combination if ( rgbFlag != FLAG_NOT_SET ) { int i; for (i=0, num_ignored = 0; i<3; i++) { ignored[i] = strncmp("IGNORE", uc(argv[rgbFlag + i + 1]), 6) == 0 ? 1 : 0; num_ignored += ignored[i] ? 1 : 0; } asfRequire(num_ignored < 3, "Cannot ignore all bands. Exported image would be blank.\n"); strcpy (command_line.red_channel, ignored[0] ? "Ignored" : argv[rgbFlag + 1]); strcpy (command_line.green_channel, ignored[1] ? "Ignored" : argv[rgbFlag + 2]); strcpy (command_line.blue_channel, ignored[2] ? "Ignored" : argv[rgbFlag + 3]); // Check to see if the bands are numeric and in range int r_channel = atoi(command_line.red_channel); int g_channel = atoi(command_line.green_channel); int b_channel = atoi(command_line.blue_channel); /////////// Numeric channel case //////////// // Remove trailing non-numeric characters from the channel number // string and pad front end nicely with a zero if (!ignored[0] && is_numeric(command_line.red_channel) && r_channel >= 1 && r_channel <= MAX_BANDS) { sprintf(command_line.red_channel, "%02d", atoi(command_line.red_channel)); } if (!ignored[1] && is_numeric(command_line.green_channel) && g_channel >= 1 && g_channel <= MAX_BANDS) { sprintf(command_line.green_channel, "%02d", atoi(command_line.green_channel)); } if (!ignored[2] && is_numeric(command_line.blue_channel) && b_channel >= 1 && b_channel <= MAX_BANDS) { sprintf(command_line.blue_channel, "%02d", atoi(command_line.blue_channel)); } } // Set up the bands for true or false color optical data true_color = false_color = 0; int with_sigma = FALSE; if (truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET) { int ALOS_optical = (md->optical && strncmp(md->general->sensor, "ALOS", 4) == 0) ? 1 : 0; if (md->optical && truecolorFlag != FLAG_NOT_SET) { if (ALOS_optical) { with_sigma = TRUE; strcpy(command_line.red_channel, "03"); strcpy(command_line.green_channel, "02"); strcpy(command_line.blue_channel, "01"); true_color = 1; asfPrintStatus("Applying True Color contrast expansion to following channels:"); } else { char **bands = extract_band_names(md->general->bands, 3); asfRequire(bands != NULL, "-truecolor option specified for non-true color optical image.\n"); asfPrintWarning("Attempting to use the -truecolor option with non-ALOS\n" "optical data.\n"); strcpy(command_line.red_channel, bands[2]); strcpy(command_line.green_channel, bands[1]); strcpy(command_line.blue_channel, bands[0]); int i; for (i=0; i<3; i++) { FREE(bands[i]); } FREE(bands); } } if (md->optical && falsecolorFlag != FLAG_NOT_SET) { if (ALOS_optical) { with_sigma = TRUE; strcpy(command_line.red_channel, "04"); strcpy(command_line.green_channel, "03"); strcpy(command_line.blue_channel, "02"); false_color = 1; asfPrintStatus("Applying False Color contrast expansion to the following channels:"); } else { char **bands = extract_band_names(md->general->bands, 4); asfRequire(bands != NULL, "-falsecolor option specified for an optical image with fewer than 4 bands.\n"); asfPrintWarning("Attempting to use the -falsecolor option with non-ALOS\n" "optical data.\n"); strcpy(command_line.red_channel, bands[3]); strcpy(command_line.green_channel, bands[2]); strcpy(command_line.blue_channel, bands[1]); int i; for (i=0; i<3; i++) { FREE(bands[i]); } FREE(bands); } } if (!ALOS_optical && !md->optical) { asfPrintError("-truecolor or -falsecolor option selected with non-optical data\n"); } } if (rgbFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET) { char red_band[16], green_band[16], blue_band[16]; asfPrintStatus("\nRed channel : %s %s\n", command_line.red_channel, sigma_str(with_sigma)); asfPrintStatus("Green channel: %s %s\n", command_line.green_channel, sigma_str(with_sigma)); asfPrintStatus("Blue channel : %s %s\n\n", command_line.blue_channel, sigma_str(with_sigma)); if (is_numeric(command_line.red_channel) && is_numeric(command_line.green_channel) && is_numeric(command_line.blue_channel)) { sprintf(red_band, "%02d", atoi(command_line.red_channel)); sprintf(green_band, "%02d", atoi(command_line.green_channel)); sprintf(blue_band, "%02d", atoi(command_line.blue_channel)); band_names = find_bands(in_base_name, rgbFlag, red_band, green_band, blue_band, &num_bands_found); } else { band_names = find_bands(in_base_name, rgbFlag, command_line.red_channel, command_line.green_channel, command_line.blue_channel, &num_bands_found); } } // Set band if ( bandFlag != FLAG_NOT_SET) { strcpy (command_line.band, argv[bandFlag + 1]); band_names = find_single_band(in_base_name, command_line.band, &num_bands_found); } else if (rgbFlag == FLAG_NOT_SET && truecolorFlag == FLAG_NOT_SET && falsecolorFlag == FLAG_NOT_SET && bandFlag == FLAG_NOT_SET) { bandFlag=1; // For proper messaging to the user strcpy (command_line.band, "all"); band_names = find_single_band(in_base_name, command_line.band, &num_bands_found); } // Read look up table name if ( lutFlag != FLAG_NOT_SET) { strcpy(command_line.look_up_table_name, argv[lutFlag + 1]); rgb = 1; } // Set scaling mechanism if ( byteFlag != FLAG_NOT_SET ) { strcpy (sample_mapping_string, argv[byteFlag + 1]); for ( ii = 0; ii < strlen(sample_mapping_string); ii++) { sample_mapping_string[ii] = toupper (sample_mapping_string[ii]); } if ( strcmp (sample_mapping_string, "TRUNCATE") == 0 ) command_line.sample_mapping = TRUNCATE; else if ( strcmp(sample_mapping_string, "MINMAX") == 0 ) command_line.sample_mapping = MINMAX; else if ( strcmp(sample_mapping_string, "SIGMA") == 0 ) command_line.sample_mapping = SIGMA; else if ( strcmp(sample_mapping_string, "HISTOGRAM_EQUALIZE") == 0 ) command_line.sample_mapping = HISTOGRAM_EQUALIZE; else if ( strcmp(sample_mapping_string, "NONE") == 0 ) { asfPrintWarning("Sample remapping method (-byte option) is set to NONE\n" "which doesn't make sense. Defaulting to TRUNCATE...\n"); command_line.sample_mapping = TRUNCATE; } else asfPrintError("Unrecognized byte scaling method '%s'.\n", sample_mapping_string); } int is_polsarpro = (md->general->bands && strstr(md->general->bands, "POLSARPRO") != NULL) ? 1 : 0; if ( !is_polsarpro && lutFlag != FLAG_NOT_SET && bandFlag == FLAG_NOT_SET && md->general->band_count > 1) { asfPrintError("Look up tables can only be applied to single band" " images\n"); } if ( !is_polsarpro && lutFlag != FLAG_NOT_SET && command_line.sample_mapping == NONE && md->general->data_type != BYTE && md->general->band_count == 1) { asfPrintError("Look up tables can only be applied to byte output" " images\n"); } // Report what is going to happen if (rgbFlag != FLAG_NOT_SET || truecolorFlag != FLAG_NOT_SET || falsecolorFlag != FLAG_NOT_SET) { if (num_bands_found >= 3) { asfPrintStatus("Exporting multiband image ...\n\n"); rgb = 1; } else { asfPrintError("Not all RGB channels found.\n"); } } else if (bandFlag != FLAG_NOT_SET) { if (strcmp_case(command_line.band, "ALL") == 0) { if (multiband(command_line.format, extract_band_names(md->general->bands, md->general->band_count), md->general->band_count)) asfPrintStatus("Exporting multiband image ...\n\n"); else if (num_bands_found > 1) asfPrintStatus("Exporting each band into individual greyscale files ...\n\n"); } else if (num_bands_found == 1) { if (lutFlag != FLAG_NOT_SET) asfPrintStatus("Exporting band '%s' applying look up table ...\n\n", command_line.band); else asfPrintStatus("Exporting band '%s' as greyscale ...\n\n", command_line.band); } else asfPrintError("Band could not be found in the image.\n"); } else if (lutFlag != FLAG_NOT_SET) asfPrintStatus("Exporting applying look up table.\n\n"); else asfPrintStatus("Exporting as greyscale.\n\n"); //If user added ".img", strip it. ext = findExt(in_base_name); if (ext && strcmp(ext, ".img") == 0) *ext = '\0'; meta_free(md); /***********************END COMMAND LINE PARSING STUFF***********************/ if ( strcmp (command_line.format, "ENVI") == 0 ) { format = ENVI; } else if ( strcmp (command_line.format, "ESRI") == 0 ) { format = ESRI; } else if ( strcmp (command_line.format, "GEOTIFF") == 0 || strcmp (command_line.format, "GEOTIF") == 0) { format = GEOTIFF; } else if ( strcmp (command_line.format, "TIFF") == 0 || strcmp (command_line.format, "TIF") == 0) { format = TIF; } else if ( strcmp (command_line.format, "JPEG") == 0 || strcmp (command_line.format, "JPG") == 0) { format = JPEG; } else if ( strcmp (command_line.format, "PGM") == 0 ) { format = PGM; } else if ( strcmp (command_line.format, "PNG") == 0 ) { format = PNG; } else if ( strcmp (command_line.format, "PNG_ALPHA") == 0 ) { format = PNG_ALPHA; } else if ( strcmp (command_line.format, "PNG_GE") == 0 ) { format = PNG_GE; } else if ( strcmp (command_line.format, "KML") == 0 ) { format = KML; } else if ( strcmp (command_line.format, "POLSARPRO") == 0 ) { format = POLSARPRO_HDR; } else if ( strcmp (command_line.format, "HDF5") == 0 ) { format = HDF; } else if ( strcmp (command_line.format, "NETCDF") == 0 ) { format = NC; } else { asfPrintError("Unrecognized output format specified\n"); } /* Complex data generally can't be output into meaningful images, so we refuse to deal with it. */ /* md = meta_read (command_line.in_meta_name); asfRequire ( md->general->data_type == BYTE || md->general->data_type == INTEGER16 || md->general->data_type == INTEGER32 || md->general->data_type == REAL32 || md->general->data_type == REAL64, "Cannot cope with complex data, exiting...\n"); meta_free (md); */ // Do that exporting magic! asf_export_bands(format, command_line.sample_mapping, rgb, true_color, false_color, command_line.look_up_table_name, in_base_name, command_line.output_name, band_names, NULL, NULL); // If the user didn't ask for a log file then nuke the one that's been kept // since everything has finished successfully if (logFlag == FLAG_NOT_SET) { fclose (fLog); remove(logFile); } for (ii = 0; ii<num_bands_found; ii++) { FREE(band_names[ii]); } FREE(band_names); FREE(in_base_name); FREE(output_name); exit (EXIT_SUCCESS); }
static int proj_to_sr(const char *infile, const char *outfile, double pixel_size) { int ii, jj, kk; const float_image_sample_method_t sampling_method = FLOAT_IMAGE_SAMPLE_METHOD_BILINEAR; // overall algorithm: // 1. find extents in time/slant space // 2. for each pixel in output, resample in input space meta_parameters *inMeta = meta_read(infile); int nl = inMeta->general->line_count; int ns = inMeta->general->sample_count; if (!inMeta->projection && !inMeta->transform) asfPrintError("Expected a projection/transform block!\n"); if (!inMeta->state_vectors) asfPrintError("Input data does not have state vectors!\n"); //asfPrintStatus("Converting %s to slant range...\n", infile); // first, find extents in time/slant space // do this by projecting image corners to time/slant int tl_x=0, tl_y=0; int tr_x=ns-1, tr_y=0; int bl_x=0, bl_y=nl-1; int br_x=ns-1, br_y=nl-1; // we have to find the "real" corners of the image // do this using the first band of the input image as a reference if (inMeta->general->band_count == 1) asfPrintStatus("Tiling the input image...\n"); else asfPrintStatus("Tiling the reference band of the input image...\n"); FloatImage *in = float_image_new_from_metadata(inMeta, infile); // find top left pixel -- TOP-most non-no-data pixel in the image for (ii=0; ii<nl; ++ii) for (jj=0; jj<ns; ++jj) { double val = float_image_get_pixel(in, jj, ii); if (val != inMeta->general->no_data && val != 0.0) { tl_x = jj; tl_y = ii; goto found_tl; } } asfPrintError("Couldn't find top-left pixel! Entire image no data?\n"); found_tl: // find top right pixel -- RIGHT-most non-no-data pixel in the image for (jj=ns-1; jj>=0; --jj) for (ii=0; ii<nl; ++ii) { double val = float_image_get_pixel(in, jj, ii); if (val != inMeta->general->no_data && val != 0.0) { tr_x = jj; tr_y = ii; goto found_tr; } } asfPrintError("Couldn't find top-right pixel! Entire image no data?\n"); found_tr: // find bottom left pixel -- LEFT-most non-no-data pixel in the image for (jj=0; jj<ns; ++jj) for (ii=nl-1; ii>=0; --ii) { double val = float_image_get_pixel(in, jj, ii); if (val != inMeta->general->no_data && val != 0.0) { bl_x = jj; bl_y = ii; goto found_bl; } } asfPrintError("Couldn't find bottom-left pixel! Entire image no data?\n"); found_bl: // find bottom right pixel -- BOTTOM-most non-no-data pixel in the image for (ii=nl-1; ii>=0; --ii) for (jj=ns-1; jj>=0; --jj) { double val = float_image_get_pixel(in, jj, ii); if (val != inMeta->general->no_data && val != 0.0) { br_x = jj; br_y = ii; goto found_br; } } asfPrintError("Couldn't find bottom-right pixel! Entire image no data?\n"); found_br: asfPrintStatus("Determining image extents in time/slant coordinates.\n"); //asfPrintStatus("Corners are at: TL (%d,%d)\n", tl_y, tl_x); //asfPrintStatus(" (line,sample) TR (%d,%d)\n", tr_y, tr_x); //asfPrintStatus(" BL (%d,%d)\n", bl_y, bl_x); //asfPrintStatus(" BR (%d,%d)\n", br_y, br_x); double tl_time, tl_slant; double tr_time, tr_slant; double bl_time, bl_slant; double br_time, br_slant; meta_get_timeSlantDop(inMeta, tl_y, tl_x, &tl_time, &tl_slant, NULL); meta_get_timeSlantDop(inMeta, tr_y, tr_x, &tr_time, &tr_slant, NULL); meta_get_timeSlantDop(inMeta, bl_y, bl_x, &bl_time, &bl_slant, NULL); meta_get_timeSlantDop(inMeta, br_y, br_x, &br_time, &br_slant, NULL); //asfPrintStatus("Corners are at: TL (%f,%f)\n", tl_time, tl_slant); //asfPrintStatus(" (time,slant) TR (%f,%f)\n", tr_time, tr_slant); //asfPrintStatus(" BL (%f,%f)\n", bl_time, bl_slant); //asfPrintStatus(" BR (%f,%f)\n", br_time, br_slant); double slant_start = min4(tl_slant, tr_slant, bl_slant, br_slant); double slant_end = max4(tl_slant, tr_slant, bl_slant, br_slant); double time_min = min4(tl_time, tr_time, bl_time, br_time); double time_max = max4(tl_time, tr_time, bl_time, br_time); double slant_incr; double time_start, time_end, time_incr; int onl, ons; if (pixel_size > 0) { slant_incr = pixel_size; ons = (slant_end - slant_start) / slant_incr; if (inMeta->sar) { // in this case, the original data has a SAR block, we will use the // same azimuth time per pixel. time_incr = inMeta->sar->azimuth_time_per_pixel; // we always want to be DECREASING in time // latest time is on top (line 1), earliest on bottom (line ONL) if (time_incr > 0) { time_incr = -time_incr; inMeta->sar->azimuth_time_per_pixel = -inMeta->sar->azimuth_time_per_pixel; } time_start = time_max; time_end = time_min; onl = (time_end - time_start) / time_incr; } else { // here, no sar block in the original data, just make a square // image with decreasing time onl = ons; time_incr = (time_min - time_max) / (double)onl; time_start = time_max; time_end = time_min; } } else { // not provided a slant range pixel size, we'll figure something out if (inMeta->sar) { // use the same azimuth time per pixel. time_incr = inMeta->sar->azimuth_time_per_pixel; // we always want to be DECREASING in time // latest time is on top (line 1), earliest on bottom (line ONL) if (time_incr > 0) { time_incr = -time_incr; inMeta->sar->azimuth_time_per_pixel = -inMeta->sar->azimuth_time_per_pixel; } time_start = time_max; time_end = time_min; onl = (time_end - time_start) / time_incr; } else { // no info... determine azimuth time per pixel by keeping // the height the same as in the original image onl = nl; time_incr = (time_min - time_max) / (double)onl; time_start = time_max; time_end = time_min; } // make it square, to get the slant range pixel size ons = onl; pixel_size = slant_incr = (slant_end - slant_start) / (double)ons; } asfRequire(onl > 0, "Internal Error: Invalid output line count: %d\n", onl); asfRequire(ons > 0, "Internal Error: Invalid output sample count: %d\n", ons); asfPrintStatus(" Slant range values: %f -> %f\n", slant_start, slant_end); asfPrintStatus(" Slant range pixel size: %f\n", pixel_size); asfPrintStatus(" Time values: %f -> %f\n", time_start, time_end); asfPrintStatus(" Output Image will be %5d x %5d LxS\n", onl, ons); asfPrintStatus(" (Input Image was %5d x %5d LxS)\n", nl, ns); // generate a grid over the image, to generate our splines // this grid size seems to work pretty well... int n = 120; asfPrintStatus("Creating %dx%d mapping grid...\n", n, n); // changed how these are calculated, so that the spline will cover // the entire value range double time_grid_incr = fabs(time_end - time_start) / (double)(n-1); if (time_incr < 0) time_grid_incr = -time_grid_incr; double slant_grid_incr = fabs(slant_end - slant_start) / (double)(n-1); if (slant_incr < 0) slant_grid_incr = -slant_grid_incr; // allocating memory for the splines, and the arrays to generate them gsl_interp_accel **samp_accels = MALLOC(sizeof(gsl_interp_accel *) * n); gsl_spline **samp_splines = MALLOC(sizeof(gsl_spline *) * n); gsl_interp_accel **line_accels = MALLOC(sizeof(gsl_interp_accel *) * n); gsl_spline **line_splines = MALLOC(sizeof(gsl_spline *) * n); double *slant_in = MALLOC(sizeof(double)*n); double *line_out = MALLOC(sizeof(double)*n); double *samp_out = MALLOC(sizeof(double)*n); // an alias -- use the same array (to save memory -- these are not used // at the same time), but create an alias for it, so it is not so confusing double *time_in = slant_in; //double max_err = 0; // set up the vertical splines for (jj=0; jj<n; ++jj) { double slant = slant_start + jj*slant_grid_incr; for (ii=0; ii<n; ++ii) { // splines need strictly increasing range variables if (time_grid_incr > 0) time_in[ii] = time_start + ii*time_grid_incr; else time_in[ii] = time_end - ii*time_grid_incr; ts2ls(inMeta, time_in[ii], slant, &line_out[ii], &samp_out[ii]); //printf("time: %f, slant: %f ==> line: %f, samp %f\n", // time_in[ii], slant, line_out[ii], samp_out[ii]); } samp_accels[jj] = gsl_interp_accel_alloc(); samp_splines[jj] = gsl_spline_alloc(gsl_interp_cspline, n); gsl_spline_init(samp_splines[jj], time_in, samp_out, n); line_accels[jj] = gsl_interp_accel_alloc(); line_splines[jj] = gsl_spline_alloc(gsl_interp_cspline, n); gsl_spline_init(line_splines[jj], time_in, line_out, n); } // now, we're on to the resampling stage.. loop through output pixels asfPrintStatus("Generating slant range image...\n"); double no_data_value = meta_is_valid_double(inMeta->general->no_data) ? inMeta->general->no_data : 0; // keep track of error sizes double max_error = 0; double avg_error = 0; int count = 0; // these stride values allow us to track when we're in between grid points int ii_n = onl/n; int jj_n = ons/n; int ii_n2 = ii_n/2; int jj_n2 = jj_n/2; // set up output metadata meta_parameters *outMeta = meta_read(infile); if (outMeta->transform) { FREE(outMeta->transform); outMeta->transform = NULL; } if (outMeta->projection) { FREE(outMeta->projection); outMeta->projection = NULL; } outMeta->general->line_count = onl; outMeta->general->sample_count = ons; if (!outMeta->sar) outMeta->sar = meta_sar_init(); outMeta->sar->image_type = 'S'; outMeta->sar->azimuth_time_per_pixel = time_incr; assert(outMeta->sar->azimuth_time_per_pixel < 0); outMeta->sar->time_shift = time_start; outMeta->general->y_pixel_size = inMeta->sar->azimuth_time_per_pixel / time_incr * inMeta->general->y_pixel_size; assert(outMeta->general->y_pixel_size > 0); outMeta->sar->slant_range_first_pixel = slant_start; outMeta->general->x_pixel_size = slant_incr; outMeta->sar->line_increment = outMeta->sar->sample_increment = 1; outMeta->general->start_sample = outMeta->general->start_line = 0; outMeta->general->no_data = no_data_value; char **band_name = extract_band_names(inMeta->general->bands, inMeta->general->band_count); // now generate output image char *img_file = appendExt(outfile, ".img"); float *out = MALLOC(sizeof(float) * ons); for (kk=0; kk<inMeta->general->band_count; ++kk) { if (inMeta->general->band_count != 1) asfPrintStatus("Working on band: %s\n", band_name[kk]); // for the 2nd and higher bands, free the band from the previous iteration, // and read in the next band from the input image if (kk>0) { float_image_free(in); asfPrintStatus("Loading input...\n"); in = float_image_band_new_from_metadata(inMeta, kk, infile); } FILE *ofp = FOPEN(img_file, kk==0 ? "wb" : "ab"); asfPrintStatus("Generating output...\n"); for (ii=0; ii<onl; ++ii) { asfLineMeter(ii,onl); double time = time_start + ii * time_incr; // set up horizontal splines for this row gsl_interp_accel *samp_accel = gsl_interp_accel_alloc(); gsl_spline *samp_spline = gsl_spline_alloc(gsl_interp_cspline, n); gsl_interp_accel *line_accel = gsl_interp_accel_alloc(); gsl_spline *line_spline = gsl_spline_alloc(gsl_interp_cspline, n); //printf("time: %f slant: %f\n", time, slant_start); for (jj=0; jj<n; ++jj) { slant_in[jj] = slant_start + jj * slant_grid_incr; //printf("time: %f slant: %f\n", time, slant_in[jj]); samp_out[jj] = gsl_spline_eval_check(samp_splines[jj], time, samp_accels[jj]); line_out[jj] = gsl_spline_eval_check(line_splines[jj], time, line_accels[jj]); //printf("samp_out: %f line_out: %f\n", samp_out[jj], line_out[jj]); } gsl_spline_init(samp_spline, slant_in, samp_out, n); gsl_spline_init(line_spline, slant_in, line_out, n); // use the splines to produce output pixels for (jj=0; jj<ons; ++jj) { double slant = slant_start + jj * slant_incr; double samp = gsl_spline_eval_check(samp_spline, slant, samp_accel); double line = gsl_spline_eval_check(line_spline, slant, line_accel); // check the spline every so often (halfway between grid points) // only do this on band #1 (the reference band) if (kk==0 && ii%ii_n2==0 && ii%ii_n!=0 && jj%jj_n2==0 && jj%jj_n!=0) { double samp_real, line_real; ts2ls(inMeta, time, slant, &line_real, &samp_real); double err = (line-line_real)*(line-line_real) + (samp-samp_real)*(samp-samp_real); //printf("(%d,%d) -- Actual: (%f,%f) Splined: (%f,%f)\n", // ii, jj, line_real, samp_real, line, samp); if (err > max_error) max_error = err; avg_error += err; ++count; } // now interpolate within the original image // if we are outside, use "no_data" from metadata double val = no_data_value; if (line > 0 && line < nl-1 && samp > 0 && samp < ns-1) val = float_image_sample(in, samp, line, sampling_method); out[jj] = (float)val; } gsl_interp_accel_free(samp_accel); gsl_spline_free(samp_spline); gsl_interp_accel_free(line_accel); gsl_spline_free(line_spline); put_float_line(ofp, outMeta, ii, out); } fclose(ofp); } // free the last band of the input float_image_free(in); FREE(slant_in); FREE(line_out); FREE(samp_out); for (ii=0; ii<n; ++ii) { gsl_interp_accel_free(samp_accels[ii]); gsl_spline_free(samp_splines[ii]); gsl_interp_accel_free(line_accels[ii]); gsl_spline_free(line_splines[ii]); } FREE(samp_accels); FREE(samp_splines); FREE(line_accels); FREE(line_splines); FREE(out); for (kk=0; kk<inMeta->general->band_count; ++kk) FREE(band_name[kk]); FREE(band_name); // see how bad our errors were avg_error /= (double)count; asfPrintStatus("Model max error: %f, avg: %f\n", max_error, avg_error); double thresh = 0.1; if (max_error > 100*thresh) asfPrintError("Maximum error exceeded threshold: %f > %f\n", max_error, 100*thresh); else if (avg_error > 10*thresh) asfPrintError("Average error exceeded threshold: %f > %f\n", avg_error, 10*thresh); if (max_error > 10*thresh) asfPrintWarning("Maximum error exceeds threshold: %f > %f\n", max_error, 10*thresh); if (avg_error > thresh) asfPrintWarning("Average error exceeds threshold: %f > %f\n", avg_error, thresh); char *meta_file = appendExt(outfile, ".meta"); asfPrintStatus("Writing %s\n", meta_file); meta_write(outMeta, meta_file); free(meta_file); free(img_file); meta_free(outMeta); meta_free(inMeta); return 0; //success }
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; }
static int gr2sr_pixsiz_imp(const char *infile, const char *outfile, float srPixSize, int apply_pp_earth_radius_fix) { meta_parameters *inMeta, *outMeta; int np, nl; /* in number of pixels,lines */ int onp, onl; /* out number of pixels,lines */ int nBands; /* number of bands in input/output */ int ii; float *gr2sr; /* GR 2 SR resampling vector for Range */ int *lower; /* floor of gr2sr vector */ int *upper; /* ceiling of gr2sr vector */ float *ufrac; /* Upper fraction from gr2sr vector */ float *lfrac; /* Lower fraction from gr2sr vector */ float *inBuf; /* Input buffer */ float *outBuf; /* Output buffer */ FILE *fpi, *fpo; /* File pointers */ int line; /* Loop counter */ int band; /* Loop counter */ char *iimgfile; /* .img input file */ char *oimgfile; /* .img output file */ gr2sr = (float *) MALLOC(sizeof(float) * MAX_IMG_SIZE); upper = (int *) MALLOC(sizeof(int) * MAX_IMG_SIZE); lower = (int *) MALLOC(sizeof(int) * MAX_IMG_SIZE); ufrac = (float *) MALLOC(sizeof(float) * MAX_IMG_SIZE); lfrac = (float *) MALLOC(sizeof(float) * MAX_IMG_SIZE); inMeta = meta_read(infile); if (srPixSize < 0) { /* In an e-mail from Rick: Slant Range Pixel Size = C (speed of light) / [SampleRate (sample rate) * 2,000,000.] SampleRate can be extracted from the L1 metadata : RNG CMPLX SAMPLE RATE 18.9599991 The meta->sar->range_sampling_rate is 10^6 times the value above, so we use C/(2*meta->sar->range_sampling_rate) */ int osc = inMeta->sar->original_sample_count; if (osc < 0) osc = inMeta->general->sample_count; srPixSize = SPD_LIGHT / ((2.0 * inMeta->sar->range_sampling_rate) * inMeta->general->sample_count / osc); } nl = inMeta->general->line_count; np = inMeta->general->sample_count; nBands = inMeta->general->band_count; char **band_name = extract_band_names(inMeta->general->bands, nBands); onl=nl; gr2sr_vec(inMeta, srPixSize, gr2sr, apply_pp_earth_radius_fix); /* Determine the output image size */ onp = 0; for (ii=0; ii<MAX_IMG_SIZE; ii++) { if (gr2sr[ii]<np) onp=ii; /* gr input still in range-- keep output */ else break; /* gr input is off end of image-- stop sr output */ } asfPrintStatus("Input image is %dx%d\n", nl, np); asfPrintStatus("Output image will be %dx%d\n", onl, onp); /* Split gr2sr into resampling coefficients */ for (ii=0; ii<onp; ii++) { lower[ii] = (int) gr2sr[ii]; upper[ii] = lower[ii] + 1; ufrac[ii] = gr2sr[ii] - (float) lower[ii]; lfrac[ii] = 1.0 - ufrac[ii]; if (lower[ii]>=np) lower[ii]=np-1; /* range clip */ if (upper[ii]>=np) upper[ii]=np-1; /* range clip */ } outMeta = meta_read(infile); outMeta->sar->slant_shift += ((inMeta->general->start_sample) * inMeta->general->x_pixel_size); outMeta->general->start_sample = 0.0; outMeta->sar->sample_increment = 1.0; outMeta->sar->image_type = 'S'; outMeta->general->x_pixel_size = srPixSize; outMeta->general->sample_count = onp; if (outMeta->sar){ update_doppler(np, onp, gr2sr, outMeta); } iimgfile = replExt(infile, "img"); oimgfile = replExt(outfile, "img"); fpi = FOPEN(iimgfile,"rb"); fpo = FOPEN(oimgfile,"wb"); inBuf = (float *) MALLOC (np*sizeof(float)); outBuf = (float *) MALLOC (onp*sizeof(float)); for (band = 0; band < nBands; band++) { if (inMeta->general->band_count != 1) asfPrintStatus("Converting to slant range: band %s\n", band_name[band]); for (line = 0; line < onl; line++) { get_float_line(fpi, inMeta, line + band*onl, inBuf); for (ii=0; ii<onp; ii++) { /* resample to slant range */ outBuf[ii] = inBuf[lower[ii]]*lfrac[ii]+inBuf[upper[ii]]*ufrac[ii]; } put_float_line(fpo,outMeta,line + band*onl,outBuf); asfLineMeter(line,onl); } } for (ii=0; ii < inMeta->general->band_count; ii++) FREE(band_name[ii]); FREE(band_name); meta_write(outMeta, outfile); meta_free(inMeta); meta_free(outMeta); FREE(ufrac); FREE(lfrac); FREE(gr2sr); FREE(upper); FREE(lower); FREE(inBuf); FREE(outBuf); FCLOSE(fpi); FCLOSE(fpo); FREE(iimgfile); FREE(oimgfile); return TRUE; }
void import_radarsat2(const char *inBaseName, radiometry_t radiometry, const char *outBaseName, int ampOnly) { FILE *fp; radarsat2_meta *radarsat2; meta_parameters *meta; char **inDataNames=NULL, inDataName[1024], *inMetaName=NULL; char *outDataName=NULL, str[512]; float *amp = NULL, *phase = NULL, *tmp = NULL, re, im; int band, sample; // Check radiometry if (radiometry != r_AMP) { asfPrintWarning("Radiometry other than AMPLITUDE is currently not " "supported.\n"); radiometry = r_AMP; } if (!fileExists(inBaseName)) inMetaName = appendExt(inBaseName, ".xml"); else { inMetaName = (char *) MALLOC(sizeof(char)*1024); strcpy(inMetaName, inBaseName); } outDataName = appendExt(outBaseName, ".img"); radarsat2 = read_radarsat2_meta(inMetaName); asfPrintStatus(" DataType: %s, ProductType: %s\n", radarsat2->dataType, radarsat2->productType); if (strcmp_case(radarsat2->dataType, "COMPLEX") != 0) asfPrintError("Currently only complex data supported!\n"); meta = radarsat2meta(radarsat2); meta_write(meta, outDataName); // Let's check the GeoTIFF data. // Unfortunately, there is no identifier in the GeoTIFF that would identify // the data as Radarsat-2 data. // // The only thing that we can actually do is to look whether the data in the // GeoTIFF file fit the general bill. We can the image dimensions. The data // needs to have 2 bands (I and Q) and 16 bit. The citation geokey needs to // be the really non-descriptive "Uncorrected Satellite Data". TIFF *tiff = NULL; GTIF *gtif = NULL; data_type_t data_type; short sample_format, bits_per_sample, planar_config; short num_bands; int is_scanline_format, is_palette_color_tiff, wrong=FALSE; char *error_message = (char *) MALLOC(sizeof(char)*2048); inDataNames = extract_band_names(meta->general->basename, meta->general->band_count); fp = FOPEN(outDataName, "wb"); int band_count = radarsat2->band_count; if (ampOnly) { strcpy(meta->general->bands, "AMP"); meta->general->band_count = 1; band_count = 1; } for (band=0; band<band_count; band++) { // path from the xml (metadata) file char *path = get_dirname(inBaseName); if (strlen(path)>0) { strcpy(inDataName, path); if (inDataName[strlen(inDataName)-1] != '/') strcat(inDataName, "/"); } else strcpy(inDataName, ""); free(path); strcat(inDataName, inDataNames[band]); tiff = XTIFFOpen(inDataName, "r"); if (!tiff) asfPrintError("Could not open data file (%s)\n", inDataName); gtif = GTIFNew(tiff); if (!gtif) asfPrintError("Could not read GeoTIFF keys from data file (%s)\n", inDataName); // Check image dimensions uint32 tif_sample_count; uint32 tif_line_count; TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &tif_line_count); TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &tif_sample_count); if ((meta->general->sample_count != tif_sample_count) || (meta->general->line_count != tif_line_count)) asfPrintError(error_message, "Problem with image dimensions. Was looking for %d lines " "and %d samples.\nFound %ld lines and %ld samples instead!" "\n", meta->general->line_count, meta->general->sample_count, tif_line_count, tif_sample_count); // Check general TIFF tags get_tiff_data_config(tiff, &sample_format, &bits_per_sample, &planar_config, &data_type, &num_bands, &is_scanline_format, &is_palette_color_tiff, REPORT_LEVEL_WARNING); // The specs say the data is supposed to be unsigned but it is not. // Let is pass as long as we are talking about integer data here strcpy(error_message, ""); if (sample_format != SAMPLEFORMAT_UINT && sample_format != SAMPLEFORMAT_INT) { strcat(error_message, "Problem with sampling format. Was looking for integer, "); if (sample_format == SAMPLEFORMAT_COMPLEXIEEEFP) strcat(error_message, "found complex floating point instead!\n"); else if (sample_format == SAMPLEFORMAT_COMPLEXINT) strcat(error_message, "found complex integer instead!\n"); else if (sample_format == SAMPLEFORMAT_IEEEFP) strcat(error_message, "found floating point instead!\n"); else if (sample_format == SAMPLEFORMAT_VOID) strcat(error_message, "found void instead!\n"); wrong = TRUE; } if (bits_per_sample != 16) { sprintf(str, "Problem with bits per sample. Was looking for 16, found %d " "instead!\n", bits_per_sample); strcat(error_message, str); wrong = TRUE; } if (data_type != INTEGER16) { strcat(error_message, "Problem with data type. Was looking INTEGER16, "); if (data_type == ASF_BYTE) strcat(error_message, "found BYTE instead!\n"); else if (data_type == INTEGER32) strcat(error_message, "found INTEGER32 instead!\n"); else if (data_type == REAL32) strcat(error_message, "found REAL32 instead!\n"); else if (data_type == REAL64) strcat(error_message, "found REAL64 instead!\n"); else if (data_type == COMPLEX_BYTE) strcat(error_message, "found COMPLEX_BYTE instead!\n"); else if (data_type == COMPLEX_INTEGER16) strcat(error_message, "found COMPLEX_INTEGER16 instead!\n"); else if (data_type == COMPLEX_INTEGER32) strcat(error_message, "found COMPLEX_INTEGER32 instead!\n"); else if (data_type == COMPLEX_REAL32) strcat(error_message, "found COMPLEX_REAL32 instead!\n"); else if (data_type == COMPLEX_REAL64) strcat(error_message, "found COMPLEX_REAL64 instead!\n"); wrong = TRUE; } if (num_bands != 2) { sprintf(str, "Problem with number of bands. Was looking for 2, " "found %d instead!\n", num_bands); strcat(error_message, str); wrong = TRUE; } if (wrong) asfPrintError(error_message); // Check GTCitationGeoKey char *citation = NULL; int citation_length, typeSize; tagtype_t citation_type; citation_length = GTIFKeyInfo(gtif, GTCitationGeoKey, &typeSize, &citation_type); if (citation_length > 0) { citation = (char *) MALLOC(citation_length * typeSize); GTIFKeyGet(gtif, GTCitationGeoKey, citation, 0, citation_length); if (citation && strcmp_case(citation, "UNCORRECTED SATELLITE DATA") != 0) { asfPrintError("Problem with GTCitationGeoKey. Was looking for " "'Uncorrected Satellite Data',\nfound '%s' instead!\n", citation); } } else asfPrintError("Problem with GTCitationGeoKey. Was looking for " "'Uncorrected Satellite Data',\ndid not find any key!\n"); tiff_type_t tiffInfo; get_tiff_type(tiff, &tiffInfo); if (tiffInfo.format != SCANLINE_TIFF && tiffInfo.format != STRIP_TIFF && tiffInfo.format != TILED_TIFF) asfPrintError("Can't read the GeoTIFF file (%s). Unrecognized TIFF " "type!\n", inDataNames[band]); // If we made it here, we are reasonably sure that we have the file that // we are looking for. asfPrintStatus("\n Importing %s ...\n", inDataNames[band]); uint32 scanlineSize = TIFFScanlineSize(tiff); tdata_t *tiff_real_buf = _TIFFmalloc(scanlineSize); tdata_t *tiff_imag_buf = _TIFFmalloc(scanlineSize); if (!tiff_real_buf || !tiff_imag_buf) asfPrintError("Can't allocate buffer for reading TIFF lines!\n"); amp = (float *) MALLOC(sizeof(float)*meta->general->sample_count); phase = (float *) MALLOC(sizeof(float)*meta->general->sample_count); // Check whether we need to flip the image in any fashion int flip_vertical = FALSE; if (strcmp_case(radarsat2->lineTimeOrdering, "DECREASING") == 0) { asfPrintStatus(" Data will be flipped vertically while ingesting!\n"); flip_vertical = TRUE; } int flip_horizontal = FALSE; if (strcmp_case(radarsat2->pixelTimeOrdering, "DECREASING") == 0) { asfPrintStatus(" Data will be flipped horizontally while ingesting!\n"); flip_horizontal = TRUE; } if (flip_horizontal) tmp = (float *) MALLOC(sizeof(float)*meta->general->sample_count); // FIXME: still need to implement flipping vertically // Read file line by line uint32 row; int sample_count = meta->general->sample_count; int line_count = meta->general->line_count; for (row=0; row<(uint32)meta->general->line_count; row++) { asfLineMeter(row, meta->general->line_count); if (flip_vertical) { switch (tiffInfo.format) { case SCANLINE_TIFF: TIFFReadScanline(tiff, tiff_real_buf, line_count-row-1, 0); TIFFReadScanline(tiff, tiff_imag_buf, line_count-row-1, 1); break; case STRIP_TIFF: ReadScanline_from_TIFF_Strip(tiff, tiff_real_buf, line_count-row-1, 0); ReadScanline_from_TIFF_Strip(tiff, tiff_imag_buf, line_count-row-1, 1); break; case TILED_TIFF: ReadScanline_from_TIFF_TileRow(tiff, tiff_real_buf, line_count-row-1, 0); ReadScanline_from_TIFF_TileRow(tiff, tiff_imag_buf, line_count-row-1, 1); break; default: asfPrintError("Can't read this TIFF format!\n"); break; } } else { switch (tiffInfo.format) { case SCANLINE_TIFF: TIFFReadScanline(tiff, tiff_real_buf, row, 0); TIFFReadScanline(tiff, tiff_imag_buf, row, 1); break; case STRIP_TIFF: ReadScanline_from_TIFF_Strip(tiff, tiff_real_buf, row, 0); ReadScanline_from_TIFF_Strip(tiff, tiff_imag_buf, row, 1); break; case TILED_TIFF: ReadScanline_from_TIFF_TileRow(tiff, tiff_real_buf, row, 0); ReadScanline_from_TIFF_TileRow(tiff, tiff_imag_buf, row, 1); break; default: asfPrintError("Can't read this TIFF format!\n"); break; } } for (sample=0; sample<sample_count; sample++) { switch (sample_format) { case SAMPLEFORMAT_UINT: re = (float)(((uint16*)tiff_real_buf)[sample]); im = (float)(((uint16*)tiff_imag_buf)[sample]); break; case SAMPLEFORMAT_INT: re = (float)(((int16*)tiff_real_buf)[sample]); im = (float)(((int16*)tiff_imag_buf)[sample]); break; } amp[sample] = sqrt(re*re + im*im); phase[sample] = atan2(im, re); } if (flip_horizontal) { for (sample=0; sample<sample_count; sample++) tmp[sample] = amp[sample]; for (sample=0; sample<sample_count; sample++) amp[sample] = tmp[sample_count-sample-1]; } put_band_float_line(fp, meta, band*2, (int)row, amp); if (!ampOnly) put_band_float_line(fp, meta, band*2+1, (int)row, phase); } FREE(amp); FREE(phase); if (tmp) FREE(tmp); _TIFFfree(tiff_real_buf); _TIFFfree(tiff_imag_buf); GTIFFree(gtif); XTIFFClose(tiff); } // update the name field with directory name char *path = get_dirname(inBaseName); if (strlen(path)<=0) path = g_get_current_dir(); char *p = path, *q = path; while (q) { if ((q = strchr(p, DIR_SEPARATOR)) != NULL) p = q+1; } sprintf(meta->general->basename, "%s", p); FREE(path); meta_write(meta, outDataName); meta_free(meta); FREE(radarsat2); FCLOSE(fp); }