ReduceOpenEXR.h

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00024 #include <vigra/sized_int.hxx>
00025 #include <vigra_ext/HDRUtils.h>
00026 #include <vigra_ext/FileRAII.h>
00027 
00028 #include <ImfRgbaFile.h>
00029 #include <ImfArray.h>
00030 
00031 
00032 // hack to read pgm header
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 vigra::RGBValue<float> PixelType;
00057     typedef std::shared_ptr<Imf::RgbaInputFile> InFilePtr;
00058     typedef std::shared_ptr<vigra_ext::FileRAII> AutoFilePtr;
00059 
00060     // open all input files.
00061     std::vector<AutoFilePtr> inputGrayFiles;
00062     std::vector<InFilePtr> inputFiles;
00063     std::vector<vigra::Rect2D> inputROIs;
00064     vigra::Rect2D outputROI;
00065     vigra::Rect2D outputSize;
00066     for (unsigned i=0; i < input.size(); i++) {
00067         std::string grayFile = hugin_utils::stripExtension(input[i]) + "_gray.pgm";
00068         InFilePtr in(new Imf::RgbaInputFile(input[i].c_str()));
00069         inputFiles.push_back(in);
00070         Imath::Box2i dw = in->dataWindow();
00071         vigra::Rect2D roi(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
00072         DEBUG_DEBUG("image " << i << "ROI: " << roi);
00073         dw = in->displayWindow();
00074         vigra::Rect2D imgSize(dw.min.x, dw.min.y, dw.max.x+1, dw.max.y+1);
00075 
00076         AutoFilePtr inGray(new vigra_ext::FileRAII(grayFile.c_str(), "rb"));
00077         int w, h, maxval;
00078         readPGMHeader(inGray->get(), w, h, maxval);
00079         vigra_precondition(w == roi.width() && h == roi.height(), ".exr and _gray.pgm images not of the same size");
00080         inputGrayFiles.push_back(inGray);
00081         if (i==0) {
00082             outputROI = roi;
00083             outputSize = imgSize;
00084         } else {
00085             outputROI |= roi;
00086             outputSize |= imgSize;
00087         }
00088         inputROIs.push_back(roi);
00089     }
00090     DEBUG_DEBUG("output display: " << outputSize);
00091     DEBUG_DEBUG("output data (ROI): " << outputROI);
00092 
00093     // create output file
00094     Imath::Box2i displayWindow (Imath::V2i (outputSize.left(), outputSize.top()),
00095                                 Imath::V2i (outputSize.right() - 1, outputSize.bottom() - 1));
00096     Imath::Box2i dataWindow (Imath::V2i (outputROI.left(), outputROI.top()),
00097                              Imath::V2i (outputROI.right() - 1, outputROI.bottom() - 1));
00098     Imf::RgbaOutputFile outputFile (output.c_str(), displayWindow, dataWindow, Imf::WRITE_RGBA);
00099 
00100     int roiWidth = outputROI.right() - outputROI.left();
00101     // process some 64k of scanlines at a time.
00102     // ass
00103     int nScanlines = 64*1024 /2/4/input.size()/roiWidth;
00104     if (nScanlines < 10) nScanlines = 10;
00105     DEBUG_DEBUG("processing " << nScanlines << " scanlines in one go");
00106 
00107     typedef std::shared_ptr<vigra::ArrayVector<vigra::UInt8> > Array8Ptr;
00108     typedef std::shared_ptr<Imf::Array2D<Imf::Rgba> > ArrayPtr;
00109     std::vector<ArrayPtr> inputArrays;
00110     std::vector<Array8Ptr> inputGrayArrays;
00111     std::vector<Imf::Rgba *> inputPtr(input.size());
00112     std::vector<vigra::UInt8 *> inputGrayPtr(input.size());
00113     // create frame buffers for the input files
00114     for (unsigned i=0; i < input.size(); i++) {
00115         ArrayPtr p(new Imf::Array2D<Imf::Rgba>);
00116         p->resizeErase(nScanlines, roiWidth);
00117         inputArrays.push_back(p);
00118         Array8Ptr pg(new vigra::ArrayVector<vigra::UInt8>(nScanlines*roiWidth, vigra::UInt8(0)));
00119         inputGrayArrays.push_back(pg);
00120     }
00121     // create output framebuffer
00122     Imf::Array2D<Imf::Rgba> outputArray(nScanlines, roiWidth);
00123 
00124     // main processing loop
00125     int y = outputROI.top();
00126     while (y < outputROI.bottom())
00127     {
00128         for (unsigned j=0; j < input.size(); j++) {
00129             Imf::Rgba * pixels = &(*inputArrays[j])[0][0];
00130             // shift to our buffer origin and apply shift required by readPixels()
00131             pixels = pixels - outputROI.left() - y * roiWidth;
00132             inputFiles[j]->setFrameBuffer( pixels, 1, roiWidth);
00133             // TODO: restrict reading to actual ROI of input image.
00134             int ys = std::max(y, inputROIs[j].top());
00135             int ye = std::min(y + nScanlines-1, inputROIs[j].bottom()-1);
00136             // read if inside roi
00137             if (ys <=ye)
00138                 inputFiles[j]->readPixels (ys, ye);
00139             inputPtr[j] = &(*inputArrays[j])[0][0];
00140 
00141             // read data from raw gray level input
00142             for(int k=0; k < nScanlines; k++) {
00143                 if (k+y >= inputROIs[j].top() && k+y < inputROIs[j].bottom()) {
00144                     // read scanline from raw image
00145                     vigra::UInt8 * grayp = inputGrayArrays[j]->data() +
00146                                              (inputROIs[j].left()-outputROI.left()) + k*roiWidth;
00147                     int nElem = inputROIs[j].width();
00148                     size_t n = fread(grayp, 1, nElem, inputGrayFiles[j]->get());
00149                     assert (n == (size_t)nElem);
00150                 }
00151             }
00152             inputGrayPtr[j] = inputGrayArrays[j]->data();
00153         }
00154         // reduce content
00155         Imf::Rgba * outputPtr = &outputArray[0][0];
00156         Imf::Rgba * outputPtrEnd = outputPtr + nScanlines*roiWidth;
00157         for (; outputPtr != outputPtrEnd; ++outputPtr)
00158         {
00159             reduce.reset();
00160             bool valid = false;
00161             bool complete = true;
00162             for (unsigned int j=0; j< input.size(); j++) {
00163                 Imf::Rgba p = *inputPtr[j];
00164                 bool isValid = p.a > 0;
00165                 valid |= isValid;
00166                 complete &= isValid;
00167                 if (isValid) {
00168                     reduce(PixelType(p.r, p.g, p.b), *inputGrayPtr[j]);
00169                 }
00170                 ++inputPtr[j];
00171                 ++inputGrayPtr[j];
00172             }
00173             // need to properly set the alpha...
00174             PixelType val = reduce();
00175             outputPtr->r = val.red();
00176             outputPtr->g = val.green();
00177             outputPtr->b = val.blue();
00178             if (onlyCompleteOverlap) {
00179                 outputPtr->a = complete ? 1 : 0;
00180             } else {
00181                 outputPtr->a = valid ? 1 : 0;
00182             }
00183         }
00184         // save pixels.
00185         Imf::Rgba * pixels = &outputArray[0][0];
00186         pixels = pixels - outputROI.left() - y * roiWidth;
00187 
00188         outputFile.setFrameBuffer (pixels,
00189                                    1, roiWidth);
00190         int wh = std::min(outputROI.bottom()-y, nScanlines);
00191         outputFile.writePixels( wh );
00192         y += nScanlines;
00193     }
00194 }
00195 
00196 #if 0
00197         // read in pixels
00198         for (int j=0; j < input.size(); j++) {
00199             int yend = y + nScanlines;
00200             // check if there is something to read from this image
00201             if (heightLeft[j] > 0) {
00202                 // calculate y-offset in terms of data window of image
00203                 int y_rel_start = inputROIs[j].top() - y;
00204                 if (y_rel_start > 0 && y_rel_start < nScanlines) {
00205                     // we have something to read, setup correct framebuffer address
00206                     //
00207                     inputFiles[j].setFrameBuffer( &(*(inputArrays[j]))[0][0] - outputROI().left()
00208                                                      - outputROI().top() * roiWidth,
00209                                                 1, roiWidth);
00210                       
00211                     int y_read_start = y
00212                     int y_read_end = std::min(inputRoi
00213                     
00214             if (!( inputROIs[j].bottom() <= y || inputROIs[j].top() >= yend )) {
00215                 // inside the ROI. Calculate the number of rows inside the buffer
00216                 
00217                 // calculate position in framebuffer.
00218                 if (y >= inputROIs[j].top()
00219                 int ystart = 
00220         }
00221 #endif
00222 

Generated on 31 Aug 2016 for Hugintrunk by  doxygen 1.4.7