Canvas Bitmap Operations - bitblt in JavaScript
Written by Ian Elliot
Thursday, 31 May 2018
Article Index
Canvas Bitmap Operations - bitblt in JavaScript
ImageData object
Security
Page 1 of 3

With Canvas you can now work with bitmaps at the pixel level. It's not difficult but you need to organise things to make it really easy and a good understanding helps.

Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas

[画像:largecover360]

Contents

  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
    Extract: Basic Paths
    Extract: SVG Paths
    Extract: Bezier Curves
  4. Stroke and Fill
    Extract: Stroke Properties
    Extract: Fill and Holes
    Extract: Gradient & Pattern Fills
  5. Transformations
    Extract: Transformations
    Extract: Custom Coordinates
    Extract Graphics State
  6. Text
    Extract: Text, Typography & SVG
    Extract: Unicode
  7. Clipping, Compositing and Effects
    Extract: Clipping & Basic Compositing
  8. Generating Bitmaps
    Extract: Introduction To Bitmaps
    Extract : Animation
  9. WebWorkers & OffscreenCanvas
    Extract: Web Workers
    Extract: OffscreenCanvas
  10. Bit Manipulation In JavaScript
    Extract: Bit Manipulation
  11. Typed Arrays
    Extract: Typed Arrays
  12. Files, blobs, URLs & Fetch
    Extract: Blobs & Files
    Extract: Read/Writing Local Files
    Extract: Fetch API **NEW!
  13. Image Processing
    Extract: ImageData
    Extract:The Filter API
  14. 3D WebGL
    Extract: WebGL 3D
  15. 2D WebGL
    Extract: WebGL Convolutions

<ASIN:B07XJQDS4Z>

<ASIN:1871962579>

<ASIN:1871962560>

One of the operations that low-level APIs tend to give you that higher level graphics systems tend to ignore is the bitblt - bit-block operation (pronounced bit-blit). This is essentially a low-level copy of a group of bits stored in memory to another area of memory.

What has this got to do with graphics?

The answer is that in many cases the bits represented the pixels of a bitmap and the bitblt was one way to update or modify another bitmap by copying another bitmap into it. Bitblt operations are useful when ever you want to perform dynamic updating of an bitmap and the good news is that at long last you can now do this using JavaScript and its is all because of the canvas object.

Until the canvas object was introduced as part of HTML5 JavaScript could be used to load and display images but you couldn't dynamically modify or generate images. Load and display was as far as it went. Now you can get at and modify pixels as much as you like.

It is assumed that you know the basics of using the canvas tag. If not read A Programmer's Guide to Canvas first. For simplicity the browser used is Chrome but you can use Firefox, Edge or any modern browser.

Drawing an image

The first part of the canvas bitmap operations that we need to look at is the drawImage method.

This will draw a bitmap onto a canvas.

What is interesting about this method is not so much that it provides a link between a bitmap and the canvas object but the range of bitmap sources that can be used.

The source for a bitmap can either be a bitmap object, another canvas object or a video object. Notice that if you are using a canvas object as the source of the bitmap you have to have actually drawn something on it first and you have to use the canvas object not the drawing context - see later for an example. If you use a video object then the current frame is rendered to the canvas.

To start with the simplest you can take any standard Image object and draw it to the canvas. You can derive your image object from the DOM or create it directly within JavaScript.

For example suppose the page contains an image:

<img id="myImage" src="/test.jpg"/>

then you can retrieve the image object from the DOM using:

var img1=document.getElementById("myImage");

and you can then display it on the canvas, with the 2D drawing context stored in ctx, using:

ctx.drawImage(img,10, 10);

The drawImage method takes a number of different parameters but in this simply form drawImage(image,x,y) simply draws as much of the image that fits on the canvas with its top left hand corner at x,y.

The only problem is that you have to make sure that the image has loaded before you try using it. If this is a problem use:

img.addEventListener("load", function(){
ctx.drawImage(img1, 0,0);
});

Alternatively you could load the image dynamically using JavaScript. The only problem with this approach is that you have to use asynchronous code to allow for the time to download the bitmap. For example:

var img=new Image();
img.onload = function(){
ctx.drawImage(img,0, 0);
}
img.src = "test.jpg";

In this case the loading of the bitmap starts as soon as the src property is set. When the bitmap is loaded the onload function is called which draws it to the canvas. (Notice the way closure makes this asynchronous code much easier to write because the callback can still access ctx even though it is out of scope at the point the function is called.)

The complete program is:

<body>
<canvas id="Canvas"
width="600" height="600"
style="height:600px;width:600px;">
</canvas>
</body>
<script>
var c = document.getElementById("Canvas");
var ctx = c.getContext("2d");
var img=new Image();
img.onload = function(){
ctx.drawImage(img, 10, 10);
img.src = "test.jpg";
</script>

If you want to scale the image then use the alternative form of the drawImage method:

drawImage(image,x,y,w,h);

where w and h specify the width and height that the image is scaled to. For example:

ctx.drawImage(img,10, 10,300,300);

[画像:scale1]

The problem here is that you might well distort the bitmap by scaling it unequally in the x and y directions. The solution is to use the Image object's width and height properties:

ctx.drawImage(img,10,10,img.width/4,img.height/4);

[画像:scale2]

The final form of the drawImage method give you complete control over the way the image is drawn:

drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)

This looks complicated but it simply specifies the location of a source and a destination rectangle. The source rectangle has its top left hand corner at sx,sy and is sw wide and sh high. The destination rectangle has its top left hand corner at dx,dy and it is dw wide and dh high. The draw copies pixels in the source rectangle to the source rectangle performing any scaling that is needed. For example, to display the area of the bitmap within the rectangle with its top left-hand corner at 700,200 of width 600 and height 800 to the canvas in a square with its top left-hand corner at 0,0 and side 200 you would use:

ctx.drawImage(img,700,200,600,600,0,0,200,200);

[画像:scale3]

Finally you can use all three versions of the drawImage method with another canvas object as the source of the bitmap.

For example:

ctx2.drawImage(canvas,0,0,200,200);

will draw the contents of canvas onto the drawing context ctx2 of another canvas object.

You can also draw a canvas object onto itself. For example

ctx.drawImage(canvas,0,0,200,200);

will copy the contents of the canvas object back onto itself in a 200 by 200 rectangle if ctx is the drawing context of the canvas object. Notice that the source bitmap is copied before it is drawn back to the canvas.

So to summarize:

There are three drawImage methods

  • drawImage(image,dx,dy)
  • drawImage(image,dx,dy,dw,dh)
  • drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)

Where image is either a canvas, video or an image object derived either from the DOM or constructed in JavaScript and sx,sy,sw,sh define the source rectangle and dx,dy,dw,dh define the destination rectangle.


Prev - Next >>

Last Updated ( Thursday, 06 September 2018 )