Email Updates RSS Subscribe

This blog is created and maintained by the technical team at Hook in an effort to preserve and share the insights and experience gained during the research and testing phases of our development process. Often, much of this information is lost or hidden once a project is completed. These articles aim to revisit, expand and/or review the concepts that seem worth exploring further. The site also serves as a platform for releasing tools developed internally to help streamline ad development.


Hook is a digital production company that develops interactive content for industry leading agencies and their brands. For more information visit


Alchemy Series Part 4: D is for Data Manipulation

Posted on March 16th, 2011 by Jake

So far, we’ve gone though getting the environment setup, basic compilation and implementation of alchemy into a swf, and the standard Hello World example. So what next you ask? Well I answer with “More Contrived Examples!” Sadly its tough to make examples that don’t feel totally contrived, while also making those examples easy to understand while staying on point. Kind of like the old racing adage, “Cheap, Fast, Reliable, pick any two”. So I picked easy to understand and on point. Which means we are still in the land of contrived examples, and for that I apologize. Either way, on with the contrivedness! :)

The Example can be Downloaded Here.

This example is broken up into three different parts. The first deals with basic object creation and return, the second, deals with ByteArrays as file streams in C (I promise that is super useful), and finally the third is keeping data stored in C as a way of keeping state internal to your library.

So if you run the supplied example inside of the Flash CS5 IDE or from FlashDevelop/Builder, or something that watches for traces, you will see this:

– Start Basic Data Example –
(ALC) Text: Test Text
(ALC) Int: 15
(ALC) Number: 3.141592
(ALC) AS3 Obj Text: Hawt String
(ALC) AS3 Obj Int: 42
Obj: Test Text
Obj: 15
Obj: 3.141592

– Start ByteArrays as Streams Example –
In Bytes Length: 10000
>Out Bytes Length Before: 0
(ALC) Bytes Read 1024
(ALC) Bytes Written 1024
(ALC) Bytes Read 2048
(ALC) Bytes Written 2048
(ALC) Bytes Read 3072
(ALC) Bytes Written 3072
(ALC) Bytes Read 4096
(ALC) Bytes Written 4096
(ALC) Bytes Read 5120
(ALC) Bytes Written 5120
(ALC) Bytes Read 6144
(ALC) Bytes Written 6144
(ALC) Bytes Read 7168
(ALC) Bytes Written 7168
(ALC) Bytes Read 8192
(ALC) Bytes Written 8192
(ALC) Bytes Read 9216
(ALC) Bytes Written 9216
(ALC) Bytes Read 10000
(ALC) Bytes Written 10000
>Out Bytes Length After: 10000

– Start Image Data Example –
Length: 40000
Memory address for RED image: 1069136
Length: 10000
Memory address for GREEN image: 1069152

You will also see a Red square with a translucent and smaller Green square on top of it. Epic exciting I know, but the behind the scenes bits are pretty awesome if you ask me :) First up, basic data handling example.

Data in, Data out
At this point, I’m assuming you have worked your way through the Part 3 post, and are fairly comfortable compiling things, and working with that compiled swc in flash. But I do want to point out some changes in the main() function of this example.

//Virtual Function (thunk) maps
AS3_Val showArgsMethod = AS3_Function(NULL, showArgs);
AS3_Val storeImageBytesMethod = AS3_Function(NULL, storeImageBytes);
AS3_Val adjustAlphaMethod = AS3_Function(NULL, adjustAlpha);
AS3_Val getImageBytesMethod = AS3_Function(NULL, getImageBytes);
AS3_Val freeImageBytesMethod = AS3_Function(NULL, freeImageBytes);
AS3_Val copyBytesMethod = AS3_Function(NULL, copyBytes);

The first bit is still the same. We declare and define an AS3_Function thunk for each of the function we want to expose and map that to the actual internal C function. So far so standard.

The next line you’ve seen before as well

//Bundle up the thunks into an AS3 Object.  This object is what flash sees
//after you call init() on the loaded Alchemy loader.
AS3_Val flashObj = AS3_Object("showArgs:AS3ValType, copyBytes:AS3ValType", showArgsMethod, copyBytesMethod);

This, as before, creates an AS3 Object that will hold the mappings to our internal functions. This is how those functions are accessed from ActionScript. You also pass in a Type Template pattern as a string, and then references to the thunks. Still pretty normal. However you will notice that we’ve defined six functions, but have only included two in our AS3 Object. If we put all six in there, the line starts to get very unwieldy. So we can use the AS3_SetS() function to attach more properties/functions to our AS3 Object.

