//! copies this surface into another, scaling it to fit it. void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) { const core::dimension2d<u32> destSize = target->getDimension(); const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; target->lock(); s32 fx = core::ceil32( sourceXStep ); s32 fy = core::ceil32( sourceYStep ); f32 sx; f32 sy; sy = 0.f; for ( u32 y = 0; y != destSize.Height; ++y ) { sx = 0.f; for ( u32 x = 0; x != destSize.Width; ++x ) { target->setPixel( x, y, getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ), blend ); sx += sourceXStep; } sy += sourceYStep; } target->unlock(); }
//! copies this surface into another, scaling it to fit it. void CImage::copyToScalingBoxFilter(IImage* target, SINT32 bias, bool blend) { const dimension2d<UINT32> destSize = target->getDimension(); const Real sourceXStep = (Real)Size.Width / (Real)destSize.Width; const Real sourceYStep = (Real)Size.Height / (Real)destSize.Height; target->lock(); SINT32 fx = ceil32(sourceXStep); SINT32 fy = ceil32(sourceYStep); Real sx; Real sy; sy = 0.f; for (UINT32 y = 0; y != destSize.Height; ++y) { sx = 0.f; for (UINT32 x = 0; x != destSize.Width; ++x) { target->setPixel(x, y, getPixelBox(floor32(sx), floor32(sy), fx, fy, bias), blend); sx += sourceXStep; } sy += sourceYStep; } target->unlock(); }
//----------------------------------------------------------------------------- void Image::resize(ushort width, ushort height, Filter filter) { // resizing dynamic images is not supported assert(mAutoDelete); assert(mDepth == 1); // reassign buffer to temp image, make sure auto-delete is true Image temp; temp.loadDynamicImage(mBuffer, mWidth, mHeight, 1, mFormat, true); // do not delete[] mBuffer! temp will destroy it // set new dimensions, allocate new buffer mWidth = width; mHeight = height; mBufSize = PixelUtil::getMemorySize(mWidth, mHeight, 1, mFormat); mBuffer = OGRE_ALLOC_T(uchar, mBufSize, MEMCATEGORY_GENERAL); mNumMipmaps = 0; // Loses precomputed mipmaps // scale the image from temp into our resized buffer Image::scale(temp.getPixelBox(), getPixelBox(), filter); }
//----------------------------------------------------------------------------- void Image::resize(ushort width, ushort height, Filter filter) { // resizing dynamic images is not supported assert(m_bAutoDelete); assert(m_uDepth == 1); // reassign buffer to temp image, make sure auto-delete is true Image temp; temp.loadDynamicImage(m_pBuffer, m_uWidth, m_uHeight, 1, m_eFormat, true); // do not delete[] m_pBuffer! temp will destroy it // set new dimensions, allocate new buffer m_uWidth = width; m_uHeight = height; m_uSize = PixelUtil::getMemorySize(m_uWidth, m_uHeight, 1, m_eFormat); m_pBuffer = new uchar[m_uSize]; m_uNumMipmaps = 0; // Loses precomputed mipmaps // scale the image from temp into our resized buffer Image::scale(temp.getPixelBox(), getPixelBox(), filter); }
//--------------------------------------------------------------------- Image & Image::combineTwoImagesAsRGBA(const Image& rgb, const Image& alpha, PixelFormat fmt) { // the images should be the same size, have the same number of mipmaps if (rgb.getWidth() != alpha.getWidth() || rgb.getHeight() != alpha.getHeight() || rgb.getDepth() != alpha.getDepth()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Images must be the same dimensions", "Image::combineTwoImagesAsRGBA"); } if (rgb.getNumMipmaps() != alpha.getNumMipmaps() || rgb.getNumFaces() != alpha.getNumFaces()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Images must have the same number of surfaces (faces & mipmaps)", "Image::combineTwoImagesAsRGBA"); } // Format check if (PixelUtil::getComponentCount(fmt) != 4) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Target format must have 4 components", "Image::combineTwoImagesAsRGBA"); } if (PixelUtil::isCompressed(fmt) || PixelUtil::isCompressed(rgb.getFormat()) || PixelUtil::isCompressed(alpha.getFormat())) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Compressed formats are not supported in this method", "Image::combineTwoImagesAsRGBA"); } freeMemory(); mWidth = rgb.getWidth(); mHeight = rgb.getHeight(); mDepth = rgb.getDepth(); mFormat = fmt; mNumMipmaps = rgb.getNumMipmaps(); size_t numFaces = rgb.getNumFaces(); // Set flags mFlags = 0; if (mDepth != 1) mFlags |= IF_3D_TEXTURE; if(numFaces == 6) mFlags |= IF_CUBEMAP; mBufSize = calculateSize(mNumMipmaps, numFaces, mWidth, mHeight, mDepth, mFormat); mPixelSize = static_cast<uchar>(PixelUtil::getNumElemBytes( mFormat )); mBuffer = static_cast<uchar*>(OGRE_MALLOC(mBufSize, MEMCATEGORY_GENERAL)); // make sure we delete mAutoDelete = true; for (size_t face = 0; face < numFaces; ++face) { for (uint8 mip = 0; mip <= mNumMipmaps; ++mip) { // convert the RGB first PixelBox srcRGB = rgb.getPixelBox(face, mip); PixelBox dst = getPixelBox(face, mip); PixelUtil::bulkPixelConversion(srcRGB, dst); // now selectively add the alpha PixelBox srcAlpha = alpha.getPixelBox(face, mip); uchar* psrcAlpha = static_cast<uchar*>(srcAlpha.data); uchar* pdst = static_cast<uchar*>(dst.data); for (size_t d = 0; d < mDepth; ++d) { for (size_t y = 0; y < mHeight; ++y) { for (size_t x = 0; x < mWidth; ++x) { ColourValue colRGBA, colA; // read RGB back from dest to save having another pointer PixelUtil::unpackColour(&colRGBA, mFormat, pdst); PixelUtil::unpackColour(&colA, alpha.getFormat(), psrcAlpha); // combine RGB from alpha source texture colRGBA.a = (colA.r + colA.g + colA.b) / 3.0f; PixelUtil::packColour(colRGBA, mFormat, pdst); psrcAlpha += PixelUtil::getNumElemBytes(alpha.getFormat()); pdst += PixelUtil::getNumElemBytes(mFormat); } } } } } return *this; }