开发者

Can Flash/AS3 load external images regardless of Content-Type?

开发者 https://www.devze.com 2023-03-14 10:51 出处:网络
Disclaimer: I\'m not a flash developer but I\'m trying to solve a flash issue. Please don\'t assume I\'m intimately

Disclaimer: I'm not a flash developer but I'm trying to solve a flash issue. Please don't assume I'm intimately familiar with AS or Flash, because I'm not.

The dilemma I currently have is that I'm hosting a resource that is application/octet-stream. In my Actionscript code, I'm using some library that ( from what I can recall ) does new Image and loads a resource into that object which was created.

There is a method, loadImage(url) which accepts a url and that's where you feed it the path to the image.

I do not have access to the loadImage source code, so I don't know exactly what it does, but the working one loads the image fine because the Content-Type is image/jpeg. The non-working one ( this one I'm trying to fix ) doesn't because of the different Content-Type.

I'm wondering if someone can tell me if I can make the flash basically parse the URI as if it were image/jpeg, regardless of the Content-Type?

I do not have access to the source code at the moment, but I'm just throwing this out there to get input

If need be, I'll try and get some source code tomorrow

EDIT: Ok, I have access to the source now. Here's the part that loads the image:

postcardImage = new Image();
postcardImage.loadImage(imagePath);

I assume that Image the constructor is native to flash/AS, but I haven't been able to google the loadImage method so it must be custom, right?

Or could the Image constructor itself be custom? An extended version of the original Image with loadImage method and such?

Anyways, does anyone know how I can view the source code of loadImage?

EDIT #2: I did an ack-grep and found the source code for the loadImage method defined in a library:

public class Image extends Sprite {

    private var _source:String;
    private var _loader:Loader;
    private var _bmapData:BitmapData;
    private var _loadedBytes:Number;
    private var _totalBytes:Number;

    public function Image() {
        trace('IMAGE');
    }

    public function loadImage(s:String):void {
        _source = s;
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
        _loader.contentLoaderInfo.addEventListener(Event.INIT, onLoading);
        _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
        _loader.load(new URLRequest(_source));

        function onProgress(e:ProgressEvent):void {
            _loadedBytes = e.target.bytesLoaded;
            dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
            if(!_totalBytes) {
                setTotalBytes(e.target.bytesTotal);
            }
        }

        function onLoading(e:Event):void {
            _loader.contentLoaderInfo.removeEventListener(Event.INIT, onLoading);
        }

        function onLoaded(e:Event):void {
            _bmapData = e.target.content.bitmapData;
            addChild(e.target.content);
            dispatchEvent(new Event(Event.COMPLETE));
            _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
        }
    }

    public function getBmapData():BitmapData {
        return _bmapData;
    }

    public function duplicate():Image {
        var dup:Image = new Image();
        dup.addChild(new Bitmap(_bmapData.clone()));
        return dup;
    }

    public function getLoadedBytes():Number {
        return _loadedBytes;
    }

    private function setTotalBytes(n:Number):void {
        _totalBytes = n;
        dispatchEvent(new Event("TOTALBYTES_SET"));
    }

    public function getT开发者_JAVA百科otalBytes():Number {
        return _totalBytes;
    }

}   

Can anyone offer advice as to how I can do the loadBytes on this? I was thinking of defining a custom method, loadResource or something which can load regardless of Content-Type... or just create an optional parameter in the current load method and inside, branch out based on what was passed.


I've been playing with ByteArray methods of late and this sounded fun. I've amended your Image class with a method for passing the URL of the octet-stream. Let me know how it works out!

note: I'm not setting the _loadedBytes and _totalBytes properties, but am drawing the loaded image to enable the public 'getBmapData' method.

