Commit 33f8d618 authored by Tyler Wilson's avatar Tyler Wilson
Browse files

Added VAX->IEEE conversion routines to ProcessImport for reading Galileo NIMS qubs. Ref#2368

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@6575 41f8697f-d340-4b68-9986-7bafba869bb8
parent b4b6d143
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>

<application name="pds2isis" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Application/application.xsd">
<application name="pds2isis" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"http://isis.astrogeology.usgs.gov/Schemas/Application/application.xsd">

  <brief>Import PDS or ISIS2 image into ISIS3 cube format</brief>

@@ -116,6 +118,13 @@
    <change name="Kimberly Oyama" date="2012-11-21">
      Added app tests for BIP and BIL formatted input. References #819.
    </change>
    <change name="Tyler Wilson" data ="2016-02-25">
     Added an app test for opening Galileo NIMS qubes saved in VAX format.  Modified the filter
     tag on FROM parameter in this document to also recognize *.qub files.  All changes
     relating to converting VAX to IEEE were made in ProcessImport, ProcessImportPds.
     References:  #2368.
    </change>
	
  </history>

  <category>
@@ -140,7 +149,7 @@
	  enter the label file name.
        </description>
        <filter>
          *.lbl *.img
          *.lbl *.img *.qub
        </filter>
      </parameter>

+7 −0
Original line number Diff line number Diff line
APPNAME = pds2isis

include $(ISISROOT)/make/isismake.tsts

commands:
	$(APPNAME) from=$(INPUT)/30i001ci.qub \
	 to=$(OUTPUT)/30i001ci.cub > /dev/null;
+309 KiB

File added.

Preview size limit exceeded, changes collapsed.

