PDA

View Full Version : BitmapData has no graphics object? Senocular would you read this please



Sirisian
July 3rd, 2007, 03:01 PM
//Following is for senocular, since I realized he doesn't have PM on or something.
I know you work for Adobe. I was wondering if you had any influence to adding things to to the AS3 framework. I noticed something about the BitmapData object. It doesn't have any form of the graphics object that the derived DisplayObjects have. This means that when I wish to render a polygon region from one BitmapData to another I am forced to create a Shape object and render to that then draw it to my desired BitmapData.

I was wondering why no direct method for rendering a polygon region from one BitmapData to another exists. Or did they find that it makes sense for people to allocate a whole new object just to render?

I made a post about this a while ago, but no one had much experience in the area I guess.

I was hoping you could clarify my ideas and maybe help to get this implemented in a future version of the flash.

Thanks for you time.

TheCanadian
July 3rd, 2007, 07:24 PM
Well for starters, BitmapData extends from Object (which doesn't have a graphics property). Second, DisplayObject doesn't define the graphics property, Sprite and Shape do.

Does copyPixels not work? I sort of don't understand what you're trying to do.

senocular
July 3rd, 2007, 07:28 PM
BitmapData is just data. To put this data to the screen, you would use a Bitmap instance. The Bitmap class extends DisplayObject and can be added to the display list.

These classes are separated because a) you may want to work with just the data and not have to worry about having the extra overhead that comes associated with display objects and b) you can share a single BitmapData instance between multiple Bitmap instances maintaining separate objects but reducing redundancy in data (saving memory).

Does that clear things up a bit?

Sirisian
July 3rd, 2007, 08:37 PM
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Bitmap.html

Yeah I've researched this heavily. The Bitmap object, while being derived from DisplayObject, does not have access to a graphics object, so it's not possible to render from one BitmapData object to another.

I think you might have misunderstood what I'm saying. If I wanted to render the image:
http://www.sirisian.templarian.com/pictures/bmptobmp1.png
using this polygon region of said image:
(70,50)
(170,100)
(20,150)
To this image:
http://www.sirisian.templarian.com/pictures/bmptobmp2.png

Ideally you'd end up with:
http://www.sirisian.templarian.com/pictures/bmptobmp3.png

In AS3 in order to perform this kind of BitmapData to BitmapData rendering (since the draw command can only perform rectangle cropping) you have to put the data into a DisplayObject. This is fine for small projects. Since all you do is:


var b:BitmapData = new BitmapData(200,200, false, 0x000000);
//load data into b
var s:Shape = new Shape();
var mat:Matrix = //matrix here
s.graphics.beginBitmapFill(b, mat);
s.graphics.moveTo(70,50);
s.graphics.lineTo(170,100);
s.graphics.lineTo(20,150);
s.graphics.lineTo(70, 50);
s.graphics.endFill();
var b2:BitmapData = new BitmapData(200,200, false, 0x000000);
//load image data into b2
var mat2:Matrix = //matrix stuff here
b2.draw(s, mat2);I mean sure it works, but being able to do:

var b:BitmapData = new BitmapData(200,200, false, 0x000000);
//Load image data into b
var b2:BitmapData = new BitmapData(200,200, false, 0x000000);
//Load image data into b2
var bmp:Bitmap = new Bitmap(b2);
var mat:Matrix = //matrix here
bmp.graphics.beginBitmapFill(b, mat);
bmp.graphics.moveTo(70,50);
bmp.graphics.lineTo(170,100);
bmp.graphics.lineTo(20,150);
bmp.graphics.lineTo(70, 50);
bmp.graphics.endFill();Gets rid of having to allocate and deal with another buffer of data.

I hope that makes it clear as to what I wish was available. This would speed up a lot of the work I've been doing by elimination the extra buffer. I mean it's not too inconvenient, but there's a better option available I hope you see.

Dazzer
July 3rd, 2007, 09:44 PM
Might be possible if you manipulated things at byte level using byteArrays.

Though I'm no expert in image manipulation.

CarlLooper
July 3rd, 2007, 10:02 PM
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Bitmap.html
I mean sure it works, but being able to do:

var b:BitmapData = new BitmapData(200,200, false, 0x000000);
//Load image data into b
var b2:BitmapData = new BitmapData(200,200, false, 0x000000);
//Load image data into b2
var bmp:Bitmap = new Bitmap(b2);
var mat:Matrix = //matrix here
bmp.graphics.beginBitmapFill(b, mat);
bmp.graphics.moveTo(70,50);
bmp.graphics.lineTo(170,100);
bmp.graphics.lineTo(20,150);
bmp.graphics.lineTo(70, 50);
bmp.graphics.endFill();Gets rid of having to allocate and deal with another buffer of data.

I hope that makes it clear as to what I wish was available. This would speed up a lot of the work I've been doing by elimination the extra buffer. I mean it's not too inconvenient, but there's a better option available I hope you see.

The Drawing API (graphics routines), as provided through a Shape object, are functions that repeatedly draw graphics to the Shape object (ie. on every frame). The interface implied by your pseudocode:

bmp.graphics.whatever()

is that you would have the graphics renderer update your BitmapData object on a per frame basis - which is obviously not what you want. You want a one off render. So you need something other than what the graphics renderer does. But you want to use the graphics renderer to do it.