package {
import flash.utils.ByteArray;
import flash.net.URLStream;
import flash.display.Bitmap;
import flash.net.URLRequest;
import flash.events.ProgressEvent;
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;

public class Image extends Sprite {

    private var _source : String;
    private var _loader : Loader;
    private var _bmapData : BitmapData;
    private var _loadedBytes : Number;
    private var _totalBytes : Number;
    private var _stream : URLStream;
    private var _bytes:ByteArray;

    public function Image() {
        trace('IMAGE');
    }

    public function loadImage(s : String) : void {
        _source = s;
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
        _loader.contentLoaderInfo.addEventListener(Event.INIT, onLoading);
        _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
        _loader.load(new URLRequest(_source));

        function onProgress(e : ProgressEvent) : void {
            _loadedBytes = e.target.bytesLoaded;
            dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
            if(!_totalBytes) {
                setTotalBytes(e.target.bytesTotal);
            }
        }

        function onLoading(e : Event) : void {
            _loader.contentLoaderInfo.removeEventListener(Event.INIT, onLoading);
        }

        function onLoaded(e : Event) : void {
            _bmapData = e.target.content.bitmapData;
            addChild(e.target.content);
            dispatchEvent(new Event(Event.COMPLETE));
            _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
        }
    }



    // ByteArray methods
    // adapted from Ted Patrick's 
    // http://ted.onflash.org/2007/12/progressive-image-loading-with.php

    public function loadBytes( s:String = "" ):void {

        // FOR EASY TESTING ONLY:
        if( s == "" ) s = "http://onflex.org/flexapps/applications/ProgressiveImageLoading/jpg.jpg";        

        // create URLStream with listeners
        _stream = new URLStream();
        _stream.addEventListener( ProgressEvent.PROGRESS , streamProgress );

        // Not firing, so lets not use it...
        //_stream.addEventListener( Event.COMPLETE , streamComplete );


        // create Loader for later
        _loader = new Loader();

        // create new ByteArray instance
        _bytes = new ByteArray();

        // go ahead and add it to the display list
        addChild( _loader );

        // start the show!
        _stream.load( new URLRequest(s) );

    }

    private function streamProgress(p : ProgressEvent) : void {

        trace("PROGRESS: ",  p.bytesLoaded, "of", p.bytesTotal );

        if( _stream.connected ) _stream.readBytes(_bytes, _bytes.length );

        if( _bytes.length == p.bytesTotal ) {

            // get rid of the event listeners to avoid re-firing 
            _stream.removeEventListener( ProgressEvent.PROGRESS , streamProgress ); 

            streamComplete();   
        }
    }

    private function streamComplete() : void {
        _loader.loadBytes( _bytes );
        _loader.contentLoaderInfo.addEventListener( Event.INIT, makeBitmapData );
    }

    private function makeBitmapData( e:Event ):void{

        _loader.contentLoaderInfo.removeEventListener( Event.INIT, makeBitmapData );

        // set the bitmapData for the other public methods
        _bmapData = new BitmapData(_loader.width, _loader.height );
        _bmapData.draw( this );
    }

    //-----




    public function getBmapData() : BitmapData {
        return _bmapData;
    }

    public function duplicate() : Image {
        var dup : Image = new Image();
        dup.addChild(new Bitmap(_bmapData.clone()));
        return dup;
    }

    public function getLoadedBytes() : Number {
        return _loadedBytes;
    }

    private function setTotalBytes(n : Number) : void {
        _totalBytes = n;
        dispatchEvent(new Event("TOTALBYTES_SET"));
    }

    public function getTotalBytes() : Number {
        return _totalBytes;
    }
}  
} 


Short answer: Yes.

I would assume that the code is using a Loader object behind the scenes to do the actual image loading/retrieval (this is the standard way of doing such things). Loader objects support PNG, JPEG, and GIF (first frame only) formats.

Now, I'm not sure if Loaders use the content type of the response to guess the image format (I would guess not, but I could be wrong). I do know that Loaders have a loadBytes() method which loads an image directly from its raw bytes -- the format sniffing only uses the image's actual data in that case, as there is no HTTP request directly involved. So, if it's really the content type that's the culprit, you could load the image separately as raw data, then get an image object from that raw data using loadBytes(), bypassing the issue entirely.

We'd have to see the code to really know what's going on, of course.

0

精彩评论

暂无评论...
验证码 换一张
取 消