how to turn an existing color image into a black-white image? - actionscript-3

What diffrent approaches exists out there in actionscript 3.0 ?
I found this library: mojocolors
But this is more for graphics-color I guess…
Thx

var n:Number = 1/3;
var matrix:Array = [n,n,n,0,0,
n,n,n,0,0,
n,n,n,0,0,
0,0,0,1,0];
var cmf:ColorMatrixFilter = new ColorMatrixFilter(matrix);
bitmap.filters = [cmf];

In general, assuming that you start with an RGB image, you convert it to HSI color space and use the I (intensity) component.

To convert an image to grayscale, you need to iterate over each pixel in the image buffer and average the R, G and B component into one entity, then duplicate it three times to get the new color. pseudo-code (assuming 8bit color):
for each pixel in buffer:
pixel.rgb = ((pixel.red + pixel.green + pixel.blue) / 3) * 0x010101;
I am sure you can do something with Adobe's PixelBender to achieve this faster.

Apply the filter created by this method to the DisplayObject that contains the image you want in black and white:
public static function createBlackAndWhiteFilter():ColorMatrixFilter {
var rLum:Number = 0.2225;
var gLum:Number = 0.7169;
var bLum:Number = 0.0606;
var bwMatrix:Array = [rLum, gLum, bLum, 0, 0, rLum, gLum, bLum, 0, 0, rLum, gLum, bLum, 0, 0, 0, 0, 0, 1, 0];
return new ColorMatrixFilter(bwMatrix);
}//createBlackAndWhiteFilter

Related

How to flip a card with cocos2d-x