AS3_SetS(flashObj, "storeImageBytes", storeImageBytesMethod);
AS3_SetS(flashObj, "adjustAlpha", adjustAlphaMethod);
AS3_SetS(flashObj, "getImageBytes", getImageBytesMethod);
AS3_SetS(flashObj, "freeImageBytes", freeImageBytesMethod);

AS3_SetS() allows use to add properties by name and set their inial value. The first parameter is the object we want to add our properties to. The second is a (constant) char* list of characters that is the name of our property. Lastly we pass in the initial value of that property. In this case, we are passing in the thunks we made to expose out C functions with. That is the first bit of data management in the first example. Setting properties at runtime to AS3 Objects. Remember this is a “real” AS3 Object, so it can be returned to Flash and used directly.

This concept is more obviously implemented in the showArgs() C function. This function serves no purpose other than to demonstrate a few different ways of dealing with basic data. From Flash we do this:

/////****** BASIC DATA EXAMPLE *****\\\\\
//Demonstrate Object Properties
trace("-- Start Basic Data Example --");
var testObj:Object = { stringProp:"Hawt String", answerProp:42 };
var retObj:Object; 
retObj = _lib.showArgs("Test Text", 15, 3.141592, testObj);
trace("Obj: " + retObj.myText);
trace("Obj: " + retObj.myInt);
trace("Obj: " + retObj.myDbl);

and we should get the following debug output:
– Start Basic Data Example –
(ALC) Text: Test Text
(ALC) Int: 15
(ALC) Number: 3.141592
(ALC) AS3 Obj Text: Hawt String
(ALC) AS3 Obj Int: 42
Obj: Test Text
Obj: 15
Obj: 3.141592

Once the C library is instantiated, we can start to call functions on it. In this case we are creating a new object, “testObj” and defining a few dynamic properties on it by hand.

var testObj:Object = { stringProp:"Hawt String", answerProp:42 };

Then we make the call, passing in a few more parameters in addition to the testObj:

retObj = _lib.showArgs("Test Text", 15, 3.141592, testObj);

This maps, not surprisingly, to the showArgs() function in our C file. So lets dig into that a bit.
The first bit is very similar to our echoMe() function from the previous post. We declare some variables, and parse out the arguments using the AS3_ArrayValue() function.

//Declare some variables to hold the passed in data
char* myText;	//AS3_String maps to char*
int myInt;		//AS3_Int maps to int
double myDbl;	//AS3_Number maps to double
AS3_Val myObj;	//AS3_Object passed in.
//Declare some more vars to hold the values parsed out of myObj
char* testObjString;
int testObjInt;
//Delcare var for our return object
AS3_Val returnObj;
//Parse out arguments using AS3_ArrayValue
//This takes the passed in args object, and creates new C values
//from it based on the string of types given as a pattern
AS3_ArrayValue(args, "StrType, IntType, DoubleType, AS3ValType", &myText, &myInt, &myDbl, &myObj);

So this is expecting us to pass in a String, Int, Double, and a Generic AS3 Value. Which we do with “Test Text”, 15, 3.141592, and testObj and store those in their respective C variables. The first three are fairly standard, so we store them and then print them out with fprintf() which I touched on last time. Basically fprintf takes a stream to write to and some things to write out in a specific format:

//Print out the basic arguments
fprintf(stderr, "(ALC) Text: %s", myText);
fprintf(stderr, "(ALC) Int: %i", myInt);
fprintf(stderr, "(ALC) Number: %f", myDbl);

In this case, our stream is stderr (declared in stdio.h). The flash debugger will catch this and print it out much like a trace. The second argument we have a char* (a string of characters) and a format identifier. Lastly is a list of values that will populate those format identifiers. A good reference for fprintf is here:
As you can probably tell, %s will display a char*, %i will display an integer, and %f will display a floating point value. There are many things you can display in this manner, check out the reference page above for a complete list.

So that takes care of passing in basic atomic data. What about objects and other forms of complex data? For that we can use AS3_ObjectValue()

//Parse passed in AS3 Object into valid C types
AS3_ObjectValue(myObj, "stringProp:StrType, answerProp:IntType", &testObjString, &testObjInt);
fprintf(stderr, "(ALC) AS3 Obj Text: %s", testObjString);
fprintf(stderr, "(ALC) AS3 Obj Int: %i", testObjInt);

