Search code examples
javascriptarraysactionscript-3flashbitmapdata

How to sychronously get the width and height from a base64 string of image data?


Is there a way to get an image width and height from a base64 encoded image data synchronously? Possibly by header information.

I must make this extremely clear. I'm not interested in async methods. Please move on if you want to know reasons why async won't work. Don't even comment.

Here is my example code to encode my data. Encoding is synchronous. I'm using this call:

var base64ImageData:String = DisplayObjectUtils.getBase64ImageDataString(displayObject, DisplayObjectUtils.PNG, null, true);

Here is my code to decode my data. The only method I've found in AS3 to decode is asynchronous. I'm using this call:

var bitmapData:BitmapData = DisplayObjectUtils.getBitmapDataFromBase64(bitmapDataString);

Let me repeat, I'm looking for a synchronous action. It cannot be asynchronous.

More information:
I'm working in ActionScript3 which is a sibling to JavaScript. If it works in JavaScript it most likely works in AS3. But I cannot work with the dom. No adding images to the dom and checking values.

Helpful hacks:
If it's possible to add width and height into the base64 stream and then get it later that will work as well.


Solution

  • This only works for png's first thing first is to convert base64 do a buffer (Uint8array) then read the byte 16-20 (width) and 20-24 (height) as int32 value

    function getPngDimensions(base64) {
      let header = base64.slice(0, 50)
      let uint8 = Uint8Array.from(atob(header), c => c.charCodeAt(0))
      let dataView = new DataView(uint8.buffer, 0, 28)
    
      return {
        width: dataView.getInt32(16),
        height: dataView.getInt32(20)
      }
    }
    
    // Just to get some random base64 images
    var random = (bottom, top) => Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
    var canvas = document.createElement('canvas')
    canvas.width = random(10, 100)
    canvas.height = random(10, 100)
    console.log(`canvas width: ${canvas.width}, height: ${canvas.height}`)
    var base64 = canvas.toDataURL().split(',')[1]
    console.log(base64)
    
    var dimensions = getPngDimensions(base64)
    console.log(dimensions)