17

I have this

data:image/png;base64,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

I would like to get the height and width from this string using JavaScript. How would I do this? Is it even possible?

You can assume access to jQuery, window.btoa, and window.atob.

Naftali
  • 142,114
  • 39
  • 237
  • 299
Travis Smith
  • 508
  • 2
  • 7
  • 21
  • 5
    Put it in an `Image` object. – SLaks Mar 10 '13 at 21:36
  • Specifically, I am looking for something that will parse and read the base64 string and do two things: (1) Verify that it is a PNG (Note: to me, it appears that all PNGs have the initial substring 'iVBORw0KGgoAAAANSUhEUgAAA'), & (2) Determine from the IHDR header the width, height (& it would be great to get the rest as well: bit depth, color type, compression mode, filter, and interlace). If possible, I'd like to avoid canvas or Image. – Travis Smith Mar 11 '13 at 17:02
  • It is not very likely that you will be able to write a PNG parser in Javascript that is faster than the browser's native parser. – SLaks Mar 11 '13 at 17:27
  • I don't believe it is possible to get this information with javascript/jQuery, since this information is simply handled by the browser and not exposed to javascript in any way I know of. It makes me wonder where the data uri comes from, and whether you can't get the information before it arrives in the webpage. – Sygmoral Mar 11 '13 at 17:28
  • 3
    @Sygmoral: It is certainly possible to parse the PNG file format in pure JS. – SLaks Mar 11 '13 at 17:31

5 Answers5

39

I’m sure that it’s possible to parse that out of the PNG somehow, but assuming data URI support (since we can assume atob), you can just create an image and wait for it to load (this works in any format):

var image = document.createElement('img');

image.addEventListener('load', function() {
    // image.width × image.height
});

image.src = 'data:image/png;base64,…';

Here's a demo.


Okay, apparently you’d like to extract this information manually. A PNG file starts with the bytes 89 50 4E 47 0D 01 1A 0A, followed by the IHDR chunk that contains the width and height and must be the first chunk. (Yay, easier!) A chunk has a 4-byte length, a 4-byte type, and then a length-byte content. IHDR’s content starts with a 4-byte width and a 4-byte height, so a PNG’s width and height are always bytes 16–24! This can all be checked if you like, but for a simple way that assumes the PNG is valid:

function toInt32(bytes) {
    return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
}

function getDimensions(data) {
    return {
        width: toInt32(data.slice(16, 20)),
        height: toInt32(data.slice(20, 24))
    };
}

var base64Characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

function base64Decode(data) {
    var result = [];
    var current = 0;

    for(var i = 0, c; c = data.charAt(i); i++) {
        if(c === '=') {
            if(i !== data.length - 1 && (i !== data.length - 2 || data.charAt(i + 1) !== '=')) {
                throw new SyntaxError('Unexpected padding character.');
            }

            break;
        }

        var index = base64Characters.indexOf(c);

        if(index === -1) {
            throw new SyntaxError('Invalid Base64 character.');
        }

        current = (current << 6) | index;

        if(i % 4 === 3) {
            result.push(current >> 16, (current & 0xff00) >> 8, current & 0xff);
            current = 0;
        }
    }

    if(i % 4 === 1) {
        throw new SyntaxError('Invalid length for a Base64 string.');
    }

    if(i % 4 === 2) {
        result.push(current >> 4);
    } else if(i % 4 === 3) {
        current <<= 6;
        result.push(current >> 16, (current & 0xff00) >> 8);
    }

    return result;
}

function getPngDimensions(dataUri) {
    if (dataUri.substring(0, 22) !== 'data:image/png;base64,') {
        throw new Error('Unsupported data URI format');
    }

    // 32 base64 characters encode the necessary 24 bytes
    return getDimensions(base64Decode(dataUri.substr(22, 32)));
}

var dimensions = getPngDimensions('data:image/png;base64,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');

