00001
00024 #include <vigra/sized_int.hxx>
00025 #include <vigra_ext/HDRUtils.h>
00026 #include <vigra_impex/auto_file.hxx>
00027
00028 #include <ImfRgbaFile.h>
00029 #include <ImfArray.h>
00030
00031
00032
00033 inline bool readPGMHeader(FILE * file, int & w, int &h, int & maxval)
00034 {
00035 char line[257];
00036 fgets(line, 256, file);
00037 if (strncmp(line,"P5", 2)) {
00038 printf("pgm read: not a pgm file\n");
00039 return false;
00040 }
00041
00042 fgets(line, 256, file);
00043 while (line[0] == '#')
00044 fgets(line, 256, file);
00045
00046 sscanf(line,"%d %d", &w, &h);
00047 fgets(line, 256, file);
00048 sscanf(line, "%d", &maxval);
00049 return true;
00050 }
00051
00052 template<class Functor>
00053 void reduceFilesToHDR(std::vector<std::string> input, std::string output,
00054 bool onlyCompleteOverlap, Functor & reduce)
00055 {
00056 typedef float MaskType;
00057 typedef vigra::RGBValue<float> PixelType;
00058 typedef boost::shared_ptr<Imf::RgbaInputFile> InFilePtr;
00059 typedef boost::shared_ptr<vigra::auto_file> AutoFilePtr;
00060
00061
00062 std::vector<AutoFilePtr> inputGrayFiles;
00063 std::vector<InFilePtr> inputFiles;
00064 std::vector<vigra::Rect2D> inputROIs;
00065 vigra::Rect2D outputROI;
00066 vigra::Rect2D outputSize;
00067 for (unsigned i=0; i < input.size(); i++) {
00068 std::string grayFile = hugin_utils::stripExtension(input[i]) + "_gray.pgm";
00069 InFilePtr in(new Imf::RgbaInputFile(input[i].c_str()));
00070 inputFiles.push_back(in);
00071 Imath::Box2i dw = in->dataWindow();
00072 vigra::Rect2D roi(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
00073 DEBUG_DEBUG("image " << i << "ROI: " << roi);
00074 dw = in->displayWindow();
00075 vigra::Rect2D imgSize(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
00076
00077 AutoFilePtr inGray(new vigra::auto_file(grayFile.c_str(), "rb"));
00078 int w, h, maxval;
00079 readPGMHeader(inGray->get(), w, h, maxval);
00080 vigra_precondition(w == roi.width() && h == roi.height(), ".exr and _gray.pgm images not of the same size");
00081 inputGrayFiles.push_back(inGray);
00082 if (i==0) {
00083 outputROI = roi;
00084 outputSize = imgSize;
00085 } else {
00086 outputROI |= roi;
00087 outputSize |= imgSize;
00088 }
00089 inputROIs.push_back(roi);
00090 }
00091 DEBUG_DEBUG("output display: " << outputSize);
00092 DEBUG_DEBUG("output data (ROI): " << outputROI);
00093
00094
00095 Imath::Box2i displayWindow (Imath::V2i (outputSize.left(), outputSize.top()),
00096 Imath::V2i (outputSize.right() - 1, outputSize.bottom() - 1));
00097 Imath::Box2i dataWindow (Imath::V2i (outputROI.left(), outputROI.top()),
00098 Imath::V2i (outputROI.right() - 1, outputROI.bottom() - 1));
00099 Imf::RgbaOutputFile outputFile (output.c_str(), displayWindow, dataWindow, Imf::WRITE_RGBA);
00100
00101 int roiWidth = outputROI.right() - outputROI.left();
00102
00103
00104 int nScanlines = 64*1024 /2/4/input.size()/roiWidth;
00105 if (nScanlines < 10) nScanlines = 10;
00106 DEBUG_DEBUG("processing " << nScanlines << " scanlines in one go");
00107
00108 typedef boost::shared_ptr<vigra::ArrayVector<vigra::UInt8> > Array8Ptr;
00109 typedef boost::shared_ptr<Imf::Array2D<Imf::Rgba> > ArrayPtr;
00110 std::vector<ArrayPtr> inputArrays;
00111 std::vector<Array8Ptr> inputGrayArrays;
00112 std::vector<Imf::Rgba *> inputPtr(input.size());
00113 std::vector<vigra::UInt8 *> inputGrayPtr(input.size());
00114
00115 for (unsigned i=0; i < input.size(); i++) {
00116 ArrayPtr p(new Imf::Array2D<Imf::Rgba>);
00117 p->resizeErase(nScanlines, roiWidth);
00118 inputArrays.push_back(p);
00119 Array8Ptr pg(new vigra::ArrayVector<vigra::UInt8>(nScanlines*roiWidth, vigra::UInt8(0)));
00120 inputGrayArrays.push_back(pg);
00121 }
00122
00123 Imf::Array2D<Imf::Rgba> outputArray(nScanlines, roiWidth);
00124
00125
00126 int y = outputROI.top();
00127 while (y < outputROI.bottom())
00128 {
00129 for (unsigned j=0; j < input.size(); j++) {
00130 Imf::Rgba * pixels = &(*inputArrays[j])[0][0];
00131
00132 pixels = pixels - outputROI.left() - y * roiWidth;
00133 inputFiles[j]->setFrameBuffer( pixels, 1, roiWidth);
00134
00135 int ys = std::max(y, inputROIs[j].top());
00136 int ye = std::min(y + nScanlines-1, inputROIs[j].bottom()-1);
00137
00138 if (ys <=ye)
00139 inputFiles[j]->readPixels (ys, ye);
00140 inputPtr[j] = &(*inputArrays[j])[0][0];
00141
00142
00143 for(int k=0; k < nScanlines; k++) {
00144 if (k+y >= inputROIs[j].top() && k+y < inputROIs[j].bottom()) {
00145
00146 vigra::UInt8 * grayp = inputGrayArrays[j]->data() +
00147 (inputROIs[j].left()-outputROI.left()) + k*roiWidth;
00148 int nElem = inputROIs[j].width();
00149 size_t n = fread(grayp, 1, nElem, inputGrayFiles[j]->get());
00150 assert (n == (size_t)nElem);
00151 }
00152 }
00153 inputGrayPtr[j] = inputGrayArrays[j]->data();
00154 }
00155
00156 Imf::Rgba * outputPtr = &outputArray[0][0];
00157 Imf::Rgba * outputPtrEnd = outputPtr + nScanlines*roiWidth;
00158 for (; outputPtr != outputPtrEnd; ++outputPtr)
00159 {
00160 reduce.reset();
00161 bool valid = false;
00162 bool complete = true;
00163 for (unsigned int j=0; j< input.size(); j++) {
00164 Imf::Rgba p = *inputPtr[j];
00165 bool isValid = p.a > 0;
00166 valid |= isValid;
00167 complete &= isValid;
00168 if (isValid) {
00169 reduce(PixelType(p.r, p.g, p.b), *inputGrayPtr[j]);
00170 }
00171 ++inputPtr[j];
00172 ++inputGrayPtr[j];
00173 }
00174
00175 PixelType val = reduce();
00176 outputPtr->r = val.red();
00177 outputPtr->g = val.green();
00178 outputPtr->b = val.blue();
00179 if (onlyCompleteOverlap) {
00180 outputPtr->a = complete ? 1 : 0;
00181 } else {
00182 outputPtr->a = valid ? 1 : 0;
00183 }
00184 }
00185
00186 Imf::Rgba * pixels = &outputArray[0][0];
00187 pixels = pixels - outputROI.left() - y * roiWidth;
00188
00189 outputFile.setFrameBuffer (pixels,
00190 1, roiWidth);
00191 int wh = std::min(outputROI.bottom()-y, nScanlines);
00192 outputFile.writePixels( wh );
00193 y += nScanlines;
00194 }
00195 }
00196
00197 #if 0
00198
00199 for (int j=0; j < input.size(); j++) {
00200 int yend = y + nScanlines;
00201
00202 if (heightLeft[j] > 0) {
00203
00204 int y_rel_start = inputROIs[j].top() - y;
00205 if (y_rel_start > 0 && y_rel_start < nScanlines) {
00206
00207
00208 inputFiles[j].setFrameBuffer( &(*(inputArrays[j]))[0][0] - outputROI().left()
00209 - outputROI().top() * roiWidth,
00210 1, roiWidth);
00211
00212 int y_read_start = y
00213 int y_read_end = std::min(inputRoi
00214
00215 if (!( inputROIs[j].bottom() <= y || inputROIs[j].top() >= yend )) {
00216
00217
00218
00219 if (y >= inputROIs[j].top()
00220 int ystart =
00221 }
00222 #endif
00223