void import_radarsat2(const char *inBaseName, radiometry_t radiometry,
		      const char *outBaseName, int ampOnly)
{
  FILE *fp;
  radarsat2_meta *radarsat2;
  meta_parameters *meta;
  char **inDataNames=NULL, inDataName[1024], *inMetaName=NULL;
  char *outDataName=NULL, str[512];
  float *amp = NULL, *phase = NULL, *tmp = NULL, re, im;
  int band, sample;

  // Check radiometry
  if (radiometry != r_AMP) {
    asfPrintWarning("Radiometry other than AMPLITUDE is currently not "
		    "supported.\n");
    radiometry = r_AMP;
  }
  
  if (!fileExists(inBaseName))
    inMetaName = appendExt(inBaseName, ".xml");
  else {
    inMetaName = (char *) MALLOC(sizeof(char)*1024);
    strcpy(inMetaName, inBaseName);
  }
  outDataName = appendExt(outBaseName, ".img");

  radarsat2 = read_radarsat2_meta(inMetaName);
  asfPrintStatus("   DataType: %s, ProductType: %s\n",
		 radarsat2->dataType, radarsat2->productType);
  if (strcmp_case(radarsat2->dataType, "COMPLEX") != 0)
    asfPrintError("Currently only complex data supported!\n");
  meta = radarsat2meta(radarsat2);
  meta_write(meta, outDataName);

  // Let's check the GeoTIFF data.
  // Unfortunately, there is no identifier in the GeoTIFF that would identify
  // the data as Radarsat-2 data.
  //
  // The only thing that we can actually do is to look whether the data in the
  // GeoTIFF file fit the general bill. We can the image dimensions. The data
  // needs to have 2 bands (I and Q) and 16 bit. The citation geokey needs to
  // be the really non-descriptive "Uncorrected Satellite Data".

  TIFF *tiff = NULL;
  GTIF *gtif = NULL;
  data_type_t data_type;
  short sample_format, bits_per_sample, planar_config;
  short num_bands;
  int is_scanline_format, is_palette_color_tiff, wrong=FALSE;
  char *error_message = (char *) MALLOC(sizeof(char)*2048);

  inDataNames = extract_band_names(meta->general->basename, 
				   meta->general->band_count);
  fp = FOPEN(outDataName, "wb");

  int band_count = radarsat2->band_count;
  if (ampOnly) {
    strcpy(meta->general->bands, "AMP");
    meta->general->band_count = 1;
    band_count = 1;
  }
  for (band=0; band<band_count; band++) {

    // path from the xml (metadata) file
    char *path = get_dirname(inBaseName);
    if (strlen(path)>0) {
      strcpy(inDataName, path);
      if (inDataName[strlen(inDataName)-1] != '/')
        strcat(inDataName, "/");
    }
    else
      strcpy(inDataName, "");
    free(path);
    strcat(inDataName, inDataNames[band]);

    tiff = XTIFFOpen(inDataName, "r");
    if (!tiff)
      asfPrintError("Could not open data file (%s)\n", inDataName);
    gtif = GTIFNew(tiff);
    if (!gtif)
      asfPrintError("Could not read GeoTIFF keys from data file (%s)\n",
		    inDataName);

    // Check image dimensions
    uint32 tif_sample_count;
    uint32 tif_line_count;

    TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &tif_line_count);
    TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &tif_sample_count);
    if ((meta->general->sample_count != tif_sample_count) ||
	(meta->general->line_count != tif_line_count))
      asfPrintError(error_message, 
		    "Problem with image dimensions. Was looking for %d lines "
		    "and %d samples.\nFound %ld lines and %ld samples instead!"
		    "\n", 
		    meta->general->line_count, meta->general->sample_count, 
		    tif_line_count, tif_sample_count);

    // Check general TIFF tags
    get_tiff_data_config(tiff, &sample_format, &bits_per_sample, &planar_config,
			 &data_type, &num_bands, &is_scanline_format, 
			 &is_palette_color_tiff, REPORT_LEVEL_WARNING);

    // The specs say the data is supposed to be unsigned but it is not.
    // Let is pass as long as we are talking about integer data here
    strcpy(error_message, "");
    if (sample_format != SAMPLEFORMAT_UINT && 
	sample_format != SAMPLEFORMAT_INT) {
      strcat(error_message, 
	     "Problem with sampling format. Was looking for integer, ");
      if (sample_format == SAMPLEFORMAT_COMPLEXIEEEFP)
	strcat(error_message, "found complex floating point instead!\n");
      else if (sample_format == SAMPLEFORMAT_COMPLEXINT)
	strcat(error_message, "found complex integer instead!\n");
      else if (sample_format == SAMPLEFORMAT_IEEEFP)
	strcat(error_message, "found floating point instead!\n");
      else if (sample_format == SAMPLEFORMAT_VOID)
	strcat(error_message, "found void instead!\n");
      wrong = TRUE;
    }
    if (bits_per_sample != 16) {
      sprintf(str, "Problem with bits per sample. Was looking for 16, found %d "
	      "instead!\n", bits_per_sample);
      strcat(error_message, str);
      wrong = TRUE;
    }
    if (data_type != INTEGER16) {
      strcat(error_message, "Problem with data type. Was looking INTEGER16, ");
      if (data_type == ASF_BYTE)
	strcat(error_message, "found BYTE instead!\n");
      else if (data_type == INTEGER32)
	strcat(error_message, "found INTEGER32 instead!\n");
      else if (data_type == REAL32)
	strcat(error_message, "found REAL32 instead!\n");
      else if (data_type == REAL64)
	strcat(error_message, "found REAL64 instead!\n");
      else if (data_type == COMPLEX_BYTE)
	strcat(error_message, "found COMPLEX_BYTE instead!\n");
      else if (data_type == COMPLEX_INTEGER16)
	strcat(error_message, "found COMPLEX_INTEGER16 instead!\n");
      else if (data_type == COMPLEX_INTEGER32)
	strcat(error_message, "found COMPLEX_INTEGER32 instead!\n");
      else if (data_type == COMPLEX_REAL32)
	strcat(error_message, "found COMPLEX_REAL32 instead!\n");
      else if (data_type == COMPLEX_REAL64)
	strcat(error_message, "found COMPLEX_REAL64 instead!\n");
      wrong = TRUE;
    }
    if (num_bands != 2) {
      sprintf(str, "Problem with number of bands. Was looking for 2, "
	      "found %d instead!\n", num_bands);
      strcat(error_message, str);
      wrong = TRUE;
    }
    if (wrong)
      asfPrintError(error_message);

    // Check GTCitationGeoKey
    char *citation = NULL;
    int citation_length, typeSize;
    tagtype_t citation_type;

    citation_length = GTIFKeyInfo(gtif, GTCitationGeoKey, &typeSize,
				  &citation_type);
    if (citation_length > 0) {
      citation = (char *) MALLOC(citation_length * typeSize);
      GTIFKeyGet(gtif, GTCitationGeoKey, citation, 0, citation_length);
      if (citation && 
	  strcmp_case(citation, "UNCORRECTED SATELLITE DATA") != 0) {
	asfPrintError("Problem with GTCitationGeoKey. Was looking for "
		      "'Uncorrected Satellite Data',\nfound '%s' instead!\n", 
		      citation);
      }
    }
    else
      asfPrintError("Problem with GTCitationGeoKey. Was looking for "
		    "'Uncorrected Satellite Data',\ndid not find any key!\n");

    tiff_type_t tiffInfo;
    get_tiff_type(tiff, &tiffInfo);
    if (tiffInfo.format != SCANLINE_TIFF &&
	tiffInfo.format != STRIP_TIFF    &&
	tiffInfo.format != TILED_TIFF)
      asfPrintError("Can't read the GeoTIFF file (%s). Unrecognized TIFF "
		    "type!\n", inDataNames[band]);

    // If we made it here, we are reasonably sure that we have the file that
    // we are looking for.
    asfPrintStatus("\n   Importing %s ...\n", inDataNames[band]);

    uint32 scanlineSize = TIFFScanlineSize(tiff);
    tdata_t *tiff_real_buf = _TIFFmalloc(scanlineSize);
    tdata_t *tiff_imag_buf = _TIFFmalloc(scanlineSize);
    if (!tiff_real_buf || !tiff_imag_buf)
      asfPrintError("Can't allocate buffer for reading TIFF lines!\n");

    amp = (float *) MALLOC(sizeof(float)*meta->general->sample_count);
    phase = (float *) MALLOC(sizeof(float)*meta->general->sample_count);

    // Check whether we need to flip the image in any fashion
    int flip_vertical = FALSE;
    if (strcmp_case(radarsat2->lineTimeOrdering, "DECREASING") == 0) {
      asfPrintStatus("   Data will be flipped vertically while ingesting!\n");
      flip_vertical = TRUE;
    }
    int flip_horizontal = FALSE;
    if (strcmp_case(radarsat2->pixelTimeOrdering, "DECREASING") == 0) {
      asfPrintStatus("   Data will be flipped horizontally while ingesting!\n");
      flip_horizontal = TRUE;
    }
    if (flip_horizontal)
      tmp = (float *) MALLOC(sizeof(float)*meta->general->sample_count);

    // FIXME: still need to implement flipping vertically
    // Read file line by line
    uint32 row;
    int sample_count = meta->general->sample_count;
    int line_count = meta->general->line_count;
    for (row=0; row<(uint32)meta->general->line_count; row++) {
      asfLineMeter(row, meta->general->line_count);
      if (flip_vertical) {
	switch (tiffInfo.format) 
	  {
	  case SCANLINE_TIFF:
	    TIFFReadScanline(tiff, tiff_real_buf, line_count-row-1, 0);
	    TIFFReadScanline(tiff, tiff_imag_buf, line_count-row-1, 1);
	    break;
	  case STRIP_TIFF:
	    ReadScanline_from_TIFF_Strip(tiff, tiff_real_buf, 
					 line_count-row-1, 0);
	    ReadScanline_from_TIFF_Strip(tiff, tiff_imag_buf, 
					 line_count-row-1, 1);
	    break;
	  case TILED_TIFF:
	    ReadScanline_from_TIFF_TileRow(tiff, tiff_real_buf, 
					   line_count-row-1, 0);
	    ReadScanline_from_TIFF_TileRow(tiff, tiff_imag_buf, 
					   line_count-row-1, 1);
	    break;
	  default:
	    asfPrintError("Can't read this TIFF format!\n");
	    break;
	  }
      }
      else {
	switch (tiffInfo.format) 
	  {
	  case SCANLINE_TIFF:
	    TIFFReadScanline(tiff, tiff_real_buf, row, 0);
	    TIFFReadScanline(tiff, tiff_imag_buf, row, 1);
	    break;
	  case STRIP_TIFF:
	    ReadScanline_from_TIFF_Strip(tiff, tiff_real_buf, row, 0);
	    ReadScanline_from_TIFF_Strip(tiff, tiff_imag_buf, row, 1);
	    break;
	  case TILED_TIFF:
	    ReadScanline_from_TIFF_TileRow(tiff, tiff_real_buf, row, 0);
	    ReadScanline_from_TIFF_TileRow(tiff, tiff_imag_buf, row, 1);
	    break;
	  default:
	    asfPrintError("Can't read this TIFF format!\n");
	    break;
	  }
      }
      for (sample=0; sample<sample_count; sample++) {
	switch (sample_format)
	  {
	  case SAMPLEFORMAT_UINT:
	    re = (float)(((uint16*)tiff_real_buf)[sample]);
	    im = (float)(((uint16*)tiff_imag_buf)[sample]);
	    break;
	  case SAMPLEFORMAT_INT:
	    re = (float)(((int16*)tiff_real_buf)[sample]);
	    im = (float)(((int16*)tiff_imag_buf)[sample]);
	    break;
	  }
	amp[sample] = sqrt(re*re + im*im);
	phase[sample] = atan2(im, re);
      }
      if (flip_horizontal) {
	for (sample=0; sample<sample_count; sample++)
	  tmp[sample] = amp[sample];
	for (sample=0; sample<sample_count; sample++)
	  amp[sample] = tmp[sample_count-sample-1];
      }
	  
      put_band_float_line(fp, meta, band*2, (int)row, amp);
      if (!ampOnly)
	put_band_float_line(fp, meta, band*2+1, (int)row, phase);
    }
      
    FREE(amp);
    FREE(phase);
    if (tmp)
      FREE(tmp);
    _TIFFfree(tiff_real_buf);
    _TIFFfree(tiff_imag_buf);
    GTIFFree(gtif);
    XTIFFClose(tiff);
  }

  // update the name field with directory name
  char *path = get_dirname(inBaseName);
  if (strlen(path)<=0)
    path = g_get_current_dir();
  char *p = path, *q = path;
  while (q) {
    if ((q = strchr(p, DIR_SEPARATOR)) != NULL)
      p = q+1;
  }
  sprintf(meta->general->basename, "%s", p);
  FREE(path);
  meta_write(meta, outDataName);

  meta_free(meta);
  FREE(radarsat2);
  FCLOSE(fp);
}
Esempio n. 2
0
int get_tiff_data_config(TIFF *tif,
                         short *sample_format, short *bits_per_sample, short *planar_config,
                         data_type_t *data_type, short *num_bands,
                         int *is_scanline_format, int *is_palette_color_tiff, report_level_t report_level)
{
  int     ret = 0, read_count;
  uint16  planarConfiguration = 0;
  uint16  bitsPerSample = 0;
  uint16  sampleFormat = 0;
  uint16  samplesPerPixel = 0;

  *data_type = -1;
  *num_bands = 0;

  /*********************************************************/
  /*  Read all tags and accept them as-is into the fields  */
  /*********************************************************/
  // Required tag for all images
  ret = 0;

  tiff_type_t t;
  get_tiff_type(tif, &t);
  *is_scanline_format = (t.format == SCANLINE_TIFF) ? 1 : 0;
  if (t.format != SCANLINE_TIFF &&
      t.format != STRIP_TIFF    &&
      t.format != TILED_TIFF)
  {
    ret = -1;
  }

  read_count = TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
  if (read_count) *bits_per_sample = bitsPerSample;

  read_count += TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
  if (read_count < 2          &&
      (bitsPerSample == 8   ||
       bitsPerSample == 16  ||
       bitsPerSample == 32))
  {
      asfReport(report_level,
              "Found missing or invalid sample format.  Should be unsigned integer,\n"
              "integer, or IEEE floating point.\n");
      switch (bitsPerSample) {
          case 8:
              asfReport(report_level,
                    "Data is 8-bit data ...guessing unsigned integer sample\n"
                        "format and attempting to continue.\n");
              sampleFormat = SAMPLEFORMAT_UINT;
              read_count++;
              break;
          case 16:
              asfReport(report_level,
                    "Data is 16-bit data ...guessing signed integer sample\n"
                        "format and attempting to continue.\n");
              sampleFormat = SAMPLEFORMAT_INT;
              read_count++;
              break;
          case 32:
              asfReport(report_level,
                    "Data is 32-bit data ...guessing IEEE floating point sample\n"
                        "format and attempting to continue.\n");
              sampleFormat = SAMPLEFORMAT_IEEEFP;
              read_count++;
              break;
          default:
              ret = -1;
              break;
      }
  }
  if (read_count == 2) {
    *sample_format = sampleFormat;
    switch (sampleFormat) {
      case SAMPLEFORMAT_UINT:
      {
        switch (bitsPerSample) {
          case 8:
            *data_type = BYTE;
            break;
          case 16:
            *data_type = INTEGER32;
            break;
          case 32:
            *data_type = REAL32;
            break;
          default:
            *data_type = 0;
            break;
        }
      }
      break;
      case SAMPLEFORMAT_INT:
      {
        switch (bitsPerSample) {
          case 8:
          case 16:
            *data_type = INTEGER16;
            break;
          case 32:
            *data_type = INTEGER32;
            break;
          default:
            *data_type = 0;
            break;
        }
      }
      break;
      case SAMPLEFORMAT_IEEEFP:
      {
        *data_type = REAL32;
      }
      break;
      default:
      {
        switch (bitsPerSample) {
          case 8:
              // Most likely unsigned 8-bit byte
            *data_type = BYTE;
            break;
          case 16:
              // Most likely 16-bit integer
            *data_type = INTEGER16;
            break;
          case 32:
              // Most likely 32-bot float
            *data_type = REAL32;
            break;
          default:
            *data_type = 0;
            break;
        }
      }
      break;
    }
  }

  read_count = TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
  if (read_count != 1) {
      samplesPerPixel = 0;
  }

  unsigned short *maps[3];
  read_count = TIFFGetField(tif, TIFFTAG_COLORMAP, maps+0, maps+1, maps+2);
  *is_palette_color_tiff = 0;
  if (read_count) {
    if (samplesPerPixel == 1) {
      *is_palette_color_tiff = 1;
    }
    // NOTE: Do not free the colormaps ...this results in a glib double-free error
    // when closing the tiff file.
  }

  read_count = TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarConfiguration);
  if (read_count) *planar_config = planarConfiguration;

  /*********************************************************/
  /*  Determine health                                     */
  /*********************************************************/

  if (bitsPerSample != 8  &&
      bitsPerSample != 16 &&
      bitsPerSample != 32)
  {
    // Only support byte, integer16, integer32, and 32-bit floats
    ret = -1;
  }
  else {
      *num_bands = samplesPerPixel;
  }

  if (sampleFormat != SAMPLEFORMAT_UINT &&
      sampleFormat != SAMPLEFORMAT_INT  &&
      sampleFormat != SAMPLEFORMAT_IEEEFP)
  {
    ret = -1;
  }

  if (samplesPerPixel < 1 || samplesPerPixel > MAX_BANDS) {
    // Only support 1 through MAX_BANDS bands in the image
    ret = -1;
  }

  if (samplesPerPixel > 1 &&
      planarConfiguration != PLANARCONFIG_CONTIG &&
      planarConfiguration != PLANARCONFIG_SEPARATE)
  {
    ret = -1;
  }

  // Required tag only for color (multi-band) images
  if (ret == 0 && samplesPerPixel > 1) {
    if (planarConfiguration != PLANARCONFIG_CONTIG &&
        planarConfiguration != PLANARCONFIG_SEPARATE)
    {
      ret = guess_planar_configuration(tif, planar_config);
      if (ret == 0) {
          asfReport(report_level,
                "Found multi-band TIFF but the planar configuration TIFF tag\n"
                    "is not populated ...GUESSING the planar configuration to be %s\n"
                    "based on calculated scanline lengths for interlaced and band-sequential\n"
                    "TIFFs v. the actual scanline length derived from the TIFF file itself.\n",
                    (*planar_config == PLANARCONFIG_CONTIG) ?
                    "Contiguous Planes (interlaced)" :
                    (*planar_config == PLANARCONFIG_SEPARATE) ?
                    "Separate Planes (band-sequential)" :
                    "Unknown Planar Config (?)");
      }
    }
  }

  return ret;
}
Esempio n. 3
0
int read_tiff(const char *filename, int *nlines, int *nsamps,
              unsigned char **data)
{
  TIFF *tiff = XTIFFOpen(filename, "r");
  if (!tiff) {
    return FALSE;
  }

  uint32 width;
  uint32 height;
  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);

  *nlines = (int)height;
  *nsamps = (int)width;

  unsigned char *dest = CALLOC(width*height*3, sizeof(unsigned char));

  data_type_t data_type;
  tiff_data_config_t data_config;
  int num_bands, is_scanline_format, is_palette_color_tiff;
  uint32 row;

  // Determine what type of TIFF this is (scanline/strip/tiled)
  if (get_tiff_data_config(tiff,
                           &data_config.sample_format,
                           &data_config.bits_per_sample,
                           &data_config.planar_config,
                           &data_type,
                           &data_config.samples_per_pixel,
                           &is_scanline_format,
                           &is_palette_color_tiff,
                           REPORT_LEVEL_NONE))
  {
    return FALSE;
  }
  num_bands = data_config.samples_per_pixel;

  tiff_type_t tiffInfo;
  get_tiff_type(tiff, &tiffInfo);
  if (tiffInfo.imageCount > 1) {
    ; // Only first image in multi-image files will be utilized - WARN the user here?
  }
  if (tiffInfo.imageCount < 1) {
    // TIFF contains zero images ...fail
    return FALSE;
  }
  if (tiffInfo.format != SCANLINE_TIFF &&
      tiffInfo.format != STRIP_TIFF    &&
      tiffInfo.format != TILED_TIFF)
  {
    // Unrecognized TIFF type
    return FALSE;
  }
  if (tiffInfo.volume_tiff) {
    // 3-dimensional (a 'volume tiff') found ...this is unsupported
    return FALSE;
  }
  if (num_bands > 1 &&
      data_config.planar_config != PLANARCONFIG_CONTIG &&
      data_config.planar_config != PLANARCONFIG_SEPARATE)
  {
    // Invalid planar configuration setting found in TIFF file...
    return FALSE;
  }

  uint32 scanlineSize = TIFFScanlineSize(tiff);
  if (scanlineSize <= 0) {
    // Invalid scanline size found in TIFF file...
    return FALSE;
  }

  if (data_config.bits_per_sample != 8)
    return FALSE;

  int is_rgb = data_config.samples_per_pixel >= 3;

  // Populate the buffer with actual data
  if (is_rgb) {
    // TIFF read buffer (red band)
    tdata_t *rtif_buf = _TIFFmalloc(scanlineSize);
    // TIFF read buffer (green band) 
    tdata_t *gtif_buf = _TIFFmalloc(scanlineSize); 
    // TIFF read buffer (blue band)
    tdata_t *btif_buf = _TIFFmalloc(scanlineSize); 

    if (!rtif_buf || !gtif_buf || !btif_buf)
      return FALSE;

    for (row=0; row < height; row++) {
      // Read a scanline and populate r, g, and b tiff buffers
      // NOTE: Empty bands will have the no_data value populated in the
      //tiff buffer
      read_tiff_rgb_scanline(tiff, tiffInfo.format, &data_config,
                             row, scanlineSize, width,
                             0, 1, 2,
                             rtif_buf, gtif_buf, btif_buf);
      // Interleave the rgb values into an rgb buffer
      interleave_byte_rgbScanlines_to_byte_buff(dest,
                                                rtif_buf, gtif_buf, btif_buf,
                                                0, 1, 2,
                                                row, width, &data_config);
    }

    _TIFFfree(rtif_buf);
    _TIFFfree(gtif_buf);
    _TIFFfree(btif_buf);
  }
  else { // is greyscale
    // TIFF read buffer (interleaved bands)
    tdata_t *tif_buf  = _TIFFmalloc(scanlineSize); 
    if (!tif_buf)
      return FALSE;

    for (row=0; row < height; row++) {
      // Read a scanline into a tiff buffer (using first non-blank band as
      // the greyscale image)
      // NOTE: Since displaying a greyscale band specifically selects a band,
      // empty or not, the selected band is read as-is.
      read_tiff_greyscale_scanline(tiff, tiffInfo.format, &data_config,
                                   row, scanlineSize, width, 0, tif_buf);
      copy_byte_scanline_to_byte_buff(dest, tif_buf,
                                      row, width, &data_config);
    }

    _TIFFfree(tif_buf);
  }

  *data = dest;
  return TRUE;
}