Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleImageDri.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 /**
27  * @example ExampleImageDri.cpp
28  @relates Image
29  @brief Creates a DRI image (dynamic range increase) out of three input images:
30  * normal exposure, under-exposed and over-exposed. THE INPUT IMAGES MUST
31  * BE GIVEN IN THIS ORDER!
32  *
33  * This algorithm is fairly simple:
34  * Iterate over all pixel of the normal exposed image. If the mean color value
35  * is below a threshold, take the pixel from the over-exposed image. If it is
36  * over a certain threshold, take it from the under-exposed image. To avoid
37  * sharp edges, a weighted sum is used. The weight results from the distance
38  * to the threshold.
39  * Both thresholds can be set, as well as the blending range.
40  *
41  * @author rwulff
42  */
43 
44 #include <Base/Image/Image.hh>
45 #include <Base/Image/ImageIO.hh>
46 #include <Base/ImageUtils/ImageDraw.hh>
47 
48 
49 using namespace BIAS;
50 using namespace std;
51 
52 
53 int main(int argc, char *argv[]) {
54 
55  const unsigned char LO_THRESHOLD = (unsigned char)100;
56  const unsigned char HI_THRESHOLD = (unsigned char)230;
57 
58  // blend over a certain range:
59  // 1.0 = whole range
60  // 2.0 = 1/2 range
61  // 3.0 = 1/3 range and so on...
62  // e.g. if LO_THRESHOLD = 50 and BLENDING_RANGE = 2.0, intensities between
63  // 25 (= 50 * 1/2.0) and 50 will be blended linearly
64  const float BLENDING_RANGE = 1.0f;
65 
66  // check params
67  if (argc < 4) {
68  cout << "wrong parameter count!!" << endl << endl;
69  cout << "usage:" << endl;
70  cout << argv[0] << " " << "<normal_image> <darker_image> <brighter_image>" << endl;
71  return -1;
72  }
73 
74  // load images
75  Image<unsigned char> imNorm, imDark, imBright;
76 
77  if (ImageIO::Load(argv[1], imNorm) != 0) {
78  cout << "normal image could not be loaded!" << endl;
79  return -1;
80  }
81  else {
82  cout << "normal image loaded!" << endl;
83  }
84  if (ImageIO::Load(argv[2], imDark) != 0) {
85  cout << "darker image could not be loaded!" << endl;
86  return -1;
87  }
88  else {
89  cout << "darker image loaded!" << endl;
90  }
91  if (ImageIO::Load(argv[3], imBright) != 0) {
92  cout << "brighter image could not be loaded!" << endl;
93  return -1;
94  }
95  else {
96  cout << "brighter image loaded!" << endl;
97  }
98 
99  cout << "images loaded" << endl;
100 
101  // ensure that input images have same size and RGB color model and init diffImage
102  BIASASSERT(imNorm.GetWidth() == imDark.GetWidth() && imNorm.GetHeight() == imDark.GetHeight());
103  BIASASSERT(imDark.GetWidth() == imBright.GetWidth() && imDark.GetHeight() == imBright.GetHeight());
104  BIASASSERT(imNorm.GetColorModel() == ImageBase::CM_RGB);
105  BIASASSERT(imDark.GetColorModel() == ImageBase::CM_RGB);
106  BIASASSERT(imBright.GetColorModel() == ImageBase::CM_RGB);
107 
108  Image<unsigned char> imDri(imNorm);
109 
110  // get image data
111  unsigned char *imNormData = imNorm.GetImageData();
112  unsigned char *imDarkData = imDark.GetImageData();
113  unsigned char *imBrightData = imBright.GetImageData();
114  unsigned char *imDriData = imDri.GetImageData();
115  unsigned int offset = 0;
116  unsigned char mean = 0;
117  float weight = 0.0f;
118 
119  cout << "starting iteration..." << endl;
120 
121  // iterate over pixels and draw difference image
122  for (unsigned int y = 0; y < imNorm.GetHeight(); y++) {
123  for (unsigned int x = 0; x < imNorm.GetWidth(); x++) {
124  offset = y*imNorm.GetWidth()*imNorm.GetChannelCount() + x*imNorm.GetChannelCount();
125 
126  mean = (imNormData[offset] + imNormData[offset+1] + imNormData[offset+2]) / 3;
127 
128  if (mean < LO_THRESHOLD) {
129  weight = ((float)(LO_THRESHOLD - mean)) / (float)(LO_THRESHOLD);
130  weight *= BLENDING_RANGE; // blend over a certain range
131  weight = weight > 1.0f ? 1.0f : weight;
132  imDriData[offset] = (unsigned char)(weight*(float)imBrightData[offset] + (1.0f-weight)*(float)imNormData[offset]);
133  imDriData[offset+1] = (unsigned char)(weight*(float)imBrightData[offset+1] + (1.0f-weight)*(float)imNormData[offset+1]);
134  imDriData[offset+2] = (unsigned char)(weight*(float)imBrightData[offset+2] + (1.0f-weight)*(float)imNormData[offset+2]);
135  }
136  else if (mean > HI_THRESHOLD) {
137  weight = ((float)(mean - HI_THRESHOLD)) / (float)(255 - HI_THRESHOLD);
138  weight *= BLENDING_RANGE; // blend over a certain range
139  weight = weight > 1.0f ? 1.0f : weight;
140  imDriData[offset] = (unsigned char)(weight*(float)imDarkData[offset] + (1.0f-weight)*(float)imNormData[offset]);
141  imDriData[offset+1] = (unsigned char)(weight*(float)imDarkData[offset+1] + (1.0f-weight)*(float)imNormData[offset+1]);
142  imDriData[offset+2] = (unsigned char)(weight*(float)imDarkData[offset+2] + (1.0f-weight)*(float)imNormData[offset+2]);
143  }
144  else {
145  imDriData[offset] = imNormData[offset];
146  imDriData[offset+1] = imNormData[offset+1];
147  imDriData[offset+2] = imNormData[offset+2];
148  }
149  }
150  }
151 
152  ImageIO::Save("dri.mip", imDri);
153 
154  cout << "done!" << endl;
155 
156  return 0;
157 }
unsigned int GetWidth() const
Definition: ImageBase.hh:312
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
unsigned int GetHeight() const
Definition: ImageBase.hh:319
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
Definition: ImageIO.cpp:141