본문 바로가기

삽질

[WM] SHLoadImageFile 문제점과 Image API

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


이런 것들을 할 수 있네요. 나중에 해봐야 겠습니다. +_+