So you create a Shape object, have the graphics renderer draw to such, and then use the BitmapData function to "grab" it.

There is no internal overhead in doing this. A Shape object doesn't occupy anywhere near the ammount of memory occupied by your BitmapData object. It only stores the instructions necessary to redraw the display (ie. as embodied by your code).

But the interface you are proposing would occupy far more memory - not only the instructions for doing the drawing but the bitmap necessary to store the drawing.

To keep things optimal it is better to have these separated. In this way you get to choose when you want graphics just drawn to the display (ie. drawing instructions only) or when you want them (also) drawn to a bitmap.

Carl

Sirisian
July 3rd, 2007, 11:14 PM
Good idea, however I update my rendering every frame, so having the drawing instruction in said Shape object has no advantages. You might be onto something though with how the drawing stuff is saved into the shape object. I was under the impression it had it's own buffer. But if it just holds the instructions and references to objects then that is a totally different case.

CarlLooper
July 6th, 2007, 01:11 AM
Good idea, however I update my rendering every frame, so having the drawing instruction in said Shape object has no advantages. You might be onto something though with how the drawing stuff is saved into the shape object. I was under the impression it had it's own buffer. But if it just holds the instructions and references to objects then that is a totally different case.

Yes, the original brainwave behind the invention of Flash was the use of vector graphics - rather than bitmaps - for websites. Your swf file need only contain the instructions necessary to draw your graphics rather than contain the graphics themselves.

At runtime a display buffer is created (but only one) Your instructions basically draw into this display - but only if your Shape object is actually on the display list. But keep in mind that the drawn graphics only have a momentary existence within the display buffer. At each frame your graphics are actually redrawn - not from a bitmap - but from your instructions! Shape objects never take up any more memory than that necessary to store the drawing instructions. That's the whole idea behind such objects - the whole idea behind the success of Flash - from when it first began life.

Now if you really want to do so - in order to implement the interface you're proposing - you can subclass the BitmapData class, and add your own "graphics" class - which wraps all the drawing API functionality you want, ie. you can create your own BitmapData class with drawing functions that can draw into a bitmap.

As mentioned, there will be no overhead in doing this. All you will be doing is creating your own way of writing your code, - which is absolutely a fine thing to do. You will then be able to write:

import BitmapDataEx; // your own class
...
myObject = new BitmapDataEx();
myObject.graphics.clear();
myObject.graphics.lineStyle(...);

Now you might ask why Actionscript doesn't already provide this.

However, there are an infinite number of things that ActionScript doesn't provide - if it was to provide them all it would make reading the documentation a very long process.

But what it does provide is the building blocks for you to create an infinite number of things - well - I'm exaggerating of course, but you get the idea.

good luck
Carl

CarlLooper
July 6th, 2007, 02:57 AM
Something like this:

class MyBitmapData extends BitmapData
{
public var graphics:MyGraphics;
public function MyBitmapData()
{
graphics = new MyGraphics(this);
}
}

class MyGraphics
{
private var shape:Shape;
private var bmd:MyBitmapData;

public function MyGraphics(bmd:MyBitmapData)
{
shape = new Shape();
}

// wrap all graphics command, eg. clear would be
public function clear()
{
shape.graphics.clear();
}

// you'll need one additional function which draws the shape to a bitmap:
public function draw()
{
bmd.draw(shape,...);
}
}

CarlLooper
July 6th, 2007, 03:30 AM
Keep in mind that all the above does is change the way you might write the code. Indeed the way I've written the above could very well be slower than if you had just created a Shape object on it's own and referenced such in a bimapdata.draw call.

This is because the compiler could very well optimise graphics calls where they are otherwise directly grouped within a Shape. I don't know, but it wouldn't surprise me if this was the case. Both Shape and Sprite are wrappers around the Graphics class, and the Graphics class is not instantiable, suggesting that Shape and Sprite are necessary interfaces to otherwise optimised compilation of the graphics calls therein.

Being wrapped the way I've done it means that each graphics call is being made through an additional indirection from your custom class - which in itself would incur a slight overhead. But if you add to this the possibility that Shape and Sprite compilation may involve compile time optimisation - then you will lose out on this extra optimisation.

If the above is true, and performance over code writing ease is more important to you (as it would seem) than you can just revert to the traditional way:

Create a Shape object. Code it's drawing instructions. And then use bitmapdata.draw to exploit it.

Carl

CarlLooper
July 6th, 2007, 05:16 AM
Ok, attached is a demo of the classes you are after. And here is some demo code using such:

import BitmapDataEx;

var bmd = new BitmapDataEx(100, 100, true);

bmd.graphics.clear();
bmd.graphics.lineStyle(1,0xFFFF0000);
bmd.graphics.drawCircle(50,50,40);
bmd.graphics.draw();

var bitmap = new Bitmap(bmd);

addChild(bitmap);

CarlLooper
July 7th, 2007, 07:39 PM
A full implementation is at this thread:

http://www.kirupa.com/forum/showthread.php?t=267587

Note that all the class does is provide encapsulation of what you might otherwise have to write yourself.

There is nothing experimental going on here.

There is no performance benefit.

Carl

Sirisian
July 7th, 2007, 09:52 PM
I already have a wrapper class built into my engine. Thanks anyway. I guess it's not really a problem seeing as flash was designed for vector graphics. I don't use vector graphics since I use pixel art, so I guess it doesn't really matter.