简体   繁体   English

如何从base64图像数据字符串中同步获取宽度和高度?

[英]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 ? 有没有办法从base64编码的图像数据中同步获取图像的宽度和高度? 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. 我在AS3中发现的唯一解码方法是异步的。 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. 我正在使用ActionScript3,它是JavaScript的兄弟。 If it works in JavaScript it most likely works in AS3. 如果它在JavaScript中有效,则很可能在AS3中起作用。 But I cannot work with the dom. 但是我无法使用dom。 No adding images to the dom and checking values. 请勿将图像添加到dom并检查值。

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. 如果有可能将宽度和高度添加到base64流中,然后再获取它,那么它也将正常工作。

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 这仅适用于png的第一件事,首先是将base64转换为缓冲区(Uint8array),然后读取字节16-20(宽度)和20-24(高度)作为int32值

 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) 

The following does not work but it's attempting to convert @Endless answer to AS3. 以下内容不起作用,但尝试将@Endless答案转换为AS3。 I have this so far: 到目前为止,我有:

protected function windowedapplication1_applicationCompleteHandler(event:FlexEvent):void {
    var base64ImageData:String = DisplayObjectUtils.getBase64ImageDataString(this, DisplayObjectUtils.PNG, null, true);
    var size:Object = getPngDimensions(base64ImageData);
}

public function getPngDimensions(base64:String):Point {
    base64 = base64.split(',')[1];
    trace(base64.length);
    base64 = base64.replace(/\n/g, "");
    trace(base64.length);
    //var header:String = base64.slice(0, 52); // 50 gave error later on
    var header:String = base64.slice(0, base64.length);
    var base64Decoder:Base64Decoder = new Base64Decoder();
    var byteArray:ByteArray;

    base64Decoder.reset();
    base64Decoder.decode(header);

    // base64Decoder.toByteArray(); ==>
    // Error: A partial block (2 of 4 bytes) was dropped. Decoded data is probably truncated!
    // added the whole length (52 works as well)
    byteArray = base64Decoder.toByteArray();
    byteArray.position = 0;

    //var width:String = byteArray.readUTFBytes(0);
    //var value:ByteArray = new ByteArray();
    //value.readBytes(byteArray, 0, 28);
    var thing:Number = byteArray.readDouble(); // -8.091055181950927E-264
    byteArray.position = 0;
    var thing2:Number = byteArray.readFloat(); // -2.5073895107184266E-33
    byteArray.position = 0;
    var width:Number = byteArray.readFloat();
    byteArray.position = 16;
    var width:Number = byteArray.readFloat();
    byteArray.position = 20;
    var width:Number = byteArray.readFloat();
    byteArray.position = 28;
    var width:Number = byteArray.readFloat(); // 1.1074230549312416E-38
    byteArray.position = 0;
    var other:String = byteArray.readUTFBytes(byteArray.length);
    // other == "PNG\r\n\n"

    var point:Point = new Point();
    point.x = int(width);
    point.y = int(height);

    return point;
}

If I use ByteArray.readUTFBytes() I get "PNG" as a result but no width or height. 如果我使用ByteArray.readUTFBytes() ,结果为“ PNG”,但没有宽度或高度。

"If I use ByteArray.readUTFBytes() I get "PNG" as a result but no width or height." “如果我使用ByteArray.readUTFBytes() ,结果是“ PNG”,但没有宽度或高度。”

Don't read bytes as UTF format since that only extracts text chars. 不要将字节读取为UTF格式,因为这只会提取文本字符。 You want decimal values. 您需要十进制值。

  • readDouble and readFloat is too much, they read 8 bytes per action. readDoublereadFloat太多,每个动作读取8个字节。 PNG format uses only 4 bytes per width OR height value, so just read (unsigned) integers. PNG格式每个宽度或高度值仅使用4个字节,因此只需读取(无符号)整数。
  • Remember that every read action automatically moves the byteArray position. 请记住,每个read动作都会自动移动byteArray的位置。 For example to know bytePos-1's value you must "walk"/read past it so you end up at bytePos-2, or for Double type you will end up at bytePos-9. 例如,要知道bytePos-1的值,您必须“遍历” /读取它的值,以便最终到达bytePos-2;对于Double型,您必须最终到达bytePos-9。

See if this re-fix of your code gets the expected values of width & height... 查看此代码重新修复是否获得宽度和高度的期望值...

public function getPngDimensions(base64:String):Point 
{
    base64 = base64.split(',')[1];
    trace("Base64 length A : " + base64.length);
    base64 = base64.replace(/\n/g, "");
    trace("Base64 length B : " + base64.length);
    //var header:String = base64.slice(0, 52); // 50 gave error later on
    var header:String = base64.slice(0, base64.length);
    var base64Decoder:Base64Decoder = new Base64Decoder();
    var byteArray:ByteArray;

    base64Decoder.reset();
    base64Decoder.decode(header);

    // base64Decoder.toByteArray(); ==>
    // Error: A partial block (2 of 4 bytes) was dropped. Decoded data is probably truncated!
    // added the whole length (52 works as well)
    byteArray = base64Decoder.toByteArray();
    byteArray.position = 0;

    //# Get Width and Height values
    //# type Int is 4 bytes long so pointer auto-moves ahead by 4 bytes during Read action
    byteArray.position = 16; //start position for values...
    var width:int = byteArray.readUnsignedInt(); //reads 4 bytes, stops at Pos 20
    var height:int = byteArray.readUnsignedInt(); //reads 4 bytes, stops at Pos 24

    //# Double check (if needed)
    //trace("PNG width  : " + width);
    //trace("PNG height : " + height);

    //# Return as Point
    var point:Point = new Point();
    point.x = width; point.y = height;
    return point;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM