Monthly news review


This post reviews news in the month that has passed. Comment below to leave your opinion.

$150 Smartphone spectrometer can tell the number of calories in your food

Not a day goes by without a new accessory for Smartphone being unveiled. We now have accessories for everything from health to payments. A miniature spectrometer is however something unheard of, especially one backed by a cloud service that learns from every scan. One step closer to the tricorder. Awesome.

The perfect iOS email app finally exists

Accompli is being touted as a better (nay perfect) e-mail app. Like Outlook, it has mail, calendar and contacts, all working seamlessly. The attachments view is fantastic to quickly find and send attachments. There are a few rough edges, which is to be expected in a freshly baked app.

HTML5 apps can be just as speedy as native apps with the new Famo.us Javascript framework

The Famo.us open source framework is tackling performance of mobile browsers as a platform problem aka HTML5 head-on. Currently, their site is invite-only, which I received a couple of days back. I’ve been through their demos using Chrome for Desktop and iOS and they are stellar.

Car-hacking: A New Fear For Drivers of Tech-Loaded Vehicles

As our cars get more tech savvy and connected, they’ll be more prone to the same kinds of vulnerabilities that affect other computing devices. While you are still driving around in your old(ish) car you can still do some neat things this month: use CarPlay if you have the right system from Pioneer, control your Smartphone hands-free using Bluetooth LE, evaluate your driving performance, and get haptic feedback to avoid running into trouble. The latter is rather ambitious.

Massive Security Bug In OpenSSL Could Affect A Huge Chunk Of The Internet

I hope you have heard of this flaw already. Otherwise, stop whatever you’re doing, update your computer systems, review what your service providers have done about it, and change your passwords on compromised services. It is serious and needs immediate action. The sad thing is that the flaw has been known to some for a while.

Now, when did our governments decide they could spy on us without using the legal system? Brazil has taken the first steps to prevent that kind of thing from happening by passing an Internet Bill of Rights (text in Portuguese).

Amazon unveils Fire TV

Amazon has taken a leap over Apple’s hobby by creating a device for its Prime subscribers. It also looks like a nice low-end game console, no console (pun intended) there for Nintendo and others. If I were Nintendo, I would stop making consoles (sold at cost) and make money on mobile games. Amazon has also subtly changed their branding by not calling it Kindle Fire TV.

Microsoft Launches .NET Foundation

Microsoft is recognizing the fact that the .NET community is keen on using C# everywhere. A C# programmer can now target several platforms thanks to Xamarin. Reuse is the keyword that comes to mind when thinking of .NET these days. It used to be so with Java, and thanks to Google and Android it still is (somewhat). Oracle, though, wants to litigate instead of fanning the embers.

In related news, Microsoft has also announced that Windows for the internet of things will be free. That includes all devices with screen size under 9 inches. And, PC users can now update Windows 8.1. Slowly and steadily Microsoft has made Windows 8 more PC-user friendly.

Monthly news review


Continuing the series on monthly, predominantly technological, news review…

CarPlay

iOS has arrived in the car, at least the premium car, not that it wasn’t there already. The experience is based around your iOS device and makes driving as distraction-free as possible.

Popcorn Times

Popcorn Times was born, died and re-born. Watching pirated movies online is nothing new, make it convenient and you’ve got a winner. What makes the application itself interesting is its use of Node-WebKit and peerflix.

Android Wear

No doubt now that Google is taking Android to wearables, starting with smartwatches. These days it looks like everyone is one-upping Apple, but somehow it ends up raking in all the profits.

WebScaleSQL

That’s a nerdy name for a new fork of MySQL that scales better.

Facebook buying Oculus VR

Looks like Facebook is making use of its cash reserves again. Earlier, they paid significantly more to buy WhatsApp.

Office for iPad

Lot’s of Office news this month, concluding with Microsoft launching Office for iPad. It is already top of charts in several countries. Earlier Microsoft launched a free OneNote app for Mac. I wonder which Office app is most useful, now that everyone concurs PowerPoints should be ditched.

ReadMill team acqhired by Dropbox

ReadMill was my favorite reading app for a while. Unfortunately, and especially on mobile, e-books are not easily ported to other apps.

Philips announces 4K TV with Android

TV makers have adopted widely divergent Smart TV OS strategies. LG has embraced WebOS. Samsung has embraced something akin to Chrome OS with support for HTML 5, Native Client, and WebGL. Will Android take over?

CorelDRAW Graphics Suite X7

