2009-11-29 27 views
6

Estoy intentando cargar dinámicamente un archivo JPEG progresivo usando ActionScript 3. Para hacerlo, he creado una clase llamado Progressiveloader que crea un URLStream y lo usa para transferir los bytes jpeg progresivos a un byteArray. Cada vez que crece byteArray, utilizo un cargador para cargarBytes the byteArray. Esto funciona, en cierta medida, porque si agregoChild the Loader, puedo ver el jpeg tal como se transmite, pero no puedo acceder al contenido del Loader y lo más importante, no puedo cambiar el ancho y la altura del Loader .Cómo cargar dinámicamente un jpeg/jpg progresivo en ActionScript 3 usando Flash y saber su ancho/alto antes de que esté completamente cargado

Después de muchas pruebas, parece que descubrí que la causa del problema es que hasta que el cargador haya cargado completamente el jpg, es decir, hasta que vea el byte final del jpg, no conoce el ancho y altura, y no crea un DisplayObject de contenido para asociarlo con el contenido del Loader.

Mi pregunta es, ¿habría una manera de saber realmente el ancho y la altura del jpeg antes de que se cargue?

P.S .: Creo que esto sería posible, debido a la naturaleza de un jpeg progresivo, se carga a su tamaño completo, pero con menos detalles, por lo que el tamaño debe ser conocido. Incluso cuando se carga un jpeg normal de esta forma, el tamaño se ve en la pantalla, excepto que los píxeles que aún no están cargados se muestran en gris.

Gracias.

Respuesta

1

Creo que su problema es que loadBytes es asíncrona ... eso significa que hay que esperar hasta que el evento "completa" antes de recuperar (o cambiar) su anchura y altura ... Es decir:

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

leer los metadatos sería la mejor manera de leer la información de la imagen sin cargarla en la imagen, creo.

por lo que debe asegurarse de que la imagen tenga metadatos incrustados en su archivo. entonces podría leerlo con una biblioteca de metadatos as3 como http://patrickshyu.com/2009/04/jpg-exif-metadata-in-actionscript-3/

o podría crear un script del lado del servidor que lea en los metadatos de la imagen y lo envíe a actionscript.

+0

También puede probar la carga de imágenes progresiva mediante loadBytes aquí es un artículo sobre el tema y un ejemplo: http: // onflash.org/ted/2007/12/progressive-image-loading-with.php parece como la anchura y la altura de la imagen se conoce antes de que comience la carga/visualización, pero que no he testen que yo – Aaike

10

Elegí la respuesta de Cay, pero también responderé mi propia pregunta para agregar algunas aclaraciones e informar a todos los demás de lo que pasé, hice mal y eventualmente lo hice bien, en caso de que alguien se tropiece con mi pregunta.

Si desea cargar progresivamente un jpeg, necesita dos cosas: un URLStream y un Loader. Luego debe seguir estos pasos:

1) Debe usar un URLStream para cargar el archivo jpeg desde un URLRequest en un ByteArray.

2) Debe agregar un controlador de eventos PROGRESS al URLStream. En ese controlador, necesita usar un cargador para cargar bytes() los bytes recién cargados del URLStream.

3) Es necesario un controlador de cargador evento COMPLETE a los acces cada pasada del JPEG cargado y hacer lo que quiera en él, como en la pantalla o cambiar su tamaño, etc.

4) Es necesario un evento completo URLStream controlador para asegurarse de que se hayan cargado todos los bytes y para limpiarlo y cerrar la secuencia.

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

Algunas notas sobre todo el proceso:

1) El confirmBytesLoaded es su cola de saber cuando la imagen ha sido completamente cargado.

2) El cargador no va a distribuir un evento completo si los bytes que se le dio no permite visualizar más de la imagen. Por lo tanto, el evento de progreso del cargador no es necesario a menos que desee saber el progreso de la carga de cada pasada del jpeg.

3) En onLoaderComplete se puede hacer lo que quiera. En ese punto, el evento te brinda una imagen completa para trabajar. Puede acceder al atributo loader.content. Recuerde que, si no es el último evento completo del cargador, significa que es la imagen cargada parcialmente con CustomActions que tendrá, por lo tanto en defensa inferior o con algunos píxeles grises.

4) Cuando se utiliza loadBytes, se carga la imagen en su contexto de aplicación. Así que asegúrese de cargar solo contenido de confianza de esta manera. Todavía no estoy seguro de si hay una forma de evitar esto, para que sea seguro. Ver: http://onflash.org/ted/2008/01/loaderload-vs-loaderloadbytes.php

PS: Aquí está el enlace a donde la mayor parte de mi código proviene de:

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

Éstos son algunos enlaces que realmente le muestran una manera de leer el ancho y la altura de sí mismo mediante analizar cada byte como su se cargan usando la especificación 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

-2

Usted puede lograr esto con un simple script PHP:

$imagedata = getimagesize($yourpath); 

$width = $imagedata[0]; 
$height = $imagedata[1]; 
Cuestiones relacionadas