USGS

Isis 3.0 Object Programmers' Reference

Home

ProcessExport.cpp

Go to the documentation of this file.
00001 
00022 #include <iostream>
00023 #include <iomanip>
00024 #include "ProcessExport.h"
00025 #include "Preference.h"
00026 #include "IException.h"
00027 #include "LineManager.h"
00028 #include "BandManager.h"
00029 #include "SpecialPixel.h"
00030 #include "Histogram.h"
00031 #include "Stretch.h"
00032 #include "Application.h"
00033 #include "EndianSwapper.h"
00034 #include "Projection.h"
00035 
00036 using namespace std;
00037 namespace Isis {
00038 
00040   ProcessExport::ProcessExport() : Isis::Process() {
00041 
00042     p_outputMinimum = 0.0;
00043     p_outputMiddle = 0.5;
00044     p_outputMaximum = 1.0;
00045 
00046     p_inputMinimum.clear();
00047     p_inputMiddle.clear();
00048     p_inputMaximum.clear();
00049 
00050     p_endianSwap = NULL;
00051 
00052     SetFormat(BSQ);
00053     SetOutputEndian(Isis::IsLsb() ? Isis::Lsb : Isis::Msb);
00054     SetOutputType(Isis::Real);
00055 
00056     p_Null_Set = false;
00057     p_Lis_Set = false;
00058     p_Lrs_Set = false;
00059     p_His_Set = false;
00060     p_Hrs_Set = false;
00061 
00062     p_progress->SetText("Exporting");
00063   }
00064 
00065 
00067   ProcessExport::~ProcessExport() {
00068     if(p_endianSwap != NULL) {
00069       delete p_endianSwap;
00070     }
00071     for(unsigned int i = 0; i < p_str.size(); i++) {
00072       delete p_str[i];
00073     }
00074     p_str.clear();
00075   }
00076 
00077 
00100   void ProcessExport::SetInputRange(const double minimum, const double maximum) {
00101     double middle = (minimum + maximum) / 2.0;
00102     SetInputRange(minimum, middle, maximum);
00103   }
00104 
00129   void ProcessExport::SetInputRange(const double minimum, const double maximum, const int index) {
00130     double middle = (minimum + maximum) / 2.0;
00131     SetInputRange(minimum, middle, maximum, index);
00132   }
00133 
00160   void ProcessExport::SetInputRange(const double minimum, const double middle,
00161                                     const double maximum) {
00162     if(minimum >= middle) {
00163       string message =
00164         "minimum must be less than the middle [ProcessExport::SetInputRange]";
00165       throw IException(IException::Programmer, message, _FILEINFO_);
00166     }
00167     if(middle >= maximum) {
00168       string message =
00169         "middle must be less than the maximum [ProcessExport::SetInputRange]";
00170       throw IException(IException::Programmer, message, _FILEINFO_);
00171     }
00172     p_inputMinimum.clear();
00173     p_inputMinimum.resize(InputCubes.size(), minimum);
00174     p_inputMiddle.clear();
00175     p_inputMiddle.resize(InputCubes.size(), middle);
00176     p_inputMaximum.clear();
00177     p_inputMaximum.resize(InputCubes.size(), maximum);
00178   }
00179 
00208   void ProcessExport::SetInputRange(const double minimum, const double middle,
00209                                     const double maximum, const int index) {
00210     if(minimum >= middle) {
00211       string message =
00212         "minimum must be less than the middle [ProcessExport::SetInputRange]";
00213       throw IException(IException::Programmer, message, _FILEINFO_);
00214     }
00215     if(middle >= maximum) {
00216       string message =
00217         "middle must be less than the maximum [ProcessExport::SetInputRange]";
00218       throw IException(IException::Programmer, message, _FILEINFO_);
00219     }
00220     if(index >= (int)InputCubes.size() || index < 0) {
00221       string message =
00222         "index out of bounds";
00223       throw IException(IException::Programmer, message, _FILEINFO_);
00224     }
00225 
00226     p_inputMinimum.resize(index + 1, minimum);
00227     p_inputMiddle.resize(index + 1, middle);
00228     p_inputMaximum.resize(index + 1, maximum);
00229     p_inputMinimum[index] = minimum;
00230     p_inputMiddle[index] = middle;
00231     p_inputMaximum[index] = maximum;
00232   }
00233 
00366   void ProcessExport::SetInputRange() {
00367     p_inputMinimum.clear();
00368     p_inputMiddle.clear();
00369     p_inputMaximum.clear();
00370 
00371     for(unsigned int i = 0; i < InputCubes.size(); i++) {
00372       // Get the manual stretch parameters if needed
00373       QString strType = Application::GetUserInterface().GetString("STRETCH");
00374       if(strType == "MANUAL") {
00375         p_inputMinimum.push_back(Application::GetUserInterface().GetDouble("MINIMUM"));
00376         p_inputMaximum.push_back(Application::GetUserInterface().GetDouble("MAXIMUM"));
00377 
00378         p_inputMiddle.push_back(Isis::NULL8);
00379       }
00380 
00381       // Or get the automatic parameters
00382       else if(strType != "NONE") {
00383         Isis::Histogram *hist = InputCubes[i]->histogram(0);
00384         p_inputMinimum.push_back(hist->Percent(
00385                                    Application::GetUserInterface().GetDouble("MINPERCENT")));
00386         p_inputMaximum.push_back(hist->Percent(
00387                                    Application::GetUserInterface().GetDouble("MAXPERCENT")));
00388         p_inputMiddle.push_back(Isis::NULL8);
00389         Application::GetUserInterface().Clear("MINIMUM");
00390         Application::GetUserInterface().Clear("MAXIMUM");
00391         Application::GetUserInterface().PutDouble("MINIMUM", p_inputMinimum[i]);
00392         Application::GetUserInterface().PutDouble("MAXIMUM", p_inputMaximum[i]);
00393 
00394         if(strType == "PIECEWISE") {
00395           p_inputMiddle[i] = hist->Median();
00396 
00397           // If the median is the min or max, back off to linear
00398           if(p_inputMiddle[i] == p_inputMinimum[i] ||
00399               p_inputMiddle[i] == p_inputMaximum[i]) {
00400             p_inputMiddle[i] = Isis::NULL8;
00401           }
00402         }
00403 
00404         // Make sure the image isn't constant
00405         if(p_inputMinimum[i] == p_inputMaximum[i]) {
00406           p_inputMaximum[i] = p_inputMinimum[i] + 1.0;
00407           if(strType == "PIECEWISE") p_inputMiddle[i] = p_inputMinimum[i] + 0.5;
00408         }
00409       }
00410     }
00411   }
00412 
00413 
00414    bool ProcessExport::HasInputRange() const {
00415      return p_inputMinimum.size() > 0;
00416    }
00417 
00418 
00420    double ProcessExport::GetInputMinimum(unsigned int n) const {
00421      if (n >= p_inputMinimum.size())
00422        throw IException(IException::Programmer,
00423            "There is no input minimum for channel " + IString((int) n),
00424            _FILEINFO_);
00425 
00426      return p_inputMinimum[n];
00427    }
00428 
00429 
00431    double ProcessExport::GetInputMaximum(unsigned int n) const {
00432      if (n >= p_inputMaximum.size())
00433        throw IException(IException::Programmer,
00434            "There is no input maximum for channel " + IString((int) n),
00435            _FILEINFO_);
00436 
00437      return p_inputMaximum[n];
00438    }
00439 
00440 
00456   void ProcessExport::SetOutputRange(const double minimum, const double maximum) {
00457     if(minimum >= maximum) {
00458       string message =
00459         "minimum must be less than the maximum [ProcessExport::SetOutputRange]";
00460       throw IException(IException::Programmer, message, _FILEINFO_);
00461     }
00462 
00463     p_outputMinimum = minimum;
00464     p_outputMaximum = maximum;
00465     p_outputMiddle = (p_outputMinimum + p_outputMaximum) / 2.0;
00466   }
00467 
00468 
00478   void ProcessExport::SetOutputNull(const double value) {
00479     p_Null = value;
00480     p_Null_Set = true;
00481   }
00482 
00483 
00493   void ProcessExport::SetOutputLis(const double value) {
00494     p_Lis = value;
00495     p_Lis_Set = true;
00496   }
00497 
00498 
00508   void ProcessExport::SetOutputLrs(const double value) {
00509     p_Lrs = value;
00510     p_Lrs_Set = true;
00511   }
00512 
00513 
00523   void ProcessExport::SetOutputHis(const double value) {
00524     p_His = value;
00525     p_His_Set = true;
00526   }
00527 
00528 
00538   void ProcessExport::SetOutputHrs(const double value) {
00539     p_Hrs = value;
00540     p_Hrs_Set = true;
00541   }
00542 
00543 
00547   double ProcessExport::OutputNull() {
00548     return p_Null_Set ? p_Null : p_outputMinimum;
00549   }
00550 
00551 
00555   double ProcessExport::OutputLis() {
00556     return p_Lis_Set ? p_Lis : p_outputMinimum;
00557   }
00558 
00559 
00563   double ProcessExport::OutputLrs() {
00564     return p_Lrs_Set ? p_Lrs : p_outputMinimum;
00565   }
00566 
00567 
00571   double ProcessExport::OutputHis() {
00572     return p_His_Set ? p_His : p_outputMaximum;
00573   }
00574 
00575 
00579   double ProcessExport::OutputHrs() {
00580     return p_Hrs_Set ? p_Hrs : p_outputMaximum;
00581   }
00582 
00583 
00610   void ProcessExport::SetOutputType(Isis::PixelType pixelIn) {
00611     p_pixelType = pixelIn;
00612 
00613     if(p_format < 0 || p_format > 3) {
00614       string message =
00615         "Format of the output file must be set prior to calling this method [ProcessExport::SetOutputType]";
00616       throw IException(IException::Programmer, message, _FILEINFO_);
00617     }
00618     if(pixelIn == Isis::UnsignedByte)
00619       SetOutputRange((double)VALID_MIN1, (double)VALID_MAX1);
00620     else if(pixelIn == Isis::UnsignedWord)
00621       SetOutputRange((double)VALID_MINU2, (double)VALID_MAXU2);
00622     else if(pixelIn == Isis::SignedWord)
00623       SetOutputRange((double)VALID_MIN2, (double)VALID_MAX2);
00624     else if(pixelIn == Isis::Real)
00625       if(p_format == JP2) {
00626         string message =
00627           "Unsupported bit type for JP2 formatted files [ProcessExport::SetOutputType]";
00628         throw IException(IException::Programmer, message, _FILEINFO_);
00629       }
00630       else {
00631         SetOutputRange(-DBL_MAX, DBL_MAX);
00632       }
00633     else {
00634       string message =
00635         "Unsupported bit type [ProcessExport::SetOutputType]";
00636       throw IException(IException::Programmer, message, _FILEINFO_);
00637     }
00638   }
00639 
00640 
00651   void ProcessExport::SetOutputEndian(enum ByteOrder byteOrderIn) {
00652     if(p_endianSwap != NULL) {
00653       delete p_endianSwap;
00654     }
00655     p_endianType = byteOrderIn;
00656     if(byteOrderIn == Isis::NoByteOrder) {
00657       p_endianSwap = new EndianSwapper("NoByteOrder");
00658     }
00659     else if(byteOrderIn == Isis::Lsb) {
00660       p_endianSwap = new EndianSwapper("LSB");
00661     }
00662     else if(byteOrderIn == Isis::Msb) {
00663       p_endianSwap = new EndianSwapper("MSB");
00664     }
00665   }
00666 
00667 
00678   void ProcessExport::InitProcess() {
00679     if(InputCubes.size() < 1) {
00680       string m = "You have not specified any input cubes";
00681       throw IException(IException::Programmer, m, _FILEINFO_);
00682     }
00683 
00684     // TODO this really belongs here, but causes problems because of its
00685     // coupling with an application User Interface that contains a STRETCH
00686     // parameter
00687     //if (!HasInputRange()) SetInputRange();
00688 
00689     // Construct a line buffer manager
00690     if(p_format == BIP) {
00691       p_progress->SetMaximumSteps((InputCubes[0]->sampleCount()) * (InputCubes[0]->lineCount()));
00692     }
00693     else {
00694       p_progress->SetMaximumSteps((InputCubes[0]->lineCount()) * (InputCubes[0]->bandCount()));
00695     }
00696 
00697 
00698     // Setup a stretch object
00699     p_str.clear();
00700     for(unsigned int i = 0; i < InputCubes.size(); i++) {
00701       p_str.push_back(new Stretch());
00702       if(p_inputMinimum.size() > 0) {
00703         if(Isis::IsValidPixel(p_inputMinimum[i])) {
00704           p_str[i]->AddPair(p_inputMinimum[i], p_outputMinimum);
00705           if(Isis::IsValidPixel(p_inputMiddle[i])) {
00706             p_str[i]->AddPair(p_inputMiddle[i], p_outputMiddle);
00707           }
00708           p_str[i]->AddPair(p_inputMaximum[i], p_outputMaximum);
00709         }
00710       }
00711 
00712       p_str[i]->SetNull(p_Null_Set ? p_Null : p_outputMinimum);
00713       p_str[i]->SetLis(p_Lis_Set ? p_Lis : p_outputMinimum);
00714       p_str[i]->SetLrs(p_Lrs_Set ? p_Lrs : p_outputMinimum);
00715       p_str[i]->SetHis(p_His_Set ? p_His : p_outputMaximum);
00716       p_str[i]->SetHrs(p_Hrs_Set ? p_Hrs : p_outputMaximum);
00717     }
00718 
00719     p_progress->CheckStatus();
00720     return;
00721   }
00722 
00723 
00742   void ProcessExport::StartProcess(void funct(Isis::Buffer &in)) {
00743     InitProcess();
00744 
00745     Isis::BufferManager *buff;
00746     if(p_format == BSQ) {
00747       buff = new Isis::LineManager(*InputCubes[0]);
00748     }
00749     else if(p_format == BIL || p_format == JP2) {
00750       buff = new Isis::LineManager(*InputCubes[0], true);
00751     }
00752     else if(p_format == BIP) {
00753       buff = new Isis::BandManager(*InputCubes[0]);
00754     }
00755     else {
00756       string m = "Invalid storage order.";
00757       throw IException(IException::Programmer, m, _FILEINFO_);
00758     }
00759 
00760     // Loop and let the app programmer fiddle with the buffers
00761     for(buff->begin(); !buff->end(); buff->next()) {
00762       // Read a line of data
00763       InputCubes[0]->read(*buff);
00764       // Stretch the pixels into the desired range
00765       for(int i = 0; i < buff->size(); i++) {
00766         (*buff)[i] = p_str[0]->Map((*buff)[i]);
00767       }
00768       // Invoke the user function
00769       funct(*buff);
00770       p_progress->CheckStatus();
00771     }
00772   }
00773 
00774 
00793   void ProcessExport::StartProcess(void funct(vector<Buffer *> &in)) {
00794     int length = (p_format == BIP) ?
00795       InputCubes[0]->bandCount() : InputCubes[0]->lineCount();
00796 
00797     // Loop and let the app programmer fiddle with the lines
00798     vector<BufferManager *> imgrs = GetBuffers();
00799     for (int k = 1; k <= length; k++) {
00800       vector<Buffer *> ibufs;
00801 
00802       for (unsigned int j = 0; j < InputCubes.size(); j++) {
00803         // Read a line of data
00804         InputCubes[j]->read(*imgrs[j]);
00805 
00806         // Stretch the pixels into the desired range
00807         for (int i = 0; i < InputCubes[0]->sampleCount(); i++)
00808           (*imgrs[j])[i] = p_str[j]->Map((*imgrs[j])[i]);
00809 
00810         ibufs.push_back(imgrs[j]);
00811       }
00812 
00813       // Invoke the user function
00814       funct(ibufs);
00815 
00816       for (unsigned int i = 0; i < imgrs.size(); i++) imgrs[i]->next();
00817       p_progress->CheckStatus();
00818     }
00819   }
00820 
00821 
00822   vector<BufferManager *> ProcessExport::GetBuffers() {
00823     InitProcess();
00824     vector<BufferManager *> imgrs;
00825     if (p_format == BSQ) {
00826       imgrs = GetBuffersBSQ();
00827     }
00828     else if (p_format == BIL || p_format == JP2) {
00829       imgrs = GetBuffersBIL();
00830     }
00831     else if (p_format == BIP) {
00832       imgrs = GetBuffersBIP();
00833     }
00834     else {
00835       string m = "Invalid storage order.";
00836       throw IException(IException::Programmer, m, _FILEINFO_);
00837     }
00838     return imgrs;
00839   }
00840 
00841 
00857   vector<BufferManager *> ProcessExport::GetBuffersBSQ() {
00858     int samples = InputCubes[0]->sampleCount();
00859     int lines = InputCubes[0]->lineCount();
00860 
00861     vector<BufferManager *> imgrs;
00862     for (unsigned int i = 0; i < InputCubes.size(); i++) {
00863       if((InputCubes[i]->sampleCount() == samples) &&
00864           (InputCubes[i]->lineCount() == lines)) {
00865 
00866         Isis::LineManager *iline = new Isis::LineManager(*InputCubes[i]);
00867         iline->begin();
00868         imgrs.push_back(iline);
00869       }
00870       else {
00871         string m = "All input cubes must have the same dimensions";
00872         throw IException(IException::Programmer, m, _FILEINFO_);
00873       }
00874     }
00875 
00876     return imgrs;
00877   }
00878 
00879 
00896   vector<BufferManager *> ProcessExport::GetBuffersBIL() {
00897     int samples = InputCubes[0]->sampleCount();
00898     int lines = InputCubes[0]->lineCount();
00899 
00900     vector<BufferManager *> imgrs;
00901     for (unsigned int i = 0; i < InputCubes.size(); i++) {
00902       if ((InputCubes[i]->sampleCount() == samples) &&
00903           (InputCubes[i]->lineCount() == lines)) {
00904 
00905         Isis::LineManager *iline = new Isis::LineManager(*InputCubes[i], true);
00906         iline->begin();
00907         imgrs.push_back(iline);
00908       }
00909       else {
00910         string m = "All input cubes must have the same dimensions";
00911         throw IException(IException::Programmer, m, _FILEINFO_);
00912       }
00913     }
00914 
00915     return imgrs;
00916   }
00917 
00934   vector<BufferManager *> ProcessExport::GetBuffersBIP() {
00935     int bands = InputCubes[0]->bandCount();
00936     int samples = InputCubes[0]->sampleCount();
00937 
00938     vector<BufferManager *> imgrs;
00939     for(unsigned int i = 0; i < InputCubes.size(); i++) {
00940       if((InputCubes[i]->bandCount() == bands) && (InputCubes[i]->sampleCount() == samples)) {
00941         Isis::BandManager *iband = new Isis::BandManager(*InputCubes[i]);
00942         iband->begin();
00943         imgrs.push_back(iband);
00944       }
00945       else {
00946         string m = "All input cubes must have the same dimensions";
00947         throw IException(IException::Programmer, m, _FILEINFO_);
00948       }
00949     }
00950 
00951     return imgrs;
00952   }
00953 
00954 
00955 
00956 
00969   void ProcessExport::StartProcess(std::ofstream &fout) {
00970     InitProcess();
00971 
00972     Isis::BufferManager *buff;
00973     if(p_format == BSQ) {
00974       buff = new Isis::LineManager(*InputCubes[0]);
00975     }
00976     else if(p_format == BIL) {
00977       buff = new Isis::LineManager(*InputCubes[0], true);
00978     }
00979     else if(p_format == BIP) {
00980       buff = new Isis::BandManager(*InputCubes[0]);
00981     }
00982     else {
00983       string m = "Output stream cannot be generated for requested storage order type.";
00984       throw IException(IException::Programmer, m, _FILEINFO_);
00985     }
00986 
00987     // Loop for each line of data
00988     for(buff->begin(); !buff->end(); buff->next()) {
00989       // Read a line of data
00990       InputCubes[0]->read(*buff);
00991       // Stretch the pixels into the desired range
00992       for(int i = 0; i < buff->size(); i++) {
00993         (*buff)[i] = p_str[0]->Map((*buff)[i]);
00994       }
00995       if(p_pixelType == Isis::UnsignedByte)
00996         isisOut8(*buff, fout);
00997       else if(p_pixelType == Isis::UnsignedWord)
00998         isisOut16u(*buff, fout);
00999       else if(p_pixelType == Isis::SignedWord)
01000         isisOut16s(*buff, fout);
01001       else if(p_pixelType == Isis::Real)
01002         isisOut32(*buff, fout);
01003       p_progress->CheckStatus();
01004     }
01005     delete buff;
01006     return;
01007   }
01008 
01009 
01026   void ProcessExport::isisOut8(Buffer &in, std::ofstream &fout) {
01027     char *out8 = new char[in.size()];
01028     for(int samp = 0; samp < in.size(); samp++) {
01029       double pixel = in[samp];
01030       if(pixel <= 0.0) {
01031         out8[samp] = 0;
01032       }
01033       else if(pixel >= 255.0) {
01034         out8[samp] = 255;
01035       }
01036       else {
01037         out8[samp] = (char)(in[samp] + 0.5);  //Rounds
01038       }
01039     }
01040     fout.write(out8, in.size());
01041     delete[] out8;
01042     return;
01043   }
01044 
01045 
01063   void ProcessExport::isisOut16s(Buffer &in, std::ofstream &fout) {
01064     short *out16s = new short[in.size()];
01065     for(int samp = 0; samp < in.size(); samp++) {
01066       double pixel = in[samp];
01067       short tempShort;
01068       if(pixel <= -32768.0) {
01069         tempShort = -(short)32768;
01070       }
01071       else if(pixel >= 32767.0) {
01072         tempShort = (short)32767;
01073       }
01074       else {
01075         //Rounds
01076         if(in[samp] < 0.0) {
01077           tempShort = (short)(in[samp] - 0.5);
01078         }
01079         else {
01080           tempShort = (short)(in[samp] + 0.5);
01081         }
01082       }
01083       void *p_swap = &tempShort;
01084       out16s[samp] = p_endianSwap->ShortInt(p_swap);
01085     }
01086     fout.write((char *)out16s, in.size() * 2);
01087     delete[] out16s;
01088     return;
01089   }
01090 
01091 
01109   void ProcessExport::isisOut16u(Buffer &in, std::ofstream &fout) {
01110     unsigned short *out16u = new unsigned short[in.size()];
01111     for(int samp = 0; samp < in.size(); samp++) {
01112       double pixel = in[samp];
01113       unsigned short tempShort;
01114       if(pixel <= 0.0) {
01115         tempShort = 0;
01116       }
01117       else if(pixel >= 65535.0) {
01118         tempShort = 65535;
01119       }
01120       else {
01121         tempShort = (unsigned short)(in[samp] + 0.5); //Rounds
01122       }
01123       unsigned short *p_swap = &tempShort;
01124       out16u[samp] = p_endianSwap->UnsignedShortInt(p_swap);
01125     }
01126 
01127     fout.write((char *)out16u, in.size() * 2);
01128     delete[] out16u;
01129     return;
01130   }
01131 
01132 
01149   void ProcessExport::isisOut32(Buffer &in, std::ofstream &fout) {
01150     int *out32 = new int[in.size()];
01151     for(int samp = 0; samp < in.size(); samp++) {
01152       double pixel = in[samp];
01153       float tempFloat;
01154       if(pixel <= -((double)FLT_MAX)) {
01155         tempFloat = -((double)FLT_MAX);
01156       }
01157       else if(pixel >= (double)FLT_MAX) {
01158         tempFloat = (double)FLT_MAX;
01159       }
01160       else {
01161         tempFloat = (double)in[samp];
01162       }
01163       void *p_swap = &tempFloat;
01164       out32[samp] = p_endianSwap->ExportFloat(p_swap);
01165     }
01166     fout.write((char *)out32, in.size() * 4);
01167     delete[] out32;
01168     return;
01169   }
01170 
01171 
01182   void ProcessExport::CreateWorldFile(const QString &worldFile) {
01183     try {
01184       Projection *proj = InputCubes[0]->projection();
01185       proj->SetWorld(1.0, 1.0);
01186       ofstream os;
01187       os.open(worldFile.toAscii().data(), ios::out);
01188 
01189       // X resolution
01190       os << std::fixed << setprecision(15)
01191          << proj->Resolution() << endl;
01192       // scale and rotation
01193       os << 0.0 << endl;
01194       os << 0.0 << endl;
01195 
01196       // Y resolution
01197       os << std::fixed << setprecision(15)
01198          << -proj->Resolution() << endl;
01199 
01200       // Upper left x at pixel middle
01201       os << std::fixed << setprecision(15)
01202          << proj->XCoord() << endl;
01203 
01204       // Upper left y at pixel middle
01205       os << std::fixed << setprecision(15)
01206          << proj->YCoord() << endl;
01207 
01208       os.close();
01209     }
01210     catch(IException &e) {
01211     }
01212   }
01213 }