Creates a DRI image (dynamic range increase) out of three input images: normal exposure, under-exposed and over-exposed. THE INPUT IMAGES MUST BE GIVEN IN THIS ORDER!This algorithm is fairly simple: Iterate over all pixel of the normal exposed image. If the mean color value is below a threshold, take the pixel from the over-exposed image. If it is over a certain threshold, take it from the under-exposed image. To avoid sharp edges, a weighted sum is used. The weight results from the distance to the threshold. Both thresholds can be set, as well as the blending range.
#include <Base/Image/Image.hh>
#include <Base/Image/ImageIO.hh>
#include <Base/ImageUtils/ImageDraw.hh>
using namespace BIAS;
using namespace std;
int main(int argc, char *argv[]) {
const unsigned char LO_THRESHOLD = (unsigned char)100;
const unsigned char HI_THRESHOLD = (unsigned char)230;
const float BLENDING_RANGE = 1.0f;
if (argc < 4) {
cout << "wrong parameter count!!" << endl << endl;
cout << "usage:" << endl;
cout << argv[0] << " " << "<normal_image> <darker_image> <brighter_image>" << endl;
return -1;
}
cout << "normal image could not be loaded!" << endl;
return -1;
}
else {
cout << "normal image loaded!" << endl;
}
cout << "darker image could not be loaded!" << endl;
return -1;
}
else {
cout << "darker image loaded!" << endl;
}
cout << "brighter image could not be loaded!" << endl;
return -1;
}
else {
cout << "brighter image loaded!" << endl;
}
cout << "images loaded" << endl;
unsigned char *imDriData = imDri.GetImageData();
unsigned int offset = 0;
unsigned char mean = 0;
float weight = 0.0f;
cout << "starting iteration..." << endl;
for (
unsigned int y = 0; y < imNorm.
GetHeight(); y++) {
for (
unsigned int x = 0; x < imNorm.
GetWidth(); x++) {
mean = (imNormData[offset] + imNormData[offset+1] + imNormData[offset+2]) / 3;
if (mean < LO_THRESHOLD) {
weight = ((float)(LO_THRESHOLD - mean)) / (float)(LO_THRESHOLD);
weight *= BLENDING_RANGE;
weight = weight > 1.0f ? 1.0f : weight;
imDriData[offset] = (unsigned char)(weight*(float)imBrightData[offset] + (1.0f-weight)*(float)imNormData[offset]);
imDriData[offset+1] = (unsigned char)(weight*(float)imBrightData[offset+1] + (1.0f-weight)*(float)imNormData[offset+1]);
imDriData[offset+2] = (unsigned char)(weight*(float)imBrightData[offset+2] + (1.0f-weight)*(float)imNormData[offset+2]);
}
else if (mean > HI_THRESHOLD) {
weight = ((float)(mean - HI_THRESHOLD)) / (float)(255 - HI_THRESHOLD);
weight *= BLENDING_RANGE;
weight = weight > 1.0f ? 1.0f : weight;
imDriData[offset] = (unsigned char)(weight*(float)imDarkData[offset] + (1.0f-weight)*(float)imNormData[offset]);
imDriData[offset+1] = (unsigned char)(weight*(float)imDarkData[offset+1] + (1.0f-weight)*(float)imNormData[offset+1]);
imDriData[offset+2] = (unsigned char)(weight*(float)imDarkData[offset+2] + (1.0f-weight)*(float)imNormData[offset+2]);
}
else {
imDriData[offset] = imNormData[offset];
imDriData[offset+1] = imNormData[offset+1];
imDriData[offset+2] = imNormData[offset+2];
}
}
}
cout << "done!" << endl;
return 0;
}