Software/Programming2014. 8. 11. 12:19

프로그래밍 목적이라기 보다는 DSP에서 한번 나왔던 개념이기에 혹시 궁금하신 분들은 참고하길 바랍니다~

 

사전적인 의미

:구조체의 구성 요소(member)의 선언에서 ':'을 함께하는 정수식을 지정하는 방법

 

목적

:메모리의 낭비를 줄이기 위함

 

요즘 컴퓨터는 성능이 매우 좋아서 별로 쓰이지 않지만, DSP와 같이 자원이 한정적인 기기들에는 여전히 유용하다.

예를들어 Int형 정수를 사용하는데 그 값은 0아니면 1만 나온다고 하자.(가령 GPIOA의 MUX는 0아니면 1이면 충분하다.) Uint16이라고 해도 16비트 즉 2바이트다. 1비트면 충분한데 16비트로 사용한다면 정말 큰 메모리 낭비이지 않겠는가? 이때, 선언은 16비트라도 메모리를 1비트로 사용할 수 있다.

 

아래 구조체를 보자

 

struct BitFieldTest    {

unsinged int a : 2;

unsinged int b : 3;

};

 

이 구조체에 대한 size는 32비트(16X2)로 잡히고 하위 두 비트(0,1 번째)와 그 위의 세 비트(2,3,4 번째)가 사용되고 나머지 비트들은 사용되지 않는다. 따라서 메모리를 아낄 수 있다.

 

단점을 들자면 이 32비트 메모리에서 특정 비트들만 값을 변경할 때, 예를 들어 BitFieldTest.a = 1을 하면 단순히 a에 1을 대입하는 것이 아니라 (BitFieldTest & 3 | 1)로 처리되어 비트 연산을 수행하기 때문에 메모리는 아끼지만 속도가 느려지게 된다. MCU에서 MUX레지스터를 자주 바꾸지는 않을테니 큰 문제는 되지 않을것이라 본다.

위의 (BitFieldTest & 3 | 1)이 무슨 의미냐 하면 3이란 숫자는 0b11로 2비트를 의미하기 때문에 BitField의 2비트를 &로 추려내고 여기에 or연산자로 1을 대입하는 것이다. 따라서 한번 연산할 것을 2번연산하게 되는 것이다.

 

struct GPAMUX_BITS    {

Uint16 PWM1_GPIOA0 : 1;

Uint16 PWM2_GPIOA1 : 1;

...

};

 

DSP 28x의 GPAMUX_BITS이다 단지 ON, OFF 만 사용한다면 0,1이면 되기에 1비트만으로도 충분하다.

 

signed 변수를 사용할 때 오버플로우 또는 언더플로우가 발생하지 않도록 값의 대입을 조심하도록 하자.

또한 당연하겠지만 비트수에 따른 표현 가능한 수의 갯수는 2의 n승이다.

Posted by 십자성군
Software/Programming2013. 5. 25. 16:46

다룰것.


이진트리

최적 이진 탐색트리

AVL 트리

2-3 트리

2-3-4 트리

레드블랙 트리(rb트리)

M-원 트리

B-트리

etc




일반적인 이진트리이다. 그러나 마구잡이로 넣어버리면 한쪽방향으로만 뻗어가는 트리가 생길 수도 있겠지?

트리를 만드는 목적은 무엇이냐?

배열이나 단순한 링크드리스트같은 선형구조는 원하는 자료 탐색에 있어서 난항을 겪게된다.

여기에서 탐색을 위한 규칙성이 있다면 탐색하기 편하겠다. 그런데 이진트리에서 한쪽 방향으로만 뻗어버리면 배열과 다를게 없을것이다.




다음과 같은 이진탐색트리에서 알 수 있는 규칙성은?

한 노드에서 그 왼쪽으로 뻗은 자식은 부모보다 작은 숫자이다.

반면 오른쪽으로 뻗은 자식은 부모보다 큰 숫자이다.




트리는 탐색, 접근시간이 짧아야 한다. 여기서 AVL트리의 차례. 트리의 회전을 이용하자.

AVL Tree 개념 : http://blog.naver.com/ryutuna?Redirect=Log&logNo=100122795293



균형치(Balance Factor)가 +-2 미만이어야 한다. 2 이상일 경우 LL, RR, LR, RL 회전을 통하여 균형치를 맞춰준다.



LL회전


RR회전


LR회전


RL회전


용어 정리

1. 균형치(Balance factor)

- 균형치 = 왼쪽 서브트리의 높이 – 오른쪽 서브트리의 높이