CorelDRAW has announced the X7 iteration of their suite. The user interface has received a significant overhaul. Heavy users will encounter a crash every other day that will make them lose their work, that has not changed.

Quake III on Raspberry Pi using open source graphics driver

Last month Broadcom announced open source drivers for the GPU on Raspberry Pi. Simon Hall has thus claimed the bounty announced by Raspberry Pi Foundation. In unrelated news, Oxford Flood Network uses Raspberry Pi to monitor flooding levels. Interesting convergence of ideas such as smart cities, internet of things, and open hardware.

Angry Birds for Chrome is a milestone for HTML 5


Angry Birds for Chrome is in their Web Store (now discontinued), I consider it a milestone for HTML5, and WebGL in particular. Some colleagues are reporting that it works better on Internet Explorer 9.

Use Tile Studio to construct tiled maps


Tile Studio is a free and open source utility for making tile based games. The key features of Tile Studio are:

  1. Manage several tile sets in a single project. Multiple maps can be created with each tile set.
  2. Bitmap editor for editing tiles.
  3. Specify bounds for collision detection. The left, right, top, bottom and diagonals of a cell can be marked. The bounds can be exported, along with other map data, to be used in games or applications.
  4. Specify a one byte map code for any cell in the map. This can be used to tag each cell with a special value which can indicate, among other things, enemy positions in games.
  5. Create and use animated tiles.
  6. Export tile sets to image files in bitmap or PNG format.
  7. Export map data to binary files.
  8. Generate game code using templates.

Exporting the tile map from Tile Studio

Tile Studio provides means to export map data to files by means of templates [5]. These templates can produce complete source code or just simple text or binary files. In the example template (see export.tsd) below we do two things:

  1. Export the tile set images to PNG files
  2. Produce a binary file containing a sequence of 32 bit integer values, by reading the map data row by row. Each 32 bit integer is a result of the concatenation of the tile index, the bound values and the map code. We assume that we will not need more than 2^15 – 1 tiles in each tile set (32767 tiles is quite a large number of tiles!).

The images created by Tile Studio can and should be optimized further using image manipulation tools to optimize the color depth (palette size) and so on. Programs such as pngout, which optimize the image size further by using better compression, can also be used.

export.tsd

;
; Create the tile set bitmap. The width by default has been limited to 160
; pixels. Adjust this as required.
;
#tileset
#tilebitmap <TileSetIdentifier>.png 160
#end tilebitmap
#end tileset

;
; Generate binary files containing map data. The file format is an
; ordinary sequence of 32 bit values.
;
#tileset
#map
; concatenate tile number, bounds data and map value into a 32 bit value
#binfile <MapIdentifier>.bin 32
#mapdata
<TileNumber:"16"><BoundMapValue:"16">
#end mapdata
#end binfile
#end map
#end tileset

Compressing map data

The binary file exported from Tile Studio in the previous section can be optimized further. This may need to be done to keep the resources of J2ME games and applications to the smallest size possible. Unfortunately the template language provided by the tool itself is quite limited so we have built a simple java utility for this task. The source code of the utility is shown below (see TileStudioUtil.java). Have a look at the javadoc of the writeSparseMatrix method, to get a notion of the format of the output file created by this utility. The utility can be executed in the following manner to produce the binary file (diags.map) used in the example in the next section:

java TileStudioUtil diags.bin diags.map 20 20 1

TileStudioUtil.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

public class TileStudioUtil {

    private static final int INFILE_INDEX = 0;

    private static final int OUTFILE_INDEX = 1;

    private static final int HEIGHT_INDEX = 2;

    private static final int WIDTH_INDEX = 3;

    private static final int INDEXSIZE_INDEX = 4;

    private static final int NUM_ARGUMENTS = 5;

