I'm fading out a Bitmap in AS3 by repeatedly applying a ColorTransform every frame to its BitmapData;
_bitmap.colorTransform(_bitmap.rect, new ColorTransform(1, 1, 1, .9, 0, 0, 0, 1));
When applying the apparent reverse to fade it back in I get a discoloured image.
_bitmap.colorTransform(_bitmap.rect, new ColorTransform(1, 1, 1, 1.1, 0, 0, 0, 1));
The problem appears to occur only to fully faded-out images. If I only go part way it is recoverable.
fading out:
(source: ggpht.com)
faded back
(source: ggpht.com)
I would guess that this is due to destructively changing the bitmap data. Try retaining the original data, and applying your transform fresh on every frame, or alternatively wrapping the bitmap in a Sprite and applying the color transform onto that instead.
Related
I'm using SkiaSharp to draw text onto a canvas that I've already drawn a background image onto.
It's working fine when just drawing regular text, but I want to add an embossed effect to the text. To do this, I've tried using SKImageFilter.CreateDistantLitDiffuse, which gives the right effect, but the problem is that it fills the background with the light color (also influenced by the diffuse lighting constant). This ends up obliterating my background.
The image below shows the text with the embossed effect, but as you can see, it's background is not transparent. Also, the text should be white, but it's colour has been changed by the filter.
The image filter I'm using is:
fontPaint.ImageFilter = SKImageFilter.CreateDistantLitDiffuse(
new SKPoint3(2, 3, 4),
SKColors.Transparent,
-3,
(float)0.2)
canvas.DrawText(element.Value, coords, fontPaint);
I've seen examples of embossing by drawing the text twice with an offset, but this doesn't give the desired effect.
Any ideas of how I can work-around this issue with the image filter filling in the background?
I managed to get pretty close to what I'm wanting by using CreateMatrixConvolution.
float[] kernel = new float[25]
{
-1, 0, -.5f, 0, 0,
0, -1, -.5f, 0, 0,
-.5f, -.5f, 1.5f, .5f, .5f,
0, 0, .5f, 1, 0,
0, 0, .5f, 0 , 1
};
fontPaint.ImageFilter = SKImageFilter.CreateMatrixConvolution(
new SKSizeI(5,5), kernel, 1f, 1f, new SKPointI(1, 1),
SKMatrixConvolutionTileMode.Clamp, true);
This gives me the following result:
It's not exactly the same as what I was wanting, which is more like this:
But it's pretty close. If anyone has any suggestions on how I can get it closer to the example above, I'd love to hear it. Possibly tweaking the kernel might work, but I've already spent ages playing around with variations.
I have a car image and i need to blink effect on its tyres and glasses with the help of canvas.
For that i used canvas draw image function and it is working fine but problem is when i hover on tyre tab tyres should be blink and when i hover on glass tab glasses should be blink but it happens only once.
Like if i hover first on tyre tab then it blinks using blink function but when i mouseout and hover on glass tab this time also blink effect but on tyres(on first hover tab) not on glasses, because in my code it draw image once until that has different functions for both.
I searched many answers on online but unable to achieve that. I already used clearRect function but i think by this my first image is not removing.
I am creating an image with this code:
context.clearRect(0, 0, canvas.width, canvas.height);
context.save();
context.drawImage(mask, 0, 0); //mask
context.fillStyle= ""; //fill color style
context.fillStyle= "#6600ee"; //fill color style
context.fillRect(0, 0, canvas.width, canvas.height);
context.globalCompositeOperation = "destination-atop";
context.drawImage(shadow, 0, 0); //shadow
context.drawImage(glossreflection, 0, 0); //reflection
context.restore();
and try to remove on mouse out By:
context.clearRect(0, 0, canvas.width, canvas.height);
I put alerts also that all are working but i am not understanding about this issue.
I can't figure how to make drawImage work... It just does nothing (except that it throws an exception with an undefined description) :
layerCtx.globalAlpha = 0,2; // same thing with this line commented
layerCtx.drawImage(cvs, 0 , 0);
I have 2 canvas, one is a layer and the other is for drawing using the mouse. I want to save what the user has drawn on the first canvas to the layer and apply opacity...
I won't give you all the code but you have to know that the following code works :
layerCtx.putImageData(ctx.getImageData(0, 0, 800, 500), 0, 0);
but I can't use opacity with the previous, so as it is advised in other stackoverflow.com related questions, I'd like to use drawImage with a canvas element.
ctx is the context for my canvas cvs,
layerCtx is the context fort my canvas layer
You're gonna hate this: You wrote 0,2 instead of 0.2. That's why it isn't working.
I know a comma is used as a decimal in a lot of European countries, but 0.2 is what its gotta be for this.
Working example to check your code by:
http://jsfiddle.net/zC4Wh/
I have a drawn a Circle Shape in AS3. I want to render the Circle into a Bitmap with nice/antialiased Edges. Because I want it to work on Mobile Devices (Air Apps are limited to stagequality = low) I need a workaround. Any custom shape to bitmap renderer available?
Not sure this solution would work for Air Mobile Apps, but worth looking into.
Didier Brun # ByteArray.org posted an API used to draw primitive shapes (as BitmapData, not from Vector draw calls either), which might help you get your circles to draw the way you want.
http://www.bytearray.org/?p=67
Code Snippet (from that URL):
// create the BitmapData to work on
var pixels:Raster = new Raster(320, 240, true);
// draw stuff
pixels.drawRoundRect( new Rectangle ( 20, 20, 200, 100), 18, 0xFF00FFFF );
pixels.drawRect( new Rectangle ( 70, 70, 100, 100 ), 0xFF009900 );
pixels.filledTri( 40, 40, 80, 110, 50, 30, 0xFF998811 );
pixels.aaCircle(100, 100, 40, 0x77AA88 );
pixels.circle(40, 40, 30, 0xFF000000);
pixels.line(10, 10, 60, 80, 0xFF000000 );
// show it
addChild ( new Bitmap ( pixels ) );
Hopefully the library / source code is compatible for your project! :)
Have you consider using the drawWithQuality method?
The drawWithQuality() method works exactly like the draw() method, but instead of using the Stage.quality property to determine the quality of vector rendering, you specify the quality parameter to the drawWithQuality() method.
StageQuality.LOW is going to make your bitmap quality low if you're using draw() because the source will be of low quality whether it's on the DisplayList or not.
I don't think there's a way around this.. You'll have to load in circle graphics or import images to use.
If it is only something simple as circle, you can synthesize smooth image pixel by pixel. Create BitmapData of sufficient size and loop on pixels. On every pixel, compute distance from center - if it less than circle radius - half of pixel diagonal, set pixel to circle color. If it greater than circle radius + half of pixel diagonal, call setPixel32(x, y, 0).
Pixels that won't pass both conditions are near the edge - to do exact antialiasing, you must compute how much of pixel is covered by circle. Maybe you can find some convincing simple approximation. Good luck!
Update:
OK, I think I can remember simpler approach... You can draw your circle or any shapes two times bigger than they should be, then draw that bitmap into another with scale 0.5 (set through matrix) and smoothing on. That would be supersampling 4x. If stage quality doesn't affect bitmap smoothing, it should work.
In ActionScript 3 bitmap is created from BitmapData, so you need to create if first with
_bitmapData = new BitmapData(..
BitmapData has method draw, passing DisplayObject instance (Sprite, MovieClip or other) to it as parameter, will draw it's content into BitmapData.
Example:
var c:Sprite = new Sprite();
c.graphics.clear();
c.graphics.beginFill(0x00FF00, 0.5);
c.graphics.lineStyle(2.0);
c.graphics.drawRectangle(0, 0, 100, 100);
c.graphics.endFill();
var bd:BitmapData = new BitmapData(100, 100);
bd.draw(c);
var bitmap:Bitmap = new Bitmap(bd);
If you try the following code:
g.beginFill(0xFF0000);
g.drawRect(0, 0, 50, 50);
g.drawRect(25, 25, 50, 50);
g.endFill();
You would think that it would draw 2 overlapping red squares. However, it doesn't - it draws two red squares except for the overlapping area which is now completely transparent.
Any idea how to get around this?
Post-Accepted-Answer:
Thanks Christophe Herreman! Changing the code to:
g.beginFill(0xFF0000);
g.drawRect(0, 0, 50, 50);
g.endFill();
g.beginFill(0xFF0000);
g.drawRect(25, 25, 50, 50);
g.endFill();
Worked just as intended! I'd be interested to know if this was "intended behaviour" or an actual bug though!
All calls prior to endFill() will just store the points of the polygon you want to draw and connect them once endFill() is called. Since the code in your example has an overlapping part, it will be filtered out when the actual lines of the polygon are drawn. I actually don't know if this is intended behavior of the Flash player or a bug.
To solve this, just add a new call to beginFill() before drawing the new rectangle.
g.beginFill(0xFF0000);
g.drawRect(0, 0, 50, 50);
g.beginFill(0xFF0000);
g.drawRect(25, 25, 50, 50);
g.endFill();
Wouldn't you need to create a second graphic object to apply the second fill to? I bet you really have one strangely shaped graphic object instead of two intersecting rectangles.