nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

MFCでBitmapファイルを開く(BITMAPINFOHEADER, BITMAPINFOHEADERを取得) [C++][MFC]

はじめに

MFCでBitmapファイルを開く方法を下記に記載します。

<使用例>

f:id:nprogram:20180501002747p:plain

ソースコードファイルの記載は以下のとおりです。クラスではなく、ユーティリティ関数として作成しました。 [BitmapUtil.cpp]

#include "stdafx.h"
#include "BitmapUtil.h"

bool LoadBitmapFile(CString fileName , BITMAPFILEHEADER &bmpHeader, BITMAPINFOHEADER &bmpInfo, BYTE** bitmapImageBuffer, int &bitmapImageBufferSize) {


    HANDLE file = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ,
        NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

    DWORD bytesread;

    // read BITMAPFILEHEADER
    if (ReadFile(file, &bmpHeader, sizeof(BITMAPFILEHEADER), &bytesread, NULL) == false)
    {
        CloseHandle(file);
        return false;
    }

    // read BITMAPINFOHEADER
    if (ReadFile(file, &bmpInfo, sizeof(BITMAPINFOHEADER),
        &bytesread, NULL) == false)
    {
        CloseHandle(file);
        return false;
    }

    // First check if the file is actually a bitmap:
    if (bmpHeader.bfType != 'MB')
    {
        CloseHandle(file);
        return false;
    }

    // check if it's uncompressed
    if (bmpInfo.biCompression != BI_RGB)
    {
        CloseHandle(file);
        return false;
    }

    // check if it's 24bit
    if (bmpInfo.biBitCount != 24)
    {
        CloseHandle(file);
        return false;
    }
    int width = bmpInfo.biWidth;
    int height = abs(bmpInfo.biHeight);
    bitmapImageBufferSize = bmpHeader.bfSize - bmpHeader.bfOffBits;

    *bitmapImageBuffer = new BYTE[bitmapImageBufferSize];

    if (ReadFile(file, *bitmapImageBuffer, bitmapImageBufferSize, &bytesread, NULL) == false)
    {
        delete[] *bitmapImageBuffer;
        CloseHandle(file);
        return false;
    }

    CloseHandle(file);
    return true;
}

ヘッダファイルの記載は以下のとおりです。 [BitmapUtil.h]

#pragma once
bool LoadBitmapFile(CString fileName, BITMAPFILEHEADER &bmpHeader, BITMAPINFOHEADER &bmpInfo, BYTE** bitmapImageBuffer, int &size);

利用側のコードは以下のとおりです。 ここでは、ボタン押下時のイベントハンドラ処理に記載しました。 [MFCApplication1Dlg.cpp]

void CMFCApplication1Dlg::OnBnClickedButton1()
{
    // TODO: ここにコントロール通知ハンドラー コードを追加します。
    //BMP画像をファイルから読み込む

    CString         filter("BMP Files (*.bmp)|*.bmp||");
    CFileDialog     selDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, filter);

    if (selDlg.DoModal() == IDOK)
    {
        m_fileNameBitmap = selDlg.GetPathName();


        BITMAPFILEHEADER bmpHeader;
        BITMAPINFOHEADER bmpInfo;
        BYTE* bitmapImageBuffer = nullptr;
        int size = 0;

        bool result = LoadBitmapFile(m_fileNameBitmap, bmpHeader, bmpInfo, &bitmapImageBuffer, size);

        std::string strWidth = std::to_string(bmpInfo.biWidth);
        std::string strHeight = std::to_string(bmpInfo.biHeight);

        CString cstrWidth(strWidth.c_str());
        CString cstrHeight(strHeight.c_str());
        m_width = cstrWidth;
        m_height = cstrHeight;

        m_BitmapImageBufferSize = size;


        UpdateData(FALSE);
    }

}

参考サイト

なお、以下のサイト参考にさせていただきました。 tipsandtricks.runicsoft.com