How to flip images horizontally with HTML5

HtmlCanvas

Html Problem Overview


In IE, I can use:

<img src="http://example.com/image.png" style="filter:FlipH">

to implement an image flip horizontally.

Is there any way to flip horizontally in HTML5? (maybe by using canvas?)

thanks all :)

Html Solutions


Solution 1 - Html

canvas = document.createElement('canvas');
canvasContext = canvas.getContext('2d');

canvasContext.translate(width, 0);
canvasContext.scale(-1, 1);
canvasContext.drawImage(image, 0, 0);

Here's a snippet from a sprite object being used for testing and it produces the results you seem to expect.

Here's another site with more details. http://andrew.hedges.name/widgets/dev/

Solution 2 - Html

You don't need HTML5, it can be done with CSS same as in IE:

-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
transform: scale(-1, 1);
filter: FlipH;

Solution 3 - Html

I like Eschers function above. I have made it a little neater and better. I have added flop (vertically) besides flip. Also a possibility to draw/rotate around the center of the image instead of top left. Finally, the function does not require all arguments. img, x and y are required but the rest are not.

If you were using something like context.drawImage(...), you can now just use drawImage(...) and add the rotate/flip/flop functionality explained here:

function drawImage(img, x, y, width, height, deg, flip, flop, center) {

context.save();

if(typeof width === "undefined") width = img.width;
if(typeof height === "undefined") height = img.height;
if(typeof center === "undefined") center = false;

// Set rotation point to center of image, instead of top/left
if(center) {
	x -= width/2;
	y -= height/2;
}

// Set the origin to the center of the image
context.translate(x + width/2, y + height/2);

// Rotate the canvas around the origin
var rad = 2 * Math.PI - deg * Math.PI / 180;	
context.rotate(rad);

// Flip/flop the canvas
if(flip) flipScale = -1; else flipScale = 1;
if(flop) flopScale = -1; else flopScale = 1;
context.scale(flipScale, flopScale);

// Draw the image    
context.drawImage(img, -width/2, -height/2, width, height);

context.restore();
}

Examples:

var myCanvas = document.getElementById("myCanvas");
var context = myCanvas.getContext("2d"); // i use context instead of ctx

var img = document.getElementById("myImage"); // your img reference here!

drawImage(img, 100, 100); // just draw it 
drawImage(img, 100, 100, 200, 50); // draw it with width/height specified
drawImage(img, 100, 100, 200, 50, 45); // draw it at 45 degrees
drawImage(img, 100, 100, 200, 50, 0, true); // draw it flipped
drawImage(img, 100, 100, 200, 50, 0, false, true); // draw it flopped
drawImage(img, 100, 100, 200, 50, 0, true, true); // draw it flipflopped
drawImage(img, 100, 100, 200, 50, 45, true, true, true); // draw it flipflopped and 45 degrees rotated around the center of the image :-)

Solution 4 - Html

One option is to horizontally flip the pixels of images stored in ImageData objects directly, e.g. function flip_image (canvas) { var context = canvas.getContext ('2d') ; var imageData = context.getImageData (0, 0, canvas.width, canvas.height) ; var imageFlip = new ImageData (canvas.width, canvas.height) ; var Npel = imageData.data.length / 4 ;

   	for ( var kPel = 0 ; kPel < Npel ; kPel++ ) {
   	   	var kFlip      = flip_index (kPel, canvas.width, canvas.height) ;
   	   	var offset     = 4 * kPel ;
   	   	var offsetFlip = 4 * kFlip ;
   	   	imageFlip.data[offsetFlip + 0] = imageData.data[offset + 0] ;
   	   	imageFlip.data[offsetFlip + 1] = imageData.data[offset + 1] ;
   	   	imageFlip.data[offsetFlip + 2] = imageData.data[offset + 2] ;
   	   	imageFlip.data[offsetFlip + 3] = imageData.data[offset + 3] ;
   	}

   	var canvasFlip = document.createElement('canvas') ;
   	canvasFlip.setAttribute('width', width) ;
   	canvasFlip.setAttribute('height', height) ;

   	canvasFlip.getContext('2d').putImageData(imageFlip, 0, 0) ;
   	return canvasFlip ;
}

function flip_index (kPel, width, height) {
   	var i     = Math.floor (kPel / width) ;
   	var j     = kPel % width ;
   	var jFlip = width - j - 1 ;
   	var kFlip = i * width + jFlip ;
   	return kFlip ;
}
<!-- end snippet -->

