본문 바로가기

Projects/CoVNC

비트맵 파일 저장하고 읽기

BMP파일 읽고 저장하는 소스인데요 고수님 봐주세요

struct userheader {

      unsigned count;           // <--여기 count 에다가는 0을 넣고 싶고요

      char maker[4];            // <--name <---요걸 넣고 싶어요

} User_Header;


위 구조체를 아래 소스에있는

FILE_HEADER 앞전에 넣어줄려고 합니다.


// include header file
//------------------------------------------------------------------------------------
#include <stdio.h>
#include <memory.h>


//------------------------------------------------------------------------------------
// 상수값 정의
//------------------------------------------------------------------------------------
#define READ_FILE_NAME "test.bmp" // 비트맵 파일 이름 정의
#define WRITE_FILE_NAME "test_writed.bmp" // 비트맵 파일 이름 정의


//------------------------------------------------------------------------------------
// Bitmap File Header 에 대한 구조체 정의
//------------------------------------------------------------------------------------

// 32bit 컴퓨터로 인한 패딩 현상 방지를 위해
#pragma pack(push, 1)

typedef struct tFILE_HEADER
{
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} FILE_HEADER;

#pragma pack(pop)


//------------------------------------------------------------------------------------
// Bitmap Info Header 에 대한 구조체 정의
//------------------------------------------------------------------------------------

typedef struct tINFO_HEADER
{
   unsigned long biSize;
   unsigned long biWidth;
   unsigned long biHeight;
   unsigned short biPlanes;
   unsigned short biBitCount;
   unsigned long biCompression;
   unsigned long biSizeImage;
   unsigned long biXPelsPerMeter;
   unsigned long biYPelsPerMeter;
   unsigned long biClrUsed;
   unsigned long biClrImportant;
} INFO_HEADER;

//------------------------------------------------------------------------------------
// 비트맵 파일 전체에 대한 구조체 정의
//------------------------------------------------------------------------------------

typedef struct tMY_BITMAP
{
FILE_HEADER  bmpFileHeader; // file header 부분
INFO_HEADER  bmpInfoHeader; // info header 부분
unsigned char* bmpPalette;  // palette 부분
unsigned char* bmpRawData;  // 실제 이미지 data 부분
} MY_BITMAP;


//------------------------------------------------------------------------------------
// 함수 원형 정의부
//------------------------------------------------------------------------------------

int get_bmpFileHeader(unsigned char* bmpBuf, MY_BITMAP* pBitmap);
int get_bmpInfoHeader(unsigned char* bmpBuf, MY_BITMAP* pBitmap);
int get_bmpPalette(unsigned char* bmpBuf, MY_BITMAP* pBitmap);
int get_bmpRawData(unsigned char* bmpBuf, MY_BITMAP* pBitmap);
int write_bmpInfo(MY_BITMAP* pBitmap);
int make_bmp(unsigned char* bmpBuf, MY_BITMAP* pBitmap);

//------------------------------------------------------------------------------------
// main 함수 시작
//------------------------------------------------------------------------------------

