22 Replies Latest reply on Apr 5, 2011 2:07 AM by Sharkow

    Spark Image "bug"?

    Sharkow

      Hello. I've encountered a problem with spark:Image class. I need to get it as a BitmapData.

      There's a BitmapData.draw(...) method for this. It works well with other components and allows to create a Bitmap representation of them.
      Actually, I'm using M2D engine and there such technique is used to accelerate DisplayObjects.

       

      I need to capture my image when it has finished loading content.

      So, I add an eventListener for COMPLETE event. But, what I get captured is just a white rectangle!

      I think, the problem is that the image doesn't finish its rendering yet, so it has content just loaded into memory by the time Event.COMPLETE is fired.

      So, I've tried to use FlexEvent.UPDATE_COMPLETE instead. It seems, it's fired three times when image.source changes.

      I get three BitmapData objects and the last one appears to be correct.

      Of cource, it can be thought of as a solution, but I don't like it It seems to be buggy.

       

      Maybe there is a "right" way to capture an image?

       

      mx:Image works right, by the way. But I want spark

        • 1. Re: Spark Image "bug"?
          CleanCoder Level 2

          Is your Image added to the dipslayList at the time when you are trying to capture the Bitmap? Im pretty sure that it has to be on the displayList in order to use the BitmapData. Also, you should be able to access the bitmapData of the Image source through the "bitmapData" property of the image. Use that bitmapData to determine what is actually getting captured.

          • 2. Re: Spark Image "bug"?
            CleanCoder Level 2

            Is your Image added to the dipslayList at the time when you are trying  to capture the Bitmap? Im pretty sure that it has to be on the  displayList in order to use the BitmapData. Also, you should be able to  access the bitmapData of the Image source through the "bitmapData"  property of the image. Use that bitmapData to determine what is actually  getting captured.

            • 3. Re: Spark Image "bug"?
              Sharkow Level 1

              Yes, it is added to the displayList in time.

               

              I've tried to access the bitmapData property of the image, and it turned out, that it is null the first two times, when UPDATE_COMPLETE is fired. The last time, when I get a properly showed image, it's not. That's better, it's easier to identify the "correct" event by checking the bitmapData.

               

              I forgot to say, that problems start when the source of the image is changing frequently. If I count UPDATE_COMPLETE events and just handle every third one, then I lose count in such situations.

              Now, just checking the bitmapData property should solve it. I only need to distinguish it's values before and after changing the source. Will check clearOnLoad property...

               

              Thank you

              • 4. Re: Spark Image "bug"?
                CleanCoder Level 2

                I think you were on the right track with listening for the "complete" event, not the "updateComplete" event. However,  your "updateComplete" event should not be firing 3 times either. Where are you setting the "source" property of the image, commitProperties or updateDisplayList? It sounds like something is getting invalidated multiple times which is causing the multiple "updateComplete" events. I would recommend setting the "source" property in commitProperties, before the call to super.commitProperties.

                • 5. Re: Spark Image "bug"?
                  Shongrunden Adobe Employee

                  Does it work if you wait for the "ready" event instead of "complete" ?

                  • 6. Re: Spark Image "bug"?
                    Sharkow Level 1

                    Shongrunden,

                    No, listening for READY gives the same result as COMPLETE.

                     

                    CleanCoder,

                    I would recommend setting the "source" property in commitProperties, before the call to super.commitProperties.

                    Could you explain a little more in detail? Actually, I'm quite new to Flash

                    I can't find commitProperties and updateDisplayList methods.

                     

                    I'm setting the image source first  in an ADDED_TO_STAGE eventListener, and then in a mouse eventListener. I get the same result every time, as I've discribed above.

                    I don't do anything else in the mouse eventListener. So, getting three bitmaps - two clean ones and one correct.

                    • 7. Re: Spark Image "bug"?
                      CoreyRLucier Adobe Employee

                      I haven't seen a case where listening for READY , then querying bitmapData directly to obtain the bitmap, doesn't work.  In fact for trusted images (images loaded from a trusted domain or embedded), I'm not sure it's even possible that READY would be fired without valid bitmap data since it's fired right after the bitmapData is assigned internally.

                       

                      If you've found otherwise please post a simple test case.

                       

                      -C

                      • 8. Re: Spark Image "bug"?
                        Sharkow Level 1

                        I've checked the bitmapData property of the image after READY and COMPLETE being fired. It has a correct value. If I just assign it to a Bitmap object and add it to the stage, it's shown properly.

                        But if I make my own bitmapData and invoke its draw(...) method, I get a clear area. So, as I said, I think, that problem is that the image itself isn't being rendered yet by the time READY (COMPLETE) is being fired. And I need the image itself, not its bitmapData.

                         

                        So, I think, I can handle it now by listening for UPDATE_COMPLETE and checking the bitmapData of the image. But the problem is present, anyway

                        • 9. Re: Spark Image "bug"?
                          CleanCoder Level 2

                          When I mentioned setting the "source" property in commitProperties I was assuming that you were extending a component or skin class, in which case you would be able to override the commitProperties function. Also, you shouldnt have to wait for the "addedToStage" event just to set the "source" property, you can do that immiediately after you instantiate it. Where are you creating the Image, and just for clarification, what  exactly are you trying to accomplish with your Image? Do you want the  Image to change based on mouse events or what are the circumstances where the Image "source" would be changed?

                          • 10. Re: Spark Image "bug"?
                            Sharkow Level 1

                            Well, I wait for the ADDED_TO_STAGE event for other puposes.

                            I'm creating the image in the class constructor.

                             

                            I'm going to use the Image for creating a bitmap with an image loaded externally. That bitmap will be loaded to an object used by M2D engine. As a result, I will be showing images using M2D with better performance instead of using common Flash (Flex) classes.

                            I'm using spark:Image, because it is convinient for scaling and smoothing of loaded images.

                            The Image itself won't be shown.

                             

                            Yes, the Image will change based on mouse events.

                            • 11. Re: Spark Image "bug"?
                              CleanCoder Level 2

                              Just so I'm clear,

                               

                              Do the mouse events occur on the actual object displaying the BitmapData (like button functionality), or from some other object on the stage (like a shooting game where a user click on the screen and graphics change to reflect the damage)?

                               

                              "I'm creating the image in the class constructor." Im assuming the class you are referring to extends UIComponent because you are using "updateComplete" events correct?

                              • 12. Re: Spark Image "bug"?
                                Sharkow Level 1

                                Currently mouse events occur on the whole application.

                                The UPDATE_COMPLETE event I was talking about refers to the Image itself, not to my class.

                                image.addEventListener(FlexEvent.UPDATE_COMPLETE, rendered);
                                

                                 

                                My class extends UIComponent and recieves a BorderContainer object in its constructor. It creates an Image and adds it to that BorderContainer.

                                Don't ask me, why It's all becuse of M2D. Furthermore, the BorderContainer is made invisible

                                 

                                But that tricks are for sure not connected with the problem. I've tried capturing the spark:Image like this before, using only pure Flex SDK, without strange tricks and had the same problem.

                                • 13. Re: Spark Image "bug"?
                                  CleanCoder Level 2

                                  I am not familiar M2D at all, so you lost me at the invisible BorderContainer. And by invisible do you mean it is added to the displayList with its "visible" property set to "false"? If so there might be an issue capturing the BitmapData on an invisible DisplayObject (your Image is added as a child of the BorderContainer so it would be invisible also...). Also, does the Image get created in the constructor also, or do you create that in the "createChildren" function? If you set the Image source from the constructor, the Image isnt actually added to the displayList at that point, so that could be part of the problem.

                                  • 14. Re: Spark Image "bug"?
                                    Sharkow Level 1

                                    Yes, the BorderContainer is added to the displayList, and its "visible" property is set to "false". Indeed, my Image becomes invisible, too. But that's OK. Note, that I can get it captured when the UPDATE_COMPLETE is fired the third time And, again, I've tried to capture it earlier, when it was visible and shown, with the same result.

                                     

                                    The Image is created in the constructor. Yes, it really has to be on the displayList to operate it. That's why I'm adding it to that BorderContainer The source is being set after that.

                                    • 15. Re: Spark Image "bug"?
                                      CleanCoder Level 2

                                      Is this similar to what you are working with? I pass in an invisible BorderContainer already added to the displayList. The bitmapData in my image_completeHandler seems to work as expected. Also, my _image only fires 2 "updateComplete" events (which is irrelevant because you shouldnt have to listen for it anyway).

                                       

                                      package
                                      {
                                      import flash.display.BitmapData;
                                      import flash.events.Event;
                                      
                                      import mx.core.UIComponent;
                                      import mx.events.FlexEvent;
                                      
                                      import spark.components.BorderContainer;
                                      import spark.components.Image;
                                      
                                      public class Foo extends UIComponent
                                      {
                                           //---------------------------------------------------------------------------
                                           //
                                           //  Constructor
                                           //
                                           //---------------------------------------------------------------------------
                                           
                                           /**
                                            * 
                                            */
                                           public function Foo( container:BorderContainer )
                                           {
                                                super();
                                                
                                                _image = new Image();
                                                _image.addEventListener(Event.COMPLETE, image_completeHandler);
                                                _image.addEventListener(FlexEvent.UPDATE_COMPLETE, image_updateCompleteHandler);
                                                container.addElement(_image);
                                                _image.source = "assets/hills.jpg";
                                           }
                                           
                                           //---------------------------------------------------------------------------
                                           //
                                           //  Variables
                                           //
                                           //---------------------------------------------------------------------------
                                           
                                           /**
                                            * 
                                            */
                                           private var _image:Image;
                                           
                                           //---------------------------------------------------------------------------
                                           //
                                           //  Methods private
                                           //
                                           //---------------------------------------------------------------------------
                                           
                                           /**
                                            * 
                                            */
                                           private function image_completeHandler( event:Event ):void
                                           {
                                                var bmpData:BitmapData = _image.bitmapData;
                                                trace(bmpData.width, bmpData.height);
                                           }
                                           
                                           /**
                                            * 
                                            */
                                           private function image_updateCompleteHandler( event:FlexEvent ):void
                                           {
                                                trace(event.type);
                                           }
                                      }
                                      
                                      }
                                      
                                      • 16. Re: Spark Image "bug"?
                                        Sharkow Level 1

                                        I'm doing more or less the same, except one thing.

                                        As I've written before, if I just get the bitmapData property of the Image, it's always fine.

                                        But that's not what I need. I need this:

                                        var bmpData:BitmapData = new BitmapData(image.width, image.height);
                                        bmpData.draw(image);
                                        var bmp:Bitmap = new Bitmap(bmpData);
                                        addChild(bmp);
                                        

                                        And that works as expected only after the last UPDATE_COMPLETE is being fired.

                                        • 17. Re: Spark Image "bug"?
                                          CleanCoder Level 2

                                          Instead of using the image.width and image.height use the image.bitmapData.width and image.bitmapData.height in the constructor of your new BitmapData. If your trace the values of image.width and image.height I believe they will be 0 at that point, unless you have explicity set the size of your image. The bitmapData dimensions from the image should reflect the actual width and height of the data you want to capture. Trace out (image.width, image.height, image.bitmapData.width, image.bitmapData.height) and see what you get.

                                          • 18. Re: Spark Image "bug"?
                                            Sharkow Level 1

                                            This is not the problem, I'm sure. I set the size of the image explicitly. And I get clear write rectangles of its size, not just nothing.

                                            • 19. Re: Spark Image "bug"?
                                              CleanCoder Level 2

                                              See if this works for you:

                                               

                                              // App code
                                              
                                              var container:BorderContainer = new BorderContainer();
                                                                  container.visible = false;
                                                                  container.width = container.height = 0;
                                                                  addElement(container);
                                                                  var foo:Foo = new Foo(container);
                                                                  addElement(foo);
                                              
                                              // in Foo
                                              
                                              /**
                                               * 
                                               */
                                              private function image_completeHandler( event:Event ):void
                                              {
                                                      var image:Image = event.target as Image;
                                                   var sourceData:BitmapData = image.bitmapData;
                                                   var targetData:BitmapData = new BitmapData(image.width, image.height);
                                                   targetData.draw(sourceData);
                                                   var bmp:Bitmap = new Bitmap(targetData);
                                                   addChild(bmp);
                                              }
                                              
                                              • 20. Re: Spark Image "bug"?
                                                Sharkow Level 1
                                                var image:Image = event.target as Image;
                                                var sourceData:BitmapData = image.bitmapData;
                                                var targetData:BitmapData = new BitmapData(image.width, image.height);
                                                targetData.draw(sourceData);
                                                var bmp:Bitmap = new Bitmap(targetData);
                                                addChild(bmp);

                                                In this block of code just a fragment of the source image is drawn, because its bitmapData property returns an unscaled image. And the size information you get by

                                                image.width, image.height

                                                is for the scaled image.

                                                I'm sure, that there's no way to get what I want by the bitmapData property. The point is to draw the image to a BitmapData itself.

                                                • 21. Re: Spark Image "bug"?
                                                  CleanCoder Level 2

                                                  I apologize, but I am thoroughly confused at this point, probably because I dont really understand your use case. Perhaps someone more familiar with M2D might be able help you better.

                                                  • 22. Re: Spark Image "bug"?
                                                    Sharkow Level 1

                                                    Well, the solution with checking the bitmapData when listening to UPDATE_COMPLETE seems fine, so many thanks for it