Page 1 of 2 Working with lower level data is very much part of graphics. This extract from Ian Elliot's book on JavaScript Graphics looks at how to use typed arrays to access graphic data.
Now available as a paperback or ebook from Amazon.
JavaScript Bitmap Graphics With Canvas
Contents
- JavaScript Graphics
- Getting Started With Canvas
- Drawing Paths
Extract: Basic Paths Extract: SVG Paths Extract: Bezier Curves
- Stroke and Fill
Extract: Stroke Properties Extract: Fill and Holes Extract: Gradient & Pattern Fills
- Transformations
Extract: Transformations Extract: Custom Coordinates Extract Graphics State
- Text
Extract: Text, Typography & SVG Extract: Unicode
- Clipping, Compositing and Effects
Extract: Clipping & Basic Compositing
- Generating Bitmaps
Extract: Introduction To Bitmaps Extract : Animation
- WebWorkers & OffscreenCanvas
Extract: Web Workers Extract: OffscreenCanvas
- Bit Manipulation In JavaScript
Extract: Bit Manipulation
- Typed Arrays
Extract: Typed Arrays
- Files, blobs, URLs & Fetch
Extract: Blobs & Files Extract: Read/Writing Local Files Extract: Fetch API **NEW!
- Image Processing
Extract: ImageData Extract:The Filter API
- 3D WebGL
Extract: WebGL 3D
- 2D WebGL
Extract: WebGL Convolutions
<ASIN:B07XJQDS4Z>
<ASIN:1871962579>
<ASIN:1871962560>
JavaScript's typed arrays provide a way to work with binary data and to work with structures that would otherwise be very difficult. In this chapter we look at the basic idea of using typed arrays - views, BufferArray and block operations. This leads on to features such as blobs and dataURLs all of which are often useful when working with bitmaps and are covered in the next chapter.
JavaScript is a lightly typed language, and this is how most users like it, but there are times when you need to work with data that has specific representations. For example, you might need to read in and work with a byte array. Here it isn't only the case that each array element should behave like a byte data type, i.e. be limited to 0 to 255, but it is also important that it is stored using a single byte of memory and the array should be a contiguous area of memory treated as a sequence of bytes. In such a situation it isn't clear that is really is a case of data typing, but more a way of getting back to the underlying representation of the data.
To make the point clearer - anything you can store in a typed array can be stored in a standard JavaScript Array object. In this sense you get nothing new apart from the guarantee of a particular layout in memory and the representation used.
Typed arrays were introduced in JavaScript to allow it to work with OpenGL as part of the implementation of WebGL. While previously you could arrange to convert a JavaScript Array into whatever the API needed, a byte array say, this proved to be too slow. Typed arrays enable the data to be constructed in JavaScript in a format that can be consumed without conversion by the API, so improving performance.
Since their introduction, typed arrays have become a way of working with external frameworks of all kinds and a way of accessing binary data directly. Before typed arrays the standard way of working with binary data was to store it as a string and convert each character to and from its representation as an integer. Typed arrays make binary data much easier to work with.
There is also the issue of efficiency. Typed arrays allow the JavaScript engine to perform some optimizations, but these depend on the engine and are a matter of some ongoing debate. Here we focus on the way typed arrays allow us to work with binary data rather than matters of efficiency.
Basic Typed Arrays
The way that typed arrays work is very simple and very powerful and very similar to the way that arrays work in C.
Creating a typed array is just a matter of using the array's constructor. For example:
var bytes=new Uint8Array(10);
bytes[0]=0xFF;
bytes[9]=0xFF;
console.log(bytes[0]);
creates an array of 10 unsigned 8-bit types. Notice that once created you can use the array as normal, but it doesn't have all of the methods that the Array object does. In this case the array elements are single bytes representing 0 to 255. All typed arrays are initialized to 0 when created.
Notice that the array is allocated enough memory to hold all of the elements when it is first constructed. For example:
var Ints=new Uint16Array(10);
creates an array of 16-bit unsigned integers and hence allocates 20 bytes of memory to store the entire array.
There are types for one-, two- and four-byte integer values, both signed and unsigned, and a four- and eight-byte float and using any of the typed arrays follows the same pattern:
Type
|
Size
|
Description
|
Equivalent C type
|
Int8Array
|
1
|
8-bit two’s complement signed integer
|
signed char
|
Uint8Array
|
1
|
8-bit unsigned integer
|
unsigned char
|
Uint8ClampedArray
|
1
|
8-bit unsigned integer
|
unsigned char
|
Int16Array
|
2
|
16-bit two’s complement signed integer
|
short
|
Uint16Array
|
2
|
16-bit unsigned integer
|
unsigned short
|
Int32Array
|
4
|
32-bit two’s complement signed integer
|
int
|
Uint32Array
|
4
|
32-bit unsigned integer
|
unsigned int
|
Float32Array
|
4
|
32-bit IEEE floating point number
|
float
|
Float64Array
|
8
|
64-bit IEEE floating point number
|
double
|
The only type that might need further explanation is the Uint8ClampedArray. A byte variable has a very small range 0 to 255 and usually overflow is a problem. There are generally two ways to deal with this, either rollover to 0 after 255, or to use saturation arithmetic which clamps the value to 255. In other words, Uint8ClampedArray doesn't allow a value bigger than 255 and:
clamped[0]=255+1
is 255.
If you need to support a wide range of browsers, note that IE10 doesn't support clamped arrays. Notice also that for the unclamped array types the alternative strategy is taken and the value rolls over. For example:
bytes[0]=255+1;
is 0. It also rolls over if you try to assign a value that is too large. So rollover is the rule for all typed arrays except for clamped.
|