AS3_ObjectValue() works in a similar fashion to AS3_ArrayValue(). You give it an AS3 object, a type template, and the destinations for the parsed values. The AS3_ObjectValue() handles all of the details of the type conversion, which is nice. Then we print out the respective values. So far so good. So what about returning an AS3 object? We can do that too:

//Build return object
returnObj = AS3_Object("myText:StrType", myText);
AS3_SetS(returnObj, "myInt", AS3_Int(myInt));
AS3_SetS(returnObj, "myDbl", AS3_Number(myDbl));

This should look mighty familiar to you, as its nearly identical to what we did when putting our thunks together in main(). First we make an object with AS3_Object(), and feed it a property name:Type and then an initial value. From there we can add more dynamic properties with AS3_SetS(). Its as simple as that.

So now we can send data into C functions, modify it, print it, and recombine it to be returned back to flash as a proper AS3 object. As you will discover, once you get the hang of getting your values converted back and forth, working with Alchemy isn’t so hard at all :) So lets look at something slightly (no much mind you) more practical.

ByteArrays and File Streams
I’ve read quite a few posts and comments on the internet debating whether or not Alchemy is faster than straight ActionScript, since it all runs within the flash virtual machine anyway. The consensus seems to be a giant “it depends”. For me however, its not so much about that. Its more about being able to access the bagillion (careful, thats a technical term) lines of C/C++ code out there that has been written to do just about anything you want over the last 40ish years. For us it was getting access to Xiph’s wonderful Ogg and Vorbis libraries for dealing with sound data. Can you imagine flash with access to something like FMOD? Or even physics engines? or C based path finding libraries? Yeah epic… For me, this is the real power of Alchemy, though the faster memory access is also a nice bonus :) My real point to all of that blathering is many of the libraries out there (especially libraries that convert stuff) use file data off of the command line, and write the modified data back out to a file stream. So instead of trying to convert your data or make deep hacks at the C code, you can simply stream your ByteArray data as a standard file stream right to the library, as if it were coming right off of the command line. The core concept for this was demonstrated here:

The idea is that we can use funopen() to redefine how the file streams work in C. Basically we replace the built in methods for accessing the data with our own. For this we can use Alchemy’s ByteArray functions:

* bytearray manipulations for use as C streams
static int readba(void *src, char *dst, int length)
	return AS3_ByteArray_readBytes(dst, (AS3_Val)src, length);
static int writeba(void *dst, const char *src, int length)
	return AS3_ByteArray_writeBytes((AS3_Val)dst, (char *)src, length);
static fpos_t seekba(void *src, fpos_t offs, int whence)
	return AS3_ByteArray_seek((AS3_Val)src, offs, whence);
static int closeba(void *src)
	AS3_Val zero = AS3_Int(0);
	AS3_SetS((AS3_Val)src, "position", zero);
	return 0;

To make use of these new functions we can reassign them like this:

//Open bytearrays as stdio streams
FILE *output = funopen((void *)outBytes, readba, writeba, seekba, closeba);

For this section of the post we will be using the copyBytes() function from the alcexample.c file. The we call this from ActionScript in the “Byte Arrays as C Streams” section of

/////***** BYTE ARRAYS AS C STREAMS *****\\\\\
trace("\n-- Start ByteArrays as Streams Example --");
var inBytes:ByteArray = new BitmapData(50, 50, true, 0xFFFFFFFF).getPixels(new Rectangle(0, 0, 50, 50));
var outBytes:ByteArray = new ByteArray();
inBytes.position = 0;
trace("In Bytes Length: " + inBytes.length);
trace(">Out Bytes Length Before: " + outBytes.length)
_lib.copyBytes(inBytes, outBytes);
trace(">Out Bytes Length After: " + outBytes.length);

So what are we doing here? To demonstrate how to use ByteArrays as C streams, we will simply be taking some byte data, iterating over it all, and pushing it into a new output stream. Effectively making a copy of the byte data. I know its not that exciting, but its what made our OggVorbis encoder possible. So I think its a pretty awesome concept.

In the above ActionScript, we are simply generating some byte data to copy by making a white square as bitmap data, and using getPixels() to convert that to a ByteArray. Then we create an empty ByteArray as a container for the copied byte data. Finally we call copyBytes() on the C lib and pass in the input and output ByteArrays.

Meanwhile… In the C copyBytes() function we start off like we always do, declare some vars, and parse out the arguments.

//Declare byte arrays
AS3_Val inBytes;
AS3_Val outBytes;
//Declare other needed vars
long inLength;
long outLength;
long bytesRead = 0;
long bytesWritten = 0;
int i = 0;
//Parse args
AS3_ArrayValue(args, "AS3ValType, AS3ValType", &inBytes, &outBytes);

