Monday, October 24, 2005

More fun with image formats in AS3

So I did post a PNG encoder done in AS3. Well, when you look at the code you realize it's still rather simple. So you might not believe that AS3 is able to something 'real'. This weekend I was looking for some good sample code to show off AS3 and after typing in "JPEG encoder source code" into our favorite search engine, I got a link to this. Well, this code looked rather non portable to something like Java or JavaScript but I took the challenge and made it happen. It really works!

It's certainly not the highest performance possible, but encoding a 1024x768 image in about 6 seconds in not too shabby for an initial implementation, don't you think so? Try to do this in AS2 and you will certainly fail. ;-)

The funny part here is that I was hunting for an artifact bug for about 4 hours, not understanding why I got color banding when decoding the JPEG I had encoded. Little did I get that I had used Remote Desktop to log into my office machine to code this and missed that it forces 16bit depth for some reason although I had selected 24bit. Talking about overfocus, I was really sure it was a bug in my code :-) Usually Flash detects the native screen depth and will try display content decently using ordered dithering. But in this case the Flash Player was advised by the OS to use a 32bit bitmap resulting in the 'bug' I was seeing. There was some ugly color banding since Windows XP does not apply any dithering in 16bit display mode but just simple clamping.

Anyway, I hope you may find this useful somehow... To use it, you need to instantiate it using a quality parameter which is the standard 1...100 value for JPEG compression:

var jpegEnc:JPEGEncoder(75); // argument
// is the quality parameter
var jpegDat:ByteArray = jpegEnc.encode(myBitmapData);

The input parameter for JPEGEncoder.encode() is a BitmapData object. Similarly to the PNG encoder the resulting ByteArray object will contain the encoded JPEG file which you can send to your server.

Monday, October 17, 2005

PNG Encoder in AS3

I hope you are already playing around with AS3, because in my opinion it rocks! There are really endless possiblities, especially when taking into account some of the new classes like ByteArray and the new number types uint and int. I added a little sample here. This code is not entirely my doing, I merely fixed a couple of bugs, but hopefully it shows the power. It implements a simple PNG encoder, taking a BitmapData as input and returns the encoded PNG as a ByteArray which you can then process further, f.ex. sending it to your server. The main reason that this is trivial to do in AS3 is a 'little' feature in ByteArray which allows you to compress data using zlib.

To use this class, have a BitmapData object somewhere and then call it this way:
var myPNG:ByteArray = PNGEnc.encode(myBitmapData);
Very simple. Obviously this could be extended to do a better job overall, support for scanline filters would be the first thing to look at probably. Here is the class which does the job:
import flash.geom.*;
import flash.display.*;
import flash.util.*;

public class PNGEnc {

public static function encode(img:BitmapData):ByteArray {
// Create output byte array
var png:ByteArray = new ByteArray();
// Write PNG signature
png.writeUnsignedInt(0x89504e47);
png.writeUnsignedInt(0x0D0A1A0A);
// Build IHDR chunk
var IHDR:ByteArray = new ByteArray();
IHDR.writeInt(img.width);
IHDR.writeInt(img.height);
IHDR.writeUnsignedInt(0x08060000); // 32bit RGBA
IHDR.writeByte(0);
writeChunk(png,0x49484452,IHDR);
// Build IDAT chunk
var IDAT:ByteArray= new ByteArray();
for(var i:int=0;i < img.height;i++) {
// no filter
IDAT.writeByte(0);
var p:uint;
if ( !img.transparent ) {
for(var j:int=0;j < img.width;j++) {
p = img.getPixel(j,i);
IDAT.writeUnsignedInt(
uint(((p&0xFFFFFF) << 8)|0xFF));
}
} else {
for(var j:int=0;j < img.width;j++) {
p = img.getPixel32(j,i);
IDAT.writeUnsignedInt(
uint(((p&0xFFFFFF) << 8)|
(shr(p,24))));
}
}
}
IDAT.compress();
writeChunk(png,0x49444154,IDAT);
// Build IEND chunk
writeChunk(png,0x49454E44,null);
// return PNG
return png;
}

private static var crcTable:Array;
private static var crcTableComputed:Boolean = false;

private static function writeChunk(png:ByteArray,
type:uint, data:ByteArray) {
if (!crcTableComputed) {
crcTableComputed = true;
crcTable = [];
for (var n:uint = 0; n < 256; n++) {
var c:uint = n;
for (var k:uint = 0; k < 8; k++) {
if (c & 1) {
c = uint(uint(0xedb88320) ^
uint(c >>> 1));
} else {
c = uint(c >>> 1);
}
}
crcTable[n] = c;
}
}
var len:uint = 0;
if (data != null) {
len = data.length;
}
png.writeUnsignedInt(len);
var p:uint = png.position;
png.writeUnsignedInt(type);
if ( data != null ) {
png.writeBytes(data);
}
var e:uint = png.position;
png.position = p;
var c:uint = 0xffffffff;
for (var i:int = 0; i < (e-p); i++) {
c = uint(crcTable[
(c ^ png.readUnsignedByte()) &
uint(0xff)] ^ uint(c >>> 8));
}
c = uint(c^uint(0xffffffff));
png.position = e;
png.writeUnsignedInt(c);
}
}

Sunday, October 02, 2005

Next generation Flash Player user experience

That was early... Mike Downey is already asking for feature wishes for the next version of the Flash authoring tool. While I could ask the same question for the Flash Player, let's limit this mini post to a smaller scope: The usability of the Flash plugin itself, not from a developer, but user point of view.

I would really like to give some power back to end users, knowing very well that some things are, let's say, less than user friendly. We could actively reduce the impression of some (power-)users that Flash content is merely a nuisance and maybe make some 3rd party browser extensions redundant. It will push Flash further in being taken more and more seriously when it comes to RIAs.

So how could we turn down the 'noise'? What annoys you the most about the Flash experience in the browser? How could we fix it (apart from uninstalling it of course ;-)? What kind of controls would you like to give to users? How can we enhance the interactivity with Flash content? Remember that I am not interested in developer features here (I am sure we'll get plenty of those), but real end user capabilities which will control all types of Flash content. I am sure there is a long laundry list of things we could do. Let me know about your ideas, we are willing to listen.