2016-12-14 1 views
0

Есть ли способ получить ширину и высоту изображения из данных изображения с кодировкой base64 синхронно? Возможно, информация заголовка.Как синхронно получить ширину и высоту из строки данных изображения base64?

Я должен сделать это предельно ясным. Меня не интересуют асинхронные методы. Пожалуйста, перейдите, если вы хотите узнать причины, по которым async не будет работать. Даже не комментируйте.

Вот мой пример кода для кодирования моих данных. Кодировка является синхронной. Я это call с помощью:

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

Вот мой код, чтобы расшифровать мои данные. Единственный метод, который я нашел в AS3 для декодирования, является асинхронным. Я это call с помощью:

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

Позвольте мне повторить, что я ищу в синхронного действия. Он не может быть асинхронным.

Дополнительная информация:
Я работаю в ActionScript3, которая является сестрой в JavaScript. Если он работает в JavaScript, он, скорее всего, работает в AS3. Но я не могу работать с домом. Без добавления изображений в dom и проверки значений.

Полезные хаки:
Если это возможно, чтобы добавить ширину и высоту в поток base64, а затем получить его позже, что будет работать, как хорошо.

ответ

3

Это работает только для первого дела 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)

+0

Благодарим Вас за это. Если я смогу преобразовать это в ActionScript3, я проверю это как ответ, но это может быть вне меня. AS3 имеет один класс под названием ByteArray() для работы с байтовыми массивами. Документация http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118666ade46-7d54.html. API Docs http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/ByteArray.html. Это та область, где JS и AS отличаются, и я еще не смог расшифровать все это. –

+0

Все еще интересно, почему вы используете флешку: P уже не мертв? Но, извините, я ничего не знаю о AS – Endless

+0

Нет проблем. Я это выясню. Поскольку вам интересно, для меня Flash - это набор инструментов или холст художников. Как набор инструментов, я могу с ним поработать. В качестве холста я могу использовать его для легкого создания векторного или растрового искусства и анимации. То, как я ежедневно смотрю на него, это Flash или (Flex) - это окно с инструментами. Люди говорят, что HTML5 - это то, что используют все классные дети, Flash - настолько нераскрытый. Мне было все равно. Я не играю с кардасианцами. Я буду продолжать использовать Flex, и если HTML догонит, тогда здорово, возможно, я тоже буду использовать это. По какой-то причине разработчики являются фанатиками. Я просто создатель контента. –

2

следующее не работает, но оно пытается преобразовать @Endless ответ на AS3. У меня это до сих пор:

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; 
} 

Если я использую ByteArray.readUTFBytes() я получаю «PNG» в результате, но не ширины или высоты.

+0

Nice (+1) ... слишком поздно предложил это. Другая вещь, которую я имел в виду, была очень халатной и полезной, только если вы используете .swf в браузере: используйте ExternalInterface для загрузки, создайте '' ' '' ', используя base64data (у вас есть браузер для декодирования), затем прочитайте свойства' '' .width/.height'' –

+0

Спасибо за предложение. Я пытаюсь избежать внешнего интерфейса, если нет другого пути. Я думаю, если бы я понял ByteArrays больше, я мог бы перевести другой ответ. –

+0

намного чище/портативное решение! хорошо сделано –

1

«Если я использую ByteArray.readUTFBytes() я получаю„PNG“в результате, но не ширины или высоты.»

Не читать байты как формат UTF так, что только экстракты текстовых символов. Вы хотите десятичные значения.

  • readDouble и readFloat слишком много, они читают 8 байт за действие. Формат PNG использует только 4 байта на ширину или значение высоты, поэтому просто читайте (без знака) целые числа.
  • Помните, что каждое действие read автоматически перемещает позицию byteArray. Например, чтобы знать значение bytePos-1, вы должны «ходить»/читать мимо, чтобы вы закончили работу с bytePos-2, или для типа Double вы попадете в bytePos-9.

Смотрите, если это повторное исправление вашего кода получает ожидаемые значения ширины & высоты ...

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; 
} 
+0

Yay! Это сработало! Спасибо, и спасибо, что научили меня чему-то новому! Если бы был способ отметить два ответа правильно, я бы отметил и это, и @Endless ответ. Хотя спрос, вероятно, равен нулю, StackOverflow может реализовывать несколько ответов, когда они относятся к различным языкам. Итак, хотя ответ Endless был в JavaScript, ваш ответ был в ActionScript. Один ответ правильный для разработчиков JavaScript, а другой для разработчиков ActionScript. –

+0

@ 1.21gigawatts Просто поместите рабочие части ('readInt' и т. Д.) В свой собственный ответ & отметьте это как правильно. Моя логика заключается в том, что, поскольку это вопрос ** AS3 **, я и @Endless просто предоставили полезное руководство для рабочего решения с вашей собственной реализацией. –

+0

Для тех, кто хочет понять больше, чем я, я нашел эти два класса, которые показывают, как создавать PNG и JPEG. PNG https://github.com/mikechambers/as3corelib/blob/master/src/com/adobe/images/PNGEncoder.as и JPG https://github.com/mikechambers/as3corelib/blob/master/src/com/ саман/изображения/JPGEncoder.as. Возвращение ценностей из них имеет больше смысла. Другой класс, чтобы получить размеры JPG без загрузки всего файла http: //www.anttikupila.ком/вспышка/посаживания JPG-размеры-с-as3-без нагрузки-The-весь-файл / –

Смежные вопросы