'PROG.'에 해당되는 글 44건

  1. 2016.01.12 C#의 문제점
  2. 2015.06.02 Unmanaged Exports
  3. 2014.12.04 C# VS DELPHI 1
  4. 2013.04.18 Delphi TForm OldCreateOrder Property
  5. 2013.04.12 DELPHI StrToInt, StrtoIntDef, TryStrtoInt.. 사용시 주의
  6. 2013.04.11 DELPHI, RESOURCE에 데이터 넣기
  7. 2013.04.09 Delphi URW2824 Internal Error
  8. 2013.03.11 UNICODE stream 사용시 주의
  9. 2013.01.29 C++ 시스템 에러 사용자 정의
  10. 2012.05.04 델파이에서 TortoiseSVN SubWCRev 활용
  11. 2012.05.04 IOTAProjectOptions 의 Value 항목들
  12. 2012.04.25 델파이 2007 dproj 파싱 문제, 알수 없는 오류들
  13. 2011.02.24 TThread 에서의 예외 처리
  14. 2010.12.04 로그라이크류 개발을 위한 nForge 생성
  15. 2010.11.23 GR32 (TBitmap32) 에서 Blurred Text 그리기
  16. 2010.11.17 GR32 (TBitmap32) 에서 Flood Fill
  17. 2010.11.15 GR32 (TBitmap32) 에서 Gradient Fill
  18. 2010.01.26 Delphi 2007 Remote Debuging
  19. 2010.01.08 모달시 뒷 배경을 반투명으로...
  20. 2009.11.26 OpenCV + Delphi
  21. 2009.11.20 Open Source C/C++ IDE, QT + MinGW + OpenCV 2
  22. 2009.09.30 TRAC on Window
  23. 2009.09.23 Delphi2007, Vista에서 dcc컴파일 옵션이 제대로 안붙는 문제
  24. 2009.05.19 JAVA를 배워야 하는가
  25. 2007.08.16 반올림 (Rounding)
  26. 2007.07.13 특정 폴더와 파일들을 압축하기
  27. 2007.06.18 HSL Color Space를 사용하는 색상 선택창을 만들어 보자. 2
  28. 2007.06.18 Raster To Vector Conversion
  29. 2007.05.29 적목 효과 제거 프로그램을 만들어보자
  30. 2007.05.27 델파이는 객체지향적인 언어인가?

C#의 문제점

Posted by NUL PROG. : 2016. 1. 12. 11:51
기존 라이브러리를 C#으로 포팅해가며 이리저리 테스트하다보니...
딱 두가지가 문제더군요

1. 마샬링에 의한 퍼포먼스 저하...
   
- 그냥 감수한다... 뭐 퍼포먼스 좀 떨어지면 어때... 
- 감수 할수 없는 부분은 C++로 작성하고 UI만 C#으로 만든다.

2. GC에 의한 렉 발생

- GC가 발생하지 않도록 온갖 객체를 재사용하는 식으로 코딩(?)한다.
- 렉이 발생해도 별 문제 없는 타이밍에 GC.Collect 호출.

이런 저런 해결책이라는게 결과적으로 C#의 매력을 떨어뜨리네요.


  

Unmanaged Exports

Posted by NUL PROG. : 2015. 6. 2. 22:50

목적

  1. C#으로 쉽게 갈수 있는 길은 쉽게 가자.
  2. 하지만 델파이의 편리함은 버릴수 없다.
설치
  1. PowerCell 2.0 설치
    http://ratinel.tistory.com/25
  2. VS 2010 -> 도구 -> 확장 관리자 -> NuGet 패키지 관리자 설치
  3. VS 2010 -> 도구 -> NuGet 패키지 관리자 -> Unmanaged Exports 설치
    failed to initialize the powershell host 오류
    start-job { Set-ExecutionPolicy Unrestricted } -RunAs32 | wait-job | Receive-Job

사용

  1. 아직 안써봄....;


  

C# VS DELPHI

Posted by NUL PROG. : 2014. 12. 4. 23:00
C# 이 등장한지 (등장한걸 알게 된지) 대략 15년 쯤 된 것 같다.

처음엔 무시했고 시간이 지나도 굳이 저걸 쓸필요는 없겠다 싶었는데...

DELPHI의 발전이 너무 더디고 상대적으로 C#의 발전은 순조로와서 윈도우즈 운영체제하의 어플리케이션을 개발하는 입장에서 C#을 무시할 수 없게 됐다.

무엇보다 팀원에게 점점 시장에서 밀리기만 하는... 엠바케데로의 툴만을 배우라고 하기는 꺼림칙하다.




이런 연유로

그간은 전혀 관심도 없었던 C#에 대해 최근 틈나는대로 파고들면서 DELPHI 와 비교해 볼까 한다....

아래의 내용은 아직 관련 지식이 부족하고 선입견이 있을수 있기에

또 금새 생각이 바뀔수도 있을 것이다.

다분히 주관적인 글이다.




C# 의 장점

1. user control 적용의 편리함...

   델파이와 달리 프로젝트별로 user control 관리한다.
   장기간 유지 보수할 경우에는 편리한 델파이 컴포넌트가 악몽이 될수도 있는데,
   이런 고민이 없어졌다... 이건 2번과도 이어진다.

2. partial class

   라이브러리를 개발하고 유지보수하면서 늘 겪는 문제다.
   비슷하지만 다른 S/W 를 줄창 개발하다보니 결국 프로젝트마다 라이브러리 버전이 달라져 버린다.
   다품종 소량 생산의 S/W 를 만들다 보니. 하위 호환까지 따져 가며 작성하기엔 너무 고단한 일인데...
   partial class 와 1번을 조합하면 확기적으로 코드관리가 수월해질 거다

 3. 안정적인 IDE

  IDE의 창시자는  터보 파스칼 / 터보 C의 Borland 이지만,
  현재의 IDE의 수준은 MS 툴에 비교가 안되게 허접하다.
  그래도 오브젝트 파스칼 자체가 가독성이 좋고 구조가 간단해서 그나마 다행이랄까

4. 더 있을건데 아직은 C#을 잘몰라서... 여기까지... 



C#의 단점

1. Save as project 가 없다.

   그게 굳이 필요한가? 라고 생각할 분들이 많겠지만,
   유사하지만 다른.... 다품종 소량 생산 하는 개발자 입장에선 귀찮음을 덜어주는 매우 고마운 기능이다.
 
2. 코드 공개

   델파이의 핵심 프레임워크인 VCL은 내부 클래스의 코드를 볼수 있다.
   입문서 하나 딸랑 읽고 델파이를 익혀서 VCL의 파생 클래스를 자유자재로 만들어 사용할수 있었던 것도
   VCL 을 들여다 볼수 있으니까 가능한 것이었고,
   디자인 패턴이 뭔지도 모를때부터 자연스럽게 클래스의 설계 방식을 익힐수 있었다.

3. 선언과 구현의 분리
 
   구세대 프로그래머라서 그런지 헤더가 없는게 영 보기 어렵다.
   헤더 파일 자체가 없어도 델파이 처럼 선언과 구현이 분리 되어야 눈에 잘 들어온다.
   특히 IDE 없이 일반 텍스트 편집기로 코드를 보는 일이 많고 작성하는 일도 가끔은 있기 때문에
   블럭이 접히는 에디터를 따로 구해야할 판이다.

4. 배열 형태의 property

  델파이는 Grid.Values[r,c], Grid.Colors[r,c] 이런 식으로 다양한 프로퍼티가 가능하다.
  최근엔 namespace 까지 해서... 이름이 길어지는게 요즘 추세라지만... 짧게 할수 있는 건 짧은게 좋다
  위의 예를 C#으로 하자면 Grid.Rows[r].Columns[c].Color ,Grid.Rows[r].Columns[c].Value 너무 길다.
  구현도 더 복잡해진다.



별 차이 없는 것 들

1. garbage collection

   개인적으론 garbage collection 보단 스마트 포인터를 쓰는 게 낫다고 본다
   일의 특성상 반드시 메모리 관리를 직접 해주어야만 하는 경우가 은근히 많은데...
   unsafe 로 예외적으로 관리하기 보단 smart pointer 를 쓰는게 개인적으로 더 낫다고 본다.
   근데 smart pointer 는 델파이 기본 제공이 아니다. 만들어써야한다. 그래서 별차이 없음으로 분류

2. 컨트롤 사용이 복잡함

   MS 의 컨트롤은 모양이 더 이쁘다. 하지만 클래스 구조나 사용상의 컨셉을 보자면 VCL 이 더 좋다고 본다.
   다만 VCL은 20년이 지나도록 그닥 발전이 없다
   발전하긴 했는데... 20년이란 세월에 비교하자면... 좋은 점수를 주긴 힘들다.
   그래서 별차이 없음으로 분류

3. H/W API 지원

   점점 델파이는 밀려나가고 있다. 윈도우즈하에선 벤더들이 DOT NET을 밀고 나갈 작정으로 보인다.
   그래도 C++ 혹은 C API는 필수로 지원하니까 C++과 함께 사용하면 된다.
   C#도 어차피 C++과 같이 써야만 하는 일이 생긴다.
   물론 C#은 VC++과 IDE 를 함께 쓰니 더 편하긴 하겠지만, 
   어차피 C++은 모듈로 작성하기 때문에 큰 문제는 되지 않는다.



 
  

Delphi TForm OldCreateOrder Property

Posted by NUL PROG. : 2013. 4. 18. 19:28
폼의 생성과 파괴 시점이 중요할때가 있는데,

이 프로퍼티에 따라서 함수 호출의 순서가 달라지니 주의해야 한다.



기본값은 False 로

Create완료후에 AfterConstruction에서 OnCreate 가 호출 되고 Destroy 시작 전에 BeforeDestruction 에서 OnDestroy가 호출 된다.

True로 세팅 되면 Contructor 내부에서 마지막에 OnCreate 가 호출 되고 Destroy 내부에서 처음에 OnDestroy 가 호출된다.



생성/파괴 시점에 사용자 이벤트를 호출하다가 예외가 발생한다면 수습이 안되므로 False가 이치에 맞으니, 특별한 이유가 없는 한 가급적 기본값 그대로 써야 한다.

Create / Destroy 는 객체 멤버의 초기화와 메모리 해제에 중점을 두고, 그외의 동작들은 AfterConstruction / BeforeDestruction 에서 처리해야 한다. TCustomForm이라면 DoCreate / DoDestroy 를 쓸수도 있다.
  
