From: Agnelo Vaz Date: Mon, 23 Oct 2017 13:27:17 +0000 (+0100) Subject: ImageVisual API for Orientation Correction X-Git-Tag: dali_1.2.63~1^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=6338a533d19079e4415f75270d687e787ee1fa89 ImageVisual API for Orientation Correction Added Property OrientationCorrection which can control if the image should be rotated to it's Orientation as defined by exif data. Provided for JPEG images containing the exif data for Orientation. Limitations: The image provided will be cached, the orientation of the first cached image will be used for subsequent images until the cache image is released. Change-Id: I7627839c143c06dfde63a32eb8171e2205bf18af --- diff --git a/automated-tests/resources/keyboard-Landscape.jpg b/automated-tests/resources/keyboard-Landscape.jpg new file mode 100644 index 0000000..5bc6f39 Binary files /dev/null and b/automated-tests/resources/keyboard-Landscape.jpg differ diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp index 24c5c5d..c2161d1 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp @@ -60,7 +60,8 @@ int UtcTextureManagerRequestLoad(void) FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - &observer ); + &observer, + true ); const VisualUrl& url = textureManager.GetVisualUrl( textureId ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp index 1bd6203..3de6688 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp @@ -49,6 +49,7 @@ const char* TEST_REMOTE_IMAGE_FILE_NAME = "https://www.tizen.org/sites/all/theme const char* TEST_INVALID_FILE_NAME = TEST_RESOURCE_DIR "/invalid.jpg"; const char* TEST_REMOTE_INVALID_FILE_NAME = "https://www.tizen.org/invalid.png"; const char* TEST_MASK_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/mask.png"; +const char* TEST_ROTATED_IMAGE = TEST_RESOURCE_DIR "/keyboard-Landscape.jpg"; bool gResourceReadySignalFired = false; @@ -1720,3 +1721,61 @@ int UtcDaliImageVisualLoadPolicy03(void) END_TEST; } + +int UtcDaliImageVisualOrientationCorrection(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliImageVisualOrientationCorrection Enabling OrientationCorrection should rotate an image with exif (90deg) orientation data with requested" ); + + VisualFactory factory = VisualFactory::Get(); + tet_infoline( "Create visual with Orientation correction set OFF" ); + Property::Map propertyMap; + propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); + propertyMap.Insert( ImageVisual::Property::URL, TEST_ROTATED_IMAGE ); + propertyMap.Insert( DevelImageVisual::Property::ORIENTATION_CORRECTION, false ); + Visual::Base imageVisual = factory.CreateVisual( propertyMap ); + + tet_infoline( "Create control for visual, need to loaded it" ); + DummyControl actor = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + Stage::GetCurrent().Add( actor ); + + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + // Wait for image to load + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + Vector2 originalImageSize; + tet_infoline( "Get size of original visual to compare later with rotated image" ); + imageVisual.GetNaturalSize( originalImageSize ); + DALI_TEST_GREATER( originalImageSize.width, originalImageSize.height, TEST_LOCATION ); // Width and Height must be different for this test. + imageVisual.Reset(); // remove handle so can unregister it and remove from cache + dummyImpl.UnregisterVisual( DummyControl::Property::TEST_VISUAL ); + application.SendNotification(); + application.Render(); + + tet_infoline( "Create visual with Orientation correction set ON " ); + propertyMap.Clear(); + propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); + propertyMap.Insert( ImageVisual::Property::URL, TEST_ROTATED_IMAGE ); + propertyMap.Insert( DevelImageVisual::Property::ORIENTATION_CORRECTION, true ); + imageVisual = factory.CreateVisual( propertyMap ); + + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + // Wait for image to load + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + Vector2 rotatedImageSize; + imageVisual.GetNaturalSize( rotatedImageSize ); + tet_infoline( "Confirm that visual has rotated" ); + DALI_TEST_EQUALS( originalImageSize.width, rotatedImageSize.height , TEST_LOCATION ); + DALI_TEST_EQUALS( originalImageSize.height, rotatedImageSize.width , TEST_LOCATION ); + + Property::Map resultMap; + imageVisual.CreatePropertyMap( resultMap ); + + // check the Property::ORIENTATION_CORRECTION value from the returned map + Property::Value* typeValue = resultMap.Find( DevelImageVisual::Property::ORIENTATION_CORRECTION, Property::BOOLEAN ); + DALI_TEST_EQUALS( typeValue->Get(), true, TEST_LOCATION ); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h index e37d712..acb9b11 100644 --- a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h @@ -105,6 +105,13 @@ enum Type * @see ReleasePolicy::Type */ RELEASE_POLICY = CROP_TO_MASK + 2, + + /** + * @brief Determines if image orientation should be corrected so the image displays as it was intended. + * @details Name "orientationCorrection", Type Property::BOOLEAN, if true the image's orientation will be corrected. + * @note Default true + */ + ORIENTATION_CORRECTION = CROP_TO_MASK + 3, }; } //namespace Property diff --git a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp index d60834f..32f2bc0 100644 --- a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp @@ -24,6 +24,11 @@ namespace Toolkit namespace Internal { +namespace +{ +const bool ENABLE_ORIENTATION_CORRECTION( true ); +} // namespace + FixedImageCache::FixedImageCache( TextureManager& textureManager, UrlList& urlList, ImageCache::FrameReadyObserver& observer, unsigned int batchSize ) @@ -100,7 +105,7 @@ void FixedImageCache::LoadBatch() mImageUrls[ mUrlIndex ].mTextureId = mTextureManager.RequestLoad( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - this ); + this, ENABLE_ORIENTATION_CORRECTION ); mRequestingLoad = false; ++mUrlIndex; } diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp index 8abe059..847e681 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp @@ -45,6 +45,9 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " #else #define LOG_CACHE #endif + +const bool ENABLE_ORIENTATION_CORRECTION( true ); + } namespace Dali @@ -139,7 +142,7 @@ void RollingImageCache::LoadBatch() mImageUrls[ imageFrame.mUrlIndex ].mTextureId = mTextureManager.RequestLoad( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - this ); + this, ENABLE_ORIENTATION_CORRECTION ); mRequestingLoad = false; } diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 9522618..ea3c49c 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -303,7 +303,8 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image ) mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ), mReleasePolicy( DevelImageVisual::ReleasePolicy::DESTROYED ), mAttemptAtlasing( false ), - mLoading( false ) + mLoading( false ), + mOrientationCorrection( true ) { } @@ -399,6 +400,10 @@ void ImageVisual::DoSetProperties( const Property::Map& propertyMap ) { DoSetProperty( Toolkit::DevelImageVisual::Property::RELEASE_POLICY, keyValue.second ); } + else if( keyValue.first == ORIENTATION_CORRECTION_NAME ) + { + DoSetProperty( Toolkit::DevelImageVisual::Property::ORIENTATION_CORRECTION, keyValue.second ); + } } } @@ -406,7 +411,7 @@ void ImageVisual::DoSetProperties( const Property::Map& propertyMap ) if ( mLoadPolicy == DevelImageVisual::LoadPolicy::IMMEDIATE ) { auto attemptAtlasing = mAttemptAtlasing; - LoadTexture( attemptAtlasing, mAtlasRect, mTextures ); + LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection ); } } @@ -557,6 +562,16 @@ void ImageVisual::DoSetProperty( Property::Index index, const Property::Value& v int loadPolicy; Scripting::GetEnumerationProperty( value, LOAD_POLICY_TABLE, LOAD_POLICY_TABLE_COUNT, loadPolicy ); mLoadPolicy = DevelImageVisual::LoadPolicy::Type( loadPolicy ); + break; + } + case Toolkit::DevelImageVisual::Property::ORIENTATION_CORRECTION: + { + bool orientationCorrection( mOrientationCorrection ); + if( value.Get( orientationCorrection ) ) + { + mOrientationCorrection = orientationCorrection; + } + break; } } } @@ -740,7 +755,7 @@ bool ImageVisual::IsSynchronousResourceLoading() const return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } -void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures ) +void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection ) { TextureManager& textureManager = mFactoryCache.GetTextureManager(); @@ -757,7 +772,7 @@ void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& t textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, IsSynchronousResourceLoading(), mTextureId, atlasRect, atlasing, mLoading, mWrapModeU, - mWrapModeV, textureObserver, atlasUploadObserver, atlasManager ); + mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection ); } void ImageVisual::InitializeRenderer() @@ -769,7 +784,7 @@ void ImageVisual::InitializeRenderer() if( mTextureId == TextureManager::INVALID_TEXTURE_ID && ! mTextures ) // Only load the texture once { - LoadTexture( attemptAtlasing, mAtlasRect, mTextures ); + LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection ); } if( attemptAtlasing ) // Flag needs to be set before creating renderer @@ -921,7 +936,7 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::DevelImageVisual::Property::LOAD_POLICY, mLoadPolicy ); map.Insert( Toolkit::DevelImageVisual::Property::RELEASE_POLICY, mReleasePolicy ); - + map.Insert( Toolkit::DevelImageVisual::Property::ORIENTATION_CORRECTION, mOrientationCorrection ); } void ImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index 87111b7..e485904 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -53,20 +53,21 @@ typedef IntrusivePtr< ImageVisual > ImageVisualPtr; * * The following properties are optional * - * | %Property Name | Type | - * |--------------------|-------------------| - * | url | STRING | - * | alphaMaskUrl | STRING | - * | fittingMode | INTEGER OR STRING | - * | samplingMode | INTEGER OR STRING | - * | desiredWidth | INTEGER | - * | desiredHeight | INTEGER | - * | synchronousLoading | BOOLEAN | - * | pixelArea | VECTOR4 | - * | wrapModeU | INTEGER OR STRING | - * | wrapModeV | INTEGER OR STRING | - * | loadPolicy | INTEGER OR STRING | - * | releasePolicy | INTEGER OR STRING | + * | %Property Name | Type | + * |-----------------------|-------------------| + * | url | STRING | + * | alphaMaskUrl | STRING | + * | fittingMode | INTEGER OR STRING | + * | samplingMode | INTEGER OR STRING | + * | desiredWidth | INTEGER | + * | desiredHeight | INTEGER | + * | synchronousLoading | BOOLEAN | + * | pixelArea | VECTOR4 | + * | wrapModeU | INTEGER OR STRING | + * | wrapModeV | INTEGER OR STRING | + * | loadPolicy | INTEGER OR STRING | + * | releasePolicy | INTEGER OR STRING | + * | orientationCorrection | BOOLEAN | * * where pixelArea is a rectangular area. * In its Vector4 value, the first two elements indicate the top-left position of the area, @@ -273,8 +274,9 @@ private: * @param[in, out] atlasing flag if the image has been put in a atlas (true), passing false will not atlas even if possible. * @param[out] atlasRect if atlasing is used this the texture area of the image in the atlas. * @param[out] textures resulting texture set from the image loading. + * @param[in] orientationCorrection flag determines if orientation correction should be performed */ - void LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures ); + void LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection ); /** * @brief Initializes the Dali::Renderer from the image url @@ -355,6 +357,7 @@ private: Vector4 mAtlasRect; bool mAttemptAtlasing; ///< If true will attempt atlasing, otherwise create unique texture bool mLoading; ///< True if the texture is still loading. + bool mOrientationCorrection; ///< true if the image will have it's orientation corrected. }; diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index e795863..308b1ee 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -108,7 +108,7 @@ TextureSet TextureManager::LoadTexture( bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect, bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU, Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver, - AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager) + AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection ) { TextureSet textureSet; @@ -135,7 +135,7 @@ TextureSet TextureManager::LoadTexture( PixelData data; if( url.IsValid() ) { - Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode ); + Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection ); if( pixelBuffer ) { data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer @@ -185,7 +185,7 @@ TextureSet TextureManager::LoadTexture( atlasingStatus = false; if( !maskInfo ) { - textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver ); + textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver, orientationCorrection ); } else { @@ -196,7 +196,8 @@ TextureSet TextureManager::LoadTexture( fittingMode, samplingMode, TextureManager::NO_ATLAS, maskInfo->mCropToMask, - textureObserver ); + textureObserver, + orientationCorrection); } TextureManager::LoadState loadState = GetTextureState( textureId ); @@ -226,9 +227,10 @@ TextureManager::TextureId TextureManager::RequestLoad( FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas, - TextureUploadObserver* observer ) + TextureUploadObserver* observer, + bool orientationCorrection ) { - return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, UPLOAD_TO_TEXTURE, observer ); + return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, UPLOAD_TO_TEXTURE, observer, orientationCorrection ); } TextureManager::TextureId TextureManager::RequestLoad( @@ -240,15 +242,16 @@ TextureManager::TextureId TextureManager::RequestLoad( Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas, bool cropToMask, - TextureUploadObserver* observer ) + TextureUploadObserver* observer, + bool orientationCorrection ) { - return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, UPLOAD_TO_TEXTURE, observer ); + return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection ); } TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl ) { // Use the normal load procedure to get the alpha mask. - return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL ); + return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL, true ); } TextureManager::TextureId TextureManager::RequestLoadInternal( @@ -261,7 +264,8 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( UseAtlas useAtlas, bool cropToMask, StorageType storageType, - TextureUploadObserver* observer ) + TextureUploadObserver* observer, + bool orientationCorrection ) { // First check if the requested Texture is cached. const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId ); @@ -287,7 +291,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( textureId = GenerateUniqueTextureId(); mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(), desiredSize, contentScale, fittingMode, samplingMode, - false, cropToMask, useAtlas, textureHash ) ); + false, cropToMask, useAtlas, textureHash, orientationCorrection ) ); cacheIndex = mTextureInfoContainer.size() - 1u; DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId ); @@ -299,6 +303,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( TextureInfo& textureInfo( mTextureInfoContainer[ cacheIndex ] ); textureInfo.maskTextureId = maskTextureId; textureInfo.storageType = storageType; + textureInfo.orientationCorrection = orientationCorrection; DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureInfo loadState:%s\n", textureInfo.loadState == TextureManager::NOT_STARTED ? "NOT_STARTED" : @@ -489,7 +494,7 @@ bool TextureManager::LoadTexture( TextureInfo& textureInfo ) DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End()); loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, - textureInfo.samplingMode, true); + textureInfo.samplingMode, textureInfo.orientationCorrection ); } } diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.h b/dali-toolkit/internal/visuals/texture-manager-impl.h index 7a243fd..7693b1c 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.h +++ b/dali-toolkit/internal/visuals/texture-manager-impl.h @@ -138,7 +138,8 @@ public: bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU, Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver, AtlasUploadObserver* atlasObserver, - ImageAtlasManagerPtr imageAtlasManager); + ImageAtlasManagerPtr imageAtlasManager, + bool orientationCorrection ); /** * @brief Requests an image load of the given URL. @@ -148,22 +149,24 @@ public: * * When the client has finished with the Texture, Remove() should be called. * - * @param[in] url The URL of the image to load - * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic - * @param[in] fittingMode The FittingMode to use - * @param[in] samplingMode The SamplingMode to use - * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, - * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. - * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. - * This is called when an image load completes (or fails). - * @return A TextureId to use as a handle to reference this Texture + * @param[in] url The URL of the image to load + * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic + * @param[in] fittingMode The FittingMode to use + * @param[in] samplingMode The SamplingMode to use + * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, + * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. + * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. + * This is called when an image load completes (or fails). + * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data + * @return A TextureId to use as a handle to reference this Texture */ TextureId RequestLoad( const VisualUrl& url, const ImageDimensions desiredSize, FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlasing, - TextureUploadObserver* observer ); + TextureUploadObserver* observer, + bool orientationCorrection ); /** * @brief Requests an image load of the given URL, when the texture has @@ -175,18 +178,19 @@ public: * * When the client has finished with the Texture, Remove() should be called. * - * @param[in] url The URL of the image to load - * @param[in] maskTextureId The texture id of an image to mask this with (can be INVALID if no masking required) - * @param[in] contentScale The scale factor to apply to the image before masking - * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic - * @param[in] fittingMode The FittingMode to use - * @param[in] samplingMode The SamplingMode to use - * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, - * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. - * @param[in] cropToMask Only used with masking, this will crop the scaled image to the mask size. If false, then the mask will be scaled to fit the image before being applied. - * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. - * This is called when an image load completes (or fails). - * @return A TextureId to use as a handle to reference this Texture + * @param[in] url The URL of the image to load + * @param[in] maskTextureId The texture id of an image to mask this with (can be INVALID if no masking required) + * @param[in] contentScale The scale factor to apply to the image before masking + * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic + * @param[in] fittingMode The FittingMode to use + * @param[in] samplingMode The SamplingMode to use + * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, + * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. + * @param[in] cropToMask Only used with masking, this will crop the scaled image to the mask size. If false, then the mask will be scaled to fit the image before being applied. + * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. + * This is called when an image load completes (or fails). + * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data + * @return A TextureId to use as a handle to reference this Texture */ TextureId RequestLoad( const VisualUrl& url, TextureId maskTextureId, @@ -196,7 +200,8 @@ public: Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlasing, bool cropToMask, - TextureUploadObserver* observer ); + TextureUploadObserver* observer, + bool orientationCorrection ); /** * Requests a masking image to be loaded. This mask is not uploaded to GL, @@ -260,19 +265,20 @@ private: * * When the client has finished with the Texture, Remove() should be called. * - * @param[in] url The URL of the image to load - * @param[in] maskTextureId The texture id of an image to use as a mask. If no mask is required, then set to INVALID_TEXTURE_ID - * @param[in] contentScale The scaling factor to apply to the content when masking - * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic - * @param[in] fittingMode The FittingMode to use - * @param[in] samplingMode The SamplingMode to use - * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, - * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. - * @param[in] cropToMask Whether to crop the target after masking, or scale the mask to the image before masking. - * @param[in] storageType, Whether the pixel data is stored in the cache or uploaded to the GPU - * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. - * This is called when an image load completes (or fails). - * @return A TextureId to use as a handle to reference this Texture + * @param[in] url The URL of the image to load + * @param[in] maskTextureId The texture id of an image to use as a mask. If no mask is required, then set to INVALID_TEXTURE_ID + * @param[in] contentScale The scaling factor to apply to the content when masking + * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic + * @param[in] fittingMode The FittingMode to use + * @param[in] samplingMode The SamplingMode to use + * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, + * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. + * @param[in] cropToMask Whether to crop the target after masking, or scale the mask to the image before masking. + * @param[in] storageType, Whether the pixel data is stored in the cache or uploaded to the GPU + * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. + * This is called when an image load completes (or fails). + * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data + * @return A TextureId to use as a handle to reference this Texture */ TextureId RequestLoadInternal( const VisualUrl& url, @@ -284,7 +290,8 @@ private: UseAtlas useAtlas, bool cropToMask, StorageType storageType, - TextureUploadObserver* observer ); + TextureUploadObserver* observer, + bool orientationCorrection ); typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching. @@ -304,7 +311,8 @@ private: bool loadSynchronously, bool cropToMask, UseAtlas useAtlas, - TextureManager::TextureHash hash ) + TextureManager::TextureHash hash, + bool orientationCorrection ) : url( url ), desiredSize( desiredSize ), useSize( desiredSize ), @@ -320,7 +328,8 @@ private: storageType( UPLOAD_TO_TEXTURE ), loadSynchronously( loadSynchronously ), useAtlas( useAtlas ), - cropToMask( cropToMask ) + cropToMask( cropToMask ), + orientationCorrection( true ) { } @@ -349,6 +358,7 @@ private: bool loadSynchronously:1; ///< True if synchronous loading was requested UseAtlas useAtlas:1; ///< USE_ATLAS if an atlas was requested. This is updated to false if atlas is not used bool cropToMask:1; ///< true if the image should be cropped to the mask size. + bool orientationCorrection:1; ///< true if the image should be rotated to match exif orientation data }; // Structs: diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 6282559..e28a910 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -87,6 +87,7 @@ const char * const MASK_CONTENT_SCALE_NAME("maskContentScale"); const char * const CROP_TO_MASK_NAME("cropToMask"); const char * const LOAD_POLICY_NAME("loadPolicy"); const char * const RELEASE_POLICY_NAME("releasePolicy"); +const char * const ORIENTATION_CORRECTION_NAME("orientationCorrection"); // Text visual const char * const TEXT_PROPERTY( "text" ); diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 27030df..50f809f 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -75,6 +75,7 @@ extern const char * const MASK_CONTENT_SCALE_NAME; extern const char * const CROP_TO_MASK_NAME; extern const char * const LOAD_POLICY_NAME; extern const char * const RELEASE_POLICY_NAME; +extern const char * const ORIENTATION_CORRECTION_NAME; // Text visual extern const char * const TEXT_PROPERTY;