Tag Archives: javascript

Concept for an Image Processing App

This is a writeup for a concept I had been working on – an image processing application. It did not come to pass but I’d like to share some of the ideas behind it (previous posts touches upon some ideas too). It might be of interest to those of you working on developing full-scale applications integrated in web browsers.

The early days

An early sketchup for the application took inspiration from audio-processing software. In particular SynC Modular (later known as Reaktor). It had several levels of building instruments and effects for audio processing. At the high level, non-expert users could wire up high-level modules that had well-defined input/output sockets. In addition, UI for parameters could be designed that allowed users to configure the internals of modules. At the low level, expert users could program up logic for signal manipulation using predefined low-level primitives. The expert users could then package up the internals in a high-level module that exposed inputs/outputs for wiring.

In my first iteration, the user-interface consisted mostly of html/javascript/css code, but resorted to Flash for display of image, graph manipulation, and processing. Since Flash must be compiled before execution, image processing had to use predefined modules when deployed. New modules resulted in a re-compilation and deployment of the application. This restriction would hinder the usability of the application so the search for an alternative started. The only alternative present at the time was the Java VM. It’s usage was very low but still widely deployed. Next was the search for a compiler that could allow runtime compilation. I stumbled upon the Scala Programming Language which included an open-source compiler. Besides solving my problem, the language was also a great teaching tool for programming languages. With the Scala compiler at hand I could migrate the Flash-based processing to a Scala-based applet.

Putting the ideas into action

Here is a small picture showing the general layout of the application. It shows the result of mandelbrot fractal applied to an image. The module generating the fractal has several input parameters and an input image to apply it to, then an output image to store the resulting image to.

When editing the Fractal node we can see the actual Scala code that generates the image. In this code, the input image is transformed by mapping each pixel over a lambda function which yields the transformed pixel. Behind the scenes, a new image is produced, then stored as the output image.

Pixels in images are not manipulated directly with xy-coordinates. This allows the application to subdivide the image into segments that can be transformed concurrently. In addition, an initial pass on a miniaturized image is performed, allowing the user to view a quick preview. The final image is then progressively refined in the last pass.

Simple serialization with XML strings in Javascript

Introduction

Included in this post are some quick and simple functions for doing XML serialization in Javascript through strings. Reserved XML characters < > & ' " are escaped from input and if any invalid input are found an exception will be thrown.

List of XML utility functions:

  • toXmlHeader() – Creates the XML header.
  • toXmlElem(name: string, attributes: object) – Creates and closes an XML element.
  • toXmlElemOpen(name: string, attributes: object) – Creates and opens an XML element.
  • toXmlElemClose(name: string) – Closes an XML element.
  • toXmlText(text: string) – Creates XML text.

A serialization example

var xml = toXmlHeader();
xml += toXmlElemOpen("Library"); // No attributes given.
 
xml += toXmlElemOpen("Authors", {country: "Norway"});
xml += toXmlElem("Author", {name:"Petter Dass"});
xml += toXmlElemClose("Authors");
 
xml += toXmlElemOpen("Books"); // No attributes given.
xml += toXmlElem("Book", {title:"book1", author:"author1"});
xml += toXmlElemOpen("Book", {title:"book2", author:"author1"});
xml += toXmlText("Ach, So?");
xml += toXmlElemClose("Book");
xml += toXmlElem("Book", {title:"book3", author:"author2"});
xml += toXmlElem("Book"); // No attributes given.
xml += toXmlElemClose("Books");
 
xml += toXmlElemClose("Library");
alert(xml); // the complete xml is now contained inside the string.
<?xml version="1.0" encoding="UTF-8"?>
<Library>
<Authors country="Norway">
<Author name="Petter Dass"/></Authors>
<Books>
<Book title="book1" author="author1"/>
<Book title="book2" author="author1">Ach, So?</Book>
<Book title="book3" author="author2"/>
<Book/></Books></Library>

Sourcecode for the XML utility functions

function toXmlValid(str) {
  if (str === undefined || str === null || str.match === undefined || str.match(/<|>|&|'|"/) !== null) {
    throw("invalid string given");
  }
 
  return str;
}
 
function escapeXmlText(str) {
  if (str === undefined || str === null || str.replace === undefined) {
    throw("invalid string given");
  }
 
  // The order of replace is important because the & character is used in escaping.
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;");
}
 
function unescapeXmlText(str) {
  if (str === undefined || str === null || str.replace === undefined) {
    throw("invalid string given");
  }
 
  // The order of replace is important because the & character is used in unescaping.
  return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&apos;/g, "'").replace(/&quot;/g, "\"").replace(/&amp;/g, "&");
}
 
