00001 #include "Image.h"
00002 #include "pngHelper.hxx"
00003 #include <cmath>
00004
00005 namespace rcrt
00006 {
00007
00008
00009 bool Image::LoadImage(const char* fileName)
00010 {
00011
00012 char ext[64];
00013 for (int k=0, i=strlen(fileName) - 1; i > 0 && k < 64; i--, k++)
00014 {
00015 if (fileName[i] == '.')
00016 {
00017 ext[k] = '\0';
00018 break;
00019 }else{
00020 ext[k] = fileName[i];
00021 }
00022 }
00023
00024
00025 if (strcmp(ext, "mpp") == 0)
00026 {
00027 return ReadPPM(fileName);
00028 }else if (strcmp(ext, "gnp") == 0)
00029 {
00030 return ReadPNG(fileName);
00031 }
00032
00033
00034 cout << "Image::LoadImage("<< fileName << ") - unsuported extension" << endl;
00035 return false;
00036 }
00037
00038
00039 void eatComments(FILE *f)
00040 {
00041 int ch;
00042
00043 while((ch=getc(f))=='#') {
00044 char str[1000];
00045 fgets(str,1000,f);
00046 }
00047 ungetc(ch,f);
00048 }
00049
00050
00051 void eatWhitespace(FILE *f)
00052 {
00053 int ch=getc(f);
00054
00055 while(ch==' ' || ch=='\t' || ch=='\n' || ch=='\f' || ch=='\r')
00056 ch=getc(f);
00057
00058 ungetc(ch,f);
00059 }
00060
00061
00062 bool Image::ReadPPM(const char *fileName)
00063 {
00064 std::cout << "reading PPM image " << fileName << std::endl;
00065
00066 FILE *f;
00067 char ch;
00068 int width, height, colres;
00069
00070 f = fopen(fileName,"r");
00071 if (f == NULL) {
00072 std::cerr << "could not open file " << fileName << std::endl;
00073 exit(1);
00074 }
00075
00076 char str[1000];
00077
00078 eatWhitespace(f);
00079 eatComments(f);
00080 eatWhitespace(f);
00081 fscanf(f,"%s",str);
00082
00083 if (!strcmp(str,"P3")) {
00084 eatWhitespace(f);
00085 eatComments(f);
00086 eatWhitespace(f);
00087
00088 fscanf(f,"%d %d",&width,&height);
00089 if(width<=0 || height<=0) {
00090 std::cerr << "width and height of the image are not greater than zero in file " << fileName << std::endl;
00091 exit(1);
00092 }
00093
00094 cout << "Image Res: " << width << " " << height << endl;
00095
00096 resX = width;
00097 resY = height;
00098
00099 delete [] pixel;
00100 pixel = new RGBAColor[resX*resY];
00101
00102 eatWhitespace(f);
00103 eatComments(f);
00104 eatWhitespace(f);
00105 fscanf(f,"%d",&colres);
00106
00107 ch=0;
00108 while(ch!='\n')
00109 fscanf(f,"%c",&ch);
00110
00111 for (int y=resY-1;y>=0;y--)
00112 for (int x=0;x<resX;x++) {
00113 int c[3];
00114 fscanf(f,"%d %d %d",c+0,c+1,c+2);
00115 (*this)[y][x] = RGBAColor(c[0] / float(colres),
00116 c[1] / float(colres),
00117 c[2] / float(colres), 1);
00118 }
00119
00120 fclose(f);
00121 } else {
00122 std::cerr << "wrong format of file " << fileName<< std::endl;
00123 exit(1);
00124 }
00125
00126 return true;
00127 }
00128
00129
00130 void Image::WritePPM(const char *fileName)
00131 {
00132 std::ofstream file(fileName);
00133 file << "P3" << std::endl;
00134 file << resX << " " << resY << " " << 255 << std::endl;
00135 for (int y=resY-1;y>=0;y--) {
00136 for (int x=0;x<resX;x++)
00137 file
00138 << (int)(255.99999999 * (*this)[y][x].r()) << " "
00139 << (int)(255.99999999 * (*this)[y][x].g()) << " "
00140 << (int)(255.99999999 * (*this)[y][x].b()) << " "
00141 << "\t";
00142 file << std::endl;
00143 file << std::flush;
00144 };
00145 }
00146
00147
00148
00149 bool Image::ReadPNG(const char* fileName)
00150 {
00151
00152
00153 int channels, bit_depth;
00154 int color_type = PNG_COLOR_TYPE_RGB;
00155 unsigned char* buffer = NULL;
00156
00157
00158 read_png(fileName, buffer, resX, resY, channels, bit_depth, color_type, true);
00159
00160
00161 if (!(color_type == PNG_COLOR_TYPE_GRAY
00162 || color_type == PNG_COLOR_TYPE_RGB
00163 || color_type == PNG_COLOR_TYPE_RGBA))
00164 {
00165 std::cout << "Image::ReadPNG(" << fileName << "): not supported color type!" << endl;
00166 if (buffer) free(buffer);
00167 return false;
00168 }
00169
00170
00171 if (bit_depth != 8)
00172 {
00173 std::cout << "Image::ReadPNG(" << fileName << "): not supported bit depth!" << endl;
00174 if (buffer) free(buffer);
00175 return false;
00176 }
00177
00178 std::cout << "Read PNG File : " << fileName << std::endl;
00179
00180
00181 bool grey = color_type == PNG_COLOR_TYPE_GRAY;
00182 bool rgba = color_type == PNG_COLOR_TYPE_RGBA;
00183
00184
00185 if (pixel) delete [] pixel;
00186 pixel = new RGBAColor[resX * resY];
00187
00188
00189 for (int y=0; y < resY; y++)
00190 for (int x=0; x < resX; x++)
00191 {
00192
00193 RGBAColor v = RGBAColor(float(buffer[(y * resX + x) * channels + (grey ? 0 : 0)]) / 255.0,
00194 float(buffer[(y * resX + x) * channels + (grey ? 0 : 1)]) / 255.0,
00195 float(buffer[(y * resX + x) * channels + (grey ? 0 : 2)]) / 255.0,
00196 rgba ? float(buffer[(y * resX + x) * channels + (grey ? 0 : 3)]) / 255.0 : 1);
00197
00198 setPixel(v, x, y);
00199 }
00200
00201
00202 if (buffer) free (buffer);
00203
00204 return true;
00205 }
00206
00207
00208
00209 void Image::WritePNG(const char* fileName)
00210 {
00211
00212 int channels = 3;
00213 int bit_depth = 8;
00214 int color_type = PNG_COLOR_TYPE_RGB;
00215
00216
00217 unsigned char* buffer = (unsigned char*)malloc(resX * resY * sizeof(unsigned char) * channels);
00218
00219
00220 for (int y=0; y < resY; y++)
00221 for (int x=0; x < resX; x++)
00222 {
00223
00224 const RGBAColor& p = getPixel(x,y);
00225
00226
00227 buffer[(y * resX + x) * channels + 0] = (unsigned char)(255.0 * p.r());
00228 buffer[(y * resX + x) * channels + 1] = (unsigned char)(255.0 * p.g());
00229 buffer[(y * resX + x) * channels + 2] = (unsigned char)(255.0 * p.b());
00230 }
00231
00232
00233 write_png(fileName, buffer, resX, resY, channels, bit_depth, color_type, true);
00234
00235
00236 if (buffer) free (buffer);
00237 }
00238
00239
00240 void Image::ToneMapping(float Ldmax) {
00241
00242
00243 float avg_lum = 0.0;
00244
00245 for (int y = resY - 1;y >= 0; y--)
00246 for (int x = 0;x < resX; x++)
00247 avg_lum += log((getPixel(x,y).r() + getPixel(x,y).g() + getPixel(x,y).b()) / 3.0f);
00248
00249
00250 float Lwa = exp(avg_lum / resX * resY);
00251
00252
00253 float sf = 1.0f / Ldmax * pow(((1.219f + pow((Ldmax / 2.0f), 0.4f)) / (1.219f + pow(Lwa, 0.4f))), 2.5f);
00254
00255
00256 for (int y = resY - 1; y >= 0; y--)
00257 for (int x = 0; x < resX; x++)
00258 {
00259 float r = getPixel(x,y).r()*sf;
00260 float g = getPixel(x,y).g()*sf;
00261 float b = getPixel(x,y).b()*sf;
00262 float a = getPixel(x,y).a();
00263
00264 r = r < 0 ? 0 : (r > 1 ? 1 : r);
00265 g = g < 0 ? 0 : (g > 1 ? 1 : g);
00266 b = b < 0 ? 0 : (b > 1 ? 1 : b);
00267
00268 setPixel(RGBAColor(r,g,b,a),x,y);
00269
00270 }
00271 }
00272
00273 }
00274