int main(int argc, char *argv[])
{
MY_BITMAP Bitmap;   // 비트맵 데이터가 저장될 구조체 선언
FILE *pBitmapFile;   // 파일을 읽기 위한 스트림
unsigned int nFileSize;  // 파일의 사이즈
unsigned char* pBitmapBuf; // 파일의 모든 데이타가 저장될 버퍼
int is;      // 함수 호출이 성공했는지 보기위한 변수


pBitmapFile = fopen(READ_FILE_NAME, "rb"); // 비트맵 파일을 연다.

// 파일이 존재하지않는 등의 이유로 파일 열기를 실패 하였을경우 pBitmapFile값은 null
if (!pBitmapFile)
{
  printf("failed to open bitmap file...\nExit...\n");
  return 0; // 프로그램 종료
}

// 파일의 사이즈를 알아오기 위해 파일 포인터의 위치를 가장 끝으로 옮기후 그 위치를 읽어온다.
// 파일의 사이즈를 알아야 그만큼의 바이트를 메모리에 할당하고 파일의 모든 데이터를
// 변수값에 저장할 수 있다.
fseek(pBitmapFile, 0L, SEEK_END); // 파일 포인터의 위치를 끝으로 옮기기
nFileSize = ftell(pBitmapFile);  // 현재 파일 포인터의 위치를 읽어오기


// 파일의 사이즈 만큼 바이트 수를 메모리에 할당한다
pBitmapBuf = new unsigned char[nFileSize];


// 파일의 데이터를 읽어오기 위해 다시 파일 포인터의 위치를 처음으로 옮긴다
fseek(pBitmapFile, 0L, SEEK_SET);

// 파일의 데이터를 처음부터 파일의 사이즈만큼 바이트단위로 읽는다.
fread(pBitmapBuf, sizeof(char), nFileSize, pBitmapFile);
printf("read bitmap file...\n");

// 이제 파일의 모든 데이터는 pBitmapBuf에 저장되어 있다
fclose(pBitmapFile); // 파일 닫기



// pBitmapBuf 에서 Bitmap File Header 부분을 분리해 낸다
is = get_bmpFileHeader(pBitmapBuf, &Bitmap);
if (!is) // 실패시 프로그램 종료
{
  printf("failed to read bitmap file header...\n\n");
}
printf("get bitmap file header...\n");

// pBitmapBuf 에서 Bitmap Info Header 부분을 분리해 낸다
is = get_bmpInfoHeader(pBitmapBuf, &Bitmap);
if (!is) // 실패시 프로그램 종료
{
  printf("failed to read bitmap info header...\n\n");
}
printf("get bitmap info header...\n");

// pBitmapBuf 에서 Bitmap Palette 부분을 분리해 낸다
is = get_bmpPalette(pBitmapBuf, &Bitmap);
if (!is) // 실패시 프로그램 종료
{
  printf("failed to read bitmap palette...\n\n");
}
printf("get bitmap palette...\n");

// pBitmapBuf 에서 Bitmap Raw Data 부분을 분리해 낸다
is = get_bmpRawData(pBitmapBuf, &Bitmap);
if (!is) // 실패시 프로그램 종료
{
  printf("failed to read bitmap raw data...\n\n");
}
printf("get bitmap raw data...\n");


// 비트맵 정보 출력
write_bmpInfo(&Bitmap);
printf("write bitmap info...\n");

if (pBitmapBuf) // 버퍼 메모리 해제
{
  delete pBitmapBuf;
  pBitmapBuf = NULL;
}

// 구조체의 내용을 기반으로 파일에 쓰기 위해 임시 버퍼를 만듬
// 당연히 버퍼의 크기는 파일의 크기만큼 이어야 함
nFileSize = Bitmap.bmpFileHeader.bfSize;

pBitmapBuf = new unsigned char[nFileSize];

// 임시 버퍼에 구조체의 내용을 채운다
is = make_bmp(pBitmapBuf, &Bitmap);
if (!is) // 실패시 프로그램 종료
{
  printf("failed to make bitmap...\n\n");
}

// 파일에 써서 test_writed.bmp 파일을 만들어낸다
pBitmapFile = fopen(WRITE_FILE_NAME, "wb");
fwrite(pBitmapBuf, sizeof(char), nFileSize, pBitmapFile);
printf("make bitmap file...\n");
fclose(pBitmapFile);

// 지금까지 쓰였던 메모리 해제
if (pBitmapBuf)
{
  delete pBitmapBuf;
  pBitmapBuf = NULL;
}

if (Bitmap.bmpPalette) delete Bitmap.bmpPalette;
if (Bitmap.bmpRawData) delete Bitmap.bmpRawData;


return 0;
}

//------------------------------------------------------------------------------------
// 버퍼에서 file header 부분을 읽어와 구조체에 저장
//------------------------------------------------------------------------------------

int get_bmpFileHeader(unsigned char* bmpBuf, MY_BITMAP* pBitmap)
{
unsigned int len = sizeof(FILE_HEADER);

if (!bmpBuf || !pBitmap) return 0;

// bmpBuf 에서부터 len 만큼을 구조체의 bmpfileHeader 에 memory copy
memcpy(&pBitmap->bmpFileHeader, bmpBuf, len);

return 1;
}

//------------------------------------------------------------------------------------
// 버퍼에서 info header 부분을 읽어와 구조체에 저장
//------------------------------------------------------------------------------------

int get_bmpInfoHeader(unsigned char* bmpBuf, MY_BITMAP* pBitmap)
{
unsigned int len = sizeof(INFO_HEADER);
unsigned int start = sizeof(FILE_HEADER);

if (!bmpBuf || !pBitmap) return 0;

// bmpBuf 에서부터 len 만큼을 구조체의 bmpInfoHeader 에 memory copy
memcpy(&pBitmap->bmpInfoHeader, bmpBuf + start, len);

return 1;
}

