{"id":108,"date":"2007-06-11T23:09:17","date_gmt":"2007-06-12T07:09:17","guid":{"rendered":"http:\/\/dougmccune.com\/blog\/2007\/06\/11\/imagesnapshot-class-in-flex-3-sdk\/"},"modified":"2007-06-11T23:09:17","modified_gmt":"2007-06-12T07:09:17","slug":"imagesnapshot-class-in-flex-3-sdk","status":"publish","type":"post","link":"https:\/\/dougmccune.com\/blog\/2007\/06\/11\/imagesnapshot-class-in-flex-3-sdk\/","title":{"rendered":"ImageSnapshot class in Flex 3 SDK"},"content":{"rendered":"<p>There are a few new graphics classes in the Flex 3 SDK that make it easier to create image snapshots of Flex UI components. The <strong>ImageSnapshot<\/strong> class provides some static methods for creating snapshots of components and encoding them as PNG or JPEG images. In addition to the ImageSnapshot class, we also get the PNGEncoder, JPEGEncoder, Base64Encoder, and Base64Decoder, which were all previously in the as3corelib project.<\/p>\n<p><strong>mx.graphics.codec.JPEGEncoder<\/strong><br \/>\n<strong>mx.graphics.codec.PNGEncoder<\/strong><\/p>\n<p>The JPEGEncoder and PNGEncoder classes were in the as3corelib project prior to Flex 3. They have since been rolled into the main Flex framework. Nice! They&#8217;re pretty straightforward, and they&#8217;ve been around for awhile in the as3corelib project, so they shouldn&#8217;t need much explanation.<\/p>\n<p><strong>mx.graphics.codec.IImageEncoder<\/strong><\/p>\n<p>The IImageEncoder interface defines an interface for a class that encodes a BitmapData object or the raw bytes of a Bitmap into a new encoded ByteArray. The two classes that implement this interface are <strong>PNGEncoder<\/strong> and <strong>JPEGEncoder<\/strong>. If you were to write your own image encoders you could implement this interface and then you could pass your custom encoder to <strong>ImageSnapshot.captureImage()<\/strong> (read below for more on that).<\/p>\n<p><strong>mx.graphics.ImageSnapshot<\/strong><\/p>\n<p>The ImageSnapshot class is a new addition to the Flex SDK that simplifies the process of capturing an image from a Flex UI control. This is a task that is often performed, I can think of a bunch of examples right off the top of my head where I&#8217;ve had to do this. A live reflection class is one candidate to use this new helper class. I have a feeling a big use of this class is going to be saving image snapshots to the user&#8217;s computer in an AIR application. And another use-case that I recently dealt with is converting a Flex UI component to a Base 64 encoded image (see my previous post). <\/p>\n<p>When I needed to get a Base64-encoded string of a given Flex UI component I did something like this:<\/p>\n<pre><code>\r\nprivate function getBase64String(component:UIComponent):String) {\r\n\tvar bitmapData:BitmapData = new BitmapData(component.width, component.height, true, 0xffffff);\r\n\tbitmapData.draw(component);\r\n\r\n\tvar bytes:ByteArray = PNGEncoder.encode(bitmapData);\r\n\r\n\tvar b64encoder:Base64Encoder = new Base64Encoder();\r\n\tb64encoder.encodeBytes(bytes);\r\n\r\n\tvar b64String:String = b64encoder.flush();\r\n\t\r\n\treturn b64String;\r\n}\r\n<\/code><\/pre>\n<p>But now we have a much easier way. The ImageSnapshot class has a few static methods that we can use. We get:<\/p>\n<p><strong>captureBitmapData<\/strong><br \/>\nThis is the utility function that returns a BitmapData object. This basically saves us a line of code and simplifies the call. Dimensions are capped at 2880 pixels for each side.<\/p>\n<p><strong>captureImage<\/strong><br \/>\nThis returns an ImageSnapshot object. That doesn&#8217;t get us all that much, but there are a few pretty cool things. We can pass <strong>captureImage<\/strong> a parameter that tells it how to encode the image. PNGEncoder and JPEGEncoder have been rolled into the framework now, so we can pass in either of those and it will encode the image as a PNG or a JPEG.<\/p>\n<p>Once we get the ImageSnapshot object that the static method returns then we can access the byte data of the encoded image with the <strong>data<\/strong> property. Then we could pass the JPEG or PNG encoded image to a server to save the file, or if you&#8217;re writing an AIR application you could save the file to the hard drive (or drop it onto the clipboard).<\/p>\n<p><strong>encodeImageAsBase64<\/strong><br \/>\nThis function takes an ImageSnapshot object and encodes it as a Base 64 string. Easy enough.<\/p>\n<p>So to go back to the sample code above, now we can generate a Base 64 encoded string like this:<\/p>\n<pre><code>\r\nprivate function getBase64String(component:UIComponent):String) {\r\n\tvar snapshot:ImageSnapshot = ImageSnapshot.captureImage(component);\r\n\tvar b64String:String = ImageSnapshot.encodeImageAsBase64(snapshot);\r\n\r\n\treturn b64String;\r\n}\r\n<\/code><\/pre>\n<p>and if you&#8217;re too good for three lines of code:<\/p>\n<pre><code>\r\nprivate function getBase64String(component:UIComponent):String) {\r\n\treturn ImageSnapshot.encodeImageAsBase64(ImageSnapshot.captureImage(component));\r\n}\r\n<\/code><\/pre>\n<p><strong>Bypassing the 2,880 pixel limit<\/strong><br \/>\nFlash Player has a limitation of only allowing a single bitmap object to have a max width or height of 2,880 pixels. I&#8217;ve never run into this problem, but I guess people with massive monitors can have a problem. The ImageSnapshot class does some fancy footwork in the <strong>captureImage<\/strong> method that allows you to generate an encoded JPEG or PNG snapshot that is larger than 2,880 pixels. Basically it creates multiple BitmapData objects and stitches them together to form one final ByteArray. Look at the source code for ImageSnapshot and check out the <strong>captureAll<\/strong> method.<\/p>\n<p>This gets around the 2,880 pixel limit, but there&#8217;s a 256 meg size limit on a single ByteArray object. From the documentation in the ImageSnapshot class: &#8220;This ByteArray is limited to around 256MB so scaled images with an area equivalent to about 8192&#215;8192 will result in out of memory errors.&#8221; <\/p>\n<p>So nothing groundbreaking here, but we get to save some boilerplate code that we used to have to write to generate a BitmapData object from a Flex UI object, or to generate the bytes of an encoded JPEG or PNG image. I&#8217;m guessing a big reason for Adobe including this in Flex 3 is to make it easier to save JPEG or PNG snapshots of charts in an AIR application.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are a few new graphics classes in the Flex 3 SDK that make it easier to create image snapshots of Flex UI components. The ImageSnapshot class provides some static methods for creating snapshots of components and encoding them as PNG or JPEG images. In addition to the ImageSnapshot class, we also get the PNGEncoder, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[2],"tags":[8],"class_list":["post-108","post","type-post","status-publish","format-standard","hentry","category-flex","tag-flex-3"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/posts\/108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/comments?post=108"}],"version-history":[{"count":0,"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/posts\/108\/revisions"}],"wp:attachment":[{"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/media?parent=108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/categories?post=108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dougmccune.com\/blog\/wp-json\/wp\/v2\/tags?post=108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}