내부적으로  Val(String, Var, Err) 함수를 쓰는 것들인데,

16진수를 인식하기도 합니다.

'$1234'   =>4660 당연하겠죠...
'0x1234' =>4660 C언어 스타일도 16진수로 인식합니다.
'x1234'   =>4660 이것 마저도 16진수로 인식하다니... 이건 좀 ....



그러고 보니 델파이 쓴지 10년이 넘었는데, 처음 익힐때 빼고는 도움말이나 레퍼런스를 읽어 본 기억이 없네요.

이번에 찾아보려니 실행도 안되네요. 어딘가 파일이 손상 된 듯....;

embacadero 홈페이지의 도움말에는 이런 언급이 전혀 없군요.

아마 봐봐야 별 도움 안되니 걍 소스 뒤져보는데에 익숙해진 듯합니다.




C++ 문서들은 그 방대함과 세세함이 참 부럽습니다.

물론 안봐도 대충 쓸수 있는 파스칼이 편하기는 한데... 이런게 의도하지 않은 결과를 일으키면 참난감함.



  

DELPHI, RESOURCE에 데이터 넣기

Posted by NUL PROG. : 2013. 4. 11. 18:13
일단 리소스 에디터를 추천  http://melander.dk/reseditor/




이걸 쓰면 RC 파일 작성하고 컴파일하는 수고를 할 필요가 없어짐

단지,

