Hugin trunk 0.1
Loading...
Searching...
No Matches
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>
37
38
39// hack to read pgm header
40inline 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
59template<class Functor>
60void 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
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;
95 } else {
96 outputROI |= roi;
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];
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();
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 readPGMHeader(FILE *file, int &w, int &h, int &maxval)
void reduceFilesToHDR(std::vector< std::string > input, std::string output, bool onlyCompleteOverlap, Functor &reduce)
Class used for opening files.
Definition FileRAII.h:34
#define DEBUG_DEBUG(msg)
Definition utils.h:68
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition utils.cpp:130
std::string getExtension(const std::string &basename2)
Get extension of a filename.
Definition utils.cpp:99
std::string tolower(const std::string &s)
convert a string to lowercase
Definition stl_utils.h:49
bool FileExists(const std::string &filename)
checks if file exists
Definition utils.cpp:362
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41