백만년만에 글을 쓰게 되었는데, 글이 책리뷰라서 좀 안타깝긴하다.
네이버 카페 코드인(http://codein.co.kr)에서 책 리뷰를 해 줄 리뷰어를 모집했고, 그래서 얼른 냉큼 후딱 신청해서 당첨이 되었다.

리뷰하려고 하는 책은 "안드로이드 프로그래밍 정복 1권" 이다.

안드로이드프로그래밍정복.1(개정판)SDK2.3진저브레드를적용한안드?
카테고리 미분류
지은이 김상형 (한빛미디어, 2011년)
상세보기


회사에서 하는 일이 Office 프로그램개발인데, Java를 이용해서 만들어야 했으므로 Java swing을 기준으로 개발을 해 왔었다. 하지만 시대의 급변에 따라서 모바일 환경이 중요해졌고, 안드로이드쪽을 공부해야 했었다. 그 때 마침 리뷰어를 모집하는 글이 눈에 띈 것이다.


보통의 프로그래밍 개발 관련 자료들은 인터넷에 널려 있다. 이러한것들이 책으로 출간되는 이유는 무엇일까? 개인적으로 몇가지는 꼽자면 아래와 같다.

1.
첫번째 이유는 튜토리얼은 영어로 되어 있다는 것이다. 아무리 영어를 잘 한다고해도 한글로 되어 있는 문서보다 영어를 읽는데는 어려움이 따른다. 물론 영어 단어의 의미를 정확하게 파악하기도 힘들다.

2.
두번째 이유는 정제되어 있는 내용을 쉽게 읽을 수 있다는 것이다. 인터넷에 떠다니는 내용들은 정확한 내용이 아닐 수도 있고, 아예 잘못된 내용들이 맞는것처럼 돌아 다니는 경우도 있다. 물론 경험적인 측면에서 내려진 답들은 책에 나오지는 않을 수 있지만, "경험적"이라는 의미가 "정확한"이라는 의미가 되지 않는것은 확실히다.

3.
세번째 이유는 좀 더 읽기 쉽다는 것이다. 아무리 좋은 내용이라도 모니터로 보는것과 종이로 보는것이 눈의 피로도에서도 다를 것이다. 그리고 책을 한장 한장 넘겨가면서 읽는것, 그리고 몇번씩 줄을 그어가면서 읽는것, 중요한 내용을 표시하기 위해서 책의 한쪽 끝을 접어 두는것 등의 아날로그적 감성도 한 몫한다.

물론 다른 의견을 가지고 있는 사람도 있으리라.



이전에도 개인적인 궁금함으로 몇권을 안드로이드 관련 책을 따로 구매해서 읽었는데, 그리 만족스럽지는 않았다. 인터넷에 있는 튜토리얼 보다도 못한 책들도 읽었던 것으로 기억한다. 차라리 영어로 되어 있는 인터넷 사이트를 보는게 더 편했을법한 책들도 읽어 보았다.

그런 면에서는 지금 리뷰를 하는 책은 이제까지 읽었던 책 중에서는 제일 좋다고 생각한다. 원래 출간 될 때에는 한권으로 되어 있는 책이었는데, Android SDK 2.3이 나오고 책의 내용도 더 보강을 해서 1권과 2권으로 나누어서 총 2권으로 다시 출간 되었다.



1권은 개발환경 설정부터 Android 개발에 관련된 전반적인 내용이 나온다.

이클립스 설치부터 ADT, DDMS 사용법까지 개발환경을 스크린 샷과 함께 제공해 준다. 현재 Android SDK 3.0이 나오지 않은 상태에서는 책에 있는데로 하면 큰 무리는 없을 듯 하나, 환경 설치등은 인터넷에서 찾아서 최신환경에 맞추는것이 좋아 보인다.

그리고 안드로이드의 기본인 액티비티, 레이아웃, 뷰, 메뉴 관리, 리소스 관리 등이 나온다. 이는 안드로이드에서 기본이 되는 내용이므로 Android를 처음 접하시는 분들은 반드시 읽어보고 알아야 하는 내용이다. 원래 기본기가 중요한거다.


2권에서는 고급스러운 주제들이 나온다.

실무에서 사용하기 좋은 정보들은 2권에 있다. 1권에 있는 내용들은 기초를 다루고 있기 때문에 자바에 경력이 충분하고 본인이 프로그래밍적인 센스가 있다고 생각하는 사람이라면, 기본기는 인터넷으로 튜토리얼을 찾아서 읽고 2권을 구매하여 읽는것이 도움이 될 듯하다.

2권에서는 렌더링, 애니메이션, 네트워크, 미디어 처리에 대해서 나오며, Hello World 프로그램만 짜고 싶지 않다면 2권을 반드시 읽어 보는것이 좋을 듯 하다.



처음에는 이 책을 보고 인터넷에서 떠돌아 다니면서 보았던 안드로이드 관련 정보들을 머릿속에서 새롭게 정리하다는 생각으로 읽어 보았다. 1권에서는 안드로이드 기본에 대해서 잘 나와 있기 때문에 도움이 되었다. 그리고 "이제 실무에 쓸 수 있는 내용을 읽어 볼까~"했는데 정작 고급주제들은 2권에 있다고 한다.

처음 책을 받았을때는 "정복"시리즈답게 한권에 모두 있을 줄 알았는데, 알고보니 내가 리뷰를 하게 된 책은 1권이었던 것이다. -_- 책을 다 읽고 나서 책표지에 있는 "1" 이라는 숫자를 발견하다니 ;;;


실무에서 사용할 고급스러운 주제는 2권에 있으니 책을 구매하실 때는 이러한 점에 유의해야 한다. 처음부터 탄탄한 기초를 쌓고 싶다면 1권부터 사서 읽으시고, 이미 기본적인 내용을 알고 있으시다면 2권부터 시작해도 큰 무리는 없을 듯 하다.

다음 주말즈음에는 2권을 구매하여 읽어 볼 생각이다. 고급 주제중에 일부는 인터넷에서 자료를 찾기 힘든 내용도 있다. File이나 CP 같은 경우에는 인터넷에서 자료를 좀 찾을 수 있었지만, 서페이스뷰 같은 경우에는 쉽게 찾기 힘든 분야이기도하고, 잘 설명 된것도 못 보았다. ( 잘 설명된 "한글"페이지가 있다면 알려..굽신굽신..)


여하튼 1권만 읽었으니 1권만 평가를 한다면, 이제까지 읽어 보았던 안드로이드 관련 책 중에는 제일 잘 만든 책임은 확실하다.
저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
  1. 닉쑤 2011.04.03 05:52 신고

    리뷰 솔직담백하게 잘 쓰시는데요? ㅋ

    별일 없으시죠? ^^

    아, 저 4월 20일날 한국가요. 움하하!

    • Chan 2011.04.03 21:17 신고

      오~ 한국에? 좋은 소식 가지고 오길 빌께. ㅎㅎ

최근 들어 일을 하면서, 어떻게 하면 오해 하지 않도록 코드를 짤 수 있을까? 에 대해서 많은 생각을 한다.

과제 제출용으로 작성하거나, 혹은 테스트로 작성하는 코드가 아니라면, 일반적으로 하나의 프로그램을 여러명이서 작성하게 된다. 그러므로 내가 만들어 낸 코드를 나 혼자 쓰는것이 아니라, 다른 사람도 사용하게 된다. 이때 다른 사람들은 내가 만들 소스 코드를 정확하게 이해하고 쓸 수 있을까? 내가 소스를 이렇게 작성한 의도를 정확하게 파악할 수 있을까?

그렇기 때문에 나 스스로 코드를 작성할때, 되도록이면 오해하지 않는 코드를 작성할 수 있도록 노력하고 있다. 물론 노력하고 있다는 것은 여전히 그렇게 하지 못하고 있다는 의미를 포함하고 있다. ㅎㅎ

내가 생각하는 오해하지 않는 코드의 조건은 아래와 같다.
1. 읽기가 쉬워한다.
2. 의미가 명확해야 한다.

그래서 오해하지 않는 코드를 짜기 위한 생각해둔 방법중 하나인 "수직적인 코드"에 대해서 이야기 해 보고자 한다. "수직적 코드"는 내가 임의로 붙인 이름이다. 아마도 이미 나보다 백만배는 더 똑똑한 사람이 이런 개념을 정리해 두었을거라 생각하지만... 조사 따위 하지 않는다. ㅋㅋㅋㅋ



예를 들어...

간단한 프로그램을 예로 들어 설명하도록 하겠다.

프로그램의 동작

1. 사용자 이름과 암호를 입력 받아 로그인을 한다.
2. 파일 dialog를 띄워서 특정 파일을 선택한 후에 OK라는 글자를 저장한다.
3. 사용자에게 결과를 알려 준다.

이 프로그램을 작성하는 두가지 예제를 차례대로 보고, 수평적 코드와 수직적 코드에 대해서 알아 보자.


첫번째 예제

아래의 코드는 위에 제시한 프로그램을 구현한 아주 더럽게 작성된 예이다. 이 글에서 설명하고자 하는 것을 명확하게 하기 위해서 아주 극단적인 예제로 작성했으니, "세상에 저렇게 프로그램을 짜는 사람이 어디 있냐?" 라고 말하지 마시길... ( 알고보면 자신이 짠 코드들 중에 저런 코드가 존재할 수도 있으니... ㅎㅎ )

첫번째 예제

첫번째 예제


다시 한번 말하지만, 위의 코드는 조금 억지스러운 부분이 있다. 하지만 설명을 위해서 그러니 용서를... 위의 코드는 상당히 코드를 읽기가 힘들다. 하나의 메소드를 읽고 있는 도중에 다시 다른 메소드를 호출하고 있고, 다시 메소드를 읽고 있는 도중에 또 다른 메소드를 호출하게 된다. 이러한 코드는 한곳에서 코드를 모두 읽어 볼 수 없고, 하나의 메소드에서 또 다른 메소드로 계속 추적하면서 내용을 읽어 보아야 한다.

위에서 작성한 코드를 시퀀스 다이어그램과 비슷한 형태로 나타내면 아래와 같이 나타낼 수 있다.

수평적 코드 그림

수평적 코드


이 코드는 startSave에서 loginAndSave를 호출하고, 다시 loginAndSave가 save를 호출하고 있다. 하나의 메소드가 또 다른 메소드를 호출하게 되어, 코드의 흐름이 왼쪽으로 오른쪽으로 좌우로 넓게 나열되게 된다. 이러한 코드를 "수평적 코드"라고 하자.



두번째 예제

그럼 위의 동작을 하는 코드를 좀 더 알아 보기 쉽게 작성해 보자.

두번째 예제

두번째 예제


두번째 예시는 상당히 코드 읽기가 쉬워졌다. 각각의 메소드에서는 단지 1개의 일만 하고 있고, 각 메소드에서 다른 메소드를 호출하는 일도 없다. 그러므로 코드의 시작 위치인 main에서 여러 depth의 메소드를 계속 추적할 필요 없이, 하나의 메소드를 읽고, 다시 제자리로 돌아와서 또 다른 메소드를 읽으면 된다. 메소드명이 명확하므로 main에서 메소드명만 읽고, 굳이 코드를 읽지 않아도 한번에 코드의 흐름을 이해할 수 있다.

두분째 예제를 마찬가지로 시퀀스 다이어그램과 비슷하게 그려서 보도록 하자.

수직적 코드 그림

수직적 코드


위의 그림에서 볼 수 있다시피, 두번째 예제의 그림은 main에서 어떠한 메소드를 호출했다가도, 곧바로 자신에게 돌아오게 되어 있고, 호출한 메소드에서 또 다른 메소드를 호출하지 않고 있으므로, 프로그램의 흐름이 아랫쪽으로 흘러가게 된다. 이러한 코드를 "수직적 코드"라고 하자.


두 예제를 비교해보니...

첫번째 예와 두번째 예에서 메소드 이름을 자세히 보았다면 다른점을 느꼈을 것이다. 첫번째 잘못된 예의 경우에는 하나의 메소드가 두가지 일을 하고 있다. 이렇게 되면 하나의 메소드에서 여러가지 일을 해야 해서 당연히 코드가 복잡해 질 수 밖에 없고, 나중에 코드를 변경하려고 해도 신경써야 할 일이 많아 질 수 있다.


그리고, 첫번째 예제에서 LoginUI를 여러개를 바꿔가면서 사용하고 싶다면 어떻게 해야 할까? 혹은 Login을 체크하는 알고리즘이 여러개라면 어떻게 처리해야 할까?

첫번째 예제에서는 하나의 메소드(loginAndSave)에서 LoginUI도 띄우고 login도 하고 save도 하므로, LoginUI만 교체한다거나, LoginChecker를 다른것으로 교체하는것이 까다롭다. 상속관계를 이용해서 오버라이딩을 하려고 해도, LoginUI만을 다른것으로 교체하기가 힘들다.

하지만 두번째 예제의 경우에는 하나의 메소드가 단 한가지만의 일을 하도록 되어 있다. 물론 코드를 키워나가는것도 더 쉽다. 두번째 예에서 새로운 모양의 LoginUI를 만들고 싶다면, createLoginUI 메소드를 protected로 바꾸고, VCoding을 상속 받아서 createLoginUI만을 오버라이딩 하면 된다. LoginChecker도 마찬가지다.


그리고 method가 한개의 일을 하도록 작성했으므로, 문제가 발생했을때 이 문제를 발생시키는 메소드 1개만 확인하면 버그의 처리도 쉬워 질 것이다. 물론, 유닛테스트도 훨씬 쉽게 수행할 수 있을 것으로 생각된다.


그래서...

이렇듯 수직적인 코드는, 코드 읽기를 쉽게 만들어 줄 뿐만 아니라, 코드를 점점 키워나가는데도 도움이 된다. 그러므로 프로그래밍을 할때 수직적인 코드를 항상 생각하도록 하자.

수직적인 코드 작성하기 수칙

1. 1개의 메소드에서는 1개의 일만 한다.
2. 메소드에서 또 다른 메소드를 호출하지 않도록 노력한다.

수직적인 코드짜기의 제 1수칙이 "1개의 메소드에서는 1개의 일만 한다"는 것인데,
실상 두번째 예제를 보면 아시다시피 main() 메소드에서 아주 많은 일을 하고 있다.

그렇다면 "1개의 메소드에서 1개의 일만 한다"는 것은 좀 말이 안되는것 아냐? 라고 물을 수 있다. 물론 말이 안된다. "프로그램의 어느 정도 깊이에서 코드를 쉽게 읽을 수 있도록 할까?"는 오롯이 프로그래머의 마음에 달렸다.

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
  1. 닉쑤 2010.09.10 06:31 신고

    우하하하하하

    역시 진작에 때려쳤어야 되는건데..

    아까운 내 4년.. ㅋ

    • 2010.09.10 10:18 신고

      ㅋㅋㅋ 그때 때려친걸 고마워해야지~ ㅎㅎ.

  2. 닉쑤 2010.09.10 12:29 신고

    아,그런거임? ㅋ

    도와줘서 감사.ㅋ

프로그래밍 도중에 이미지를 이용해서 작업을 하는 경우가 있다. 이때 이미지 변환중에서 가장 자주 사용되는 변환은, 이미지 크기 늘리기, 회전하기 등이 있겠지만, 이미지 자체를 변환 시키는 것으로는 GrayScale, 즉 회색화(?)시켜야 하는 경우가 있다.

우리는 프로그래밍할때 어떤색을 분리해 보라고 하면, 빛의 3원색으로 빨간색, 녹색, 파란색, 즉 RGB로 분리하게 된다. HTML에서 색을 표현할때도,  #FF9933(Red=0xFF, Green=0x99, Blue=0x33)등으로 표현하니깐 말이다. 그러므로 최소단위인, RGB를 이용해서 색의 변환을 수행해야 한다. 물론 GrayScale도 이 세가지 색깔을 이용해서 회색으로 만들어 줄 수 있다.


제일 간단한 방법

조금만 생각하면 누구나 떠 올릴 수 있는, 제일 간단한 방식으로는 Red, Green, Blue를 모두 더해서 그 평균값을 이용해서 회색을 만드는 방법이 있다.

gray = ( Red + Green + Blue ) / 3

RGB의 평균값으로 만들어낸 이미지

RGB의 평균값으로 만들어낸 이미지



요렇게 회색화된 이미지를 만들어 냈으니 끝.이라고 생각한다면 오산.


YUV 표현 방법

색의 표현방법은 우리가 일반적으로 사용하고, 알고 있는 RGB 세가지 색깔로 표현하는 방법 이외에 더 많은 방법이 존재한다. 그 중에 하나가 Yxx 색 표현 방법이다. 이때 Yxx는 여러종류가 있다. YPbPr, YCbCr, YIQ등이 있는데, 이것을 그냥 통칭해서 YUV라고 부르도록 하자.

RGB만 있으면 모든색을 표현할 수 있는데, 왜 YUV를 사용할까?

아주 오랜 옛날(?) 이야기가 되겠지만, 이전에는 흑백 텔레비젼을 사용했다. 흑백에서는 색깔이 중요한것이 아니라 오직 밝기만이 중요했다. 말 그대로 흑백이니깐 말이다. 그런데 흑백 텔레비젼만 계속 사용했으면 모르겠지만, 얼마 후 칼라텔레비젼에 나오고 나서 문제가 생겼다. 바로 색깔 정보를 전송해야 한다는것이다. 그러면 색깔 정보를 다 포함한 RGB를 모두 쏴 주면 될것 아닌가? 라고 생각하겠지만, 기존에 흑백 텔레비젼을 사용하던 사람들도 TV는 계속 잘 볼 수 있어야 할 것 아닌가?

그래서 기존에 흑백 TV들이 칼라 정보를 잘못 처리 하지 않도록 밝기 정보는 그대로 유지해야 하는 문제가 생겼다. 즉, 밝기 정보(Y)만을 따로 분리해서 전송하고, 색깔 정보(U,V)는 따로 보내는 방법을 사용하게 되었다. 그렇게해서 생겨난것이 YUV 이다.

그렇다면 YUV중 하나인 YCbCr 은 무슨 말일까?

YCbCr (ITU-R BT.709)

Y = 색의 밝기 정보 ( 기존 흑백 TV를 위한 정보 )
Cb = 색의 밝기 정보에서 파란색의 차이 ( blue-difference chroma compoents )
Cr = 색의 밝기 정보에서 빨간색의 차이 ( red-difference chroma compoents )

밝기정보, Cb, Cr 을 이용하면 실제로 보여주어야 하는 Color을 표현할 수 있다.
( 녹색은 밝기정보, blue, red 정보를 이용하여 계산해 낼 수 있으므로 굳이 전송하지 않는다. )

YPbPr이라는것도 있는데, YPrPb는 아날로그 시스템을 위한 표현방법이고, YCrCb는 디지털(CRT, LCDl, PDP등)을 위해서 따로 만들어둔 표현방법이다. 여기서는 디지털의 색표현방법인 YCrCb에 대해서만 이야기 하도록 하자.

이로써, 색을 표현할때에는 RGB를 이용한 색의 표현 방법 말고 YCrCb를 이용한 색의 표현방법이 있다는것을 알게 되었다. 색의 표현방법이 다르므로 이 표현방법을 이용해서 회색으로 만들어 주는 방법 역시 다르다.

우리가 회색으로 만들고자 하는 이미지는 RGB의 정보를 가지고 있고, 이를 YUV 값으로 변환하게 되면 이때 만들어진 Y 값은 자동적으로 밝기 정보를 가지게 된다. 이 Y 값인 밝기 정보만으로 gray scale 이미지를 만들 수 있다. 그렇다면 Y 값을 구하는 공식을 알아 보도록 하자.

YCrCb
Y = Red * 0.2126 + Geeen * 0.7152 + Blue * 0.0722

YPrPb
Y = Red * 0.299 + Green * 0.587  + Blue * 0.114

우리는 YCrCb만을 볼 것 이므로 각 R, G, B 정보를 이용해서 Y 를 추출해 내고, Y 밝기 값을 이용해서 이미지를 grayscale로 만들어 보면 아래와 같이 나온다. ( 위의 공식에서 RGB에 곱하는 값이 서로 다른 이유는 사람의 눈에 더 민감한 색에 더 많은 가중치를 주어서 계산하기 위해서 위와 같이 복잡한 식이 된다. )

RGB to YCrCb에서 Y값을 이용한 GrayScale Image

RGB to YCrCb에서 Y값을 이용한 GrayScale Image


그렇다면 RGB 평균을 내서 만들어낸 GraySacle이미지와 YCrCb를 이용해서 만들어낸 GrayScale이미지를 서로 비교해 보도록 하자. 나뭇잎 부분의 밝기를 비교해보면 서로 다른 명암을 가지는것을 알 수 있을 것이다.
RGB평균과 YCrCb에서 Y를 이용한 이미지 비교

RGB평균과 YCrCb에서 Y를 이용한 이미지 비교


위와 같이 YCrCb에서 Y 값인 밝기를 이용해서 GrayScale이미지를 만들어 낼 수 있었다.


다른 방법은 없을까?

그렇다면 색을 표현하는 방법은 RGB와 YCrCb밖일까? 당근 그렇지 않다. 그 중에서도 밝기를 따로 나타내고 있는 색 표현방법에는 HSL이나 HSV(혹은 HSB), HSI가 있다.

HSL = Hue, Saturation, Lighness
HSV = Hue, Saturation, Value ( 혹은 HSB = Hue, Saturation, Brightness )
HSI = Hue, Saturation, Intensity

각 마지막에 있는 L, B, V, I 는 모두 밝기 정보를 나타낸다.
이때 RGB를 HSL, HSV(HSB), HSI 로 바꾸는 공식은 모두 다른데, 이때 각 표현 방법중에서 밝기를 계산하는 공식은 다음과 같다.

L = ( Max(R,G,B)  + MIN(R,G,B) ) / 2
V(B) = Max(R, G, B)
I = ( R + G + B ) / 3  (우리가 일반적으로 생각하는 공식)

위에서 보다시피 HSx 방식을 이용하기만 해도 여러가지 공식으로 밝기 값을 처리 할 수 있다.



결론

GrayScale이미지를 만들어 낼때는 별로 생각없이 만들어 내는것이 일반적이다. 혹은 누가 이미 만들어 놓은 그래픽 라이브러리를 잘 가져다가 쓰고, "아~ 뭐 잘 나왔겠지."라고 생각하는것이 일반적이다. GrayScale 이미지를 하나 만들어 낼려고 해도 생각할것이 아주 많다는것을 알 수 있다. 위와 같은 정보를 알지 못하고 그냥 생각없이 만들어진 라이브러리를 가져다 쓰게 되면 내가 원하지 않던 결과를 낼 수도 있기 때문에 잘 생각하고 쓰도록 하자.

당장 급하다면 그냥 가져다 쓴다고 해도, 어느정도 시간이 느긋하다면 "어떻게해서 이렇게 나오는 것일까?"에 대해서 생각해 보는것이 어떨까?


자바에서의 Gray Scale

자바에서도 GrayScale이미지를 만들어 낼 수 있는 방법이 여러가지가 있다. 하지만 내가 원하는 결과를 내기 위해서는 공부가 좀 필요하리라 본다. 자바에서 이미지를 Gray scale로 만드는 방법을 보고 싶다면 아래의 이미지와 소스를 받아서 직접 실행해 보도록 하자.

자바에서 각종 GrayScale 방법

Java의 각종 GrayScale 방법



테스트용 이미지

테스트용 이미지





참고자료

아래의 자료를 참고하면 정리하는데 도움이 될 것이다.
HSL, HSV : http://en.wikipedia.org/wiki/HSL_and_HSV
YCrCb : http://en.wikipedia.org/wiki/YCbCr
RGB, YUV에 대한 설명 : http://cafe.naver.com/camuser/234 - 원본 문서를 못 찾겠음 T_T

==
옛날에 대충 적어 두었던 글을 살짝 정리해서 올림.
적을 글은 많은데.. 언제 다... ;;
저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
  1. 닉쑤 2010.08.02 07:50 신고

    오우 어려워 어려워~
    ㅡㅡ;

    역시 나는 프로그래머는 못되는거임? ㅋ

    • 2010.08.02 08:44 신고

      뭔... 그런걸 가지고... 그냥 하는거지... 궁금하니깐 찾아 보는거고...
      대신 영어 잘하잖아~ ㅎㅎ

  2. 닉쑤 2010.08.02 09:17 신고

    궁금하지 않아요. ㅋㅋ

    과연... 잘 할까요?

    서바이벌 잉글리쉬라는게 있음.. ㅋ

    • 2010.08.02 17:54 신고

      난 서바이벌하지 못할것 같아. ㅎㅎ.

  3. 如旻 2010.08.03 09:59 신고

    아- 저 사진!!
    우.. 오랜만이다.
    너의 역작!
    ㅋㅋㅋㅋㅋㅋㅋㅋ

    • 2010.08.03 10:14 신고

      풉.
      한때 똑딱이로도 저정도는 그냥 찍었는데..

      사진 안 찍은지 몇년. T_T

  4. 학부생 2012.02.07 17:15 신고

    감사합니다 좋은글 잘읽었습니다

  5. 컴퓨터공학도 2012.07.24 22:42 신고

    어휴..학술제 때 어플리케이션을 제작하는데, 영상처리가 필요해서 찾다가
    좋은 글을 보고 가네요 ㅎ
    너무 감사합니다!

    • 2012.07.26 17:04 신고

      영상처리까지야.
      그냥 알고 있는거 정리해서 적은건데요. ㅎㅎ

      방문 감사합니다.

  6. pica 2014.01.14 23:16 신고

    많은 도움이 되었습니다.
    궁금했던 부분이 많이 해결되었네요.
    감사합니다.

  7. 어벙이 2015.08.17 12:46 신고

    퍼갈게요.. 좋은글 보고 갑니다. `^^

이번에 책을 무려 3권이나 구입했는데, 그 중에 하나.

  테스트 주도 개발  켄트 벡 지음, 김창준 외 옮김
최근 학계와 업계에서 많은 주목을 받고 있는 프로그래밍 방법인 '테스트 주도 개발(Test-Driven Development)'에 대해 설명한 책이다. 테스트 주도 개발을 퍼뜨린 장본인이며 객체 지향 프로그래밍의 선구자 중 한 사람인 켄트 벡이 직접 서술했고, 부록에는 TDD 시연 동영상을 수록했다.



지금은 겨우 서문을 다 읽고 1부의 1장을 아주 조금 읽었다.
실제 내용은 겨우 5-6페이지 읽었을 뿐이다.

책의 앞에는 옮긴이의 서문과, 옮긴이가 쓴 TDD 수련법, 옮긴이와 글쓴이의 인터뷰내용이 들어 있다.
이 내용은 테스트주도개발을 처음 접하는 독자들에게는 그렇게 크게 느낄만한 내용이 없다.

처음 읽는 사람은테스트 주도 개발이 뭔지도, 왜 필요한지도 모르기 때문이다.


저자의 글에서 몇가지 정리하면..

. 매 결정사항에 대해 피드백을 제공하는 실행 가능한 코드를 기반으로 하는 유기적인 설계를 해야 한다.
. 테스트를 쉽게 만들려면 반드시 응집도는 높고 결합도는 낮은 컴포넌트들로 구성되게끔 설계해야 한다.

| 용기 |
두려움이란 나쁜 의미의 - 무서워요. 프로그래머는 젖꼭지가 필요해요 - 두려움을 뜻하는 것이 아니고, "정말 어려운 문제라서 시작 단계인 지금은 어떻게 마무리될지 알 수 없군" 하고 생각하는 식의 합리적인 두려움을 말한다.

. 두려움은 여러분을 망설이게 만든다.
. 두려움은 여러분이 커뮤니케이션을 덜 하게 만든다.
. 두려움은 여러분이 피드백 받는 것을 피하도록 만든다.

프로그래밍 문제가 어려울수록 각각의 테스트는 좀 더 작은 부분을 커버해야 한다.

순수하게 TDD로만 풀어낼 수는 없는 프로그래밍 작업이 분명히 있을 것이다( 혹은 최소한 아직까지는). 예를들면 보안 소프트웨어와 동시성(concurrency)은, TDD로 해당 소프트웨어의 목표가 달성되었다는것을 기계적으로 보여주기에 부족한 두 가지 주제라고 할 수 있다.

설계는 반드시 잘 되어야 한다. 그렇게 해야만 Test를 이용해서 개발하기가 쉬워진다. 즉, 테스트가 설계를 잘 하도록 도와주지는 않는다. 그렇기 때문에
설계가 우선 되어야 한다.



들어가는 글에서..
"... 하지만 미합중국 달러로 명명된 채권만 다루더군요. 저는 새로운 채권 펀드를 시작하려고 하는데 제 전략상 다른 화폐로 채권을 다룰 필요가 있습니다." 라고 했다. 보스가 워드를 돌아보며 말했다. "저기, 우리가 그걸 할 수 있을까요?"
이것이 바로 어떤 소프트웨어 개발자에게든 악몽이 될만한 시나리오다. 당신의 몇가지 가정하에 성공적이고 행복하게 순항하고 있었는데 별안간 모든것이 바뀌었다.

.....

그날 하루가 끝나갈 즈음에는 테스트가 전부 통과했다. 워드는 코드를 빌드에 체크인하고 보스를 찾아갔다. "할 수 있습니다.", 그는 확신에 차서 말했다.

이 이야기에 대해 조금만 생각해보자. 이틀 만에 잠재적 시장이 몇 곱절이나 커졌고 덕분에 와이캐시의 가치 역시 몇 배 늘어났다. 하지만 그렇게 빨리 그토록 많은 비즈니스 가치를 만들어내는 능력은 우연이 아니었다.


저기에서는 저기 빨간 말이 진짜 마음에 와 닿는다.

당신의 몇가지 가정하에 성공적이고 행복하게 순항하고 있었는데 별안간 모든것이 바뀌었다.

대충 요렇다~


딱 요만큼만 보고, 충분히 -_- 필요하다고 공감했다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

어쩌다가.. Windows API 프로그래밍을 해야 할 일이 생겼다.
물론. 그냥 재미 삼아 하는거지만 ㅎㅎ

off screen DC 에 그려지는 픽셀 데이터를 빼 와서
JNI을 통해서 Java 쪽에 넘겨 주어야 하는 일이 발생했다.


이것저것 하다가. 분명히 색깔은 가지고 오는데,
비율이 안 맞는것이다. ㅠ_ㅠ

ㅎㅎㅎㅎ 알고 봤더니 -_- width와 height 인자를 반대로 주고 있었다는.. ㅋㅋㅋㅋ

이제 그 부분을 고친 뒤에, 수행을 해 봤는데. 이거 너무나 느린것이다.


1. Java 에서 int[]을 만들어서 C 를 호출한다.
2. C 에서는 DC에 그림을 그린다.
3. C 에서 DC에 그려진 그림의 각 픽셀을 int[] 에 저장한다.
4. Java 측으로 돌아와서 int[] 을 정보를 가지고 1pixel씩 그림을 그려준다.

900 * 900 에 대해서 위의 작업을 해 주는데, 무려 2.2초씩이나 걸리는것이다.

처음에는 900 * 900 의 픽셀들에 일일이 값을 셋팅하고,
자바에서 다시 그림을 그려주는 작업이 시간이 많이 걸릴거라 생각하고,
더 이상 퍼포먼스를 높일 수 없겠군아~ 라고 생각을 했으나..
확인 결과 이게 왠일 -_-;;


C 측의 GetPixel 에서 시간이 2초 정도 걸리는것이다. -_-;;;;;

혹시나 DC 가 아니고 BitMap 에 그려진 정보를 바로 볼 수는 없을까? 라는 생각에
msdn을 열나 뒤져 봤지만, 윈도우 개발자가 아닌지라 -_-;;;
구글을 열나 뒤져 봤지만, 윈도우 개발자가 아닌지라 -_-;;;


결국 소멤(삼성소프트웨어멤버쉽)에 댕기는 친구에게,
"이러이러 하니 어쩌면 좋겠느냐~" 했더니 -_-
단 20초만에 -_-;; 사이트를 불러주는 자식 -_-; 그것도 한국어 사이트로 -_-;;

구글에서 -_- GetPixel 로 검색해 봤단다 -_-;;



물론 나도 해 봤다. GetPixel , GetPixel slow, DC GetPixel 등등으로..
( 난 영문으로 -_-;;;;; )


한국에도 좋은 자료가 많이 있군아~ 라는 생각을 깊이 했다. -_-;;;



암튼 GetPixel 에 대해서 좀 알아 보자.

COLORREF GetPixel(
  HDC hdc,    // handle to DC
  int nXPos,  // x-coordinate of pixel
  int nYPos   // y-coordinate of pixel
);

너무나도 단순한 함수이다.
해당 DC의 x, y 위치에 있는 픽셀을 COLORREF ( DWORD - 즉 unsigned int ( 32 bit ) ) 로
반환 해 주는 함수 이다.

하지만 이 놈이 느린 이유가 있다.

1. DC 에 선택되어 있는 비트맵 구조를 알아 온다.
2. 해당 비트맵 버퍼를 알아 온다.
3. 비트맵 버퍼를 파싱하여 x, y 위치에 있는 Pixel 정보를 얻오온다.

http://www.gosu.net/GosuWeb/Article-detail.aspx?ArticleCode=185
( 안타깝게도 고수 닷넷은 가입을 하고 로그인 해야만 문서를 볼 수 있다. )

위의 과정 중에서 하나의 이미지에 대해서 작업할 경우
1, 2, 그리고 3번의 일부분은 최초 단 한번만 수행하고,
이미 구해진 정보를 활용하도록하면 초 스피드로 처리할 수 있다는 게 핵심이다.


해당 링크에 가 보면 class 형태로 만들어져 있는 코드가 있고,
그것을 그대로 활용하기만 하면 문제 없이 사용할 수 있다.

하지만!!!
사용하는 Type 들이 CDC 를 사용한다던지 -_-;
CBitmap 를 사용한더던지 하는 -_-; 정말로 -_- 재미 없는
MFC 코드를 쓰고 있다는것이.. 걸림돌이었다. -_-;;


그래서 -_- 그냥 static 컴파일 해 버릴려고 막 마음을 가질 무렵 -_-;
아까 도움을 주었던 친구가 CDC와 CBitmap을 쓰던 놈을 -_-
Windows API만 가지고 사용할 수 있도록 -_-
HDC등으로 변경해 주었다. ㅋㅋㅋ
( 결국 -_- 내가 한일은 거의 없다는 거다. ㅎㅎ )

위의 링크에서 제공되는 것도 문제가 좀 있기는 하다.
16컬러 이하의 이미지 일때 처리가 되지 않는 등의 문제가 있다고는 한다.
( 맞는지는 모르겠는데 DC에 적용된 Bitmap이 16컬러 이하인 경우를 이야기 하는것 같다. )
( 하지만 요즘에 16컬러 이하를 쓰는 사람은 없다고 보는게 옳을듯 하다 -_-; )




결론 1.
GetPixel 이 너무 느려서 못 써 먹을때에는 위의 링크를 이용하도록 하자.

결론 2.
900 * 900 이미지에 대해 개선전 2.2초대가 걸리던 것이 -_- 개선 후 0.2초대가 걸린다 -_-;


현재 Java 측 코드가 무식하게 -_-
BufferedImage를 만든뒤에 거기의 Graphics에 -_-
1 pixel 씩 drawline 하고 있다. -_-;;
이것도 개선해야 하는데 -_- 개선할 여지가 안 보인다. -_-;;;


암튼
주말에 몸이 안 좋아서 계속 쉬었는데.. 그래도 마냥 논것 같지 않아서. 다행이다 싶다. ㅎㅎ

신고
크리에이티브 커먼즈 라이선스
Creative Commons License
  1. 유겸애비 2006.12.11 06:49 신고

    축하해요. 내가 맛난거 사주지요

    • Chan 2006.12.11 09:57 신고

      하하 ;; 아직까지 문제가 있긴있다는 ;; ㅎㅎ;;
      투명도 처리가 ;; ㅎㅎ ;;

  2. 옷장수 2006.12.11 09:17 신고

    그렇게, 피곤해서 이사나 제대로 하겠소? ㅋㅋ

    • Chan 2006.12.11 09:57 신고

      짐은 옷, 이불, 놋북이 끝인지라. ㅎㅎ;;

  3. SnowBoy 2006.12.11 10:03 신고

    저는 16bit이하로 쓰는 경우가 자주 있어요 흐흐,,윈도우즈 터미널 서비스 클라이언트로 붙으면 대략 난감.. ^^;;;;

    • Chan 2006.12.11 10:19 신고

      ㅋㅋㅋㅋ 16컬러 입니다. ㅋㅋㅋㅋ
      비트로 따지면 4bit?? ㅋㅋㅋㅋ

  4. 타오 2006.12.11 16:10 신고

    조만간 win32 jni 작업을 해야할지도 모르는데 잘됐삼! 헬프미!

    • Chan 2006.12.12 00:42 신고

      ㅋㅋ 실력 좋으면서 무슨 부탁을.. ㅎㅎ
      저도 -_- 복사해서 붙여넣는 수준이라. ㅋㅋ

  5. 16비트는 계산을... 2010.10.30 04:51 신고

    16비트 컬러의 경우(16색상 말고)는 저 코드 써봣는데
    잘못된 값을 얻어오더군요...
    코드작성자분이 뭔가 계산을 잘못한듯.

    • Chan 2010.10.31 23:28 신고

      오우~ 글 감사합니다.
      최근에도 이 글이 검색어로 많이 노출이 되는데.
      좋은 정보가 되었네요 ^^

      감사합니다.

  6. ;;;; 2011.07.17 13:09 신고

    저.. 혹시 그.. API로 된 소스코드좀 주실수 있으신가요;;
    C++ Class는 배워본적이 없는지라 전혀 이해가 안갈뿐더러
    CDC에서 막혀서 이틀째이러고있는데;;
    다른곳을 아무리 검색해봐도 나오는건 전부 Class를 쓰거나 CDC를쓰더군요;;

    그래서 한번

    MyBit=CreateCompatibleBitmap(desktop,1,1);
    OldBit=(HBITMAP)SelectObject(mdesktop,MyBit);

    BitBlt(mdesktop,0,0,1,1,desktop,x,y,SRCCOPY);//고속복사
    GetBitmapBits(MyBit,data_size,&pattern);//비트맵 얻어옴
    이런식으로 만들어봤는데;;; 속도가;;
    그리고 활성화된 게임같은창같은곳에 가져가면 0xffffff만 나오는;;;;

    어떡해 못보내주시나요?
    vain430@naver.com으로..

+ Recent posts