I need to flip a card to see its back, then side and then front gradually with animation like this: https://www.youtube.com/watch?v=te0Je0y4zU0 . How I can do this with cocos2d-x? I have took a look on OrbitCamera and RotateBy in 3D tests. They are very close to the one I want to, the only problem is that when the sprite turns around I see not the back (as at should be another texture, but the same spite from back camera). I understand that I should use 2 sprites to get the effect, but how I should do that, I don't know. Should I position 2 sprite with different Z order? Please advice.
Try this:
float duration = 2.0f;
auto actionBy = RotateBy::create(duration / 2, Vec3(0, 90, 0));
backCard->runAction(RotateBy::create(0, Vec3(0, 90, 0)));
frontCard->runAction( Sequence::create(
actionBy,
CallFunc::create([backCard, actionBy](){backCard->runAction(actionBy);}),
nullptr)
you need to simply do this :
CCRotateTo *act1= CCRotateTo::create(0.5, -180);
CCRotateTo *act2= CCRotateTo::create(1.0, 180);
CCSequence* act3 = CCSequence::create(act1,act2,NULL);
sprite->runAction(act3);
you should view https://www.youtube.com/watch?v=Q4fJrMvZVhI
same with cocos2dx using javascript.
reveal: function (pIsFaceUp) {
let self = this;
let timeFlip =0.5;
let callFunc = cc.callFunc(function () {
self.cardBG.spriteFrame = pIsFaceUp ? self.texFrontBG : self.texBackBG;
self.point.node.active = pIsFaceUp;
self.suit.node.active = pIsFaceUp;
self.mainPic.node.active = pIsFaceUp;
if(!pIsFaceUp)
self.node.skewY=135;
else
self.node.skewY=45;
});
if(!pIsFaceUp)
{
self.node.skewY=0;
let action = cc.skewBy(timeFlip/2,0,45);
let action2 = cc.skewTo(timeFlip/2,0,180);
self.node.runAction(cc.sequence(action,callFunc,action2));
}else
{
self.node.skewY=180;
let action = cc.skewBy(timeFlip/2,0,-45);
let action2 = cc.skewTo(timeFlip/2,0,0);
self.node.runAction(cc.sequence(action,callFunc,action2));
}
},
Use 2 Sprites: spriteFront, spriteBack
init (show spriteBack at first):
scale spriteFront to (0, 1) (scale X to 0, while keeping scale Y to 1)
scale spriteBack to (1, 1)
flip animation:
scale spriteBack to (0, 1)
after the animation,
scale spriteFront to (1, 1)
float fDuration = 0.8f;
CCArray* pArray = CCArray::create();
pArray->addObject(CCScaleTo::create(fDuration/2, 0, 1));
pArray->addObject(CCTargetedAction::create(spriteFront, CCScaleTo::create(fDuration/2, 1)));
CCFiniteTimeAction* flipCardAnimation = CCSequence::create(pArray);
spriteBack->runAction(flipCardAnimation);

AS3 Alchemy and ByteArray.setPixels() issue. "bytearray.position = 0" doesn't work

I'm encoding the BitmapData using this method:
http://www.websector.de/blog/2009/06/21/speed-up-jpeg-encoding-using-alchemy/
Code example:
var loader:CLibInit = new CLibInit;
as3_jpeg_wrapper = loader.init();
var baSource: ByteArray = bitmapData.clone().getPixels( new Rectangle( 0, 0, WIDTH, HEIGHT) );
var baAlchmey: ByteArray = as3_jpeg_wrapper.write_jpeg_file(baSource, WIDTH, HEIGHT, 3, 2, quality);
After encoding i need to convert resulting byteArray back to BitmapData. I'm using setPixels() method.
For example:
baAlchemy.position = 0;
var bd:BitmapData = new BitmapData(width, height);
bd.setPixels(rect, baAlchemy);
And i get "Error #2030: End of file was encountered?".
Can anybody help me?
It looks like you are trying to pass the bytes of a compressed JPEG to setPixels().
However, according to the documentation setPixels(), it the second argument to be:
A ByteArray object that consists of 32-bit unmultiplied pixel values to be used in the rectangular region
Or, in other words, an uncompressed image. You will first have to decompress your image, before you can render it into a BitmapData

HTML5: Inverse text-color on canvas

I want to draw text on a canvas in the inverse color of the background (to make sure the text is readible no matter the background color). I believe in oldskool bitblt-ing, this was an XOR operation.
How to do this?
Update: most of the newer browsers now support the blending mode "difference" which can achieve the same result.
context.globalCompositeOperation = "difference";
Updated demo.
Old answer:
One should think that the XOR mode for composition would do this, but unfortunately canvas' XOR only XORs the alpha bits.
By applying the following code we can however receive a result such as this:
You can make an extension to the canvas like this:
CanvasRenderingContext2D.prototype.fillInversedText =
function(txt, x, y) {
//code - see below
}
Now you can call it on the context as the normal fillText, but with a slight change:
ctx.fillInversedText(txt, x, y);
For this to work we do the following first - measure text. Currently we can only calculate width of text and then assume the height. This may or may not work well as fonts can be very tall and so forth. Luckily this will change in the future, but for now:
var tw = this.measureText(txt).width;
var th = parseInt(ctx.font, '10');
th = (th === 0) ? 10 : th; //assume default if no font and size is set
Next thing we need to do is to setup an off-screen canvas to draw the text we want ot invert:
var co = document.createElement('canvas');
co.width = tw;
co.height = th;
Then draw the actual text. Color does not matter as we are only interested in the alpha channel for this canvas:
var octx = co.getContext('2d');
octx.font = this.font;
octx.textBaseline = 'top';
octx.fillText(txt, 0, 0);
Then we extract the pixel buffers for the area we want to draw the inverted text as well as all the pixels for the off-screen canvas which now contains our text:
var ddata = this.getImageData(x, y, tw, th);
var sdata = octx.getImageData(0, 0, tw, th);
var dd = ddata.data; //cache for increased speed
var ds = sdata.data;
var len = ds.length;
And then we invert each pixel where alpha channel for pixel is greater than 0.
for (var i = 0; i < len; i += 4) {
if (ds[i + 3] > 0) {
dd[i] = 255 - dd[i];
dd[i + 1] = 255 - dd[i + 1];
dd[i + 2] = 255 - dd[i + 2];
}
}
Finally put back the inverted image:
this.putImageData(ddata, x, y);
This may seem as a lot of operations, but it goes pretty fast.
Demo (warning if you are sensitive to flicker)
(the psychedelic background is just to have some variations as fiddle needs external images and most are prevented by CORS when we use pixel manipulation).
I've removed my old answer, as it did not solve the question. As of recently, there are new globalCompositeOperations that do all kinds of great things. I've created an example that shows how to obtain inverted text. In case that link breaks, the method is essentially this:
ctx.globalCompositeOperation = "difference";
ctx.fillStyle = "white";
//draw inverted things here
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

reproduce GIF-like image in canvas

I need an image that is drawn in html5 canvas to look like a gif image (make it have 256 colors only). Is there any function that makes canvas have only 256 or less colors and make it convert images that are placed into it have only 256 or less colors?
Thanks in advance
I'm not sure there is such a method in the 2D context of the canvas.
However, it does not seem to be very complicate. 256 colors = 8 levels of red, green and blue.
So you can convert the image to respect this rule.
To achieve this, you need to change the color of each pixels.
Whad I'd do is to create a temporary canvas to manipulate the image, something like this (not tested):
//create copy of the image in a temporary context
this.tmpCanvas = document.createElement('canvas');
this.tmpCanvas.width = myIMage.width;
this.tmpCanvas.height = myIMage.height;
var scaledContext = this.tmpCanvas.getContext('2d');
scaledContext.drawImage(myIMage, 0, 0, myIMage.width, myIMage.height, 0, 0, myIMage.width, myIMage.height);
//get image data
imageData = scaledContext.getImageData(0, 0, myIMage.width, myIMage.height);
//loop over copied image date and modifiy pixels value
for(var i = 0; i < imageData.length; i += 4) { // 4 because RGBA
//red component
imageData[i] = Math.round(imageData[i] / 64);
//green component
imageData[i + 1] = Math.round(imageData[i+1] / 64);
//blue component
imageData[i + 2] = Math.round(imageData[i+2] / 64);
}
scaledContext.putImageData(imageData, 0, 0);
I didn't test this code, but the idea is there

as3 wipe fade alpha using tween

Is it possible to fade the alpha with a soft wipe transition using as3 tween?
I thought maybe http://www.greensock.com might have the answer but I have found nothing. I would like the image to slowly fade away from one side to the other. A soft dissolve.
I thought maybe its possible using a mask but I don't think masks accept alphas otherwise it could be done that way.
Actually masks allow alphas. It's kind of a hack. You should try writing this in code:
maskMC.cacheAsBitmap = true;
objMC.cacheAsBitmap = true;
objMC.mask = maskMC;
Where objMC is your animated MovieClip and maskMC is your Mask that contains a gradient shape with transparency. See an example here: Link
You can also achieve this effect using Greensock. Code would look like this:
TweenLite.to(objMC, 1, {"alpha":0, "x":objMC.x + 10});
When using TweenLite, you need to provide object to animate, duration of animation and an instance of an Object class (that's stuff we write between curly braces). This instance contains all the values we want to change gradually.
You can accomplish this by using the ALPHA blendmode.
Make a shape that has a gradient whose alpha goes from full to nothing, then make it's blend mode ALPHA, put it in the same container as your item you wish to mask.
Then set the container blendmode to LAYER
Psuedo Code:
container.blendMode = BlendMode.LAYER; //container holds both the mask and the thing you want masked
maskObj.blendMode = BlendMode.ALPHA;
drawMaskGradients();
Here is a function I've used in the past to create said mask via code: (itemContainer is the object I'm masking)
You could however do this all in the Flash IDE using design tools.
softMaskSprite = new Sprite();
this.blendMode = BlendMode.LAYER;
softMaskSprite.blendMode = BlendMode.ALPHA;
softMaskSprite.mouseChildren = false;
softMaskSprite.mouseEnabled = false;
this.addChildAt(softMaskSprite,this.getChildIndex(itemContainer)+1);
//Create Sides
var top:Shape = new Shape();
var matr:Matrix = new Matrix();
matr.createGradientBox(areaWidth + (softMaskWidth * 2), softMaskWidth, 90 * (Math.PI / 180), 0, 0);
top.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x0000FF], [0,1], [0,255], matr, SpreadMethod.PAD);
top.graphics.drawRect(0, 0, areaWidth + (softMaskWidth * 2), softMaskWidth);
top.graphics.endFill();
top.x = softMaskWidth * -1;
top.y = softMaskWidth * -1;
softMaskSprite.addChild(top);
//BOTTOM
var bottom:Shape = new Shape();
matr = new Matrix();
matr.createGradientBox(areaWidth + (softMaskWidth * 2), softMaskWidth, 90 * (Math.PI / 180), 0, 0);
bottom.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x0000FF], [1,0], [0,255], matr, SpreadMethod.PAD);
bottom.graphics.drawRect(0, 0, areaWidth + (softMaskWidth * 2), softMaskWidth);
bottom.graphics.endFill();
bottom.y = areaHeight;
bottom.x = softMaskWidth * -1;
softMaskSprite.addChild(bottom);