This parses our arguments and assigns our two ActionScript ByteArrays to inBytes and outBytes. The goal here is to read through all of the inBytes bytes, and copy it to the outBytes ByteArray, all the while treating it like a file stream.

Next we set up the streams to make use of our ByteArray wrapper functions from before.

//Open bytearrays as stdio streams
FILE *output = funopen((void *)outBytes, readba, writeba, seekba, closeba);
FILE *input = funopen((void *)inBytes, readba, writeba, seekba, closeba);

Now being as though we are treating these guys as streams, we don’t know how many bytes there will be, so we are going to want to store off the length of the ByteArrays, using our old friend AS3_ObjectValue()

//check length
AS3_ObjectValue(inBytes, "length:IntType", &inLength);
AS3_ObjectValue(outBytes, "length:IntType", &outLength);

Now that we are all set up, we can actually do something with the data. To make an attempt to stay faithful to what generally happens, we are going to copy 1k chunks of the stream to a buffer, (where you would in theory modify the data) and then copy the contents of that buffer back to the output stream

while(bytesRead < inLength)
{//copy bytes
	//Read 1k at a time
	for(i = 0; i < 1024 && bytesRead < inLength; i++)
	{//read to buffer
	bytesRead += fread(readBuffer, 1,1,input);
	}//read to buffer
	fprintf(stderr, "(ALC) Bytes Read %ld", bytesRead);
	//write 1k out to stream
	for(i = 0; i < 1024 && bytesWritten < inLength; i++)
	{//write to output
		bytesWritten += fwrite(readBuffer, 1,1,output);
	}//write to output
	fprintf(stderr, "(ALC) Bytes Written %ld", bytesWritten);
}//copy bytes

Now our ActionScript outBytes ByteArray will contain a copy of the contents of the inBytes ByteArray.

Finally when we are all done, we close up the streams, and release our AS3 objects:

//Close up streams

Pointers and Data Structures
Ok, so far so good I hope. All of this was in preparation for this last section. In this part of the example, we will be demonstrating how to store data into malloc’d memory inside of the Alchemy code. For this example we will be making use of the storeImageBytes(), freeImageBytes(), adjustAlpha(), and getImageBytes() functions in the alcexample.c file. If pointers or non-memory managed languages are new to you, you may want to grab a quick nap, or take a break and get something to eat. :) Its not the simplest thing in the world on first viewing.

Deep Breath, here we go.

If you run the example swf, you will see a red box with a smaller translucent green box sitting inside of it. What we are going to do, is store the bitmap data for both boxes inside of the Alchemy code (on the heap) and save off the memory address that starts the contents of that data. Once its stored there, we can manipulate it within the C code, without having to push that data into Alchemy again and again. We can just manipulate it right in memory, and when we are done, we can pull it back out. This is an example of how to keep state inside of your C code.

First up, creating the ByteArrays that contain our bitmap data for the boxes:

/////******* STATE MANAGEMENT ******\\\\\
//Build a red test image (red square)
trace("\n-- Start Image Data Example --");
var redBytes:ByteArray;
var redBD:BitmapData = new BitmapData(100, 100, true, 0xFFFF0000);
redBytes = redBD.getPixels(redBD.rect);
//Build Green Test image (green square)
var greenBytes:ByteArray;
var greenBD:BitmapData = new BitmapData(50, 50, true, 0xFF00FF00);
greenBytes = greenBD.getPixels(greenBD.rect);

Once we have that we store that data on heap:

//Store bytes in alchemy memory
redBytes.position = 0;
var redPtr:Number = _lib.storeImageBytes(redBytes);
trace("Memory address for RED image: " + redPtr);
greenBytes.position = 0;
var greenPtr:Number = _lib.storeImageBytes(greenBytes);
trace("Memory address for GREEN image: " + greenPtr);

As you can see when we call _lib.storeBytes() we get a number back in return. This number is the memory address that represents the start of our stored data. Any time you want to access that data you will need to pass that back into the C code, which will then get a reference to the data from the memory address. But before we get too far ahead or ourselves, lets check out what storeImageBytes() does.

The first part should at this point be very familiar to you. Declare some vars, parse the arguments, and store the values from the arguments. In this case we are also saving off the length of the passed in ByteArray.

//Delcare incoming byte array
AS3_Val bytes;
//Var to hold the length value
int length;
//Pars args
AS3_ArrayValue(args, "AS3ValType", &bytes);
//Determine length
AS3_ObjectValue(bytes, "length:IntType", &length);