+317 −2
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ namespace Isis {
    //  Initialize input file information
    p_inFile = "";
    p_pixelType = Isis::None;
    p_suffixPixelType = Isis::None;
    p_ns = p_nl = p_nb = 0;
    p_byteOrder = Isis::NoByteOrder;
    p_fileHeaderBytes = 0;
@@ -59,7 +60,9 @@ namespace Isis {
    p_dataTrailerBytes = 0;
    p_dataPreBytes = 0;
    p_dataPostBytes = 0;
    p_suffixData = 0;
    p_organization = ProcessImport::BSQ;

    p_base.push_back(0.0);
    p_mult.push_back(1.0);
    // Make all special pixels invalid
@@ -75,6 +78,8 @@ namespace Isis {
    p_saveDataPre = false;
    p_saveDataPost = false;
    p_saveFileTrailer = false;
    p_vax_convert = false;


    p_fileHeader = NULL;
    p_fileTrailer = NULL;
@@ -112,6 +117,192 @@ namespace Isis {
    }
  }

//tjw:



  /**
   * Determines if the VAX encoded pixel value is special or not
   *
   * @param vax A pointer to a VAX pixel
   * @param pix An enumerated value indicating the VAX pixel type
   * @return bool Returns true if the bit pattern for the enumerated
   *         type matches that pointed to by vax.  Returns false
   *         otherwise.
   */


  bool ProcessImport::IsVAXSpecial(unsigned int *vax, VAXSpecialPixel pix){



     unsigned int VAX_NULL = 0xFFFFFFFF;
     unsigned int VAX_MIN  = 0xFFEFFFFF;
     unsigned int VAX_LRS  = 0xFFFEFFFF;
     unsigned int VAX_LIS  = 0xFFFDFFFF;
     unsigned int VAX_HIS  = 0xFFFCFFFF;
     unsigned int VAX_HRS  = 0xFFFBFFFF;
     int n;

     unsigned int x;
     memcpy(&x,vax,sizeof(unsigned int));

     switch(pix) {

        case VAX_NULL4:
            n=memcmp(&VAX_NULL,&x,sizeof(unsigned int));
            if (n==0){    
                return true;

      }
        break;

        case VAX_LRS4:
            n=memcmp(&VAX_LRS,&x,sizeof(unsigned int));
            if (n==0){

                return true;
      }
        break;

        case VAX_LIS4:
            n=memcmp(&VAX_LIS,&x,sizeof(unsigned int));
            if (n==0) {

                return true;
      }
        break;

        case VAX_HIS4:
            n=memcmp(&VAX_HIS,&x,sizeof(unsigned int));
            if (n==0){

                return true;
      }
        break;

        case VAX_HRS4:
            n=memcmp(&VAX_HRS,&x,sizeof(unsigned int));
            if (n==0){

              return true;
      }
        break;

        case VAX_MIN4:
            n=memcmp(&VAX_MIN,&x,sizeof(unsigned int));
        if (n==0){

            return true;
        }
        break;

        default:
            return false;

      }

    return false;

 }

  //tjw

  /**
   * Conversion routine which translates VAX_REAL to IEEE_REAL
   *
   * @param ibuf Memory buffer of input data to be converted
   * @return double the converted value
   */


  double ProcessImport::VAXConversion(void *ibuf) {



      float result;
      double dresult;
      bool swap_bytes = false;
      bool swap_words = true;
      int exp_adjust = -1;
      int exp_mask = 0;
      int exp_word = 1;
      int exp_byte;
      Isis::ByteOrder in_order = p_byteOrder;
      Isis::ByteOrder out_order;


      unsigned int *oli, *ili;   //4-byte buffer io ptrs
      unsigned short *osi;       //2-byte buffer io ptrs
      char *oci;                 //1-byte buffer io ptrs

      if ( Isis::IsLsb() ) {

          exp_byte  = 1;
          out_order = Isis::Lsb;

      }

      //Byte order = MSB
      else {
          exp_byte = 0;
          out_order = Isis::Msb;
      }

      if (in_order != out_order) {
          swap_bytes =true;

      }

      oli = (unsigned int * ) ibuf;
      ili = (unsigned int * ) ibuf;

      if (IsVAXSpecial(oli,Isis::VAX_NULL4) )
        return Isis::NULL8;

      if (IsVAXSpecial(oli,Isis::VAX_LIS4) )
        return Isis::LOW_INSTR_SAT8;

      if (IsVAXSpecial(oli,Isis::VAX_LRS4) )
        return Isis::LOW_REPR_SAT8;

      if (IsVAXSpecial(oli,Isis::VAX_HIS4) )
        return Isis::HIGH_INSTR_SAT8;

      if (IsVAXSpecial(oli,Isis::VAX_HRS4) )
        return Isis::HIGH_REPR_SAT8;

      if (IsVAXSpecial(oli,Isis::VAX_MIN4) )
        return Isis::VALID_MIN8;

      //test for word swapping
     if (swap_words) {

         *oli = (*ili <<16) | (*ili >> 16);
     }

      osi = (unsigned short* ) oli;

      //test for byte swapping

      if (swap_bytes) {          
          osi[0] = (osi[0] >> 8 ) | (osi[0] << 8);
          osi[1] = (osi[1] >> 8 ) | (osi[1] << 8);
      }

      //Isolate the exponent and do the conversion
      oci = (char *) &osi[exp_word];

      if ( (oci[exp_byte] & EXPONENT_MASK) != exp_mask)
          oci[exp_byte] += exp_adjust;

      result = *(float *)oli;
      dresult = static_cast<double>(result);
      return dresult;

  }



  /**
   * Sets the pixel type of the input file.
@@ -134,6 +325,19 @@ namespace Isis {
    }
  };

  void ProcessImport::SetSuffixPixelType(const Isis::PixelType type) {

    if ((type == Isis::Double) || (type == Isis::Real) || (type == Isis::SignedWord) ||
        (type == Isis::UnsignedWord) || (type == Isis::UnsignedByte)) {
      p_suffixPixelType = type;
    }
    else {
      QString msg = "Unsupported pixel type [" +
                   Isis::PixelTypeName(type) + "]";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }
  };


  /**
   * Sets the physical size of the input cube. This must be invoked prior to
@@ -149,9 +353,13 @@ namespace Isis {
   */
  void ProcessImport::SetDimensions(const int ns, const int nl, const int nb) {
    if (ns > 0 && nl > 0 && nb > 0) {


      p_ns = ns;
      p_nl = nl;
      p_nb = nb;


    }
    else {
      QString msg = "Illegal dimension [" + toString(ns) + ", " +
@@ -195,6 +403,7 @@ namespace Isis {
  void ProcessImport::SetFileHeaderBytes(const int bytes) {
    if (bytes >= 0) {
      p_fileHeaderBytes = bytes;

    }
    else {
      QString msg = "Illegal file header size [" + toString(bytes) + "]";
@@ -253,7 +462,9 @@ namespace Isis {
   */
  void ProcessImport::SetDataHeaderBytes(const int bytes) {
    if (bytes >= 0) {

      p_dataHeaderBytes = bytes;

    }
    else {
      QString msg = "Illegal data header size [" + toString(bytes) + "]";
@@ -262,6 +473,14 @@ namespace Isis {
  };


  void ProcessImport::SetSuffixOffset(int samples,int lines, int coreBands,int itemBytes){

        p_suffixData = samples*lines*coreBands*itemBytes;


  };


  /**
   * This method sets the number of bytes in the trailer of each
   * datablock of a file. A data trailer is a block of non-image
@@ -315,6 +534,7 @@ namespace Isis {

    if (bytes >= 0) {
      p_dataPreBytes = bytes;

    }
    else {
      QString msg = "Illegal data prefix size [" + toString(bytes) + "]";
@@ -345,6 +565,7 @@ namespace Isis {

    if (bytes >= 0) {
      p_dataPostBytes = bytes;

    }
    else {
      QString msg = "Illegal data suffix size [" + toString(bytes) + "]";
@@ -527,6 +748,7 @@ namespace Isis {
   * This method returns the number of file header bytes
   */
  int ProcessImport::FileHeaderBytes() const {

    return p_fileHeaderBytes;
  }

@@ -567,6 +789,7 @@ namespace Isis {
   * This method returns the number of data duffix bytes
   */
  int ProcessImport::DataSuffixBytes() const {

    return p_dataPostBytes;
  }

@@ -745,6 +968,26 @@ namespace Isis {
   */
  void ProcessImport::SetOrganization(const ProcessImport::Interleave org) {
    p_organization = org;

  };


  //tjw:
  /**
   * Sets the VAX flag of the input cube.  If true, then the core pixel type of
   * the input cube is VAX, and VAX conversion routines need to be run to
   * convert the pixels to IEEE format.
   *
   * @param vax_convert Flag indicating whether or not to run VAX conersion methods
   */



  void ProcessImport::SetVAXConvert(const bool vax_convert){


      p_vax_convert = vax_convert;

  };


@@ -1154,6 +1397,8 @@ namespace Isis {
   *             Position[]. Byte count[]"
   */
  void ProcessImport::ProcessBsq(void funct(Isis::Buffer &out)) {


   // Figure out the number of bytes to read for a single line
    int readBytes = Isis::SizeOf(p_pixelType);
    readBytes = readBytes * p_ns;
@@ -1176,11 +1421,14 @@ namespace Isis {

    // Handle the file header
    streampos pos = fin.tellg();
    //tjw
    if (p_saveFileHeader) {
      p_fileHeader = new char[p_fileHeaderBytes];
      fin.read(p_fileHeader, p_fileHeaderBytes);
      fin.seekg(p_suffixData+p_fileHeaderBytes,ios_base::beg);
    }
    else {
        fin.seekg(p_fileHeaderBytes+p_suffixData, ios_base::beg);
        fin.seekg(p_fileHeaderBytes, ios_base::beg);
    }

@@ -1219,14 +1467,19 @@ namespace Isis {
        mult = p_mult[0];
      }


      // Handle any data headers (e.g., the data at the beginning of each band)
      pos = fin.tellg();
      if (p_saveDataHeader) {
        p_dataHeader.push_back(new char[p_dataHeaderBytes]);
        fin.read(p_dataHeader.back(), p_dataHeaderBytes);

      }
      else {
        //cout << p_suffixData << endl;
        fin.seekg(p_dataHeaderBytes, ios_base::cur);


       }

      // Check the last io
@@ -1277,26 +1530,37 @@ namespace Isis {
        for(int samp = 0; samp < p_ns; samp++) {
          switch(p_pixelType) {
            case Isis::UnsignedByte:
              //cout << "UnsignedByte" << endl;
              (*out)[samp] = (double)((unsigned char *)in)[samp];
              break;
            case Isis::UnsignedWord:
              //cout << "Unsigned word."<< endl;
              (*out)[samp] =
                (double)swapper.UnsignedShortInt((unsigned short int *)in+samp);
              break;
            case Isis::SignedWord:
            //cout << "Signed Word." << endl;
              (*out)[samp] = (double)swapper.ShortInt((short int *)in+samp);
              break;
            case Isis::Real:
              //tjw:
              if(p_vax_convert)
                (*out)[samp]= VAXConversion( (float *)in+samp );
              else
                (*out)[samp] = (double)swapper.Float((float *)in+samp);

              break;
            case Isis::Double:
              //cout << "Double"  << endl;
              (*out)[samp] = (double)swapper.Double((double *)in+samp);
              break;


            default:
              break;
          }

          // Sets out to isis special pixel or leaves it if valid

          (*out)[samp] = TestPixel((*out)[samp]);

          if (Isis::IsValidPixel((*out)[samp])) {
@@ -1395,6 +1659,10 @@ namespace Isis {
  }






  /**
   * Function to process files stored as Band Interleaved by Line
   *
@@ -1429,6 +1697,21 @@ namespace Isis {

    // Handle the file header
    streampos pos = fin.tellg();



    if (p_saveFileHeader) {
      p_fileHeader = new char[p_fileHeaderBytes];
      fin.read(p_fileHeader, p_fileHeaderBytes);
      fin.seekg(p_suffixData+p_fileHeaderBytes,ios_base::beg);
    }
    else {
        fin.seekg(p_fileHeaderBytes+p_suffixData, ios_base::beg);
        fin.seekg(p_fileHeaderBytes, ios_base::beg);
    }


#if 0
    if (p_saveFileHeader) {
      p_fileHeader = new char[p_fileHeaderBytes];
      fin.read(p_fileHeader, p_fileHeaderBytes);
@@ -1436,6 +1719,8 @@ namespace Isis {
    else {
      fin.seekg(p_fileHeaderBytes, ios_base::beg);
    }
#endif


    // Check the last io
    if (!fin.good()) {
@@ -1532,6 +1817,10 @@ namespace Isis {
              (*out)[samp] = (double)swapper.ShortInt((short int *)in+samp);
              break;
            case Isis::Real:
              //tjw:
              if(p_vax_convert)
                (*out)[samp]= VAXConversion( (float *)in+samp );
              else
                (*out)[samp] = (double)swapper.Float((float *)in+samp);
              break;
            case Isis::Double:
@@ -1642,6 +1931,7 @@ namespace Isis {
   */
  void ProcessImport::ProcessBip(void funct(Isis::Buffer &out)) {


    // Figure out the number of bytes to read for a single line
    int readBytes = Isis::SizeOf(p_pixelType);
    readBytes = readBytes * p_ns * p_nb;
@@ -1663,15 +1953,33 @@ namespace Isis {
    }

    // Handle the file header

    //tjw
    streampos pos = fin.tellg();
    if (p_saveFileHeader) {
      p_fileHeader = new char[p_fileHeaderBytes];
      fin.read(p_fileHeader, p_fileHeaderBytes);
      fin.seekg(p_suffixData+p_fileHeaderBytes,ios_base::beg);
    }
    else {
        fin.seekg(p_fileHeaderBytes+p_suffixData, ios_base::beg);
        fin.seekg(p_fileHeaderBytes, ios_base::beg);
    }



#if 0

    if (p_saveFileHeader) {
      p_fileHeader = new char[p_fileHeaderBytes];
      fin.read(p_fileHeader, p_fileHeaderBytes);
    }
    else {
      fin.seekg(p_fileHeaderBytes, ios_base::beg);
    }

#endif

    // Check the last io
    if (!fin.good()) {
      QString msg = "Cannot read file [" + p_inFile + "]. Position [" +
@@ -1754,6 +2062,7 @@ namespace Isis {
        // Swap the bytes if necessary and convert any out of bounds pixels
        // to special pixels
        int osamp = 0;

        for(int samp = band; samp < p_ns * p_nb; samp += p_nb) {
          switch(p_pixelType) {
            case Isis::UnsignedByte:
@@ -1767,10 +2076,14 @@ namespace Isis {
              (*out)[osamp] = (double)swapper.ShortInt((short int *)in+samp);
              break;
            case Isis::Real:
              //tjw:
              if(p_vax_convert)
                (*out)[osamp]= VAXConversion( (float *)in+samp );
              else
                (*out)[osamp] = (double)swapper.Float((float *)in+samp);
              break;
            case Isis::Double:
              (*out)[samp] = (double)swapper.Double((double *)in+samp);
              (*out)[osamp] = (double)swapper.Double((double *)in+samp);
              break;
            default:
              break;
@@ -2088,3 +2401,5 @@ namespace Isis {

}


+57 −0
Original line number Diff line number Diff line
@@ -145,8 +145,34 @@ namespace Isis {
   *                                            child classes.  Added virtual keyword
   *                                            to destructor.  References #2215.
   *
   *   @history 2016-02-23 Tyler Wilson - Added VAXConversion(...) and IsVAXSpecial(...) routines 
   *                        for importing Galileo NIMS qubs which were originally saved in VAX format.  
   *                        References #2368.
   *
   */


// VAX conversion
#define EXPONENT_MASK ((char) 0x7F)




//Data type for Galileo:  NIMS data
 enum VAXDataType{
         VAX_REAL,
         VAX_INT
 };

enum VAXSpecialPixel {
  VAX_MIN4,
  VAX_NULL4,
  VAX_LRS4,
  VAX_LIS4,
  VAX_HIS4,
  VAX_HRS4
};

  class ProcessImport : public Isis::Process {
    public:
      ProcessImport();
@@ -167,9 +193,17 @@ namespace Isis {
       * Returns the pixel type
       * @return The pixel type of input data
       */

      void SetSuffixPixelType(const Isis::PixelType type);

      Isis::PixelType PixelType() {
        return p_pixelType;
      }

      Isis::PixelType SuffixPixelType() {
        return p_suffixPixelType;
      }

      void SetDimensions(const int ns, const int nl, const int nb);

      /**
@@ -206,6 +240,14 @@ namespace Isis {
        return p_byteOrder;
      }


      //tjw:  VAX_REAL -> IEEE_REAL

      bool IsVAXSpecial(unsigned int *vax,VAXSpecialPixel pix);
      double VAXConversion(void *ibuf);
      void SetSuffixOffset(int samples,int lines, int coreBands,int itemBytes);


      void SetFileHeaderBytes(const int bytes);
      void SetFileTrailerBytes(const int bytes);
      void SetDataHeaderBytes(const int bytes);
@@ -252,6 +294,11 @@ namespace Isis {
                                  all bands is followed by the second pixel for
                                  all bands.*/
      };

      //tjw
      void SetVAXConvert(const bool vax_flag);


      void SetOrganization(const ProcessImport::Interleave org);
      Interleave Organization() const;

@@ -280,9 +327,15 @@ namespace Isis {
    private:
      QString p_inFile;                 //!< Input file name
      Isis::PixelType p_pixelType;      //!< Pixel type of input data
      Isis::PixelType p_suffixPixelType;
      int p_ns;                         //!< Number of samples
      int p_nl;                         //!< Number of lines
      int p_nb;                         //!< Number of bands
      int p_suffixData;                 //!< Number of bytes past the file header bytes
                                        //!< where the suffix data bands are stored
                                        //!


      Isis::ByteOrder p_byteOrder;      //!< Byte order of data
      int p_fileHeaderBytes;            /**< The number of bytes of non-image data at
                                        the beginning of a file. This does not
@@ -381,6 +434,10 @@ namespace Isis {
                                             data. All pixels between this value and the min
                                             will be converted to the Isis LIS value.*/

      bool p_vax_convert;               /**< A boolean flag which is set to true if we
                                             are converting a VAX formatted real number.   */


      void ProcessBsq(void funct(Isis::Buffer &out) = NULL);
      void ProcessBil(void funct(Isis::Buffer &out) = NULL);
      void ProcessBip(void funct(Isis::Buffer &out) = NULL);
Loading