Commit 61a27c16e79a05ed6ba17ee95a1d4d4a826c6b3d

Authored by Tom Robinson
1 parent f6d1ca29

Implement image fitting modes

Change-Id: Id3088e4f8b6158266b1531a28c1d71b89ac86b95
examples/image-scaling-and-filtering/image-scaling-and-filtering-example.cpp
... ... @@ -30,6 +30,10 @@ namespace
30 30 const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-gradient.jpg" );
31 31 const Vector4 BACKGROUND_COLOUR( 1.0f, 1.0f, 1.0f, 0.15f );
32 32  
  33 +const char* BORDER_IMAGE( DALI_IMAGE_DIR "border-4px.9.png" );
  34 +const int BORDER_WIDTH = ( 11.0f + 4.0f ); // Shadow size = 11, border size = 4.
  35 +const char* RESIZE_HANDLE_IMAGE( DALI_IMAGE_DIR "resize-handle.png" );
  36 +
33 37 const int MARGIN_SIZE = 10;
34 38  
35 39 const char* const NEXT_BUTTON_ID = "NEXT_BUTTON";
... ... @@ -45,28 +49,28 @@ const char* const STYLE_LABEL_TEXT = "grouplabel";
45 49 const char* const STYLE_BUTTON_TEXT = "buttonlabel";
46 50  
47 51  
48   -
49 52 const char* IMAGE_PATHS[] =
50 53 {
51   - // Worst case for aliasing in downscaling, 2k x 2k 1 bit per pixel dithered
52   - // black and white image:
53   - DALI_IMAGE_DIR "gallery-large-14.wbmp",
54 54 // Variety of sizes, shapes and formats:
55   - DALI_IMAGE_DIR "animation-list.png",
  55 + DALI_IMAGE_DIR "dali-logo.png",
56 56 DALI_IMAGE_DIR "layer1.png",
57 57 DALI_IMAGE_DIR "layer2.png",
  58 + DALI_IMAGE_DIR "animation-list.png",
58 59 DALI_IMAGE_DIR "music-libray-main-screen.png",
59 60 DALI_IMAGE_DIR "music-libray-record-cover.png",
60 61 DALI_IMAGE_DIR "contacts-background.png",
61 62 DALI_IMAGE_DIR "portrait_screen_primitive_shapes.gif",
62 63 DALI_IMAGE_DIR "landscape_screen_primitive_shapes.gif",
63 64 DALI_IMAGE_DIR "square_primitive_shapes.bmp",
64   - DALI_IMAGE_DIR "dali-logo.png",
65   - DALI_IMAGE_DIR "com.samsung.dali-demo.ico",
66 65 DALI_IMAGE_DIR "gallery-large-14.jpg",
67 66 DALI_IMAGE_DIR "book-landscape-cover.jpg",
68 67 DALI_IMAGE_DIR "book-portrait-p1.jpg",
69 68 DALI_IMAGE_DIR "book-landscape-cover-back.jpg",
  69 +
  70 + // Worst case for aliasing in downscaling, 2k x 2k 1 bit per pixel dithered
  71 + // black and white image:
  72 + DALI_IMAGE_DIR "gallery-large-14.wbmp",
  73 +
70 74 DALI_IMAGE_DIR "background-1.jpg",
71 75 DALI_IMAGE_DIR "background-blocks.jpg",
72 76 DALI_IMAGE_DIR "background-magnifier.jpg",
... ... @@ -151,8 +155,10 @@ public:
151 155 : mApplication( application ),
152 156 mImageStageScale( 0.5f, 0.5f ),
153 157 mCurrentPath( 0 ),
154   - mFittingMode( FittingMode::SCALE_TO_FILL ),
155   - mSamplingMode( SamplingMode::BOX_THEN_LINEAR)
  158 + mFittingMode( FittingMode::FIT_WIDTH ),
  159 + mSamplingMode( SamplingMode::BOX_THEN_LINEAR),
  160 + mImageLoading( false ),
  161 + mQueuedImageLoad( false )
156 162 {
157 163 // Connect to the Application's Init signal
158 164 mApplication.InitSignal().Connect( this, &ImageScalingAndFilteringController::Create );
... ... @@ -184,9 +190,6 @@ public:
184 190 background.SetSize( stage.GetSize() );
185 191 stage.Add( background );
186 192  
187   - // Make grey pixels for the desired box, the desired height the desired width:
188   - BufferImage desiredBackground = BufferImage::WHITE();
189   -
190 193 BufferImage heightBackground = BufferImage::WHITE();
191 194 PixelBuffer* const heightPixel = heightBackground.GetBuffer();
192 195 heightPixel[0] = 0x8f;
... ... @@ -207,7 +210,7 @@ public:
207 210 mWidthBox.SetOpacity( 0.2f );
208 211 background.Add( mWidthBox );
209 212  
210   - mDesiredBox = Toolkit::ImageView::New( desiredBackground );
  213 + mDesiredBox = Toolkit::ImageView::New( BORDER_IMAGE );
211 214 background.Add( mDesiredBox );
212 215  
213 216 mDesiredBox.SetSize( stage.GetSize() * mImageStageScale );
... ... @@ -239,27 +242,24 @@ public:
239 242 mPinchDetector.Attach( mImageView );
240 243 mPinchDetector.DetectedSignal().Connect( this, &ImageScalingAndFilteringController::OnPinch );
241 244  
242   - // Make a grab-handle for resizing the image:
243   - mGrabCorner = Toolkit::PushButton::New();
244   - mGrabCorner.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
245   - mGrabCorner.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
  245 + mGrabCorner = Toolkit::ImageView::New( RESIZE_HANDLE_IMAGE );
  246 + mGrabCorner.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
246 247 mGrabCorner.SetName( "GrabCorner" );
247 248 mGrabCorner.SetAnchorPoint( AnchorPoint::BOTTOM_RIGHT );
248 249 mGrabCorner.SetParentOrigin( ParentOrigin::BOTTOM_RIGHT );
249   - mGrabCorner.SetSize( Vector2( stage.GetSize().width*0.08f, stage.GetSize().width*0.08f ) );
  250 + mGrabCorner.SetPosition( -BORDER_WIDTH, -BORDER_WIDTH );
250 251 mGrabCorner.SetOpacity( 0.6f );
251 252  
252 253 Layer grabCornerLayer = Layer::New();
253 254 grabCornerLayer.SetAnchorPoint( AnchorPoint::BOTTOM_RIGHT );
254 255 grabCornerLayer.SetParentOrigin( ParentOrigin::BOTTOM_RIGHT );
255   -
256 256 grabCornerLayer.Add( mGrabCorner );
257   - mImageView.Add( grabCornerLayer );
  257 + mDesiredBox.Add( grabCornerLayer );
  258 +
258 259 mPanGestureDetector = PanGestureDetector::New();
259 260 mPanGestureDetector.Attach( mGrabCorner );
260 261 mPanGestureDetector.DetectedSignal().Connect( this, &ImageScalingAndFilteringController::OnPan );
261 262  
262   -
263 263 // Tie-in input event handlers:
264 264 stage.KeyEventSignal().Connect( this, &ImageScalingAndFilteringController::OnKeyEvent );
265 265  
... ... @@ -394,7 +394,6 @@ public:
394 394 return popup;
395 395 }
396 396  
397   - //void CreatePopupButton( Toolkit::Popup popup, const char* id )
398 397 Toolkit::PushButton CreatePopupButton( Actor parent, const char* id )
399 398 {
400 399 Toolkit::PushButton button = Toolkit::PushButton::New();
... ... @@ -523,9 +522,17 @@ public:
523 522  
524 523 void OnImageLoaded( ResourceImage image )
525 524 {
526   - DALI_ASSERT_DEBUG( image == mNextImage );
527   - mImageView.SetImage( image );
528   - mImageView.SetSize( Size( image.GetWidth(), image.GetHeight() ) );
  525 + DALI_ASSERT_DEBUG( image == mNextImage );
  526 + mImageView.SetImage( image );
  527 + mImageView.SetSize( Size( image.GetWidth(), image.GetHeight() ) );
  528 + mImageLoading = false;
  529 +
  530 + // We have finished loading, if a resize had occured during the load, trigger another load now.
  531 + if( mQueuedImageLoad )
  532 + {
  533 + mQueuedImageLoad = false;
  534 + LoadImage();
  535 + }
529 536 }
530 537  
531 538 bool OnControlTouched( Actor actor, const TouchEvent& event )
... ... @@ -590,8 +597,10 @@ public:
590 597 void OnPan( Actor actor, const PanGesture& gesture )
591 598 {
592 599 Stage stage = Stage::GetCurrent();
593   - mImageStageScale.x = std::max( 0.05f, std::min( 1.0f, mImageStageScale.x + (gesture.displacement.x * 2.0f / stage.GetSize().width ) ) );
594   - mImageStageScale.y = std::max( 0.05f, std::min( 1.0f, mImageStageScale.y + (gesture.displacement.y * 2.0f / stage.GetSize().height ) ) );
  600 + // 1.0f and 0.75f are the maximum size caps of the resized image, as a factor of stage-size.
  601 + mImageStageScale.x = std::max( 0.05f, std::min( 0.95f, mImageStageScale.x + ( gesture.displacement.x * 2.0f / stage.GetSize().width ) ) );
  602 + mImageStageScale.y = std::max( 0.05f, std::min( 0.70f, mImageStageScale.y + ( gesture.displacement.y * 2.0f / stage.GetSize().height ) ) );
  603 +
595 604 ResizeImage();
596 605 }
597 606  
... ... @@ -669,21 +678,53 @@ public:
669 678 }
670 679  
671 680 private:
672   - void ResizeImage()
  681 +
  682 + void LoadImage()
673 683 {
674   - const char * const path = IMAGE_PATHS[mCurrentPath];
  684 + mImageLoading = true;
675 685  
  686 + const char * const path = IMAGE_PATHS[ mCurrentPath ];
676 687 Stage stage = Stage::GetCurrent();
677 688 Size imageSize = stage.GetSize() * mImageStageScale;
678 689 const ImageDimensions imageSizeInt = ImageDimensions::FromFloatArray( &imageSize.x );
679 690  
680 691 ResourceImage image = ResourceImage::New( path, imageSizeInt, mFittingMode, mSamplingMode );
681   - image.LoadingFinishedSignal().Connect( this, &ImageScalingAndFilteringController::OnImageLoaded );
  692 +
  693 + // If the image was cached, the load has already occured, bypass hooking the signal.
  694 + if( image.GetLoadingState() )
  695 + {
  696 + OnImageLoaded( image );
  697 + }
  698 + else
  699 + {
  700 + image.LoadingFinishedSignal().Connect( this, &ImageScalingAndFilteringController::OnImageLoaded );
  701 + }
682 702  
683 703 mNextImage = image;
  704 + }
684 705  
685   - mDesiredBox.SetSize( stage.GetSize() * mImageStageScale );
686   - mHeightBox.SetSize( stage.GetSize().width, (stage.GetSize() * mImageStageScale).height );
  706 + void ResizeImage()
  707 + {
  708 +
  709 + Stage stage = Stage::GetCurrent();
  710 + Size imageSize = stage.GetSize() * mImageStageScale;
  711 +
  712 + // If an image is already loading, queue another load when it has finished.
  713 + // This way we get continuous updates instead of constantly re-requesting loads.
  714 + if( mImageLoading )
  715 + {
  716 + mQueuedImageLoad = true;
  717 + }
  718 + else
  719 + {
  720 + LoadImage();
  721 + }
  722 +
  723 + // Border size needs to be modified to take into account the width of the frame.
  724 + Vector2 borderScale( ( imageSize + Vector2( BORDER_WIDTH * 2.0f, BORDER_WIDTH * 2.0f ) ) / stage.GetSize() );
  725 + mDesiredBox.SetSize( stage.GetSize() * borderScale );
  726 +
  727 + mHeightBox.SetSize( stage.GetSize().width, (stage.GetSize() * mImageStageScale).height );
687 728 mWidthBox.SetSize( (stage.GetSize() * mImageStageScale).width, stage.GetSize().height );
688 729 }
689 730  
... ... @@ -697,7 +738,7 @@ private:
697 738 Toolkit::Popup mPopup;
698 739 PinchGestureDetector mPinchDetector;
699 740 float mLastPinchScale;
700   - Toolkit::PushButton mGrabCorner;
  741 + Toolkit::ImageView mGrabCorner;
701 742 PanGestureDetector mPanGestureDetector;
702 743 Toolkit::ImageView mImageView;
703 744 ResourceImage mNextImage; //< Currently-loading image
... ... @@ -705,6 +746,9 @@ private:
705 746 int mCurrentPath;
706 747 FittingMode::Type mFittingMode;
707 748 SamplingMode::Type mSamplingMode;
  749 + bool mImageLoading;
  750 + bool mQueuedImageLoad;
  751 +
708 752 };
709 753  
710 754 void RunTest( Application& application )
... ...
resources/images/border-4px.9.png 0 → 100644