2. 트리의 높이(Height)

- 높이 혹은 깊이(Depth)라고 하며 그 트리에 속한 노드의 최대 레벨로 정해진다.

3. 레벨(Level)

- 루트를 레벨1로 정의하기도 하고 0으로 정의하기도 하지만 본 문서에선 1로 정의하도록 하겠다. 만약 한 노드의 레벨이 L이라면 그 자식의 레벨은 L+1이 된다.


B+트리 설명은 다음 링크에서...

http://blog.naver.com/hytgogo?Redirect=Log&logNo=30121130366

'Software > Programming' 카테고리의 다른 글

MFC)버튼을 누르는 동안 지속되는 카운팅 예제  (2) 2014.10.19
비트필드(Bit Field)  (0) 2014.08.11
전위표기. 후위표기  (0) 2013.05.25
MFC 새로운 가상함수 추가  (0) 2012.08.12
[MFC] bmp파일 열기  (3) 2012.08.11
Posted by 십자성군
Software/Programming2013. 5. 25. 16:32

ex)전위표기

4*5-14/7*3 이 있다고 하자


괄호를 적절하게 넣어서 표현하면

(4*5)-((14/7)*3)이다.


제일 안쪽에서 먼저 계산할것부터 표현하면

1. 4*5

2. 14/7

3. (2)*3

4. (1)-(3)


4번부터 순서대로 표기하면

1. -(1)(3)

2. -(*4 5)(3)

3. -*4 5 (*(2) 3)

4. -*4 5 (*/14 7 3)


결과 : -*4 5 */ 14 7 3        :전위표기

ex)후위표기

4번부터 순서대로 표기하면

1. (1)(3)-

2. (4 5 *)(3)-

3. 4 5 * ((2) 3 *)-

4. 4 5 * 14 7 / 3 * -


결과 : 4 5 * 14 7 / 3 * -


Stack을 이용하여 전위표기를 후위표기로 표기하는 알고리즘을 구현할 수 있다

Posted by 십자성군
Software/Programming2012. 8. 12. 00:24

클래스 마법사를 이용

클래스 속성의 이벤트 오픈


가상함수는 원래 존재하는 함수의 기능을 바꾸어 구현할때 사용

Posted by 십자성군
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 십자성군
Software/Programming2012. 8. 10. 22:28


1193120077_BmpTest001.rar

4개의 비트맵 파일을 불러와서 메모리비트맵에 저장한 다음

새로운 메모리비트맵에 4개의 비트맵을 차례로 출력 후 그림파일로 

저장하는 예제입니다...

소스폴더에 보시면 1.bmp부터 4.bmp까지 있는데

다른 비트맵파일로 바꾼뒤에 테스트 해보셔도 됩니다.

CMyImage클래스가 그림을 불러오고 저장하는 클래스니 확인하셔야 하구요

View클래스의 OnInitialUpdate함수에 그림파일을 불러오는 부분이 있으니

잘 해석해보시면 어떻게 해야할지 아실줄로 생각됩니다.

View클래스외에는 수정한게 없으니

CMyImage클래스와 View클래스만 보시면 될 것 같네요...

 

다운받으시려면 아래 다운로드에 마우스커서를 놓고

오른쪽 버튼을 누른 뒤 "다른 이름으로 대상 저장" 을 눌러 저장해 주세요...

아래 다운로드 소스는 제 Paran블로그에 올려두었습니다... (물론 비공개글입니다.)

Posted by 십자성군
Software/Programming2012. 8. 10. 22:10

제가 프로그램을 짜고있는데 커머파일은 되는데 실행할때 에러가 나서요ㅠㅠ

 

제 프로그램의 내용은 이미지 파일 두개를 연속으로 열고 그 후에 지정된 폴더에 있는 이미지 파일을 연속적으로 여는건데요

 

문제는 이미지 파일 두개를 연속으로 열때는 문제가 없는데 그 후에 지정된 폴더내에 있는 이미지 파일을 연속적으로 열려고 할때 에러가 난다는 겁니다. 에러의 내용은

 

 

 

이거구요ㅠㅠ

 

그림 맨위에 gray in light.bmp 파일이 첫번째로 open한 파일의 이름입니다.

 

이미지 파일 두개를 오픈하는 소스는 다음과 같구요

 

