static void test_double_attr(xmlDoc *doc, char *key, double expected) { double val = xml_get_double_attribute(doc, key); if (meta_is_valid_double(expected)) { if (fabs(val-expected)<.00001 ) { ++n_ok; } else { printf("WRONG! for key: %s\n" " Expected: %f\n" " Got: %f\n", key, expected, val); ++n_bad; } } else { if (meta_is_valid_double(val)) { printf("WRONG! for key: %s\n" " Expected: %f\n" " Got: %f\n", key, expected, val); ++n_bad; } else { ++n_ok; } } }
static int fftMatchBF(char *file1, char *file2, float *dx, float *dy, float *cert, double tol) { int qf_saved = quietflag; quietflag = TRUE; int ok = FALSE; float dx1=0, dx2=0, dy1=0, dy2=0, cert1=0, cert2=0; fftMatch(file1, file2, NULL, &dx1, &dy1, &cert1); if (!meta_is_valid_double(dx1) || !meta_is_valid_double(dy1) || cert1<tol) { *dx = *dy = *cert = 0; } else { fftMatch(file2, file1, NULL, &dx2, &dy2, &cert2); if (!meta_is_valid_double(dx2) || !meta_is_valid_double(dy2) || cert2<tol) { *dx = *dy = *cert = 0; } else if (fabs(dx1 + dx2) > .25 || fabs(dy1 + dy2) > .25) { *dx = *dy = *cert = 0; } else { *dx = (dx1 - dx2) * 0.5; *dy = (dy1 - dy2) * 0.5; *cert = cert1 < cert2 ? cert1 : cert2; ok = TRUE; } } quietflag = qf_saved; //asfPrintStatus("Result %s:\n" // "dx1=%8.2f dy1=%8.2f cert=%f\n" // "dx2=%8.2f dy2=%8.2f cert=%f\n", ok?"Yes":"No", dx1, dy1, cert1, dx2, dy2, cert2); return ok; }
/* readImg: reads the image file given by in into the (nl x ns) float array dest. Reads a total of (delY x delX) pixels into topleft corner of dest, starting at (startY , startX) in the input file. */ static void readImage(FILE *in,meta_parameters *meta, int startX,int startY,int delX,int delY, float add,float *sum, float *dest, int nl, int ns) { float *inBuf=(float *)MALLOC(sizeof(float)*(meta->general->sample_count)); register int x,y,l; double tempSum=0; // We've had some problems matching images with some extremely large // or NaN values. If only some pixels in the image have these values, // we should still be able to match. // Hard to say what a "crazy big" value would be... // We'll make the maximum allowed value MAXFLOAT (the maximum single // precision floating point number), divided by the number of pixels. const double maxval = ((double)MAXFLOAT) / ((double)ns*nl); /*Read portion of input image into topleft of dest array.*/ for (y=0;y<delY;y++) { l=ns*y; get_float_line(in,meta,startY+y,inBuf); if (sum==NULL) { for (x=0;x<delX;x++) { if (fabs(inBuf[startX+x]) < maxval && meta_is_valid_double(inBuf[startX+x])) { dest[l+x]=inBuf[startX+x]+add; } } } else { for (x=0;x<delX;x++) { if (fabs(inBuf[startX+x]) < maxval && meta_is_valid_double(inBuf[startX+x])) { tempSum+=inBuf[startX+x]; dest[l+x]=inBuf[startX+x]+add; } } } for (x=delX;x<ns;x++) { dest[l+x]=0.0; /*Fill rest of line with zeros.*/ } } /*Fill remainder of array (bottom portion) with zero lines.*/ for (y=delY;y<nl;y++) { l=ns*y; for (x=0;x<ns;x++) { dest[l+x]=0.0; /*Fill rest of in2 with zeros.*/ } } if (sum!=NULL) { *sum=(float)tempSum; } FREE(inBuf); }
static void get_bounding_box_linesamp(meta_parameters *metaSAR, meta_parameters *metaDEM, double *line_lo, double *line_hi, double *samp_lo, double *samp_hi, int h_padding, int v_padding) { *line_lo = metaDEM->general->line_count; *samp_lo = metaDEM->general->sample_count; *line_hi = *samp_hi = 0; // must call meta_get_latLon for each corner int nl = metaSAR->general->line_count; int ns = metaSAR->general->sample_count; double lat, lon, line, samp; meta_get_latLon(metaSAR, 0, 0, 0, &lat, &lon); meta_get_lineSamp(metaDEM, lat, lon, 0, &line, &samp); if (meta_is_valid_double(line) && meta_is_valid_double(samp)) update_extents(line, samp, line_lo, line_hi, samp_lo, samp_hi); meta_get_latLon(metaSAR, 0, ns-1, 0, &lat, &lon); meta_get_lineSamp(metaDEM, lat, lon, 0, &line, &samp); if (meta_is_valid_double(line) && meta_is_valid_double(samp)) update_extents(line, samp, line_lo, line_hi, samp_lo, samp_hi); meta_get_latLon(metaSAR, nl-1, 0, 0, &lat, &lon); meta_get_lineSamp(metaDEM, lat, lon, 0, &line, &samp); if (meta_is_valid_double(line) && meta_is_valid_double(samp)) update_extents(line, samp, line_lo, line_hi, samp_lo, samp_hi); meta_get_latLon(metaSAR, nl-1, ns-1, 0, &lat, &lon); meta_get_lineSamp(metaDEM, lat, lon, 0, &line, &samp); if (meta_is_valid_double(line) && meta_is_valid_double(samp)) update_extents(line, samp, line_lo, line_hi, samp_lo, samp_hi); // Add a little bit of fudge to each -- we want there to be some room // for adjustment via the co-registration. // Add about some pixels worth to each top/left/bottom/right. nl = metaDEM->general->line_count; ns = metaDEM->general->sample_count; *line_lo -= v_padding; if (*line_lo < 0) *line_lo = 0; if (*line_lo > nl-1) *line_lo = nl-1; *line_hi += v_padding; if (*line_hi < 0) *line_hi = 0; if (*line_hi > nl-1) *line_hi = nl-1; *samp_lo -= h_padding; if (*samp_lo < 0) *samp_lo = 0; if (*samp_lo > ns-1) *samp_lo = ns-1; *samp_hi += h_padding; if (*samp_hi < 0) *samp_hi = 0; if (*samp_hi > ns-1) *samp_hi = ns-1; }
static void line_samp_to_proj(ImageInfo *ii, double line, double samp, double *x, double *y) { meta_parameters *meta = ii->meta; if (meta_supports_meta_get_latLon(meta)) { double lat, lon, projZ; meta_get_latLon(meta, line, samp, 0, &lat, &lon); if (meta->projection && meta->projection->type != LAT_LONG_PSEUDO_PROJECTION) { latlon_to_proj(meta->projection, 'R', lat*D2R, lon*D2R, 0, x, y, &projZ); } else { int zone; if (meta_is_valid_double(meta->general->center_longitude) && meta->general->center_longitude > -180 && meta->general->center_longitude < 180) { zone = utm_zone(meta->general->center_longitude); } else { zone = utm_zone(lon); } latLon2UTM_zone(lat, lon, 0, zone, x, y); } } else { *x = samp; *y = line; } }
/******************************************************* * slantRange2groundPixel: * Calculate the ground range pixel from the total slant * range*/ int slantRange2groundPixel(meta_parameters *meta,double slant) { double a,x,y,Gr0, GrX; double Rsc, Re; int groundPixel; Rsc = meta_get_sat_height(meta, meta->general->line_count/2, 0); Re = meta_get_earth_radius(meta, meta->general->line_count/2, 0); a = (Rsc-Re)/Re; x = 1+a; y = meta->sar->slant_range_first_pixel / Re; Gr0 = Re * acos((1.0 + x*x - y*y) / (2.0 * x)); y = slant/Re; GrX = Re * acos((1.0 + x*x - y*y) / (2.0 * x)); if (!meta_is_valid_double(Gr0) || !meta_is_valid_double(GrX)) { asfPrintError("Cannot convert slant range to ground range.\n"); } if (meta && meta->projection && meta_is_valid_double(meta->projection->perX)) { groundPixel = (int) ((GrX-Gr0)/meta->projection->perX)+0.5; // printf("Slant %f :: ",slant); // printf("GP = (%f-%f) / %f = %i\n",GrX,Gr0,meta->projection->perX,groundPixel); } else if (meta && meta->general->data_type != COMPLEX_BYTE && meta->general->data_type != COMPLEX_INTEGER16 && meta->general->data_type != COMPLEX_INTEGER32 && meta->general->data_type != COMPLEX_REAL32 && meta->general->data_type != COMPLEX_REAL64 ) { groundPixel = (int) ((GrX-Gr0)/meta->general->x_pixel_size)+0.5; // printf("Slant %f :: ",slant); // printf("GP = (%f-%f) / %f = %i\n",GrX,Gr0,meta->general->x_pixel_size,groundPixel); } else { groundPixel=0; // just to quiet the compiler warning asfPrintError("Cannot convert slant range to ground range without a valid perX size.\n"); } return(groundPixel);}
int is_ignored_rgb(ImageStatsRGB *stats, float val) { if (!meta_is_valid_double(val)) // always ignore NaN return TRUE; else if (stats->have_no_data && val == stats->no_data_value) return TRUE; else if (stats->have_no_data_range && val >= stats->no_data_min && val <= stats->no_data_max) return TRUE; else return FALSE; }
int meta_uses_incid_polynomial(meta_parameters *meta) { return strcmp_case(meta->general->sensor, "ALOS") == 0 && strcmp_case(meta->general->sensor_name, "SAR") == 0 && meta_is_valid_double(meta->sar->incid_a[0]) && meta->sar->incid_a[0] != 0 && meta->sar->incid_a[1] != 0 && meta->sar->incid_a[2] != 0 && meta->sar->incid_a[3] != 0 && meta->sar->incid_a[4] != 0 && meta->sar->incid_a[5] != 0; }
static void set_ignores(ImageInfo *ii, int from_gui) { if (ii->data_ci->data_type == GREYSCALE_FLOAT || ii->data_ci->data_type == GREYSCALE_BYTE) { ImageStats *stats = &ii->stats; if (from_gui) { stats->have_no_data = get_checked("gs_ignore_value_checkbutton"); if (stats->have_no_data) stats->no_data_value = get_double_from_entry("gs_ignore_value_entry"); else stats->no_data_value = 0; stats->have_no_data_range = get_checked("gs_ignore_range_checkbutton"); if (stats->have_no_data_range) { stats->no_data_min = get_double_from_entry("gs_ignore_range_min_entry"); stats->no_data_max = get_double_from_entry("gs_ignore_range_max_entry"); } else { stats->no_data_min = 0; stats->no_data_max = 0; } } else { if (meta_is_valid_double(ii->meta->general->no_data)) { stats->have_no_data = TRUE; stats->no_data_value = ii->meta->general->no_data; } else { stats->have_no_data = FALSE; stats->no_data_value = -99999; // should never be checked } stats->have_no_data_range = FALSE; } } else { if (from_gui) { set_ignores_rgb(&ii->stats_r, "red"); set_ignores_rgb(&ii->stats_g, "green"); set_ignores_rgb(&ii->stats_b, "blue"); } else { ii->stats_r.have_no_data = FALSE; ii->stats_r.have_no_data_range = FALSE; ii->stats_g.have_no_data = FALSE; ii->stats_g.have_no_data_range = FALSE; ii->stats_b.have_no_data = FALSE; ii->stats_b.have_no_data_range = FALSE; } } }
static int line_samp_ok(double line, double samp) { if (!meta_is_valid_double(line) || !meta_is_valid_double(samp)) { asfPrintWarning("Invalid line/sample values: line %f, sample %f.\n", line, samp); return FALSE; } else { int nl = curr->meta->general->line_count; int ns = curr->meta->general->sample_count; if (line < 0 || line > nl || samp < 0 || samp > ns) { // we could actually plot the point if it isn't "too crazy" // we define "too crazy" as more than an image width/height out if (line < -nl || line > 2*nl || samp <-ns || samp > 2*ns) { asfPrintWarning("Point is outside the image: line %f, sample %f.\n" "Ignoring this point -- too far outside the image.\n", line, samp); return FALSE; } else { asfPrintWarning("Point is outside the image: line %f, sample %f.\n", line, samp); return TRUE; } } else { // normal case: inside the image return TRUE; } } // not reached assert(0); return FALSE; }
meta_parameters *iso2meta(iso_meta *iso) { int ii; meta_parameters *meta = raw_init(); char str[30]; // Convenience pointers iso_generalHeader *header = iso->generalHeader; iso_productComponents *comps = iso->productComponents; iso_productInfo *info = iso->productInfo; iso_productSpecific *spec = iso->productSpecific; iso_setup *setup = iso->setup; iso_processing *proc = iso->processing; iso_instrument *inst = iso->instrument; iso_platform *platform = iso->platform; iso_productQuality *quality = iso->productQuality; meta->meta_version = 3.5; // General block for (ii=0; ii<comps->numAnnotations; ii++) if (comps->annotation[ii].type == MAIN_TYPE) strncpy(meta->general->basename, comps->annotation[ii].file.name, 256); strcpy(meta->general->sensor, header->mission); strcpy(meta->general->sensor_name, info->sensor); strcpy(meta->general->mode, info->elevationBeamConfiguration); strcpy(meta->general->receiving_station, info->receivingStation); strcpy(meta->general->processor, header->generationSystem); if (info->imageDataType == DETECTED_DATA_TYPE && info->imageDataDepth == 8) meta->general->data_type = ASF_BYTE; else if (info->imageDataType == DETECTED_DATA_TYPE && info->imageDataDepth == 16) meta->general->data_type = INTEGER16; else if (info->imageDataType == DETECTED_DATA_TYPE && info->imageDataDepth == 32) // assumption here is that we are not dealing with INTERGER32 meta->general->data_type = REAL32; else if (info->imageDataType == DETECTED_DATA_TYPE && info->imageDataDepth == 64) meta->general->data_type = REAL64; else if (info->imageDataType == COMPLEX_DATA_TYPE && info->imageDataDepth == 8) meta->general->data_type = COMPLEX_BYTE; else if (info->imageDataType == COMPLEX_DATA_TYPE && info->imageDataDepth == 16) meta->general->data_type = COMPLEX_INTEGER16; else if (info->imageDataType == COMPLEX_DATA_TYPE && info->imageDataDepth == 32) // assumption here is that we are not dealing with COMPLEX_INTEGER32 meta->general->data_type = COMPLEX_REAL32; else if (info->imageDataType == COMPLEX_DATA_TYPE && info->imageDataDepth == 64) meta->general->data_type = COMPLEX_REAL64; if (info->imageDataType == RAW_DATA_TYPE) meta->general->image_data_type = RAW_IMAGE; else if (info->imageDataType == COMPLEX_DATA_TYPE) meta->general->image_data_type = COMPLEX_IMAGE; else if (info->imageDataType == DETECTED_DATA_TYPE) meta->general->image_data_type = AMPLITUDE_IMAGE; // more detailed mapping of imageDataType will probably need pixelValueID // context if (strcmp_case(info->pixelValueID, "RADAR BRIGHTNESS") == 0) meta->general->radiometry = r_AMP; // dealing with any form of calibration not implemented yet dateTime2str(info->sceneCenterCoord.azimuthTimeUTC, meta->general->acquisition_date); meta->general->orbit = info->absOrbit; if (info->orbitDirection == ASCENDING) meta->general->orbit_direction = 'A'; else if (info->orbitDirection == DESCENDING) meta->general->orbit_direction = 'D'; meta->general->frame = setup->frameID; meta->general->band_count = comps->numLayers; strcpy(meta->general->bands, polLayer2str(comps->imageData[0].polLayer)); for (ii=1; ii<comps->numLayers; ii++) { sprintf(str, ", %s", polLayer2str(comps->imageData[ii].polLayer)); strcat(meta->general->bands, str); } meta->general->line_count = info->numberOfRows; meta->general->sample_count = info->numberOfColumns; meta->general->start_line = info->startRow; meta->general->start_sample = info->startColumn; meta->general->x_pixel_size = info->groundRangeResolution; meta->general->y_pixel_size = info->azimuthResolution; meta->general->center_latitude = info->sceneCenterCoord.lat; meta->general->center_longitude = info->sceneCenterCoord.lon; spheroid_type_t spheroid = WGS84_SPHEROID; // FIXME: needs to know reference spheroid_axes_lengths(spheroid, &meta->general->re_major, &meta->general->re_minor); meta->general->bit_error_rate = quality->imageDataQuality[0].bitErrorRate; meta->general->missing_lines = quality->imageDataQuality[0].missingLines; meta->general->no_data = (float) quality->imageDataQuality[0].noData; // SAR block meta->sar = meta_sar_init(); if (info->projection == SLANTRANGE_PROJ) meta->sar->image_type = 'S'; else if (info->projection == GROUNDRANGE_PROJ) meta->sar->image_type = 'G'; else if (info->projection == MAP_PROJ) meta->sar->image_type = 'P'; if (setup->lookDirection == RIGHT_LOOK) meta->sar->look_direction = 'R'; else if (setup->lookDirection == LEFT_LOOK) meta->sar->look_direction = 'L'; meta->sar->azimuth_look_count = info->azimuthLooks; meta->sar->range_look_count = info->rangeLooks; if (spec->imageCoordinateType == RAW_COORD) meta->sar->deskewed = FALSE; else if (spec->imageCoordinateType == ZERODOPPLER) meta->sar->deskewed = TRUE; meta->general->line_scaling = info->rowScaling; meta->general->sample_scaling = info->columnScaling; meta->sar->range_time_per_pixel = info->columnSpacing; meta->sar->azimuth_time_per_pixel = info->rowSpacing; meta->sar->slant_shift = spec->slantRangeShift; //meta->sar->slant_range_first_pixel = info->rangeTimeFirstPixel * SPD_LIGHT; meta->sar->slant_range_first_pixel = spec->projectedSpacingSlantRange; meta->sar->wavelength = SPD_LIGHT / inst->centerFrequency; meta->sar->prf = spec->commonPRF; meta->sar->earth_radius = info->earthRadius; meta->sar->satellite_height = info->satelliteHeight; // meta->sar->satellite_binary_time; // meta->sar->satellite_clock_time; for (ii=0; ii<=proc->doppler[0].polynomialDegree; ii++) meta->sar->range_doppler_coefficients[ii] = proc->doppler[0].coefficient[ii]; meta->sar->azimuth_doppler_coefficients[0] = proc->doppler[0].coefficient[0]; // meta->sar->chirp_rate // meta->sar->pulse_duration meta->sar->range_sampling_rate = spec->commonRSF; if (info->polarizationMode == SINGLE_POL) strcpy(meta->sar->polarization, "SINGLE"); else if (info->polarizationMode == DUAL_POL) strcpy(meta->sar->polarization, "DUAL"); else if (info->polarizationMode == QUAD_POL) strcpy(meta->sar->polarization, "QUAD"); meta->sar->multilook = proc->multiLookedFlag; meta->sar->pitch = info->pitch; meta->sar->roll = info->roll; meta->sar->yaw = info->yaw; meta->sar->incid_a[0] = info->sceneCenterCoord.incidenceAngle; meta->sar->heading_angle = info->headingAngle; meta->sar->chirp_rate = proc->processingParameter[0].chirpRate; meta->sar->pulse_duration = proc->processingParameter[0].pulseDuration; // meta->projection // meta->transform // meta->airsar // meta->uavsar // meta->statistics int numVectors = platform->numStateVectors; meta->state_vectors = meta_state_vectors_init(numVectors); meta->state_vectors->vector_count = numVectors; ymd_date ymdStart, ymdSV; julian_date jd; hms_time hmsStart, hmsSV; ymdStart.year = info->startTimeUTC.year; ymdStart.month = info->startTimeUTC.month; ymdStart.day = info->startTimeUTC.day; hmsStart.hour = info->startTimeUTC.hour; hmsStart.min = info->startTimeUTC.min; hmsStart.sec = info->startTimeUTC.second; meta->state_vectors->year = info->startTimeUTC.year; date_ymd2jd(&ymdStart, &jd); meta->state_vectors->julDay = jd.jd; meta->state_vectors->second = date_hms2sec(&hmsStart); for (ii=0; ii<numVectors; ii++) { ymdSV.year = platform->stateVec[ii].timeUTC.year; ymdSV.month = platform->stateVec[ii].timeUTC.month; ymdSV.day = platform->stateVec[ii].timeUTC.day; hmsSV.hour = platform->stateVec[ii].timeUTC.hour; hmsSV.min = platform->stateVec[ii].timeUTC.min; hmsSV.sec = platform->stateVec[ii].timeUTC.second; meta->state_vectors->vecs[ii].time = time_difference(&ymdSV, &hmsSV, &ymdStart, &hmsStart); meta->state_vectors->vecs[ii].vec.pos.x = platform->stateVec[ii].posX; meta->state_vectors->vecs[ii].vec.pos.y = platform->stateVec[ii].posY; meta->state_vectors->vecs[ii].vec.pos.z = platform->stateVec[ii].posZ; meta->state_vectors->vecs[ii].vec.vel.x = platform->stateVec[ii].velX; meta->state_vectors->vecs[ii].vec.vel.y = platform->stateVec[ii].velY; meta->state_vectors->vecs[ii].vec.vel.z = platform->stateVec[ii].velZ; } if (meta->sar->azimuth_time_per_pixel > 0) meta->sar->time_shift = 0.0; else meta->sar->time_shift = meta->state_vectors->vecs[numVectors-1].time; if (meta->sar->yaw == 0 || !meta_is_valid_double(meta->sar->yaw)) { meta->sar->yaw = meta_yaw(meta, meta->general->line_count/2.0, meta->general->sample_count/2.0); } /* // few calculations need state vectors meta->sar->earth_radius = meta_get_earth_radius(meta, line_count/2, sample_count/2); // meta->sar->earth_radius_pp meta->sar->satellite_height = meta_get_sat_height(meta, meta->general->line_count/2, meta->general->sample_count/2); meta->sar->incid_a[0] = meta_incid(meta, line_count/2, sample_count/2)*R2D; */ // Location block meta_get_corner_coords(meta); /* meta->location = meta_location_init(); for (ii=0; ii<4; ii++) { if (info->sceneCornerCoord[ii].refRow == 0 && info->sceneCornerCoord[ii].refColumn == 0) { meta->location->lat_start_near_range = info->sceneCornerCoord[ii].lat; meta->location->lon_start_near_range = info->sceneCornerCoord[ii].lon; } else if (info->sceneCornerCoord[ii].refRow == 0 && info->sceneCornerCoord[ii].refColumn == sample_count) { meta->location->lat_start_far_range = info->sceneCornerCoord[ii].lat; meta->location->lon_start_far_range = info->sceneCornerCoord[ii].lon; } else if (info->sceneCornerCoord[ii].refRow == line_count && info->sceneCornerCoord[ii].refColumn == 0) { meta->location->lat_end_near_range = info->sceneCornerCoord[ii].lat; meta->location->lon_end_near_range = info->sceneCornerCoord[ii].lon; } else if (info->sceneCornerCoord[ii].refRow == line_count && info->sceneCornerCoord[ii].refColumn == sample_count) { meta->location->lat_end_far_range = info->sceneCornerCoord[ii].lat; meta->location->lon_end_far_range = info->sceneCornerCoord[ii].lon; } } */ return meta; }
int asf_windspeed(platform_type_t platform_type, char *band_id, double wind_dir, int cmod4, double landmaskHeight, char *landmaskFile, char *demFile, char *inBaseName, char *colormapName, char *outBaseName) { char *inDataName, outDataName[1024], outMetaName[1024]; FILE *in = NULL, *out = NULL; asfPrintStatus("\n Determining windspeeds in: %s\n", inBaseName); strcpy(outDataName, outBaseName); strcpy(outMetaName, outBaseName); inDataName = (char *)MALLOC(sizeof(char) * (strlen(inBaseName) + 10)); strcpy(inDataName, inBaseName); append_ext_if_needed(inDataName, ".img", NULL); append_ext_if_needed(outDataName, ".img", NULL); append_ext_if_needed(outMetaName, ".meta", NULL); // New images for processing in to out meta_parameters *imd = meta_read(inBaseName); meta_general *img = imd->general; // convenience ptr meta_parameters *omd = meta_read(inBaseName); meta_general *omg = omd->general; // convenience ptr meta_sar *oms = omd->sar; // convenience ptr omg->band_count = 0; strcpy(omg->bands, ""); strcpy(oms->polarization, ""); if (strstr(img->bands, "VV") == NULL && strstr(img->bands, "HH") == NULL) { asfPrintError("Cannot find any VV or HH polarized bands in this data. Available\n" "bands are %s). Wind speeds can only be determined on Sigma0-\n" "calibrated SAR data in HH or VV polarizations.\n", img->bands); } in = (FILE *)FOPEN(inDataName, "rb"); out = (FILE *)FOPEN(outDataName, "wb"); FREE(inDataName); // For each band double alpha = 1.0; // Default for VV polarization; int band_num; float *data = (float *)MALLOC(sizeof(float) * img->sample_count); for (band_num = 0; band_num < img->band_count; band_num++) { // Get band name, check for proper polarization, and create new output bandname, set alpha char *band_name = get_band_name(img->bands, img->band_count, band_num); long offset = img->line_count * band_num; char polarization[2]=""; if (strncmp_case(band_name, "SIGMA-VV", 8) == 0 || strncmp_case(band_name, "SIGMA-HH", 8) == 0) { asfPrintStatus("\nProcessing wind speed calculations on band %s...\n\n", band_name); (omg->band_count)++; strcpy(polarization, (strstr(band_name, "VV") != NULL) ? "VV" : "HH"); strcpy(oms->polarization, polarization); sprintf(&omg->bands[strlen(omg->bands)], "%s%s%s", WINDSPEED_BAND_BASENAME, polarization, (band_num < img->band_count - 1 && img->band_count > 0) ? ", " : ""); alpha = (strcmp(polarization, "VV") == 0) ? 1.0 : DEFAULT_HH_POL_ALPHA; // For CMODx } else { asfPrintStatus("\nFound band: %s (Cannot calculate wind speed on this type of band)\n\n", band_name); continue; // Skip this band } // Calculate average r_look for entire image (r_look is the angle between the NADIR line // and a line point directly north, the 'look angle' of the platform.) double r_look = asf_r_look(imd); double phi_diff = wind_dir - r_look; // Pre-populate incidence angles (as a function of sample) and get min/max incidence angle // as well int line, sample; double *incids = (double *)MALLOC(img->sample_count * sizeof(double)); double min_incid = DBL_MAX; double max_incid = DBL_MIN; for (sample = 0; sample < img->sample_count; sample++) { incids[sample] = R2D * meta_incid(imd, img->line_count / 2, sample); min_incid = (incids[sample] < min_incid) ? incids[sample] : min_incid; max_incid = (incids[sample] > max_incid) ? incids[sample] : max_incid; } // Get min/max radar cross-sections asfPrintStatus("\nFinding min/max radar cross-sections...\n\n"); double rcs_min = DBL_MAX; double rcs_max = DBL_MIN; for (line = 0; line < img->line_count; line++) { // Get a line get_float_line(in, imd, line+offset, data); for (sample = 0; sample < img->sample_count; sample++) { if (meta_is_valid_double(data[sample]) && data[sample] >= 0.0) { rcs_min = (data[sample] < rcs_min) ? data[sample] : rcs_min; rcs_max = (data[sample] > rcs_max) ? data[sample] : rcs_max; } } asfLineMeter(line, img->line_count); } // FIXME: Generate 2D array of windspeeds here. One dimension is incidence angle and // the other is radar cross-section. The values in the table are wind speed as a function // of incidence angle and radar cross-section (given the provided wind direction.) The idea // is to more-quickly populate a grid of results and then to interpolate results for each // pixel of the image rather then perform the full calculation (very sloooow) double windspeed1 = 0.0, windspeed2 = 0.0; for (line = 0; line < img->line_count; line++) { // Get a line get_float_line(in, imd, line+offset, data); for (sample = 0; sample < img->sample_count; sample++) { // FIXME: Here is where we should apply a land mask ...in this if-statement expression if (meta_is_valid_double(data[sample]) && data[sample] >= 0.0) { // Calculate windspeed // FIXME: This returns the angle, at the target pixel location, between straight up // and the line to the satellite. Make sure Frank's code doesn't assume the angle // between the line to the satellite and a horizontal line, i.e. 90 degrees minus // this angle. double incidence_angle = incids[sample]; switch (platform_type) { case p_RSAT1: if (!cmod4) { // Use CMOD5 to calculate windspeeds double hh = alpha; ws_inv_cmod5((double)data[sample], phi_diff, incidence_angle, &windspeed1, &windspeed2, (double)MIN_CMOD5_WINDSPEED, (double)MAX_CMOD5_WINDSPEED, 25, hh); data[sample] = windspeed1; // When 2 answers exist, take the lower (per Frank Monaldo) } else { // Use CMOD4 to calculate windspeeds asfPrintError("The CMOD4 algorithm is not yet supported. Avoid the -cmod4\n" "option for now and let %s default to using the CMOD5 algorithm\n" "instead.\n"); } break; case p_PALSAR: case p_TERRASARX: case p_ERS1: case p_ERS2: default: asfPrintError("Found a platform type (%s) that is not yet supported.\n", (platform_type == p_PALSAR) ? "PALSAR" : (platform_type == p_TERRASARX) ? "TerraSAR-X" : (platform_type == p_ERS1) ? "ERS-1" : (platform_type == p_ERS2) ? "ERS-2" : "UNKNOWN PLATFORM"); } } } put_float_line(out, omd, line+offset, data); asfLineMeter(line, img->line_count); } } // end for (each band) FREE(data); // Insert colormap into metadata meta_write(omd, outMetaName); meta_free(imd); meta_free(omd); asfPrintStatus("Windspeed calculation complete.\n\n"); return EXIT_SUCCESS; }
int open_google_earth() { char *kml_filename = appendExt(curr->filename, ".kml"); char *basename = get_basename(curr->filename); char *dirname = get_dirname(curr->filename); char *arg; if (strlen(dirname)==0) { char *tmpdir = g_get_current_dir(); dirname = escapify(tmpdir); arg = MALLOC(sizeof(char)*(strlen(dirname)+strlen(kml_filename)+20)); sprintf(arg, "%s/%s", dirname, kml_filename); //free(tmpdir); } else { arg = STRDUP(kml_filename); } char *png_file = appendExt(arg, ".png"); printf("png file: %s\n", png_file); printf("Temporary kml file: %s\n", arg); FILE *kml_file = fopen(arg, "w"); if (!kml_file) { asfPrintWarning("Couldn't open kml file!\n"); return FALSE; } dbf_header_t *dbf; int nAttr, nCoords; double *lat, *lon, center_lat, center_lon; char configFile[255], *name; meta_parameters *meta; sprintf(configFile, "%s/convert2vector.config", get_asf_share_dir()); c2v_config *cfg = read_c2v_config(configFile); kml_header(kml_file); meta = meta2vector(curr->filename, &dbf, &nAttr, &lat, &lon, &nCoords); //meta_parameters *meta = curr->meta; if (meta && meta->general && meta_is_valid_double(meta->general->center_latitude) && meta_is_valid_double(meta->general->center_longitude)) { pixbuf2png(pixbuf_small, png_file); //kml_entry_with_overlay(kml_file, meta, basename, png_file, dirname); name = get_basename(kml_filename); center_lat = meta->general->center_latitude; center_lon = meta->general->center_longitude; write_kml_placemark(kml_file, name, center_lat, center_lon, png_file, dbf, nAttr, lat, lon, nCoords, cfg); FREE(lat); FREE(lon); FREE(dbf); } else { asfPrintWarning( "Failed, metadata doesn't contain valid lat/lon info.\n"); return FALSE; } kml_footer(kml_file); fclose(kml_file); gchar *ge; printf("kml: %s\n", kml_filename); printf("dir: %s\n", dirname); #ifdef win32 char path[1024]; FindExecutable((LPCTSTR)kml_filename, (LPCTSTR)dirname, (LPTSTR)path); ge = escapify(path); printf("Path to google earth: %s\n", ge); asfSystem("\"%s\" \"%s\"", ge, arg); #else ge = find_in_path("googleearth"); if (!ge) { message_box("Couldn't find googleearth! Is it installed?"); return FALSE; } int pid = fork(); if (pid == 0) { asfSystem("\"%s\" \"%s\"", ge, arg); //unlink(kml_filename); exit(EXIT_SUCCESS); } #endif free(kml_filename); free(basename); free(dirname); free(arg); return TRUE; }
int open_google_earth() { char *kml_filename = appendExt(curr->filename, ".kml"); char *basename = get_basename(curr->filename); char *dirname = get_dirname(curr->filename); char *arg; if (strlen(dirname)==0) { char *tmpdir = g_get_current_dir(); dirname = escapify(tmpdir); arg = MALLOC(sizeof(char)*(strlen(dirname)+strlen(kml_filename)+20)); sprintf(arg, "%s/%s", dirname, kml_filename); //free(tmpdir); } else { arg = STRDUP(kml_filename); } char *png_file = appendExt(arg, ".png"); printf("png file: %s\n", png_file); printf("Temporary kml file: %s\n", arg); FILE *kml_file = fopen(arg, "w"); if (!kml_file) { asfPrintWarning("Couldn't open kml file!\n"); return FALSE; } kml_header(kml_file); meta_parameters *meta = curr->meta; if (meta && meta->general && meta_is_valid_double(meta->general->center_latitude) && meta_is_valid_double(meta->general->center_longitude)) { pixbuf2png(pixbuf_small, png_file); kml_entry_with_overlay(kml_file, meta, basename, png_file, dirname); } else { asfPrintWarning( "Failed, metadata doesn't contain valid lat/lon info.\n"); return FALSE; } kml_footer(kml_file); fclose(kml_file); gchar *ge; printf("kml: %s\n", kml_filename); printf("dir: %s\n", dirname); #ifdef win32 char path[1024]; FindExecutable((LPCTSTR)kml_filename, (LPCTSTR)dirname, (LPTSTR)path); ge = escapify(path); printf("Path to google earth: %s\n", ge); asfSystem("\"%s\" \"%s\"", ge, arg); #else ge = find_in_path("googleearth"); if (!ge) { message_box("Couldn't find googleearth! Is it installed?"); return FALSE; } int pid = fork(); if (pid == 0) { asfSystem("\"%s\" \"%s\"", ge, arg); //unlink(kml_filename); exit(EXIT_SUCCESS); } #endif free(kml_filename); free(basename); free(dirname); free(arg); return TRUE; }
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 }
// return TRUE if there is any overlap between the two scenes static int test_overlap(meta_parameters *meta1, meta_parameters *meta2) { if (!meta_is_valid_double(meta1->general->center_longitude)) { int nl = meta1->general->line_count; int ns = meta1->general->sample_count; meta_get_latLon(meta1, nl/2, ns/2, 0, &meta1->general->center_latitude, &meta1->general->center_longitude); } if (!meta_is_valid_double(meta2->general->center_longitude)) { int nl = meta2->general->line_count; int ns = meta2->general->sample_count; meta_get_latLon(meta2, nl/2, ns/2, 0, &meta2->general->center_latitude, &meta2->general->center_longitude); } int zone1 = utm_zone(meta1->general->center_longitude); int zone2 = utm_zone(meta2->general->center_longitude); // if zone1 & zone2 differ by more than 1, we can stop now if (iabs(zone1-zone2) > 1) { return FALSE; } // The Plan: // Generate polygons for each metadata, then test of any pair of // line segments between the polygons intersect. // Other possibility: meta1 is completely contained within meta2, // or the reverse. // corners of meta1. double xp_1[5], yp_1[5]; if (meta1->location) { // use the location block if available latLon2UTM_zone(meta1->location->lat_start_near_range, meta1->location->lon_start_near_range, 0, zone1, &xp_1[0], &yp_1[0]); latLon2UTM_zone(meta1->location->lat_start_far_range, meta1->location->lon_start_far_range, 0, zone1, &xp_1[1], &yp_1[1]); latLon2UTM_zone(meta1->location->lat_end_far_range, meta1->location->lon_end_far_range, 0, zone1, &xp_1[2], &yp_1[2]); latLon2UTM_zone(meta1->location->lat_end_near_range, meta1->location->lon_end_near_range, 0, zone1, &xp_1[3], &yp_1[3]); } else { double lat, lon; int nl1 = meta1->general->line_count; int ns1 = meta1->general->sample_count; // must call meta_get_latLon for each corner meta_get_latLon(meta1, 0, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[0], &yp_1[0]); meta_get_latLon(meta1, nl1-1, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[1], &yp_1[1]); meta_get_latLon(meta1, nl1-1, ns1-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[2], &yp_1[2]); meta_get_latLon(meta1, 0, ns1-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_1[3], &yp_1[3]); } // close the polygon xp_1[4] = xp_1[0]; yp_1[4] = yp_1[0]; // corners of meta2. double xp_2[5], yp_2[5]; if (meta2->location) { // use the location block if available latLon2UTM_zone(meta2->location->lat_start_near_range, meta2->location->lon_start_near_range, 0, zone1, &xp_2[0], &yp_2[0]); latLon2UTM_zone(meta2->location->lat_start_far_range, meta2->location->lon_start_far_range, 0, zone1, &xp_2[1], &yp_2[1]); latLon2UTM_zone(meta2->location->lat_end_far_range, meta2->location->lon_end_far_range, 0, zone1, &xp_2[2], &yp_2[2]); latLon2UTM_zone(meta2->location->lat_end_near_range, meta2->location->lon_end_near_range, 0, zone1, &xp_2[3], &yp_2[3]); } else { double lat, lon; int nl2 = meta2->general->line_count; int ns2 = meta2->general->sample_count; // must call meta_get_latLon for each corner meta_get_latLon(meta2, 0, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[0], &yp_2[0]); meta_get_latLon(meta2, nl2-1, 0, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[1], &yp_2[1]); meta_get_latLon(meta2, nl2-1, ns2-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[2], &yp_2[2]); meta_get_latLon(meta2, 0, ns2-1, 0, &lat, &lon); latLon2UTM_zone(lat, lon, 0, zone1, &xp_2[3], &yp_2[3]); } // close the polygon xp_2[4] = xp_2[0]; yp_2[4] = yp_2[0]; // loop over each pair of line segments, testing for intersection int i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { if (lineSegmentsIntersect( xp_1[i], yp_1[i], xp_1[i+1], yp_1[i+1], xp_2[j], yp_2[j], xp_2[j+1], yp_2[j+1])) { return TRUE; } } } // test for containment: meta2 in meta1 int all_in=TRUE; for (i=0; i<4; ++i) { if (!pnpoly(5, xp_1, yp_1, xp_2[i], yp_2[i])) { all_in=FALSE; break; } } if (all_in) return TRUE; // test for containment: meta1 in meta2 all_in = TRUE; for (i=0; i<4; ++i) { if (!pnpoly(5, xp_2, yp_2, xp_1[i], yp_1[i])) { all_in=FALSE; break; } } if (all_in) return TRUE; // no overlap return FALSE; }
static int save_as_asf(ImageInfo *ii, const char *out_file, int what_to_save, int strict_boundary, int load) { // See if we can open the output file up front FILE *outFp = fopen(out_file, "wb"); if (!outFp) { // failed to open the output file! char errbuf[1024]; snprintf(errbuf, 1024, "Failed to open %s: %s", out_file, strerror(errno)); message_box(errbuf); strcat(errbuf, "\n"); printf("%s", errbuf); return FALSE; // failure } assert (g_poly->n > 0); assert (crosshair_line > 0 && crosshair_samp > 0); meta_parameters *meta = ii->meta; // figure out where to chop int line_min, line_max, samp_min, samp_max, nl, ns; compute_extent(meta, &line_min, &line_max, &samp_min, &samp_max, &nl, &ns); // generate metadata char *out_metaname = appendExt(out_file, ".meta"); printf("Generating %s...\n", out_metaname); // data will be saved as floating point, except scaled pixel values, // which we can make bytes. data_type_t data_type = REAL32; if (what_to_save == SCALED_PIXEL_VALUE) data_type = ASF_BYTE; meta_parameters *out_meta = build_metadata(meta, out_file, nl, ns, line_min, samp_min, data_type, what_to_save); // put_float_line() will always dump BYTE data if the optical block // is present... we want to be in control of the data type, so we must // wipe out this block if (out_meta->optical) { FREE(out_meta->optical); out_meta->optical=NULL; } if (what_to_save == LAT_LON_2_BAND) { out_meta->general->band_count = 2; strcpy(out_meta->general->bands, "LAT,LON"); } // define clipping region, if necessary double xp[MAX_POLY_LEN+2], yp[MAX_POLY_LEN+2]; int i,j,n=0; if (strict_boundary) define_clipping_region(meta, &n, xp, yp); float ndv = 0; if (meta_is_valid_double(out_meta->general->no_data)) ndv = out_meta->general->no_data; else if (strict_boundary) // need to set a no data value in this case out_meta->general->no_data = 0.; meta_write(out_meta, out_metaname); // now actually write the data printf("Generating %s...\n", out_file); if (what_to_save == LAT_LON_2_BAND) { // dump a 2-band image, lat & lon data float *lats = MALLOC(sizeof(float)*ns); float *lons = MALLOC(sizeof(float)*ns); for (i=0; i<nl; ++i) { int l = line_min+i; for (j=0; j<ns; ++j) { int s = samp_min+j; if (!strict_boundary || pnpoly(n, xp, yp, s, l)) { double lat, lon; meta_get_latLon(meta, l, s, 0, &lat, &lon); lats[j] = (float)lat; lons[j] = (float)lon; } else { lats[j] = ndv; lons[j] = ndv; } } put_band_float_line(outFp, out_meta, 0, i, lats); put_band_float_line(outFp, out_meta, 1, i, lons); asfLineMeter(i,nl); } free(lats); free(lons); } else { // normal case float *buf = MALLOC(sizeof(float)*ns); for (i=0; i<nl; ++i) { int l = line_min+i; for (j=0; j<ns; ++j) { int s = samp_min+j; float val; if (!strict_boundary || pnpoly(n, xp, yp, s, l)) { val = get_data(ii, what_to_save, l, s); } else { val = ndv; } buf[j] = val; } put_float_line(outFp, out_meta, i, buf); asfLineMeter(i,nl); } free(buf); } fclose(outFp); meta_free(out_meta); // load the generated file if we were told to if (load) load_file(out_file); return TRUE; }
int getLook(GEOLOCATE_REC *g,double range,double yaw,double *plook) { double ht,delta_range,look; double coslook; double earth_radius; int iter; /* The lowest point on Earth is the shore of the Dead Sea (Isreal/Jordan), and is 417.5 meters below sea level. Worst case range should not indicate a level lower than this. The 450.0 m tolerance below was selected as a number larger than this because a) the code uses a simple spherical model based on the earth radius at the center of the scene, and b) look angle results in a range vector longer than what the range would've been if the lowest spot on earth fell on the NADIR line. */ double range_tolerance = 450.0; /* meters */ /* Look angle in y'z' plane, Yaw angle in z''x' plane. First guess at a look angle-- a simple spherical guess: */ /* NOTE: This function is only called when working with slant range and ground range (meta->sar->image_type == 'S' or 'G') images but not for map-projected data ...otherwise, the earth radius at center of scene may not be populated depending upon the source of the image data, e.g. if imported and geocoded entirely by ASF tools then the earth_radius field in the SAR portion of the metadata _would_ be populated, but if a GeoTIFF (for example) were imported then only the major/minor fields in the projection block would be populated, not the earth_radius field in the SAR block ...the init_geolocate_meta() takes this into account for the polar radius (g->rp) regardless, populates g->earth_radius for SAR images, but ignores g->earth_radius for projected images. But as mentioned, this is OK since getLook() is only for 'S' and 'G' (SAR) images. */ if (meta_is_valid_double(g->earth_radius)) { earth_radius = g->earth_radius; } else { earth_radius = g->rp; // FIXME: Else obtain from calcRange() ? Else default to polar radius ? } ht=vecMagnitude(g->stVec.pos); if (range < (ht - earth_radius) - range_tolerance) { asfPrintWarning("getLook(): Range vector does not reach earth!\n"); return 1; } if (ht < earth_radius - range_tolerance) { asfPrintWarning("getLook(): orbit is below earth's surface!\n"); return 1; } /* Calculate look angle */ coslook = (ht*ht+range*range-earth_radius*earth_radius)/(2.0*range*ht); if (!meta_is_valid_double(coslook)) { asfPrintWarning("getLook(): coslook was NaN!\n"); return 1; } if (coslook > 1.0) { asfPrintWarning("getLook(): cosine(look angle) resulted in a value " "larger than 1.0!\n"); return 1; } look = acos(coslook); /* For a left-looking SAR, we define the look angle to be negative.*/ if ( g->side == 'L') look=-look; /* FIXME: The use of an unweighted earth radius at center of scene will result in larger errors in regions of the image that are far (corners) from where the earth_radius value is accurate. This may be an issue for wide-swath images such as ScanSAR. */ for (iter=0;iter<100;iter++) { double sininc,taninc; delta_range = range - calcRange(g,look,yaw); /* Require decimeter convergence. */ if (fabs(delta_range) < 0.1) { *plook = look; return 0; } else { /* Havn't converged yet, so update look angle. */ sininc = (ht/earth_radius)*sin(look); /* sin of inci. angle(approx) */ taninc = sininc/sqrt(1-sininc*sininc); /* tan of inci. angle */ /* The linear approximation of atan should be applicable for these small arguments. */ look += delta_range/(range*taninc); /* update for look angle */ } } /*If we get here, our look iteration hasn't converged.*/ asfPrintWarning("Error in getLook(): look iteration didn't converge.\n"); return 1; }
int main(int argc,char *argv[]) { char infile1[256], infile2[256], infile3[256]; // Input file name char outfile[256]; // Output file name char tmpPath[1024]; browse_type_t mode = NOTYPE; int i,j; int sample_count; double scale; extern int currArg; strcpy(tmpPath, ""); // Parse command line if ((argc-currArg)<1) { printf("Insufficient arguments.\n"); usage(""); } while (currArg < (argc-2)) { char *key = argv[currArg++]; if (strmatches(key, "-sentinel", "--sentinel", NULL)) { CHECK_ARG(1); scale = atof(GET_ARG(1)); mode = SENTINEL_DUAL; } else if (strmatches(key, "-tmpDir", "--tmpDir", NULL)) { CHECK_ARG(1); strcpy(tmpPath, GET_ARG(1)); } else if (strmatches(key, "-log", "--log", NULL)) { CHECK_ARG(1); strcpy(logFile,GET_ARG(1)); fLog = FOPEN(logFile, "a"); logflag = TRUE; } else if (strmatches(key, "-quiet", "--quiet", "-q", NULL)) quietflag = TRUE; else { --currArg; break; } } if ((argc-currArg) < 2) { printf("Insufficient arguments.\n"); usage(argv[0]); } if (mode == NOTYPE && argc == 4) mode = PALSAR_FBD; else if (mode == NOTYPE && argc == 5) mode = PALSAR_PLR; if (!quietflag) asfSplashScreen(argc, argv); if (mode == PALSAR_FBD) { asfPrintStatus("Creating colorized browse image from PALSAR FBD data\n"); create_name(infile1,argv[1],".img"); create_name(infile2,argv[2],".img"); create_name(outfile,argv[3],".img"); meta_parameters *meta1 = meta_read(infile1); meta_parameters *meta2 = meta_read(infile2); if (meta1->general->line_count != meta2->general->line_count || meta1->general->sample_count != meta2->general->sample_count) { asfPrintError("Images must be the same size!!!\n"); exit(1); } strcpy(meta1->general->bands,"HH"); strcpy(meta2->general->bands,"HV"); int pixel_count = meta1->general->line_count*meta1->general->sample_count; float *buf1 = MALLOC(pixel_count * sizeof(float)); float *buf2 = MALLOC(pixel_count * sizeof(float)); float *buf3 = MALLOC(pixel_count * sizeof(float)); unsigned char *cbuf1, *cbuf2, *cbuf3; FILE *fp1 = FOPEN(infile1, "r"); FILE *fp2 = FOPEN(infile2, "r"); FILE *ofp = FOPEN(outfile, "w"); char ofile1[256]; char ofile2[256]; strcpy(ofile1,argv[1]); strcat(ofile1,"_DB.img"); strcpy(ofile2,argv[2]); strcat(ofile2,"_DB.img"); printf("Creating output DB files %s and %s\n",ofile1,ofile2); FILE *ofp1 = FOPEN(ofile1, "w"); FILE *ofp2 = FOPEN(ofile2, "w"); get_float_lines(fp1,meta1,0,meta1->general->line_count, buf1); get_float_lines(fp2,meta2,0,meta2->general->line_count, buf2); /* Convert data from sigma0 to dB */ sample_count = 0; for (i=0; i<meta1->general->line_count; ++i) { for (j=0; j<meta1->general->sample_count; ++j) { if (meta_is_valid_double(buf1[sample_count])) { if (buf1[sample_count] != 0) buf1[sample_count] = 10.0 * log10f(buf1[sample_count]); if (buf2[sample_count] != 0) buf2[sample_count] = 10.0 * log10f(buf2[sample_count]); } sample_count++; } } put_float_lines(ofp1, meta1, 0,meta1->general->line_count,buf1); put_float_lines(ofp2, meta2, 0,meta1->general->line_count,buf2); meta_write(meta1, ofile1); meta_write(meta2, ofile2); fclose(fp1); fclose(fp2); fclose(ofp1); fclose(ofp2); /* Scale the data to a byte range using given min/max values */ cbuf1 = my_floats_to_bytes(buf1,(long long) pixel_count, 0.0,MINMAX,-30.0,-1.0); cbuf2 = my_floats_to_bytes(buf2,(long long) pixel_count, 0.0,MINMAX,-30.0,-10.0); /* cbuf1 = my_floats_to_bytes(buf1,(long long) pixel_count, 0.0,MINMAX,-31.0,7.1); cbuf2 = my_floats_to_bytes(buf2,(long long) pixel_count, 0.0,MINMAX,-31.0,7.1); */ strcpy(ofile1,argv[1]); strcat(ofile1,"_byte.img"); strcpy(ofile2,argv[2]); strcat(ofile2,"_byte.img"); printf("Creating output byte files %s and %s\n",ofile1,ofile2); ofp1 = FOPEN(ofile1, "w"); ofp2 = FOPEN(ofile2, "w"); meta1->general->data_type=REAL32; meta2->general->data_type=REAL32; sample_count = 0; for (i=0; i<meta1->general->line_count; ++i) { for (j=0; j<meta1->general->sample_count; ++j) { buf1[sample_count] = (float) cbuf1[sample_count]; buf2[sample_count] = (float) cbuf2[sample_count]; sample_count++; } } put_float_lines(ofp1,meta1,0,meta1->general->line_count,buf1); put_float_lines(ofp2,meta2,0,meta2->general->line_count,buf2); meta_write(meta1, ofile1); meta_write(meta2, ofile2); fclose(ofp1); fclose(ofp2); /* Create the third band for the color image */ sample_count = 0; for (i=0; i<meta1->general->line_count; ++i) { for (j=0; j<meta1->general->sample_count; ++j) { if (buf2[sample_count] != 0) { /* buf3[sample_count] = (buf1[sample_count] / buf2[sample_count]); */ buf3[sample_count] = (buf1[sample_count] - buf2[sample_count]); if (buf3[sample_count] < 1) buf3[sample_count] = 1; else if (buf3[sample_count] > 255) buf3[sample_count] = 255; } else buf3[sample_count] = 0; sample_count++; } } cbuf3 = my_floats_to_bytes(buf3,(long long) pixel_count, 0.0,SIGMA ,-25.0,-10.0); sample_count = 0; for (i=0; i<meta1->general->line_count; ++i) { for (j=0; j<meta1->general->sample_count; ++j) { buf3[sample_count] = (float) cbuf3[sample_count]; sample_count++; } } /* Finally, create the 3 banded image we were looking for */ strcpy(meta1->general->bands,"HH,HV,DIV"); meta1->general->band_count=3; put_band_float_lines(ofp,meta1,0,0,meta1->general->line_count,buf1); put_band_float_lines(ofp,meta1,1,0,meta1->general->line_count,buf2); put_band_float_lines(ofp,meta1,2,0,meta1->general->line_count,buf3); meta_write(meta1,outfile); } else if (mode == PALSAR_PLR) { /* Mode 1 - Create Color Browse from 3 bands using 3sigma stretch */ asfPrintStatus("Creating colorized browse image from PALSAR PLR data\n"); create_name(infile1,argv[1],".img"); create_name(infile2,argv[2],".img"); create_name(infile3,argv[3],".img"); create_name(outfile,argv[4],".img"); meta_parameters *meta1 = meta_read(infile1); meta_parameters *meta2 = meta_read(infile2); meta_parameters *meta3 = meta_read(infile3); if (meta1->general->line_count != meta2->general->line_count || meta1->general->sample_count != meta2->general->sample_count) { asfPrintError("Images must be the same size!!!\n"); exit(1); } if (meta3->general->line_count != meta2->general->line_count || meta3->general->sample_count != meta2->general->sample_count) { asfPrintError("Images must be the same size!!!\n"); exit(1); } int pixel_count = meta1->general->line_count*meta1->general->sample_count; float *buf1 = MALLOC(pixel_count * sizeof(float)); float *buf2 = MALLOC(pixel_count * sizeof(float)); float *buf3 = MALLOC(pixel_count * sizeof(float)); float *buf4 = MALLOC(pixel_count * sizeof(float)); unsigned char *cbuf1, *cbuf2, *cbuf3, *cbuf4; FILE *fp1 = FOPEN(infile1, "r"); FILE *fp2 = FOPEN(infile2, "r"); FILE *fp3 = FOPEN(infile3, "r"); FILE *ofp = FOPEN(outfile, "w"); get_float_lines(fp1,meta1,0,meta1->general->line_count, buf1); get_float_lines(fp2,meta2,0,meta2->general->line_count, buf2); get_float_lines(fp3,meta3,0,meta3->general->line_count, buf3); /* Convert data from sigma0 to dB */ sample_count = 0; for (i=0; i<meta1->general->line_count; ++i) { for (j=0; j<meta1->general->sample_count; ++j) { if (meta_is_valid_double(buf1[sample_count])) { if (buf1[sample_count] != 0) buf1[sample_count] = 10.0 * log10f(buf1[sample_count]); if (buf2[sample_count] != 0) buf2[sample_count] = 10.0 * log10f(buf2[sample_count]); if (buf3[sample_count] != 0) buf3[sample_count] = 10.0 * log10f(buf3[sample_count]); } sample_count++; } } /* Scale the data to a byte range using 3-sigma stretch values */ cbuf1 = my_floats_to_bytes(buf1,(long long) pixel_count, 0.0,SIGMA3,-30.0,-1.0); cbuf2 = my_floats_to_bytes(buf2,(long long) pixel_count, 0.0,SIGMA3,-30.0,-10.0); cbuf3 = my_floats_to_bytes(buf3,(long long) pixel_count, 0.0,SIGMA3,-30.0,-10.0); meta1->general->data_type=REAL32; //meta2->general->data_type=ASF_BYTE; //meta3->general->data_type=ASF_BYTE; sample_count = 0; for (i=0; i<meta1->general->line_count; ++i) { for (j=0; j<meta1->general->sample_count; ++j) { buf1[sample_count] = (float) cbuf1[sample_count]; buf2[sample_count] = (float) cbuf2[sample_count]; buf3[sample_count] = (float) cbuf3[sample_count]; sample_count++; } } /* Finally, create the 3 banded image we were looking for */ strcpy(meta1->general->bands,"HH,HV,VV"); meta1->general->band_count=3; put_band_float_lines(ofp,meta1,0,0,meta1->general->line_count,buf1); put_band_float_lines(ofp,meta1,1,0,meta1->general->line_count,buf2); put_band_float_lines(ofp,meta1,2,0,meta1->general->line_count,buf3); meta_write(meta1,outfile); } else if (mode == SENTINEL_DUAL) { asfPrintStatus("Creating colorized browse image from Sentinel dual-pol " "data\n"); if (strlen(tmpPath) > 0) { create_name(infile1,argv[5],".img"); create_name(infile2,argv[6],".img"); create_name(outfile,argv[7],".tif"); } else { create_name(infile1,argv[3],".img"); create_name(infile2,argv[4],".img"); create_name(outfile,argv[5],".tif"); } // Create temporary directory char tmpDir[1024]; if (strlen(tmpPath) > 0) sprintf(tmpDir, "%s%cbrowse-", tmpPath, DIR_SEPARATOR); else strcpy(tmpDir, "browse-"); strcat(tmpDir, time_stamp_dir()); create_clean_dir(tmpDir); asfPrintStatus("Temp dir is: %s\n", tmpDir); // Calculate ratio image char tmpRatio[512], tmpRed[512], tmpGreen[512], tmpBlue[512], tmpIn[512]; char *inFiles[2]; inFiles[0] = (char *) MALLOC(sizeof(char)*255); inFiles[1] = (char *) MALLOC(sizeof(char)*255); strcpy(inFiles[0], infile1); strcpy(inFiles[1], infile2); sprintf(tmpRatio, "%s%cdiv.img", tmpDir, DIR_SEPARATOR); raster_calc(tmpRatio, "a/b", 2, inFiles); // Resample all three bands and scale to byte meta_parameters *metaIn = meta_read(tmpRatio); double scaleFactor = 1.0/(scale/metaIn->general->x_pixel_size); meta_free(metaIn); sprintf(tmpIn, "%s%cred.img", tmpDir, DIR_SEPARATOR); resample(infile1, tmpIn, scaleFactor, scaleFactor); sprintf(tmpRed, "%s%cred_byte.img", tmpDir, DIR_SEPARATOR); floats_to_bytes_from_file(tmpIn, tmpRed, NULL, -40.0, SIGMA); sprintf(tmpIn, "%s%cgreen.img", tmpDir, DIR_SEPARATOR); resample(infile2, tmpIn, scaleFactor, scaleFactor); sprintf(tmpGreen, "%s%cgreen_byte.img", tmpDir, DIR_SEPARATOR); floats_to_bytes_from_file(tmpIn, tmpGreen, NULL, -40.0, SIGMA); sprintf(tmpIn, "%s%cblue.img", tmpDir, DIR_SEPARATOR); resample(tmpRatio, tmpIn, scaleFactor, scaleFactor); sprintf(tmpBlue, "%s%cblue_byte.img", tmpDir, DIR_SEPARATOR); floats_to_bytes_from_file(tmpIn, tmpBlue, NULL, -40.0, SIGMA); // Layer stack the bands char tmpBrowse[512]; sprintf(tmpBrowse, "%s%cbrowse.img", tmpDir, DIR_SEPARATOR); FILE *fpOut = FOPEN(tmpBrowse, "w"); meta_parameters *metaOut = meta_read(tmpRed); metaOut->general->band_count = 3; metaIn = meta_read(tmpRed); int line_count = metaIn->general->line_count; int sample_count = metaIn->general->sample_count; float *buf = (float *) MALLOC(sizeof(float)*line_count*sample_count); FILE *fpIn = FOPEN(tmpBlue, "r"); get_float_lines(fpIn, metaIn, 0, line_count, buf); put_band_float_lines(fpOut, metaOut, 0, 0, line_count, buf); FCLOSE(fpIn); fpIn = FOPEN(tmpGreen, "r"); get_float_lines(fpIn, metaIn, 0, line_count, buf); put_band_float_lines(fpOut, metaOut, 1, 0, line_count, buf); FCLOSE(fpIn); fpIn = FOPEN(tmpRed, "r"); get_float_lines(fpIn, metaIn, 0, line_count, buf); put_band_float_lines(fpOut, metaOut, 2, 0, line_count, buf); FCLOSE(fpIn); FCLOSE(fpOut); FREE(buf); strcpy(metaOut->general->bands, "red,green,blue"); meta_write(metaOut, tmpBrowse); // Export to GeoTIFF char *band_names[3] = { "blue", "green", "red" }; asf_export_bands(GEOTIFF, NONE, TRUE, FALSE, FALSE, FALSE, FALSE, tmpBrowse, outfile, band_names, NULL, NULL); // Clean up asfPrintStatus("Removing temporary directory: %s\n", tmpDir); remove_dir(tmpDir); meta_free(metaIn); meta_free(metaOut); } else asfPrintError("Mode is not defined!\n"); asfPrintStatus("Done.\n"); exit(EXIT_SUCCESS); }
// Now the thumbnail generation is combined with the stats calculations, // to speed things up a little. Both require a pass through the entire // image, so it seems natural, and the stats calculation doesn't add much // overhead. (The user is waiting while the thumbnail is being generated, // so we do want this to be as quick as possible.) unsigned char *generate_thumbnail_data(ImageInfo *ii, int tsx, int tsy) { int i,j; unsigned char *bdata = MALLOC(sizeof(unsigned char)*tsx*tsy*3); ImageStats *stats = &(ii->stats); // we will estimate the stats from the thumbnail data clear_stats(ii); // Here we do the rather ugly thing of making the thumbnail // loading code specific to each supported data type. This is // because we've combined the stats calculation into this... if (ii->data_ci->data_type == GREYSCALE_FLOAT) { // store data used to build the small image pixmap // we will calculate the stats on this subset float *fdata = CALLOC(sizeof(float), tsx*tsy); load_thumbnail_data(ii->data_ci, tsx, tsy, fdata); set_ignores(ii, !g_startup); // split out the case where we have no ignore value -- // should be quite a bit faster... if (have_ignore(stats)) { // Compute stats -- ignore "no data" value int n=0; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { float v = fdata[j+i*tsx]; if (!is_ignored(stats, v) && fabs(v)<999999999) { stats->avg += v; // first valid pixel --> initialize max/min // subsequent pixels --> update max/min if needed if (n==0) { stats->act_max = stats->act_min = v; } else { if (v > stats->act_max) stats->act_max = v; if (v < stats->act_min) stats->act_min = v; } ++n; } } } stats->avg /= (double)n; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { float v = fdata[j+i*tsx]; if (!is_ignored(stats, v) && fabs(v)<999999999) { stats->stddev += (v - stats->avg)*(v - stats->avg); } } } stats->stddev = sqrt(stats->stddev / (double)n); } else { // Compute stats, no ignore (actually, do ignore data that is NaN) stats->act_max = stats->act_min = fdata[0]; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { float v = fdata[j+i*tsx]; // added in the fabs<999... thing... sometimes values // are just ridiculous and we must ignore them if (meta_is_valid_double(v) && fabs(v)<999999999) { stats->avg += v; if (v > stats->act_max) stats->act_max = v; if (v < stats->act_min) stats->act_min = v; } } } stats->avg /= (double)(tsx*tsy); for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { float v = fdata[j+i*tsx]; if (meta_is_valid_double(v) && fabs(v)<999999999) stats->stddev += (v - stats->avg) * (v - stats->avg); } } stats->stddev = sqrt(stats->stddev / (double)(tsx*tsy)); } //printf("Avg, StdDev: %f, %f\n", stats->avg, stats->stddev); set_mapping(ii, !g_startup); // Now actually scale the data, and convert to bytes. // Note that we need 3 values, one for each of the RGB channels. if (have_lut()) { // look up table case -- no scaling, just use the lut // to convert from float to rgb byte for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int index = j+i*tsx; int n = 3*index; float val = fdata[index]; int ival; if (is_ignored(stats, val) || val<0) ival = ignore_grey_value; else ival = (int)val; apply_lut(ival, &bdata[n], &bdata[n+1], &bdata[n+2]); // histogram will appear as if we were scaling // to greyscale byte unsigned char uval = (unsigned char) calc_scaled_pixel_value(stats, val); stats->hist[uval] += 1; } } } else { // normal case -- no lut, apply selected scaling to convert from // floating point to byte for display for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int index = j+i*tsx; float val = fdata[index]; int n = 3*index; unsigned char uval = (unsigned char) calc_scaled_pixel_value(stats, val); if (is_ignored(stats, val)) { bdata[n] = bdata[n+1] = bdata[n+2] = ignore_grey_value; } else { bdata[n] = uval; bdata[n+1] = uval; bdata[n+2] = uval; stats->hist[uval] += 1; } } } } // done with our subset free(fdata); } else if (ii->data_ci->data_type == RGB_BYTE) { // store data used to build the small image pixmap // we will calculate the stats on this subset unsigned char *rgbdata = CALLOC(sizeof(unsigned char), tsx*tsy*3); load_thumbnail_data(ii->data_ci, tsx, tsy, (void*)rgbdata); set_ignores(ii, !g_startup); ImageStatsRGB *stats_r = &ii->stats_r; ImageStatsRGB *stats_g = &ii->stats_g; ImageStatsRGB *stats_b = &ii->stats_b; stats_r->act_min = rgbdata[0]; stats_r->act_max = rgbdata[0]; stats_g->act_min = rgbdata[1]; stats_g->act_max = rgbdata[1]; stats_b->act_min = rgbdata[2]; stats_b->act_max = rgbdata[2]; int nr=0, ng=0, nb=0; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, rgbdata[kk])) { stats_r->avg += rgbdata[kk]; ++nr; if (rgbdata[kk] < stats_r->act_min) stats_r->act_min = rgbdata[kk]; if (rgbdata[kk] > stats_r->act_max) stats_r->act_max = rgbdata[kk]; } if (!is_ignored_rgb(stats_g, rgbdata[kk+1])) { stats_g->avg += rgbdata[kk+1]; ++ng; if (rgbdata[kk+1] < stats_g->act_min) stats_g->act_min = rgbdata[kk+1]; if (rgbdata[kk+1] > stats_g->act_max) stats_g->act_max = rgbdata[kk+1]; } if (!is_ignored_rgb(stats_b, rgbdata[kk+2])) { stats_b->avg += rgbdata[kk+2]; ++nb; if (rgbdata[kk+2] < stats_b->act_min) stats_b->act_min = rgbdata[kk+2]; if (rgbdata[kk+2] > stats_b->act_max) stats_b->act_max = rgbdata[kk+2]; } } } if (nr>1) stats_r->avg /= (double)nr; if (ng>1) stats_g->avg /= (double)ng; if (nb>1) stats_b->avg /= (double)nb; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, rgbdata[kk])) { float d = rgbdata[kk] - stats_r->avg; stats_r->stddev += d*d; } if (!is_ignored_rgb(stats_g, rgbdata[kk+1])) { float d = rgbdata[kk+1] - stats_g->avg; stats_g->stddev += d*d; } if (!is_ignored_rgb(stats_b, rgbdata[kk+2])) { float d = rgbdata[kk+2] - stats_b->avg; stats_b->stddev += d*d; } } } stats_r->stddev = sqrt(stats_r->stddev / (double)nr); stats_g->stddev = sqrt(stats_g->stddev / (double)ng); stats_b->stddev = sqrt(stats_b->stddev / (double)nb); set_mapping(ii, !g_startup); // clear out the stats for the greyscale image - we'll just use // the histogram stats->avg = 0; stats->stddev = 0; // these are used for the axis labels on the histogram, so we put // in the averages of the mins... these are sort of bogus anyway, we // really should have 3 histograms stats->map_min = calc_fake_min(ii); stats->map_max = calc_fake_max(ii); for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, rgbdata[kk]) && !is_ignored_rgb(stats_g, rgbdata[kk+1]) && !is_ignored_rgb(stats_b, rgbdata[kk+2])) { bdata[kk] = (unsigned char)calc_rgb_scaled_pixel_value( stats_r, rgbdata[kk]); bdata[kk+1] = (unsigned char)calc_rgb_scaled_pixel_value( stats_g, rgbdata[kk+1]); bdata[kk+2] = (unsigned char)calc_rgb_scaled_pixel_value( stats_b, rgbdata[kk+2]); } else { bdata[kk] = ignore_red_value; bdata[kk+1] = ignore_green_value; bdata[kk+2] = ignore_blue_value; } } } // Update the histogram -- use greyscale average for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, rgbdata[kk]) && !is_ignored_rgb(stats_g, rgbdata[kk+1]) && !is_ignored_rgb(stats_b, rgbdata[kk+2])) { unsigned char uval = (bdata[kk]+bdata[kk+1]+bdata[kk+2])/3; stats->hist[uval] += 1; } } } free(rgbdata); } else if (ii->data_ci->data_type == GREYSCALE_BYTE) { // this case is very similar to the RGB case, above, except we // have to first grab the data into a greyscale buffer, and // then copy it over to the 3-band buffer we're supposed to return unsigned char *gsdata = MALLOC(sizeof(unsigned char)*tsx*tsy); load_thumbnail_data(ii->data_ci, tsx, tsy, (void*)gsdata); set_ignores(ii, !g_startup); stats->act_max = 0; stats->act_min = 255; stats->map_min = 0; stats->map_max = 255; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { unsigned char uval = gsdata[j+i*tsx]; stats->avg += uval; if (uval > stats->act_max) stats->act_max = uval; if (uval < stats->act_min) stats->act_min = uval; } } stats->avg /= (double)(tsx*tsy); for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { unsigned char uval = gsdata[j+i*tsx]; stats->stddev += (uval - stats->avg) * (uval - stats->avg); } } stats->stddev = sqrt(stats->stddev / (double)(tsx*tsy)); set_mapping(ii, !g_startup); for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { unsigned char uval = gsdata[j+i*tsx]; int kk = 3*(j+i*tsx); if (have_lut()) { apply_lut(uval, &bdata[kk], &bdata[kk+1], &bdata[kk+2]); stats->hist[uval] += 1; } else if (!is_ignored(stats, uval)) { // apply selected scaling to display values unsigned char display_value = (unsigned char) calc_scaled_pixel_value(stats, uval); bdata[kk] = bdata[kk+1] = bdata[kk+2] = display_value; stats->hist[display_value] += 1; } else { bdata[kk] = bdata[kk+1] = bdata[kk+2] = ignore_grey_value; } } } free(gsdata); } else if (ii->data_ci->data_type == RGB_FLOAT) { // store data used to build the small image pixmap // we will calculate the stats on this subset float *fdata = MALLOC(sizeof(float)*tsx*tsy*3); load_thumbnail_data(ii->data_ci, tsx, tsy, fdata); set_ignores(ii, !g_startup); ImageStatsRGB *stats_r = &ii->stats_r; ImageStatsRGB *stats_g = &ii->stats_g; ImageStatsRGB *stats_b = &ii->stats_b; stats_r->act_min = fdata[0]; stats_r->act_max = fdata[0]; stats_g->act_min = fdata[1]; stats_g->act_max = fdata[1]; stats_b->act_min = fdata[2]; stats_b->act_max = fdata[2]; int nr=0, ng=0, nb=0; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, fdata[kk])) { stats_r->avg += fdata[kk]; ++nr; if (fdata[kk] < stats_r->act_min) stats_r->act_min = fdata[kk]; if (fdata[kk] > stats_r->act_max) stats_r->act_max = fdata[kk]; } if (!is_ignored_rgb(stats_g, fdata[kk+1])) { stats_g->avg += fdata[kk+1]; ++ng; if (fdata[kk+1] < stats_g->act_min) stats_g->act_min = fdata[kk+1]; if (fdata[kk+1] > stats_g->act_max) stats_g->act_max = fdata[kk+1]; } if (!is_ignored_rgb(stats_b, fdata[kk+2])) { stats_b->avg += fdata[kk+2]; ++nb; if (fdata[kk+2] < stats_b->act_min) stats_b->act_min = fdata[kk+2]; if (fdata[kk+2] > stats_b->act_max) stats_b->act_max = fdata[kk+2]; } } } if (nr>1) stats_r->avg /= (double)nr; if (ng>1) stats_g->avg /= (double)ng; if (nb>1) stats_b->avg /= (double)nb; for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, fdata[kk])) { float d = fdata[kk] - stats_r->avg; stats_r->stddev += d*d; } if (!is_ignored_rgb(stats_g, fdata[kk+1])) { float d = fdata[kk+1] - stats_g->avg; stats_g->stddev += d*d; } if (!is_ignored_rgb(stats_b, fdata[kk+2])) { float d = fdata[kk+2] - stats_b->avg; stats_b->stddev += d*d; } } } stats_r->stddev = sqrt(stats_r->stddev / (double)nr); stats_g->stddev = sqrt(stats_g->stddev / (double)ng); stats_b->stddev = sqrt(stats_b->stddev / (double)nb); set_mapping(ii, !g_startup); // clear out the stats for the greyscale image - we'll just use // the histogram stats->avg = 0; stats->stddev = 0; // these are used for the axis labels on the histogram, so we put // in the averages of the mins... these are sort of bogus anyway, we // really should have 3 histograms stats->map_min = calc_fake_min(ii); stats->map_max = calc_fake_max(ii); for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, fdata[kk]) && !is_ignored_rgb(stats_g, fdata[kk+1]) && !is_ignored_rgb(stats_b, fdata[kk+2])) { bdata[kk] = (unsigned char)calc_rgb_scaled_pixel_value( stats_r, fdata[kk]); bdata[kk+1] = (unsigned char)calc_rgb_scaled_pixel_value( stats_g, fdata[kk+1]); bdata[kk+2] = (unsigned char)calc_rgb_scaled_pixel_value( stats_b, fdata[kk+2]); } else { bdata[kk] = ignore_red_value; bdata[kk+1] = ignore_green_value; bdata[kk+2] = ignore_blue_value; } } } // Update the histogram -- use greyscale average for (i=0; i<tsy; ++i) { for (j=0; j<tsx; ++j) { int kk = 3*(j+i*tsx); if (!is_ignored_rgb(stats_r, fdata[kk]) && !is_ignored_rgb(stats_g, fdata[kk+1]) && !is_ignored_rgb(stats_b, fdata[kk+2])) { unsigned char uval = (bdata[kk]+bdata[kk+1]+bdata[kk+2])/3; stats->hist[uval] += 1; } } } // done with our subset free(fdata); } else { asfPrintError("Unexpected data type: %d!\n", ii->data_ci->data_type); } return bdata; }