Как динамически загружать прогрессивный jpeg / jpg в ActionScript 3 с помощью Flash и знать его ширину / высоту до полной загрузки - PullRequest
6 голосов
/ 29 ноября 2009

Я пытаюсь динамически загрузить прогрессивный jpeg с помощью ActionScript 3. Для этого я создал класс с именем Progressiveloader, который создает URLStream и использует его для потоковой передачи прогрессивных байтов jpeg в byteArray. Каждый раз, когда растет byteArray, я использую Loader для загрузки ByteArray. Это работает, в некоторой степени, потому что, если я добавляю Child the Loader, я могу видеть jpeg в потоковом режиме, но я не могу получить доступ к содержимому Loader и, самое главное, я не могу изменить ширину и высоту Loader .

После многих испытаний я, кажется, выяснил причину проблемы в том, что до тех пор, пока загрузчик полностью не загрузит JPG, то есть до тех пор, пока он фактически не увидит конечный байт JPG, он не знает ширину и height, и он не создает объект DisplayObject для содержимого, связанного с содержимым загрузчика.

У меня такой вопрос, будет ли способ узнать ширину и высоту jpeg до его загрузки?

P.S .: Я полагаю, что это было бы возможно, из-за природы прогрессивного JPEG, он загружен в полный размер, но с меньшим количеством деталей, поэтому размер должен быть известен. Даже при такой загрузке обычного jpeg размер отображается на экране, за исключением того, что пиксели, которые еще не загружены, отображаются серым цветом.

Спасибо.

Ответы [ 4 ]

10 голосов
/ 01 декабря 2009

Я выбрал ответ Кея, но я также отвечу на свой вопрос, чтобы добавить некоторые пояснения и проинформировать всех остальных о том, что я пережил, сделал неправильно и в конце концов сделал правильно, на тот случай, если кто-то еще наткнется на мой вопрос.

Если вы хотите постепенно загружать JPEG, вам нужны две вещи: URLStream и Loader. Затем вам нужно выполнить следующие шаги:

1) Вы должны использовать URLStream для загрузки jpeg из URLRequest в ByteArray.

2) Вам необходимо добавить обработчик события PROGRESS в URLStream. В этом обработчике вам нужно использовать Loader для loadBytes () недавно загруженных байтов URLStream.

3) Вам нужен обработчик событий Loader COMPLETE, чтобы получить доступ к каждому проходу загруженного jpeg и делать с ним все, что вы хотите, например, отображать его или изменять его размер и т. Д.

4) Вам нужен обработчик события URLStream COMPLETE, чтобы убедиться, что все байты были загружены, и очистить после себя и закрыть поток.

var urlStream:URLStream = new URLStream(); //We will use this to progressively stream the bytes of the jpeg
var byteArray:ByteArray = new ByteArray(); //Bytes from the URLStream will go here
var loader:Loader = new Loader(); //We will use this Loader to load the bytes from the ByteArray
var url:String = "http://myAddressToMyJpeg.jpg"; //The url to the jpeg

urlStream.load(new URLRequest(url));

urlStream.addEventListener(ProgressEvent.PROGRESS, onStreamProgress, false, 0, true);
urlStream.addEventListener(Event.COMPLETE, onStreamComplete, false, 0, true);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete, false, 0, true);

function onStreamProgress(evt:ProgressEvent):void
{
    // You could put a condition here to restrain the number of calls to updateBytes().
    // Use the evt.bytesTotal and evt.bytesLoaded to help accomplish this.
    // You will find that by limiting it, it will increase responssivness of your
    // program and give an overall better result.
    // Have it call updateBytes() every 100 bytes or so.
    updateBytes();
}

function onStreamComplete(evt:Event):void
{
    updateBytes(); // Call updateBytes one more time to load in the last bytes.

    urlStream.removeEventListener(ProgressEvent.PROGRESS, onStreamProgress); // Clean after yourself
    urlStream.removeEventListener(Event.COMPLETE, onStreamComplete); // Clean after yourself

    // Somehow, without this, it does not work. You will end up with a ~90% loaded image
    setTimeout(confirmBytesLoaded,500); // Would be nice if someone could tell me why this makes it work!!
}