    /**
     * Main method.
     *
     * @param args
     *            Arguments to the main method
     */
    public static void main(String[] args) {
        try {
            System.out.println(args.length + " arguments received.");
            if (args.length < NUM_ARGUMENTS) {
                System.out
                        .print("Command line options: ");
                System.out
                        .println("infile outfile height width indexSize");
                System.out
                        .print("infile\t\t");
                System.out
                        .println("The binary file exported from Tile Studio");
                System.out
                        .print("outfile\t\t");
                System.out
                        .println("The binary file exported by this program");
                System.out.println("height\t\tThe height of the matrix");
                System.out.println("width\t\tThe width of the matrix");
                System.out
                        .print("indexSize\tThe storage size of the matrix");
                System.out
                        .println("index in bytes");
                System.exit(0);
            }

            int indexSize = Integer.parseInt(args[INDEXSIZE_INDEX]);
            int width = Integer.parseInt(args[WIDTH_INDEX]);
            int height = Integer.parseInt(args[HEIGHT_INDEX]);
            int a[][] = new int[height][width];
            InputStream in;
            OutputStream out;

            System.out.println("Reading file " + args[INFILE_INDEX]);
            in = new FileInputStream(args[INFILE_INDEX]);
            readMatrix(in, a, height, width);
            in.close();

            System.out.println("Writing file " + args[OUTFILE_INDEX]);
            out = new FileOutputStream(args[OUTFILE_INDEX]);
            writeSparseMatrix(out, a, height, width, indexSize);
            out.close();

            System.out.println("Testing file written");
            int b[][] = new int[height][width];
            in = new FileInputStream(args[OUTFILE_INDEX]);
            readSparseMatrix(in, b, height, width, indexSize);
            in.close();

            // Compare
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (a[i][j] != b[i][j]) {
                        System.out.println("Different data at row " + i
                                + ", column " + j);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    /**
     * Read an int value from an array of bytes.
     *
     * @param data
     *            an array of bytes, only the first four elements are read
     * @param littleEndian
     *            Pass true if the least signficant byte is stored in the first
     *            element of the byte array
     *
     * @return int value
     * @throws IllegalArgumentException
     */
    public static int toInt(byte[] data, boolean littleEndian)
            throws IllegalArgumentException {
        int val = 0;

        if (littleEndian) {
            for (int i = 0; i < data.length; i++) {
                val += (data[i] & 0xFF) << (i * 8);
            }
        } else { // big endian
            for (int i = 0; i < data.length; i++) {
                val += (data[i] & 0xFF) << ((data.length - i - 1) * 8);
            }
        }

        return val;
    }

    /**
     * Write an int to an array of bytes.
     *
     * @param i
     *            The int value to write
     * @param data
     *            The byte array to write to
     * @param littleEndian
     *            If set to true the least significant byte is stored first
     * @throws IllegalArgumentException
     */
    public static void toByteArray(int i, byte[] data, boolean littleEndian)
            throws IllegalArgumentException {
        if (data.length < 4) {
            throw new IllegalArgumentException("Need at least 4 bytes");
        }

        if (littleEndian) {
            data[3] = (byte) ((i >>> 24) & 0xFF);
            data[2] = (byte) ((i >>> 16) & 0xFF);
            data[1] = (byte) ((i >>> 8) & 0xFF);
            data[0] = (byte) (i & 0xFF);
        } else {
            data[0] = (byte) ((i >>> 24) & 0xFF);
            data[1] = (byte) ((i >>> 16) & 0xFF);
            data[2] = (byte) ((i >>> 8) & 0xFF);
            data[3] = (byte) (i & 0xFF);
        }
    }

    /**
     * Reads an int matrix in binary format into an array. The file structure is
     * a simple sequence of int values. Each int is little endian. All int
     * values in the first row are stored sequentially followed by all int
     * values in the second row and so on.
     *
     *
     * @param file
     *            Binary file
     * @param array
     *            Data array
     * @param width
     *            The array width
     * @param height
     *            The array height
     * @throws IOException
     */
    public static void readMatrix(InputStream in, int array[][], int rows,
            int columns) throws IOException {
        byte[] data = new byte[4];
        int n, r, c;

        r = 0;
        while (r < rows) {
            c = 0;
            while (c < columns) {
                n = in.read(data);
                if (n == -1)
                    throw new IOException("Error reading map data at row " + r
                            + " and column " + c);
                array[r][c] = toInt(data, true);
                c++;
            }
            r++;
        }

    }

    /**
     * Writes a sparse matrix to a binary format. The binary format is a simple
     * structure as represented in the BNF notation below:
     *
     * <pre>
     *       number_of_types (type number_of_positions (positions)+)+
     *       number_of_types ::= int value
     *       type ::= int value
     *       number_of_positions ::= int value
     *       positions ::= row column
     *       row ::= int value stored in indexSize bytes
     *       column ::= int value stored in indexSize bytes
     * </pre>
     *
     * A type is any unique value, other than zero, that occurs at least once
     * in the array.
     *
     * @param out
     *            Binary output stream
     * @param array
     *            Data array
     * @param rows
     *            The number of rows in the matrix
     * @param columns
     *            The number of columns in the matrix
     * @param indexSize
     *            Size in bytes of row or column index
     *
     * @throws IOException
     */
    public static void writeSparseMatrix(OutputStream out, int array[][],
            int rows, int columns, int indexSize) throws IOException {
        byte[] data; // a byte array to store int
        Hashtable table = new Hashtable(); // a hashtable to store type
                                            // locations
        int r, c;
        Integer type; // A type (unique value) in the array
        Vector positions; // a vector to store positions of a type
        Enumeration keys;
        Iterator p;

        // Analyze data and store it in an optimized format in memory
        for (r = 0; r < rows; r++) {
            for (c = 0; c < columns; c++) {
                if (array[r][c] == 0)
                    continue;

                type = new Integer(array[r][c]);
                if (table.containsKey(type)) {
                    positions = ((Vector) table.get(type));
                } else {
                    positions = new Vector();
                    table.put(type, positions);
                }
                data = new byte[4];
                toByteArray(r, data, true);
                positions.add(data);
                data = new byte[4];
                toByteArray(c, data, true);
                positions.add(data);
            }
        }

        // Dump sparse matrix to binary file

        data = new byte[4];

        // write number of types
        toByteArray(table.size(), data, true);
        out.write(data);

        keys = table.keys();
        while (keys.hasMoreElements()) {
            type = (Integer) keys.nextElement();

            // write type
            toByteArray(type.intValue(), data, true);
            out.write(data);

            positions = (Vector) table.get(type);

            // write number of positions the type occurs
            toByteArray(positions.size() / 2, data, true);
            out.write(data);

            // write positions of type
            p = positions.iterator();
            while (p.hasNext()) {
                out.write((byte[]) p.next(), 0, indexSize);
            }
        }

    }

    /**
     * Read a sparse matrix from a binary format.
     *
     * @param file
     *            File with binary data
     * @param array
     *            Array to write to
     * @param rows
     *            Rows in the matrix
     * @param columns
     *            Columns in the matrix
     * @param indexSize
     *            The storage size of the matrix index in bytes
     * @throws IOException
     *
     * @see #writeSparseMatrix(OutputStream, int[][], int, int, int)
     */
    public static void readSparseMatrix(InputStream in, int array[][],
            int rows, int columns, int indexSize) throws IOException {
        byte[] data = new byte[4]; // a byte array to store int
        byte[] pos = new byte[indexSize]; // a byte array to store position
        int bytesRead, numTypes, t, type, numPositions, n, r, c;

        // Read sparse matrix from binary file

        // read number of types
        bytesRead = in.read(data);
        if (bytesRead == -1)
            throw new IOException("Error reading number of types");
        numTypes = toInt(data, true);

        for (t = 0; t < numTypes; t++) {
            // read type
            bytesRead = in.read(data);
            if (bytesRead == -1)
                throw new IOException("Error reading type");
            type = toInt(data, true);

            // read number of positions
            bytesRead = in.read(data);
            if (bytesRead == -1)
                throw new IOException("Error reading number of positions");
            numPositions = toInt(data, true);

            for (n = 0; n < numPositions; n++) {
                // read row
                bytesRead = in.read(pos);
                if (bytesRead == -1)
                    throw new IOException("Error reading row");
                r = toInt(pos, true);
                // read column
                bytesRead = in.read(pos);
                if (bytesRead == -1)
                    throw new IOException("Error reading column");
                c = toInt(pos, true);

                array[r][c] = type;
            }

        }

    }
}

Tiled is another neat editor for creating tiled maps.

Immersive content for the Browser


Second life is probably the best example of a 3D simulated universe, a highly immersive experience.

I’ve seen experiments in rendering 3D using Javascript. The HTML 5 Canvas element is at the center of that revolution. Check CanvasMOL as one example of what is possible. Chrome and other webkit-based browsers have been working on GPU-based acceleration of the HTML 5 Canvas and the associated WebGL 3D graphics API. Check this cool demo of WebGL in action. Browser-based games that use these features are beginning to appear. Imagine racing cars such as rendered by HelloRacer.

Adobe Flash is used by pretty much everyone in the 2D gaming community. Check out Club Penguin and Habbo as examples of this approach. Unity 3D is also available for doing Browser-based games in Java for the web, and also for a raft of different devices.

All in all, developers love it when they can target different devices and form-factors from the same code base, without worrying about obsolescence. HTML 5 may really shine there.