USGS

Isis 3.0 Object Programmers' Reference

Home

ProcessExport.cpp
Go to the documentation of this file.
1 
22 #include <iostream>
23 #include <iomanip>
24 #include "ProcessExport.h"
25 #include "Preference.h"
26 #include "IException.h"
27 #include "LineManager.h"
28 #include "BandManager.h"
29 #include "SpecialPixel.h"
30 #include "Histogram.h"
31 #include "Stretch.h"
32 #include "Application.h"
33 #include "EndianSwapper.h"
34 #include "Projection.h"
35 
36 using namespace std;
37 namespace Isis {
38 
40  ProcessExport::ProcessExport() : Isis::Process() {
41 
42  p_outputMinimum = 0.0;
43  p_outputMiddle = 0.5;
44  p_outputMaximum = 1.0;
45 
46  p_inputMinimum.clear();
47  p_inputMiddle.clear();
48  p_inputMaximum.clear();
49 
50  p_endianSwap = NULL;
51 
52  setFormat(BSQ);
53  SetOutputEndian(Isis::IsLsb() ? Isis::Lsb : Isis::Msb);
54  SetOutputType(Isis::Real);
55 
56  p_Null_Set = false;
57  p_Lis_Set = false;
58  p_Lrs_Set = false;
59  p_His_Set = false;
60  p_Hrs_Set = false;
61 
62  p_progress->SetText("Exporting");
63  }
64 
65 
68  if(p_endianSwap != NULL) {
69  delete p_endianSwap;
70  }
71  for(unsigned int i = 0; i < p_str.size(); i++) {
72  delete p_str[i];
73  }
74  p_str.clear();
75  }
76 
77 
100  void ProcessExport::SetInputRange(const double minimum, const double maximum) {
101  double middle = (minimum + maximum) / 2.0;
102  SetInputRange(minimum, middle, maximum);
103  }
104 
129  void ProcessExport::SetInputRange(const double minimum, const double maximum, const int index) {
130  double middle = (minimum + maximum) / 2.0;
131  SetInputRange(minimum, middle, maximum, index);
132  }
133 
160  void ProcessExport::SetInputRange(const double minimum, const double middle,
161  const double maximum) {
162  if(minimum >= middle) {
163  string message =
164  "minimum must be less than the middle [ProcessExport::SetInputRange]";
166  }
167  if(middle >= maximum) {
168  string message =
169  "middle must be less than the maximum [ProcessExport::SetInputRange]";
171  }
172  p_inputMinimum.clear();
173  p_inputMinimum.resize(InputCubes.size(), minimum);
174  p_inputMiddle.clear();
175  p_inputMiddle.resize(InputCubes.size(), middle);
176  p_inputMaximum.clear();
177  p_inputMaximum.resize(InputCubes.size(), maximum);
178  }
179 
208  void ProcessExport::SetInputRange(const double minimum, const double middle,
209  const double maximum, const int index) {
210  if(minimum >= middle) {
211  string message =
212  "minimum must be less than the middle [ProcessExport::SetInputRange]";
214  }
215  if(middle >= maximum) {
216  string message =
217  "middle must be less than the maximum [ProcessExport::SetInputRange]";
219  }
220  if(index >= (int)InputCubes.size() || index < 0) {
221  string message =
222  "index out of bounds";
224  }
225 
226  p_inputMinimum.resize(index + 1, minimum);
227  p_inputMiddle.resize(index + 1, middle);
228  p_inputMaximum.resize(index + 1, maximum);
229  p_inputMinimum[index] = minimum;
230  p_inputMiddle[index] = middle;
231  p_inputMaximum[index] = maximum;
232  }
233 
367  p_inputMinimum.clear();
368  p_inputMiddle.clear();
369  p_inputMaximum.clear();
370 
371  for(unsigned int i = 0; i < InputCubes.size(); i++) {
372  // Get the manual stretch parameters if needed
373  QString strType = Application::GetUserInterface().GetString("STRETCH");
374  if(strType == "MANUAL") {
375  p_inputMinimum.push_back(Application::GetUserInterface().GetDouble("MINIMUM"));
376  p_inputMaximum.push_back(Application::GetUserInterface().GetDouble("MAXIMUM"));
377 
378  p_inputMiddle.push_back(Isis::NULL8);
379  }
380 
381  // Or get the automatic parameters
382  else if(strType != "NONE") {
383  Isis::Histogram *hist = InputCubes[i]->histogram(0);
384  p_inputMinimum.push_back(hist->Percent(
385  Application::GetUserInterface().GetDouble("MINPERCENT")));
386  p_inputMaximum.push_back(hist->Percent(
387  Application::GetUserInterface().GetDouble("MAXPERCENT")));
388  p_inputMiddle.push_back(Isis::NULL8);
393 
394  if(strType == "PIECEWISE") {
395  p_inputMiddle[i] = hist->Median();
396 
397  // If the median is the min or max, back off to linear
398  if(p_inputMiddle[i] == p_inputMinimum[i] ||
399  p_inputMiddle[i] == p_inputMaximum[i]) {
400  p_inputMiddle[i] = Isis::NULL8;
401  }
402  }
403 
404  // Make sure the image isn't constant
405  if(p_inputMinimum[i] == p_inputMaximum[i]) {
406  p_inputMaximum[i] = p_inputMinimum[i] + 1.0;
407  if(strType == "PIECEWISE") p_inputMiddle[i] = p_inputMinimum[i] + 0.5;
408  }
409  }
410  }
411  }
412 
413 
414  bool ProcessExport::HasInputRange() const {
415  return p_inputMinimum.size() > 0;
416  }
417 
418 
420  double ProcessExport::GetInputMinimum(unsigned int n) const {
421  if (n >= p_inputMinimum.size())
423  "There is no input minimum for channel " + IString((int) n),
424  _FILEINFO_);
425 
426  return p_inputMinimum[n];
427  }
428 
429 
431  double ProcessExport::GetInputMaximum(unsigned int n) const {
432  if (n >= p_inputMaximum.size())
434  "There is no input maximum for channel " + IString((int) n),
435  _FILEINFO_);
436 
437  return p_inputMaximum[n];
438  }
439 
440 
456  void ProcessExport::SetOutputRange(const double minimum, const double maximum) {
457  if(minimum >= maximum) {
458  string message =
459  "minimum must be less than the maximum [ProcessExport::SetOutputRange]";
461  }
462 
463  p_outputMinimum = minimum;
464  p_outputMaximum = maximum;
466  }
467 
468 
478  void ProcessExport::SetOutputNull(const double value) {
479  p_Null = value;
480  p_Null_Set = true;
481  }
482 
483 
493  void ProcessExport::SetOutputLis(const double value) {
494  p_Lis = value;
495  p_Lis_Set = true;
496  }
497 
498 
508  void ProcessExport::SetOutputLrs(const double value) {
509  p_Lrs = value;
510  p_Lrs_Set = true;
511  }
512 
513 
523  void ProcessExport::SetOutputHis(const double value) {
524  p_His = value;
525  p_His_Set = true;
526  }
527 
528 
538  void ProcessExport::SetOutputHrs(const double value) {
539  p_Hrs = value;
540  p_Hrs_Set = true;
541  }
542 
543 
548  return p_Null_Set ? p_Null : p_outputMinimum;
549  }
550 
551 
556  return p_Lis_Set ? p_Lis : p_outputMinimum;
557  }
558 
559 
564  return p_Lrs_Set ? p_Lrs : p_outputMinimum;
565  }
566 
567 
572  return p_His_Set ? p_His : p_outputMaximum;
573  }
574 
575 
580  return p_Hrs_Set ? p_Hrs : p_outputMaximum;
581  }
582 
583 
611  p_pixelType = pixelIn;
612 
613  if(p_format < 0 || p_format > 3) {
614  string message =
615  "Format of the output file must be set prior to calling this method [ProcessExport::SetOutputType]";
617  }
618  if(pixelIn == Isis::UnsignedByte)
619  SetOutputRange((double)VALID_MIN1, (double)VALID_MAX1);
620  else if(pixelIn == Isis::UnsignedWord)
621  SetOutputRange((double)VALID_MINU2, (double)VALID_MAXU2);
622  else if(pixelIn == Isis::SignedWord)
623  SetOutputRange((double)VALID_MIN2, (double)VALID_MAX2);
624  else if(pixelIn == Isis::Real)
625  if(p_format == JP2) {
626  string message =
627  "Unsupported bit type for JP2 formatted files [ProcessExport::SetOutputType]";
629  }
630  else {
631  SetOutputRange(-DBL_MAX, DBL_MAX);
632  }
633  else {
634  string message =
635  "Unsupported bit type [ProcessExport::SetOutputType]";
637  }
638  }
639 
640 
651  void ProcessExport::SetOutputEndian(enum ByteOrder byteOrderIn) {
652  if(p_endianSwap != NULL) {
653  delete p_endianSwap;
654  }
655  p_endianType = byteOrderIn;
656  if(byteOrderIn == Isis::NoByteOrder) {
657  p_endianSwap = new EndianSwapper("NoByteOrder");
658  }
659  else if(byteOrderIn == Isis::Lsb) {
660  p_endianSwap = new EndianSwapper("LSB");
661  }
662  else if(byteOrderIn == Isis::Msb) {
663  p_endianSwap = new EndianSwapper("MSB");
664  }
665  }
666 
667 
679  if(InputCubes.size() < 1) {
680  string m = "You have not specified any input cubes";
682  }
683 
684  // TODO this really belongs here, but causes problems because of its
685  // coupling with an application User Interface that contains a STRETCH
686  // parameter
687  //if (!HasInputRange()) SetInputRange();
688 
689  // Construct a line buffer manager
690  if(p_format == BIP) {
691  p_progress->SetMaximumSteps((InputCubes[0]->sampleCount()) * (InputCubes[0]->lineCount()));
692  }
693  else {
694  p_progress->SetMaximumSteps((InputCubes[0]->lineCount()) * (InputCubes[0]->bandCount()));
695  }
696 
697 
698  // Setup a stretch object
699  p_str.clear();
700  for(unsigned int i = 0; i < InputCubes.size(); i++) {
701  p_str.push_back(new Stretch());
702  if(p_inputMinimum.size() > 0) {
704  p_str[i]->AddPair(p_inputMinimum[i], p_outputMinimum);
706  p_str[i]->AddPair(p_inputMiddle[i], p_outputMiddle);
707  }
708  p_str[i]->AddPair(p_inputMaximum[i], p_outputMaximum);
709  }
710  }
711 
712  p_str[i]->SetNull(OutputNull());
713  p_str[i]->SetLis(OutputLis());
714  p_str[i]->SetLrs(OutputLrs());
715  p_str[i]->SetHis(OutputHis());
716  p_str[i]->SetHrs(OutputHrs());
717  }
718 
720  return;
721  }
722 
723 
743  InitProcess();
744 
745  Isis::BufferManager *buff;
746  if(p_format == BSQ) {
747  buff = new Isis::LineManager(*InputCubes[0]);
748  }
749  else if(p_format == BIL || p_format == JP2) {
750  buff = new Isis::LineManager(*InputCubes[0], true);
751  }
752  else if(p_format == BIP) {
753  buff = new Isis::BandManager(*InputCubes[0]);
754  }
755  else {
756  string m = "Invalid storage order.";
758  }
759 
760  // Loop and let the app programmer fiddle with the buffers
761  for(buff->begin(); !buff->end(); buff->next()) {
762  // Read a line of data
763  InputCubes[0]->read(*buff);
764  // Stretch the pixels into the desired range
765  for(int i = 0; i < buff->size(); i++) {
766  (*buff)[i] = p_str[0]->Map((*buff)[i]);
767  }
768  // Invoke the user function
769  funct(*buff);
771  }
772  }
773 
774 
793  void ProcessExport::StartProcess(void funct(vector<Buffer *> &in)) {
794  int length = (p_format == BIP) ?
795  InputCubes[0]->bandCount() : InputCubes[0]->lineCount();
796 
797  // Loop and let the app programmer fiddle with the lines
798  vector<BufferManager *> imgrs = GetBuffers();
799  for (int k = 1; k <= length; k++) {
800  vector<Buffer *> ibufs;
801 
802  for (unsigned int j = 0; j < InputCubes.size(); j++) {
803  // Read a line of data
804  InputCubes[j]->read(*imgrs[j]);
805 
806  // Stretch the pixels into the desired range
807  for (int i = 0; i < InputCubes[0]->sampleCount(); i++)
808  (*imgrs[j])[i] = p_str[j]->Map((*imgrs[j])[i]);
809 
810  ibufs.push_back(imgrs[j]);
811  }
812 
813  // Invoke the user function
814  funct(ibufs);
815 
816  for (unsigned int i = 0; i < imgrs.size(); i++) imgrs[i]->next();
818  }
819  }
820 
821 
822  vector<BufferManager *> ProcessExport::GetBuffers() {
823  InitProcess();
824  vector<BufferManager *> imgrs;
825  if (p_format == BSQ) {
826  imgrs = GetBuffersBSQ();
827  }
828  else if (p_format == BIL || p_format == JP2) {
829  imgrs = GetBuffersBIL();
830  }
831  else if (p_format == BIP) {
832  imgrs = GetBuffersBIP();
833  }
834  else {
835  string m = "Invalid storage order.";
836  throw IException(IException::Programmer, m, _FILEINFO_);
837  }
838  return imgrs;
839  }
840 
841 
857  vector<BufferManager *> ProcessExport::GetBuffersBSQ() {
858  int samples = InputCubes[0]->sampleCount();
859  int lines = InputCubes[0]->lineCount();
860 
861  vector<BufferManager *> imgrs;
862  for (unsigned int i = 0; i < InputCubes.size(); i++) {
863  if((InputCubes[i]->sampleCount() == samples) &&
864  (InputCubes[i]->lineCount() == lines)) {
865 
867  iline->begin();
868  imgrs.push_back(iline);
869  }
870  else {
871  string m = "All input cubes must have the same dimensions";
873  }
874  }
875 
876  return imgrs;
877  }
878 
879 
896  vector<BufferManager *> ProcessExport::GetBuffersBIL() {
897  int samples = InputCubes[0]->sampleCount();
898  int lines = InputCubes[0]->lineCount();
899 
900  vector<BufferManager *> imgrs;
901  for (unsigned int i = 0; i < InputCubes.size(); i++) {
902  if ((InputCubes[i]->sampleCount() == samples) &&
903  (InputCubes[i]->lineCount() == lines)) {
904 
905  Isis::LineManager *iline = new Isis::LineManager(*InputCubes[i], true);
906  iline->begin();
907  imgrs.push_back(iline);
908  }
909  else {
910  string m = "All input cubes must have the same dimensions";
912  }
913  }
914 
915  return imgrs;
916  }
917 
934  vector<BufferManager *> ProcessExport::GetBuffersBIP() {
935  int bands = InputCubes[0]->bandCount();
936  int samples = InputCubes[0]->sampleCount();
937 
938  vector<BufferManager *> imgrs;
939  for(unsigned int i = 0; i < InputCubes.size(); i++) {
940  if((InputCubes[i]->bandCount() == bands) && (InputCubes[i]->sampleCount() == samples)) {
942  iband->begin();
943  imgrs.push_back(iband);
944  }
945  else {
946  string m = "All input cubes must have the same dimensions";
948  }
949  }
950 
951  return imgrs;
952  }
953 
954 
955 
956 
969  void ProcessExport::StartProcess(std::ofstream &fout) {
970  InitProcess();
971 
972  Isis::BufferManager *buff;
973  if(p_format == BSQ) {
974  buff = new Isis::LineManager(*InputCubes[0]);
975  }
976  else if(p_format == BIL) {
977  buff = new Isis::LineManager(*InputCubes[0], true);
978  }
979  else if(p_format == BIP) {
980  buff = new Isis::BandManager(*InputCubes[0]);
981  }
982  else {
983  string m = "Output stream cannot be generated for requested storage order type.";
985  }
986 
987  // Loop for each line of data
988  for(buff->begin(); !buff->end(); buff->next()) {
989  // Read a line of data
990  InputCubes[0]->read(*buff);
991  // Stretch the pixels into the desired range
992  for(int i = 0; i < buff->size(); i++) {
993  (*buff)[i] = p_str[0]->Map((*buff)[i]);
994  }
995  if(p_pixelType == Isis::UnsignedByte)
996  isisOut8(*buff, fout);
997  else if(p_pixelType == Isis::UnsignedWord)
998  isisOut16u(*buff, fout);
999  else if(p_pixelType == Isis::SignedWord)
1000  isisOut16s(*buff, fout);
1001  else if(p_pixelType == Isis::Real)
1002  isisOut32(*buff, fout);
1004  }
1005  delete buff;
1006  return;
1007  }
1008 
1009 
1026  void ProcessExport::isisOut8(Buffer &in, std::ofstream &fout) {
1027  char *out8 = new char[in.size()];
1028  for(int samp = 0; samp < in.size(); samp++) {
1029  double pixel = in[samp];
1030  if(pixel <= 0.0) {
1031  out8[samp] = 0;
1032  }
1033  else if(pixel >= 255.0) {
1034  out8[samp] = 255;
1035  }
1036  else {
1037  out8[samp] = (char)(in[samp] + 0.5); //Rounds
1038  }
1039  }
1040  fout.write(out8, in.size());
1041  delete[] out8;
1042  return;
1043  }
1044 
1045 
1063  void ProcessExport::isisOut16s(Buffer &in, std::ofstream &fout) {
1064  short *out16s = new short[in.size()];
1065  for(int samp = 0; samp < in.size(); samp++) {
1066  double pixel = in[samp];
1067  short tempShort;
1068  if(pixel <= -32768.0) {
1069  tempShort = -(short)32768;
1070  }
1071  else if(pixel >= 32767.0) {
1072  tempShort = (short)32767;
1073  }
1074  else {
1075  //Rounds
1076  if(in[samp] < 0.0) {
1077  tempShort = (short)(in[samp] - 0.5);
1078  }
1079  else {
1080  tempShort = (short)(in[samp] + 0.5);
1081  }
1082  }
1083  void *p_swap = &tempShort;
1084  out16s[samp] = p_endianSwap->ShortInt(p_swap);
1085  }
1086  fout.write((char *)out16s, in.size() * 2);
1087  delete[] out16s;
1088  return;
1089  }
1090 
1091 
1109  void ProcessExport::isisOut16u(Buffer &in, std::ofstream &fout) {
1110  unsigned short *out16u = new unsigned short[in.size()];
1111  for(int samp = 0; samp < in.size(); samp++) {
1112  double pixel = in[samp];
1113  unsigned short tempShort;
1114  if(pixel <= 0.0) {
1115  tempShort = 0;
1116  }
1117  else if(pixel >= 65535.0) {
1118  tempShort = 65535;
1119  }
1120  else {
1121  tempShort = (unsigned short)(in[samp] + 0.5); //Rounds
1122  }
1123  unsigned short *p_swap = &tempShort;
1124  out16u[samp] = p_endianSwap->UnsignedShortInt(p_swap);
1125  }
1126 
1127  fout.write((char *)out16u, in.size() * 2);
1128  delete[] out16u;
1129  return;
1130  }
1131 
1132 
1149  void ProcessExport::isisOut32(Buffer &in, std::ofstream &fout) {
1150  int *out32 = new int[in.size()];
1151  for(int samp = 0; samp < in.size(); samp++) {
1152  double pixel = in[samp];
1153  float tempFloat;
1154  if(pixel <= -((double)FLT_MAX)) {
1155  tempFloat = -((double)FLT_MAX);
1156  }
1157  else if(pixel >= (double)FLT_MAX) {
1158  tempFloat = (double)FLT_MAX;
1159  }
1160  else {
1161  tempFloat = (double)in[samp];
1162  }
1163  void *p_swap = &tempFloat;
1164  out32[samp] = p_endianSwap->ExportFloat(p_swap);
1165  }
1166  fout.write((char *)out32, in.size() * 4);
1167  delete[] out32;
1168  return;
1169  }
1170 
1171 
1182  void ProcessExport::CreateWorldFile(const QString &worldFile) {
1183  try {
1184  Projection *proj = InputCubes[0]->projection();
1185  proj->SetWorld(1.0, 1.0);
1186  ofstream os;
1187  os.open(worldFile.toAscii().data(), ios::out);
1188 
1189  // X resolution
1190  os << std::fixed << setprecision(15)
1191  << proj->Resolution() << endl;
1192  // scale and rotation
1193  os << 0.0 << endl;
1194  os << 0.0 << endl;
1195 
1196  // Y resolution
1197  os << std::fixed << setprecision(15)
1198  << -proj->Resolution() << endl;
1199 
1200  // Upper left x at pixel middle
1201  os << std::fixed << setprecision(15)
1202  << proj->XCoord() << endl;
1203 
1204  // Upper left y at pixel middle
1205  os << std::fixed << setprecision(15)
1206  << proj->YCoord() << endl;
1207 
1208  os.close();
1209  }
1210  catch(IException &e) {
1211  }
1212  }
1213 }