Showing posts with label pixel. Show all posts
Showing posts with label pixel. Show all posts

Tuesday, September 17, 2019

Save and Load Binary Files in HTML5

In this example, we firstly draw something (shapes & lines) on the canvas, convert it into a bitmap (pixel data) and save the pixel values as a binary file.

//Draw something
ctx.fillStyle = "red";
ctx.fillRect(0, 0, 60, 60);
ctx.beginPath();
ctx.rect(60, 60, 160, 80);
ctx.fillStyle = "blue";
ctx.fill();
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "green";
ctx.moveTo(6, 160);
ctx.lineTo(240, 360);
ctx.lineTo(60, 800);
ctx.lineTo(800, 60);
ctx.stroke();//draw
//Convert canvas draws into pixels
var buffer = ctx.getImageData(0, 0, w, h);

//https://stackoverflow.com/questions/23451726/saving-binary-data-as-file-using-javascript-from-a-browser
var saveByteArray = (function () {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, name) {
        var blob = new Blob(data, {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = name;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());
//Save pixel data (ArrayBuffer) as binary file
saveByteArray([buffer.data], 'example.bf');

Then we load the binary file and display the pixel values it stores (as a bitmap) using a new canvas.
//The requestAnimFrame fallback for better and smoother animation
var buffer = ctx.createImageData(w, h);

//http://qnimate.com/an-introduction-to-javascript-blobs-and-file-interface/
var xhr = new XMLHttpRequest(); 
xhr.open("GET", "./example.bf"); 
//although we can get the remote data directly into an arraybuffer using the string "arraybuffer" assigned to responseType property. For the sake of example we are putting it into a blob and then copying the blob data into an arraybuffer.
xhr.responseType = "blob";

function analyze_data(blob)
{
    var myReader = new FileReader();
    myReader.readAsArrayBuffer(blob);
    
    myReader.addEventListener("loadend", function(e)
    {
        var buf = e.srcElement.result;//arraybuffer object
        var buf8 = new Uint8ClampedArray(buf);//first view for copy pixel data to ImageData
        var data = new Uint32Array(buf);//second view for setting pixel values
        buffer.data.set(buf8);
        //we use putImageData() to copy the image data back to the canvas.
        ctx.putImageData(buffer, 0, 0);
    });
}

xhr.onload = function() 
{
    analyze_data(xhr.response);
}
xhr.send();

Demo & Full Source Code: Create & Save, Load & Show

Monday, September 9, 2019

Fast per pixel bitmap animation in HTML5

According to this tutorial (Faster Canvas Pixel Manipulation with Typed Arrays), we can make the code in my last post (per pixel bitmap animation in HTML5/JavaScript) faster using Typed Arrays:

//The requestAnimFrame fallback for better and smoother animation
window.requestAnimFrame = (function () {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || 
 window.mozRequestAnimationFrame || window.oRequestAnimationFrame || 
 window.msRequestAnimationFrame || function (callback) {
        window.setTimeout(callback, 1000 / 60);
    };
})();

//Prepare our canvas
var canvas = document.querySelector('#render');
var w = window.innerWidth;
var h = window.innerHeight;
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');

var time = Date.now();//record initial time
var buffer = ctx.createImageData(w, h);//The back buffer we used to paint the result into the canvas
//The main render function
//Calculate a color value from elapsed time and [x,y] coordinates (scaled to [0,1])
function render(time, fragcoord) {
    /* put the GLSL fragment shader's JavaScript equivalent here. */
    //begin of per pixel bitmap manipulation
    var x = fragcoord[0]; var y = fragcoord[1];
    var red = x;
    var green = y;
    var blue = 1/(1+time);
    var alpha = 1;
    //end of per pixel bitmap manipulation
    return [red,green,blue,alpha]; //the final color value (scaled to [0,1])
};
var buf;
function animate() {
    var delta = (Date.now() - time) / 1000;
    buffer = ctx.createImageData(w, h);
    //
    /*
    Next we create two ArrayBuffer views. 
    One that allows us to view buf as a one-dimensional array of unsigned 8-bit values 
    and another that allows us to view buf as a one-dimensional array of unsigned 32-bit values.
    */
    buf = new ArrayBuffer(buffer.data.length);
    var buf8 = new Uint8ClampedArray(buf);//first view for copy pixel data to ImageData
    var data = new Uint32Array(buf);//second view for setting pixel values
    //
    ctx.clearRect(0, 0, w, h);
    for (var x = 0; x < w; x++) {
        for (var y = 0; y < h; y++) {
            var ret = render(delta, [x/w, y/h]);
            //var i = (y * buffer.width + x) * 4;
            //buffer.data[i] = ret[0] * 255;//red
            //buffer.data[i + 1] = ret[1] * 255;//green
            //buffer.data[i + 2] = ret[2] * 255;//blue
            //buffer.data[i + 3] = ret[3] * 255;//alpha  
            data[y * w + x] =
            (ret[3]*255 << 24) | // alpha
            (ret[2]*255 << 16) | // blue
            (ret[1]*255 <<  8) | // green
             ret[0]*255;  // red
        }
    }
    /*
    now assign the contents of the ArrayBuffer buf to imageData.data. 
    We use the Uint8ClampedArray.set() method to set the data property 
    to the Uint8ClampedArray view of our ArrayBuffer by specifying buf8 as the parameter.
    */
    buffer.data.set(buf8);
    //Finally, we use putImageData() to copy the image data back to the canvas.
    ctx.putImageData(buffer, 0, 0);
    requestAnimFrame(animate);
};

window.onresize = function () {
    w = window.innerWidth;
    h = window.innerHeight;
    canvas.width = w;
    canvas.height = h;
};

animate();

Demo & Full Source Code: http://vvv.flaswf.tk/demo/?url=HTML5Pixelsfast

The difference: Here we use an ArrayBuffer "buf" to hold the ImageData "buffer", and create two ArrayBuffer views of "buf"; one as an array of unsigned 8-bit values for using "putImageData()" function to copy the image data back to the canvas, and the other one as unsigned 32-bit values for setting pixel values (just like in AS3, allowing you to use only one, instead of four, array assignment to set a pixel's value).

Sunday, August 25, 2019

Per pixel bitmap animation in HTML5/JavaScript

LICSON showed how to simulate GLSL shader effects on HTML5 Canvas using pure JavaScript:

//The requestAnimFrame fallback for better and smoother animation
window.requestAnimFrame = (function () {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || 
 window.mozRequestAnimationFrame || window.oRequestAnimationFrame || 
 window.msRequestAnimationFrame || function (callback) {
        window.setTimeout(callback, 1000 / 60);
    };
})();

//Prepare our canvas
var canvas = document.querySelector('#render');
var w = window.innerWidth;
var h = window.innerHeight;
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');

var time = Date.now();//record initial time
var buffer = ctx.createImageData(w, h);//The back buffer we used to paint the result into the canvas

//The main render function
//Calculate a color value from elapsed time and [x,y] coordinates (scaled to [0,1])
function render(time, fragcoord) {
    /* put the GLSL fragment shader's JavaScript equivalent here. */
    //begin of per pixel bitmap manipulation
    var x = fragcoord[0]; var y = fragcoord[1];
    var red = x;
    var green = y;
    var blue = 1/(1+time);
    var alpha = 1;
    //end of per pixel bitmap manipulation
    return [red,green,blue,alpha]; //the final color value (scaled to [0,1])
};

function animate() {
    var delta = (Date.now() - time) / 1000;
    buffer = ctx.createImageData(w, h);
    ctx.clearRect(0, 0, w, h);
    for (var x = 0; x < w; x++) {
        for (var y = 0; y < h; y++) {
            var ret = render(delta, [x/w, y/h]);
            var i = (y * buffer.width + x) * 4;
            buffer.data[i] = ret[0] * 255;//red
            buffer.data[i + 1] = ret[1] * 255;//green
            buffer.data[i + 2] = ret[2] * 255;//blue
            buffer.data[i + 3] = ret[3] * 255;//alpha
        }
    }
    ctx.putImageData(buffer, 0, 0);
    requestAnimFrame(animate);
};

window.onresize = function () {
    w = window.innerWidth;
    h = window.innerHeight;
    canvas.width = w;
    canvas.height = h;
};

animate();

Demo & Full Source Code: http://vvv.flaswf.tk/demo/?url=HTML5Pixels

The difference: In AS3/Haxe, a color value is represented by a single Unsigned Int value (0xAARRGGBB). In HTML5, the color data (BitmapData) array stores a whole color value as four neighboring elements (integer between 0 and 255), representing the red, green, blue and alpha values, respectively. To get/set the color value at coordinate (x,y), you should go to index "i=(y*buffer.width+x)*4", then the red, green, blue and alpha values are respectively "buffer.data[i], buffer.data[i+1], buffer.data[i+2], buffer.data[i+3]".

Links:
https://licson.net/post/glsl-fragment-shaders-in-javascript/
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas
https://bruce-lab.blogspot.com/2019/02/four-ways-for-per-pixel-bitmap.html
Faster Canvas Pixel Manipulation with Typed Arrays
References:
HTML5 Canvas: Native Interactivity and Animation for the Web, see Animation Loop (P.27), Pixel Manipulation (P.170).
Foundation HTML5 Animation with JavaScript, see Animation loops (P.16), Pixel manipulation (P.94).
HTML5 Game Development Insights, see High-Performance Update Loops (P.106), A Bitmap API Example (P.246).
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData
https://www.w3schools.com/js/js_htmldom_animate.asp
https://www.w3schools.com/tags/canvas_putimagedata.asp

Friday, February 8, 2019

Four ways for per pixel bitmap manipulation in OpenFL

A BitmapData can be seen as an array of length width*height, holding unsigned int colors values. There are at least four ways to manipulate pixels of a bitmap image(Bitmap/BitmapData) in OpenFL. The first way is using setPixel() or setPixel32() function:

var myBitmapData:BitmapData = new BitmapData(800, 600, true, 0);
myBitmapData.lock();
for (j in 0...600)
    {
    for (i in 0...200)
        {
         myBitmapData.setPixel32(i, j, (i % 255) << 24 | 0x0000ff);
        }
    }
myBitmapData.unlock();
You can use lock() and unlock() function before and after multiple calls of setPixel() function, so the BitmapData will only be updated on Screen after unlock(). The second way is using setVector() function, and a Vector of UInt to hold pixel values:
var myVector:Vector = new Vector(200 * 600, true);
for (j in 0...600)
    {
    for (i in 0...200)
        {
        myVector[j * 200 + i] = (i % 255) << 24 | 0x0000ff;
        }
    }
var myRect2:Rectangle = new Rectangle(200, 0, 200, 600);
myBitmapData.setVector(myRect2,myVector);
The third way is using setPixels() function, and a ByteArray to hold pixel values:
var myByteArray:ByteArray = new ByteArray(200 * 600 * 4);
for (j in 0...600)
   {
   for (i in 0...200)
       {
       //myByteArray.position = (j * 200 + i) * 4;
       myByteArray.writeUnsignedInt((i % 255) << 24 | 0x0000ff);
       }
   }
var myRect4:Rectangle = new Rectangle(400, 0, 200, 600);
myByteArray.position = 0;
myBitmapData.setPixels(myRect4,myByteArray);
Remember to set the position of the ByteArray to 0 before calling setPixels(). The position "(j * width + i) * 4" of the ByteArray is associated with the pixel at (x=i,y=j) in the BitmapData. There is no need to set the position of the ByteArray to "(j * 200 + i) * 4" above since in the double for loops the "writeUnsignedInt()" function will update the position automatically. The fourth way is using the Memoery API, which is similar to the third way. See https://bruce-lab.blogspot.com/2013/03/fast-way-for-per-pixel-bitmap.html for more details.
var myMem:ByteArray = new ByteArray(200 * 600 * 4);
Memory.select(myMem);
for (j in 0...600)
    {
    for (i in 0...200)
        {
        Memory.setI32((j * 200 + i) * 4, (i % 255) << 24 | 0x0000ff);
        }
    }
var myRect4:Rectangle = new Rectangle(600, 0, 200, 600);
myMem.position = 0;
myBitmapData.setPixels(myRect4,myMem);
The full source code: See the result here (HTML5): http://vvv.flaswf.tk/demo/?url=BitmapDataPixel

Friday, November 21, 2014

Open Source and Free Pixel Editors

Piskel
http://www.piskelapp.com/
A simple online web-based (HTML5) Sprite and Pixel art Editor. Offline version is also available.
Source Code: https://github.com/juliandescottes/piskel


piq
http://piq.codeus.net/
A free online (Flash) app for creating pixel art.
See also
http://pixelartor.com/
http://pixieengine.com/
http://www.pixel.tools/

GIMP
http://www.gimp.org/
The famous open source alternative to Photoshop.
See this note for using GIMP as a pixel art editor.

Paint.NET
http://www.getpaint.net/
A free powerful image and photo editing software.

GrafX2
http://pulkomandy.tk/projects/GrafX2
A bitmap paint program specialized in 256-color drawing.
Source Code (GNU GPL): https://code.google.com/p/grafx2/

mtPaint
http://mtpaint.sourceforge.net/
A painting program to create pixel art and manipulate digital photos.
Source Code (GNU GPL): https://github.com/wjaguar/mtPaint

Pixen
http://pixenapp.com/
A open source (but not 'free') pixel art editor for Mac OS X.
Source Code: https://github.com/Pixen/Pixen

Aseprite
http://www.aseprite.org/
An open source animated sprite editor & pixel art tool.
Source Code (GNU GPL): https://github.com/aseprite/aseprite/
Note: Aseprite is open source but not 'free' since donation is required for downloading the pre-built binaries. However, it is open source so you can compile for the binary by yourself.

Links:
http://pixelartus.com/tagged/pixel-art-tools

Monday, May 20, 2013

Watercolor Brush - New Version Released for Android!

Here comes the updated version of my simple & free painting tool - Watercolor Brush. This new version is much smoother than the old one.
Build with AIR, this is my first AIR project for mobile platforms.
Newer version for web will come soon and I may also release an IOS version in the future.


Download the APK (v0.1):
https://docs.google.com/file/d/0B5V2PrQ8xX_EeEszYlFNV0l0Y2s/edit?usp=sharing

Bugs, feedbacks, features requests are welcomed!

Finally, some notes for AIR mobile projets:

1. FileReference.save() works on AIR, but you need some declaration in "application.xml" to enable the save function:
http://richard-heck.blogspot.com/2011/01/how-to-write-file-to-android-filesystem.html

2. AIR Guesture events on mobile platforms:
http://paultrani.com/2011/02/touch-events-and-gestures-on-mobile/
http://www.flashandmath.com/mobile/zoompan/

3. Some optimization tips on AIR mobile performance:
http://www.andymoore.ca/2012/01/how-to-improve-your-mobile-as3air-performance/

The old version for WEB (Flash, outdated, new web version is coming soon):
http://bruce-lab.blogspot.com/2011/09/paint-online-with-chinese-water-color.html

Sunday, March 24, 2013

Fast way for per pixel bitmap manipulation in HaXe NME

I'm not sure whether this is the fastest way, but the nme.Memory API is something you must know for per pixel bitmap manipulation in NME. I learned the method from the stackoverflow thread here:
http://stackoverflow.com/questions/10157787/haxe-nme-fastest-method-for-per-pixel-bitmap-manipulation
nme.Memory support both flash and cpp targets. For flash, it use the Alchemy fast memory opcodes which can greatly boost the speed.

I ported Ralph Hauwert's Alchemy lookup-table effects to NME as a simple example for showing you how to use nme.Memory API for per pixel bitmap manipulation.

The basic idea is to do everything using a ByteArray. Create a ByteArray to hold your screen buffer, select it and use the getI32/setI32 function of the nme.Memory API. One problem is when you need to use extra data, such as some texture buffer in the process, you may need another ByteArray to hold your data. Because "selecting different memory blocks in cycles may lead to a performance loss", as stated in the API's docs, the simple trick is to create a single ByteArray as the virtual RAM, and write everything into it, while store the different position variables of the data block for later use.

In my example, I use the first part of the virtual RAM ByteArray for screen buffer and the next part for holding the texture. So you can just use the "select" function only once and then get/set values from different data blocks by the position variables you stored as the offsets of the virtual RAM's addresses.

Source Code of the example:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData
Binary:  
(Win-32)https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData/bin/w32-bin.zip
(Flash)https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData/bin/HXFastBitmapData.swf 

For pure AS3 projects, the Azoth tool also provides similar memory API for utilizing the Alchemy opcodes. If you don't want any Alchemy opcodes, you may try Vectors in AS3.

Update 2013/04/11: ASC2 now supports using fast memory opcodes in AS3.
Update 2013/05/08: Only AIR SDK 3.6 support those fast opcodes, the latest SDK 3.7 won't compile. You can download the SDK 3.6 here:
http://helpx.adobe.com/air/kb/archived-air-sdk-version.html
http://helpx.adobe.com/flash-player/release-note/fp_116_air_36_release_notes.html

Update 2013/05/07: This method also works on Android platform:
Try this pre-build apk:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData/bin/HXFastBitmapData-debug.apk

Note: When compiling for Android, run "nme setup android" first, you will install Android SDK, Android NDK, Apache ANT and Java SDK.Then open Android SDK manager and install Android 2.2 (API 8), otherwise you may encounter the "Unable to resolve target 'android-8'" problem:
http://www.nme.io/community/forums/installing-nme/unable-to-resolve-target-android-8/

Links:
http://haxe.org/api/flash/memory
http://www.nme.io/api/types/nme/Memory.html
http://stackoverflow.com/questions/10157787/haxe-nme-fastest-method-for-per-pixel-bitmap-manipulation
FlasCC version of the example: http://bruce-lab.blogspot.com/2012/12/migrating-from-alchemy-to-flascc.html
http://philippe.elsass.me/2010/05/as3-fast-memory-access-without-alchemy/
Compile AS3 Fast Memory Opcodes by ASC2:
http://obtw.wordpress.com/2013/04/03/making-bytearray-faster/

TIPS: There is no good tools for auto-formatting HaXe source code as far as I know. (FlashDevelop only supports AS3 formatting.) So I use Emacs. First rename the XXX.hx file to XXX.java, open it in Emacs, C-x h (M-x mark-whole-buffer) C-M-\ (M-x indent-region), rename it back to XXX.hx, that's it.

Sunday, December 30, 2012

Migrating from Alchemy to FlasCC - Compiling C/C++ to SWC



New year, new tools! The updated new version of Alchemy, the C/C++ to AS3 compiler - FlasCC was released some time ago. Many things have been changed. These two tools - Alchemy and FlasCC have very different APIs. However, if you have some experience with the old Alchemy, migrating from it to FlasCC is not hard.

In this post I will share my experience of migrating from Alchemy to FlasCC. I ported the very classic Alchemy example to FlasCC - Ralph Hauwert's Alchemy lookup-table effects. I will use that example to show you how to compile C/C++ code to SWC, how to use FlasCC to manipulate screen buffers, as well as the changes of the APIs.

The installation of FlasCC has been greatly simplified. You don't need to install Cygwin separately like Alchemy because the new FlasCC tool is already integrated with Cygwin. First, you have to get the FlasCC tools at
http://gaming.adobe.com/technologies/flascc/.
Unzip the package to somewhere (mine is "D:\FlasCC_1.0.0"), click "run.bat", then you will open the Cygwin window.

Let compile the sample first:

cd 05_SWC
make FLASCC=/cygdrive/d/FlasCC_1.0.0/sdk FLEX=/cygdrive/d/Program\ Files/FlashDevelop/Tools/flexsdk
This sample is a very simple and good start. You should try to read the source code and the official notes:
http://www.adobe.com/devnet-docs/flascc/docs/samples.html#T5

To create a SWC from some C/C++ functions, we need to write some wrapper code (as3api.cpp) to expose the functions to AS3.
In Alchemy, it will be something in the C/C++'s main() function like this:
int main()
{
AS3_Val initializeScreenDiffuseBufferMethod = AS3_Function(NULL, initializeScreenDiffuseBuffer);
AS3_Val rasterizeMethod = AS3_Function(NULL, rasterize);
AS3_Val setupLookupTablesMethod = AS3_Function(NULL, setupLookupTables);
AS3_Val initializeDiffuseBufferMethod = AS3_Function(NULL, initializeDiffuseBuffer);
AS3_Val result = AS3_Object("initializeScreenDiffuseBuffer: AS3ValType, rasterize:AS3ValType,setupLookupTables:AS3ValType,initializeDiffuseBuffer:AS3ValType"
,initializeScreenDiffuseBufferMethod, rasterizeMethod,setupLookupTablesMethod,initializeDiffuseBufferMethod);
AS3_Release( initializeScreenDiffuseBufferMethod );
AS3_Release( rasterizeMethod );
AS3_Release( setupLookupTablesMethod );
AS3_Release( initializeDiffuseBufferMethod );
AS3_LibInit( result );
return 0;
} 
While in FlasCC, it will be some declarations and wrapper functions outside the main function like this:
void rasterize_AS3() __attribute__((used,
annotate("as3sig:public function rasterize_AS3():void"),
annotate("as3package:FlasCCTest.lookupeffect")));

void rasterize_AS3()
{
rasterize();
}

void setupLookupTables_AS3() __attribute__((used,
annotate("as3sig:public function setupLookupTables_AS3():void"),
annotate("as3package:FlasCCTest.lookupeffect")));

void setupLookupTables_AS3()
{
setupLookupTables();
}
And the main function in FlasCC:
int main()
{
AS3_GoAsync();
}

The basic framework for using C/C++ to manipulate screen buffers:
1. Pass the texture's pixel data as ByteArray to C/C++ array.
2. Process the textures in C/C++.
3. Retrieve the screen buffer array (as bytearray) to flash and use a bitmap to render it.
The best way to pass bytearray between C/C++ and AS3 is to use pointers and C machine's RAM.

Please read the full source code of my example for details.

To pass parameters from AS3 to C/C++, and return the pointer of the array tBuffer (the screen buffer) in Alchemy:
AS3_Val initializeScreenDiffuseBuffer(void* self, AS3_Val args)
{
AS3_ArrayValue(args, "IntType, IntType", &resX, &resY);
tBuffer = malloc( resX * resY * sizeof(int) );
return AS3_Ptr(tBuffer);
}
In FlasCC:
int* initializeScreenDiffuseBuffer(int resX, int  resY)
{
tBuffer = (int*)malloc( resX * resY * sizeof(int) );
return tBuffer;//&(tBuffer[0]);//return the pointer to the screen buffer
}

void initializeScreenDiffuseBuffer_AS3() __attribute__((used,
annotate("as3sig:public function initializeScreenDiffuseBuffer_AS3(resX0:int,resY0:int):uint"),
annotate("as3package:FlasCCTest.lookupeffect")));

void initializeScreenDiffuseBuffer_AS3()
{
int* result;
//copy the AS3 resolution variables resX0, resY0 (parameters of the swc function initializeScreenDiffuseBuffer_AS3) 
//to C variables resX, resY in lookupeffect.c
AS3_GetScalarFromVar(resX,resX0);
AS3_GetScalarFromVar(resY,resY0);
//get the pointer of the screen buffer
result = initializeScreenDiffuseBuffer(resX,resY);
// return the result (using an AS3 return rather than a C/C++ return)
AS3_Return(result);
}

Now let's see some differences of the AS3 APIs:
To initialize the C/C++ SWC Lib in Alchemy:
cLibInit = new CLibInit();
alcLookupLib = cLibInit.init();
In FlasCC:
CModule.startAsync(this);
To call the SWC functions:
Alchemy:
alcLookupLib.setupLookupTables();
alcDiffuseBitmapPointer = alcLookupLib.initializeScreenDiffuseBuffer(IMAGE_WIDTH,IMAGE_HEIGHT);
FlasCC:
setupLookupTables_AS3();
alcDiffuseBitmapPointer = initializeScreenDiffuseBuffer_AS3(IMAGE_WIDTH, IMAGE_HEIGHT); 
To use domain memory - the C machine's RAM (http://www.adobe.com/devnet-docs/flascc/docs/apidocs/com/adobe/flascc/CModule.html#ram):
Alchemy:
var ns : Namespace = new Namespace( "cmodule.lookupeffect");
alchemyMemory = (ns::gstate).ds;
alchemyMemory.position = alcDiffusePointer;
alchemyMemory.writeBytes(ba,0,ba.length);

alchemyMemory.position = alcDiffuseBitmapPointer;
screenDiffuseBitmapData.setPixels(screenDiffuseBitmapData.rect, alchemyMemory);
FlasCC:
CModule.writeBytes(alcDiffusePointer, ba.length, ba);
CModule.readBytes(alcDiffuseBitmapPointer, 512 * 512 * 4, ba);
or
CModule.ram.position = alcDiffuseBitmapPointer;
screenDiffuseBitmapData.setPixels(screenDiffuseBitmapData.rect, CModule.ram);

The source code:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/FlasCC_SWC

Links:
http://www.adobe.com/devnet-docs/flascc/docs/Reference.html
http://unitzeroone.com/blog/2009/04/06/more-play-with-alchemy-lookup-table-effects/
http://blog.debit.nl/2009/03/using-bytearrays-in-actionscript-and-alchemy/

Sunday, December 23, 2012

GIMP as Pixel Editor

Some notes and tips for using GIMP (2.8) as a Pixel Editor:

1. The Grid: View->Show Grid, Image->Configure Grid (Spacing 16x16)
2. The brush: Tools->Paint Tools->Pencil(N)/Eraser(Shift+E)
Windows->Dockable Dialogs->Tool Options->Brush->Pixel&Size->1.0
3. Preview: View->New View, View->Zoom
4. Palettes from images:
Windows->Dockable Dialogs->Palettes->Palettes Menu->Import Palette->
Select Source->Image(Must be an image already opened in GIMP)

Links:
http://www.gimp.org/
http://www.eglug.org/gimpixel
http://karnakgames.com/wp/2010/10/gimp-for-pixel-art-shortcuts-setup-and-tips/
http://www.youtube.com/playlist?list=PLC6BCB8E64F315574&feature=plcp
http://www.blendernation.com/2014/11/03/learn-ow-to-create-pixel-art-in-blender/
Pixel Editors:
http://www.piskelapp.com/
https://github.com/juliandescottes/piskel
http://www.aseprite.org/
https://github.com/aseprite/

Saturday, September 24, 2011

Paint Online with Chinese Water Color Brush

I once tried to learn Chinese calligraphy and painting when I was in primary school. Unfortunately, I dropped them for lack of gifts.  However, I'm still fond of these Chinese styles of art. So I have always wanted to create something to simulate the Chinese Brush and Chinese Painting in Flash.


This is a project I made for Baidu's APP contest. This toy use automata machine to simulate the dispersion of the ink, which is explained here.
A Chinese version of this toy can be found here: http://app.baidu.com/widget?appid=138371
You can share your art and suggestions at the Forum for this toy:
http://flaswf.freeforums.org/watercolorbrush-f33.html

Friday, May 6, 2011

Simple Fast Bilinear Color Interpolation


Simple, fast implementation of bilinear color interpolation.
The purpose of this snippet is to fill a rectangle with smooth colors interpolated from the four vertices.
This snippet is ripped from my Bengine voxel raycaster, where it is used to scale a single voxel and fill the gap of screen. Color differences are calculated to avoid multiplies, so there are only adds in the for loop. Certainly, the code can be optimized further, I leave it what it is because it's easier for understanding the algorithm.
If you only want to interpolate one single pixel use its neighbours, like the height interpolation in a terrain raycaster, try to find the implementation in this code.
By the way, the simple maths behind the algorithm:
http://en.wikipedia.org/wiki/Bilinear_interpolation

Source Code:
https://flaswf.googlecode.com/svn/trunk/Snippets/SimpleFastBilinearColorInterpolation/

Tuesday, January 4, 2011

Ken Silverman's GROUFST2 Terrain Raycaster Ported to AS3


Simple nice heightmap terrain raycaster, a good start for your own voxel engine.
Fork it here:
http://wonderfl.net/c/7d41
or
http://flaswf.googlecode.com/svn/trunk/GROUFST2/
==========
Update: April, 4,2011
GROUFST2 Ported to HaXe(Supporting targeting swf and cpp both):
Source Code: https://flaswf.googlecode.com/svn/trunk/GROUFST2/Groufst2HXNME
==========
Update: 11, 11,2011
Add HTML5 support:
Source Code: https://flaswf.googlecode.com/svn/trunk/GROUFST2/Groufst2HXNME/Groufst2NME_HTML5/
DEMO:  https://flaswf.googlecode.com/svn/trunk/GROUFST2/Groufst2HXNME/Groufst2NME_HTML5/Export/html5/bin/index.html (Very, very slow.)
==========

Original source code can be found at Ken's website:
Qbasic: http://www.advsys.net/ken/voxlap.htm (GROUFST2.BAS)
EVALDRAW: http://www.advsys.net/ken/download.htm (evaldraw.zip\demos\groufst2b.kc)

And

Happy Coding 2011!

Friday, May 15, 2009

Image Binarization and Edge Tracing in Flash

Image binarization and edge tracing are some old school image technologies.

Just played with them in as3 when I was trying to create a cartoon filter for flash.
Those techs are pixel level transformations, get/setPixel and get/setPixel32 can do that job,
it works slow, though.
The result,
original image:
Binarized image:
Edge:




Nothing new here. But if you need it, here are the codes:

/**
*Simple Image Binarization and Edge Tracing Test in ActionScript3.0
*May. 15, 2009
*Bruce Jawn
*http://bruce-lab.blogspot.com/
*http://www.geocities.com/zhoubu1988

*Feel Free To Use This Code!
*Build this class file with FLEX or FlashDevelop
*OR Set Document Class in Flash IDE (9 and above)
*OR just copy what between "TIMELINE CODES BEGIN<<"*">>TIMELINE CODES END"-
*to Flash IDE TIMELINE and Press Ctrl+Enter.-
*Don't forget to give your image a linkage-"SourceImage"-
*and remove "//" before "var mytex:..."!
**/
package {
import flash.display.*;
//[SWF(backgroundColor="#000000", frameRate="12", width="550", height="400")]
public class IBET_Test_Timeline_Class extends Sprite {
[Embed(source='Your_Image_URL_Here.jpg')]
private var SourceImage:Class;
public function IBET_Test_Timeline_Class():void {
var mytex:BitmapData=(new SourceImage()).bitmapData;
//------------------------------------------------
//TIMELINE CODES BEGIN<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//var mytex:BitmapData=new SourceImage(0,0);
var w:int=mytex.width;
var h:int=mytex.height;
var c:Array=new Array(256);

function look(a:int,b:int):void {
for (var i:int=0; i< a; i++) {
c[i]=0x00ffffff;
}
for (var i:int=a; i< a+b-1; i++) {
c[i]=0x00000000;
}
for (var i:int=a+b-1; i<=255; i++) {
c[i]=0x00ffffff;
}
}//end of function look

look(50,100);

var outB:BitmapData=new BitmapData(w,h,false,0x000000);//Binarized Image

//Graylize Source Image
for (var i:int=w-1; i>=0; i--) {
for (var j:int=0; j<=h-1; j++) {
var pixelValue:uint=mytex.getPixel32(i,j);
var alphaValue:uint=pixelValue>>24&0xFF;
var red:uint=pixelValue>>16&0xFF;
var green:uint=pixelValue>>8&0xFF;
var blue:uint=pixelValue&0xFF;
var color:uint=Math.round(0.3*red+0.59*green+0.11*blue);
var cc:uint=c[color];
if (cc>0) {
color=0xffffff;
} else {
color=0x000000;
}
outB.setPixel(i,j,color);
}//end of for0
}//end of for1

var outT:BitmapData=outB.clone();//Edge Image

for (i=1; i<=w-1; i++) {
for (j=1; j<=h-1; j++) {
var pixelValue1:uint=outB.getPixel(i,j);
if (pixelValue1==0) {
var n1:uint=outB.getPixel(i+1,j);
var n2:uint=outB.getPixel(i,j+1);
var n3:uint=outB.getPixel(i-1,j);
var n4:uint=outB.getPixel(i,j-1);
var n5:uint=outB.getPixel(i-1,j-1);
var n6:uint=outB.getPixel(i+1,j+1);
var n7:uint=outB.getPixel(i+1,j-1);
var n8:uint=outB.getPixel(i-1,j+1);
if (n1+n2+n3+n4+n5+n6+n7+n8==0) {
outT.setPixel(i,j,0xffffff);
}//end of if (n1+n2+n3+n4+n5+n6+n7+n8==0)
}//end of if (pixelValue1==0)
}//end of for0
}//end of for1

addChild(new Bitmap(outB));
addChild(new Bitmap(outT));
this.getChildAt(0).y=h;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>TIMELINE CODES END
//------------------------------------------------
}//end of function IBET_Test_Timeline_Class
}//end of class
}//end of package

================================================
UPDATA 2009_7_09
another cartoon filter (version B) using Image binarization and edge tracing:
original image:

result:


source file:http://flaswf.googlecode.com/files/CartoonFilter_B.as

Friday, August 1, 2008

Rpixel3d release -another way to 3D!

This is something I wanted to do since 2005, but started and finished half an year ago.This is an final vision because I won't have time to do with it any more.

I am sorry that this work is not effective at all, be careful of your CPU if your use a larger picture! We all know that 3d for pixels can't be used for real time 3d textures now. However, I do like its simplicity. You can use it for small pictures or in pre-rendered 3D movies if you like.Maybe you will write an flash-10 vision, use the new Vector3D class instead of Robert Penner's old one, to test the speed.

The difference:
Rpixel3d:Map every texel to a pixel.(SLOW)
Real3d:Map every pixel to a texel.(FAST)

The only useful thing here is how to fix fishbowl distortion.If you only use BitmapData setpixel() to draw 3D transform, there will be annoying gaps between pixels.The trick is to use a Shape and drawRect() or lineTo() and then a Bitmap to draw() that Shape back.
Enjoy!
demo
source

Sponsors