function confirmBytesLoaded():void
{
    updateBytes(); // As said earlier, you need to check it one last time it seems.
    if (urlStream.connected) urlStream.close(); // Close the stream once you're done with it.
}

function updateBytes():void
{
    // Important step. We copy the bytes from the stream into our byteArray,
    // but we only want to add the new bytes to our byteArray, so we use the lenght
    // attribute as an offset so that the new bytes gets added after the bytes that we added before.
    urlStream.readBytes(byteArray, byteArray.length);

    if(byteArray.length > 0) // Make sure there are new bytes to load.
    {
        loader.loadBytes(byteArray); // Use the Loader to decode the loaded bytes.
    }
}

// onLoaderComplete will be called many times.
// Every time there is enough new bytes to diplay more of the image
// onLoaderComplete will be called. So for every pass of the jpeg one
// this will be called.
function onLoaderComplete(evt:Event):void
{   
    // bm will now contain the bitmapData of the progressively loaded jpeg.
    var bm:Bitmap = Bitmap(loader); // We make a bitmap object from the loader.

    bm.width = 400; // Because my goal was to be able to resize the image as it is loaded and display it :).
    bm.height = 400; // Because my goal was to be able to resize the image as it is loaded and display it :).
    addChild(bm); // See the result for yourself...
}

Некоторые примечания по всему процессу:

1) verifyBytesLoaded - ваша очередь, чтобы узнать, когда изображение было полностью загружено.

2) Загрузчик не будет отправлять полное событие, если предоставленные им байты не позволяют отображать больше изображения. Таким образом, событие прогресса загрузчика не требуется, если вы не хотите знать ход загрузки каждого прохода jpeg.

3) В onLoaderComplete вы можете делать все, что захотите. В этот момент событие дает вам полное изображение для работы. Вы можете получить доступ к атрибуту loader.content. Помните, что если это не последнее событие завершения Loader, это означает, что это будет частично загруженное изображение CustomActions, которое будет у вас, так или в более низком разрешении, или с некоторыми серыми пикселями в нем.

4) Когда вы используете loadBytes, он загружает изображение в контексте вашего приложения. Поэтому убедитесь, что вы загружаете только доверенный контент таким способом. Я еще не уверен, есть ли способ обойти это, чтобы обеспечить его безопасность. Смотри: http://onflash.org/ted/2008/01/loaderload-vs-loaderloadbytes.php

P.S: Вот ссылка на источник большей части моего кода:

http://orangeflash.eu/?p=13

Вот несколько ссылок, которые на самом деле показывают вам способ чтения ширины и высоты самостоятельно, анализируя каждый байт по мере их загрузки, используя спецификацию jped:

http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/

http://www.emstris.com/2009/05/extracting-binary-info/

http://blog.onebyonedesign.com/?p=71

1 голос
/ 29 ноября 2009

Я думаю, что ваша проблема в том, что loadBytes является асинхронным ... это означает, что вам нужно дождаться события "complete", прежде чем вы получите (или измените) его ширину и высоту ... Я имею в виду:

var loader:Loader=new Loader();
loader.loadBytes(myBytes);
trace(loader.width, loader.contentLoaderInfo.width); //will always output zero
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaded);
function imgLoaded(e) {
   trace(loader.width, loader.height); //will output the loader dimensions
   trace(loader.contentLoaderInfo.width, loader.contentLoaderInfo.height); //will always output the original JPEG dimensions
}
0 голосов
/ 03 мая 2010

Этого можно добиться с помощью простого PHP-скрипта:

$imagedata = getimagesize($yourpath);

$width = $imagedata[0];
$height = $imagedata[1];
0 голосов
/ 29 ноября 2009

чтение метаданных было бы лучшим способом прочитать информацию об изображении без загрузки самого изображения, я думаю.

, поэтому вам нужно убедиться, что в изображение встроены метаданные. тогда вы можете прочитать его с помощью библиотеки метаданных as3, например http://patrickshyu.com/2009/04/jpg-exif-metadata-in-actionscript-3/

или вы можете создать серверный сценарий, который читает метаданные изображения и отправляет его в actioncript.

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