BOOL CWinColorDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
 if (!CDocument::OnOpenDocument(lpszPathName))
  return FALSE;
 //1번째 이미지 파일
 // TODO: Add your specialized creation code here
 CFile hFile;
 hFile.Open(lpszPathName,CFile::modeRead | CFile::typeBinary);
 hFile.Read(&dibHf,sizeof(BITMAPFILEHEADER)); // 파일 헤드를 읽음
 if(dibHf.bfType!=0x4D42)
 {
  AfxMessageBox("Not BMP file!!");
  return FALSE;
 } //이 파일이 BMP파일인지 검사. 0x4d42=='BM'
 hFile.Read(&dibHi,sizeof(BITMAPINFOHEADER)); //"영상정보의 Header"를 읽는다. 
 if(dibHi.biBitCount!=8 && dibHi.biBitCount!=24)
 {
  AfxMessageBox("Gray/True Color Possible!!");
  return FALSE;
 }
 if(dibHi.biBitCount==8)
  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]; //dibHi.biSizeImage

 m_OutImg = new unsigned char [ImgSize];
 
 hFile.Read(m_InImg, ImgSize);

 height = dibHi.biHeight;
 width = dibHi.biWidth;
 
 if(dibHi.biBitCount==24){} //return TRUE;
 // 영상데이터 대입
 
 int i,j,index;
 int rwsize = WIDTHBYTES(dibHi.biBitCount*width);
 for( i=0; i<height; i++)
 {
  index = i*rwsize;
  for(j=0; j<width; j++)
   m_InImg[index+j] = (unsigned char)palRGB[(int)m_InImg[index+j]].rgbBlue;
 }
   
 
 hFile.Close();
 

 //2번째 이미지 파일
 CFile h1File;
 CFileDialog dlg(TRUE);
 if (dlg.DoModal() == IDOK )
 {
  CString lpszPathName2 = dlg.GetPathName();
  h1File.Open(lpszPathName2,CFile::modeRead | CFile::typeBinary);
  h1File.Read(&dibHf1,sizeof(BITMAPFILEHEADER)); // 파일 헤드를 읽음

  if(dibHf1.bfType!=0x4D42)
  {
   AfxMessageBox("Not BMP file!!"); return FALSE;
  } //이 파일이 BMP파일인지 검사. 0x4d42=='BM'
  h1File.Read(&dibHi1,sizeof(BITMAPINFOHEADER)); //"영상정보의 Header"를 읽는다. 
  if(dibHi1.biBitCount!=8 && dibHi1.biBitCount!=24)
  {
   AfxMessageBox("Gray/True Color Possible!!");
   return FALSE;
  }
  
  if(dibHi1.biBitCount==8)
   h1File.Read(palRGB,sizeof(RGBQUAD)*256);

  // 메모리 할당 (바뀐 부분)
  int ImgSize1;
  if(dibHi1.biBitCount==8) ImgSize1 = h1File.GetLength()-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER)-256*sizeof(RGBQUAD);
  else if(dibHi1.biBitCount==24) ImgSize1 = h1File.GetLength()-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER);
  m_InImg1 = new unsigned char [ImgSize1]; //dibHi1.biSizeImage
  m_OutImg1 = new unsigned char [ImgSize1];


        h1File.Read(m_InImg1, ImgSize1);

  height1 = dibHi1.biHeight;
  width1 = dibHi1.biWidth;

 
  h1File.Close();
 
  //return TRUE;

  // 영상데이터1 대입
  
  int i1,j1,index1;
  int rwsize1 = WIDTHBYTES(dibHi1.biBitCount*width1);
  for(i1=0; i1<height1; i1++)
  {
   index1 = i1*rwsize1;
   for(j1=0; j1<width1; j1++)
    m_InImg1[index1+j1] = (unsigned char)palRGB[(int)m_InImg1[index1+j1]].rgbBlue;
  }

 }
 //if(dibHi1.biBitCount==24) //return TRUE;

 return TRUE;
}

 

폴더내에 있는 이미지 파일을 연속적으로 오픈하는 부분은 다음과 같습니다.

 

