mane
mane

Reputation: 1179

Is it possible to rotate an image if you only have image data url using javascript?

I have a problem where I need to rotate an image but I only have the image data url available.

What I need to do is rotate the image first and then load it in the canvas, and I can't rotate the image after loading it in the canvas.

Is it possible to rotate image if you only have the image data url.

Upvotes: 3

Views: 10504

Answers (3)

Roman Grinev
Roman Grinev

Reputation: 1037

There is a simple function to rotate the data URL image. It works even if your image has a width and height that do not equal like in nicael answer.

var src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/wAALCAAmACgBAREA/8QAGQAAAgMBAAAAAAAAAAAAAAAABggAAwcJ/8QAKRAAAQMDAwMEAgMAAAAAAAAAAQIDBAAFEQcSIQYTMTJBUYEUoSIjkf/aAAgBAQAAPwDpRVUuWzAjOSJDqWWGxuW4s4CRQDK1usTc5Edht99BWEqkKGxtIz5+cfVH8eQ1LYQ8w4l1lwbkrQchQ+QasqUAa2vdvolSd+0rkNjGfUOTS/Uweijxc6HbSV7tj7iQM52jg4o9qUE6vWJd66PeW0krehqEhKR7gcK/RJ+qXWmN0ksSrJ0bHLgKXpajIUD7A+n9Af7RnVUmUzDZU8+6hlpPKluKCQPs1l2ouq9tds8q22h5UmQ8O2p9Kf60pPqwT5OOOKxWtw0/1XtZtEK3XR8xJbKA13XE4bUBwnkeOMea0xh9qS0l1lxLrahlK0KBB+6XjVq9TZ/WE+I8+tUWMsIaZz/FPAOcfPPmgqpUo+0cvU2J1bGgofX+HISvuMk5SSEkggex4r//2Q=="

var img_src = document.createElement('img')
img_src.src = src
document.getElementById('container').appendChild(img_src)


rotate90(src,function(res){
   var img_res = document.createElement('img')
   img_res.src = res
   document.getElementById('container').appendChild(img_res)
})

function rotate90(src, callback){
  var img = new Image()
  img.src = src
  img.onload = function() {
    var canvas = document.createElement('canvas')
    canvas.width = img.height
    canvas.height = img.width
    canvas.style.position = "absolute"
    var ctx = canvas.getContext("2d")
    ctx.translate(img.height, img.width / img.height)
    ctx.rotate(Math.PI / 2)
    ctx.drawImage(img, 0, 0)
    callback(canvas.toDataURL())
  }
}
<div id="container"></div>

Also, you can try it here

Upvotes: 4

f01
f01

Reputation: 1856

You can reverse the following function to get the bitmap/pixels from bytes. This was taken from this example based on this guide. After you have the pixels do the old school rotation one pixel at a time. I included an example (but in C++ sorry!) how to rotate pixels one at a time. Then generate again the image data URL using the same logic as below.

 window.generateBitmapDataURL = function(rows, scale) {
        // Expects rows starting in bottom left
        // formatted like this: [[[255, 0, 0], [255, 255, 0], ...], ...]
        // which represents: [[red, yellow, ...], ...]

        if (!window.btoa) {
            alert('Oh no, your browser does not support base64 encoding - window.btoa()!!');
            return false;
        }

        scale = scale || 1;
        if (scale != 1) {
            rows = _scaleRows(rows, scale);
        }

        var height = rows.length,                                // the number of rows
            width = height ? rows[0].length : 0,                 // the number of columns per row
            row_padding = (4 - (width * 3) % 4) % 4,             // pad each row to a multiple of 4 bytes
            num_data_bytes = (width * 3 + row_padding) * height, // size in bytes of BMP data
            num_file_bytes = 54 + num_data_bytes,                // full header size (offset) + size of data
            file;

        height = _asLittleEndianHex(height, 4);
        width = _asLittleEndianHex(width, 4);
        num_data_bytes = _asLittleEndianHex(num_data_bytes, 4);
        num_file_bytes = _asLittleEndianHex(num_file_bytes, 4);

        // these are the actual bytes of the file...

        file = ('BM' +               // "Magic Number"
                num_file_bytes +     // size of the file (bytes)*
                '\x00\x00' +         // reserved
                '\x00\x00' +         // reserved
                '\x36\x00\x00\x00' + // offset of where BMP data lives (54 bytes)
                '\x28\x00\x00\x00' + // number of remaining bytes in header from here (40 bytes)
                width +              // the width of the bitmap in pixels*
                height +             // the height of the bitmap in pixels*
                '\x01\x00' +         // the number of color planes (1)
                '\x18\x00' +         // 24 bits / pixel
                '\x00\x00\x00\x00' + // No compression (0)
                num_data_bytes +     // size of the BMP data (bytes)*
                '\x13\x0B\x00\x00' + // 2835 pixels/meter - horizontal resolution
                '\x13\x0B\x00\x00' + // 2835 pixels/meter - the vertical resolution
                '\x00\x00\x00\x00' + // Number of colors in the palette (keep 0 for 24-bit)
                '\x00\x00\x00\x00' + // 0 important colors (means all colors are important)
                _collapseData(rows, row_padding)
               );

        return 'data:image/bmp;base64,' + btoa(file);
    };

This is how to rotate the pixels taken from this example.

//Open the source and create the destination bitmap 
Graphics::TBitmap *SrcBitmap=new Graphics::TBitmap; 
Graphics::TBitmap *DestBitmap=new Graphics::TBitmap; 
SrcBitmap->LoadFromFile("YourBitmap.bmp");

//rotate by 90° 

DestBitmap->Width=SrcBitmap->Height; 
DestBitmap->Height=SrcBitmap->Width; 

//Rotate one pixel at a time 
for (int x=0;x<SrcBitmap->Width;x++) 
{ 
  for(int y=0;y<SrcBitmap->Height;y++) 
  { 
    DestBitmap->Canvas->Pixels[y][SrcBitmap->Width-1-x]= 
       SrcBitmap->Canvas->Pixels[x][y]; 
  } 
} 

//Assign the Destination bitmap to a TImage 
Image1->Picture->Bitmap=DestBitmap; 
delete DestBitmap; 
delete SrcBitmap;

Upvotes: 0

nicael
nicael

Reputation: 19024

Yes, it is.

var canvas = document.createElement('canvas');

canvas.width="1000"; //specify width of your canvas
canvas.height="1000"; //specify height of your canvas
var img = document.createElement("img"); 
img.src = "image.png"; //specify url

var ctx = canvas.getContext("2d");

ctx.rotate(90 * Math.PI/180); // rotate by 90 degrees
ctx.drawImage(img,100,100); //draw it
ctx.fill();
document.body.appendChild(canvas); // display it!

Upvotes: 3

Related Questions