How to flip images horizontally with HTML5
Asked Answered
C

7

62

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 :)

Cogon answered 27/6, 2010 at 22:18 Comment(0)
R
129
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/

Rube answered 27/6, 2010 at 22:35 Comment(4)
is there a reason why do not we use css? transform: scaleX(-1); is there some issue like saving/posting image?Serotine
what if i need to draw multiple images in the same canvas but only of that to flip horizontallyIatrochemistry
@Serotine - yes, for saving to database, cloud, etc.Ryan
@rahulcp you can use ctx.save() to save a snapshot of your ctx settings and use ctx.restore() to revert to those settings after drawing the flipped image.Uke
L
77

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;
Litchi answered 28/6, 2010 at 17:0 Comment(2)
How have I lived without this?! Excellent!Insurrection
This is the coolest solution by far; Thank you CSS once again for making our lives easier...Hypertensive
C
14

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 :-)
Czerny answered 23/5, 2016 at 10:7 Comment(1)
i like that idea, i improved it a bit, so that i can use it with spritesheets and certain positionsLatchkey
L
6

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

Laverty answered 17/3, 2017 at 11:31 Comment(0)
Y
4

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 ;
}
Yonina answered 4/1, 2016 at 11:0 Comment(0)
C
3

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.

Confirmed answered 15/1, 2020 at 10:27 Comment(1)
That's good solution for me. But what about flop? like horizontal flippingBate
P
2

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();
}
Psychogenesis answered 8/12, 2015 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.