X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fimage-loader%2Fimage-atlas-impl.cpp;h=8c4dba6d1408863d188db0e8aa96e3979cf36f1c;hp=d1674990a1b13dae58ccc2633a3934e55210cc53;hb=f2039d47f9bed8104575da80a2ecf0bb6e37ff8d;hpb=f3e45e41c5f16ccc2538b283897ed6efb07e4ea9 diff --git a/dali-toolkit/internal/image-loader/image-atlas-impl.cpp b/dali-toolkit/internal/image-loader/image-atlas-impl.cpp index d167499..8c4dba6 100644 --- a/dali-toolkit/internal/image-loader/image-atlas-impl.cpp +++ b/dali-toolkit/internal/image-loader/image-atlas-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,97 +19,93 @@ #include "image-atlas-impl.h" // EXTERNAL INCLUDES -#include -#include #include #include +#include +#include namespace Dali { - namespace Toolkit { - namespace Internal { typedef unsigned char PixelBuffer; -Texture ImageAtlas::PackToAtlas( const std::vector& pixelData, Dali::Vector& textureRects ) +Texture ImageAtlas::PackToAtlas(const std::vector& pixelData, Dali::Vector& textureRects) { // Record each block size Dali::Vector blockSizes; - SizeType count = pixelData.size(); - for( SizeType index = 0; index < count; index++ ) + SizeType count = pixelData.size(); + for(SizeType index = 0; index < count; index++) { - blockSizes.PushBack( ImageDimensions( pixelData[index].GetWidth(), pixelData[index].GetHeight() ) ); + blockSizes.PushBack(ImageDimensions(pixelData[index].GetWidth(), pixelData[index].GetHeight())); } // Ask atlasPacker for packing position of each block Dali::Vector packPositions; - ImageDimensions atlasSize = AtlasPacker::GroupPack( blockSizes, packPositions ); + ImageDimensions atlasSize = AtlasPacker::GroupPack(blockSizes, packPositions); // Prepare for outout texture rect array textureRects.Clear(); - textureRects.Resize( count ); + textureRects.Resize(count); // create the texture for uploading the multiple pixel data - Texture atlasTexture = Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, atlasSize.GetWidth(), atlasSize.GetHeight() ); + Texture atlasTexture = Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, atlasSize.GetWidth(), atlasSize.GetHeight()); - float atlasWidth = static_cast( atlasTexture.GetWidth() ); - float atlasHeight = static_cast( atlasTexture.GetHeight() ); - int packPositionX, packPositionY; + float atlasWidth = static_cast(atlasTexture.GetWidth()); + float atlasHeight = static_cast(atlasTexture.GetHeight()); + int packPositionX, packPositionY; // Upload the pixel data one by one to its packing position, and record the texture rects - for( SizeType index = 0; index < count; index++ ) + for(SizeType index = 0; index < count; index++) { packPositionX = packPositions[index].GetX(); packPositionY = packPositions[index].GetY(); - atlasTexture.Upload( pixelData[index], 0u, 0u, - packPositionX, packPositionY, - pixelData[index].GetWidth(), pixelData[index].GetHeight() ); + atlasTexture.Upload(pixelData[index], 0u, 0u, packPositionX, packPositionY, pixelData[index].GetWidth(), pixelData[index].GetHeight()); // Apply the half pixel correction to avoid the color bleeding between neighbour blocks - textureRects[index].x = ( static_cast( packPositionX ) +0.5f ) / atlasWidth; // left - textureRects[index].y = ( static_cast( packPositionY ) +0.5f ) / atlasHeight; // right - textureRects[index].z = ( static_cast( packPositionX + pixelData[index].GetWidth() )-0.5f ) / atlasWidth; // right - textureRects[index].w = ( static_cast( packPositionY + pixelData[index].GetHeight() )-0.5f ) / atlasHeight;// bottom + textureRects[index].x = (static_cast(packPositionX) + 0.5f) / atlasWidth; // left + textureRects[index].y = (static_cast(packPositionY) + 0.5f) / atlasHeight; // right + textureRects[index].z = (static_cast(packPositionX + pixelData[index].GetWidth()) - 0.5f) / atlasWidth; // right + textureRects[index].w = (static_cast(packPositionY + pixelData[index].GetHeight()) - 0.5f) / atlasHeight; // bottom } return atlasTexture; } -ImageAtlas::ImageAtlas( SizeType width, SizeType height, Pixel::Format pixelFormat ) -: mAtlas( Texture::New( Dali::TextureType::TEXTURE_2D, pixelFormat, width, height ) ), - mPacker( width, height ), - mAsyncLoader( Toolkit::AsyncImageLoader::New() ), +ImageAtlas::ImageAtlas(SizeType width, SizeType height, Pixel::Format pixelFormat) +: mAtlas(Texture::New(Dali::TextureType::TEXTURE_2D, pixelFormat, width, height)), + mPacker(width, height), + mAsyncLoader(Toolkit::AsyncImageLoader::New()), mBrokenImageUrl(""), mBrokenImageSize(), - mWidth( static_cast(width) ), - mHeight( static_cast( height ) ), - mPixelFormat( pixelFormat ) + mWidth(static_cast(width)), + mHeight(static_cast(height)), + mPixelFormat(pixelFormat) { - mAsyncLoader.ImageLoadedSignal().Connect( this, &ImageAtlas::UploadToAtlas ); + mAsyncLoader.ImageLoadedSignal().Connect(this, &ImageAtlas::UploadToAtlas); } ImageAtlas::~ImageAtlas() { const std::size_t count = mLoadingTaskInfoContainer.Count(); - for( std::size_t i=0; i < count; ++i ) + for(std::size_t i = 0; i < count; ++i) { // Call unregister to every observer in the list. // Note that, the Atlas can be registered to same observer multiple times, and the Unregister method only remove one item each time. // In this way, the atlas is actually detached from a observer either every upload call invoked by this observer is completed or atlas is destroyed. - if( mLoadingTaskInfoContainer[i]->observer ) + if(mLoadingTaskInfoContainer[i]->observer) { - mLoadingTaskInfoContainer[i]->observer->Unregister( *this ); + mLoadingTaskInfoContainer[i]->observer->Unregister(*this); } } mLoadingTaskInfoContainer.Clear(); } -IntrusivePtr ImageAtlas::New( SizeType width, SizeType height, Pixel::Format pixelFormat ) +IntrusivePtr ImageAtlas::New(SizeType width, SizeType height, Pixel::Format pixelFormat) { - IntrusivePtr internal = new ImageAtlas( width, height, pixelFormat ); + IntrusivePtr internal = new ImageAtlas(width, height, pixelFormat); return internal; } @@ -121,35 +117,35 @@ Texture ImageAtlas::GetAtlas() float ImageAtlas::GetOccupancyRate() const { - return 1.f - static_cast( mPacker.GetAvailableArea() ) / ( mWidth*mHeight ); + return 1.f - static_cast(mPacker.GetAvailableArea()) / (mWidth * mHeight); } -void ImageAtlas::SetBrokenImage( const std::string& brokenImageUrl ) +void ImageAtlas::SetBrokenImage(const std::string& brokenImageUrl) { - mBrokenImageSize = Dali::GetClosestImageSize( brokenImageUrl ); - if(mBrokenImageSize.GetWidth() > 0 && mBrokenImageSize.GetHeight() > 0 ) // check the url is valid + mBrokenImageSize = Dali::GetClosestImageSize(brokenImageUrl); + if(mBrokenImageSize.GetWidth() > 0 && mBrokenImageSize.GetHeight() > 0) // check the url is valid { mBrokenImageUrl = brokenImageUrl; } } -bool ImageAtlas::Upload( Vector4& textureRect, - const std::string& url, - ImageDimensions size, - FittingMode::Type fittingMode, - bool orientationCorrection, - AtlasUploadObserver* atlasUploadObserver ) +bool ImageAtlas::Upload(Vector4& textureRect, + const std::string& url, + ImageDimensions size, + FittingMode::Type fittingMode, + bool orientationCorrection, + AtlasUploadObserver* atlasUploadObserver) { ImageDimensions dimensions = size; ImageDimensions zero; - if( size == zero ) // image size not provided + if(size == zero) // image size not provided { - dimensions = Dali::GetClosestImageSize( url ); - if( dimensions == zero ) // Fail to read the image & broken image file exists + dimensions = Dali::GetClosestImageSize(url); + if(dimensions == zero) // Fail to read the image & broken image file exists { - if( !mBrokenImageUrl.empty() ) + if(!mBrokenImageUrl.empty()) { - return Upload( textureRect, mBrokenImageUrl, mBrokenImageSize, FittingMode::DEFAULT, true, atlasUploadObserver ); + return Upload(textureRect, mBrokenImageUrl, mBrokenImageSize, FittingMode::DEFAULT, true, atlasUploadObserver); } else { @@ -161,21 +157,21 @@ bool ImageAtlas::Upload( Vector4& textureRect, unsigned int packPositionX = 0; unsigned int packPositionY = 0; - if( mPacker.Pack( dimensions.GetWidth(), dimensions.GetHeight(), packPositionX, packPositionY ) ) + if(mPacker.Pack(dimensions.GetWidth(), dimensions.GetHeight(), packPositionX, packPositionY)) { - unsigned short loadId = mAsyncLoader.Load( url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection); - mLoadingTaskInfoContainer.PushBack( new LoadingTaskInfo( loadId, packPositionX, packPositionY, dimensions.GetWidth(), dimensions.GetHeight(), atlasUploadObserver ) ); + unsigned short loadId = mAsyncLoader.Load(url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection); + mLoadingTaskInfoContainer.PushBack(new LoadingTaskInfo(loadId, packPositionX, packPositionY, dimensions.GetWidth(), dimensions.GetHeight(), atlasUploadObserver)); // apply the half pixel correction - textureRect.x = ( static_cast( packPositionX ) +0.5f ) / mWidth; // left - textureRect.y = ( static_cast( packPositionY ) +0.5f ) / mHeight; // right - textureRect.z = ( static_cast( packPositionX + dimensions.GetX() )-0.5f ) / mWidth; // right - textureRect.w = ( static_cast( packPositionY + dimensions.GetY() )-0.5f ) / mHeight;// bottom + textureRect.x = (static_cast(packPositionX) + 0.5f) / mWidth; // left + textureRect.y = (static_cast(packPositionY) + 0.5f) / mHeight; // right + textureRect.z = (static_cast(packPositionX + dimensions.GetX()) - 0.5f) / mWidth; // right + textureRect.w = (static_cast(packPositionY + dimensions.GetY()) - 0.5f) / mHeight; // bottom - if( atlasUploadObserver ) + if(atlasUploadObserver) { // register to the observer, // Not that a matching unregister call should be invoked in UploadToAtlas if the observer is still alive by then. - atlasUploadObserver->Register( *this ); + atlasUploadObserver->Register(*this); } return true; @@ -184,19 +180,19 @@ bool ImageAtlas::Upload( Vector4& textureRect, return false; } -bool ImageAtlas::Upload( Vector4& textureRect, PixelData pixelData ) +bool ImageAtlas::Upload(Vector4& textureRect, PixelData pixelData) { unsigned int packPositionX = 0; unsigned int packPositionY = 0; - if( mPacker.Pack( pixelData.GetWidth(), pixelData.GetHeight(), packPositionX, packPositionY ) ) + if(mPacker.Pack(pixelData.GetWidth(), pixelData.GetHeight(), packPositionX, packPositionY)) { - mAtlas.Upload( pixelData, 0u, 0u, packPositionX, packPositionY, pixelData.GetWidth(), pixelData.GetHeight() ); + mAtlas.Upload(pixelData, 0u, 0u, packPositionX, packPositionY, pixelData.GetWidth(), pixelData.GetHeight()); // apply the half pixel correction - textureRect.x = ( static_cast( packPositionX ) +0.5f ) / mWidth; // left - textureRect.y = ( static_cast( packPositionY ) +0.5f ) / mHeight; // right - textureRect.z = ( static_cast( packPositionX + pixelData.GetWidth() )-0.5f ) / mWidth; // right - textureRect.w = ( static_cast( packPositionY + pixelData.GetHeight() )-0.5f ) / mHeight;// bottom + textureRect.x = (static_cast(packPositionX) + 0.5f) / mWidth; // left + textureRect.y = (static_cast(packPositionY) + 0.5f) / mHeight; // right + textureRect.z = (static_cast(packPositionX + pixelData.GetWidth()) - 0.5f) / mWidth; // right + textureRect.w = (static_cast(packPositionY + pixelData.GetHeight()) - 0.5f) / mHeight; // bottom return true; } @@ -204,20 +200,20 @@ bool ImageAtlas::Upload( Vector4& textureRect, PixelData pixelData ) return false; } -void ImageAtlas::Remove( const Vector4& textureRect ) +void ImageAtlas::Remove(const Vector4& textureRect) { - mPacker.DeleteBlock( static_cast(textureRect.x*mWidth), - static_cast(textureRect.y*mHeight), - static_cast((textureRect.z-textureRect.x)*mWidth+1.f), - static_cast((textureRect.w-textureRect.y)*mHeight+1.f) ); + mPacker.DeleteBlock(static_cast(textureRect.x * mWidth), + static_cast(textureRect.y * mHeight), + static_cast((textureRect.z - textureRect.x) * mWidth + 1.f), + static_cast((textureRect.w - textureRect.y) * mHeight + 1.f)); } -void ImageAtlas::ObserverDestroyed( AtlasUploadObserver* observer ) +void ImageAtlas::ObserverDestroyed(AtlasUploadObserver* observer) { const std::size_t count = mLoadingTaskInfoContainer.Count(); - for( std::size_t i=0; i < count; ++i ) + for(std::size_t i = 0; i < count; ++i) { - if( mLoadingTaskInfoContainer[i]->observer == observer ) + if(mLoadingTaskInfoContainer[i]->observer == observer) { // the observer is destructing, so its member function should not be called anymore mLoadingTaskInfoContainer[i]->observer = NULL; @@ -225,76 +221,78 @@ void ImageAtlas::ObserverDestroyed( AtlasUploadObserver* observer ) } } -void ImageAtlas::UploadToAtlas( uint32_t id, PixelData pixelData ) +void ImageAtlas::UploadToAtlas(uint32_t id, PixelData pixelData) { - if( mLoadingTaskInfoContainer[0]->loadTaskId == id) + if(mLoadingTaskInfoContainer[0]->loadTaskId == id) { - Rect packRect( mLoadingTaskInfoContainer[0]->packRect ); - if( !pixelData || ( pixelData.GetWidth() ==0 && pixelData.GetHeight() == 0 )) + Rect packRect(mLoadingTaskInfoContainer[0]->packRect); + if(!pixelData || (pixelData.GetWidth() == 0 && pixelData.GetHeight() == 0)) { if(!mBrokenImageUrl.empty()) // replace with the broken image { - UploadBrokenImage( packRect ); + UploadBrokenImage(packRect); } } else { - if( pixelData.GetWidth() < packRect.width || pixelData.GetHeight() < packRect.height ) + if(pixelData.GetWidth() < packRect.width || pixelData.GetHeight() < packRect.height) { - DALI_LOG_ERROR( "Can not upscale the image from actual loaded size [ %d, %d ] to specified size [ %d, %d ]\n", - pixelData.GetWidth(), pixelData.GetHeight(), - packRect.width, packRect.height ); + DALI_LOG_ERROR("Can not upscale the image from actual loaded size [ %d, %d ] to specified size [ %d, %d ]\n", + pixelData.GetWidth(), + pixelData.GetHeight(), + packRect.width, + packRect.height); } - mAtlas.Upload( pixelData, 0u, 0u, packRect.x, packRect.y, packRect.width, packRect.height ); + mAtlas.Upload(pixelData, 0u, 0u, packRect.x, packRect.y, packRect.width, packRect.height); } - if( mLoadingTaskInfoContainer[0]->observer ) + if(mLoadingTaskInfoContainer[0]->observer) { mLoadingTaskInfoContainer[0]->observer->UploadCompleted(); - mLoadingTaskInfoContainer[0]->observer->Unregister( *this ); + mLoadingTaskInfoContainer[0]->observer->Unregister(*this); } - mLoadingTaskInfoContainer.Erase( mLoadingTaskInfoContainer.Begin() ); + mLoadingTaskInfoContainer.Erase(mLoadingTaskInfoContainer.Begin()); } } -void ImageAtlas::UploadBrokenImage( const Rect& area ) +void ImageAtlas::UploadBrokenImage(const Rect& area) { - Devel::PixelBuffer brokenBuffer = LoadImageFromFile( mBrokenImageUrl, ImageDimensions( area.width, area.height ) ); - SizeType loadedWidth = brokenBuffer.GetWidth(); - SizeType loadedHeight = brokenBuffer.GetHeight(); + Devel::PixelBuffer brokenBuffer = LoadImageFromFile(mBrokenImageUrl, ImageDimensions(area.width, area.height)); + SizeType loadedWidth = brokenBuffer.GetWidth(); + SizeType loadedHeight = brokenBuffer.GetHeight(); - bool needBackgroundClear = false; - SizeType packX = area.x; - SizeType packY = area.y; + bool needBackgroundClear = false; + SizeType packX = area.x; + SizeType packY = area.y; // locate the broken image in the middle. - if( area.width > loadedWidth) + if(area.width > loadedWidth) { - packX += (area.width - loadedWidth)/2; + packX += (area.width - loadedWidth) / 2; needBackgroundClear = true; } - if( area.height > loadedHeight) + if(area.height > loadedHeight) { - packY += (area.height - loadedHeight)/2; + packY += (area.height - loadedHeight) / 2; needBackgroundClear = true; } - if( needBackgroundClear ) + if(needBackgroundClear) { - SizeType size = area.width * area.height * Pixel::GetBytesPerPixel( mPixelFormat ); - Devel::PixelBuffer background = Devel::PixelBuffer::New( area.width, area.height, mPixelFormat ); - unsigned char* buffer = background.GetBuffer(); - for( SizeType idx = 0; idx < size; idx++ ) + SizeType size = area.width * area.height * Pixel::GetBytesPerPixel(mPixelFormat); + Devel::PixelBuffer background = Devel::PixelBuffer::New(area.width, area.height, mPixelFormat); + unsigned char* buffer = background.GetBuffer(); + for(SizeType idx = 0; idx < size; idx++) { buffer[idx] = 0x00; } - PixelData pixelData = Devel::PixelBuffer::Convert( background ); - mAtlas.Upload( pixelData, 0u, 0u, area.x, area.y, area.width, area.height ); + PixelData pixelData = Devel::PixelBuffer::Convert(background); + mAtlas.Upload(pixelData, 0u, 0u, area.x, area.y, area.width, area.height); } - PixelData brokenPixelData = Devel::PixelBuffer::Convert( brokenBuffer ); - mAtlas.Upload( brokenPixelData, 0u, 0u, packX, packY, loadedWidth, loadedHeight ); + PixelData brokenPixelData = Devel::PixelBuffer::Convert(brokenBuffer); + mAtlas.Upload(brokenPixelData, 0u, 0u, packX, packY, loadedWidth, loadedHeight); } } // namespace Internal