00001
00027 #ifndef _VIGRA_EXT_IMAGETRANSFORMSGPU_H
00028 #define _VIGRA_EXT_IMAGETRANSFORMSGPU_H
00029
00030 #include <fstream>
00031 #include <iostream>
00032 #include <iomanip>
00033
00034 #include <hugin_shared.h>
00035 #include <vigra/basicimage.hxx>
00036 #include <vigra_ext/ROIImage.h>
00037 #include <vigra_ext/Interpolators.h>
00038 #include <vigra/accessor.hxx>
00039 #include <vigra/impex.hxx>
00040 #include <vigra_ext/impexalpha.hxx>
00041 #include <vigra_ext/FunctorAccessor.h>
00042
00043 #include <hugin_math/hugin_math.h>
00044 #include <hugin_utils/utils.h>
00045 #include <appbase/ProgressDisplayOld.h>
00046
00047 #include "MultiThreadOperations.h"
00048 #include <boost/thread/thread.hpp>
00049 #include <boost/bind.hpp>
00050
00051 using vigra::NumericTraits;
00052
00053 namespace vigra_ext
00054 {
00055
00056 IMPEX void SetGPUDebugMessages(const bool doPrint);
00057
00058 bool IMPEX transformImageGPUIntern(const std::string& coordXformGLSL,
00059 const std::string& interpolatorGLSL,
00060 const int interpolatorSize,
00061 const std::string& photometricGLSL,
00062 const std::vector<double>& invLut,
00063 const std::vector<double>& destLut,
00064 const vigra::Diff2D srcSize,
00065 const void* const srcBuffer,
00066 const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType,
00067 const void* const srcAlphaBuffer,
00068 const int srcAlphaGLType,
00069 const vigra::Diff2D destUL,
00070 const vigra::Diff2D destSize,
00071 void* const destBuffer,
00072 const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType,
00073 void* const destAlphaBuffer,
00074 const int destAlphaGLType,
00075 const bool warparound);
00076
00077
00078 enum {
00079
00080 XGL_BYTE=0, XGL_UNSIGNED_BYTE, XGL_SHORT, XGL_UNSIGNED_SHORT, XGL_INT, XGL_UNSIGNED_INT, XGL_FLOAT,
00081
00082 XGL_RGBA8, XGL_RGBA16, XGL_RGBA32F, XGL_LUMINANCE8_ALPHA8, XGL_LUMINANCE16_ALPHA16, XGL_LUMINANCE_ALPHA32F,
00083 XGL_RGB8, XGL_RGB16, XGL_RGB32F, XGL_LUMINANCE8, XGL_LUMINANCE16, XGL_LUMINANCE32F,
00084
00085 XGL_LUMINANCE, XGL_RGB, XGL_LUMINANCE_ALPHA, XGL_RGBA
00086 };
00087
00088 struct Error_GpuNumericTraits_not_specialized_for_this_case { };
00089
00090 template <class A>
00091 struct GpuNumericTraits {
00092 typedef Error_GpuNumericTraits_not_specialized_for_this_case ImagePixelComponentType;
00093 enum {NumBands = 0};
00094 enum {ImageGLInternalFormat = 0};
00095 enum {ImageGLTransferFormat = 0};
00096 enum {ImageGLFormat = 0};
00097 enum {ImagePixelComponentGLType = 0};
00098 };
00099
00100 #define DEFINE_GPUNUMERICTRAITS(IMAGECOMPONENT, GLFORMAT, GLFORMATRGB, GLTRANSFER, GLTRANSFERRGB, GLTYPE) \
00101 template<> \
00102 struct GpuNumericTraits<IMAGECOMPONENT> { \
00103 typedef IMAGECOMPONENT ImagePixelComponentType; \
00104 enum {NumBands = 1}; \
00105 enum {ImageGLInternalFormat = GLFORMAT}; \
00106 enum {ImageGLTransferFormat = GLTRANSFER}; \
00107 enum {ImageGLFormat = XGL_LUMINANCE}; \
00108 enum {ImagePixelComponentGLType = GLTYPE}; \
00109 }; \
00110 template<> \
00111 struct GpuNumericTraits<vigra::RGBValue<IMAGECOMPONENT, 0, 1, 2> > { \
00112 typedef IMAGECOMPONENT ImagePixelComponentType; \
00113 enum {NumBands = 3}; \
00114 enum {ImageGLInternalFormat = GLFORMATRGB}; \
00115 enum {ImageGLTransferFormat = GLTRANSFERRGB}; \
00116 enum {ImageGLFormat = XGL_RGB}; \
00117 enum {ImagePixelComponentGLType = GLTYPE}; \
00118 }; \
00119 template<> \
00120 struct GpuNumericTraits<vigra::TinyVector<IMAGECOMPONENT, 2> > { \
00121 typedef IMAGECOMPONENT ImagePixelComponentType; \
00122 enum {NumBands = 2}; \
00123 enum {ImageGLInternalFormat = GLFORMAT}; \
00124 enum {ImageGLTransferFormat = GLFORMAT}; \
00125 enum {ImageGLFormat = XGL_LUMINANCE_ALPHA}; \
00126 enum {ImagePixelComponentGLType = GLTYPE}; \
00127 }; \
00128 template<> \
00129 struct GpuNumericTraits<vigra::TinyVector<IMAGECOMPONENT, 4> > { \
00130 typedef IMAGECOMPONENT ImagePixelComponentType; \
00131 enum {NumBands = 4}; \
00132 enum {ImageGLInternalFormat = GLFORMATRGB}; \
00133 enum {ImageGLTransferFormat = GLFORMATRGB}; \
00134 enum {ImageGLFormat = XGL_RGBA}; \
00135 enum {ImagePixelComponentGLType = GLTYPE}; \
00136 };
00137
00138 DEFINE_GPUNUMERICTRAITS(vigra::Int8, XGL_LUMINANCE8_ALPHA8, XGL_RGBA8, XGL_LUMINANCE8, XGL_RGB8, XGL_BYTE);
00139 DEFINE_GPUNUMERICTRAITS(vigra::UInt8, XGL_LUMINANCE8_ALPHA8, XGL_RGBA8, XGL_LUMINANCE8, XGL_RGB8, XGL_UNSIGNED_BYTE);
00140 DEFINE_GPUNUMERICTRAITS(vigra::Int16, XGL_LUMINANCE16_ALPHA16, XGL_RGBA16, XGL_LUMINANCE16, XGL_RGB16, XGL_SHORT);
00141 DEFINE_GPUNUMERICTRAITS(vigra::UInt16, XGL_LUMINANCE16_ALPHA16, XGL_RGBA16, XGL_LUMINANCE16, XGL_RGB16, XGL_UNSIGNED_SHORT);
00142 DEFINE_GPUNUMERICTRAITS(vigra::Int32, XGL_LUMINANCE_ALPHA32F, XGL_RGBA32F, XGL_LUMINANCE32F, XGL_RGB32F, XGL_INT);
00143 DEFINE_GPUNUMERICTRAITS(vigra::UInt32, XGL_LUMINANCE_ALPHA32F, XGL_RGBA32F, XGL_LUMINANCE32F, XGL_RGB32F, XGL_UNSIGNED_INT);
00144 DEFINE_GPUNUMERICTRAITS(float, XGL_LUMINANCE_ALPHA32F, XGL_RGBA32F, XGL_LUMINANCE32F, XGL_RGB32F, XGL_FLOAT);
00145
00146
00147 DEFINE_GPUNUMERICTRAITS(double, XGL_LUMINANCE_ALPHA32F, XGL_RGBA32F, XGL_LUMINANCE32F, XGL_RGB32F, XGL_FLOAT);
00148
00149
00176 template <class SrcImageIterator, class SrcAccessor,
00177 class DestImageIterator, class DestAccessor,
00178 class TRANSFORM,
00179 class PixelTransform,
00180 class AlphaImageIterator, class AlphaAccessor,
00181 class Interpolator>
00182 void transformImageGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00183 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
00184 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
00185 TRANSFORM & transform,
00186 PixelTransform & pixelTransform,
00187 vigra::Diff2D destUL,
00188 Interpolator interp,
00189 bool warparound,
00190 AppBase::MultiProgressDisplay & prog)
00191 {
00192 typedef typename SrcAccessor::value_type SrcValueType;
00193 typedef typename DestAccessor::value_type DestValueType;
00194 typedef typename AlphaAccessor::value_type AlphaValueType;
00195
00196 prog.pushTask(AppBase::ProgressTask("Remapping", "", 0));
00197
00198 vigra::Diff2D srcSize = src.second - src.first;
00199 vigra::Diff2D destSize = dest.second - dest.first;
00200
00201 vigra_ext::ImageInterpolator<SrcImageIterator, SrcAccessor, Interpolator>
00202 interpol (src, interp, warparound);
00203
00204
00205
00206 std::ostringstream coordXformOss;
00207 coordXformOss << std::setprecision(20) << std::showpoint;
00208 transform.emitGLSL(coordXformOss);
00209
00210 std::ostringstream interpolatorOss;
00211 interpolatorOss << std::setprecision(20) << std::showpoint;
00212 interpol.emitGLSL(interpolatorOss);
00213
00214 std::ostringstream photometricOss;
00215 std::vector<double> invLut;
00216 std::vector<double> destLut;
00217 photometricOss << std::setprecision(20) << std::showpoint;
00218 pixelTransform.emitGLSL(photometricOss, invLut, destLut);
00219
00220
00221
00222
00223
00224 transformImageGPUIntern(coordXformOss.str(),
00225 interpolatorOss.str(),
00226 interp.size,
00227 photometricOss.str(),
00228 invLut,
00229 destLut,
00230 srcSize,
00231 src.first[0],
00232 GpuNumericTraits<SrcValueType>::ImageGLInternalFormat,
00233 GpuNumericTraits<SrcValueType>::ImageGLTransferFormat,
00234 GpuNumericTraits<SrcValueType>::ImageGLFormat,
00235 GpuNumericTraits<SrcValueType>::ImagePixelComponentGLType,
00236 NULL,
00237 XGL_BYTE,
00238 destUL,
00239 destSize,
00240 dest.first[0],
00241 GpuNumericTraits<DestValueType>::ImageGLInternalFormat,
00242 GpuNumericTraits<DestValueType>::ImageGLTransferFormat,
00243 GpuNumericTraits<DestValueType>::ImageGLFormat,
00244 GpuNumericTraits<DestValueType>::ImagePixelComponentGLType,
00245 alpha.first[0],
00246 GpuNumericTraits<AlphaValueType>::ImagePixelComponentGLType,
00247 warparound);
00248
00249 prog.popTask();
00250 }
00251
00252
00254 template <class SrcImageIterator, class SrcAccessor,
00255 class SrcAlphaIterator, class SrcAlphaAccessor,
00256 class DestImageIterator, class DestAccessor,
00257 class TRANSFORM,
00258 class PixelTransform,
00259 class AlphaImageIterator, class AlphaAccessor,
00260 class Interpolator>
00261 void transformImageAlphaGPUIntern(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00262 std::pair<SrcAlphaIterator, SrcAlphaAccessor> srcAlpha,
00263 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
00264 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
00265 TRANSFORM & transform,
00266 PixelTransform & pixelTransform,
00267 vigra::Diff2D destUL,
00268 Interpolator interp,
00269 bool warparound,
00270 AppBase::MultiProgressDisplay & prog)
00271 {
00272 typedef typename SrcAccessor::value_type SrcValueType;
00273 typedef typename SrcAlphaAccessor::value_type SrcAlphaType;
00274 typedef typename DestAccessor::value_type DestValueType;
00275 typedef typename AlphaAccessor::value_type DestAlphaType;
00276
00277 prog.pushTask(AppBase::ProgressTask("Remapping", "", 0));
00278
00279 vigra::Diff2D srcSize = src.second - src.first;
00280 vigra::Diff2D destSize = dest.second - dest.first;
00281
00282
00283 vigra_ext::ImageInterpolator<SrcImageIterator, SrcAccessor, Interpolator>
00284 interpol (src, interp, warparound);
00285
00286
00287
00288 std::ostringstream coordXformOss;
00289 coordXformOss << std::setprecision(20) << std::showpoint;
00290 if(!transform.emitGLSL(coordXformOss))
00291 {
00292 std::cerr << "nona: Found unsupported transformation in stack." << std::endl
00293 << " This geometric transformation is not supported by GPU." << std::endl
00294 << " Remove -g switch and try with CPU transformation." << std::endl;
00295 exit(1);
00296 };
00297
00298 std::ostringstream interpolatorOss;
00299 interpolatorOss << std::setprecision(20) << std::showpoint;
00300 interpol.emitGLSL(interpolatorOss);
00301
00302 std::ostringstream photometricOss;
00303 std::vector<double> invLut;
00304 std::vector<double> destLut;
00305 photometricOss << std::setprecision(20) << std::showpoint;
00306 pixelTransform.emitGLSL(photometricOss, invLut, destLut);
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 #if 1
00351 transformImageGPUIntern(coordXformOss.str(),
00352 interpolatorOss.str(),
00353 interp.size,
00354 photometricOss.str(),
00355 invLut,
00356 destLut,
00357 srcSize,
00358 src.first[0],
00359 GpuNumericTraits<SrcValueType>::ImageGLInternalFormat,
00360 GpuNumericTraits<SrcValueType>::ImageGLTransferFormat,
00361 GpuNumericTraits<SrcValueType>::ImageGLFormat,
00362 GpuNumericTraits<SrcValueType>::ImagePixelComponentGLType,
00363 srcAlpha.first[0],
00364 GpuNumericTraits<SrcAlphaType>::ImagePixelComponentGLType,
00365 destUL,
00366 destSize,
00367 dest.first[0],
00368 GpuNumericTraits<DestValueType>::ImageGLInternalFormat,
00369 GpuNumericTraits<DestValueType>::ImageGLTransferFormat,
00370 GpuNumericTraits<DestValueType>::ImageGLFormat,
00371 GpuNumericTraits<DestValueType>::ImagePixelComponentGLType,
00372 alpha.first[0],
00373 GpuNumericTraits<DestAlphaType>::ImagePixelComponentGLType,
00374 warparound);
00375 #endif
00376
00377 #if 0
00378
00379 vigra::FVector4Image phonyDest(destSize);
00380 vigra::FImage phonyDestAlpha(destSize);
00381 vigra::FRGBImage phonySrc(srcSize);
00382 vigra::FImage phonySrcAlpha(srcSize);
00383
00384 transformImageGPUIntern(oss.str(), srcSize, phonySrc[0], XGL_FLOAT, XGL_RGB,
00385 phonySrcAlpha[0], XGL_FLOAT, XGL_RED,
00386 destUL, destSize, phonyDest[0], XGL_FLOAT, XGL_RGBA,
00387 phonyDestAlpha[0], XGL_FLOAT, XGL_RED,
00388 warparound);
00389
00390
00391 int xstart = destUL.x;
00392 int xend = destUL.x + destSize.x;
00393 int ystart = destUL.y;
00394 int yend = destUL.y + destSize.y;
00395
00396 double samples = 0.0;
00397 double sumError = 0.0;
00398 double sumErrorSq = 0.0;
00399
00400
00401
00402 vigra::FVector4Image::traverser yd = phonyDest.upperLeft();
00403 vigra::FImage::traverser ydm = phonyDestAlpha.upperLeft();
00404 DestImageIterator ydest(dest.first);
00405 AlphaImageIterator ydesta(alpha.first);
00406
00407 int numMessages = 0;
00408
00409 for(int y=ystart; y < yend; ++y, ++yd.y, ++ydm.y, ++ydest.y, ++ydesta.y)
00410 {
00411
00412
00413 vigra::FVector4Image::traverser xd(yd);
00414 vigra::FImage::traverser xdm(ydm);
00415 DestImageIterator xdest(ydest);
00416 AlphaImageIterator xdesta(ydesta);
00417
00418 for(int x=xstart; x < xend; ++x, ++xd.x, ++xdm.x, ++xdest.x, ++xdesta.x)
00419 {
00420 double sx,sy;
00421 bool result = transform.transformImgCoordPartial(sx,sy,x,y);
00422 float errorX = (*xd)[2] - static_cast<float>(sx);
00423 float errorY = (*xd)[1] - static_cast<float>(sy);
00424 double error = sqrt(errorX * errorX + errorY * errorY);
00425
00426 if (error != 0.0 && numMessages < 150) {
00427 std::cout << std::setprecision(20) << "pos=[" << x << ", " << y << "] shouldBe=[" << sx << ", " << sy << " is=[" << (*xd)[2] << ", " << (*xd)[1] << "] error=" << error << std::endl;
00428 ++numMessages;
00429 }
00430
00431 sumError += error;
00432 sumErrorSq += (error * error);
00433
00434 samples += 1.0;
00435
00436 dest.third.set(NumericTraits<DestValueType>::fromRealPromote(std::min(255.0, std::max(0.0, 255.0 * 10.0 * error))), xdest);
00437 alpha.second.set(255, xdesta);
00438 }
00439 }
00440
00441 double avgError = sumError/samples;
00442
00443 std::cout << "numSamples=" << samples << std::endl
00444 << "average error=" << avgError << std::endl
00445 << "stddev=" << (sumErrorSq/samples - avgError*avgError) << std::endl;
00446 #endif
00447
00448 prog.popTask();
00449 };
00450
00451
00478 template <class SrcImageIterator, class SrcAccessor,
00479 class DestImageIterator, class DestAccessor,
00480 class AlphaImageIterator, class AlphaAccessor,
00481 class TRANSFORM,
00482 class PixelTransform>
00483 void transformImageGPU(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00484 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
00485 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
00486 vigra::Diff2D destUL,
00487 TRANSFORM & transform,
00488 PixelTransform & pixelTransform,
00489 bool warparound,
00490 Interpolator interpol,
00491 AppBase::MultiProgressDisplay & progress)
00492 {
00493 switch (interpol) {
00494 case INTERP_CUBIC:
00495 DEBUG_DEBUG("using cubic interpolator");
00496 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00497 vigra_ext::interp_cubic(), warparound,
00498 progress);
00499 break;
00500 case INTERP_SPLINE_16:
00501 DEBUG_DEBUG("interpolator: spline16");
00502 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00503 vigra_ext::interp_spline16(), warparound,
00504 progress);
00505 break;
00506 case INTERP_SPLINE_36:
00507 DEBUG_DEBUG("interpolator: spline36");
00508 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00509 vigra_ext::interp_spline36(), warparound,
00510 progress);
00511 break;
00512 case INTERP_SPLINE_64:
00513 DEBUG_DEBUG("interpolator: spline64");
00514 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00515 vigra_ext::interp_spline64(), warparound,
00516 progress);
00517 break;
00518 case INTERP_SINC_256:
00519 DEBUG_DEBUG("interpolator: sinc 256");
00520 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00521 vigra_ext::interp_sinc<8>(), warparound,
00522 progress);
00523 break;
00524 case INTERP_BILINEAR:
00525 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00526 vigra_ext::interp_bilin(), warparound,
00527 progress);
00528 break;
00529 case INTERP_NEAREST_NEIGHBOUR:
00530 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00531 vigra_ext::interp_nearest(), warparound,
00532 progress);
00533 break;
00534 case INTERP_SINC_1024:
00535 transformImageGPUIntern(src, dest, alpha, transform, pixelTransform, destUL,
00536 vigra_ext::interp_sinc<32>(), warparound,
00537 progress);
00538 break;
00539 }
00540 }
00541
00543 template <class SrcImageIterator, class SrcAccessor,
00544 class SrcAlphaIterator, class SrcAlphaAccessor,
00545 class DestImageIterator, class DestAccessor,
00546 class AlphaImageIterator, class AlphaAccessor,
00547 class TRANSFORM, class PixelTransform>
00548 void transformImageAlphaGPU(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00549 std::pair<SrcAlphaIterator, SrcAlphaAccessor> srcAlpha,
00550 vigra::triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
00551 std::pair<AlphaImageIterator, AlphaAccessor> alpha,
00552 vigra::Diff2D destUL,
00553 TRANSFORM & transform,
00554 PixelTransform & pixelTransform,
00555 bool warparound,
00556 Interpolator interpol,
00557 AppBase::MultiProgressDisplay & progress)
00558 {
00559 switch (interpol) {
00560 case INTERP_CUBIC:
00561 DEBUG_DEBUG("using cubic interpolator");
00562 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00563 vigra_ext::interp_cubic(), warparound,
00564 progress);
00565 break;
00566 case INTERP_SPLINE_16:
00567 DEBUG_DEBUG("interpolator: spline16");
00568 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00569 vigra_ext::interp_spline16(), warparound,
00570 progress);
00571 break;
00572 case INTERP_SPLINE_36:
00573 DEBUG_DEBUG("interpolator: spline36");
00574 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00575 vigra_ext::interp_spline36(), warparound,
00576 progress);
00577 break;
00578 case INTERP_SPLINE_64:
00579 DEBUG_DEBUG("interpolator: spline64");
00580 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00581 vigra_ext::interp_spline64(), warparound,
00582 progress);
00583 break;
00584 case INTERP_SINC_256:
00585 DEBUG_DEBUG("interpolator: sinc 256");
00586 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00587 vigra_ext::interp_sinc<8>(), warparound,
00588 progress);
00589 break;
00590 case INTERP_BILINEAR:
00591 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00592 vigra_ext::interp_bilin(), warparound,
00593 progress);
00594 break;
00595 case INTERP_NEAREST_NEIGHBOUR:
00596 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00597 vigra_ext::interp_nearest(), warparound,
00598 progress);
00599 break;
00600 case INTERP_SINC_1024:
00601 transformImageAlphaGPUIntern(src,srcAlpha, dest, alpha, transform, pixelTransform, destUL,
00602 vigra_ext::interp_sinc<32>(), warparound,
00603 progress);
00604 break;
00605 }
00606 }
00607
00608 };
00609
00610 #endif // _VIGRA_EXT_IMAGETRANSFORMSGPU_H