696 Bytes

resources/images/resize-handle.png 0 → 100644

2.56 KB

resources/scripts/shader-effect-ripple.json
... ... @@ -9,12 +9,13 @@
9 9 0.0
10 10 ],
11 11 "parentOrigin": [0.5, 0.5, 0.5],
12   - "size": [200, 200, 0],
  12 + "widthResizePolicy":"FILL_TO_PARENT",
  13 + "heightResizePolicy":"DIMENSION_DEPENDENCY",
13 14 "effect": "Ripple2D",
14 15 "image": {
15 16 "filename": "{DALI_IMAGE_DIR}gallery-medium-25.jpg",
16   - "width": 200,
17   - "height": 80,
  17 + "width": 400,
  18 + "height": 400,
18 19 "loadPolicy": "IMMEDIATE",
19 20 "releasePolicy": "NEVER"
20 21 },
... ... @@ -35,11 +36,11 @@
35 36 {
36 37 "actor": "Image1",
37 38 "property": "uTime",
38   - "value": 10.0,
  39 + "value": 36.0,
39 40 "alphaFunction": "LINEAR",
40 41 "timePeriod": {
41 42 "delay": 0,
42   - "duration": 10.0
  43 + "duration": 20.0
43 44 },
44 45 "guiBuilderTimelineColor": "#8dc0da"
45 46 }
... ...