Commit 7469c935 authored by Fedor Morozov's avatar Fedor Morozov

HDR formats support and HDR making. Code only.

parent eff6dccb
This diff is collapsed.
......@@ -55,6 +55,8 @@ file(GLOB grfmt_hdrs src/grfmt*.hpp)
file(GLOB grfmt_srcs src/grfmt*.cpp)
list(APPEND grfmt_hdrs src/bitstrm.hpp)
list(APPEND grfmt_srcs src/bitstrm.cpp)
list(APPEND grfmt_hdrs src/rgbe.hpp)
list(APPEND grfmt_srcs src/rgbe.cpp)
source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs})
......
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "grfmt_hdr.hpp"
#include "rgbe.hpp"
namespace cv
{
HdrDecoder::HdrDecoder()
{
m_signature = "#?RGBE";
m_signature_alt = "#?RADIANCE";
file = NULL;
m_type = CV_32FC3;
}
HdrDecoder::~HdrDecoder()
{
}
size_t HdrDecoder::signatureLength() const
{
return m_signature.size() > m_signature_alt.size() ?
m_signature.size() : m_signature_alt.size();
}
bool HdrDecoder::readHeader()
{
file = fopen(m_filename.c_str(), "rb");
if(!file) {
CV_Error(Error::StsError, "HDR decoder: can't open file");
}
RGBE_ReadHeader(file, &m_width, &m_height, NULL);
if(m_width <= 0 || m_height <= 0) {
CV_Error(Error::StsError, "HDR decoder: invalid image size");
}
return true;
}
bool HdrDecoder::readData(Mat& img)
{
if(!file) {
readHeader();
}
if(img.cols != m_width || img.rows != m_height ||
img.type() != CV_32FC3) {
CV_Error(Error::StsError, "HDR decoder: bad mat");
}
RGBE_ReadPixels_RLE(file, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
fclose(file); file = NULL;
return true;
}
bool HdrDecoder::checkSignature( const String& signature ) const
{
if(signature.size() >= (m_signature.size()) &&
!memcmp(signature.c_str(), m_signature.c_str(), m_signature.size()))
return true;
if(signature.size() >= (m_signature.size()) &&
!memcmp(signature.c_str(), m_signature_alt.c_str(), m_signature_alt.size()))
return true;
return false;
}
ImageDecoder HdrDecoder::newDecoder() const
{
return new HdrDecoder;
}
HdrEncoder::HdrEncoder()
{
m_description = "Radiance HDR (*.hdr;*.pic)";
}
HdrEncoder::~HdrEncoder()
{
}
bool HdrEncoder::write( const Mat& img, const std::vector<int>& params )
{
if(img.type() != CV_32FC3) {
CV_Error(Error::StsBadArg, "HDR encoder: need 32FC3 mat");
}
if(!(params.empty() || params[0] == HDR_NONE || params[0] == HDR_RLE)) {
CV_Error(Error::StsBadArg, "HDR encoder: wrong compression param");
}
FILE *fout = fopen(m_filename.c_str(), "wb");
if(!fout) {
CV_Error(Error::StsError, "HDR encoder: can't open file");
}
RGBE_WriteHeader(fout, img.cols, img.rows, NULL);
if(params.empty() || params[0] == HDR_RLE) {
RGBE_WritePixels_RLE(fout, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
} else {
RGBE_WritePixels(fout, const_cast<float*>(img.ptr<float>()), img.cols * img.rows);
}
fclose(fout);
return true;
}
ImageEncoder HdrEncoder::newEncoder() const
{
return new HdrEncoder;
}
bool HdrEncoder::isFormatSupported( int depth ) const {
return depth == CV_32F;
}
}
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_HDR_H_
#define _GRFMT_HDR_H_
#include "grfmt_base.hpp"
namespace cv
{
enum HdrCompression
{
HDR_NONE = 0,
HDR_RLE = 1
};
// Radiance rgbe (.hdr) reader
class HdrDecoder : public BaseImageDecoder
{
public:
HdrDecoder();
~HdrDecoder();
bool readHeader();
bool readData( Mat& img );
bool checkSignature( const String& signature ) const;
ImageDecoder newDecoder() const;
size_t signatureLength() const;
protected:
String m_signature_alt;
FILE *file;
};
// ... writer
class HdrEncoder : public BaseImageEncoder
{
public:
HdrEncoder();
~HdrEncoder();
bool write( const Mat& img, const std::vector<int>& params );
ImageEncoder newEncoder() const;
bool isFormatSupported( int depth ) const;
protected:
};
}
#endif/*_GRFMT_HDR_H_*/
\ No newline at end of file
......@@ -71,6 +71,7 @@ TiffDecoder::TiffDecoder()
TIFFSetErrorHandler( GrFmtSilentTIFFErrorHandler );
TIFFSetWarningHandler( GrFmtSilentTIFFErrorHandler );
}
m_hdr = false;
}
......@@ -133,6 +134,14 @@ bool TiffDecoder::readHeader()
m_width = wdth;
m_height = hght;
if((bpp == 32 && ncn == 3) || photometric == PHOTOMETRIC_LOGLUV)
{
m_type = CV_32FC3;
m_hdr = true;
return true;
}
m_hdr = false;
if( bpp > 8 &&
((photometric != 2 && photometric != 1) ||
(ncn != 1 && ncn != 3 && ncn != 4)))
......@@ -171,6 +180,10 @@ bool TiffDecoder::readHeader()
bool TiffDecoder::readData( Mat& img )
{
if(m_hdr && img.type() == CV_32FC3)
{
return readHdrData(img);
}
bool result = false;
bool color = img.channels() > 1;
uchar* data = img.data;
......@@ -380,6 +393,46 @@ bool TiffDecoder::readData( Mat& img )
return result;
}
bool TiffDecoder::readHdrData(Mat& img)
{
int rows_per_strip = 0, photometric = 0;
if(!m_tif)
{
return false;
}
TIFF *tif = static_cast<TIFF*>(m_tif);
TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric );
TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
int size = 3 * m_width * m_height * sizeof (float);
int strip_size = 3 * m_width * rows_per_strip;
float *ptr = img.ptr<float>();
for (size_t i = 0; i < TIFFNumberOfStrips(tif); i++, ptr += strip_size)
{
TIFFReadEncodedStrip(tif, i, ptr, size);
size -= strip_size * sizeof(float);
}
close();
ptr = img.ptr<float>();
for(size_t i = 0; i < img.total(); i++, ptr += 3)
{
if(photometric == PHOTOMETRIC_LOGLUV)
{
float r = 3.240479f * ptr[0] + -1.537150f * ptr[1] + -0.498535f * ptr[2];
float g = -0.969256f * ptr[0] + 1.875991f * ptr[1] + 0.041556f * ptr[2];
float b = 0.055648f * ptr[0] + -0.204043f * ptr[1] + 1.057311f * ptr[2];
ptr[0] = b; ptr[1] = g; ptr[2] = r;
}
else
{
float tmp = ptr[0];
ptr[0] = ptr[2];
ptr[2] = tmp;
}
}
return true;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
......@@ -405,7 +458,11 @@ ImageEncoder TiffEncoder::newEncoder() const
bool TiffEncoder::isFormatSupported( int depth ) const
{
return depth == CV_8U || depth == CV_16U;
#ifdef HAVE_TIFF
return depth == CV_8U || depth == CV_16U || depth == CV_32F;
#else
return depth == CV_8U || depth == CV_16U;
#endif
}
void TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag,
......@@ -557,6 +614,39 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
return true;
}
bool TiffEncoder::writeHdr(const Mat& img)
{
float *ptr = const_cast<float*>(img.ptr<float>());
for(size_t i = 0; i < img.total(); i++, ptr += 3)
{
float x = 0.412453f * ptr[2] + 0.357580f * ptr[1] + 0.180423f * ptr[0];
float y = 0.212671f * ptr[2] + 0.715160f * ptr[1] + 0.072169f * ptr[0];
float z = 0.019334f * ptr[2] + 0.119193f * ptr[1] + 0.950227f * ptr[0];
ptr[0] = x; ptr[1] = y; ptr[2] = z;
}
TIFF* tif = TIFFOpen(m_filename.c_str(), "w");
if (!tif)
{
return false;
}
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.cols);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.rows);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_SGILOG);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_LOGLUV);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
int strip_size = 3 * img.cols;
ptr = const_cast<float*>(img.ptr<float>());
for (int i = 0; i < img.rows; i++, ptr += strip_size)
{
TIFFWriteEncodedStrip(tif, i, ptr, strip_size * sizeof(float));
}
TIFFClose(tif);
return true;
}
#endif
#ifdef HAVE_TIFF
......@@ -568,6 +658,12 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/)
int channels = img.channels();
int width = img.cols, height = img.rows;
int depth = img.depth();
#ifdef HAVE_TIFF
if(img.type() == CV_32FC3)
{
return writeHdr(img);
}
#endif
if (depth != CV_8U && depth != CV_16U)
return false;
......
......@@ -53,7 +53,7 @@ enum TiffCompression
{
TIFF_UNCOMP = 1,
TIFF_HUFFMAN = 2,
TIFF_PACKBITS = 32773
TIFF_PACKBITS = 32773,
};
enum TiffByteOrder
......@@ -108,6 +108,8 @@ public:
protected:
void* m_tif;
int normalizeChannelsNumber(int channels) const;
bool readHdrData(Mat& img);
bool m_hdr;
};
#endif
......@@ -130,6 +132,7 @@ protected:
int count, int value );
bool writeLibTiff( const Mat& img, const std::vector<int>& params );
bool writeHdr( const Mat& img );
};
}
......
......@@ -52,5 +52,6 @@
#include "grfmt_jpeg2000.hpp"
#include "grfmt_exr.hpp"
#include "grfmt_webp.hpp"
#include "grfmt_hdr.hpp"
#endif/*_GRFMTS_H_*/
......@@ -47,6 +47,7 @@
#include "grfmts.hpp"
#undef min
#undef max
#include <iostream>
/****************************************************************************************\
* Image Codecs *
......@@ -60,6 +61,8 @@ struct ImageCodecInitializer
{
decoders.push_back( new BmpDecoder );
encoders.push_back( new BmpEncoder );
decoders.push_back( new HdrDecoder );
encoders.push_back( new HdrEncoder );
#ifdef HAVE_JPEG
decoders.push_back( new JpegDecoder );
encoders.push_back( new JpegEncoder );
......@@ -203,7 +206,6 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
decoder->setSource(filename);
if( !decoder->readHeader() )
return 0;
CvSize size;
size.width = decoder->width();
size.height = decoder->height();
......@@ -271,7 +273,6 @@ static bool imwrite_( const String& filename, const Mat& image,
ImageEncoder encoder = findEncoder( filename );
if( encoder.empty() )
CV_Error( CV_StsError, "could not find a writer for the specified extension" );
if( !encoder->isFormatSupported(image.depth()) )
{
CV_Assert( encoder->isFormatSupported(CV_8U) );
......
This diff is collapsed.
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _RGBE_HDR_H_
#define _RGBE_HDR_H_
// posted to http://www.graphics.cornell.edu/~bjw/
// written by Bruce Walter (bjw@graphics.cornell.edu) 5/26/95
// based on code written by Greg Ward
#include <stdio.h>
typedef struct {
int valid; /* indicate which fields are valid */
char programtype[16]; /* listed at beginning of file to identify it
* after "#?". defaults to "RGBE" */
float gamma; /* image has already been gamma corrected with
* given gamma. defaults to 1.0 (no correction) */
float exposure; /* a value of 1.0 in an image corresponds to
* <exposure> watts/steradian/m^2.
* defaults to 1.0 */
} rgbe_header_info;
/* flags indicating which fields in an rgbe_header_info are valid */
#define RGBE_VALID_PROGRAMTYPE 0x01
#define RGBE_VALID_GAMMA 0x02
#define RGBE_VALID_EXPOSURE 0x04
/* return codes for rgbe routines */
#define RGBE_RETURN_SUCCESS 0
#define RGBE_RETURN_FAILURE -1
/* read or write headers */
/* you may set rgbe_header_info to null if you want to */
int RGBE_WriteHeader(FILE *fp, int width, int height, rgbe_header_info *info);
int RGBE_ReadHeader(FILE *fp, int *width, int *height, rgbe_header_info *info);
/* read or write pixels */
/* can read or write pixels in chunks of any size including single pixels*/
int RGBE_WritePixels(FILE *fp, float *data, int numpixels);
int RGBE_ReadPixels(FILE *fp, float *data, int numpixels);
/* read or write run length encoded files */
/* must be called to read or write whole scanlines */
int RGBE_WritePixels_RLE(FILE *fp, float *data, int scanline_width,
int num_scanlines);
int RGBE_ReadPixels_RLE(FILE *fp, float *data, int scanline_width,
int num_scanlines);
#endif/*_RGBE_HDR_H_*/
......@@ -80,6 +80,8 @@ CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs,
float h = 3, float hColor = 3,
int templateWindowSize = 7, int searchWindowSize = 21);
CV_EXPORTS_W void makeHDR(InputArrayOfArrays srcImgs, std::vector<float> expTimes, OutputArray dst);
} // cv
#endif
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "opencv2/photo.hpp"
#include "opencv2/imgproc.hpp"
namespace cv
{
static void triangleWeights(float weights[])
{
for(int i = 0; i < 128; i++) {
weights[i] = i + 1.0f;
}
for(int i = 128; i < 256; i++) {
weights[i] = 256.0f - i;
}
}
static void generateResponce(float responce[])
{
for(int i = 0; i < 256; i++) {
responce[i] = log((float)i);
}
responce[0] = responce[1];
}
void makeHDR(InputArrayOfArrays _images, std::vector<float> exp_times, OutputArray _dst)
{
std::vector<Mat> images;
_images.getMatVector(images);
if(images.empty()) {
printf("Need at least one vector image.");
}
if(images.size() != exp_times.size()) {
printf("Number of images and number of exposure times must be equal.");
}
int width = images[0].cols;
int height = images[0].rows;
for(size_t i = 0; i < images.size(); i++) {
if(images[i].cols != width || images[i].rows != height) {
printf("Image dimensions must be equal.");
}
if(images[i].type() != CV_8UC3) {
printf("Images must have CV_8UC3 type.");
}
}
_dst.create(images[0].size(), CV_32FC3);
Mat result = _dst.getMat();
float weights[256], responce[256];
triangleWeights(weights);
generateResponce(responce);
float *res_ptr = result.ptr<float>();
for(size_t pos = 0; pos < result.total(); pos++, res_ptr += 3) {
float sum[3] = {0, 0, 0};
float weight_sum = 0;
for(size_t im = 0; im < images.size(); im++) {
uchar *img_ptr = images[im].ptr() + 3 * pos;
float w = (weights[img_ptr[0]] + weights[img_ptr[1]] +
weights[img_ptr[2]]) / 3;
weight_sum += w;
for(int channel = 0; channel < 3; channel++) {
sum[channel] += w * (responce[img_ptr[channel]] - log(exp_times[im]));
}
}
for(int channel = 0; channel < 3; channel++) {
res_ptr[channel] = exp(sum[channel] / weight_sum);
}
}
}
};
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment