BitmapDataUnlimited

I think everybody who has worked with BitmapData in ActionScript knows about the 2880 pixel limitation of the Flash Player. Fortunately Adobe decided to rise this limit in Flash Player 10, I think something about 4000px.

Last week I visited the Flash Forum Conference in Cologne which was btw. great. A lot of inspiration and cool stuff. In his presentation Mario Klingemann talked about »Andre Michelle’s Huge Bitmap hack«. The basic idea is to embed or load a large png and create a BitmapData by cloning it. The same approach can be found here.

The png thing didn’t work out for me so I tried the same thing with gif images which worked perfectly. The result is the BitmapDataUnlimited Class, a wrapper class to generate BitmapData objects in every size you want. You can even make a transparent BitmapData. It consists of a Gif Class which creates a gif image in the specified size on runtime. The performance is not too bad either. It takes less than 2s to create a 5000 x 5000px BitmapData.

Update
There is another limit in the Flashplayer I didn’t knew of or just didn’t remember. if a display object exceeds 8191 x 8191 it won’t be rendered. With BitmapDataUnlimited you can create even bigger Bitmaps which are getting rendered very well but keep in mind that this will take a lot of memory, e.g. a BitmapData with 12000 x 12000 px needs more than 1GB.

Update September 23rd, 2008
post about the 8191 limit

Update December 11th, 2008
BitmapData.draw() is limited to 4096px

example:

import com.formatlos.as3.lib.display.BitmapDataUnlimited;
import com.formatlos.as3.lib.display.events.BitmapDataUnlimitedEvent;
 
var bdu:BitmapDataUnlimited = new BitmapDataUnlimited();
bdu.addEventListener(BitmapDataUnlimitedEvent.COMPLETE, onBmpReady);
bdu.create(5000, 5000, true);
 
var hugeBmp : BitmapData;
 
function onBmpReady(event : BitmapDataUnlimitedEvent) : void
{
	hugeBmp = bdu.bitmapData;
	trace("BitmapData: w=" + hugeBmp.width + " h=" + hugeBmp.height);
}

files:

version 0.5
added clipRect to the draw() method like in the BitmapData.draw()
BitmapDataUnlimited_05.zip

version 0.4
added draw() method to bypass the 4096px limit of BitmapData.draw()
BitmapDataUnlimited_04.zip

version 0.3
added Error Event
BitmapDataUnlimited_03.zip

version 0.2
just a few minor changes
BitmapDataUnlimited_02.zip

version 0.1
BitmapDataUnlimited_01.zip