function toXmlHeader() {
  return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
}
 
function toXmlAttr(name, value) {
  return " " + toXmlValid(name) + "=\"" + escapeXmlText(value) + "\"";
}
 
function toXmlElem(tagName, attributes) {
  var str = "\n<" + toXmlValid(tagName);
 
  if (attributes !== undefined) {	
    for (var key in attributes) {
      if (attributes.hasOwnProperty(key) === true) {
        str += toXmlAttr(key, attributes[key]);
      }
    }
  }
 
  return str + "/>";
}
 
function toXmlElemOpen(tagName, attributes) {
  var str = "\n<" + toXmlValid(tagName);
 
  if (attributes !== undefined) {
    for (var key in attributes) {
      if (attributes.hasOwnProperty(key) === true) {
        str += toXmlAttr(key, attributes[key]);
      }
    }
  }
 
  return str + ">";
}
 
function toXmlElemClose(tagName) {
  return "</" + toXmlValid(tagName) + ">";
}
 
function toXmlText(text) {
  return escapeXmlText(text);
}

References

Comparison against null and undefined in Javascript

Values in Javascript can come from

  • Object – object reference
  • String – immutable, 16-bit USC-2
  • Boolean – true, false
  • Number – only 64-bit floating point, IEEE 754 (double)
  • null – empty object reference
  • undefined – unassigned variables and function arguments, missing object properties

Boolean evaluation of values using == and != operators

Values that are interpreted as false:

  • false
  • null
  • undefined
  • "" – the empty string
  • 0 – the number 0
  • NaN – not a number, result of undefined math operation

All other values and objects are interpreted as true.

Working with comparison operators

The == and != operators will do implicit type conversion of it’s arguments to match their type.┬áSince the null and undefined values are both equal with these operators, errors can occur when a missing object property is used in a null-comparison.

By using the === and !== operators, no implicit type conversion will be done. The values null and undefined are not equal using these operators. These operators can be used to check against missing properties and unassigned arguments among other.

Notice: Be careful if updating your old javascript code with === and !== for null-comparison tests. It might be that an undefined-comparison should have been used instead (or both). Failure to recognise these cases can introduce hard-to-catch errors.

References

Code documentation for Javascript and Actionscript 3

Prerequisites for Actionscript documentation

Prerequisites for Javascript documentation

Actionscript 3 Code Documentation

Example documentation:

/**
* class-description
*/
class-declaration
/**
* method-description
*
* @see method-name
* @param name description
* @return description
*/
method-declaration.
/** attribute-description */
attribute-declaration

Extracting the documentation from the sourcecode:

asdoc.exe -source-path /source/directory -doc-sources /source/directory -output /output/directory -window-title "Project Title"

Javascript Code Documentation

Example documentation:

/**
 * class-description
 *
 * @author author
 * @extends class-name
 * @see class-name
 * @version version
 * @constructor
 */
class-constructor-declaration.
/**
 * method-description
 *
 * @see class-name#method-name
 * @param {data-type} name description
 * @return description
 * @type data-type-of-return
 */
method-declaration.

Extracting the documentation from the sourcecode:

perl jsdoc.pl /source/directory --directory /output/directory --project-name "Project Title"

References for this post

Multiple Inheritance in Javascript

Notice

Javascript does not support multiple inheritance, so the given method will break the instanceof operator! Javascript checks inheritance by traversing the linked list prototype.__proto__ for occurences of the requested prototype. This means that one prototype can only contain one reference to another prototype and in effect only inherit from one prototype. By discarding support for the instanceof operator, multiple inheritance can be simulated.

A support function is available that provide similar functionality as the instanceof operator.

Description and implementation details

The function responsible for applying inheritance between classes works by copying all missing attributes/methods from parent class(es) to the inheritance class. In addition, metadata in the class constructors allows for isInstanceOf() comparisons to to made on objects.

/**
 * Check if object is instance of given class.
 *
 * @param {Object} object Object to check inheritance of.
 * @param {Function} classConstructor Constructor function to check inheritance against.
 * @return Boolean indicating success of comparison.
 * @type {Boolean}
 */
function isInstanceOf(object, classConstructor) {
  // Check for class metadata
  if (object.constructor.meta === undefined || classConstructor.meta === undefined) {
    return object instanceof classConstructor; // Use standard inheritance test
  }
 
  // Use inheritance metadata to perform instanceof comparison
  return object.constructor.meta.fromClasses[classConstructor.meta.index] !== undefined;
}
 
/**
 * Applies inheritance to a class (first argument) from classes (second, third, and
 * so on, arguments).
 *
 * Notes:
 *  - This WILL BREAK the instanceof operator! Use the isInstanceOf() function instead.
 *  - Parent classes must be fully declared before calling this function.
 *  - Multiple classes will be copied in sequence.
 *  - Properties that already exists in class will not be copied.
 */
