IppDib 클래스의 파일 입출력 함수들의 실제 구현은 소스 4-4에 나타내었다. BMP 파일을 불러오는 방법은 3.4절 BmpShow 프로그램에서 자세히 설명하였으므로 여기서는 설명을 생략한다. LoadBMP 함수를 제대로 이해하면 SaveBMP 함수 또한 어렵지 않을 것이다.
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') BOOL IppDib::Load(const char* filename) { const char* ext = strrchr(filename, '.'); if (!_strcmpi(ext, ".bmp")) return LoadBMP(filename); else return FALSE; } BOOL IppDib::Save(const char* filename) { const char* ext = strrchr(filename, '.'); if (!_strcmpi(ext, ".bmp")) return SaveBMP(filename); else return FALSE; } BOOL IppDib::LoadBMP(const char* filename) { FILE* fp = NULL; fopen_s(&fp, filename, "rb"); if (!fp) return false; BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih; // BITMAPFILEHEADER 읽기 if (fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, fp) != 1) { fclose(fp); return false; } // BMP 파일임을 나타내는 "BM" 마커가 있는지 확인 if (bmfh.bfType != DIB_HEADER_MARKER) { fclose(fp); return false; } // BITMAPINFOHEADER 읽기 if (fread(&bmih, sizeof(BITMAPINFOHEADER), 1, fp) != 1) { fclose(fp); return false; } m_nWidth = bmih.biWidth; m_nHeight = bmih.biHeight; m_nBitCount = bmih.biBitCount; // 픽셀 데이터 공간 계산 DWORD dwWidthStep = (DWORD)((m_nWidth * m_nBitCount / 8 + 3) & ~3); DWORD dwSizeImage = m_nHeight * dwWidthStep; if (m_nBitCount == 24) m_nDibSize = sizeof(BITMAPINFOHEADER) + dwSizeImage; else m_nDibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << m_nBitCount) + dwSizeImage; // Packed-DIB 저장할 메모리 공간 동적 할당 if (m_pDib) DestroyBitmap(); m_pDib = new BYTE[m_nDibSize]; if (m_pDib == NULL) { fclose(fp); return FALSE; } // 파일로부터 Packed-DIB 크기만큼을 읽기 fseek(fp, sizeof(BITMAPFILEHEADER), SEEK_SET); if (fread(m_pDib, sizeof(BYTE), m_nDibSize, fp) != m_nDibSize) { delete[] m_pDib; m_pDib = NULL; fclose(fp); return FALSE; } // 파일 닫기 fclose(fp); return TRUE; } BOOL IppDib::SaveBMP(const char* filename) { if (!IsValid()) return FALSE; FILE* fp; fopen_s(&fp, filename, "wb"); if (!fp) return FALSE; BITMAPFILEHEADER bmfh; bmfh.bfType = DIB_HEADER_MARKER; bmfh.bfSize = (DWORD)sizeof(BITMAPFILEHEADER) + m_nDibSize; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * GetPaletteNums())); fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, fp); fwrite(GetBitmapInfoAddr(), m_nDibSize, 1, fp); fclose(fp); return TRUE; }