72 Responses (Add Your Comment)

  1. HI There,

    I have download loaded the code and when I input anything greater than 5000 it comes up with and error saying ” ArgumentError: Error #2015: Invalid BitmapData.
    at flash.display::BitmapData/clone()
    at com.formatlos.as3.lib.display::BitmapDataUnlimited/onLoaderComplete()”

    why is this

  2. thanks steven for posting this error. you were right in the first place it’s a memory issue, e.g. a BitmapData with 12000×12000 px needs more than 1GB of your ram.

  3. Hi,

    can we Load picture with size upper 2880 ? or just draw a rectangle ?

    My Loader never completed after load my picture :-(

    please help

  4. sure, you can load a picture greater than 2880px and draw it to the BitmapData but only jpg and gif files.

    For pngs with alpha channel the Loader doesn’t fire the COMPLETE Event if it exceeds the magic limit.

  5. I also tried the latest version and keep getting an error:

    ArgumentError: Error #2015: Invalid BitmapData.
    at flash.display::BitmapData/clone()

  6. actually it was just my computer not having enough memory, nothing wrong with the BitmapDataUnlimited class,

    it is working great

  7. When using this class to create a bitmap data from a loaded image, it will only display the image when scaled to a maximum 8154 pixel height.

    Interestingly, this value is identical to just loading the image into a new Bitmap created from a clone of the BitmapData of the loaded image.

    Making this class no improvement over cloning the regular BitmapData of a image.

    eg:
    var dummyBm:Bitmap = new Bitmap(dummyBitmap.bitmapData.clone());
    locator.addChild(dummyBm);
    locator.scaleX = 1.5562;
    locator.scaleY = 1.5562;

    where dummyBitmap is just
    created by casting:
    Bitmap(e.target.content)

    from the loaderComplete event of a image loader class.

    The height of this image scaled to those values is 8154.5 and displays ok, scale any higher and the image doesn’t display.
    And the same results happen getting a bitmapData from a BitmapUnlimited.

  8. sure, the result is the same, because you do the same! By scaling the resulting Bitmap you hit another limitation in the FlashPlayer (http://blog.formatlos.de/2008/09/23/beyond-8191px/). you have to draw the scaled image to the BitmapData created by BitmapDataUnlimited.

  9. Christophe!

    I had the same issue, until I realized that the BitmapDataUnlimited object (called bdu in the example on the top of the page) HAS TO BE a class member variable, or a static variable.

    Otherwise (when it is a local variable in a function) it is automatically destroyed when the execution leaves the variable’s scope (the function).

  10. Thanks so much! BitmapDataUnlimited makes the world a better place.

  11. Hi, can anyone let me know what I’m doing wrong! I’ve only been using Flash for 2 weeks, and all I want to do is create and save some big computer generated artwork!

    [SWF(width=800, height=200, backgroundColor=0xffffff, frameRate=31)]

    import com.formatlos.as3.lib.display.BitmapDataUnlimited;
    import com.formatlos.as3.lib.display.events.BitmapDataUnlimitedEvent;

    var bdu:BitmapDataUnlimited = new BitmapDataUnlimited();
    bdu.addEventListener(BitmapDataUnlimitedEvent.COMPLETE, onBmpReady);
    bdu.create(8000, 2000, true);

    var hugeBitmapData : BitmapData;

    function onBmpReady(event : BitmapDataUnlimitedEvent) : void
    {
    hugeBitmapData = bdu.bitmapData;
    trace(“BitmapDataUnlimited: w=” + hugeBitmapData.width + ” h=” + hugeBitmapData.height);

    //Create bitmap to draw on screen at scaled down size
    var big:Bitmap = addChild(new Bitmap(hugeBitmapData)) as Bitmap;
    big.width=800;
    big.height=200;

    //Sprite to draw into the bitmapdata
    var s:Sprite = new Sprite();
    s.graphics.beginFill(0xff0000);
    s.graphics.drawRect(0, 0, 8000, 100);
    s.graphics.endFill();

    hugeBitmapData.draw(s);

    }

    When the draw method is called, I don’t think that it’s using the draw method within BitmapDataUnlimited!

    Many thanks for any help.

    Eddie

  12. Hey!
    Thanks a lot for your precious class!
    I am having a problem though…
    I use the “draw()” method of your class ‘bdu.draw(printCanvas)’ and the printCanvas has dimensions:4075 x 5315.
    So, I see that in the final result there is an horizontal “line” or else you can say the canvas is divided in 2 places. I think this happens after the draw method reaches the 4096px limit for my canvas height…
    Is there something wrong or I am doing something wrong? Is there a way to fix this “division line”?
    Thanks in advance!

  13. johns problems weren’t related to BitmapDataUnlimited, so no worries the “draw()” method is working correctly

  14. @Eddie P.

    hey, with hugeBitmapData.draw(s); you’re using the native BitmapData.draw() mehod which doesn’t draw anything beyond 4096px. Use the draw method of BitmapDataUnlimited which bypasses this issue. in your case: bdu.draw(s)

  15. Thank you Martin, I’m getting there a bit at a time :-)

    I’ll drop a link to a few big example files when I’ve done the art part.

    Thanks again.

    Eddie

  16. Hello,Martin…
    I am really sorry but I thought the problem was solved for ever…well it didn’t.
    I have written a small test to check that something is wrong, I don’t know what..
    Please, try the following code and see the white lines.

  17. is possible to add the rectangle on the bdu draw function?

    I want to use only this draw method, but in odd pages I cant get the odd page..

    is possible?

  18. I would say yes, but I think it’s a not that easy. I’ll have a try when I have some time, maybe end of the week.

  19. @rui: added the clipRect

  20. Hi Martin again! I believe the _clipRect is not working.. how did you tried?

    Imagine this:
    bdu.create(4000, 2000);
    ….
    bdu.draw(myCanvas,null,null,new Rectangle(2000,0,2000,2000),false);

    and the result is not the expected.. I tried to workaround an solution but my math is in bad mood.

    Thank again,
    Rui

  21. hey rui, it’s working in my example (same syntax as your example above).
    Just to be sure: What’s the result und what did you expect?
    Basically the clip rectangle works a little bit different than one might expect.

  22. Hi, What i saw is that you have on the begin of the while cicle this:

    //use source if(x == 0 && y == 0){
    _bitmapData.draw(source_, matrix, colorTransform_, blendMode_, clip, smoothing_);
    }

    but if the “x” of the rectangle isn’t 0 this will never be used.. and it will pass to chunk right away

    I dont know if I explain well.. sorry bad english.

  23. yeah that’s right, this is just for performance issues … I could use the chunk for this as well. Try to explain, what you want to achieve, or even better: send some screenshots, drawings, code, whatever explains it best, otherwise it’s not possible for me to help

  24. I’ll mail you..

  25. I would like to load big pictures (max height 2048px and width can go up to 40 000+px).

    Is it possible with BitmapDataUnlimited ?
    Anyone have an exemple ?

  26. loading a huge picture is basically no problem, you can do it even without BitmapDataUnlimited. But you’ll get another problem if you want to display that pic, because DisplayObjects larger than 8191px won’t be displayed properly. see here

  27. I can load a big picture but it’s totally black when I try to get the copypixel zone that interested me to display.
    With a 8191px large it’s ok but 8192px (and more) it’s black.

    Basically it’s a fullscreen feature. So I never need more than a screen resolution in pixel.
    I think there’s a limitation at loading data.
    Project is in Flex.

    Do you think that just using a graphics can solve this problem ?

  28. This works beautifully. Thanks so much.

    I really made the rounds today trying to find a solution for FP9 bitmaps limitations. Mostly from reading the thread over at KP.

    Going to incorporate with some of this type of stuff to create some big fun images.

    Thanks again:)

  29. Hello Martin and thanks again for your great class!
    I wanted to say that in some pc’s the following line of your code is NOT executed at all!!

    “chunk = _bitmapData.clone();”

    The chunk is null so (!chunk) gives me “true” as a result and the clone() must execute!!

    I get NO errors, no messages, nothing!
    The program flow just stops silently…
    Has this something to do with the computer’s system memory? I am trying to clone a huuuuge bitmapData object with width = 6377 and height = 8739.
    Any ideas why the flow stops at this line??
    If I rename my variable to “Chuck” my program will think Norris is coming and it will allow the execution??? just joking :)

  30. yeah you are right, that’s a memory problem. bitmapData.clone() fails silently sometimes if there isn’t enough system memory left

  31. Thanks for your answer Martin. You think I can subtitute the clone() method with something else?
    Thanks again.

  32. unfortunately not

  33. nice work

  34. I need to save a canvas using either ImageSnapshot or PNGEncoder/JPGEncoder and this will be containing several other object inside of the canvas (yes I’m using Flex for this), and I need to know if this is possible. If I expand all of the children (which are dynamically added) to a bitmapDataUnlimited then do I make n bitmapDataUnlimited objects and thus crash my user’s browser since they will all be 12,000px x 3,000px? This will only occur at the end since they will be scaled from say… 600px x 150px. Any suggestions?

  35. I’m not completely sure what you are trying to do, maybe you can upload/mail an image which shows what you want to achieve, than it’s easier to understand.

    Why do you use such a big canvas if you scale it down afterwards anyway?

  36. what about applyFilters to the bitmapdata can this class handle that?

  37. sure … you basically get a native BitmapData with the complete built in functionality (more or less ;))

  38. k, I think I realized what I need. I’ve created my own version of Flex’s ImageCapture class and it works great. However, the end result is to scale a small displayobject to a larger bitmap version. This small display object has all of the child elements (minus user added bitmaps) added using embedded vectors and fonts. This all works fantastic up to 4100 pixels. Which is why I want to supplement the ImageSnapshot.captureAll’s BitmapData object for your BitmapDataUnlimited class. The problem arises when I need to implement a Matrix Transform to scale the source to the desired size (roughly 3000 x 12,000 px) which is about 3X what I’m able to output now. My question is if there is anyway to add a matrix transform argument to your draw() method? Thanks!

  39. Once I draw a huge bitmap with BDU, should I then “dispose” the data as I do with regular BitmapData class? If so, how do I call the dispose method?

    thanks,

    _stooge

  40. BitmapDataUnlimited is just a wrapper class to generate built-in BitmapData Objects, so you can dispose the generated BitmapData like a normal one (because it is a normal one)

  41. I am working on an app that lets you create signs. I am currently working with a 60″x24″ area at 120dpi(7200×2880). I have glow filters around some of the objects. I am having two problems. These problems only occur when i go to convert the bmd to any image format(bmp,png,jpg).

    1. I have to use a matrix with the properly calculated scale to get the bitmap to draw the correct size, even though the movieclip I am drawing is already the correct size.

    2.The glow filters stop drawing after the 4096th pixel, and the background turns transparent.

    I have been picking at this for the last two days and am having no luck.

  42. var bitmapData:BitmapData = bdu.bitmapData;
    var m:Matrix = new Matrix(scale,0,0,scale);
    bitmapData.draw(zone, m);

    works but is truncated.

    If I try :

    var bitmapData:BitmapData = bdu.bitmapData;
    var m:Matrix = new Matrix(scale,0,0,scale);
    bdu.draw(zone, m);

    i get this error :

    1067: Implicit coercion of a value of type flash.geom:Matrix to an unrelated type flash.geom:ColorTransform

  43. the BitmapDataUnlimited.draw() method doesn’t have the matrix parameter. I implemented
    the method just for bypassing the 4096px limit in BitmapData.draw()
    http://blog.formatlos.de/2008/12/11/bitmapdatadraw-is-limited-to-4096px/

    if you want to use a matrix for drawing you have to use the built-in function …
    bitmapData.draw();

    btw. you are welcome to implement the matrix parameter in BitmapDataUnlimited.draw() but I guess
    it’s not that easy or maybe not even possible

  44. Well i just tried some simple tuning and it looks like it is working for me :

    http://bin.cakephp.org/view/1976916705

  45. I am having an issue with my text being cut off. I have some large text that is about 5000 px wide and is offset about 500 px to the right. The text justs gets cut off at one point. I am using the BDU draw function so i am not sure what is going on.

  46. It seems to only happen when the text gets past a certain width.

  47. I was mistaken in were this problem lies. This only happens when a glow filter is on the textfield.

  48. You rock!! Thanks so much for this class.

  49. I’m trying use the bdu draw method on a Flex4 HTMLLoader object and am getting my image cropped. Most likely I am using the draw method incorrectly. The HTMLLoader contains html content that may easily be 15,000 pixels high (thus the need for this class). Before I draw, I resize the HTML component to the contentWidth & contentHeight (ex. 900×15,000).

    With the HTML component resized I call the draw method and pass the HTML component in. Then I pass the BitmapData to JPEGEncoder and write it to a jpg file (I never need to display the image, just write it).

    What I get is about the first 450 Y pixels of the HTML content and then 14,560 Y pixels of white. Here’s my latest attempt:

    var bdu:BitmapDataUnlimited = new BitmapDataUnlimited();
    var clipRect:Rectangle = new Rectangle(0,0,html.contentWidth*2,html.contentHeight*2);
    var _onBmpReady:Function
    bdu.addEventListener(BitmapDataUnlimitedEvent.COMPLETE, _onBmpReady = function (e: BitmapDataUnlimitedEvent):void{
    var hugeBitmapData : BitmapData;
    hugeBitmapData = bdu.bitmapData;
    bdu.draw(html,null,null,clipRect);
    /* my function to write the image */
    writeImage(bdu.bitmapData,’testimage.jpg’);
    });
    bdu.create(w,h,false,0xFFFFFF);

    Any help is appreciated

  50. ah, nevermind. I had a couple things going against me. First, the HTMLLoader resize wasn’t finishing in time to draw the content, so the ~450px was the original html component size. So I added a delay (resizing that component didn’t seem to fire a resize event). The delay worked, up to 2080px at which point the HTMLLoader hit its max height.

    Sow BDU works as described. Thanks anyway!

  51. What about JPEGs?

  52. Hi All,
    I am also facing the same issue, i wants to load the bitmapData with biger image (more than 5000 h/w) i have tried with BitmapDataUnlimited class, but using BitmapDataUnlimited class not able to load image of size 5000 height and width,
    As Abram menstioned
    bdu.draw(html,null,null,clipRect);
    i am not finding any Draw method in BitmapDataUnlimited clas

    kidnly guide me to fix this issue.
    Waiting for reply.

  53. BitmapDataUnlimited bdu = new BitmapDataUnlimited();
    bdu.addEventListener(BitmapDataUnlimitedEvent.COMPLETE, onBmpReady);
    bdu.create(4000,4000, true);

    function onBmpReady(event : BitmapDataUnlimitedEvent) : void
    {
    if(bdu != null){
    var hugeBitmapData:BitmapData = bdu.bitmapData;

    bdu.draw(_designArea,null,null,null,null,false);
    var quality:int = 115;
    var jpg:JPEGEncoder = new JPEGEncoder(quality);
    var byteArray:ByteArray = jpg.encode(bdu.bitmapData);
    }

    the above code work fine, but the pdf background color became blck color.

    kindly guide me if any body know the issue

  54. I wants to load image of more tahn 5000 height and width

    please let me know if you have any other solution

  55. hey Sangeeta,

    I don’t get your request … BitmapDataUnlimited is not a Class for loading big Images, it’s for creating huge Bitmaps on runtime. Anyways loading big images shouldn’t be a problem through the normal AS3 methods….

    background getting black: you create a transparent bitmap and encode a JPG out of it … JPGs don’t have an alpha channel so it gets black. Instead create a nontransparent bitmap (bdu.create(4000,4000, false, 0xff0000);)

  56. Hi Martin,

    Thanks for your reply.

    I have tried the solution which you provided for background color issue.
    bdu.create(4000,4000, false, 0xff0000);)

    when i make transferency = false
    i am getting the below error.

    Error #1502: A script has executed for longer than the default timeout period of 15 seconds.
    at mx.graphics.codec::JPEGEncoder/fDCTQuant()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\graphics\codec\JPEGEncoder.as:770]
    at mx.graphics.codec::JPEGEncoder/processDU()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\graphics\codec\JPEGEncoder.as:649]
    at mx.graphics.codec::JPEGEncoder/internalEncode()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\graphics\codec\JPEGEncoder.as:573]
    at mx.graphics.codec::JPEGEncoder/encode()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\graphics\codec\JPEGEncoder.as:330]
    at sdcomponent.windows::WinPrint/onBmpReady()[D:\Workspace_4.2\IPCC_Creation\ServiceDesigner\src\sdcomponent\windows\WinPrint.mxml:448]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at sdcomponent.as3.lib.display::BitmapDataUnlimited/dispatchEvent()[D:\Workspace_4.2\IPCC_Creation\ServiceDesigner\src\sdcomponent\as3\lib\display\BitmapDataUnlimited.as:249]
    at sdcomponent.as3.lib.display::BitmapDataUnlimited/dispatchComplete()[D:\Workspace_4.2\IPCC_Creation\ServiceDesigner\src\sdcomponent\as3\lib\display\BitmapDataUnlimited.as:238]
    at sdcomponent.as3.lib.display::BitmapDataUnlimited/onLoaderComplete()[D:\Workspace_4.2\IPCC_Creation\ServiceDesigner\src\sdcomponent\as3\lib\display\BitmapDataUnlimited.as:233]

  57. the error has nothing to do with BitmapDataUnlimited, it just tells you that it takes very long to encode the JPG … one solution is to change the minimum script execution time (there is a compiler argument in the flex sdk for that) or you use another JPG encoder, the one your are using is damn slow. just search in google and you’ll find at least 5 better ones.

  58. Thanks Martin
    my request is to load the huge bitmap (more than 8000 pixel of hieght and width)

    BitmapDataUnlimited is able to create the bitmap of max size 4096 pixel,

    kinldy guide me to create huge bitmap.

  59. Sorry I actually don’t get what you want to do! Like written above, you can create Bitmaps of any size with BitmapDataUnlimited but it’s NOT for loading images.

  60. using bitmapDataUnlimited i am able to create bitmap of only 4000 pixel of height and width. i need to create bitmap of 8000 pixels of height and width.

    I fixed the Background color issue thanks for helping me.

  61. Hi Martin,

    Thanks for your help, i found the error in JPEGEncoder,
    in google i am not finding any other encoder.

    it will be great help if you information of any alternative way for JPEGEncoder

    Thanks

  62. great job. Thank you.

  63. Martin, we are using your class in our multi-runtime upload solution ;) Recently after people have upgraded to Flash Player 11, our uploader started to hang. Problem investigation finally narrowed to BitmapDataUnlimited’s random inability to dispatch COMPLETE event. In case you wonder, this is what we did to overcome it: https://github.com/moxiecode/plupload/commit/003f9413b0fd5bc6290f65bb3741d640e46c10b1

    What was the logic behind direct implementation of the IEventDispatcher interface anyway?

    By the way Flash Player 11 is said to not have the limit anymore (http://www.adobe.com/products/flashplayer/features.html#categorylens_featureset_6), whatever that means.

  64. Hi,i am an artist using flash to creat artwork.I would like to export a png as big as possible ( 12 000 would be great) but i don’t understand anything about coding or scripting.If someone can help me it would be great.
    Cyril
    My email : beuda@cyrilcorallo.com

Trackbacks:

Leave a Reply

Formatting: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Other Entries

About

Martin Rädlinger is an Interactive Developer & Designer. He specializes in interactive coding predominantly with ActionScript, but every new challenge is welcome. If you like his work feel free to get in touch with him. At the moment he's available for freelance work.

Contact

Martin Rädlinger
mail: mr [at] formatlos.de
web: www.formatlos.de
xing: Martin Rädlinger
linkedin: Martin Rädlinger
skype: martinraedlinger