This next bit, grabs some memory from the heap and stores a pointer to that memory

//Allocate memory for and save an instance of the imageData Struct
imageData *image = (imageData *)malloc(sizeof(imageData));

I know, I know, there is that pesky “imageData” type that I haven’t mentioned yet. So lets get to that real quick. At the very top of the alcexample.c file, you will see the definition for that typedef struct.

typedef struct
        unsigned char *data;
	int length;
} imageData;

Basically this is just an object that has two properties or members, “data”, and “length”. Data is a pointer to some memory that holds a list of unsigned chars. Why unsigned chars you ask? Well, they have a valid range of 0 to +255. Hmmm… what else goes from 0 to 255? Oh I know! A single channel of color data! In flash if I say 0xFFFF0000 you probably immediately think Red at full Alpha, because Flash uses the ARGB color format (alpha, red, green, blue). This is a hex number, when converted to Decimal, looks like 255 255 0 0 (argb). So half alpha blue would look like 127 0 0 255 or 0x7F0000FF. So what we are going to do is store the actual image byte data right there in the “data” member. Then we are also going to store the length of our byte data in the “length” member. However we want to make sure that our instance of the imageData struct doesn’t go out of scope when we leave the storeImageBytes() function, so we need to grab some memory off of the heap, instead of the stack. Which is where the malloc line, once again, comes into play.


With a pointer to our newly malloc’d imageData instance, we can access the “data” member of that instance and malloc some more memory to store our actual byte data in and also save off the length:

//Allocate some heap memory
image->data = (unsigned char *)malloc(sizeof(unsigned char)*length);
//Save length
image->length = length;

Now with everything ready, we can read in our byte data from the passed in ByteArray and shove it into our struct. We can use Alchemy’s built in ByteArray methods to get the data out.

//Write bytes to buffer
AS3_ByteArray_readBytes(image->data, bytes, length);

So now if we checked out the data that has been stored (assuming its from the red square bitmap data) when we execute this:

fprintf(stderr, "A: %i", image->data[0]);
fprintf(stderr, "R: %i", image->data[1]);
fprintf(stderr, "G: %i", image->data[2]);
fprintf(stderr, "B: %i", image->data[3]);

we would see:
A: 255
R: 255
G: 0
B: 0

That would be the ARGB colors of the first pixel in our red square. Awesome right?

After we do some clean up we can then return the memory address of our struct instance:

return AS3_Number((long)image);

That number is the number we are going to store in our ActionScript code, to be used to reference the image data that we care about.

Great so now we have the data in there, what can we do. Well staying consistent with the rest of the horribly forced examples, we are going to modify the Alpha Channel of that image data. From ActionScript we are going to do this:

//Adjust the alpha of the image bytes
_lib.adjustAlpha(redPtr, 0.8);
_lib.adjustAlpha(greenPtr, 0.3);

The first argument is that memory address we received from when we stored the image data. The second argument is a 0 – 1 value that we will multiply against our Alpha Channel bytes in our stored image data.

The adjustAlpha() function once again starts out like the rest. Delcare some vars and parse the arguments

//Get access to image data from memory address
imageData *image;
unsigned int imageAddress;
//Storage for alpha multiplier
double alphaMult;
int count;
unsigned char alpha;
unsigned char red;
unsigned char green;
unsigned char blue;
//Parse args
AS3_ArrayValue(args, "IntType, DoubleType", &imageAddress, &alphaMult);

Next however, is the tricky bit. We need to take that passed in memory address and create a pointer to the data at that address, which is of the imageData type defined by our struct

//Get pointer to image
image = (imageData *)imageAddress;

So now, image is a pointer to the imageData instance we care about. So lets do something with it.

//Walk pixels
count = 0;
while(count < image->length)
{//each pixel
	alpha = image->data[count];
	red = image->data[++count];
	green = image->data[++count];
	blue = image->data[++count];
	//Modify channels
	alpha = (unsigned char)(alpha*alphaMult);		
	//Store back into data
	image->data[count-3] = alpha;
	image->data[count-2] = red;
	image->data[count-1] = green;
	image->data[count-0] = blue;
}//each pixel