//------------------------------------------------------------------------------------
// 버퍼에서 palette 부분을 읽어와 구조체에 저장
//------------------------------------------------------------------------------------

int get_bmpPalette(unsigned char* bmpBuf, MY_BITMAP* pBitmap)
{
unsigned int nPaletteEntry;
unsigned int start = sizeof(FILE_HEADER) + sizeof(INFO_HEADER);
unsigned int len;

// 몇 비트 비트맵인지
switch (pBitmap->bmpInfoHeader.biBitCount)
{
  case 24: // true 칼라
  nPaletteEntry = 0;
  break;
  case 8:  // 256 칼라
  nPaletteEntry = 256;
  break;
  case 4:  // 16 칼라
  nPaletteEntry = 16;
  break;
  case 1:  // 2 칼라
  nPaletteEntry = 2;
  break;
  default:
  return 0;
}

// true 칼라면 팔레트를 사용하지 않는다
if (nPaletteEntry == 0)
{
  pBitmap->bmpPalette = NULL;
  return 1;
}
else
{
  // 메모리 할당
  pBitmap->bmpPalette = new unsigned char[nPaletteEntry * 3];


  len = nPaletteEntry * 3;
  memcpy(pBitmap->bmpPalette, bmpBuf + start, len); // 메모리 카피
}

return 1;
}

//------------------------------------------------------------------------------------
// 버퍼에서 raw data 부분을 읽어와 구조체에 저장
//------------------------------------------------------------------------------------

int get_bmpRawData(unsigned char* bmpBuf, MY_BITMAP* pBitmap)
{
unsigned int len;
unsigned int start = pBitmap->bmpFileHeader.bfOffBits;

//읽어올 크기 정하기
len = pBitmap->bmpFileHeader.bfSize - start;


// 읽어올 크기만큼 메모리 할당
pBitmap->bmpRawData = new unsigned char[len];

// 메모리 카피
memcpy(pBitmap->bmpRawData, bmpBuf + start, len);

return 1;
}

//------------------------------------------------------------------------------------
// 구조체의 내용을 화면에 출력
//------------------------------------------------------------------------------------

int write_bmpInfo(MY_BITMAP* pBitmap)
{
printf("\n");
printf("   bftype : %c%c\n", pBitmap->bmpFileHeader.bfType & 0x00ff,  pBitmap->bmpFileHeader.bfType >> 8);
printf("     Size : %d [Byte]\n", pBitmap->bmpFileHeader.bfSize);
printf("    Width : %d\n", pBitmap->bmpInfoHeader.biWidth);
printf("   Height : %d\n", pBitmap->bmpInfoHeader.biHeight);
printf("Bit Count : %d\n", pBitmap->bmpInfoHeader.biBitCount);
printf("Image Data:");

for (int i = 0; i < 200; i++)
{
  if (i % 20 == 0) printf("\n");
  printf("%2x ", pBitmap->bmpRawData[i]);
}
printf("\n...............\n");

return 1;
}

//------------------------------------------------------------------------------------
// 구조체의 내용을 bmpBuf 에 하나로 묶음
// 파일에 쓰는거는 메인함수에 있습니다.
//------------------------------------------------------------------------------------

int make_bmp(unsigned char* bmpBuf, MY_BITMAP* pBitmap)
{
unsigned int nSize = pBitmap->bmpFileHeader.bfSize;
unsigned int len, start;

// file header
start = 0;
len = sizeof(FILE_HEADER);
memcpy(bmpBuf + start, &pBitmap->bmpFileHeader, len);

// info header
start += len;
len = sizeof(INFO_HEADER);
memcpy(bmpBuf + start, &pBitmap->bmpInfoHeader, len);

// 팔렛트가 존재하면 팔렛트의 내용도 써주어야 한다
if (pBitmap->bmpPalette != NULL)
{
  start += len;
  len = pBitmap->bmpFileHeader.bfOffBits - start;
  memcpy(bmpBuf + start, pBitmap->bmpPalette, len);
}

// raw data
start += len;
len = nSize - start;
memcpy(bmpBuf + start, pBitmap->bmpRawData, len);

return 1;
}


'Projects > CoVNC' 카테고리의 다른 글

DIB를 DDB로 변환  (0) 2007.02.05
BMP를 DDB로 변환  (0) 2007.02.01
CF_BITMAP 사용하기  (0) 2007.01.30
클립보드에서 이미지 읽기  (0) 2007.01.25
Swap16IfLE() 매크로  (0) 2007.01.24