이미지 클래스 전체 모습 ¶
~cpp
class CImage
{
protected:
HDIB m_hImage; //image handle
HDIB m_hUndoImage; //undo image handle
CSize m_Size; //image size
public:
BOOL InitDIB(BOOL bCreatePalette = TRUE);
void SetHandle(HANDLE hHandle);
BOOL CreateDIBPalette();
virtual ~CImage() { Free(); }
void Free();
int GetBitCount();
HDIB GetHandle() {return m_hImage;}
BOOL IsDataNull() {return (m_hImage == NULL);}
CSize GetSize() {return m_Size;}
int GetHeight() {return m_Size.cy;}
int GetWidth() {return m_Size.cx;}
int GetRealWidth() {return WIDTHBYTES((GetWidth()*GetBitCount()));}
HDIB GetUndoHandle() {return m_hUndoImage;}
CPalette *GetPalette() {return m_pPal;}
BOOL Draw(HDC hDC, LPRECT sourceRect, LPRECT destRect);
BOOL Save(LPCTSTR lpszFileName);
BOOL Load(LPCTSTR lpszFileName);
protected:
BOOL LoadBMP(LPCTSTR lpszFileName);
BOOL SaveBMP(LPCTSTR lpszFileName);
};
/******************************************************
DIB와 관련된 전역 함수
******************************************************/
LPSTR WINAPI FindDIBBits(LPSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
}
DWORD WINAPI DIBWidth(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
/* point to the header (whether Win 3.0 and old) */
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
/* return the DIB width if it is a Win 3.0 DIB */
if (IS_WIN30_DIB(lpDIB))
return lpbmi->biWidth;
else /* it is an other-style DIB, so return its width */
return (DWORD)lpbmc->bcWidth;
}
DWORD WINAPI DIBHeight(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
/* point to the header (whether old or Win 3.0 */
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
/* return the DIB height if it is a Win 3.0 DIB */
if (IS_WIN30_DIB(lpDIB))
return lpbmi->biHeight;
else /* it is an other-style DIB, so return its height */
return (DWORD)lpbmc->bcHeight;
}
WORD WINAPI PaletteSize(LPSTR lpbi)
{
/* calculate the size required by the palette */
if (IS_WIN30_DIB (lpbi))
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
else
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
WORD WINAPI DIBNumColors(LPSTR lpbi)
{
WORD wBitCount; // DIB bit count
/* If this is a Windows-style DIB, the number of colors in the
* color table can be less than the number of bits per pixel
* allows for (i.e. lpbi->biClrUsed can be set to some value).
* If this is the case, return the appropriate value.
*/
if (IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed != 0)
return (WORD)dwClrUsed;
}
/* Calculate the number of colors in the color table based on
* the number of bits per pixel for the DIB.
*/
if (IS_WIN30_DIB(lpbi))
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
/* return number of colors based on bits per pixel */
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/******************************************************
클립보드를 위한 전역 함수
******************************************************/
HGLOBAL WINAPI CopyHandle (HGLOBAL h)
{
if (h == NULL)
return NULL;
DWORD dwLen = ::GlobalSize((HGLOBAL) h);
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
if (hCopy != NULL)
{
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
memcpy(lpCopy, lp, dwLen);
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
이미지 화일 읽고 쓰기 ¶
~cpp
BOOL CImage::Load(LPCTSTR lpszFileName)
{
CString filetype;
filetype = lpszFileName;
filetype.MakeUpper();
if(filetype.Find(".BMP") > -1) return LoadBMP(lpszFileName);
else if(filetype.Find(".TIF") > -1) return LoadTIF(lpszFileName);
else if(filetype.Find(".GIF") > -1) return LoadGIF(lpszFileName);
else if(filetype.Find(".JPG") > -1) return LoadJPG(lpszFileName);
else return FALSE;
}
~cpp
BOOL CImage::LoadBMP(LPCTSTR lpszFileName)
{
CFile file;
CFileException fe;
LPSTR pDIB;
DWORD dwBitsSize;
BITMAPFILEHEADER bmfHeader;
// 읽기 모드로 파일 열기
if(!file.Open(lpszFileName, CFile::modeRead|CFile::shareDenyWrite, &fe))
return FALSE;
// 파일의 길이를 구함
dwBitsSize = file.GetLength();
// 파일 헤더 읽기
if(file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader))!=sizeof(bmfHeader))
return FALSE;
// BMP 파일임을 나타내는 "BM" 마커가 있는지 확인
if (bmfHeader.bfType != DIB_HEADER_MARKER)
return FALSE;
// 메모리 할당
if((m_hImage = (HDIB)::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize)) == NULL) return FALSE;
// 메모리 고정
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hImage);
// 파일 읽기
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
::GlobalUnlock((HGLOBAL) m_hImage);
::GlobalFree((HGLOBAL) m_hImage);
return FALSE;
}
// 메모리 풀어줌
::GlobalUnlock((HGLOBAL) m_hImage);
// DIB 초기화
InitDIB();
return TRUE;
}
~cpp
BOOL CImage::Save(LPCTSTR lpszFileName)
{
CString filetype;
filetype = lpszFileName;
filetype.MakeUpper();
if(filetype.Find(".BMP") > -1) return SaveBMP(lpszFileName);
else if(filetype.Find(".TIF") > -1) return SaveTIF(lpszFileName);
else if(filetype.Find(".GIF") > -1) return SaveGIF(lpszFileName);
else if(filetype.Find(".JPG") > -1) return SaveJPG(lpszFileName);
else return FALSE;
}
~cpp
BOOL CImage::SaveBMP(LPCTSTR lpszFileName)
{
CFile file;
CFileException fe;
BITMAPFILEHEADER bmfHdr;
LPBITMAPINFOHEADER lpBI;
DWORD dwDIBSize;
// 쓰기 모드로 파일 열기
if (!file.Open(lpszFileName, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite, &fe)) return FALSE;
// 메모리 핸들이 유효한지 확인
if (m_hImage == NULL) return FALSE;
// 메모리 고정
lpBI = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL)m_hImage);
if (lpBI == NULL) return FALSE;
// 비트맵 파일 헤더 정보를 설정
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);
if((lpBI->biCompression==BI_RLE8) || (lpBI->biCompression==BI_RLE4))
dwDIBSize += lpBI->biSizeImage;
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
lpBI->biSizeImage = dwBmBitsSize;
}
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+lpBI->biSize + PaletteSize((LPSTR)lpBI);
TRY
{
// 비트맵 파일 헤더를 파일에 쓰기
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
// 나머지 데이터를 파일에 쓰기
file.WriteHuge(lpBI, dwDIBSize);
}
CATCH (CFileException, e)
{
::GlobalUnlock((HGLOBAL) m_hImage);
THROW_LAST();
}
END_CATCH
// 메모리 풀어줌
::GlobalUnlock((HGLOBAL) m_hImage);
return TRUE;
}
모자이크 처리 부분 ¶
~cpp
HDIB CMyImage::MosaicProcess()
{
LPSTR pDIB;
LPSTR pPixels;
int i,j;
long lw; // 실제 쓰여진 Width값입니다.
int avrcolor; // 변환 후의 Color값입니다.
// 메모리 고정
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hImage);
//이미지데이타 처음 위치를 구합니다.
pPixels = DataBits(pDIB);
// 이미지 가로는 4의 배수로 저장됨으로 값을 더 더합니다.
lw = m_Size.cx + (m_Size.cx%4>0?(4-m_Size.cx%4):0);
// 네칸의 픽셀값을 동일한 값으로 평균화 합니다.
for (i=0;i<m_Size.cy;i+=2)
{
for (j=0;j<m_Size.cx;j+=2)
{
avrcolor = 0;
avrcolor += (int)((BYTE *)pPixels)[i*lw+j];
avrcolor += (int)((BYTE *)pPixels)[i*lw+(j+1)];
avrcolor += (int)((BYTE *)pPixels)[(i+1)*lw+j];
avrcolor += (int)((BYTE *)pPixels)[(i+1)*lw+(j+1)];
avrcolor/=4;
((BYTE *)pPixels)[i*lw+j] = (char)avrcolor;
((BYTE *)pPixels)[i*lw+(j+1)] = (char)avrcolor;
((BYTE *)pPixels)[(i+1)*lw+j] = (char)avrcolor;
((BYTE *)pPixels)[(i+1)*lw+(j+1)] = (char)avrcolor;
}
}
// 메모리 놓아줌
::GlobalUnlock((HGLOBAL) m_hImage);
return (HDIB)pDIB;
}
Thread ¶
내 생각엔
SpikeSolution 과정에서 중복된 코드가 나올것 같고 나중에 이것들을 묶어서 단순한 설계를 구현시킬 수 있을 것 같다.
오 신기하다. 이걸로 솔루션이 세개쯤인거네, 우리조는 선택도 할수 있네 대단한조
--
neocoin
지금 위키 참 맘에 안드네.. BR테그 쓰는 법이 뭐라구? ㅡ.ㅡ
~cpp [[BR]]
이것, 하지만 쓰지 않고 얼마든지 방법이
관하여 ¶
* 배포 계획 수립 회의
- 성공적인 제품을 정의하기 위해 충분한 스토리를 작성한다.
- 필요한 조사를 수행한다.
- 각 스토리 구현의 난이도를 추정한다.
- 스토리 구현 속도를 추정한다.
- 비즈니스 가치와 난이도에 기반하여 첫번째 배포를 하기 위한 스토리를 선택한다.
* 코드의 공동 소유
* 단순한 설계
- 모든 테스트를 실행한다.
- 모든 아이디어를 표현한다.
- 중복된 코드를 포함하지 않는다.
- 최소한의 클래스와 메소드를 가진다.