#include <OSGImageScaler.h>
Static Public Member Functions | |
| static bool | scale (ImagePtr &srcImg, ImagePtr &dstImg, osg::Int32 width, osg::Int32 height, osg::Int32 depth, const ImageGenericFilter &filter) |
Private Member Functions | |
| ImageScaler (void) | |
| ~ImageScaler (void) | |
Static Private Member Functions | |
| static void | calcContributions (UInt32 axis, Int32 uResSize, Int32 uSrcSize, const ImageGenericFilter &filter, std::vector< Contribution > contrib[3]) |
Classes | |
| struct | Contribution |
Definition at line 113 of file OSGImageScaler.h.
| ImageScaler::ImageScaler | ( | void | ) | [private] |
| ImageScaler::~ImageScaler | ( | void | ) | [private] |
| bool ImageScaler::scale | ( | ImagePtr & | srcImg, | |
| ImagePtr & | dstImg, | |||
| osg::Int32 | width, | |||
| osg::Int32 | height, | |||
| osg::Int32 | depth, | |||
| const ImageGenericFilter & | filter | |||
| ) | [static] |
rescale image
Definition at line 370 of file OSGImageScaler.cpp.
References osg::beginEditCP(), calcContributions(), osg::endEditCP(), ValueHandler::getValue(), osg::Image::OSG_FLOAT16_IMAGEDATA, osg::Image::OSG_FLOAT32_IMAGEDATA, osg::Image::OSG_UINT16_IMAGEDATA, osg::Image::OSG_UINT32_IMAGEDATA, osg::Image::OSG_UINT8_IMAGEDATA, ValueHandler::setValue(), and SWARNING.
00376 { 00377 ValueHandler *valueHandler = NULL; 00378 Int32 channels = srcImg->getComponents(); 00379 std::vector<Contribution> contrib[3]; 00380 00381 beginEditCP(dstImg); 00382 00383 switch(srcImg->getDataType()) 00384 { 00385 case Image::OSG_UINT8_IMAGEDATA: 00386 valueHandler = new ValueHandlerTempl<UInt8>(); 00387 break; 00388 case Image::OSG_UINT16_IMAGEDATA: 00389 valueHandler = new ValueHandlerTempl<UInt16>(); 00390 break; 00391 case Image::OSG_UINT32_IMAGEDATA: 00392 valueHandler = new ValueHandlerTempl<UInt32>(); 00393 break; 00394 case Image::OSG_FLOAT16_IMAGEDATA: 00395 valueHandler = new ValueHandlerTempl<Real16>(); 00396 break; 00397 case Image::OSG_FLOAT32_IMAGEDATA: 00398 valueHandler = new ValueHandlerTempl<Real32>(); 00399 break; 00400 default: 00401 SWARNING << "PixelType not scalable" << std::endl; 00402 return false; 00403 }; 00404 00405 // create kernel 00406 calcContributions(0,width, srcImg->getWidth() ,filter,contrib); 00407 calcContributions(1,height,srcImg->getHeight(),filter,contrib); 00408 calcContributions(2,depth, srcImg->getDepth() ,filter,contrib); 00409 00410 if(!dstImg->set((Image::PixelFormat)srcImg->getPixelFormat(), 00411 width, 00412 height, 00413 depth, 00414 // create mipmaps from rescaled image 00415 1, 00416 srcImg->getFrameCount(), 00417 srcImg->getFrameDelay(), 00418 NULL, 00419 srcImg->getDataType(), 00420 true, 00421 srcImg->getSideCount())) 00422 { 00423 SWARNING << "Unable to set image format" << std::endl; 00424 return false; 00425 } 00426 00427 UInt32 srcImgWidth = srcImg->getWidth(); 00428 UInt32 srcImgHeight = srcImg->getHeight(); 00429 Real64 *weightX; 00430 Real64 *weightY; 00431 Real64 *weightZ; 00432 UInt32 frames = srcImg->getFrameCount(); 00433 UInt32 sides = srcImg->getSideCount(); 00434 00435 // it makes no sense to rescale the mipmap levels, so 00436 // we simply scale the main image and then rebuild the 00437 // mipmaps 00438 Real64 value; 00439 UInt32 x,y,z,c,f,s; 00440 UInt32 x1,x2,y1,y2,z1,z2; 00441 for(s = 0 ; s < sides ; ++s) 00442 { 00443 for(f = 0 ; f < frames ; ++f) 00444 { 00445 UInt8 *dstImgData = dstImg->getData(0,f,s); 00446 UInt8 *srcImgData = srcImg->getData(0,f,s); 00447 for(z = 0 ; z < depth ; ++z) 00448 { 00449 z1 = contrib[2][z].left; 00450 z2 = contrib[2][z].right; 00451 weightZ = &contrib[2][z].weights[0]; 00452 for(y = 0 ; y < height ; ++y) 00453 { 00454 y1 = contrib[1][y].left; 00455 y2 = contrib[1][y].right; 00456 weightY = &contrib[1][y].weights[0]; 00457 for(x = 0 ; x < width ; ++x) 00458 { 00459 x1 = contrib[0][x].left; 00460 x2 = contrib[0][x].right; 00461 00462 weightX = &contrib[0][x].weights[0]; 00463 for(c = 0 ; c < channels ; ++c) 00464 { 00465 value = valueHandler->getValue(srcImgData, 00466 channels, 00467 srcImgWidth, 00468 srcImgHeight, 00469 c, 00470 x1,y1,z1, 00471 x2,y2,z2, 00472 weightX,weightY,weightZ); 00473 00474 valueHandler->setValue(value, 00475 dstImgData, 00476 channels,width,height, 00477 c,x,y,z); 00478 } 00479 } 00480 } 00481 } 00482 } 00483 } 00484 00485 if(valueHandler != NULL) 00486 delete valueHandler; 00487 00488 // rebuild mipmaps 00489 if(srcImg->getMipMapCount() > 1) 00490 dstImg->createMipmap(-1); 00491 00492 endEditCP(dstImg); 00493 00494 return true; 00495 }
| void ImageScaler::calcContributions | ( | UInt32 | axis, | |
| Int32 | uResSize, | |||
| Int32 | uSrcSize, | |||
| const ImageGenericFilter & | filter, | |||
| std::vector< Contribution > | contrib[3] | |||
| ) | [static, private] |
calculation contribution values from filter object
Definition at line 271 of file OSGImageScaler.cpp.
References osg::ImageGenericFilter::filter(), osg::ImageGenericFilter::getWidth(), osg::osgMax(), and osg::osgMin().
Referenced by scale().
00276 { 00277 Real64 dWidth; 00278 Real64 dFScale = 1.0; 00279 Real64 dFilterWidth = filter.getWidth(); 00280 00281 Real64 dScale = (Real64)uResSize / (Real64)uSrcSize; 00282 00283 // resize arrays 00284 contrib[axis].resize(uResSize); 00285 00286 if (dScale < 1.0) 00287 { // Minification 00288 dWidth = dFilterWidth / dScale; 00289 dFScale = dScale; 00290 } 00291 else 00292 { // Magnification 00293 dWidth= dFilterWidth; 00294 } 00295 00296 // Window size is the number of sampled pixels 00297 Int32 iWindowSize = 2 * (Int32)ceil(dWidth) + 1; 00298 00299 for (Int32 u = 0; u < uResSize; u++) 00300 { 00301 // Scan through line of contributions 00302 Real64 dCenter = (Real64)u / dScale; // Reverse mapping 00303 // Find the significant edge points that affect the pixel 00304 Int32 iLeft = osgMax (0, (Int32)floor (dCenter - dWidth)); 00305 //res->ContribRow[u].Left = iLeft; 00306 Int32 iRight = osgMin ((Int32)ceil (dCenter + dWidth), Int32(uSrcSize) - 1); 00307 //res->ContribRow[u].Right = iRight; 00308 00309 // Cut edge points to fit in filter window in case of spill-off 00310 if (iRight - iLeft + 1 > iWindowSize) 00311 { 00312 if (iLeft < (Int32(uSrcSize) - 1 / 2)) 00313 { 00314 iLeft++; 00315 } 00316 else 00317 { 00318 iRight--; 00319 } 00320 } 00321 // amz store the modified values! 00322 contrib[axis][u].left = iLeft; 00323 contrib[axis][u].right = iRight; 00324 00325 Real64 dTotalWeight = 0.0; // Zero sum of weights 00326 contrib[axis][u].weights.resize(iRight - iLeft + 1); 00327 for (Int32 iSrc = iLeft; iSrc <= iRight; iSrc++) 00328 { 00329 // calculate weight 00330 Real64 weight = dFScale * 00331 filter.filter(dFScale * (dCenter - (Real64)iSrc)); 00332 contrib[axis][u].weights[iSrc-iLeft] = weight; 00333 // sum weights 00334 dTotalWeight += weight; 00335 } 00336 if (dTotalWeight > 0.0) 00337 { 00338 // Normalize weight of neighbouring points 00339 for (Int32 iSrc = iLeft; iSrc <= iRight; iSrc++) 00340 { 00341 // Normalize point 00342 contrib[axis][u].weights[iSrc-iLeft] /= dTotalWeight; 00343 } 00344 // optimize kernel size 00345 while(contrib[axis][u].weights.front() == 0) 00346 { 00347 contrib[axis][u].left++; 00348 contrib[axis][u].weights.erase(contrib[axis][u].weights.begin()); 00349 } 00350 while(contrib[axis][u].weights.back() == 0) 00351 { 00352 contrib[axis][u].right--; 00353 contrib[axis][u].weights.erase(contrib[axis][u].weights.end() - 1); 00354 } 00355 #if 0 00356 printf("%d %d %d,%d\n",axis,u,contrib[axis][u].left,contrib[axis][u].right); 00357 for (Int32 iSrc = 0; iSrc < contrib[axis][u].weights.size(); iSrc++) 00358 { 00359 printf("%lf ",contrib[axis][u].weights[iSrc]); 00360 } 00361 printf("\n"); 00362 #endif 00363 } 00364 } 00365 }
1.5.5