function applyInheritance() {
  // Validate arguments
  if (arguments.length < 2) {
    throw new Error("No inheritance classes given");
  }
 
  var toClass = arguments[0];
  var fromClasses = Array.prototype.slice.call(arguments, 1, arguments.length);
 
  // Check if class referencer has been created
  if (applyInheritance.allClasses === undefined) {
    applyInheritance.allClasses = [];
  }
 
  // Check for inheritance metadata in toClass
  if (toClass.meta === undefined) {
    toClass.meta = {
      index: applyInheritance.allClasses.length,
      fromClasses : [],
      toClasses: []
    };
    toClass.meta.fromClasses[toClass.meta.index] = true; // class links to itself
    applyInheritance.allClasses.push(toClass);
  }
 
  // Apply inheritance fromClasses
  var fromClass = null;
  for (var i = 0; i < fromClasses.length; i++) {
    fromClass = fromClasses[i];
 
    // Check for inheritance metadata in fromClass
    if (fromClass.meta === undefined) {
      fromClass.meta = {
        index: applyInheritance.allClasses.length,
        fromClasses: [],
        toClasses: []
      };
      fromClasses[i].meta.fromClasses[fromClass.meta.index] = true; // class links to itself
      applyInheritance.allClasses.push(fromClass);
    }
 
    // Link toClass and fromClass
    toClass.meta.fromClasses[fromClass.meta.index] = true;
    fromClass.meta.toClasses[toClass.meta.index] = true;
 
    // Copy prototype fromClass toClass
    for (var property in fromClass.prototype) {
      if (toClass.prototype.hasOwnProperty(property) === false) {
        // Copy missing property from the parent class to the inheritance class
        toClass.prototype[property] = fromClass.prototype[property];
      }
    }
  }
}

Multiple inheritance example:

function Animal(name) {
   // Attributes
   this.name = name;
}
 
Animal.prototype.makeSound = function (soundOutput) {
   soundOutput.playSound("Unknown");
};
 
Animal.prototype.getHierarchy = function () {
   return "Animal";
};
 
function Petable(personality) {
   // Attributes
   this.personality = personality;
}
 
Petable.prototype.isCompatible = function (personality) {
   return this.personality == personality;
};
 
function Dog(name, personality, breed) {
   // Call parent constructors
   Animal.call(this, name);
   Petable.call(this, personality);
 
   // Attributes
   this.breed = breed;
}
// Apply inheritance to Dog from Animal and Petable
applyInheritance(Dog, Animal, Petable);

An example of how to override a method of a parent class:

Dog.prototype.makeSound = function (soundOutput) {
   soundOutput.playSound("Bark");
};

An example of how an overidden method can delegate to it’s parent method:

Dog.prototype.getHierarchy = function () {
   // returns "Animal.Dog"
   return Animal.prototype.getHierarchy.apply(this, arguments) + ".Dog";
};

An example of how to call a parent method:

Dog.prototype.isOwner = function (name, personality) {
   if (this.name != name) {
      return false;
   }
 
   return Petable.prototype.isCompatible.call(this, personality);
};

Notes on calling function objects

References

Associative Arrays in Javascript

Introduction

The associative array (also known as hash map) is similar to the ordinary array. Instead of indexing by integers, the associative array uses string keys. It also lacks the bookkeeping abilities of the ordinary array like sort(), splice() etc. In Javascript every object has the ability to act as an associative array.

Creating an associative array and filling it with some data:

var container = {};
container["someKey"] = 3;
container["someOtherKey"] = someObject;
container["anotherKey"] = "Some text";
 
// ... or equivalently
var container = {
  someKey: 3,
  someOtherKey: someObject,
  anotherKey: "Some text"
};

Accessing elements in the associative array:

var someValue = container["someKey"];
container["otherKey"] = someValue;
 
// ... or equivalently
var someValue = container.someKey;
container.otherKey = someValue;

Iterating through all the elements in the associative array:

for (var key in container) {
   // hasOwnProperty() checks that attribute is from non-inherited prototype
   if (container.hasOwnProperty(key)) {
      var element = container[key];
   }
}

Deleting a key in the associative array:

delete container["someKey"];
 
// ... or equivalently
delete container.someKey;
 
// Notice: Don't assign null to the deleted key as
// this will re-create the key!

Checking if a key exists in the associative array:

if (container["someKey"] === undefined) {
   // Key does not exist
}
 
// ... or equivalently
if (container.someKey === undefined) {
   // Key does not exist
}

References