Software/Programming2012. 8. 11. 19:33

목표.

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));


}

}

}

Posted by 십자성군