void CWinColorDoc::OnBatchAccumhist()
{
 // TODO: Add your command handler code here
/* CFileDialog dlg(TRUE);
 if (dlg.DoModal() == IDOK )
 {
 */
 CFileFind find; //file 검색을 위한 클래스
  CString path1 = "C:\\temp1\\*.bmp"; //원하는 폴더경로 지정
 CString fname;
 CString pname;

 int pWorking = find.FindFile((LPCTSTR)path1);//원하는 폴더 경로에  조건에 맞는 파일이 있으면 1, 없으면 0

  if (pWorking==0) {

   AfxMessageBox("파일이 없습니다.");

  }

  while(pWorking)
  {
   pWorking = find.FindNextFile(); //다음 파일 찾기
   fname = find.GetFileName(); //파일 이름 넘겨주기
   pname = find.GetFilePath(); //파일 경로 넘겨주기


 
   CFile h2File;//원하는 파일이 있을 경우 파일을 읽어들이기 위한 함수

   // CString lpszPathName3 = dlg.GetPathName();

    h2File.Open(pname,CFile::modeRead | CFile::typeBinary);

    h2File.Read(&dibHf2,sizeof(BITMAPFILEHEADER)); // 파일 헤드를 읽음

    h2File.Read(&dibHi2,sizeof(BITMAPINFOHEADER)); //"영상정보의 Header"를 읽는다.
   
     if(dibHi2.biBitCount!=8 && dibHi2.biBitCount!=24)
     {
      AfxMessageBox("Gray/True Color Possible!!");
    
     }

     if(dibHi2.biBitCount==8)

      h2File.Read(palRGB,sizeof(RGBQUAD)*256);


     // 메모리 할당 (바뀐 부분)
     double ImgSize=0.0;

         if(dibHi2.biBitCount==8)
       ImgSize = h2File.GetLength() -sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER)-256*sizeof(RGBQUAD);
      else if(dibHi2.biBitCount==24)
       ImgSize = h2File.GetLength()-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER);
   
      m_InImg2 = new unsigned char [ImgSize]; //dibHi.biSizeImage
    
      h2File.Read(m_InImg2, ImgSize);

      height2 = dibHi2.biHeight;
      width2 = dibHi2.biWidth;
    
      //if(dibHi2.biBitCount==24){} //return TRUE;
   
      // 영상데이터 대입  
   
      int i,j,index;
      int rwsize = WIDTHBYTES(dibHi2.biBitCount*width2);

      for( i=0; i<height2; i++)
      {
       index = i*rwsize;
       for(j=0; j<width2; j++)
        m_InImg2[index+j] = (unsigned char)palRGB[(int)m_InImg2[index+j]].rgbBlue;
      }
   

      OnAccFeatHisto();

      if (find.IsDirectory()) //디렉토리가 있으면
      {
       CString ffilename = pname+"\\";

       AfxMessageBox(ffilename);
       //fileopen. fullfilename
       // fclose
      } else { //디렉토리가 없으면-bmp 파일이면                                                        
       CString ffilename = pname;
       AfxMessageBox(ffilename);
       //fileopen. fullfilename                                                                                                                                                  
       //OnAcchisto();
       // fclose
      } 
   
      h2File.Close();
         delete m_InImg2;   
   }
  
  
// } 
 
}

Posted by 십자성군
Software/Programming2012. 8. 10. 22:08

// 1. 파일에서 비트맵 데이터를 읽어들임

HBITMAP dibLoadFromFile(LPCTSTR lpFileName)
{
    HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ,
                        NULL, OPEN_EXISTING, 0, NULL);

    if(hFile == INVALID_HANDLE_VALUE) return NULL;

 

    BITMAPFILEHEADER bmfh;

    DWORD dwRead;
    ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwRead, NULL);

 

    DWORD dwInfoLength = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
    LPBITMAPINFO lpbmi = (LPBITMAPINFO)new BYTE[dwInfoLength];
    ReadFile(hFile, lpbmi, dwInfoLength, &dwRead, NULL);

 

    HDC hDC = GetDC(GetDesktopWindow());

 

    LPVOID lpDIBits;
    HBITMAP hDIB = CreateDIBSection(hDC, lpbmi, DIB_RGB_COLORS, &lpDIBits, NULL, 0);

    ReleaseDC(GetDesktopWindow(), hDC);

 

    ReadFile(hFile, lpDIBits, lpbmi->bmiHeader.biSizeImage, &dwRead, NULL);

    CloseHandle(hFile);

 

    delete [] lpbmi;

 

    return hDIB;
}

 

// 2. 비트맵 데이터를 24비트 트루칼라로 바꿈