Nothing earth shattering here, but if you come from a purely ActionScript background, some things may look a bit funky. The most obvious item is the “->”. Never fear, all this does is dereference the “image” pointer and grab the value at the memory address of the member data. So for alpha= image->data[count] we are simply getting the byte that is stored in that imageData instance at “count” index. So if “count” is 0, and we are looking at the red square then the value would be 255 or 0xFF because that pixel has full Alpha (“A”rgb). Then we simply walk down each byte and do whatever we want with it. In this case, we are mutiplying the alpha value by the alpha multiplier that was passed into the function. Then we write that back to the “data” member. Simple enough. The thing to remember is that we have modfied the data on the heap, so its permenantly set that way now, until of course we change it again.

So cool… We have managed to store some data, and modify it. Now its time to get that modified data back into Flash. I’ll bet you couldn’t have guessed we use the getImageBytes() function :)

From ActionScript we can do this to get our data back out

//Get altered image back from Alchemy
var newRedBytes:ByteArray; 
newRedBytes = _lib.getImageBytes(redPtr);
newRedBytes.position = 0;

We call getImageBytes() on the C lib, and feed it the memory address to the data we care about, just as before. From there we get a brand new ByteArray that is filled with our modified image data and returned back to Flash. As with the rest of the of the functions, we again, set up some vars, and parse the args. Then we generate a pointer to our data once again. But then we get to do something new. We create an actual ActionScript ByteArray in C.

//Create a new byte array
AS3_Val flash_utils_namespace = AS3_String("flash.utils");
AS3_Val no_params = AS3_Array("");
AS3_Val ByteArray_class = AS3_NSGetS(flash_utils_namespace, "ByteArray");
AS3_Val outBytes = AS3_New(ByteArray_class, no_params);

The key function here is the AS3_NSGetS(). This gets a class definition that can then be newed up. The first parameter is the package path (as an AS3_String) to the class definition you want. In this case we are using “flash.utils”. The second parameter is a constant char* (C string) of the name of the AS3 Class we want. In this case its “ByteArray”. Then on the next line we new it up with AS3_New(). We pass to it the class definition and an array of parameters. In this case we don’t need to send anything to the ByteArray constructor, so we just use an empty AS3_Array(“”). At this point we have an honest to goodness AS3 ByteArray. Which means we can fill it with bytes.

//Write bytes to byte array
AS3_ByteArray_writeBytes(outBytes, image->data, image->length);

In our case we take the modified image data, and shove it into our newly created ByteArray. Lastly we do a bit of clean up and return the new ByteArray back to flash.

From there, in ActionScript we take those bytes, and build a new BitmapData object from it, and display it on screen.

//Set Bitmap data based on data returned from Alchemy
var newRedBD:BitmapData = new BitmapData(redBD.width, redBD.height, true, 0x00000000);
newRedBD.setPixels(redBD.rect, newRedBytes);
//Put result image on stage
var newRedImg:Bitmap = new Bitmap(newRedBD);

Now we have a semi transparent red block on screen :) w00t!

The final bit is some manual memory management. From Flash we can call


Which results in

//Pointer to image data
unsigned int imageAddress;
imageData *image;
//Parse ags
AS3_ArrayValue(args, "IntType", &imageAddress);
//Get access to our image data
image = (imageData *)imageAddress;
//Release memory used by our image data

Lots more of the same, vars, args, pointers, blah, blah, blah. But then there is the free() call. Basically we are just giving that memory back, and Flash’s Garbage Collected can now reclaim it.

Great Googly Moogly
So, if you have made it this far, congratulations, you have reached the light at the end of the tunnel, and the train is running late, so its actual sun light this time. :)

However, we still have two more Alchemy Posts in the series. Part 5 covers some other random details, like mult-file compiling/linking, Asynchronous functions, and talking to ActionScript from the C code. Should be a riot :)

Remember to like us on Facebook if you want to stay updated, or even just to show your support:

And/Or you can follow me on Twitter:
Follow JakeCallery on Twitter

Thanks for reading!

2 Responses to “Alchemy Series Part 4: D is for Data Manipulation”
  1. Jake says:

    @cyberprodigy, thanks for the kind words… there is a link to the official adobe docs in Part 1 of the series:

    As for the text color, believe me, I understand… however I managed to lose that battle when the site was being designed… I will forward your concern along though…


  2. cyberprodigy says:

    Your tutorials are great on Alchemy. But as soon as I start reading the first thing i want to do is open Inspect Panel in chrome and disable the CSS that is setting the text so ultra light. Black is better, or at least darker would be more.. lets say – readable :) . And also the link to the official documentation would make the tutorial more complete.

    Hey, but these tutorials about Alchemy are simply amazing. I guess I’m gonna read them all today :)

Leave a Reply