1. Add Resource - Add From File 로 데이터를 넣고 *.res 파일로 저장 
2. 프로젝트에 {$R 로 파일 추가
3. TResourceStream 로 읽어서 사용 

으로 끝납니다.





  

Delphi URW2824 Internal Error

Posted by NUL PROG. : 2013. 4. 9. 20:39
델파이란 놈이 다 좋은데,

가끔 이런 컴파일러 오류를 내뱉을 때가 있다.

구글 검색을 하면 이유도 참 다양하지만, 그 이유 마저도 확실치는 않다.

컴파일러 문제라는 것만 확실하다.



이번 케이스는 class helper 를 쓰다가 발생했다.

class helper 유닛을 uses 할때 interface 말고 implementation 아래에 써야 한다.

그간은 늘 implementation  아래에 써와서 몰랐었는데 (가능하면 항상 여기다 쓰는게 철칙임)

interface 아래에 쓰면 이 에러가 나더라...

(원래 그리 해야 하는 거면 메세지를 띄우든가...)



이런 메세지도 없는오류는 통상적으론 고치가가 어려운데

다행히도 델파이는 컴파일 시간이 엄청나게 빨라서 틈만 나면 빌드를 남발하는게 습관인지라,

기존 컴파일 잘되던 코드와 바뀐점을 쉽게 추론할 수 있었다.



참고로, 델파이의 빌드 속도는 살짝만 과장하면 인터프리터 언어를 실행하는 수준과 비슷하다.

10년이 넘은 구닥다리 PC로도 쾌적하게 컴파일 된다.

(쓰던 PC는 이번에 C++을 컴파일하면서 못버티고 결국 버렸다.)
  

UNICODE stream 사용시 주의

Posted by NUL PROG. : 2013. 3. 11. 22:13
http://golbenge.wordpress.com/2009/12/24/STL을 이용한 Unicode 텍스트 파일 출력

요약하자면.....

STL의 wchar_t 을 사용하는 스트림들이 내부적으론 char 로 변형해서 쓴다는 거....

내부적으로 잘 변형해서 읽고 쓰는데 문제가 없으면 아무 상관이 없으련만. 파일 입출력을 여러 형태로 하다보면 이게 또 의도대로 나오질 않는다.

왜 이렇게 했는지는 정말 의문인데... 

지금은 그걸 고민하긴 너무 바쁘니까 일단 위 링크의 방법대로 wchar_t 있는 그대로 쓰도록 조작을 해주자.

첫번째 링크는 설명이 자세하고 써먹기엔 두번째 링크가 간단하다.
  

C++ 시스템 에러 사용자 정의

Posted by NUL PROG. : 2013. 1. 29. 22:31
Thinking Asynchronously in C++ System error support in C++0x

part 1..5 까지 자세히 설명되어 있다.



블로그 프로필에 asio 개발자로 되어 있는데...

도대체 뭘해야 저런 월드 고수가 될수 있을까?



 - 일단 영어를 잘해야 할 듯 .....
 
  

델파이에서 TortoiseSVN SubWCRev 활용

Posted by NUL PROG. : 2012. 5. 4. 22:04
검색해서 찾아오신 분들은 다 같은 생각일 겁니다.

SVN의 리비전 정보로 리소스의 파일 버전으로 활용하면 편하지 않을까.... 그런 생각이죠


실행파일만 주는줄 알고 있었는데.... TortoiseSVN에서 COM 도 지원해주네요.... 여태 몰랐네....

http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/tsvn-subwcrev-com-interface.html 



델파이에서 Active X 설치 해도 되고...

전 걍 아래처럼 헤더 파일만 카피해서 씁니다.. 어차피 필요한 건 몇줄 안되거든요

2012/05/04 - [PROG.] - IOTAProjectOptions 의 Value 항목들
http://delphiaddinfortortoisesvn.tigris.org 

이런걸 조합하면 커밋할때 마다 리비전 정보를 res 파일의 버전 정보에 삽입하는 것이 가능합니다. 



2013-07-30 Tortoise SVN 1.8.1 업데이트 후 변경된 unit을 추가합니다.
그냥 Import Type Library 하면 되는데 참고삼아 올립니다. (syntax highlighter 테스트 겸...)


unit LibSubWCRev;

interface

uses Windows, ActiveX, Classes, Graphics, OleServer, StdVCL, Variants;
  
type
  ISubWCRev = interface(IDispatch)
    ['{2F5EA5B0-4DE7-4F96-8E6B-FC0C37D9C0D6}']
    procedure GetWCInfo(const wcPath: WideString; folders: WordBool; externals: WordBool); safecall;
    procedure GetWCInfo2(const wcPath: WideString; folders: WordBool; externals: WordBool; externalsNoMixed: WordBool); safecall;
    function Get_Revision: OleVariant; safecall;
    function Get_MinRev: OleVariant; safecall;
    function Get_MaxRev: OleVariant; safecall;
    function Get_Date: OleVariant; safecall;
    function Get_Url: OleVariant; safecall;
    function Get_Author: OleVariant; safecall;
    function Get_HasModifications: WordBool; safecall;
    function Get_HasUnversioned: WordBool; safecall;
    function Get_HasMixedRevisions: WordBool; safecall;
    function Get_HaveExternalsAllFixedRevision: WordBool; safecall;
    function Get_IsWcTagged: WordBool; safecall;
    function Get_IsSvnItem: WordBool; safecall;
    function Get_NeedsLocking: WordBool; safecall;
    function Get_IsLocked: WordBool; safecall;
    function Get_LockCreationDate: OleVariant; safecall;
    function Get_LockOwner: OleVariant; safecall;
    function Get_LockComment: OleVariant; safecall;
    property Revision: OleVariant read Get_Revision;
    property MinRev: OleVariant read Get_MinRev;
    property MaxRev: OleVariant read Get_MaxRev;
    property Date: OleVariant read Get_Date;
    property Url: OleVariant read Get_Url;
    property Author: OleVariant read Get_Author;
    property HasModifications: WordBool read Get_HasModifications;
    property HasUnversioned: WordBool read Get_HasUnversioned;
    property HasMixedRevisions: WordBool read Get_HasMixedRevisions;
    property HaveExternalsAllFixedRevision: WordBool read Get_HaveExternalsAllFixedRevision;
    property IsWcTagged: WordBool read Get_IsWcTagged;
    property IsSvnItem: WordBool read Get_IsSvnItem;
    property NeedsLocking: WordBool read Get_NeedsLocking;
    property IsLocked: WordBool read Get_IsLocked;
    property LockCreationDate: OleVariant read Get_LockCreationDate;
    property LockOwner: OleVariant read Get_LockOwner;
    property LockComment: OleVariant read Get_LockComment;
  end;

  CoSubWCRev = class
    class function Create: ISubWCRev;
    class function CreateRemote(const MachineName: string): ISubWCRev;
  end;

  const
    CLASS_SubWCRev: TGUID = '{F26E2640-0CFF-43DC-8325-575A3261D885}';
    
implementation

uses
  ComObj;

class function CoSubWCRev.Create: ISubWCRev;
begin
  Result := CreateComObject(CLASS_SubWCRev) as ISubWCRev;
end;

class function CoSubWCRev.CreateRemote(const MachineName: string): ISubWCRev;
begin
  Result := CreateRemoteComObject(MachineName, CLASS_SubWCRev) as ISubWCRev;
end;

end.
  

IOTAProjectOptions 의 Value 항목들

Posted by NUL PROG. : 2012. 5. 4. 19:13
SVN과 버전 정보의 연동을 위해서 써먹을수 있지 않을까 싶어 뽑아 봤습니다.

RC파일 만드는것보다는 낫겠다 싶어서요

델파이 2007 기준이고 TYPE=NAME 으로 표기했습니다.

tkLString=HostApplication
tkLString=RunParams
tkClass=EnvVars
tkClass=SysVars
tkClass=SymTabs
tkLString=Launcher
tkEnumeration=UseLauncher
tkLString=DebugCWD
tkLString=RemoteHost
tkLString=RemotePath
tkLString=RemoteParams
tkLString=RemoteLauncher
tkEnumeration=UseRemoteLauncher
tkLString=RemoteCWD
tkEnumeration=RemoteDebug
tkEnumeration=LoadAllSymbols
tkEnumeration=LoadUnspecifiedSymbols
tkLString=SymbolSearchPath
tkInteger=Align
tkInteger=BoolEval
tkInteger=Assertions
tkInteger=UnitDebugInfo
tkInteger=ImportedData
tkInteger=LongStrings
tkInteger=IOChecks
tkInteger=WriteableConst
tkInteger=LocalSymbols
tkInteger=TypeInfo
tkInteger=Optimization
tkInteger=OpenStrings
tkInteger=OverflowChecks
tkInteger=RangeChecks
tkInteger=StackChecks
tkInteger=TypedAddress
tkInteger=SafeDivide
tkInteger=VarStringChecks
tkInteger=StackFrames
tkInteger=ExtendedSyntax
tkInteger=ReferenceInfo
tkInteger=MinEnumSize
tkEnumeration=DebugInfo
tkEnumeration=RemoteSymbols
tkSet=OutputObj
tkEnumeration=GenHpp
tkEnumeration=HintFlag
tkEnumeration=WarnFlag
tkInteger=StackSize
tkInteger=MaxStackSize
tkInteger=ResourceReserve
tkInteger=ImageBase
tkEnumeration=Target
tkEnumeration=MapFile
tkEnumeration=GenDRC
tkEnumeration=GenDOC
tkLString=CompileName
tkLString=Defines
tkLString=SysDefines
tkLString=OutputDir
tkLString=UnitOutputDir
tkLString=UnitDir
tkLString=ObjDir
tkLString=SrcDir
tkLString=ResDir
tkLString=NamespacePrefix
tkLString=PkgDllDir
tkLString=OptionsString
tkLString=SOName
tkLString=SOPrefix
tkEnumeration=SOPrefixDefined
tkLString=SOSuffix
tkLString=SOVersion
tkLString=DynamicLoader
tkLString=PasCodepage
tkEnumeration=PasPlatform
tkEnumeration=SignAssembly
tkEnumeration=DelaySign
tkLString=KeyFile
tkLString=KeyContainer
tkInteger=WarnSymbolDeprecated
tkInteger=WarnSymbolLibrary
tkInteger=WarnSymbolPlatform
tkInteger=WarnSymbolExperimental
tkInteger=WarnUnitLibrary
tkInteger=WarnUnitPlatform
tkInteger=WarnUnitDeprecated
tkInteger=WarnUnitExperimental
tkInteger=WarnHresultCompat
tkInteger=WarnHidingMember
tkInteger=WarnHiddenVirtual
tkInteger=WarnGarbage
tkInteger=WarnBoundsError
tkInteger=WarnZeroNilCompat
tkInteger=WarnStringConstTrunced
tkInteger=WarnForLoopVarVarpar
tkInteger=WarnTypedConstVarpar
tkInteger=WarnAsgToTypedConst
tkInteger=WarnCaseLabelRange
tkInteger=WarnForVariable
tkInteger=WarnConstructingAbstract
tkInteger=WarnComparisonFalse
tkInteger=WarnComparisonTrue
tkInteger=WarnComparingSignedUnsigned
tkInteger=WarnCombiningSignedUnsigned
tkInteger=WarnUnsupportedConstruct
tkInteger=WarnFileOpen
tkInteger=WarnFileOpenUnitsrc
tkInteger=WarnBadGlobalSymbol
tkInteger=WarnDuplicateCtorDtor
tkInteger=WarnInvalidDirective
tkInteger=WarnPackageNoLink
tkInteger=WarnPackagedThreadvar
tkInteger=WarnImplicitImport
tkInteger=WarnHppemitIgnored
tkInteger=WarnNoRetval
tkInteger=WarnUseBeforeDef
tkInteger=WarnForLoopVarUndef
tkInteger=WarnUnitNameMismatch
tkInteger=WarnNoCfgFileFound
tkInteger=WarnMessageDirective
tkInteger=WarnImplicitVariants
tkInteger=WarnUnicodeToLocale
tkInteger=WarnLocaleToUnicode
tkInteger=WarnImagebaseMultiple
tkInteger=WarnSuspiciousTypecast
tkInteger=WarnPrivatePropaccessor
tkInteger=WarnUnsafeType
tkInteger=WarnUnsafeCode
tkInteger=WarnUnsafeCast
tkInteger=WarnOptionTruncated
tkInteger=WarnWideCharReduced
tkInteger=WarnDuplicatesIgnored
tkInteger=WarnInitSeq
tkInteger=WarnLocalPInvoke
tkInteger=WarnXMLWhitespaceNotAllowed
tkInteger=WarnXMLUnknownEntity
tkInteger=WarnXMLInvalidNameStart
tkInteger=WarnXMLInvalidName
tkInteger=WarnXMLExpectedCharacter
tkInteger=WarnXMLCREFNoResolve
tkInteger=WarnXMLNoParm
tkInteger=WarnXMLNoMatchingParm
tkLString=PkgDcpDir
tkEnumeration=UsePackages
tkLString=Packages
tkLString=UnitAliases
tkLString=ExeDescription
tkEnumeration=ImplicitBuild
tkEnumeration=RuntimeOnly
tkEnumeration=DesigntimeOnly
tkLString=DebugSourcePath
tkEnumeration=ImageDebugInfo
tkInteger=HeapSize
tkInteger=MaxHeapSize
tkInteger=LinkMaxErrors
tkEnumeration=LinkShowMangle
tkEnumeration=LinkGenImportLib
tkEnumeration=LinkGenLib
tkEnumeration=LinkNoStateFiles
tkInteger=LinkSubsysMajor
tkInteger=LinkSubsysMinor
tkEnumeration=LinkCaseSensitiveLink
tkEnumeration=LinkCalculateChecksum
tkEnumeration=LinkFastTLS
tkEnumeration=LinkReplaceResources
tkInteger=LinkUserMajor
tkInteger=LinkUserMinor
tkLString=LinkImageComment
tkLString=LinkDelayLoad
tkEnumeration=CppDebugInfo
tkEnumeration=LineNumbers
tkEnumeration=AutoRegVars
tkEnumeration=MergeDupStrs
tkEnumeration=EnableInLines
tkEnumeration=ShowWarnings
tkEnumeration=StdStackFrame
tkEnumeration=TreatEnumsAsInts
tkEnumeration=PCH
tkEnumeration=ShowInfoMsgs
tkEnumeration=ShowExtendedMsgs
tkEnumeration=GenDll
tkEnumeration=GenConsoleApp
tkEnumeration=GenPackage
tkEnumeration=GenStaticLibrary
tkEnumeration=ShowLinkerWarnings
tkEnumeration=LinkDebugVcl
tkEnumeration=InstructionSet
tkEnumeration=Alignment
tkEnumeration=CallingConvention
tkEnumeration=RegisterVars
tkEnumeration=Ansi
tkEnumeration=AutoDep
tkEnumeration=Underscore
tkEnumeration=PICCodeGen
tkEnumeration=FastFloat
tkEnumeration=PentiumFloat
tkEnumeration=NestedComments
tkEnumeration=MFCCompat
tkInteger=IdentLen
tkEnumeration=MemberPrecision
tkEnumeration=ForLoops
tkEnumeration=TwoChar
tkEnumeration=CodeModifiers
tkEnumeration=EnableRTTI
tkEnumeration=EnableExceptions
tkEnumeration=EHLocalInfo
tkEnumeration=EHDtor
tkEnumeration=EHPrologs
tkEnumeration=ZeroBaseClass
tkEnumeration=ZeroClassFunction
tkEnumeration=ForceCppCompile
tkEnumeration=MemberPointer
tkEnumeration=VTables
tkEnumeration=Templates
tkLString=PchPath
tkLString=PchStopAfter
tkEnumeration=UseDynamicRtl
tkEnumeration=MultiThreaded
tkEnumeration=ATLMultiUse
tkEnumeration=ATLDebugQI
tkEnumeration=ATLCoinitMultiThreaded
tkEnumeration=ATLAutoRegisterInproc
tkEnumeration=ATLDebugRefCount
tkEnumeration=ATLDebug
tkEnumeration=ATLThreading
tkEnumeration=CodeOpt
tkEnumeration=FloatSupport
tkLString=IncludePath
tkLString=LibPath
tkLString=DebugPath
tkLString=ReleasePath
tkLString=LibraryList
tkLString=TasmViaCppOpts
tkEnumeration=ClearPackageCache
tkEnumeration=ClearUnitCache
tkEnumeration=MarkModified
tkEnumeration=CaseSensitive
tkEnumeration=ExtendedDictionary
tkEnumeration=PurgeComment
tkInteger=PageSize
tkLString=ListFile
tkEnumeration=TasmCrossReference
tkEnumeration=TasmSymbolTables
tkEnumeration=TasmGenerateListing
tkEnumeration=TasmIncludeConditionals
tkEnumeration=TasmIncludeErrors
tkEnumeration=TasmExpanded
tkEnumeration=TasmCaseCheckingOn
tkEnumeration=TasmAllCase
tkEnumeration=TasmDebugOn
tkEnumeration=TasmFullDebug
tkEnumeration=TasmWarningsOn
tkEnumeration=TasmWarningsLevel1
tkInteger=TasmHashTable
tkInteger=TasmPasses
tkInteger=TasmSymbolLength
tkLString=TasmDirective
tkEnumeration=NoAskLibs
tkEnumeration=CGGlobalStackAccesses
tkEnumeration=CGThisPointer
tkEnumeration=CGInlinePointer
tkEnumeration=CGLinkCGLib
tkLString=DefaultNamespace
tkEnumeration=AutoRegisterTLB
tkEnumeration=AutoGenImportAssembly
tkEnumeration=AutoIncBuildNum
tkInteger=Build
tkInteger=CodePage
tkEnumeration=IncludeVersionInfo
tkClass=Keys
tkInteger=Locale
tkInteger=MajorVersion
tkInteger=MinorVersion
tkSet=ModuleAttribs
tkInteger=Release


 
  
최근 델파이 버전은 좀 다를지도 모르겠는데...

2007 버전에서는 dpr 이라는 프로젝트 소스와 함께 컴파일, 링크, 리소스, 패키지 옵션및 기타 자잘한 옵션들이 함께 저장되는 dproj 파일이 프로젝트 파일로 사용 된다.

하위 호환성을 유지하기 위해 IDE에서의 설정이나 dpr 소스의 수정에 따라 내용이 자동 변경되는데,
이때  엉뚱한 값을 저장한다든가 중복된다든가 하는문제가 발생해서 결과적으로는 아무 문제가 없이 빌드되어야할 프로젝트들이 차리리 access violation 이 더 나을 법한 도저히 이해할수 없는 오류를 내는 증상을 보여준다.
이때의 dproj를 열어 보면 파싱을 잘못했다는게 딱 보인다...;

원인을 알면 해결 방법은 간단히 유추할수 있다
이 dproj 파일을 수작업으로 고쳐주면 보통은 된다. (물론 안될때도 있다...;)
XML 형식이기에 대충 읽어 보면 뭘 의미하는지 유추할수 있고, 유추한대로 고쳐 쓰면 된다.

단, IDE 상에서 자동적으로 변경하므로 해당 프로젝트를 모두 닫고 수정한 후, 불러와서 사용한다.

비트맵 이미지들이 얽힌 리소스 관련해서는 암만 고쳐도 도루묵이라 포기하고 리소스 파일을 하나로 묶는 노가다를 하기도 했었다.

이런걸로 시간을 허비하는게 짜증나기도 하고...

정말 델파이의 고질적인 문제인데...
IDE 버그나 파싱 부분은 어찌보면 고치기 어려운 부분도 아닐진데 달라지는게 없다.
물론 이후버전을 써본건 아니지만 써본 사람들의 의견이 대체로 그렇다.
라이센스 정책상 1년 정도의 패치 밖게 받을수 없고 걍 다음 버전으로 넘어가는 델파이의 정책은 이런 버그들을 어영 부영 넘어가 버린다.

참 여러가지로 맘에 안드는데도 손에 익은 툴을 버리기가 무척 어렵다....
  

TThread 에서의 예외 처리

Posted by NUL PROG. : 2011. 2. 24. 22:13
http://edn.embarcadero.com/article/10452

예외를 보여주면서 종료시에 문제가 발생하지 않는 가장 적절한 방법 인듯...


추가로......

예외 발생 후 suspend 를 호출하면 액세스에러가 발생하는데

위 예제의 FExceptoin을 체크 하면 이를 방지 할 수 있슴

기본 TThread를 사용한다면 FatalException 체크해도 되지만,

위의 예제는 FExceptoin으로 Exception을 가져 오므로 FExceptoin 를 체크해야 함

  

로그라이크류 개발을 위한 nForge 생성

Posted by NUL PROG. : 2010. 12. 4. 21:21

아직까지도 뭘 만들지 정해진게 없이 끄적이다보니... 제목도 못정했어요

그냥 R-LIKE 로 했습니다.


아직 SVN 생성이 안되는 듯.... 소스 계속 올릴 겁니다.

필요하신분은 알아서 받아가시되 GPL 라이센스입니다.

뭐 어차피 이걸 가지고 상용 어플을 만들어봐야 팔지도 못하니 서로서로 공개하면서 배워 나가는게 좋겠죠


윈도우즈 + SDL + 델파이 기반입니다.
SDL 기반이라 리눅스 포팅도 쉽게 될 듯.....

SDL 라이브러리는 LIBSDL
SDL 라이브러리 헤더는 SDL-JEDI 에서 받으면 됩니다.


글이 심심하니 현재까지 작업된 스샷 올립니다. (공개하지는 않았지만 Direct X 기반으로 만든 2007/04/02 - [PROG.] - 게임 제작의 전반적인 컨셈 보다 완성도가 떨어집니다. 거의 손을 안대다 보니 -_-;)



실행파일도 R-LIKE 개발 페이지 에서 받을 수 있습니다.

  

GR32 (TBitmap32) 에서 Blurred Text 그리기

Posted by NUL PROG. : 2010. 11. 23. 18:45
늘 그렇듯 간단 팁입니다.


Blurred Text 란건 아래와 같은 걸 의미합니다. (영어가 맞는지는 모르겠지만 제가 쓰는 함수 이름임...;)



흰색 글자지만 배경에 흐릿하게 붉은빛이 돕니다.



이런 텍스트는 아래의 순서대로 출력합니다.

1. 붉은색 텍스트를 출력
2. Blur 처리
3. 흰색으로 다시 덮어 씀.

간단하죠


Blur 효과를 주기 위해 GR32_Lines 에 포함된 TStackBlur를 사용했습니다.
procedure JnDrawBlurredText( BMP: TBitmap32;
                        const Str: String;
                        const X, Y: Integer;
                        const ABlurrColor, ATextColor: TColor32;
                        const ARadius: Integer = 1;
                        const ARepeat: Integer = 3);
var
  i: Integer;
  BmpTxt: TBitmap32;
  szTxt: TSize;
begin
  BmpTxt := TBitmap32.Create;
  try
    BmpTxt.Font.Assign(BMP.Font);

    szTxt := BmpTxt.TextExtent(Str);
    BmpTxt.SetSize(szTxt.cx + ARadius * 2, szTxt.cy + ARadius * 2);

    BmpTxt.Clear(ABlurrColor and $00FFFFFF);
    BmpTxt.RenderText(ARadius, ARadius, Str, 0, ABlurrColor);

    with TStackBlur.Create(ARadius) do
    try
      for i := 1 to ARepeat do
        Execute(BmpTxt);
    finally
      Free;
    end;

    BmpTxt.RenderText(X, Y, Str, 0, ATextColor);
    BmpTxt.DrawMode := dmBlend;

    BmpTxt.DrawTo(BMP, X - ARadius, Y - ARadius);
  finally
    BmpTxt.Free;
  end;
end;

  

GR32 (TBitmap32) 에서 Flood Fill

Posted by NUL PROG. : 2010. 11. 17. 18:29
2010/11/15 - [PROG.] - GR32 (TBitmap32) 에서 Gradient Fill 에 이어서 Flood Fill 을 구현해 봅니다.
마찬가지로 GDI 함수로는 알파값이 누락 되기 때문에... 


1) 4 방향 FloodFill
procedure JnFloodFill1(BMP: TBitmap32; const X, Y: Integer; const AColor: TColor32);
var
  C: TColor32;
