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_impex/auto_file.hxx>
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 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     // open all input files.
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     // create output file
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     // process some 64k of scanlines at a time.
00103     // ass
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     // create frame buffers for the input files
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     // create output framebuffer
00123     Imf::Array2D<Imf::Rgba> outputArray(nScanlines, roiWidth);
00124 
00125     // main processing loop
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             // shift to our buffer origin and apply shift required by readPixels()
00132             pixels = pixels - outputROI.left() - y * roiWidth;
00133             inputFiles[j]->setFrameBuffer( pixels, 1, roiWidth);
00134             // TODO: restrict reading to actual ROI of input image.
00135             int ys = std::max(y, inputROIs[j].top());
00136             int ye = std::min(y + nScanlines-1, inputROIs[j].bottom()-1);
00137             // read if inside roi
00138             if (ys <=ye)
00139                 inputFiles[j]->readPixels (ys, ye);
00140             inputPtr[j] = &(*inputArrays[j])[0][0];
00141 
00142             // read data from raw gray level input
00143             for(int k=0; k < nScanlines; k++) {
00144                 if (k+y >= inputROIs[j].top() && k+y < inputROIs[j].bottom()) {
00145                     // read scanline from raw image
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         // reduce content
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             // need to properly set the alpha...
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         // save pixels.
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         // read in pixels
00199         for (int j=0; j < input.size(); j++) {
00200             int yend = y + nScanlines;
00201             // check if there is something to read from this image
00202             if (heightLeft[j] > 0) {
00203                 // calculate y-offset in terms of data window of image
00204                 int y_rel_start = inputROIs[j].top() - y;
00205                 if (y_rel_start > 0 && y_rel_start < nScanlines) {
00206                     // we have something to read, setup correct framebuffer address
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                 // inside the ROI. Calculate the number of rows inside the buffer
00217                 
00218                 // calculate position in framebuffer.
00219                 if (y >= inputROIs[j].top()
00220                 int ystart = 
00221         }
00222 #endif
00223 

Generated on 5 Dec 2014 for Hugintrunk by  doxygen 1.4.7