Solution 5 - Html

Mirror an image or rendering using the canvas.

> Note. This can be done via CSS as well.


Mirroring

Here is a simple utility function that will mirror an image horizontally, vertically or both.

function mirrorImage(ctx, image, x = 0, y = 0, horizontal = false, vertical = false){
    ctx.save();  // save the current canvas state
    ctx.setTransform(
        horizontal ? -1 : 1, 0, // set the direction of x axis
        0, vertical ? -1 : 1,   // set the direction of y axis
        x + (horizontal ? image.width : 0), // set the x origin
        y + (vertical ? image.height : 0)   // set the y origin
    );
    ctx.drawImage(image,0,0);
    ctx.restore(); // restore the state as it was when this function was called
}

Usage

mirrorImage(ctx, image, 0, 0, true, false); // horizontal mirror
mirrorImage(ctx, image, 0, 0, false, true); // vertical mirror
mirrorImage(ctx, image, 0, 0, true, true);  // horizontal and vertical mirror

Drawable image.

Many times you will want to draw on images. I like to call them drawable images. To make an image drawable you convert it to a canvas

To convert an image to canvas.

function makeImageDrawable(image){
    if(image.complete){ // ensure the image has loaded
        var dImage = document.createElement("canvas"); // create a drawable image
        dImage.width = image.naturalWidth;      // set the resolution
        dImage.height = image.naturalHeight;
        dImage.style.width = image.style.width; // set the display size
        dImage.style.height = image.style.height; 
        dImage.ctx = dImage.getContext("2d");   // get drawing API
                                                // and add to image
                                                // for possible later use
        dImage.ctx.drawImage(image,0,0);
        return dImage;
    }
    throw new ReferenceError("Image is not complete.");
 }

Putting it all together
 var dImage = makeImageDrawable(image);  // convert DOM img to canvas
 mirrorImage(dImage.ctx, dImage, 0, 0, false, true); // vertical flip
 image.replaceWith(dImage);  // replace the DOM image with the flipped image
 

More mirrors

If you wish to be able to mirror along an arbitrary line see the answer Mirror along line

Solution 6 - Html

I came across this page, and no-one had quite written a function to do what I wanted, so here's mine. It draws scaled, rotated, and flipped images (I used this for rending DOM elements to canvas that have these such transforms applied).

var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
var img = document.getElementById("myimage.jpg"); //or whatever
var deg = 13; //13 degrees rotation, for example
var flip = "true";

function drawImage(img, x, y, width, height, deg, flip){
    //save current context before applying transformations
    ctx.save();
    //convert degrees to radians
    if(flip == "true"){ 
        var rad = deg * Math.PI / 180;
    }else{
        var rad = 2*Math.PI - deg * Math.PI / 180;
    }
    //set the origin to the center of the image
    ctx.translate(x + width/2, y + height/2);
    //rotate the canvas around the origin
    ctx.rotate(rad);
    if(flip == "true"){
        //flip the canvas
        ctx.scale(-1,1);
    }
    //draw the image    
    ctx.drawImage(img, -width/2, -height/2, width, height);
    //restore the canvas
    ctx.restore();
}

Solution 7 - Html

For anyone stumbling upon this. If you want to do more complex drawing, the other scale-based answers don't all work. By 'complex' i mean situations where things are more dynamic, like for games.

The problem being that the location is also flipped. So if you want to draw a small image in the top left corner of the canvas and then flip it horizontally, it will relocate to the top right.

The fix is to translate to the center of where you want to draw the image, then scale, then translate back. Like so:

if (flipped) {
  ctx.translate(x + width/2, y + width/2);
  ctx.scale(-1, 1);
  ctx.translate(-(x + width/2), -(y + width/2));
}
ctx.drawImage(img, x, y, width, height);

Here x and y are the location you want to draw the image, and width and height are the width and height you want to draw the image.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKoerrView Question on Stackoverflow
Solution 1 - HtmlBuildstartedView Answer on Stackoverflow
Solution 2 - HtmlrobertcView Answer on Stackoverflow
Solution 3 - HtmlDesignConsultView Answer on Stackoverflow
Solution 4 - HtmlDaniel KorenblumView Answer on Stackoverflow
Solution 5 - HtmlBlindman67View Answer on Stackoverflow
Solution 6 - HtmlEscherView Answer on Stackoverflow
Solution 7 - HtmlMartijnView Answer on Stackoverflow