begin
  C := BMP.Pixel[X,Y];

  BMP.Pixel[X,Y] := AColor;

  if BMP.Pixel[X - 1, Y] = C then JnFloodFill1(BMP, X - 1, Y, AColor);
  if BMP.Pixel[X + 1, Y] = C then JnFloodFill1(BMP, X + 1, Y, AColor);
  if BMP.Pixel[X, Y - 1] = C then JnFloodFill1(BMP, X, Y - 1, AColor);
  if BMP.Pixel[X, Y + 1] = C then JnFloodFill1(BMP, X, Y + 1, AColor);
end;
가장 간단하게 생각할 수 있는 코드 입니다. 4방향을 탐색하면서 재귀호출을 합니다.

문제는 Stack Overflow 가 발생한다는 점.

델파이는 Tail Recursive Optimization 을 지원하지 않기 때문에 재귀호출로는 암만 고민을 하고 수정해봐야 헛일입니다. 지원한다해도 위의 코드 그대로는 안되겠죠.
델파이 프리즘은 TAILCALL 컴파일 지시자를 지원합니다.  다만 현재로서는 닷넷 기반의 델파이 프리즘은 그닥 내키지 않기 때문에 다른 방법을 써야 합니다. 이것 때문에 VC, GCC로 개발한다는것도 배보다 배꼽이 더 큰 격이죠.



2) 4 방향 FloodFill - Stack 사용
procedure JnFloodFill2(BMP: TBitmap32; const X, Y: Integer; const AColor: TColor32);
var
  C: TColor32;
  Stack: TStack;

    procedure Sub_Push(const APxPos: Integer);
    begin
      BMP.Bits[APxPos] := AColor;
      Stack.Push(Pointer(APxPos));
    end;

    procedure Sub_Check;
    var
      nPos, N: Integer;
    begin
      nPos := DWORD(Stack.Pop);

      N := nPos - 1;
      if BMP.Bits[N] = C then Sub_Push(N);

      N := nPos + 1;
      if BMP.Bits[N] = C then Sub_Push(N);
      
      N := nPos - BMP.Width;
      if BMP.Bits[N] = C then Sub_Push(N);

      N := nPos + BMP.Width;
      if BMP.Bits[N] = C then Sub_Push(N);
    end;

begin
  Stack := TStack.Create;
  try
    C := BMP.Pixel[X, Y];

    Sub_Push(X + Y * BMP.Width);
    while Stack.Count > 0 do
      Sub_Check;
  finally
    Stack.Free;
  end;
end;
재귀 호출을 없애고 TStack 을 사용했습니다.
GoTo 문으로도 작성이 가능할까요?.... 별로 하고 싶지 않습니다...;;

여기서는 속도에 문제가 좀 있습니다.
TStack 은 사실상 TList 이고, 이 놈은 매번 메모리를 늘였다 줄였다 하거든요



3) 4 방향 FloodFill - Array 사용
procedure JnFloodFill3(BMP: TBitmap32; const X, Y: Integer; const AColor: TColor32);
var
  C: TColor32;
  Stack: PIntegerArray;
  Index: Integer;

    procedure Sub_Push(const APxPos: Integer);
    begin
      BMP.Bits[APxPos] := AColor;
      Inc(Index);
      Stack[Index] := APxPos;
    end;

    procedure Sub_Check;
    var
      nPos, N: Integer;
    begin
      nPos := Stack[Index];
      Dec(Index);

      N := nPos - 1;
      if BMP.Bits[N] = C then Sub_Push(N);
      N := nPos + 1;
      if BMP.Bits[N] = C then Sub_Push(N);
      N := nPos - BMP.Width;
      if BMP.Bits[N] = C then Sub_Push(N);
      N := nPos + BMP.Width;
      if BMP.Bits[N] = C then Sub_Push(N);
    end;

begin
  Index := -1;
  C := BMP.Pixel[X, Y];

  GetMem(Stack, BMP.Width * BMP.Height);
  try
    Sub_Push(X + Y * BMP.Width);
    while Index > -1 do
      Sub_Check;
  finally
    FreeMem(Stack);
  end;
end
똑같은 코드를 TStack 대신 배열로 잡았습니다. 처음 한번만 넉넉하게 메모리를 잡아 줍니다.
이젠 불필요하게 메모리를 만지지 않겠죠.
이렇게 하니 속도가 조금 개선 되네요.
물론 그래봐야 재귀호출 보다는 느리니, 최적화된 재귀호출에 비해서도 느리겠죠...;



테스트 결과


1), 2), 3) 순서대로 200x200 사이즈의 BOX 내부에 FloodFill한 결과입니다.
1)번에서 스택 오버플로가 발생하지 않도록 기준점을 정중앙으로 잡았습니다.

1 ms 정도 느리지만 무시하고 그냥 씁시다......;;;


  

GR32 (TBitmap32) 에서 Gradient Fill

Posted by NUL PROG. : 2010. 11. 15. 18:44

Graphics32
 는 델파이를 사용하는 사람중에서는 모를 사람이 없을 정도로 유명한 라이브러리입니다.


