목표.
1. bmp파일을 연다
2. 8비트와 24비트 컬러를 출력한다.
프로젝트명 : BmpReading
BmpReading.h
==========================================================================================
// BmpReadingDoc.h : CBmpReadingDoc 클래스의 인터페이스
//
#pragma once
class CBmpReadingDoc : public CDocument
{
protected: // serialization에서만 만들어집니다.
CBmpReadingDoc();
DECLARE_DYNCREATE(CBmpReadingDoc)
// 특성입니다.
public:
// 작업입니다.
public:
// 재정의입니다.
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
#ifdef SHARED_HANDLERS
virtual void InitializeSearchContent();
virtual void OnDrawThumbnail(CDC& dc, LPRECT lprcBounds);
#endif // SHARED_HANDLERS
// 구현입니다.
public:
unsigned char *m_InImg; // bmp파일의 이미지 내용 저장
unsigned char *m_OutImg; // bmp이미지 출력용 배열
BITMAPFILEHEADER dibHf; // 비트맵 파일헤드 구조체
BITMAPINFOHEADER dibHi; // 비트맵 영상헤드 구조체
RGBQUAD palRGB[256]; // 팔레트 정보 구조체 배열
virtual ~CBmpReadingDoc(); // 이들을 가상변수로 구현화 한다
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 생성된 메시지 맵 함수
protected:
DECLARE_MESSAGE_MAP()
#ifdef SHARED_HANDLERS
// 검색 처리기에 대한 검색 콘텐츠를 설정하는 도우미 함수
void SetSearchContent(const CString& value);
#endif // SHARED_HANDLERS
public:
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
virtual BOOL OnSaveDocument(LPCTSTR lpszPathName);
};
=======================================================================================
BmpReadingDoc.cpp (일부)
=======================================================================================
#define WIDTHBYTES(bits) (((bits)+31)/32*4) //추가, 영상의 가로줄은 4바이트의 배수
//새로 정의한 가상함수 OnOpenDocument
BOOL CBmpReadingDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
// TODO: 여기에 특수화된 작성 코드를 추가합니다.
//CFile에서 처리
CFile hFile; //파일을 읽어들이면 이 클래스 형식으로 저장.
int height; //이미지의 높이를 저장할 변수
int width; //이미지의 가로길이를 저장할 변수
hFile.Open(lpszPathName,CFile::modeRead | CFile::typeBinary); //파일 열기
hFile.Read(&dibHf,sizeof(BITMAPFILEHEADER)); //dibHf에 파일헤더를 읽어들인다.
//이 파일이 BMP파일인지 검사
if(dibHf.bfType!=0x4D42)
{
AfxMessageBox(L"Not BMP file!!"); //프로젝트 생성시 유니코드를 사용하게 할 경우
return FALSE; //L을 붙여준다
}
hFile.Read(&dibHi,sizeof(BITMAPINFOHEADER)); //영상정보의 header를 읽기
if(dibHi.biBitCount != 8 && dibHi.biBitCount != 24) //8,24비트가 아닐경우
{
AfxMessageBox(L"Gray/True Color Possible!!");
return FALSE;
}
if(dibHi.biBitCount==8)
//8비트의 경우 팔레트를 생성해 주어야 한다. 총 256가지 색이므로 그 길이만큼 읽어들인다
hFile.Read(palRGB,sizeof(RGBQUAD)*256);
//메모리 할당
int ImgSize;
if(dibHi.biBitCount == 8)
{
ImgSize = hFile.GetLength()-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER)-256*sizeof(RGBQUAD); //이미지의 크기는 파일 총 길이에서, 두 헤드와 팔레트의 사이즈를
} //제외한다.
else if(dibHi.biBitCount == 24) //컬러영상
{
ImgSize = hFile.GetLength()-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER);
}
//이미지를 저장, 출력할 배열생성.
m_InImg = new unsigned char [ImgSize];
m_OutImg = new unsigned char [ImgSize];
hFile.Read(m_InImg, ImgSize);
hFile.Close();
//이미지의 길이정보
height = dibHi.biHeight;
width = dibHi.biWidth;
return TRUE;
}
BOOL CBmpReadingDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
CFile hFile;
if(!hFile.Open(lpszPathName,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
return FALSE;
//정보저장
hFile.Write(&dibHf,sizeof(BITMAPFILEHEADER));
hFile.Write(&dibHi,sizeof(BITMAPINFOHEADER));
if(dibHi.biBitCount==8)
hFile.Write(palRGB,sizeof(RGBQUAD)*256);
hFile.Write(m_InImg,dibHi.biSizeImage);
hFile.Close();
return TRUE;
}
===============================================================================
BmpReadingView.h (일부)
===============================================================================
// 구현입니다.
public:
BITMAPINFO* BmInfo; //비트맵 영상헤드를 선언
virtual ~CBmpReadingView();
===============================================================================
BmpReadingView.cpp (일부)
===============================================================================
CBmpReadingView::CBmpReadingView()
{
// TODO: 여기에 생성 코드를 추가합니다.
BmInfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+256*sizeof(RGBQUAD));
for(int i=0; i<256; i++)
{
BmInfo->bmiColors[i] .rgbRed= BmInfo->bmiColors[i] .rgbGreen = BmInfo->bmiColors[i] .rgbReserved = 0;
}
}
CBmpReadingView::~CBmpReadingView()
{
if(BmInfo) delete BmInfo;
}
void CBmpReadingView::OnDraw(CDC* pDC)
{
#define WIDTHBYTES(bits) (((bits)+31)/32*4); //이미지 가로 바이트 길이는 4바이트의 배수
//BmInfo;
int height;
int width;
int rwsize;
CBmpReadingDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.
if(pDoc->m_InImg==NULL)
return;
//24비트 비트맵 파일의 영상출력
if(pDoc->dibHi.biBitCount==24){
height=pDoc->dibHi.biHeight;
width=pDoc->dibHi.biWidth;
rwsize=WIDTHBYTES(pDoc->dibHi.biBitCount*pDoc->dibHi.biWidth);
BmInfo -> bmiHeader = pDoc->dibHi;
SetDIBitsToDevice(pDC->GetSafeHdc(),0,0,width,height,0,0,0,height,pDoc->m_InImg,BmInfo,DIB_RGB_COLORS);
}
else //8비트 컬러일 경우
{
int index;
rwsize=WIDTHBYTES(pDoc->dibHi.biBitCount*pDoc->dibHi.biWidth);
//팔레트를 읽어들이며 반복출력
for(int i=0; i<pDoc->dibHi.biHeight;i++)
for(int j=0; j<pDoc->dibHi.biWidth;j++){
index=pDoc->m_InImg[i*rwsize+j];
BYTE R=pDoc->palRGB[index].rgbRed;
BYTE G=pDoc->palRGB[index].rgbGreen;
BYTE B=pDoc->palRGB[index].rgbBlue;
//pDC->SetPixel(j,i,RGB(R,G,B));
//영상 반전출력
pDC->SetPixel(j,pDoc->dibHi.biHeight-i-1,RGB(R,G,B));
}
}
}
'Software > Programming' 카테고리의 다른 글
전위표기. 후위표기 (0) | 2013.05.25 |
---|---|
MFC 새로운 가상함수 추가 (0) | 2012.08.12 |
MFC 여러개 bmp이미지 부르기, 합치기 (0) | 2012.08.10 |
MFC 비트맵 파일처리 3. (수정필요) (0) | 2012.08.10 |
MFC 비트맵 파일 다루기 1. (0) | 2012.08.10 |