삽질2009.09.30 09:41

JSON 라이브러리중 json-simple를 사용했습니다.

다음 도서 검색 OpenAPI를 사용하는 예입니다.
URL url = new URL("http://apis.daum.net/search/book?q=Java&apikey=OEPNAPI_KEY&searchType=title&output=json&result=5pageno=1");
// 한글 처리를 위해 InputStreamReader를 UTF-8 인코딩으로 감싼다.
InputStreamReader isr = new InputStreamReader(url.openConnection().getInputStream(), "UTF-8");

// JSON을 Parsing 한다. 문법오류가 날 경우 Exception 발생, without Exception -> parse 메소드
JSONObject object = (JSONObject)JSONValue.parseWithException(isr);
// 객체
JSONObject channel = (JSONObject)(object.get("channel"));
// item 배열
JSONArray items = (JSONArray)channel.get("item");

for(int i = 0 ; i < items.size(); i++) {
	JSONObject obj1 = (JSONObject)items.get(i);			
	System.out.println(obj1.get("title").toString());
}
json-simple 은 그 이름 자체로 간단하게 json을 사용할 수 있었습니다. 한글 처리 때문에 삽질을 좀 하긴 했지만.....
Posted by 꿍스
생각2009.08.17 23:43
오늘 2009년 매쉬업 경진대회에 출전했던 도서나눔 사이트 ggats.com을 유지보수 하던 중 도서검색 결과가 DB에 저장될때 오류가 발생하여 오류를 찾다보니 네이버 도서검색 API(http://dev.naver.com/openapi/apis/data/book)의 아웃풋이 바뀐 걸 알았습니다.

이전에는 bid(네이버 도서에서의 책ID 즉 book.naver.com 의 키 인듯 합니다.) 를 노출하여 예를 들어 '소설 손자병법'의 예전 link 아웃풋은 http://book.naver.com/bookdb/book_detail.php?bid=117701 였지만, 어느세

http://openapi.naver.com/l?AAAC3MSw6DIBgE4NP8LIk8LLJgoVav0UihgfQBJWji7VVCMosvk8zkPVqlQ3ij1RvFRUsZ+q827QqmEbobdGMBh57XRjYX5FQwwMBAkgIKskUu2ZdyOUdgPdD5zPWOf8tmE36Gby2MrngYmxf/wdGdi1l7A+xOiBANOQBWP/V3mwAAAA==

라는 얄궃은 값을 보내주어 bid 값을 유추할 수 없도록 만들었습니다.

유저들보고 OpenAPI를 적극적으로 사용하여 어플리케이션을 개발하라고 유도했지만 어느새 어떠한 통보도 없이 OpenAPI의 아웃풋을 변경했습니다. 아무래도 bid값을 link 아웃풋에 노출시키는 것이 부담이 되었던 것 같습니다.

최근 네이버 데스크톱 단순 통보로 서비스를 중단하는 것을 보며 '네이버' 같은 기업의 Open Platform이 성숙하기에는 아직 시간이 걸릴것 같다고 느꼈습니다.
Posted by 꿍스
삽질2009.08.07 15:29

AJAX 비동기 처리를 위한 IXMLHTTPRequest, COM 인터페이스의 하나이기 때문에 웹 브라우저 안에서 뿐 아니라 윈도우즈어플리케이션으로도 구현이 가능합니다.

더욱이 IXMLHTTPRequest는 Windows CE기반의 Windows Mobile에서도 구현이 되어있을 뿐 아니라, IXMLDOMDocument와 같은 XML DOM 인터페이스와도 바로 연결이 가능하므로 윈도우즈 어플리케이션에서 복잡한 Socket처리나, WinInet라이브러리를 별도로 사용하지 않아도 쉽게 웹의 OpenAPI를 사용할 수 있습니다. ( 내부적으로는 WinInet, Socket을 사용합니다. )

http://msdn.microsoft.com/en-us/library/aa924919.aspx : IXMLHTTPRequest 인터페이스 설명

웹의 AJAX와 같이 동기, 비동기 방식을 모두사용 가능할 뿐만아니라 모든 메소드를 제공하고 IStream 방식으로 받아 아래의 포스팅과 같이 파일로 저장할 수도있습니다.

CComQIPtr pDispatch;
CComPtr pXMLHTTP;
CComPtr pXMLDoc;
		
const CComVariant VAL_NULL = NULL;
const CComVariant VAL_FALSE = FALSE;
long length_posts = 0;
CComBSTR bstr;
HRESULT hr;
		
pXMLHTTP.CoCreateInstance(CLSID_XMLHTTP);
		
pXMLHTTP->open(CComBSTR("GET"), CComBSTR("http://me2day.net/api/get_posts/ggungs"), VAL_FALSE , VAL_NULL , VAL_NULL);
hr = pXMLHTTP->send(VAL_NULL);
if(hr != S_OK) {
	//MessageBox(L"전송실패");
	return;
}
			
hr = pXMLHTTP->get_responseXML(&pDispatch);
if(hr == E_PENDING) {
	//MessageBox(L"PENDING");
	return;
}
		
pDispatch->QueryInterface(IID_IXMLDOMDocument, (void **)&pXMLDoc);
pDispatch.Release();

if(pNodeList) { pNodeList.Release(); }
pXMLDoc->selectNodes(L"/posts/post", &pNodeList);
pNodeList->get_length(&length_posts);
		
 ..... // XML 처리
		
pXMLDoc.Release();
pXMLHTTP.Release();

 

위의 예는 동기 방식으로 미투데이 OpenAPI에 접속하여 XML 데이터를 가져와서 XML 파싱하는 예입니다.

물론 AJAX의 꽃인 비동기 처리로 onreadystatechange에 자바스크립트처럼 함수가 호출되도록 할 수 있지만 VC++ 에서는 좀 복잡하게 처리해야 할듯 합니다.
(http://www.ookii.org/post/using_ixmlhttprequestonreadystatechange_from_c.aspx 참고)

IXMLHTTPRequest 인터페이스를 잘 사용하면 HTTP 프로토콜 로직 처리를 안해도 되기 때문에 빠르게 개발가능합니다.

Posted by 꿍스
삽질2009.08.04 00:24

SHCreateStreamOnFile 함수로 지정된 파일에 대한 IStream 인터페이스를 얻은 다음 CopyTo 메소드로 스트림을 복사합니다. (http://msdn.microsoft.com/en-us/library/bb759864(VS.85).aspx)

	pStreamSrc = ........

	STATSTG StatInfo;
	CComPtr pStreamDest;
	hr = SHCreateStreamOnFile(L"C:\\profile.png", STGM_WRITE | STGM_CREATE, &pStreamDest) ;
	pStream->Stat(&StatInfo, STATFLAG_NONAME );
	pStream->CopyTo(pStreamDest, StatInfo.cbSize, NULL, NULL);
	pStreamDest->Commit(0);

Windows Mobile 에서는 SHCreateStreamOnFile 함수가 없어서 직접 구현해야 합니다.

http://www.pocketpcdn.com/articles/articles.php?&atb.set(a_id)=6211&atb.set(c_id)=57&atb.perform(details)

참고해주세요.

Posted by 꿍스
생각2009.07.31 17:43

소셜네트워크서비스(SNS) 서비스가 주목을 받고있습니다. 하지만 SNS가 서비스 됨에 따라 인맥 네트워크간 부익부 빈익빈 현상이 발생합니다. 이 현상은 바바라시 교수의 링크에 언급된 네트워크의 법칙으로 네트워크 노드간의 링크는 네트워크는 점점 노드가 생겨남에 따가 연결수가 많은 링크를 선택하게 된다는 법칙입니다. 이 현상이 SNS에서도 발생합니다. 트위터를 예로들면 유명인사들의 트위터의 Follower들은 수많은데 비하여 알려지지않는 트위터는 Follower가 0인 경우가 많습니다. 그런데도 유명인사들의 트위터들은 끊임없이 Follower들이 많아집니다. 

SNS가 성장하기 위해서는 불균형을 해소를 위해 노력해야 하는 과제를 안고있습니다. 주목을 받지못하고 도대되어 버리면 무형의 링크가 아닌 사람은 떠나버리거나 소흘하게 됩니다. SNS는 활동하는 실제 트래픽이 중요합니다. 그것이 곧 SNS의 경쟁력이기 때문입니다.

이런 불균형을 해소하기 위한 방법으로 친구를 매칭시켜주는 시스템들이 있지만 소셜게임도 그 방법 중의 하나라고 생각합니다. 기존의 한정된 구역이 아닌 전혀 다른 구역으로 링크를 확장할 수 있어 유명인사들에게 집중된 링크의 불균형을 해소할 수 있다고 생각합니다.  


< 출처 : 고슴도치플러스 팀블로그 >

그림은 FaceBook에서 서비스 되고있는 고슴도치플러스의 Catch Me If You Can 입니다. 처음 게임을 하면서 누구랑 하는지도몰랐지만 게임 후 기록으로 지구 반대편의 사람과 같이 게임을 한것임을 알 수 있었습니다.

하지만 이러한 게임이 지속적으로 친목을 기를 수 있는 기능을 해야 앞에서 말한 네트워크의 불균형을 해소할 수 있을 것입니다. 한번게임을 하고 마는 일시적인 친목은 네트워크가 가진 불균형을 해소하지 못할 것입니다. SNS 기반에서 동작하는 소셜게임이 갖추어야할 중요한 점은 바로 게임을 통한 친목이 지속적으로 있도록 해야 한다는 점이라고 생각합니다.

PS) 사실 이 내용은 제가 소셜게임 지원부분에서 면접시에 말하고자 하는내용이었는데 면접에서 아쉽게 말할 기회를 찾지 못했습니다. 미숙하게나마 제 머리속의 생각들을 정리해서 써봅니다.

트위터를 100명의 마을이라고 하면 5명만 떠들고 논다고 합니다. (http://podcast.co.kr/2512405)
Posted by 꿍스
생각2009.07.21 23:59

<html>
  <head>
    <title>Canvas demo</title>
    <script type="text/javascript">
      function draw () {
        var canvas = document.getElementById ('hello');
        if (canvas.getContext) {
          var ctx = canvas.getContext('2d');
          ctx.fillRect (25, 25, 50, 50);
        }
      }
    </script>

    <style type="text/css">
      canvas { border: 2px solid red; }
    </style>
  </head>

  <body onload="draw ();">
    <canvas id="hello" width="100" height="100"></canvas>
  </body>

</html>

HTML5의 Canvas 요소는 그래픽을 표현할 수 있는 요소입니다. 차후 Flash나 실버라이트를 부분적으로 대채할 수 있을 정도로 뛰어난 기능을 나타내는 것 같습니다.

JQuery로 유명한 존 레식이 참여하고 있는 Processing.js 보면 Javascript로 Canvas 요소를 쉽게 사용할 수 있습니다.

http://processingjs.org/

다만 아직 IE에서는 canvas 요소를 지원하지 않습니다. http://excanvas.sourceforge.net/ 를 이용해서 따로 별도의 자바스크립트를 추가해야 합니다.

http://hascanvas.com 에 가면 HTML의 Canvas 를 활용한 다양한 예제를 볼 수 있습니다.



Posted by 꿍스
삽질2009.07.11 23:39

처음 Windows Mobile에서 Common Dialog Box 를 사용하시는 분들이라면 메세지 처리를 한번 보셔야 할 것 같습니다.

당연히 일어나야 할 것 같은 메세지가 일어나지 않는다면 의심해 보세요. 현재 Windows Mobile 에서는 2개의 Common Dialog Box 메세지 만을 제공합니다.

CDM_SETDEFEXT

This message sets the default filename extension for an Explorer-style Open or Save As common dialog box.

CDN_TYPECHANGE

This message is sent by an Explorer-style Open or Save As common dialog box when the user selects a new file type from the file types combo box.


위에는 메세지고 밑에껏은 Notify 메세지 입니다. 둘 다 File Dialog Box에서 쓰이는 군요.

http://msdn.microsoft.com/en-us/library/aa931534.aspx

저는 당연히 Dialog Box 가 초기화 되면 Notify Message가 발생할 줄 알고 잘못된 점이 제 코드 인줄 알고 WTL 소스를 뒤지기 시작하는 가 하면 ( WTL은 Overriding 으로 편하게 File Dialog Message를 처리할 수 있습니다. ) Remote Spy++ 까지 써가면서 관찰했는데 메세지 자체가 안일어 나는 것 같아서 찾아보니 이렇네요.

Posted by 꿍스
삽질2009.06.15 23:03

하루종일 삽질 삽질을 거듭하여 샘플정도로 간단하게 만들어 봤습니다.

CComPtr m_pImgFactory;
CComPtr image;
m_pImgFactory->CreateImageFromFile(filename, &image);

CComQIPtr pBitmap;
CComPtr pBitmapOps;

// 불러온 Iimage로 IBitmapImage 생성
m_pImgFactory->CreateBitmapFromImage(image, 0, 0, PixelFormatDontCare, InterpolationHintNearestNeighbor, &pBitmap);
pBitmap->QueryInterface(IID_IBasicBitmapOps, (void**)&pBitmapOps);
pBitmap.Release();

// 이미지 90도 회전
pBitmapOps->Rotate(90, InterpolationHintNearestNeighbor, &pBitmap);
image.Release();
pBitmapOps.Release();

pBitmap->QueryInterface(IID_IImage, (void**)&image);
		
// 인코딩 코덱 찾기
ImageCodecInfo * codecinfo;
UINT count;
CLSID clsid;
m_pImgFactory->GetInstalledEncoders(&count, &codecinfo);

for(UINT i = 0; i < count ; i++) {
	// JPEG 코덱 찾기
	if(wcscmp(codecinfo[i].MimeType, _T("image/jpeg")) == 0) {
		clsid = codecinfo[i].Clsid;
				
		break;
	}
}
free(codecinfo);

// 인코딩할 파일 저장
CComPtr pEncoder;
m_pImgFactory->CreateImageEncoderToFile(&clsid, _T("파일명"), &pEncoder);

// 인코딩할 이미지 싱크 생성
CComPtr pImgSink;
pEncoder->GetEncodeSink(&pImgSink);
// 기존의 이미지를 이미지 싱크로 보냄
image->PushIntoSink(pImgSink); 
pImgSink.Release();
// 인코딩 종료
pEncoder->TerminateEncoder();
pEncoder.Release();

 

회전 한 파일이 파일명으로 바로 저장됩니다.

Posted by 꿍스
삽질2009.06.14 20:06
WindowsMobile 에서만 쓸수있는 SHLoadImageFile 이라는 함수가 있습니다. 이 함수는 편리하게 파일 이름만 넣으면 PNG, JPG, GIF등을 지원해서 편리하게 HBITMAP 형식으로 리턴해 줍니다. 하지만 파일 전체를 무조건 로드합니다.

http://msdn.microsoft.com/en-us/library/aa455003.aspx

윈도우즈 모바일 5 부터 사용할 수 있다고 하지만 그 전에도 undocumented function 으로 사용가능 했던 것 같습니다.(구글신 검색결과)


		// 사진 파일을 지정
		HBITMAP h = ::SHLoadImageFile(filename);
		if(h != NULL) {
			m_photoImage.Attach(h);
		}
		else {
			MessageBox(_T("사진 파일을 불러오지 못했습니다."), _T("Me2PocketUploader"), MB_ICONWARNING);
		}

용량이 큰(실험 결과 1Mbyte 정도) 이상의 파일을 SHLoadImageFile로 로드하면 무조건 NULL이 리턴되었습니다. 

GetLastError로 조사해도 핸들이 잘못되었다는 메시지만 출력합니다. 어리 둥절했던 것은 에뮬레이터에서는 불러오다가 못불러오다가 했습니다. 생각해보니 메모리 용량 때문인거 같습니다. JPG파일 200kb 정도라도 실제 BITMAP으로 디코딩 될때의 메모리 점유는 3Mbyte에 육박 했습니다. 그래서 구글신께 여쭈어서 찾고 찾은것이 Windows CE의 Image API 입니다.

IImagingFactory의 CreateImageFromFile http://msdn.microsoft.com/en-us/library/aa452215.aspx , 로 얻은 IImage 인터페이스의 GetThumbnail함수로 썸네일을 바로 가져왔습니다. 큰 이미지 파일이라도 썸네일로 크기에 맞가 가져오므로 부담이 적습니다. 그래서 메모리 사용량도 상당히 줄었습니다.

저는 WTL을 사용해서 프로그래밍 했기 때문에ATL의 편리한 CComPtr이나 CComQIPtr등 COM이용에 편리한 클래스를 사용 했습니다.

#include 
#include 
#include 

CComPtr m_pImgFactory;
CComPtr m_pImage;
RECT m_photoRect;

// ImageFactory 생성
m_pImgFactory.CoCreateInstance(CLSID_ImagingFactory);

CComPtr image;
m_pImgFactory->CreateImageFromFile(filename, &image);

// 썸네일 생성	
if(image->GetThumbnail(m_photoRect.right - m_photoRect.left, m_photoRect.bottom - m_photoRect.top, &m_pImage) == S_OK) {
	m_photoFilename = filename;
	InvalidateRect(NULL); // OnPaint
}

// 지정된 DC와 영역에 그림을 그림
::GetWindowRect(GetDlgItem(IDC_PHOTO), &m_photoRect);
m_pImage->Draw(hDC, &m_photoRect, NULL);


Image API의 IBasicBitmapOps인터페이스(http://msdn.microsoft.com/en-us/library/ms939536.aspx)를 사용하면


Grouping Methods
Color Control AdjustBrightness

AdjustContrast

AdjustGamma

Manipulation Clone

Flip

Resize

Rotate


이런 것들을 할 수 있네요. 나중에 해봐야 겠습니다. +_+
Posted by 꿍스
삽질2009.06.08 20:37

Me2PocketUploader 윈도우즈 모바일 버전을 개발하면서 마블(이전은 인텔)의 PXA시리즈 CPU에서는 잘 동작하는 기능이 퀄컴의 MSM시리즈(MSM7200)칩에서는 의도하지 않은 동작을 하였습니다. 어차피 둘다 태생은 ARM 아키텍처 이지만 말입니다. 그것도 무적전설님이 알려주기 전까지는 몰랐습니다.
문제의 코드는 다음과 같습니다.
		// 댓글 닫기
		if(setCloseComment) {
			m_HTTP->AddGetData("close_comment", "true");
		}

 

setCloseCommnet 값이 BOOL값이라 BOOL값은 또 int로 정의되어 있기에 저렇게 작성했었는데, 퀄컴의 MSM CPU에서는 계속 댓글이 닫히는 문제가 생기는 것입니다. setCloseCommnet값이 FALSE라도 실행이 되어버렸던 것이지요. 전 이문제를 단순히 CPU의 아키텍처가 틀려서 라고 생각을 하고 있다가, 다음과 같이 명확하게 TRUE값을 검사했습니다.

		// 댓글 닫기
		if(setCloseComment == TRUE) {
			m_HTTP->AddGetData("close_comment", "true");
		}

 

잘 되는군요... 문제는 역시 저의 코딩 버릇이었습니다. 좀더 명확한 코드를 작성하도록 노력해야겠습니다.!! 테스트 해주신 무적전설님 감사합니다.

Posted by 꿍스
TAG C, IF, msm7200, PXA, WM