void dibSetTrueColor(HBITMAP* phDIB)
{
    DIBSECTION ds;
    GetObject(*phDIB, sizeof(DIBSECTION), &ds);

    if(ds.dsBmih.biBitCount == 24) return;

 

    HDC hDC = GetDC(GetDesktopWindow());

    HBITMAP hDDB = CreateCompatibleBitmap(hDC, ds.dsBm.bmWidth, ds.dsBm.bmHeight);
    SetDIBits(hDC, hDDB, 0, ds.dsBm.bmHeight, ds.dsBm.bmBits,

                    (LPBITMAPINFO)&ds.dsBmih, DIB_RGB_COLORS);

 

    BITMAPINFOHEADER bmih;
    ZeroMemory(&bmih, sizeof(BITMAPINFOHEADER));
    bmih.biSize = sizeof(BITMAPINFOHEADER);
    bmih.biWidth = ds.dsBm.bmWidth;
    bmih.biHeight = ds.dsBm.bmHeight;
    bmih.biPlanes = 1;
    bmih.biBitCount = 24;
    bmih.biCompression = BI_RGB;

 

    LPVOID lpDIBits;
    HBITMAP hDIB = CreateDIBSection(hDC, (LPBITMAPINFO)&bmih, DIB_RGB_COLORS,

                    &lpDIBits, NULL, 0);
    GetDIBits(hDC, hDDB, 0, ds.dsBm.bmHeight, lpDIBits, (LPBITMAPINFO)&bmih,

                    DIB_RGB_COLORS);

    ReleaseDC(GetDesktopWindow(), hDC);

 

    DeleteObject(hDDB);
    DeleteObject(*phDIB);

    *phDIB = hDIB;
}

 

// 3. 비트맵의 밝기를 조절

void dibSetBrightness(HBITMAP hDIB, int nLevel)
{
    DIBSECTION ds;
    GetObject(hDIB, sizeof(DIBSECTION), &ds);
    if(ds.dsBmih.biBitCount != 24) return;

 

    for(int y = 0; y < ds.dsBm.bmHeight; y++) {
        RGBTRIPLE* lpLine = (RGBTRIPLE*)ds.dsBm.bmBits + (y * ds.dsBm.bmWidth);
        for(int x = 0; x < ds.dsBm.bmWidth; x++) {
            RGBTRIPLE rgbT = lpLine[x];
            int r = (int)rgbT.rgbtRed + nLevel;
            int g = (int)rgbT.rgbtGreen + nLevel;
            int b = (int)rgbT.rgbtBlue + nLevel;
            rgbT.rgbtRed = (r > 255) ? 255 : ((r < 0) ? 0 : r);
            rgbT.rgbtGreen = (g > 255) ? 255 : ((g < 0) ? 0 : g);
            rgbT.rgbtBlue = (b > 255) ? 255 : ((b < 0) ? 0 : b);
            lpLine[x] = rgbT;

            }
        }
}

 

// 4. 비트맵 데이터를 파일에 저장

BOOL dibSaveToFile(LPCTSTR lpFileName, HBITMAP hDIB)
{
    HANDLE hFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,

                        FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE) return FALSE;

 

    DIBSECTION ds;
    GetObject(hDIB, sizeof(DIBSECTION), &ds);

 

    int nColors = 0;
    if(ds.dsBmih.biBitCount <= 8)
        nColors = (ds.dsBmih.biClrUsed) ? ds.dsBmih.biClrUsed : (1 << ds.dsBmih.biBitCount);

 

    BITMAPFILEHEADER bmfh;
    bmfh.bfType = 'MB';
    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)

                            + nColors * sizeof(RGBQUAD);
    bmfh.bfSize = bmfh.bfOffBits + ds.dsBmih.biSizeImage;
    bmfh.bfReserved1 = bmfh.bfReserved2 = 0;

 

    DWORD dwWritten;
    WriteFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
    WriteFile(hFile, &ds.dsBmih, sizeof(BITMAPINFOHEADER) + nColors * sizeof(RGBQUAD),

                        &dwWritten, NULL);
    WriteFile(hFile, ds.dsBm.bmBits, ds.dsBmih.biSizeImage, &dwWritten, NULL);
    CloseHandle(hFile);


    return TRUE;
}

Posted by 십자성군
Software/Programming2012. 8. 10. 00:31

http://nenunena.tistory.com/66

'Software > Programming' 카테고리의 다른 글

MFC 비트맵 파일처리 3. (수정필요)  (0) 2012.08.10
MFC 비트맵 파일 다루기 1.  (0) 2012.08.10
MFC의 흐름  (0) 2012.08.10
도큐먼트 뷰 객체 설명  (0) 2012.08.10
CFileDialog  (0) 2012.08.10
Posted by 십자성군
Software/Programming2012. 8. 10. 00:30

MFC의 흐름

http://blog.naver.com/gorory?Redirect=Log&logNo=20031488529

Posted by 십자성군