console.log(dimensions.width + ' × ' + dimensions.height);
Ry-
  • 209,133
  • 54
  • 439
  • 449
  • 3
    I would have gone with `new Image()` – Musa Mar 10 '13 at 21:41
  • This works great! So I apologize for being unclear in my question. See new comment above. – Travis Smith Mar 11 '13 at 17:02
  • @TravisSmith: Okay :D After much arduous toil, difficult labour and hard work, I read a paragraph of specification and made a thing for that. You might want to add some error-checking, though. – Ry- Mar 11 '13 at 20:37
  • 1
    For those banging their heads on the shortcut via DOM, the IMGs created via `new Image()` or `document.createElement("IMG")` won't have dimensions until _after_ it loads. I figured BASE64 images would "load" instantly... **WRONG!** Adding the "load" event listener and _then_ acting on the height and width was the key. Shameful oversight on my part. :( – Eric L. Jun 24 '13 at 19:37
  • 1
    [As per the spec](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement), there are also the `naturalHeight` and `naturalWidth` properties, which may be more appropriate in cases where you actually display and style the . – Deiwin Mar 24 '15 at 11:59
  • @Deiwin yours should be an answer if not **the** answer – tbm0115 Jun 26 '17 at 22:34
  • a bit of a waste to parse the hole base64 data when you could just read a pice of chunk of it – Endless May 12 '20 at 20:15
  • @Endless: True! Fixed. – Ry- May 12 '20 at 23:40
22

And here is a new updated es6 version 3 years later with a tiny bit of help from typed arrays that is synchronous and where you don't have to load the hole image to memory to figure it out. So its faster :)

also don't require any DOM so it can work inside Workers

function getPngDimensions(base64) {
  const header = atob(base64.slice(0, 50)).slice(16,24)
  const uint8 = Uint8Array.from(header, c => c.charCodeAt(0))
  const dataView = new DataView(uint8.buffer)

  return {
    width: dataView.getInt32(0),
    height: dataView.getInt32(4)
  }
}

// Just to get some base64 png example
const canvas = document.createElement('canvas')
const base64 = canvas.toDataURL().split(',')[1]

const dimensions = getPngDimensions(base64)
console.log(dimensions)

edit: my recommendation is also that you should try to use typed arrays instead of base64 and blobs instead of typed arrays when possible, base64 is the worse container and use more memory.

So here is a solution for you who already have a blob:

document.createElement('canvas').toBlob(async blob => {
  // blob.arrayBuffer() is the new way to read stuff
  // may not work in all browser
  let dv = new DataView(await blob.slice(16, 24).arrayBuffer())
  
  console.log({
    width: dv.getInt32(0),
    height: dv.getInt32(4)
  })
})

// you could also try out the new experimental createImageBitmap
// don't use image or canvas but this also works in web workers
// and it also works for more than just png's
// could expect this is more havier/slower than just reading bytes 16-24
document.createElement('canvas').toBlob(async blob => {
  const bitmap = await createImageBitmap(blob)
  const { width, height } = bitmap
  bitmap.close() // GC
  console.log({ width, height })
})
Endless
  • 29,359
  • 11
  • 97
  • 120
  • 1
    This is great! Any chance you could help with a JPEG version of this function? The Specifications are over my head! – case2000 Jan 17 '17 at 15:39
  • I get the height in negative **{width: 4718592 height: -1962920}**. Resolution of the image if 2400x2400 – Musab Akram Dec 25 '19 at 06:12
  • hmm. just tried changing the canvas to 2400x2400, works just fine. did you try it on anything other than png maybe? (this just works for png). – Endless Dec 25 '19 at 16:40
7

LIVE DEMO

var imgData = 'data:image/png;base64,iVBORw0.........';    
var img = new Image();       
img.onload = function(){
  alert(img.width +' '+ img.height );
};
img.src = imgData;
Roko C. Buljan
  • 180,066
  • 36
  • 283
  • 292
6

With jQuery:

var width, height;
$('<img/>').load(function(){
    width = $(this).width();
    height = $(this).height();
    // Call whatever function here that requires the width/height
}).attr('src', datauri)
Sygmoral
  • 6,883
  • 1
  • 22
  • 29
3

** in node.js

function getPNGSize (buffer) {
  if (buffer.toString('ascii', 12, 16) === 'CgBI') {
    return {
      'width': buffer.readUInt32BE(32),
      'height': buffer.readUInt32BE(36)
    };
  }
  return {
    'width': buffer.readUInt32BE(16),
    'height': buffer.readUInt32BE(20)
  };
}
getPNGSize(buffer)
аlex dykyі
  • 4,877
  • 25
  • 38