Gradient Fill 을 구현할 경우 Angus Johnson 님의 GR32_Lines/GR32_Text 를 쓰면 대부분의 Gradient 를 구현할 수 있습니다. (Gradient 이외에도 유용한 기능이 많죠)


다만 속도가 문제인데요. 비교적 단순한 Gradient 효과를 주기 위한 용도로는 조금 느린감이 있습니다.

그렇다고 인라인 어셈블리어로 대체할 능력은 안되기 때문에... 저는 윈도우 API를 사용합니다.

function GradientFill; external msimg32 name 'GradientFill';


윈도우 2000 부터 지원하는걸로 알고 있고요.

제가 만들어 쓰는 GUI 용 컴포넌트들은 이걸 많이 사용합니다.


이 함수를 비롯한 여타의 GDI 함수를 Bitmap32에 적용할 때의 문제점은 알파값이 누락 되는데 있습니다.
(혹 가능한 방법이 있을지는 모르겠네요)

그래서 API 를 쓰고 해당 부분의 알파 값을 재지정 하는 단순무식한 방법을 쓰곤 합니다 -_-;


아래는 가로 방향 Gradient 의 한 예 입니다.
procedure JnGradientFillHor(BMP: TBitmap32; const R: TRect; const B, C1, C2: TColor32);
var  
  TriVertex: array[0..1] of TTriVertex;  
  GradRect: array[0..1] of TGradientRect;
  i: Integer;
  P: PColor32;
begin
  GradRect[0].UpperLeft := 0;
  GradRect[0].LowerRight := 1;
  GradRect[1].UpperLeft := 1;
  GradRect[1].LowerRight := 2;
  TriVertex[0].Red :=   (C1 and $00FF0000) shr 8;
  TriVertex[0].Green := (C1 and $0000FF00);
  TriVertex[0].Blue :=  (C1 and $000000FF) shl 8;
  TriVertex[1].Red :=   (C2 and $00FF0000) shr 8;
  TriVertex[1].Green := (C2 and $0000FF00);
  TriVertex[1].Blue :=  (C2 and $000000FF) shl 8;
  TriVertex[0].x := R.Left;  TriVertex[0].y := R.Top;
  TriVertex[1].x := R.Right;  TriVertex[1].y := R.Bottom;
  GradientFill(BMP.Canvas.Handle, @TriVertex[0], 2, @GradRect[0], 1, GRADIENT_FILL_RECT_H);
  
  P := @BMP.Bits[0];
  for i := 0 to BMP.Width * BMP.Height - 1 do
  begin
    P^ := P^ or $FF000000;
    Inc(P);
  end;

  BMP.FrameRectS(R, B);
end;
좌측이 GR32_Lines에서 제공하는 SimpleGradientFill 함수, 우측이 위의 함수를 사용한 결과입니다.




200x200 사이즈의 Gradient Fill 에서 속도 차이가 20배 가까이 나오네요 (단위는 nanosecond)


GradientFill 함수를 커스터마이징 하면 다양한 Gradient 효과를 줄수 있습니다.

다만 Radial Gradient Fill은 방법이 없네요.. 


아무튼 전 이런 식으로 쓰고 있답니다.



  

Delphi 2007 Remote Debuging

Posted by NUL PROG. : 2010. 1. 26. 03:09

방법

Using_the_Remote_Debugger_with_Delphi_2007_and_Delphi_2009

위의 링크에서 매우 친절하게 스샷에 박스 그려서 설명해 주고 있다. (영어 몰라도 한눈에 알수 있음)


원래 있는 문제점

델파이 2007이 원격 디버깅에 문제가 좀 있다. 디버깅 하다 보면 IDE가 자주 죽어버린다.

원격 디버깅 대상 프로그램도 함께 사라져버리기도 한다 -_-;


새로 발견한 문제점?

그동안 버그를 피해가며 잘 써온 원격 디버거인데... 새로 제작하는 장비의 PC에서 오류가 발생했다.

Exception Processing Message c0000013 Parameters 764cbf7c 4 764cbf7c 764cbf7c

무시하고 써도 되긴 하는데... 원격 PC에 뜨는 메세지창을 클릭해대는 것이 여간 귀찮은게 아니다. 당연하겠지만 IDE 오류도 더 빈번히 발생하다.

처음에는 델파이에 제공되는 리모트 디버거에 문제가 있나 생각에 여기저기 뒤져봤으나 소득이 없었다.

그런데 저 오류 메세지로 검색해보니 엄청난 양의 검색 결과가 나온다.

바이러스, 악성코드에서부터 하드웨어 혹은 윈도우의 설치상의 문제 등등 원인도 다양하다...


사실 바이러스일거라고는 생각조차도 못했는데...

아마도 특정 바이러스 혹은 악성 코드가 넷트웍을 사용하면서 특정 상황에서 저런 오류를 발생시키는가 보다.

바이러스/악성코드야 지워버리면 그만이지만 난 디버깅을 해야만하니까... 별 도움이 안되는 정보다.


내 개인 데스크탑도 같은 오류가 발생했는데... 혹시나 하는 생각에 바이러스 검사를 해봤다...

시간이 너무 오래 걸린다 5% 되자 취소.


다음은 하드웨어 관련(드라이버 설치 및 알수 없는 윈도우 시스템 파일등등) 문제를 확인해보려는데...

윈도우를 다시 깔기는 싫다 - 보통 한번 윈도우를 깔면 피씨가 안켜질때까지 써야 한다고 본다. -

