示例#1
0
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;
    }
  }
}
示例#2
0
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; 
}
示例#3
0
/* 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);
}
示例#4
0
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;
}
示例#5
0
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);}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
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;
    }

  }
}
示例#10
0
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;
}
示例#11
0
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;
}
示例#12
0
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;
}
示例#13
0
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;
}
示例#14
0
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;
}
示例#15
0
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
}
示例#16
0
// 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;
}
示例#17
0
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;
}
示例#18
0
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;
}
示例#19
0
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);
}
示例#20
0
// 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;
}