[ActionScript] 서버로부터 이미지를 받아 BitmapData 타입으로 얻기

글 제목이.. 테크니컬합니다만.. Flex에서 서버에 위치한 이미지 파일을 다운로드 받아서.. 받은 이미지를 지지고 볶기 위해 BitmapData라는 타입으로 변환하고자 할때 사용하는 코드입니다.

이미지가 서버에 있으므로 URL로 경로를 지정할 수 있겠지요?  아래가 이미지에 대한 URL을 통해 다운로드 작업의 시동을 걸어 주는 코드입니다.

var ldr:Loader = new Loader();
var req:URLRequest = new URLRequest("http://www.gisdeveloper.co.kr/img/downskin.png");

ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onRequestComplete);
ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onRequestError);

ldr.load(req);

4번과 5번 코드는 다운로드가 성공적으로.. 때로는 문제가 생겨 실패했을시 발생하는 이벤트를 지정해주는 코드입니다. 성공적으로 받았을때 받은 데이터를 BitmapData 타입으로 변환하는 코드가 존재할텐데요.. 그렇다면 성공적으로 다운로드 되었을때 발생하는 이벤트에 대한 코드를 살펴면 다음과 같습니다.

private function onRequestComplete(event:Event):void
{
    var ldr:Loader = event.target.loader as Loader;
    var img:Bitmap = ldr.content as Bitmap;
    
    trace(img.bitmapData.width, img.bitmapData.height);
}

6번째 코드를 통해 다운로드 받은 이미지의 크기를 플래시 빌더의 디버깅 창에 표시해 보고 있습니다.

끝으로… 플래시는 모든 연산이 비동기화 지향적입니다. 플래시가 화면상에 화려하고 역동적인 그래픽 요소의 표현이라는 주요 목적을 갖고 있으니 당연한 것이긴 하지만…… 때론 이런 비동기적인 방식이 코드를 복잡하게 만들때가 있습니다.. 위의 경우에서도 이미지 하나를 받기 위해 비동기방식으로 이벤트를 지정해줘서 처리를 하고 있는데… 이를 동기적으로 처리할 수 있는 방법이 있다면 좋겠다는 생각이 듭니다만… 혹.. 아시는 분 계시나요?

[ActionScript] 서버로 Binary 데이터 전송

액션스크립트에서 바이너리 데이터를 서버로 전송하는 코드입니다. 물론… 서버 측에서 바이너리 데이터를 받아 들이는 서비스를 제공해야겠지요.. 바이너리 데이터 전송이므로.. 방식은 POST를 사용합니다.. 액션스크립트 코드는 다음과 같습니다..

protected function button1_clickHandler(event:MouseEvent):void
{
    var loader:URLLoader = new URLLoader();
    var request:URLRequest = new URLRequest("http://127.0.0.1:8080/Xr?edChkLog");

    var bytes:ByteArray = new ByteArray();
    bytes.writeDouble(3.14);
    bytes.writeInt(34321);
    bytes.position = 0;
   
    request.data = bytes;
    request.method = URLRequestMethod.POST;
    request.contentType = "application/octet-stream";

    loader.dataFormat = URLLoaderDataFormat.BINARY;
    loader.addEventListener(Event.COMPLETE, onCompleted);
    loader.addEventListener(IOErrorEvent.IO_ERROR, onError);

    loader.load(request);
}

바이너리 데이터는 ByteArray 타입에 저장되며.. 원하는 데이터를 write 매서드 군으로 저장시킵니다. 9번 코드와 15번 코드가 꼭 필요한지는 제거해서 확인해 보시기 바랍니다..

서버측은.. 저 같은 경우  자바의 서블릿을 사용했는데… POST 방식으로 요청을 받으므로 doPost 매서드를 오버라이드해서 데이터를 읽어오면 됩니다.. 바이너리 데이터를 쉽게 읽기 위해 DataInputStream을 사용했는데.. 이해를 돕고자.. 관련된 코드를 제시한다면 다음과 같습니다..

    ....

    ServletInputStream in = req.getInputStream();
    System.out.println("readable size: " + in.available());

    DataInputStream dis = new DataInputStream(in);
    System.out.println(dis.readDouble() + " , " + dis.readInt());

    ....

req는 서블릿의 요청에 대한 HttpServletRequest 객체입니다.. 화면상에 읽을 수 있는 바이너리의 바이트 수와 클라이언트가 보낸 실수값(3.14)와 정수값(34321)이 찍히면 정상입니다..

플래시의 액션스크립트를 이용해 서버측으로부터 바이너리 데이터를 읽을 수도.. 또.. 전송할 수 있도 있음으로 퍼포먼스를 향상 시킬 수 있겠습니다..

[ActionScript] 사용자 정의 이벤트 추가하기

추가해야할 이벤트는 많으면서 또 짐작하기 어렵고.. 시간이 없으니.. 일단 정리를 하여.. 추후 까막까막해져 혼란이 없으면 하는 바램에서 사용자 정의 이벤트를 추가하는 방법에 대해 정리를 해봅니다..

먼저 이벤트 처리 함수(이벤트 핸들러 함수)로 전달될 객체에 대한 클래스를 정의합니다.. 아래는 예입니다..

