한글 번역을 하다보니 세세한 메뉴부터 추가되는 기능까지 계속 쳐다 보게 된다는 놀라운 사실.. ㅇ_ㅇ;;
아무튼 이번에 업데이트 된 핵심(?)적인 기능중 하나는 워터마크를 추가하는 페이지가 생겼다는 건데 기존에는 텍스트만 추가 할 수 있었다. (주로 뷰어로만 활용해서 편집기능은 전혀 몰랐다능..)
두번째는 얼굴 검출(Face Detection) 기능이다.
이 기능은 v4.32 플러그인 설치시 동작하며 Irfanview의 폴더보기 기능인 "미리보기 상자" 에서 사용가능하다.
("미리보기 상자"라.. 그냥 발음 그대로 번역하는게 더 나았으려나.. 썸네일 박스.. *_*;;)
이건 좀 좋아 보이므로(?!) 잠시 설명 들어간다.
"미리보기 상자"를 누르면 탐색기처럼 좌측 폴더와 우측 사진파일이 나오는데 폴더 또는 이미지 파일을 여러개 선택했을 경우 "파일"-"선택된 파일 얼굴검출 시작" or "현재 폴더 얼굴검출 시작" 을 누르면 얼굴이 들어 있는 사진만 검색해서 목록을 만들어 주는 기능이다.
미리보기목록에서 얼굴검출 기능을 사용하면 새창이 떠서 얼굴이 들어있는 사진만 검색해준다.
전체 목록은 72개 인데 27개의 얼굴이 들어간 사진만 골라주었다.
그리고 얻어진 목록의 사진을 더블 클릭하면 우측란에 검출된 부위를 나타내준다.
검출되고 난 다음 기능은 사진을 분류해주는 기능으로 우측 목록중 하나를 눌러보면 아래쪽에 이름을 넣을 수 있는 란이 나온다.
처음엔 Unkown 이고 이름을 입력해 놓으면 다음에 비슷한 얼굴 검출시 이름을 자동으로 입력해준다.
이름은 그렇게 정하고 검출된 얼굴과 이름이 맞으면 Yes, 아니면 no 를 선택, 이때 Yes 일경우 처음 한번 폴더를 지정하며 다음번에 그 이름이 Yes 되면 사진이 그 폴더로 저장되는 방식이다.
예전 Flex 2~3버전에서 데이터를 다운받기 위해서는 ByteArray 형식을 특정 웹페이지에 데이터를 업로드 시키고 해당 웹페이지에서 파일다운로드 시키는 방식을 이용했다.
파일데이터를 웹프로그램에서 HTTP 헤더를 바이너리로 지정해야만 했기때문.
하지만 4버전부터는 Flex의 ByteArray를 웹페이지를 거치지 않고 직접 다운로드 가능하다.
이는 ByteArray를 FileReference의 save 함수의 인자로 직접넣는게 가능해졌기 때문이다.
이를 응용하면 Flex에서 작성된 데이터를 ByteArray 형식으로 변환해 다운로드 할 수 있다.
아래는 화면을 캡춰해서 PC로 바로 저장하는 화면이다.
화면캡춰&다운로드 버튼을 누르면 파일을 저장하는 화면이 나타난다.
위 화면처럼 화면캡춰, PDF저장, 이미지 편집, 사운드 파일등 ByteArray로 데이터처리하는 모든 것들을 즉시 파일로 저장가능하다.
public function saveAsImage(obj:UIComponent, name:String = ''):void {
FileReference fileReference = new FileReference();
var pngSource:BitmapData = new BitmapData (obj.width, obj.height);
pngSource.draw(obj);
var pngEncoder:PNGEncoder = new PNGEncoder();
var pngData:ByteArray = PNGEncoder.encode(pngSource);
if(name=='') {
name = 'capture.png';
} else {
name += '.png';
}
fileReference.save(pngData, name); // 핵심
}
위는 내가 쓰는 화면캡춰 후 다운로드 하는 함수로 UIComponent와 파일 명을 인자로 주면 다운로드 하게 하는 함수다.
화면캡춰 후 as3corelib.swc 의 PNG라이브러리를 이용하는 것만 빼면 별달리 어려운 점이 없는 예제다.
왜?
오래전부터 쓰던 프로그램인데 최근(6월)에 업데이트된 v4.30 버전을 다운받아 설치했지만 한글팩이 v4.28 버전밖에 없어 안타까운 마음에 '내가 만들어 볼까?'해서 작업을 했다.
준비는?
먼저 기존의 v4.28버전에 등록되어 있는 한글팩 제작자인 "다음에는 도자기가 되고픈 진흙"님께 기존소스를 받을 수 있는지 문의를 드렸다.
안되면 프로그램에 있는 내용을 참고해서 번역할려고 했는데 다행이도 소스를 주셔서 쉽게 작업을 진행 할 수 있었다. (진흙님 감사합니다. -.- _._ )
어떻게?
irfanview 의 한글팩은 프로그램내에 메뉴, 다이얼로그, 메세지를 VisualC++6으로 컴파일한 DLL 형태로 제공, 설정에서 사용할 DLL을 선택하는 방식이다.
편집하려고 보니 VC6의 리소스편집기로 수정하기엔 마우스 클릭 질이 너무 많아서 .rc 파일을 직접수정하기로 했다.
v4.30 영문파일의 .rc 와 v4.28 한글파일의 .rc 를 Acrodiff(Acroeditor 편집기에 포함) 를 이용해서 영문파일의 내용을 한글파일문장으로 대체하는 작업과 추가,삭제부분 적용, 추가된 영문번역까지 v4.30버전의 한글파일을 완성했다.
틀린점이?
이전 버전과 틀린점은 글꼴을 기존의 굴림 8포인트에서 굴림 9로 변경했고 그에 따른 표시부분을 리소스편집기에서 열어 영역크기를 조정한것 정도?
최대한 원작자의 내용을 보존해서 했기때문에 추가된 번역부분 말고는 날 탓하지 말라능.. *_*;;
(사실 오역이 두려웠음..ㅠㅠ)
문제는?
프로그램적으론 문제는 없었는데 크게 많은 량은 아녔지만 오역/의역이 문제다.
ContactSheet 을 미리보기목록 이라고 의역했는데 그냥 영문그대로 두는게 나았을까? 쩝;;
느낀점
나야 예전 소스 받아 쉽게 작업해서 올렸지만 그 전 부터 고생하신 이전 제작자님이 많이 고생을 하셨겠다는 것.
Irfanview 를 지금까지 무료로 잘쓰고 있었기 때문에 기부는 못해도 도움이 되었다는 사실에 만족한다는 것! ㅎㅎ;;
개발환경 : Flex4.1 SDK with Flash Builder4, SAP, WebService, for MDXQuery
- 생각만큼 이벤트가 잘 먹히진 않는다 -
마우스 클릭 이벤트에서 동작하는 코드들이 제대로 돌아가지 않는다.
확인된 상황은 CPU에 부하가 많이 걸리는 상황이였고 callLater 를 걸어도 마찬가지. -0-
처리한 방식은 Timer 로 300밀리초 정도의 이벤트를 발생시켜 이벤트 처리 함수에서 동작하게 만들었다.
- 모듈의 메모리 해제는 역시나 멍청한 짓이다 -
각 페이지는 모듈로 만들었지만 멍청한 FLEX 는 역시나 메모리를 해제 시켜주지 않는다. Factory 클래스로 모듈을 호출하기 때문에 한번 생성한 객체는 계속 가지고 있고 재 호출시 이미 만들어진 객체를 리턴하고 addChild 시키는 방식을 사용했다. 페이지가 50페이지 정도라 그런지 2시간의 검증시간동안에도 큰 문제 없이 모든 페이지를 열어도 잘 소화해주었다.
- 각 페이지 모듈은 Optimizer 하지 않음 -
프로젝트 관리에서 모듈을 메인 MXML에 옵티마이져를 하지 않았다. 빌드시간 너무 길어~!
뭐 상황에 따라 틀리기 때문. 참고
( http://sites.google.com/site/koreanflexdoc/4-0/usingflashbuilder/ws6f97d7caa66ef6eb1e63e3d11b6c4d0d21-7fdd/ws6f97d7caa66ef6eb1e63e3d11b6c4cffa4-7ff1 )
- Webservice 에 http 인증이 있을때 잘 되지 않는다. -
WSDL 접근시 Base64로 인증코드를 헤더에 넣었지만 Fillder 로 확인해도 헤더에 바로 집어 넣어주지 않았다.(버그인듯) 해결한 방법은 WSDL을 파일로 저장하고 WSDL을 읽어 서비스호출을 했다. 이때는 HTTP 인증이 아주 잘 되었다. ㅡㅡ
- Webservice 호출시 플렉스 자체 파서는 오류를 내 뿜는다. -
* Error #1085: 요소 유형 "Tuple"은(는) 일치하는 끝 태그 "</Tuple>"(으)로 끝나야 합니다. *
플래시빌더4(3도 안됨)에서 제공하는 Webservice 호출시 나타나는 오류다. 이 오류 말고도 Caption 도 있고 여타 XML 파싱오류가 나타난다. ㅡㅡ
XML API 자체 문제기 때문에 코드를 직접 수정할 수 없어 그냥 Object 형식으로 리턴받아 SOAP로 받은 XML을 통합적으로 사용할 수 있는 ArrayCollection 으로 변환하는 함수를 만들었다.
- Object 객체의 프로퍼티는 입력순서를 가지지 않는다. -
아래와 같은 코드를 입력하면 콘솔에 어떤 결과가 나타날까?
var obj:Object = {'e':'1', 'd':'2', 'c':'3', 'b':'4', 'a':'5' }
for (var key:String in obj) {
trace('key='+key);
}
key=a
key=b
key=c
key=d
key=e
즉, xml 로 받은 컬럼 순서를 Object 로 넣으면 다시 가져올때의 순서를 보장받을 수 없다는 것이다. 그래서 Object 를 넣을때 Array 로 컬럼에 대한 순서정보를 입력시키는 방법으로 해결했다.
- SAP 의 SOAP 결과의 XML은 완전 패턴이 없었다. -
딱부러지는 XML 이 없이 노드(Node)속에 노드로 있는 놈과 노드속에 속성(Attribute)로 있는 놈도 있고 컬럼명의 목록이 다중행으로 나오는 놈도 있다. ㅡㅡ;; 컬럼명이 없는 놈도 있고 이중인 놈도 있고.. OTL... 해결한 방법은 컬럼명이 없는 놈은 header0~숫자 형식으로 무조건 지정받게 했다. 그리고 컬럼명이 1행이상인 것들은 언더바(_)로 구분지어 컬럼명을 바꾸었고 '합계_매출' '합계_금액' 이렇게 입력된 컬럼명은
합계
매출
금액
처럼 그룹헤더 컬럼을 자동생성되게 만들었다.
그리고 컬럼명이 없어 header0과 같이 만든 컬럼의 제목열은 속성을 Object 로 받아 제목, 길이 등 컬럼속성을 추가 할 수 있게 해서 데이터와 제목열을 구분했다.
결과적으로 특이한 DataGrid가 아닌 이상은 데이터만 잘주어지면 컬럼태그를 직접쳐서 넣지 않았기 때문에 자동으로 잘 보여졌다.
- 동기, 비동기 두가지 방식으로 구현 -
Webservice 태그에 concurrency 를 single 로 하고 동기방식으로 처리해서 여러 질의를 순차적으로 받게 한 것과 multiple 로 지정하고 비동기방식으로 처리하는 2가지 방식으로 만들었다. 동기방식은 최초 데이터(처음 전송한 질의)가 매우 빠르게 보이기 때문에 시각상으로는 매우 빠르게 느껴지나 전체 시간으로 보면 느리고 비동기방식은 한꺼번에 전송하나 데이터 처리시점에 많은 CPU 부하가 걸려 버벅일 수 있다는 점이 있다. 최종적으로 선택한건 역시 비동기 동시질의! (한.. 1년 후에 보면.. 쩝)
- 개념적으로 C언어에서 말하는 포인터를 알아야 데이터 가공이 용이하다. -
이미 난 XML을 공통적인 ArrayCollection 으로 받아와서 DataGrid의 DataProvider 에 넣어 사용하게 했다. 그런데 보여지는 형식을 다르게 보여달라고 하면? 프로젝트에 따라 다르겠지만 EIS에서는 보여주는 데이터가 최종이기 때문에 나의 경우 오리지널데이터를 가공했다.
예를들면 MDXQuery 에서 20110606으로 넘어 올때 2011.06.06으로 보이게 해달라고 하면 여타 아이템렌더러를 사용할 수 있지만 EIS에서는 2011.06.06이 최종이기때문에 데이터 자체를 2011.06.06으로 변경했다. 이렇게 변경할때 포인터 개념을 알면 쉽게 변경할 수 있다.
즉, 모든 데이터를 새로 작성할 필요 없이 루프를 돌며 데이터를 가공할 수 있다.
단, 반대로 ac객체와 별도로 Object값을 꺼낸후 사용할려면 ObjectUtil.copy 를 참고하면 포인터가 아닌 복사한 별도의 객체를 얻을 수 있다.
- Object 에서 프로퍼티를 빼고 싶을때는 delete를 사용해라. -
var obj:Object = {'e':'1', 'd':'2', 'c':'3', 'b':'4', 'a':'5' }
delete obj['c']; ( or obj.c )
의 결과는
obj = {'e':'1', 'd':'2', 'b':'4', 'a':'5' }
가 된다.
이건 모르면 좀 골치가 아프다. ㄷㄷ;;
- 엑셀형식, 화면캡춰, PDF 다운로드는 fileReference로 바로 다운 가능하다. -
fileReference.save(데이터, 파일명) 으로 별도의 웹페이지에 접근할 필요없이 다운로드 가능하다. flex3 만 알던 나는 몰랐다능.. ㅡㅡ
- 엑셀 다운로드는 DataGrid의 IViewCursor 를 사용하는 방식을 이용했다. -
IViewCursor는 DataGrid에 나오는 labelFunction 이나 DataProviderRender 와 같은 아이템렌더러까지 적용된 값을 가져오기 때문이다. 보통 공개된 HTML에서 위에 header0~숫자 형식와 '합계_금액' 형식의 colspan, rowspan의 구분도 처리 할 수 있었기 때문에 HTML 도 똑같은 머지가 되어 다운로드하게 만들었다.
- 템플릿 컴포넌트와 싱글톤 클래스의 이용 -
판넬과 같은 창영역은 템플릿 컴포넌트로 만들고 공통으로 사용하는 서비스와 MDXQuery질의 같은 함수와 요소들은 싱글톤 클래스로 만들어 사용율을 최대화 했다.
- 아이템런더러의 경우 공통요소가 아니면 태그내에 MXML로 만드는게 이롭다. -
공통적으로 사용하는 부분은 파일로 빼서 호출하게 하면 이해가 쉬운데 딱 하나의 DataGrid에 딱 하나의 컬럼에 쓰는 아이템 렌더러의 경우는 파일로 빼면 복잡하고 이해가 어려워 진다. 그냥 MXML 에 틀어 박았다. ㅡㅡ
= 총 평 =
개발하면서 느낀 건 왜 이리 생각만큼 잘 안 돌아가지? 하는 느낌이 제법 많이 들었다.
마우스 클릭, 웹서비스 인증이나 DataGrid에 1픽셀정도 아주 약간씩 어긋 나는 것, 머지시키고 스크롤 되면 어긋나는 것, 아이템렌더러에 화면 갱신 주기가 느려터지는 것... 넘 많다... ㅡㅡ;;
SAP는 첨이였지만 운영환경(Webservice, SAP GUI, MDXQuery등)적인 문제 보다는 Flex 버그수준의 저런 자잘한 문제에 부딪쳐 시간잡아 먹는게 대부분이였다. ㅡㅡ
이래서 계속 Flex 쓰겠나 싶기도 하지만 최종적으로는 사용자에게 만족할 만한 결과를 주는것 같다.
잘 안드는 과일칼로 열심히 깎았습니다.
2시간 걸렸는데.. 까면서 드는 생각 "내가 왜 깐 생강 살 생각을 안했지?! ㅠㅠ"
혹시나 만드실 분들은 깐 생각을 구입하세요. ㅠㅠ
깐생강과 배와 함께 갈아 즙을 내었어요. 랩과 스타킹의 조합이.. ㅎㅎ;;
깐생강과 배를 함께 넣어 열심히 돌립니다.
배는 창원ㅇㅁㅌ서 샀는데 8000원/4개라 걍 시장서 살까 했지만 시간이 늦어 어쩔수 없었죠. ㅠㅠ
설탕도 2K 구입햇습니다.
생강 양이 많아서 그런지 믹서기가 열받아서 막 멈춰 버렸죠.... ㅠㅠ
그래서 제가 이바구를 마~~~악하니까 믹서기가 재밌다고 다시 드르륵하면서 웃으면서 생강을 다 갈아버리는거 아닌겁니까?... 제가 왕년에 좀 어마어마 했거든요~~~ (개콘-왕년에버젼)
즙은 랩으로 손을 싸고(위생장갑이 당장없어서..ㅠㅠ) 새 스타킹(새것인게 반드시 중요합니다.-0-)에 꾸역꾸역 집어 넣고 짜버렸습니다.
나중에 1.5l 패트에 부어서 재어보니 약 2리터쯤이더군요.
저 남은 윗 부분이 커품으로 가득차니 계속 저어주어야 합니다.
약2L 즙에 설탕 2K를 부었는데 이게 그 절반입니다.
첨에 가득채워 끓이다가 거품이 시끕하고 반은 딴데 붓고 반만 끓였죠.
거품이 엄청 올라오니 좀 큰 냄비에 해야 한다능.. ㅎㅎ;;
생각보다 응고되진 않았습니다.
계속 졸여서 반정도 양으로 줄였습니다.
진한 액으로 나올줄 알았는데 생각보단 진하게는 안 나왔죠.
다 된건 병에 붓고 남은 반을 다시 끓여 졸였습니다.
완성됐습니다.
생각보단 많진 않습니다. ㅎㅎ;;
그렇게 완성되어 나온 갈아만든 배즙 생강차~ ㅎㅎ;;
생강2Kg + 중간 배 4개(약 1Kg) + 설탕 2Kg = 위 병 두개가 나왔습니다.
용량 재고 넣은게 아니라서 정확한 양은 잘.. ;;
잘 먹을께요. ㅎㅎ;;