我正在尝试使用ActionScript 3动态加载渐进式jpeg.为此,我创建了一个名为Progressiveloader的类,它创建一个URLStream并使用它将渐进式jpeg字节流加载到byteArray中.每次byteArray增长时,我都使用Loader来加载byteArray.这在某种程度上是有效的,因为如果我addChild加载器,我能够看到jpeg流式传输,但我无法访问Loader的内容,最重要的是,我无法更改Loader的宽度和高度.
经过大量的测试,我似乎已经找出问题的原因是,直到Loader完全加载jpg,这意味着直到他实际看到jpg的结束字节,他不知道宽度和高度,他不会创建与Loader内容关联的内容DisplayObject.
我的问题是,有没有办法在加载之前真正知道jpeg的宽度和高度?
PS:我相信这是可能的,因为渐进式jpeg的性质,它被加载到它的全尺寸,但细节较少,因此应该知道大小.即使以这种方式加载普通的jpeg,也可以在屏幕上看到大小,除了尚未加载的像素显示为灰色.
谢谢.
我选择了Cay的答案,但我也会回答我自己的问题,补充一些澄清,并告诉其他人我经历过的事情,做错了,最后做得对,以防其他人偶然发现我的问题.
如果要逐步加载jpeg,则需要两件事:URLStream和Loader.然后,您需要按照以下步骤操作:
1)您必须使用URLStream将URLRequest中的jpeg加载到ByteArray中.
2)您需要向URLStream添加PROGRESS事件处理程序.在该处理程序中,您需要使用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)confirmBytesLoaded是您知道图像何时完全加载的队列.
2)如果给定的字节不允许显示更多图像,Loader将不会发送完整的事件.因此,除非您想知道jpeg每次传递的加载进度,否则不需要Loader进度事件.
3)在onLoaderComplete中,你可以做任何你想做的事.此时,该活动为您提供了完整的图像.您可以访问loader.content属性.记住,如果不是最后一个Loader完成事件,则意味着它将是您将拥有的CustomActions部分加载图像,因此要么在较低的防御中,要么在其中有一些灰色像素.
4)当您使用loadBytes时,它会在您的应用程序上下文中加载图像.因此,请确保您只以这种方式加载受信任的内容.我还不确定是否有办法解决这个问题,以确保安全.请参阅:http://onflash.org/ted/2008/01/loaderload-vs-loaderloadbytes.php
PS:这是我的大多数代码来自的链接:
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