package geoservice.events
{
    import flash.events.Event;
    import flash.events.MouseEvent;

    public class XrMapMouseEvent extends Event
    {
        public static const XRMAP_MOUSE_DOWN_EVENT:String 
                = "mapMouseDownEvent";
        public static const XRMAP_MOUSE_UP_EVENT:String 
                = "mapMouseUpEvent";
        public static const XRMAP_MOUSE_CLICK_EVENT:String 
                = "mapMouseClickEvent";
        public static const XRMAP_MOUSE_DBLCLICK_EVENT:String 
                = "mapMouseDblClickEvent";
        public static const XRMAP_MOUSE_MOVE_EVENT:String 
                = "mapMouseMoveEvent";
  
        public var mapX:Number;
        public var mapY:Number;
        public var mouseEvent:MouseEvent;
  
        public function XrMapMouseEvent(type:String, mouseEvent:MouseEvent, 
            mapX:Number, mapY:Number, bubbles:Boolean=false, 
            cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);

            this.mapX = mapX;
            this.mapY = mapY;
            this.mouseEvent = mouseEvent;
        }

        override public function clone():Event
        {
            return new XrMapMouseEvent(type, mouseEvent, mapX, mapY, 
                bubbles, cancelable);
        }
    }
}

하나의 이벤트 클래스에서 총 5개 종류의 이벤트를 책임지고 있습니다.. 만약 클래스 하나가 단 하나의 이벤트만을 책임진다면 생성자에서 type 인자는 필요치 않고 super를 호출할때 첫번째 인자 를 바로 값으로 지정해 주면 됩니다.

다음으로 이벤트를 발생시켜 주는 코드입니다..

parent.dispatchEvent(
    new XrMapMouseEvent(XrMapMouseEvent.XRMAP_MOUSE_DOWN_EVENT, e,
        coordMapper.V2W_X(mouseX), coordMapper.V2W_Y(mouseY)
    )
);

이벤트가 발생되는 적절한 위치에 위의 코드가 존재하면 되며.. 위의 코드는 XRMAP_MOUSE_DOWN_EVENT라는 한 종류의 이벤트를 발생시키는 코드입니다..

이제 마크업(MXML)쪽에서 이벤트를 인식하도록 하기 위한 메타 태그의 정의를 추가합니다..

[Event(name="mapMouseDownEvent", type="geoservice.events.XrMapMouseEvent")]
[Event(name="mapMouseUpEvent", type="geoservice.events.XrMapMouseEvent")]
[Event(name="mapMouseClickEvent", type="geoservice.events.XrMapMouseEvent")]
[Event(name="mapMouseDblClickEvent", type="geoservice.events.XrMapMouseEvent")]
[Event(name="mapMouseMoveEvent", type="geoservice.events.XrMapMouseEvent")]

public class XrMap extends UIComponent
{
    ....

여기까지가 사용자 정의 이벤트를 추가하기 위한 전부이고.. 다음은 이 사용하는 쪽의 코드입니다.. addEventListener를 사용해 이벤트를 추가해도 되고.. 아니면 마크업쪽에서 이벤트를 추가해도 됩니다..

마크업 쪽의 방법만을 살펴보면 다음과 같습니다.. 흔히 일반적인 컴포넌트에 대한 이벤트를 정의하는 것과 동일합니다..

      mapMouseDownEvent="map_mapMouseDownEventHandler(event)"
     mapMouseClickEvent="map_mapMouseClickEventHandler(event)"
     mapMouseDblClickEvent="map_mapMouseDblClickEventHandler(event)"
     mapMouseMoveEvent="map_mapMouseMoveEventHandler(event)"
     mapMouseUpEvent="map_mapMouseUpEventHandler(event)"/>

[ActionScript] 이미지 파일을 이용해 배경 화면 채우기

화면에 대한 전체 배경을 작은 이미지를 이용해 타일로 채우는 코드입니다.. 플래시의 동적 프로그래밍 언어의 특성이 유감없이 발휘되는…. 그래서 개인적으로는 다소 이해하기 어려웠던 내용입니다.. 뭐 여튼.. 코드를 살펴보기에 앞서 사용할 작은 이미지를 살펴보고.. 바로 코드를 살펴보도록 하겠습니다..

사용자 삽입 이미지
이제 첫번째 코드입니다..

[Embed(source="./assets/bg_logo.png")]
private var _bg_logo:Class;

private var _bg_logo_bitmap:Bitmap = new _bg_logo();

보시면.. 먼저 외부의 png 이미지 파일을 _bg_logo라는 클래스 타입으로 선언합니다.. 재밌는 액션스크립트 언어의 기능이라고 생각되는데요.. 데이터 자체를 클래스 타입으로 선언하고 재사용한다는 것.. 플래시의 태생이 멀티 미디어 저작툴이기 때문에 이런 개념을 도입한게 아닌가 싶습니다..

이렇게 선언된 클래스를 통해 바로 Bitmap 클래스 타입인 _bg_logo_bitmap 변수를 통해 생성시킵니다.. 와우!  이제 이렇게 만든 비트맵을 화면에 격자로 뿌려주는 코드는… 다음과 같습니다..

graphics.beginBitmapFill(_bg_logo_bitmap.bitmapData);
graphics.drawRect(0, 0, _width, _height);
graphics.endFill();

_width와 _height는 화면의 크기 정도라고 이해하시면 무리가 없습니다.. 제가 이 코드 꾸러미를 적용해서 얻은 결과 화면은 다음과 같습니다..

사용자 삽입 이미지