Merge "ImageVisual API for Orientation Correction" into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 26 Oct 2017 18:48:17 +0000 (18:48 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Thu, 26 Oct 2017 18:48:18 +0000 (18:48 +0000)
12 files changed:
automated-tests/resources/keyboard-Landscape.jpg [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
dali-toolkit/devel-api/visuals/image-visual-properties-devel.h
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/internal/visuals/texture-manager-impl.h
dali-toolkit/internal/visuals/visual-string-constants.cpp
dali-toolkit/internal/visuals/visual-string-constants.h

diff --git a/automated-tests/resources/keyboard-Landscape.jpg b/automated-tests/resources/keyboard-Landscape.jpg
new file mode 100644 (file)
index 0000000..5bc6f39
Binary files /dev/null and b/automated-tests/resources/keyboard-Landscape.jpg differ
index 24c5c5d..c2161d1 100644 (file)
@@ -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 );
 
index 1bd6203..3de6688 100644 (file)
@@ -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<Impl::DummyControl&>(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<bool>(), true, TEST_LOCATION );
+
+  END_TEST;
+}
index e37d712..acb9b11 100644 (file)
@@ -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
index d60834f..32f2bc0 100644 (file)
@@ -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;
   }
index 8abe059..847e681 100644 (file)
@@ -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;
   }
 
index 9522618..ea3c49c 100644 (file)
@@ -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
index 87111b7..e485904 100644 (file)
@@ -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.
 };
 
 
index e795863..308b1ee 100644 (file)
@@ -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 );
     }
   }
 
index 7a243fd..7693b1c 100644 (file)
@@ -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:
index 6282559..e28a910 100644 (file)
@@ -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" );
index 27030df..50f809f 100644 (file)
@@ -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;