결국 하드웨어 목록에서 안쓰는 걸 [사용안함]으로 체크하기로 결정 (http://pc.ahnlab.com/bluebelt_pcdic/pcdic_view.do?BBS_SEQ=274318 가뭄의 단비와 같은 글이다 ㅜㅜ)


내 데스크탑도 장비 PC와 같은 증상이라 일단 이걸로 테스트하기로 결정하고

장치관리자에서 필요없는 플로피 디스크 드라이버를 찾아 [사용안함]으로 체크...

그러니까 잘된다... 이게 도대체 뭔일인지 -_-;


바로 달려가 장비 PC에서 플로피 디스크 드라이버를 [사용안함]으로 체크...

역시 잘된다... 이런 허무한...

그런데 이건 고객이 플로피 디스크를 달아달라고 했기 때문에 장치를 없애 버리면 안된다.

장치관리자 목록을 보는데 뺼게 아무것도 없다. 장비 PC라보니 PCI 슬롯 가득, LPT, 추가적인 포트, USB 몽땅에 1394 까지 사용한다. 도대체 뺼수 있는게 없다.

결국 다시 운영체제를 설치해야만 하는가 그래도 안되면 디버깅할때만 플로프 디스크를 잠가둘까.... 하고 체념할 뻔 했는데...

장치관리자에 모니터가 2개가 보인다... 음 이거 뭐지... 하나 제거... 다시 테스트해보니 OK


결국 해결... 프로그래머 다운 해결법도 아니고 정확안 원인 파악은 안됐지만... 

리모트 디버거를 리버스 엔지니어링해서 원인을 규명하고픈 생각은 들지 않는다.


결론

XP 기준으로 내컴퓨터 - 하드웨어 - 장치관리자에서 쓰지 않는 장치는 모두 사용안함으로 체크.

  

모달시 뒷 배경을 반투명으로...

Posted by NUL PROG. : 2010. 1. 8. 08:21

델파이 2007 기준입니다.

델파이 7 버전도 되는걸로 알고 있슴.


Application.OnModalBegin

Application.OnModalEnd 를 사용합니다.

OnModalBegin 에서 반투명 폼으로 스크린을 덮어 버리고, OnModalEnd 에서 폼을 닫는 거죠.



예전에... 휴대폰 대화박스가 뜰때 이런식이라 구현해 본 건에 알고보니 이미 이런 팁은 많이 나왔더군요. -_-;

정보가 흘러 넘처서 주체하지도 못할 지경의 세상이니 이런 소박한 꼼수들이야 뭐...

Dim Out the Main Form of an Application When Modal Form is Displayed

Modal폼을 띄울때 Disable되는 폼을 Gray톤으로 ...


소스 + 실행파일 포함입니다.


  

OpenCV + Delphi

Posted by NUL PROG. : 2009. 11. 26. 22:34

어차피 DLL 인 라이브러리라 델파이에 못 붙일 것도 없죠
델파이용 DLL 헤더 만드는 일은 늘상있는 일이기도 하고요
그렇지만 전체 헤더를 몽땅 변환하는 건 정말 고되고도 재미 없는 작업입니다.
그래서 보통은 그때 그때 필요한 함수와 타입만을 끄집어 냅니다.
계속 같은 작업을 하다 보면 저절로 분량도 많아지고
같은 작업을 안하다보면 별로 쓸일이 없는 거니 굳이 전체 헤더 변환을 할필요가 없겠죠
(물론 시간만 된다면야 못할것도 없지만...)

아무튼 이번에도 그런식으로....
OpenCV 를 이용한 템플릿 매칭(Template Matching) + 소스 포함 이곳의 소스를 테스트 삼아 델파이로 컨버전 했습니다.

Source / exe / dll 포함
OpenCVDelpphi_Ex.7z



굳이 델파이로 헤더까지 만들어 쓸 필요가 있을까.... 싶을지도 모르겠지만

  1. 헤더 만들기가 그리 어려운게 아니고
  2. 헤더 만들다 보면 자연스럽게 함수 원형에 구조체나 자료 구조를 파악하게 됩니다.
  3. 가공할만한 델파이의 GUI 개발 능력에 편승할 수 있습니다.
  4. 특히 http://graphics32.org 와 연동하면 빠르고 화려한 GUI를 구성할수 있습니다... 그것도 무료로 (너무 오래된 거라 좀... 그렇지만... 아직까지도 몹시 쓸만합니다. MIL 에도 붙여 보았었죠)
  5. C 보다는 파스칼이 C++ 보다는 오브젝트 파스칼이 버그 유발 확률을 현저하게 줄여 줍니다.
  6. 알고리즘을 완벽히 파악한다면 GPU 활용에 쓰일 수도 있겠군요 (음 이건 C/C++도 마찬가지네)

위 샘플 이외에도 몇가지 더 돌려봤습니다.
그것들을 클래스로 단순화 / 캡슐화도 해봤고요.
꽤 쓸만합니다.

여가 시간이 많아진다면 계속 해보고 싶네요.
현업 때문에 쉽지는 않겠지만 가급적이면 OpenCV 의 사용을 줄이고 직접 알고리즘을 작성해 봤으면.... 하는데 ...



2015-11-24 내용추가

케케묵은 내용이지만 어쩌다가 구글링으로 여기까지 들어온 분들에게 민폐가 되지 않도록 내용 추가합니다.


델파이로 헤더를 만드는 건 아주 비효율적인 방법입니다. 

OpenCV는 현재까지 매우 빠른 발전을 보이고 있고, 앞으로도 그럴것이라 예상 되는바

그때마다 헤더 고치는 노가다를 하느니 C++ 을 사용하는 것이 훨씬 낫습니다.


델파이와 연동할 땐

C++로 DLL 제작 (virtual class 사용) Delphi에서 사용합니다. (graphics32는 여전히 쓸만합니다)





 

  

Open Source C/C++ IDE, QT + MinGW + OpenCV

Posted by NUL PROG. : 2009. 11. 20. 08:30

갑자기 C/C++을 왜?

OpenCV (Open Source Computer Vision library) 를 구경하는 중....
소스만 보기 갑갑해서 델파이로 헤더 변환 노가다 해가며 테스트 하다가...
이게 뭔 삽질인가 싶어서 비용 부담 없는(GPL, LGPL, BSD, 기타 등등) C/C++ 를 찾게 되었슴.

Code::Blocks : Cross-Flatform C++ IDE
Eclipse : 유명한 자바외 기타 등등을 위한 IDE
wxWigets : Cross-Flatform UI Framework
QT : Cross-Flatform UI Framework
MinGW : GNU Compiler for Windows
BCC5.5 : Borland C++ 5.5 Compiler. 공개되었음.
RELO : Windows 용 C++ IDE

등등을 둘러보며 헤매다가 QT 로 결정

QT는 한큐에 IDE, GUI 라이브러리와 MinGW 까지 설치 되니 이보다 더 편할 수가 없다.
게다가 Nokia 에서 인수 후, 앞으로의 전망도 좋아 보임.

설치방법

1. QT SDK를 를 설치하면 IDE인 QT Creator 와 MinGW까지 같이 한꺼번에 설치됨

2. OpenCV 를 설치

3. __exchange_and_add 에 대해 에러가 나는데, 소스를 수정해야 한다. 이것 때문에 많이 헤맸음 ㅠㅠ

  • Open cxoperations.hpp (found in <Open CV base dir>\include\opencv)
  • Find this section (lines 67-68 in 2.0):
      #else
        #include <bits/atomicity.h>
        #if __GNUC__ >= 4
  • And update it to reference a new definition, __MINGW32__ (defined by the MinGW compiler, see http://predef.sourceforge.net/precomp.html#sec31):
  •   #else
        #include <bits/atomicity.h>
        #if __GNUC__ >= 4 || __MINGW32__
    http://opencv.willowgarage.com/wiki/InstallGuide

    4. 프로젝트 생성시 다음과 같이 세팅

    INCLUDEPATH += [OpenCV설치경로]\include\opencv

    LIBS += [OpenCV설치경로]\lib\libcv200.dll.a

    LIBS += [OpenCV설치경로]\lib\libhighgui200.dll.a

    LIBS += [OpenCV설치경로]\lib\libcxcore200.dll.a


     



     

      

    TRAC on Window

    Posted by NUL PROG. : 2009. 9. 30. 09:59

    http://trac.tistory.com/

    http://kkamagui.tistory.com/90


    TOW 패키지 릴리즈및 Subversion 설치 가이드 입니다.

    TRAC 같은 경우 설정이 꽤 복잡한데 간단히 설치할수 있게 잘 정리해서 배포하시고 계십니다.

    이런 분들 매우매우 고맙죠.


    이번 기회에 회사에서 적용을 해보려고 합니다.

    개인적인 코드들도 따로 넣어보고 싶고.... (딴데다....)

    마침 회사 서버가 윈도우 2003이니 거기에 구겨넣어볼까 생각 중입니다...

    사실은 서버하나 만들어달라고 하고 리눅스로 전용 서버 구축을 했으면 하는데...

    들어줄지도 잘 모르겠고... 진행중인 프로젝트가 겹겹이 겹쳐있는 상황이라 일을 만들기가 부담스럽네요.




      

    https://forums.embarcadero.com/thread.jspa?threadID=1069&tstart=0

    간단 요약하면 환경변수의 Platform 항목을 지워주면 된다는 거


    착한 직장 동료 덕에 4년만에 노트북을 업그레이드 하게 됐습니다.

    술 사준다고 했는데 요즘 서로 바빠서 언제 먹으려나 -_-;

    아무튼 문제는 OS가 비스타라는건데... 망할 HP사가 아예비스타밖에 못쓰도록 박아놔 버렸네요.

    나중에 클래스 플랫폼 개발을 시도해보려는데 이거 리눅스 깔기도 고달플 듯


    아무튼....


    문제가 델파이 2007 사용시 설정한 컴파일 옵션이 제대로 안붙습니다.

    뭘하든 --no-config가 붙어 버립니다. -_-;

    처음엔 맵(map)파일과 리모트디버깅(rsm) 파일이 갱신이 안되길래 왜 그럴까 몇시간을 헤매다 찾았지요 어흑....

    그 후엔 인터넷이 되는 여관(출장중이라...)에서 구글 검색 중 단 하나의 링크글을 발견...

    ...

    스크립트 파싱을 못한 코드기어의 잘못인지 난데없는 Platform=MDC 가 세팅되는 비스타의 문제인지..

    외진곳에 쳐 박힌 현재로선 알길이 없지만.... (별로 알고 싶지도 않음)

    다른 버전의 윈도우에는 이런일이 없었죠....;

    나중에 누군가 헤매는 사람이 또 있을까 봐(구글 보면 그리 많지는 않은 듯?) 블로깅합니다.

    그외에도 느리고 불편한게 많네요.이노므 비스타... ㅜㅜ

      

    JAVA를 배워야 하는가

    Posted by NUL PROG. : 2009. 5. 19. 13:54
    10여년전...
    첫 직장을 물색하던 중 선택이 있었다.
    JAVA 기반 웹 서비스를 할 것인가...
    델파이 기반 Win32 FA 프로그래밍을 할 것인가...

    조건도 비슷하고...
    중요한 요소 중 하나인 집과의 거리도 둘다 2시간이나 되고 -_-;

    지금도 그러하지만 당시에도 IT 분야의 급성장과 더불어 JAVA가 꽤 각광 받고 전망있는...

    그런 언어였었고... 지금도 그러하지만 그때도 공장자동화란 그닥 폼이 나지 않는 ...ㅋ
    그런 직종이었는데 (이름 자체가 그렇다는 얘기)...

    어찌 선택을 델파이 기반 FA로 해버렸었다.
    기계공학 석사까지 마치고 막상 직업을 프로그래머로 하다보니...
    전공이 아닌 것에 대해 손해를 보지 않을까... 하는 얕은 생각에...
    좀더 편한 길을 가고자 하는 생각에...
    (이건 완벽한 판단 미스였다. 이 분야는 프로그래머에게 육체적(?)인 고통도 준다)
    공장자동화 프로그래머의 길로 들어섰다.

    그때의 선택이 옳았는지 아닌지,
    이미 지나간 선택에 대해서 판단할 수는 없지만, (일단 현재 먹고 살고는 있으니 엄청나게 잘못된 선택은 아닌 듯?)
    한가지 분명한 사실은 있다.

    S/W 의 최신 기술로부터 멀어졌다는 것!

    최근 10년간의 모든 S/W 공학 기술은 그 시작이 어디였던 간에 결국 JAVA를 통해 전파 되었다.
    실제 현업에 최신 기술을 적용하는 것도 게임산업을 제외한다면 대부분 JAVA. (닷넷도 있다고 한다면.. 뭐 그렇다고 치자 ㅋ)

    물론 기술이 뒤쳐진 1차적인 이유야 본인의 게으름이겠지만...
    설사 부지런했다 한들... 현업에서 경험치를 쌓아가며 스킬업 하는 것과
    혼자 스터디 하는 것은 어차피 차이가 있을 수 밖에 없지 않을까...

    이런 생각을 하다보니...
    JAVA를 배워야 하는게 아닌가... 하는 질문을 던지게 됐다.

    여기에 대한 해답은 차차 찾아야겠지만...
    1. 어설피 배우는 것은 그다지 효과가 없지만 당장 JAVA의 세계로 뛰어들기엔 당장의 많은 손해를 감수해야 한다는 것.
    2. 비록 개발자 이지만 현실적으로 볼때, 그 외의 분야에 시간을 투자하는 것이 더 이익일수 있다는 것.
    3. 확실한 선택은 못하더라도... 맛보기 정도는 접할수 있다는 것 - 이개 쓸모가 있느냐는 나중의 문제로 보고...

    현 프로젝트가 끝나면 해야할일이 하나 늘었다.
    아직 구입한 책도 다 못읽었는데 -_-;
      

    반올림 (Rounding)

    Posted by NUL PROG. : 2007. 8. 16. 19:15
    일반적으로 반올림이라 하면 특정 자리수가 4이하면 버리고 5이상이면 올리는것을 말하며, 이를 산술 반올림(Arithmetic Rounding) 이라 합니다. 하지만 델파이에서는 이 산술 반올림을 쓰지 않죠. (다른 언어는 레퍼런스를 참조해야 합니다. 모르겠다는 뜻 -_-;)

    델파이에서 사용하는 라운딩 방법은 Banker's Rounding이라 불리는 넘으로, 1.5와 2.5는 둘 다 2로, 3.5와 4.5는 둘 다 4로 즉, 가장 가까운 짝수로 라운딩합니다. 이는 Arithmetic Rounding 에서 발생하는 편중 오차를 줄이기 위함입니다. 1,2,3,4는 버림 6,7,8,9는 올림을 하고 5를 모두 올림해버리면, 올림을 할때가 1/9 번 많아지게 되는 것이니까요.
    즉, Round(1.5) + Round(2.5) = Round(1.5 + 2.5) 가 성립합니다.

    물론 Banker's Rounding도 오차의 여지가 있으므로 Random Rounding(제멋대로 반올림 -_-) 이나 Alternate Rounding(교대로 반올림) 등을 쓰기도 합니다.

    하지만, 간혹 산술적인 반올림(Arithmetic Rounding)이 필요한 때가 있습니다. 이때는 직접 만들어 써 줍니다.
    Arithmetic Rounding Function function RoundA( X : single ) : Integer;
    begin
       if val > 0 then result := Trunc(val + 0.5)
       else result := Trunc(val - 0.5)
    end;


    Default8087CW 와 Set8087CW($1B32); 로 델파이의 반올림 방법을 바꿀수 있긴 합니다만......
    매우 비추천하는 방법입니다.
    CPU의 컨트롤 워드를 조작하는 것이기 때문에... 다른 어떤 부분에서 영향을 받을 수도 있기 때문입니다.
      

    특정 폴더와 파일들을 압축하기

    Posted by NUL PROG. : 2007. 7. 13. 21:58
    이번 팁은 팁이 아닌 엽기행각일 수도 있다. -_-;

    파일 압축에 대한 고민

    보통의 데이터 파일의 압축은 델파이에 포함된 ZLIB를 사용하면 손쉽게 TStream 객체를 이용하여 다양한 포멧의 데이터들을 압축할 수 있기에 즐겨 사용하고 있다. 다만, 어떤 요구에 의해 사용자가 일반 압축 프로그램으로 데이터를 풀고자 희망할 때, 그러면서 동시에 많은 파일과 폴더 압축이 되어야 할 때 고민이 생긴다. 과연 이 하나의 기능을 위해 압축 컴포넌트를 설치하여 써야 한단 말인가. 특히나 자주 쓰지 않는 기능이라면, 언제나 최소한의 소스를 유지하고픈 잠재적 욕구에 의해 고민을 하지 않을 수 없다.

    순간 보이는 빵 아이콘

    사용자 삽입 이미지
    빵집이라는 무료 공짜 공개 소프트웨어가 있다. 회사에 압축 프로그램 사달라고 떼쓰기도 거시기 하기에 납품하는 PC에 늘 설치하는 이 고마운 빵집. 그렇다. 언제나 PC와 윈도우즈 및 기본적은 프리웨어를 늘 설치해서 납품해왔던 것이다. 그렇다면, 걍 빵집을 쓰면 되겠네 -_-; 빵집을 열어 보았더니 스크립트를 제공하고 있다. 공개 소프트웨어를 만들고 배포하는 분들에게 무한의 공경심과 고마움을 느껴야 한다는 절대적 사실을 또 한 번 깨닫게 된다.

    빵집 스크립트 파일 포멧

    1. 확장자는 bsz 이다.
    2. 세미콜론이 주석이다.
    3. Mode=Compress는 압축, Extract는 해제이다.
    4. ArchiveFile=압축 파일 경로+이름이며 <DATE>는 자동으로 날짜를 파일 이름에 붙여주고 <INDEX>는 동일 이름의 파일이 존재하면 파일 이름에 숫자를 추가한다.
    5. Progress.Caption=진행상황 윈도우의 캡션
    6. Progress.Text=진행상황 윈도우의 텍스트 메세지
    7. Files.RootPath=압축할 파일의 경로
    8. Files.Count=압축할 파일+폴더의 합
    9. Files.0=파일 이름 혹은 폴더 이름
    10. Files.1=파일 이름 혹은 폴더 이름
    11. Files.2=파일 이름 혹은 폴더 이름
    12. Extract.Path=압축을 해제할 때의 대상 경로
    13. After.Run=압축/해제의 완료후에 실행될 파일
    구구절절이 설명을 달아 놓았지만 그냥 빵집에서 스크립트 생성해보고 그 파일을 읽어 보면 감이 잡힐 것이다 -_-;
    사용자 삽입 이미지

    빵집 스크립트 편집 화면


    스크립트 파일을 생성해서 동작시키자

    간단한 파일 압축 함수 예제(허접하니 고쳐서 쓰시라) procedure BackUp(ABackupFolder: String);
    var
      szPath: String;
    begin
      szPath := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
      with TStringList.Create do
      try
       Add(';BreadZip Script Version 1');
       Add('Mode=Compress');
       Add('ArchiveFile=' + IncludeTrailingPathDelimiter(ABackupFolder) + 'EX_<DATE><INDEX>.zip');
       Add('Progress.Caption=백업하련다');
       Add('Progress.Text=금방 되니 참고 기둘려라.');
       Add('Files.RootPath=' + szPath);
       Add('Files.Count=3'); // 3개를 압축
       Add('Files.0=config'); // config 폴더
       Add('Files.1=data'); // data 폴더
       Add('Files.2=EX.ini'); // ex.ini 파일
       SaveToFile(szPath + 'Ex_Compress.bzs');
       ShellExecute(0, 'Open', PChar(szPath + 'Ex_Compress.bzs'), '', '', SW_SHOW);
      finally
       Free;
      end;
    end;
    압축 해제할 때도 마찬가지의 방식으로 하면 된다.

    자~ 이제 남은 건 고객의 PC에 무조건 빵집을 설치하는 일만 남은 것이다. 후후.....;
      
    "HSV Color Space를 사용하는 색상 선택 창을 만들어 보자"라는 포스트의 업그레이드판 되겠다.

    기존 TJnColorPanel 에 HSL을 추가 했고, CMYK에서 K를 빼버리는 만행도 저질렀다. 더 추가하면 RadioBox 대신 ComboBox를 넣어야 하기에, 일단은 여기서 중단. (개인적으로 한눈에 다 보이는 RadioBox를 더 선호함)

    우선 기본 개념을 살펴보자.
    1. HSL Color Space : 위키를 보자
      - 친절하게도 이미지, 수식, HSV와의 비교도 쓰여 있다.
      - 더는 설명이 필요치 않다고 여긴다.
    2. CMYK Color Model - yellow(노랑), magenta(자홍), cyan(청록)인데, 혼합할수록 명도가 떨어진다.
      - 이 Color Model은 흰색과 검은 색이 나올 수가 없기에 K로 이를 표현 하지만, 다이알로그의 공간이 모자라는 이유로 여기서는 CMY만을 넣었다.
      - 마찬가지의 이유로, YCbCr Model 도 취급하지 않았다.

    이전과 바뀐 부분을 확인해 보자.

    HSL Color Space Record TColorHLS = record
      H: Single;
      L: Single;
      S: Single;
    end;

    HSV Color Space Record TColorHSV = record
      H: Single;
      S: Single;
      V: Single;
    end;

    통일감을 주고자 타입을 전부 Single 형으로 바꾸었다. 레코드 이름이 TColorHLS인 건 오타가 아니다!
    TColorHSV와 자꾸 혼동이 되어, 확실히 구분하도록 이렇게 명명한 것이다. (헷갈리는 건 못참는다. 그래도 똑같이 헷갈린다면 할 말 없다.)

    New CMYK Color Model 함수 function CMY2RGB(const C,M,Y: Byte): TColor;
    procedure RGB2CMY(const AColor: TColor; out C,M,Y: Byte);

    CMYK에 대한 함수는 아래와 같이 이미 델파이에 정의되어 있다. 따라서 따로 레코드를 만들지 않았다.
    CMYK Color 델파이 함수 function GetCValue(cmyk: COLORREF): Byte;
    function GetMValue(cmyk: COLORREF): Byte;
    function GetYValue(cmyk: COLORREF): Byte;
    function GetKValue(cmyk: COLORREF): Byte;
    function CMYK(c, m, y, k: Byte): COLORREF;


    HSV 관련 함수가 변경되었다. TColorHSV 레코드를 실수형으로 바꾸다 보니 저리되었고, 그렇다 보니 수행속도가 더뎌져서 실수, 정수 두 가지 종류의 함수를 구현했다.
    정수형만 쓰면 오차가 발생하니까 급할 때만 정수형을 쓰도록 한다.
    HSV Color Model Record function HSV2RGB(const HSV: TColorHSV): TColor; overload;
    function HSV2RGB(H,S,V: Byte): TColor; overload;
    procedure HSV2RGB(const HSV: TColorHSV; out r,g,b: Byte); overload;
    procedure RGB2HSV(const R,G,B: Byte; var HSV: TColorHSV); overload;
    procedure RGB2HSV(const AColor: TColor; var HSV: TColorHSV); overload;


    이번에 추가된 메인 함수!! 위키,구글,Graphics32 라이브러리를 무단 참조했다. 굳이 더 자세히 쓸 게 없다. 결과만 보자 -_-;
    HSV Color Model Record function HLS2RGB(H, L, S: Integer): TColor; overload;
    function HLS2RGB(const HLS: TColorHLS): TColor; overload;
    procedure RGB2HLS(const AColor: TColor; out HLS: TColorHLS);



    사용자 삽입 이미지

    HSL Color Space


    사용자 삽입 이미지

    CMYK Color Model


    invalid-file

    다운로드 : 언제나 그렇듯 맘대로 쓰되 출처를 밝혀주면 고마울 것이다.

      

    Raster To Vector Conversion

    Posted by NUL PROG. : 2007. 6. 18. 08:32
    자주 가는 델파이 포럼에서 이에 대한 질문이 나왔었다.
    이에 대한 가장 확실한 대답은 "상용 라이브러리를 구매하라"가 되겠다 -_-;
    회사에서 인정을 해준다면 모를까(보통은 그럴 일은 없다), 괜히 알고리즘에 손대 봐야 사서 고생할 뿐이다. 범용적이고 안정적인 알고리즘을 구현하는 데에는 상당한 시간과 노력이 필요하기 때문이다.
    단, 재미삼아 해보는 것은 괜찮을 것 같다. 이런 재미도 있어야지...
    따라서 시간이 되는대로 이 주제(Raster To Vector Conversion)에 대한 포스팅을 해볼까 한다.
    물론, 전공도 전산이 아니고 업무 영역도 이쪽이 아닌지라. (머신 비전을 사용하긴 하지만 이미지 프로세싱 부분은 사서 쓴다 -_-;) 어쩌면 대단히 허접한 코드가 태어날지도 모르겠으나 늘 그렇듯 개의친 않을 것이다.

    대략적인 구상을 해보았다.

    1. 이미지의 색상을 단순화하기 위한 포토샵의 포스터라이즈 필터 구현.
      - 간단한 방법이 있지만 결과가 좀 허접하다. 좀 제대로 된 효과가 나오도록 구현을 해볼 것이다. (물론 잘 안되면 그냥 간단한 걸로 넘어가겠지만...)
    2. 외곽 픽셀 혹은 뼈대를 이루는 픽셀 추출
      - 외곽선을 따올 것인지 패치의 뼈대를 따올 것인지 두 갈래로 나뉜다.
      - 외곽선의 경우 이미지에 유용하고 뼈대의 경우 숫자나 문자 검출 유용하다고 할 수 있다.
      - 둘 다 할지 하나만 할지는 아직 정하지 않았다.
    3. 이 픽셀들을 추출할 때 각각의 픽셀의 연결 정보를 알 수 있는 적당한 자료구조를 만들어야 한다.
      - 그래야만 쉽게 Vector 변환 을 할 수 있다.
    4. 이젠 이 픽셀들을 바탕으로 Segment(선분)를 추출한다.
    5. 무수히 많은 선분 중 불필요한 것들을 삭제하고, 하나로 묶을 수 있는 것들은 묶는다.
    6. 뼈대를 추출할 때는 상관이 없으나 외곽선을 추출할 때는 2가지 옵션이 있다.
      - 단순히 외곽라인을 따라갈 것인지...
      - 이 선분들을 토대로 폴리곤을 만들 것인지
      - 둘 다 선분의 방향을 정해야 하겠지만 폴리곤을 만들 경우에는 Triangular Mesh가 추가되어야 한다. (슬슬 귀찮은 생각이 들기 시작...)
    7. 생성된 결과를 적당한 Vector Graphic 포멧으로 만들어야 하는데, SVG 가 어떨까 생각 중이다.
      브라우저에서도 읽을 수 있고, InkScape 라는 프리웨어가 있었던 걸로 기억하는데, 그게 맞는다면 파일 포멧을 찾아본 후 적용할 것이다
      브라우저에서 못 읽는다거나 프리웨어가 아니거나 포멧이 복잡하다면 -_-; 걍 대강 그려 넣겠다....;
    여기까지 쓰고나니 잠시 헷갈리기 시작한다.
    분명 GIMP 나 InkScape 가 GNU License로 알고 있는데, 그렇다면 이런 삽질할 필요 없이, 그 소스를 보면 되는게 아닌가 -_-; 어차피 소스 분석은 불가능 하겠지만....; GIMP 나 InkScape의 라이센스와 소스르 좀 뒤적거려봐야 겠다. -_-;
      

    적목 효과 제거 프로그램을 만들어보자

    Posted by NUL PROG. : 2007. 5. 29. 23:12
    적목현상이란?

    어두운 곳에서 사람의 동공이 확대되었을 때 플래시를 터트리며 사진을 찍게 되면, 플래시 빛이 이 확대된 동공을 통과하여 망막 뒤의 모세혈관에 반사되고 이 반사된 붉은빛이 다시 카메라의 렌즈로 들어와서 빨간 눈으로 사진이 찍히게 되는데 이를 적목현상이라 한다.

    이를 피하려면 ......
    1. 동공이 커지지 않게 조명을 밝게 하거나 (혹은 밝은 곳에서만 사진을 촬영 -_-;)
    2. 플래시의 빛이 반사되는 것이기에 피사체를 중심으로 플래시와 렌즈의 각도를 크게 하거나 (즉 렌즈와 플래시의 거리를 떨어뜨리거나 별도의 조명을 사용)
    하는 방법이 있다.

    일반적으로 디지털 카메라는 그 크기가 매우 작아서 특히 이런 현상이 자주 발생한다.

    아무튼 이를 보정하는 프로그램을 작성해보도록 하겠다. 일단 완성품을 보도록 하자

    사용자 삽입 이미지

    이번에도 집사람의 사진을 무단 도용하였다 (미안 -_-;)



    사용자 삽입 이미지

    마우스를 드래그하면 사각 영역이 그려지고,



    사용자 삽입 이미지

    드래그가 끝나면 선택 영역의 적목현상으로 나타난 빨간 눈을 대충 바꿔 준다.



    사람이 영역을 선택해 주기 때문에 시퀀스가 단순하다. 만약 이를 완전 자동화한다면, 사람의 얼굴을 찾고 눈을 찾는 알고리즘이 들어가야 하는데, 이게 쉽지 않고 구현한다 하더라도 어느 정도의 오류 발생을 감수해야 한다.

    아래와 같이 쉽게 쉽게 하도록 하자 -_-ㅋ
    1. RGB 칼라맵의 R 강도를 구하고 그 값이 일정 수치 이상인 경우를 찾는다.
      일정 수치라는 건 다양한 테스트로 아무거나 정하거나, 평균값을 구하거나, 평균값에 가중치를 약간 주거나 맘에 드는 걸로 하자.
      예제에서는 그냥 적당한 숫자를 넣었다.
      R 값의 강도 (Redness) 구하기 function SubGetRedness: Double;
      begin
        if r = 0 then Result := 0
        else Result := (r - g + r - b) / r / 2;
      end;
    2. R의 강도가 일정 수치를 넘으면 그 R 값을 G, B 값의 가장 작은 값으로 대체 해준다.
      이때 너무 빨간 빛이 확 줄어버릴 수 있기 때문에 적당한 가중치를 적용하여 기존 R 값을 넣어준다.
      예제에서는 8:2로 넣었다.
      R 값을 8:2 로 보정하는 식 r := Trunc(Min(g,b) * 0.8 + r * 0.2);

    너무 간단하게 끝나 버렸다......;

    눈이 아닌 부분의 픽셀을 보정하지 않게 막으려면,
    R 값이 일정 수치 이상일 때 기하학적인 정보로 눈동자의 중심을 찾고 눈동자의 중심에서 멀리 떨어진 픽셀을 제외 시키는 방법도 좋겠다.
    기하학적인 정보로 눈동자를 찾기 어렵다면, 픽셀 좌표의 분포를 검사해서 대략 적인 중심을 구할 수도 있다.

    좀 더 부드러운 느낌이 들도록 보정 하려면,
    적목효과 보정 주변 픽셀에 블랜딩을 주거나 혹은 블러 효과를 넣는 것도 좋을 것이다.

      

    델파이는 객체지향적인 언어인가?

    Posted by NUL PROG. : 2007. 5. 27. 13:46
    사용자 삽입 이미지
    유명한 델파이 동호회에서 이런 이야기가 잠시 흘러나온 적이 있다.
    내 생각을 말하자면 "객체지향적이든 아니든 중요하지 않다."이다
    물론 동문서답 격인 대답이므로 답글을 달진 않았다. (요즘은 인터넷 공간에 엉뚱한 글을 답글로 쓴다는 것은 상당한 용기가 있어야 한다.)

    우선 객체지향(OOP : Object-Oriented Programming)적인 언어라는 것이 무엇을 의미하는지 알아야 한다.

    Class, Object, Method, Message 등으로 구성되어 Encapsulation, ,Abstraction, Polymorphism의 특성이 있는 언어라 할 수 있겠다. ( 위키피디아 에서 따왔는데, 한글 위키라 그런지 설명이 좀 부실하다. 10년 전인가 이 개념을 이해하고자 3-4권의 책을 반복으로 정독하고 10여 권을 책을 훑어 본 적이 있음을 기억할 때 그리 간단하게 규정하기는 어렵다고 본다. 이것은 범위가 넓은 거대한(?) 이론이기 때문이다. )
    아무튼 대강 그런 뜻이라 여기고 넘어가도록 하자.

    항상, 그 이론보다 중요한 것은 그 이론이 발생하고 발전하게 된 동기이다.
    즉, 왜 이러한 이론이 필요한지, 무엇을 위한 이론인지가 중요하다.

    누가 이론이 아니랄까 봐 어려운 말들로 잔뜩 설명이 되어 있는 일도 있지만,
    간단히 이야기하면 원하는 기능의 코드를 빠르고 유지보수가 쉽도록, 추후의 작업에 재사용 가능하도록. 최초 설계 단계에서의 편리성과 보다 정확한 검증을 위해......
    한마디로, 생산성의 향상을 위한 것이다.

    이렇게 본다면, 어떠한 언어가 얼마나 OOP인가를 따지는 것보다는 어떠한 언어가 생산성이 있는가를 따지는 것이 더 의미가 있다고 본다. 비록 일반적 이론상의 OOP에 미치지 못하는 부분이 조금 있다손 치더라도 그걸로 인해 생산성이 더 향상된다면 굳이 이론상의 OOP를 억지로 구겨 넣어야 할 필요가 없다.
    물론 여기서 말하는 생산성은 단순히 빠른 작업 속도만이 아닌 편리성, 안정성을 추가한 개념이다. 뭐 사실 그것이 빠른 작업 속도에 영향을 끼치긴 마찬가지이지만.....

    예를 들면, 폼 기반의 애플리케이션 구조를 가진 델파이의 VCL은 객체지향적이라고 하기엔 부족한 면이 있지만, 이는 매우 편리한 UI 제작을 위한 DESIGN 개념을 위한 것이고 그만큼의 충분한 생산성을 향상시켰기 때문에 객체지향적이지 못하다는 것이 큰 문제가 되지 않는다는 것이다. 같은 이유로 모호한 다중상속을 좋아하지 않는다.

    또 한가지,

    객체지향이라는 것은 방법이나 구조에 대한 이론이기에 그 언어가 크게 중요하지 않다.
    즉 어느 정도 객체지향적으로 프로그래밍할 수 있는 언어라면 OOP 이론을 적용하여 프로그래밍하는 것 자체가 중요하지 언어가 중요한 것이 아니다.

    실제로 class만 있을 뿐이지 C++ 인지 C 인지 구별이 안 되는 코드는 사방에 널려 있다.

    델파이의 예로 들면 VCL의 폼 기반 애플리케이션 설계는 객체지향적이라 보기 미흡하지만 독립된 몇 가지의 클래스로 데이터를 관리하고 폼은 단지 보여주기만 할 뿐...... 의 방식으로 코딩한다면 매우 훌륭한 객체지향적 프로그래밍을 할 수 있다.

    요약하면... (구세대 교육을 받은 결과 인지, 요약을 하지 않으면 끝맺음이 뭔가 부실한 느낌이다. -_-; )
    • OOP를 따르는 것보다 OOP의 목적을 성취하는 것이 더 중요하다.
    • 이를 위해서는 사용하는 언어가 얼마나 객체지향적인가 보다는 개발자가 얼마나 객체지향적으로 프로그래밍할 수 있는가가 중요하다.
      
     «이전 1 2  다음»