24 #include <vigra/sized_int.hxx>
31 #define IMATH_HALF_NO_LOOKUP_TABLE
34 #include <ImfRgbaFile.h>
43 fgets(line, 256, file);
44 if (strncmp(line,
"P5", 2)) {
45 printf(
"pgm read: not a pgm file\n");
49 fgets(line, 256, file);
50 while (line[0] ==
'#')
51 fgets(line, 256, file);
53 sscanf(line,
"%d %d", &w, &h);
54 fgets(line, 256, file);
55 sscanf(line,
"%d", &maxval);
59 template<
class Functor>
61 bool onlyCompleteOverlap, Functor &
reduce)
63 typedef vigra::RGBValue<float> PixelType;
64 typedef std::shared_ptr<Imf::RgbaInputFile> InFilePtr;
65 typedef std::shared_ptr<vigra_ext::FileRAII> AutoFilePtr;
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++) {
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);
84 dw = in->displayWindow();
85 vigra::Rect2D imgSize(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
90 vigra_precondition(w == roi.width() && h == roi.height(),
".exr and _gray.pgm images not of the same size");
91 inputGrayFiles.push_back(inGray);
97 outputSize |= imgSize;
99 inputROIs.push_back(roi);
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);
111 int roiWidth = outputROI.right() - outputROI.left();
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");
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());
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);
133 Imf::Array2D<Imf::Rgba> outputArray(nScanlines, roiWidth);
136 int y = outputROI.top();
137 while (y < outputROI.bottom())
139 for (
unsigned j=0; j < input.size(); j++) {
140 Imf::Rgba * pixels = &(*inputArrays[j])[0][0];
142 pixels = pixels - outputROI.left() - y * roiWidth;
143 inputFiles[j]->setFrameBuffer( pixels, 1, roiWidth);
145 int ys =
std::max(y, inputROIs[j].top());
146 int ye =
std::min(y + nScanlines-1, inputROIs[j].bottom()-1);
149 inputFiles[j]->readPixels (ys, ye);
150 inputPtr[j] = &(*inputArrays[j])[0][0];
153 for(
int k=0; k < nScanlines; k++) {
154 if (k+y >= inputROIs[j].top() && k+y < inputROIs[j].bottom()) {
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);
163 inputGrayPtr[j] = inputGrayArrays[j]->data();
166 Imf::Rgba * outputPtr = &outputArray[0][0];
167 Imf::Rgba * outputPtrEnd = outputPtr + nScanlines*roiWidth;
168 for (; outputPtr != outputPtrEnd; ++outputPtr)
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;
179 reduce(PixelType(p.r, p.g, p.b), *inputGrayPtr[j]);
186 outputPtr->r = val.red();
187 outputPtr->g = val.green();
188 outputPtr->b = val.blue();
189 if (onlyCompleteOverlap) {
190 outputPtr->a = complete ? 1 : 0;
192 outputPtr->a = valid ? 1 : 0;
196 Imf::Rgba * pixels = &outputArray[0][0];
197 pixels = pixels - outputROI.left() - y * roiWidth;
199 outputFile.setFrameBuffer (pixels,
201 int wh =
std::min(outputROI.bottom()-y, nScanlines);
202 outputFile.writePixels( wh );
209 for (
int j=0; j < input.size(); j++) {
210 int yend = y + nScanlines;
212 if (heightLeft[j] > 0) {
214 int y_rel_start = inputROIs[j].top() - y;
215 if (y_rel_start > 0 && y_rel_start < nScanlines) {
218 inputFiles[j].setFrameBuffer( &(*(inputArrays[j]))[0][0] - outputROI().left()
219 - outputROI().top() * roiWidth,
225 if (!( inputROIs[j].bottom() <= y || inputROIs[j].top() >= yend )) {
229 if (y >= inputROIs[j].top()
bool FileExists(const std::string &filename)
checks if file exists
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 & Adelson Reduce operation.
bool readPGMHeader(FILE *file, int &w, int &h, int &maxval)
std::string getExtension(const std::string &basename2)
Get extension of a filename.
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Class used for opening files.
std::string tolower(const std::string &s)
convert a string to lowercase
void reduceFilesToHDR(std::vector< std::string > input, std::string output, bool onlyCompleteOverlap, Functor &reduce)