Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ReduceOpenEXR.h
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
24 #include <vigra/sized_int.hxx>
25 #include <vigra_ext/HDRUtils.h>
26 #include <vigra_ext/FileRAII.h>
27 
28 #ifdef _MSC_VER
29 // workaround for a bug in OpenEXR 3.1
30 // see https://github.com/AcademySoftwareFoundation/Imath/issues/212
31 #define IMATH_HALF_NO_LOOKUP_TABLE
32 #endif
33 
34 #include <ImfRgbaFile.h>
35 #include <ImfArray.h>
36 #include "hugin_utils/stl_utils.h"
37 
38 
39 // hack to read pgm header
40 inline bool readPGMHeader(FILE * file, int & w, int &h, int & maxval)
41 {
42  char line[257];
43  fgets(line, 256, file);
44  if (strncmp(line,"P5", 2)) {
45  printf("pgm read: not a pgm file\n");
46  return false;
47  }
48 
49  fgets(line, 256, file);
50  while (line[0] == '#')
51  fgets(line, 256, file);
52 
53  sscanf(line,"%d %d", &w, &h);
54  fgets(line, 256, file);
55  sscanf(line, "%d", &maxval);
56  return true;
57 }
58 
59 template<class Functor>
60 void reduceFilesToHDR(std::vector<std::string> input, std::string output,
61  bool onlyCompleteOverlap, Functor & reduce)
62 {
63  typedef vigra::RGBValue<float> PixelType;
64  typedef std::shared_ptr<Imf::RgbaInputFile> InFilePtr;
65  typedef std::shared_ptr<vigra_ext::FileRAII> AutoFilePtr;
66 
67  // open all input files.
68  std::vector<AutoFilePtr> inputGrayFiles;
69  std::vector<InFilePtr> inputFiles;
70  std::vector<vigra::Rect2D> inputROIs;
71  vigra::Rect2D outputROI;
72  vigra::Rect2D outputSize;
73  for (unsigned i=0; i < input.size(); i++) {
74  std::string grayFile = hugin_utils::stripExtension(input[i]) + "_gray.pgm";
75  // check that input images is exr file
76  vigra_precondition(hugin_utils::tolower(hugin_utils::getExtension(input[i])) == "exr", "Input files needs to be (linear) exr images");
77  // check that file with pixel weights exists
78  vigra_precondition(hugin_utils::FileExists(grayFile), "File with original pixel weights (" + grayFile + ") is missing");
79  InFilePtr in(new Imf::RgbaInputFile(input[i].c_str()));
80  inputFiles.push_back(in);
81  Imath::Box2i dw = in->dataWindow();
82  vigra::Rect2D roi(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
83  DEBUG_DEBUG("image " << i << "ROI: " << roi);
84  dw = in->displayWindow();
85  vigra::Rect2D imgSize(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
86 
87  AutoFilePtr inGray(new vigra_ext::FileRAII(grayFile.c_str(), "rb"));
88  int w, h, maxval;
89  readPGMHeader(inGray->get(), w, h, maxval);
90  vigra_precondition(w == roi.width() && h == roi.height(), ".exr and _gray.pgm images not of the same size");
91  inputGrayFiles.push_back(inGray);
92  if (i==0) {
93  outputROI = roi;
94  outputSize = imgSize;
95  } else {
96  outputROI |= roi;
97  outputSize |= imgSize;
98  }
99  inputROIs.push_back(roi);
100  }
101  DEBUG_DEBUG("output display: " << outputSize);
102  DEBUG_DEBUG("output data (ROI): " << outputROI);
103 
104  // create output file
105  Imath::Box2i displayWindow (Imath::V2i (outputSize.left(), outputSize.top()),
106  Imath::V2i (outputSize.right() - 1, outputSize.bottom() - 1));
107  Imath::Box2i dataWindow (Imath::V2i (outputROI.left(), outputROI.top()),
108  Imath::V2i (outputROI.right() - 1, outputROI.bottom() - 1));
109  Imf::RgbaOutputFile outputFile (output.c_str(), displayWindow, dataWindow, Imf::WRITE_RGBA);
110 
111  int roiWidth = outputROI.right() - outputROI.left();
112  // process some 64k of scanlines at a time.
113  // ass
114  int nScanlines = 64*1024 /2/4/input.size()/roiWidth;
115  if (nScanlines < 10) nScanlines = 10;
116  DEBUG_DEBUG("processing " << nScanlines << " scanlines in one go");
117 
118  typedef std::shared_ptr<vigra::ArrayVector<vigra::UInt8> > Array8Ptr;
119  typedef std::shared_ptr<Imf::Array2D<Imf::Rgba> > ArrayPtr;
120  std::vector<ArrayPtr> inputArrays;
121  std::vector<Array8Ptr> inputGrayArrays;
122  std::vector<Imf::Rgba *> inputPtr(input.size());
123  std::vector<vigra::UInt8 *> inputGrayPtr(input.size());
124  // create frame buffers for the input files
125  for (unsigned i=0; i < input.size(); i++) {
126  ArrayPtr p(new Imf::Array2D<Imf::Rgba>);
127  p->resizeErase(nScanlines, roiWidth);
128  inputArrays.push_back(p);
129  Array8Ptr pg(new vigra::ArrayVector<vigra::UInt8>(nScanlines*roiWidth, vigra::UInt8(0)));
130  inputGrayArrays.push_back(pg);
131  }
132  // create output framebuffer
133  Imf::Array2D<Imf::Rgba> outputArray(nScanlines, roiWidth);
134 
135  // main processing loop
136  int y = outputROI.top();
137  while (y < outputROI.bottom())
138  {
139  for (unsigned j=0; j < input.size(); j++) {
140  Imf::Rgba * pixels = &(*inputArrays[j])[0][0];
141  // shift to our buffer origin and apply shift required by readPixels()
142  pixels = pixels - outputROI.left() - y * roiWidth;
143  inputFiles[j]->setFrameBuffer( pixels, 1, roiWidth);
144  // TODO: restrict reading to actual ROI of input image.
145  int ys = std::max(y, inputROIs[j].top());
146  int ye = std::min(y + nScanlines-1, inputROIs[j].bottom()-1);
147  // read if inside roi
148  if (ys <=ye)
149  inputFiles[j]->readPixels (ys, ye);
150  inputPtr[j] = &(*inputArrays[j])[0][0];
151 
152  // read data from raw gray level input
153  for(int k=0; k < nScanlines; k++) {
154  if (k+y >= inputROIs[j].top() && k+y < inputROIs[j].bottom()) {
155  // read scanline from raw image
156  vigra::UInt8 * grayp = inputGrayArrays[j]->data() +
157  (inputROIs[j].left()-outputROI.left()) + k*roiWidth;
158  int nElem = inputROIs[j].width();
159  size_t n = fread(grayp, 1, nElem, inputGrayFiles[j]->get());
160  assert (n == (size_t)nElem);
161  }
162  }
163  inputGrayPtr[j] = inputGrayArrays[j]->data();
164  }
165  // reduce content
166  Imf::Rgba * outputPtr = &outputArray[0][0];
167  Imf::Rgba * outputPtrEnd = outputPtr + nScanlines*roiWidth;
168  for (; outputPtr != outputPtrEnd; ++outputPtr)
169  {
170  reduce.reset();
171  bool valid = false;
172  bool complete = true;
173  for (unsigned int j=0; j< input.size(); j++) {
174  Imf::Rgba p = *inputPtr[j];
175  bool isValid = p.a > 0;
176  valid |= isValid;
177  complete &= isValid;
178  if (isValid) {
179  reduce(PixelType(p.r, p.g, p.b), *inputGrayPtr[j]);
180  }
181  ++inputPtr[j];
182  ++inputGrayPtr[j];
183  }
184  // need to properly set the alpha...
185  PixelType val = reduce();
186  outputPtr->r = val.red();
187  outputPtr->g = val.green();
188  outputPtr->b = val.blue();
189  if (onlyCompleteOverlap) {
190  outputPtr->a = complete ? 1 : 0;
191  } else {
192  outputPtr->a = valid ? 1 : 0;
193  }
194  }
195  // save pixels.
196  Imf::Rgba * pixels = &outputArray[0][0];
197  pixels = pixels - outputROI.left() - y * roiWidth;
198 
199  outputFile.setFrameBuffer (pixels,
200  1, roiWidth);
201  int wh = std::min(outputROI.bottom()-y, nScanlines);
202  outputFile.writePixels( wh );
203  y += nScanlines;
204  }
205 }
206 
207 #if 0
208  // read in pixels
209  for (int j=0; j < input.size(); j++) {
210  int yend = y + nScanlines;
211  // check if there is something to read from this image
212  if (heightLeft[j] > 0) {
213  // calculate y-offset in terms of data window of image
214  int y_rel_start = inputROIs[j].top() - y;
215  if (y_rel_start > 0 && y_rel_start < nScanlines) {
216  // we have something to read, setup correct framebuffer address
217  //
218  inputFiles[j].setFrameBuffer( &(*(inputArrays[j]))[0][0] - outputROI().left()
219  - outputROI().top() * roiWidth,
220  1, roiWidth);
221 
222  int y_read_start = y
223  int y_read_end = std::min(inputRoi
224 
225  if (!( inputROIs[j].bottom() <= y || inputROIs[j].top() >= yend )) {
226  // inside the ROI. Calculate the number of rows inside the buffer
227 
228  // calculate position in framebuffer.
229  if (y >= inputROIs[j].top()
230  int ystart =
231  }
232 #endif
233 
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
void reduce(bool wraparound, SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor sa, AlphaIterator alpha_upperleft, AlphaAccessor aa, DestImageIterator dest_upperleft, DestImageIterator dest_lowerright, DestAccessor da, DestAlphaIterator dest_alpha_upperleft, DestAlphaIterator dest_alpha_lowerright, DestAlphaAccessor daa)
The Burt &amp; Adelson Reduce operation.
Definition: pyramid2.h:178
bool readPGMHeader(FILE *file, int &w, int &h, int &maxval)
Definition: ReduceOpenEXR.h:40
static char * line
Definition: svm.cpp:2784
std::string getExtension(const std::string &basename2)
Get extension of a filename.
Definition: utils.cpp:99
IMPEX double h[25][1024]
Definition: emor.cpp:169
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition: utils.cpp:130
Class used for opening files.
Definition: FileRAII.h:33
static T max(T x, T y)
Definition: svm.cpp:65
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
static T min(T x, T y)
Definition: svm.cpp:62
std::string tolower(const std::string &s)
convert a string to lowercase
Definition: stl_utils.h:49
void reduceFilesToHDR(std::vector< std::string > input, std::string output, bool onlyCompleteOverlap, Functor &reduce)
Definition: ReduceOpenEXR.h:60