00001
00002
00023 #include <math.h>
00024 #include <iostream>
00025
00026 #include <config.h>
00027
00028 #ifdef __APPLE__
00029 #include "panoinc.h"
00030 #endif
00031
00032
00033 #include "ViewState.h"
00034 #include "TextureManager.h"
00035 #include "huginApp.h"
00036 #include "GLPreviewFrame.h"
00037
00038 #include "vigra/stdimage.hxx"
00039 #include "vigra/resizeimage.hxx"
00040 #include "base_wx/wxImageCache.h"
00041 #include "photometric/ResponseTransform.h"
00042 #include "panodata/Mask.h"
00043
00044
00045
00046 #if !defined Hugin_shared || !defined _WINDOWS
00047 #define GLEW_STATIC
00048 #endif
00049 #include <GL/glew.h>
00050 #include <wx/platform.h>
00051
00052 #ifdef __WXMAC__
00053 #include <OpenGL/gl.h>
00054 #include <OpenGL/glu.h>
00055 #else
00056 #include <GL/gl.h>
00057 #include <GL/glu.h>
00058 #endif
00059
00060 TextureManager::TextureManager(PT::Panorama *pano, ViewState *view_state_in)
00061 {
00062 m_pano = pano;
00063 photometric_correct = false;
00064 view_state = view_state_in;
00065 }
00066
00067 TextureManager::~TextureManager()
00068 {
00069
00070 textures.clear();
00071 }
00072
00073 void TextureManager::DrawImage(unsigned int image_number,
00074 unsigned int display_list)
00075 {
00076
00077 std::map<TextureKey, TextureInfo>::iterator it;
00078 HuginBase::SrcPanoImage *img_p = view_state->GetSrcImage(image_number);
00079 TextureKey key(img_p, &photometric_correct);
00080 it = textures.find(key);
00081 DEBUG_ASSERT(it != textures.end());
00082 it->second.Bind();
00083 glColor4f(1.0,1.0,1.0,1.0);
00084 if (it->second.GetUseAlpha() || it->second.GetHasActiveMasks())
00085 {
00086
00087 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00088 glEnable(GL_BLEND);
00089 }
00090 if (!photometric_correct)
00091 {
00092
00093
00094 HuginBase::SrcPanoImage *img = view_state->GetSrcImage(image_number);
00095
00096 float es = viewer_exposure / img->getExposure();
00097 float scale[4] = {es / img->getWhiteBalanceRed(),
00098 es,
00099 es / img->getWhiteBalanceBlue(),
00100 1.0};
00101 glColor3fv(scale);
00102 glCallList(display_list);
00103
00104
00105
00106
00107
00108
00109
00110 if (scale[0] > 1.0 || scale[1] > 1.0 || scale[2] > 1.0)
00111 {
00112 view_state->GetTextureManager()->DisableTexture();
00113 glEnable(GL_BLEND);
00114 glBlendFunc(GL_DST_COLOR, GL_ONE);
00115 glColor4f(1.0, 1.0, 1.0, 1.0);
00116
00117
00118 bool r, g, b;
00119 unsigned short int count = 0;
00120 while (( (r = (scale[0] > 2.0))
00121 || (g = (scale[1] > 2.0))
00122 || (b = (scale[2] > 2.0)))
00123 && count < 9)
00124 {
00125 glColor4f(r ? 1.0 : 0.0, g ? 1.0 : 0.0, b ? 1.0 : 0.0, 1.0);
00126 glCallList(display_list);
00127 if (r) scale[0] /= 2.0;
00128 if (g) scale[1] /= 2.0;
00129 if (b) scale[2] /= 2.0;
00130 count++;
00131 }
00132
00133 if (scale[0] > 1.0 || scale[1] > 1.0 || scale[2] > 1.0)
00134 {
00135
00136 scale[0] -= 1.0; scale[1] -= 1.0; scale[2] -= 1.0;
00137 glColor3fv(scale);
00138 glCallList(display_list);
00139 }
00140 glEnable(GL_TEXTURE_2D);
00141 glDisable(GL_BLEND);
00142 glColor3f(1.0, 1.0, 1.0);
00143 }
00144 } else {
00145
00146 glCallList(display_list);
00147 if (it->second.GetUseAlpha() || it->second.GetHasActiveMasks())
00148 {
00149 glDisable(GL_BLEND);
00150 }
00151 }
00152 }
00153
00154 unsigned int TextureManager::GetTextureName(unsigned int image_number)
00155 {
00156
00157 std::map<TextureKey, TextureInfo>::iterator it;
00158 HuginBase::SrcPanoImage *img_p = view_state->GetSrcImage(image_number);
00159 TextureKey key(img_p, &photometric_correct);
00160 it = textures.find(key);
00161 DEBUG_ASSERT(it != textures.end());
00162 return it->second.GetNumber();
00163 }
00164
00165 void TextureManager::BindTexture(unsigned int image_number)
00166 {
00167
00168 std::map<TextureKey, TextureInfo>::iterator it;
00169 HuginBase::SrcPanoImage *img_p = view_state->GetSrcImage(image_number);
00170 TextureKey key(img_p, &photometric_correct);
00171 it = textures.find(key);
00172 DEBUG_ASSERT(it != textures.end());
00173 it->second.Bind();
00174 }
00175
00176 void TextureManager::DisableTexture(bool maskOnly)
00177 {
00178 if(view_state->GetSupportMultiTexture())
00179 {
00180 glActiveTexture(GL_TEXTURE1);
00181 glDisable(GL_TEXTURE_2D);
00182 glActiveTexture(GL_TEXTURE0);
00183 if(!maskOnly)
00184 glDisable(GL_TEXTURE_2D);
00185 }
00186 else
00187 {
00188 if(!maskOnly)
00189 glDisable(GL_TEXTURE_2D);
00190 };
00191 };
00192
00193 void TextureManager::Begin()
00194 {
00195 if (!photometric_correct)
00196 {
00197
00198 viewer_exposure = 1.0 / pow(2.0,
00199 m_pano->getOptions().outputExposureValue);
00200 };
00201 };
00202
00203 void TextureManager::End()
00204 {
00205 }
00206
00207 void TextureManager::CheckUpdate()
00208 {
00209
00210
00211
00212
00213 unsigned int num_images = m_pano->getNrOfImages();
00214 if (num_images == 0)
00215 {
00216 textures.clear();
00217 return;
00218 }
00219
00220
00221 if (photometric_correct && view_state->RequireRecalculatePhotometric())
00222 {
00223 textures.clear();
00224 }
00225 HuginBase::PanoramaOptions *dest_img = view_state->GetOptions();
00226
00227
00228 DEBUG_INFO("Updating texture sizes.");
00229
00230
00231 double total_fov = 0.0;
00232 for (unsigned int image_index = 0; image_index < num_images; image_index++)
00233 {
00234 HuginBase::SrcPanoImage *src = view_state->GetSrcImage(image_index);
00235 double aspect = double(src->getSize().height())
00236 / double(src->getSize().width());
00237 total_fov += src->getHFOV() * aspect;
00238 };
00239
00240 texel_density = double(GetMaxTotalTexels()) / total_fov;
00241
00242
00243
00244
00245
00246 int texels_used = 0;
00247 double ideal_texels_used = 0.0;
00248 for (unsigned int image_index = 0; image_index < num_images; image_index++)
00249 {
00250
00251
00252 std::map<TextureKey, TextureInfo>::iterator it;
00253 HuginBase::SrcPanoImage *img_p = view_state->GetSrcImage(image_index);
00254 TextureKey key(img_p, &photometric_correct);
00255 it = textures.find(key);
00256 TextureInfo *texinfo;
00257
00258
00259
00260
00261 #if 0
00262 if (it == textures.end())
00263 {
00264
00265
00266
00267 unsigned int max_tex_width_p = int(log2(img_p->getSize().width())),
00268 max_tex_height_p = int(log2(img_p->getSize().height()));
00269
00270 {
00271 unsigned int biggest = GetMaxTextureSizePower();
00272 if (biggest < max_tex_width_p) max_tex_width_p = biggest;
00273 if (biggest < max_tex_height_p) max_tex_height_p = biggest;
00274 }
00275 std::cout << "Texture size for image " << image_index << " is "
00276 << (1 << max_tex_width_p) << " by "
00277 << (1 << max_tex_height_p) << "\n";
00278
00279 std::cout << "About to create new TextureInfo for "
00280 << img_p->getFilename()
00281 << ".\n";
00282 std::pair<std::map<TextureKey, TextureInfo>::iterator, bool> ins;
00283 ins = textures.insert(std::pair<TextureKey, TextureInfo>
00284 (TextureKey(img_p, &photometric_correct),
00285
00286
00287 TextureInfo(max_tex_width_p, max_tex_height_p)
00288 ));
00289 texinfo = &((ins.first)->second);
00290 }
00291 else
00292 {
00293 texinfo = &(it->second);
00294 }
00295
00296
00297 double hfov = img_p->getHFOV(),
00298 aspect = double (texinfo->height) / double (texinfo->width),
00299 ideal_texels = texel_density * hfov * aspect,
00300
00301 ideal_tex_width = sqrt(ideal_texels / aspect),
00302 ideal_tex_height = aspect * ideal_tex_width;
00303
00304 ideal_texels_used += ideal_texels;
00305 std::cout << "Ideal mip size: " << ideal_tex_width << " by "
00306 << ideal_tex_height << "\n";
00307
00308 int max_mip_level = (texinfo->width_p > texinfo->height_p)
00309 ? texinfo->width_p : texinfo->height_p;
00310 int mip_level = max_mip_level - ceil((ideal_tex_width > ideal_tex_height)
00311 ? log2(ideal_tex_width) : log2(ideal_tex_height));
00312
00313 if ((texels_used + (1 << (texinfo->width_p + texinfo->height_p
00314 - mip_level * 2)))
00315 > ideal_texels_used)
00316 {
00317
00318 mip_level ++;
00319 }
00320
00321 if (mip_level > max_mip_level) mip_level = max_mip_level;
00322
00323 if (mip_level < 0) mip_level = 0;
00324
00325 int mip_width_p = texinfo->width_p - mip_level,
00326 mip_height_p = texinfo->height_p - mip_level;
00327
00328
00329 if (mip_width_p < 0) mip_width_p = 0;
00330 if (mip_height_p < 0) mip_height_p = 0;
00331
00332
00333
00334 texels_used += 1 << (mip_width_p + mip_height_p);
00335 std::cout << "biggest mipmap of image " << image_index << " is "
00336 << (1 << mip_width_p) << " by " << (1 << mip_height_p)
00337 << " (level " << mip_level <<").\n";
00338 std::cout << "Ideal texels used " << int(ideal_texels_used)
00339 << ", actually used " << texels_used << ".\n\n";
00340 if (texinfo->min_lod != mip_level)
00341 {
00342
00343 if (texinfo->min_lod > mip_level)
00344 {
00345
00346 texinfo->DefineLevels(mip_level,
00347 (texinfo->min_lod > max_mip_level) ?
00348 max_mip_level : texinfo->min_lod - 1,
00349 photometric_correct, dest_img,
00350 view_state->GetSrcImage(image_index));
00351 }
00352 texinfo->SetMaxLevel(mip_level);
00353 texinfo->min_lod = mip_level;
00354 }
00355 }
00356 #endif
00357
00358
00359
00360 double hfov = img_p->getHFOV(),
00361 aspect = double (img_p->getSize().height())
00362 / double (img_p->getSize().width()),
00363 ideal_texels = texel_density * hfov * aspect,
00364
00365 ideal_tex_width = sqrt(ideal_texels / aspect),
00366 ideal_tex_height = aspect * ideal_tex_width;
00367
00368 if (ideal_tex_width > img_p->getSize().width())
00369 ideal_tex_width = img_p->getSize().width();
00370 if (ideal_tex_height > img_p->getSize().height())
00371 ideal_tex_height = img_p->getSize().height();
00372
00373
00374
00375 unsigned int tex_width_p = int(log2(ideal_tex_width)) + 1,
00376 tex_height_p = int(log2(ideal_tex_height)) + 1;
00377
00378 {
00379 unsigned int biggest = GetMaxTextureSizePower();
00380 if (biggest < tex_width_p) tex_width_p = biggest;
00381 if (biggest < tex_height_p) tex_height_p = biggest;
00382 }
00383
00384
00385 ideal_texels_used += ideal_texels;
00386
00387 while ( (texels_used + (1 << (tex_width_p + tex_height_p)))
00388 > ideal_texels_used)
00389 {
00390
00391 if ((double) (1 << tex_height_p) / (double) (1 << tex_width_p)
00392 < aspect)
00393 {
00394 tex_width_p--;
00395 } else {
00396 tex_height_p--;
00397 }
00398 }
00399
00400 texels_used += 1 << (tex_width_p + tex_height_p);
00401 if ( it == textures.end()
00402 || (it->second).width_p != tex_width_p
00403 || (it->second).height_p != tex_height_p)
00404 {
00405
00406
00407
00408
00409
00410 TextureKey checkKey (img_p, &photometric_correct);
00411 if (textures.find(checkKey) != textures.end()) {
00412
00413 textures.erase(checkKey);
00414 }
00415
00416 std::pair<std::map<TextureKey, TextureInfo>::iterator, bool> ins;
00417 ins = textures.insert(std::pair<TextureKey, TextureInfo>
00418 (TextureKey(img_p, &photometric_correct),
00419
00420
00421 TextureInfo(view_state, tex_width_p, tex_height_p)
00422 ));
00423
00424 texinfo = &((ins.first)->second);
00425 texinfo->DefineLevels(0,
00426
00427 tex_width_p > tex_height_p ? tex_width_p : tex_height_p,
00428 photometric_correct,
00429 *dest_img,
00430 *view_state->GetSrcImage(image_index));
00431 texinfo->DefineMaskTexture(*view_state->GetSrcImage(image_index));
00432 }
00433 else
00434 {
00435 if(view_state->RequireRecalculateMasks(image_index))
00436 {
00437
00438 (*it).second.UpdateMask(*view_state->GetSrcImage(image_index));
00439 };
00440 }
00441 }
00442
00443
00444
00445 {
00446 CleanTextures();
00447 }
00448
00449
00450
00451
00452 }
00453
00454 void TextureManager::SetPhotometricCorrect(bool state)
00455 {
00456
00457 if (state != photometric_correct)
00458 {
00459 photometric_correct = state;
00460
00461
00462
00463
00464
00465
00466 textures.clear();
00467 }
00468 }
00469
00470 unsigned int TextureManager::GetMaxTotalTexels()
00471 {
00472
00473
00474
00475
00476 return 2097152;
00477
00478
00479
00480
00481
00482 }
00483
00484 unsigned int TextureManager::GetMaxTextureSizePower()
00485 {
00486
00487
00488
00489 static unsigned int max_size_p = 0;
00490 if (max_size_p) return max_size_p;
00491
00492 GLint max_size;
00493 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
00494 if (glGetError())
00495 {
00496 DEBUG_ERROR("Cannot find maximum texture size!");
00497
00498 return 6;
00499 }
00500 max_size_p = int(log2(max_size));
00501 DEBUG_INFO("Max texture size supported is " << max_size <<
00502 " (2^" << max_size_p << ")");
00503 return max_size_p;
00504 }
00505
00506 void TextureManager::CleanTextures()
00507 {
00508
00509
00510 unsigned int num_images = m_pano->getNrOfImages();
00511 bool retry = true;
00512 std::map<TextureKey, TextureInfo>::iterator tex;
00513 while (retry)
00514 {
00515 retry = false;
00516 for (tex = textures.begin(); tex != textures.end(); tex++)
00517 {
00518 bool found = false;
00519
00520
00521 for (unsigned int img = 0; img < num_images; img++)
00522 {
00523 TextureKey ik(view_state->GetSrcImage(img), &photometric_correct);
00524 if (ik == tex->first)
00525 {
00526 found = true;
00527 break;
00528 }
00529 }
00530
00531 if (!found)
00532 {
00533 DEBUG_INFO("Removing old texture for " << tex->first.filename << ".");
00534 retry = true;
00535 textures.erase(tex);
00536 break;
00537 }
00538 }
00539 }
00540 }
00541
00542 TextureManager::TextureInfo::TextureInfo(ViewState *new_view_state)
00543 {
00544
00545 DEBUG_ASSERT(0);
00546 m_viewState=new_view_state;
00547 has_active_masks=false;
00548 CreateTexture();
00549 }
00550
00551 TextureManager::TextureInfo::TextureInfo(ViewState *new_view_state, unsigned int width_p_in,
00552 unsigned int height_p_in)
00553 {
00554 m_viewState=new_view_state;
00555 has_active_masks=false;
00556 width_p = width_p_in;
00557 height_p = height_p_in;
00558 width = 1 << width_p;
00559 height = 1 << height_p;
00560 CreateTexture();
00561 }
00562
00563 void TextureManager::TextureInfo::CreateTexture()
00564 {
00565
00566 glGenTextures(1, (GLuint*) &num);
00567 DEBUG_DEBUG("textures num created " << num);
00568 glGenTextures(1, (GLuint*) &numMask);
00569
00570 min_lod = 1000;
00571 SetParameters();
00572 }
00573
00574 void TextureManager::TextureInfo::SetParameters()
00575 {
00576 BindImageTexture();
00577 glEnable(GL_TEXTURE_2D);
00578 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
00579 GL_LINEAR_MIPMAP_LINEAR);
00580
00581 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00583
00584
00585
00586 static bool checked_anisotropic = false;
00587 static bool has_anisotropic;
00588 static float anisotropy;
00589 if (!checked_anisotropic)
00590 {
00591
00592 if (GLEW_EXT_texture_filter_anisotropic)
00593 {
00594 has_anisotropic = true;
00595 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy);
00596 DEBUG_INFO("Using anisotropic filtering at maximum value "
00597 << anisotropy);
00598 } else {
00599 has_anisotropic = false;
00600 DEBUG_INFO("Anisotropic filtering is not available.");
00601 }
00602 checked_anisotropic = true;
00603 }
00604 if (has_anisotropic)
00605 {
00606 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
00607 anisotropy);
00608 }
00609 if(m_viewState->GetSupportMultiTexture())
00610 {
00611 BindMaskTexture();
00612 glEnable(GL_TEXTURE_2D);
00613 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
00614
00615 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00616 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00617 if(has_anisotropic)
00618 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,anisotropy);
00619 };
00620 GLenum error = glGetError();
00621 if (error != GL_NO_ERROR)
00622 {
00623 DEBUG_ERROR("GL Error when setting texture parameters: "
00624 << gluErrorString(error) << ".");
00625 }
00626 }
00627
00628 TextureManager::TextureInfo::~TextureInfo()
00629 {
00630
00631 DEBUG_DEBUG("textures num deleting " << num);
00632 glDeleteTextures(1, (GLuint*) &num);
00633 glDeleteTextures(1, (GLuint*) &numMask);
00634 }
00635
00636 void TextureManager::TextureInfo::Bind()
00637 {
00638 BindImageTexture();
00639 BindMaskTexture();
00640 if(m_viewState->GetSupportMultiTexture())
00641 {
00642 if(has_active_masks)
00643 glEnable(GL_TEXTURE_2D);
00644 else
00645 glDisable(GL_TEXTURE_2D);
00646 glActiveTexture(GL_TEXTURE0);
00647 };
00648 }
00649
00650 void TextureManager::TextureInfo::BindImageTexture()
00651 {
00652 if(m_viewState->GetSupportMultiTexture())
00653 {
00654 glActiveTexture(GL_TEXTURE0);
00655 glBindTexture(GL_TEXTURE_2D, num);
00656 }
00657 else
00658 glBindTexture(GL_TEXTURE_2D, num);
00659 };
00660 void TextureManager::TextureInfo::BindMaskTexture()
00661 {
00662 if(m_viewState->GetSupportMultiTexture())
00663 {
00664 glActiveTexture(GL_TEXTURE1);
00665 glEnable(GL_TEXTURE_2D);
00666 glBindTexture(GL_TEXTURE_2D, numMask);
00667 }
00668 };
00669
00670
00671
00672 void TextureManager::TextureInfo::DefineLevels(int min,
00673 int max,
00674 bool photometric_correct,
00675 const HuginBase::PanoramaOptions &dest_img,
00676 const HuginBase::SrcPanoImage &src_img)
00677 {
00678
00679
00680
00681
00682 BindImageTexture();
00683
00684 int max_mip_level = (width_p > height_p) ? width_p : height_p;
00685 if (max > max_mip_level) max = max_mip_level;
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 ImageCache::getInstance().softFlush();
00696 DEBUG_INFO("Loading image");
00697 std::string img_name = src_img.getFilename();
00698 ImageCache::EntryPtr entry = ImageCache::getInstance().getImageIfAvailable(img_name);
00699 if (!entry.get())
00700 {
00701
00702 m_imageRequest = ImageCache::getInstance().requestAsyncImage(img_name);
00703
00704 m_imageRequest->ready.connect(0,
00705 boost::bind(&TextureManager::TextureInfo::DefineLevels, this,
00706 min, max, photometric_correct, dest_img, src_img));
00707
00708 m_imageRequest->ready.connect(1,
00709 boost::bind(&GLPreviewFrame::redrawPreview,
00710 huginApp::getMainFrame()->getGLPreview()));
00711
00712
00713 GLubyte placeholder_image[64][64][4];
00714 for (int i = 0; i < 64; i++) {
00715 for (int j = 0; j < 64; j++) {
00716
00717 GLubyte c = (i/8+j/8)%2 ? 63 : 191;
00718 placeholder_image[i][j][0] = c;
00719 placeholder_image[i][j][1] = c;
00720 placeholder_image[i][j][2] = c;
00721
00722 placeholder_image[i][j][3] = 63;
00723 }
00724 }
00725 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, 64, 64,
00726 GL_RGBA, GL_UNSIGNED_BYTE,
00727 placeholder_image);
00728 SetParameters();
00729 return;
00730 }
00731
00732 m_imageRequest = ImageCache::RequestPtr();
00733 DEBUG_INFO("Converting to 8 bits");
00734 boost::shared_ptr<vigra::BRGBImage> img = entry->get8BitImage();
00735 boost::shared_ptr<vigra::BImage> mask = entry->mask;
00736
00737 int wo = 1 << (width_p - min), ho = 1 << (height_p - min);
00738 if (wo < 1) wo = 1; if (ho < 1) ho = 1;
00739
00740 DEBUG_INFO("Scaling image");
00741 vigra::BRGBImage out_img(wo, ho);
00742
00743
00744 has_mask = mask->width() && mask->height();
00745 vigra::UInt8Image *out_alpha;
00746 if (has_mask) out_alpha = new vigra::UInt8Image(wo, ho);
00747 if (wo < 2 || ho < 2)
00748 {
00749
00750
00751 for (int h = 0; h < ho; h++)
00752 {
00753 for (int w = 0; w < wo; w++)
00754 {
00755 out_img[h][w] = (*img)[0][0];
00756 if (has_mask) (*out_alpha)[h][w] = (*mask)[0][0];
00757 }
00758 }
00759 } else {
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 vigra::resizeImageNoInterpolation(srcImageRange(*img),
00771 destImageRange(out_img));
00772 if (has_mask)
00773 {
00774 vigra::resizeImageNoInterpolation(srcImageRange(*(mask)),
00775 destImageRange(*out_alpha));
00776 }
00777
00778 if (photometric_correct)
00779 {
00780 DEBUG_INFO("Performing photometric correction");
00781
00782
00783
00784 HuginBase::Photometric::InvResponseTransform <unsigned char, double>
00785 invResponse(src_img);
00786
00787
00788
00789 std::vector<double> outLut;
00790
00791
00792
00793
00794
00795 vigra_ext::EMoR::createEMoRLUT(m_viewState->GetSrcImage(0)->getEMoRParams(), outLut);
00796 vigra_ext::enforceMonotonicity(outLut);
00797 invResponse.setOutput(1.0/pow(2.0,dest_img.outputExposureValue),
00798 outLut, 255.0);
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 double scale_x = (double) src_img.getSize().width() / (double) wo,
00809 scale_y = (double) src_img.getSize().height() / (double) ho;
00810 for (int x = 0; x < wo; x++)
00811 {
00812 for (int y = 0; y < ho; y++)
00813 {
00814 double sx = (double) x * scale_x,
00815 sy = (double) y * scale_y;
00816 out_img[y][x] = invResponse(out_img[y][x],
00817 hugin_utils::FDiff2D(sx, sy));
00818 }
00819 }
00820 }
00821 }
00822
00823
00824
00825
00826
00827 DEBUG_INFO("Defining mipmap levels " << min << " to " << max
00828 << " of texture " << num << ", starting with a size of "
00829 << wo << " by " << ho << ".");
00830 GLint error;
00831 if (has_mask)
00832 {
00833
00834 unsigned char *image = new unsigned char[ho * wo * 4];
00835 unsigned char *pix_start = image;
00836 for (int h = 0; h < ho; h++)
00837 {
00838 for (int w = 0; w < wo; w++)
00839 {
00840 pix_start[0] = out_img[h][w].red();
00841 pix_start[1] = out_img[h][w].green();
00842 pix_start[2] = out_img[h][w].blue();
00843 pix_start[3] = (*out_alpha)[h][w];
00844 pix_start += 4;
00845 }
00846 }
00847
00848
00849
00850 error = gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, wo, ho,
00851 GL_RGBA, GL_UNSIGNED_BYTE,
00852 image);
00853 delete [] image;
00854 delete out_alpha;
00855 } else {
00856
00857 error = gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, wo, ho,
00858 GL_RGB, GL_UNSIGNED_BYTE,
00859 (unsigned char *) out_img.data());
00860 }
00861 if (error)
00862 {
00863 DEBUG_ERROR("GLU Error when building mipmap levels: "
00864 << gluErrorString(error) << ".");
00865 }
00866 error = glGetError();
00867 if (error != GL_NO_ERROR)
00868 {
00869 DEBUG_ERROR("GL Error when bulding mipmap levels: "
00870 << gluErrorString(error) << ".");
00871 }
00872 SetParameters();
00873 DEBUG_INFO("Finsihed loading texture.");
00874
00875
00876 }
00877
00878 void TextureManager::TextureInfo::DefineMaskTexture(const HuginBase::SrcPanoImage &srcImg)
00879 {
00880 has_active_masks=srcImg.hasActiveMasks();
00881 HuginBase::MaskPolygonVector masks=srcImg.getActiveMasks();
00882 if(has_active_masks)
00883 {
00884 unsigned int maskSize=(width>height) ? width : height;
00885 if(maskSize>64)
00886 maskSize/=2;
00887 BindMaskTexture();
00888 for(unsigned int i=0;i<masks.size();i++)
00889 masks[i].scale((double)maskSize/srcImg.getWidth(),(double)maskSize/srcImg.getHeight());
00890 vigra::UInt8Image mask(maskSize,maskSize,255);
00891
00892 if(maskSize>4)
00893 vigra_ext::applyMask(vigra::destImageRange(mask), masks);
00894 #ifdef __APPLE__
00895
00896
00897 unsigned char *image = new unsigned char[maskSize * maskSize * 2];
00898 unsigned char *pix_start = image;
00899 for (int h = 0; h < maskSize; h++)
00900 {
00901 for (int w = 0; w < maskSize; w++)
00902 {
00903 pix_start[0] = 255;
00904 pix_start[1] = mask[h][w];
00905 pix_start += 2;
00906 }
00907 }
00908 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, maskSize, maskSize,
00909 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, image);
00910 delete [] image;
00911 #else
00912 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, maskSize,maskSize,GL_ALPHA, GL_UNSIGNED_BYTE,(unsigned char *) mask.data());
00913 #endif
00914 };
00915 };
00916
00917 void TextureManager::TextureInfo::UpdateMask(const HuginBase::SrcPanoImage &srcImg)
00918 {
00919 if(m_viewState->GetSupportMultiTexture())
00920 {
00921
00922 glDeleteTextures(1, (GLuint*) &numMask);
00923
00924 glGenTextures(1, (GLuint*) &numMask);
00925 SetParameters();
00926 DefineMaskTexture(srcImg);
00927 };
00928 };
00929
00930 void TextureManager::TextureInfo::SetMaxLevel(int level)
00931 {
00932
00933 BindImageTexture();
00934
00935
00936
00937 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
00938 if(m_viewState->GetSupportMultiTexture())
00939 {
00940
00941 BindMaskTexture();
00942 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
00943 }
00944
00945 GLenum error = glGetError();
00946 if (error != GL_NO_ERROR)
00947 {
00948 DEBUG_ERROR("Error when setting the base mipmap level: "
00949 << gluErrorString(error) << ".");
00950 }
00951 }
00952
00953 TextureManager::TextureKey::TextureKey(HuginBase::SrcPanoImage *source,
00954 bool *photometric_correct_ptr)
00955 {
00956 SetOptions(source);
00957 photometric_correct = photometric_correct_ptr;
00958 }
00959
00960
00961 const bool TextureManager::TextureKey::operator==(const TextureKey comp) const
00962 {
00963 return !(*this < comp || comp < *this);
00964 }
00965
00966 const bool TextureManager::TextureKey::operator<(const TextureKey comp) const
00967 {
00968
00969
00970 if (filename < comp.filename) return true;
00971 if (filename > comp.filename) return false;
00972
00973 if (masks < comp.masks) return true;
00974 if (masks > comp.masks) return false;
00975
00976 if (!(*photometric_correct)) return false;
00977
00978 if (exposure < comp.exposure) return true;
00979 if (exposure > comp.exposure) return false;
00980 if (white_balance_red < comp.white_balance_red) return true;
00981 if (white_balance_red > comp.white_balance_red) return false;
00982 if (white_balance_blue < comp.white_balance_blue) return true;
00983 if (white_balance_blue > comp.white_balance_blue) return false;
00984 if (EMoR_params < comp.EMoR_params) return true;
00985 if (EMoR_params > comp.EMoR_params) return false;
00986 if (radial_vig_corr_coeff < comp.radial_vig_corr_coeff) return true;
00987 if (radial_vig_corr_coeff > comp.radial_vig_corr_coeff) return false;
00988 if (vig_corr_mode < comp.vig_corr_mode) return true;
00989 if (vig_corr_mode > comp.vig_corr_mode) return false;
00990 if (response_type < comp.response_type) return true;
00991 if (response_type > comp.response_type) return false;
00992 if (gamma < comp.gamma) return true;
00993 if (gamma > comp.gamma) return false;
00994 if (radial_distortion_red < comp.radial_distortion_red) return true;
00995 if (radial_distortion_red > comp.radial_distortion_red) return false;
00996 if (radial_distortion_blue < comp.radial_distortion_blue) return true;
00997 if (radial_distortion_blue > comp.radial_distortion_blue) return false;
00998
00999 return false;
01000 }
01001
01002 void TextureManager::TextureKey::SetOptions(HuginBase::SrcPanoImage *source)
01003 {
01004 filename = source->getFilename();
01005
01006
01007 std::stringstream mask_ss;
01008 source->printMaskLines(mask_ss, 0);
01009 masks = mask_ss.str();
01010
01011 exposure = source->getExposure();
01012 white_balance_red = source->getWhiteBalanceRed();
01013 white_balance_blue = source->getWhiteBalanceBlue();
01014 EMoR_params = source->getEMoRParams();
01015 radial_vig_corr_coeff = source->getRadialVigCorrCoeff();
01016 vig_corr_mode = source->getVigCorrMode();
01017 response_type = source->getResponseType();
01018 gamma = source->getGamma();
01019 radial_distortion_red = source->getRadialDistortionRed();
01020 radial_distortion_blue = source->getRadialDistortionBlue();
01021 }
01022