imread imshow 非opencv实现(完成作业的小伙伴们--)

imread imshow 非opencv实现(完成作业的小伙伴们--),第1张

 使用WinAPI 双缓冲 画图在窗口中,按Esc关闭,其他的参考官方使用键盘输入 - Win32 apps | Microsoft Docs


#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
using namespace std;

//BMP文件头、信息头等,已在windows.h中定义了
/*
typedef struct tagBITMAPFILEHEADER {            //文件头
    unsigned short      bfType;
    unsigned long       bfSize;
    unsigned short      bfReserved1;
    unsigned short      bfReserved2;
    unsigned long       bfOffBits;
} BITMAPFILEHEADER;


typedef struct tagBITMAPINFOHEADER {            //信息头
    unsigned long         biSize;
    long                  biWidth;
    long                  biHeight;
    unsigned short        biPlanes;
    unsigned short        biBitCount;
    unsigned long         biCompression;
    unsigned long         biSizeImage;
    long                  biXPelsPerMeter;
    long                  biYPelsPerMeter;
    unsigned long         biClrUsed;
    unsigned long         biClrImportant;
} BITMAPINFOHEADER;


typedef struct tagRGBQUAD {                     //颜色表
    unsigned char    rgbBlue;
    unsigned char    rgbGreen;
    unsigned char    rgbRed;
    unsigned char    rgbReserved;
} RGBQUAD;
*/
//指定文件信息头
typedef struct tagINFOHEADER {
    WORD        label;                      //标志位 0x5250
    DWORD       linesub;                    //从0开始计数
    DWORD       pixnum;                      //信息域像素数 与图像宽一致
    BYTE        datatype;                     //存储方式
    DWORD       reserve;
} INFOHEADER;
typedef struct tagPIXEL {                        //像素信息结构体
    unsigned char    B;
    unsigned char    G;
    unsigned char    R;
}PIXEL;
typedef struct tagBMP {                         //图片信息结构体
    unsigned int height;
    unsigned int width;
    unsigned short bitcount;
    PIXEL* data;
}BMP;

wchar_t* to_wchar(const char* str)                                  //宽字符转换函数工具
{
    int length = strlen(str) + 1;
    wchar_t* t = (wchar_t*)malloc(sizeof(wchar_t) * length);
    if (t != 0)
        memset(t, 0, length * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, str, strlen(str), t, length);
    return t;
}
BYTE getbit(BYTE n, int head, int bitcount)           //提取一个字节的某几位的数据
{                                                     //head为 从高位到低位数 开始的位数,bitcount为长度
    BYTE x = 0;
    int offset = 7 - head;
    for (int i = 0; i < bitcount; i++)
    {
        x += 1 << (offset - i);
    }
    return (x & n) >> (8 - head - bitcount);
}
BMP* bmpread(const char* file_path, int readtype = 1)
{
    BMP* dst = new BMP;
    FILE* fp = fopen(file_path, "rb");                              //打开文件
    if (fp == NULL)                                                 //判断文件是否成功打开
    {
        MessageBox(NULL, L"file not exist", NULL, MB_OK);
        return 0;
    }

    BITMAPFILEHEADER file_head;                                     //读取文件头
    fread(&file_head, sizeof(BITMAPFILEHEADER), 1, fp);

    if (file_head.bfType != 'MB')                                   //判断是否是bmp文件
    {
        fclose(fp);
        MessageBox(NULL, L"not bmp file", NULL, MB_OK);
        return 0;
    }

    BITMAPINFOHEADER info_head;                                    //读取信息头
    fread(&info_head, sizeof(BITMAPINFOHEADER), 1, fp);
    int height = info_head.biHeight;                               //图片信息
    int width = info_head.biWidth;
    int bitcount = info_head.biBitCount;
    int line_byte = (width * bitcount * 8 + 255) / 64 / 4 * 4;     //每行字节数,采取了更高精度的算法,当bitcount较小时不至于算错


    PIXEL* data = new PIXEL[(long long)height * (long long)width]; //像素信息
    dst->data = data;
    dst->height = height;
    dst->width = width;
    dst->bitcount = bitcount;

    //开始读像素数据
    if (bitcount <= 8)//有颜色表
    {
        //颜色表数组长度
        int quad_num = (file_head.bfOffBits - sizeof(file_head) - sizeof(info_head)) / 4;
        //创建颜色表
        RGBQUAD* color_table = new RGBQUAD[quad_num];
        //读颜色表
        fread(color_table, sizeof(RGBQUAD), quad_num, fp);

        //读数据
        BYTE bt;
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < line_byte; j++)    //一个字节一个字节读
            {
                fread(&bt, 1, 1, fp);
                for (int k = 0; k < 8 / bitcount; k++)  //一个字节内包含的信息取决于bitcount
                {
                    int sub = j * 8 / bitcount + k;     //一行一行的读,sub是一行的像素的下标,
                    if (sub + 1 > width)                //一行的像素下标大于width,也就是一行读完了
                        break;
                    BYTE t = getbit(bt, k * bitcount, bitcount);    //取一个字节内对应位数的信息,因为一个字节8位,BMP有1,4,8位的,总是能装满一个字节
                    data[i * width + sub].B = color_table[t].rgbBlue;
                    data[i * width + sub].G = color_table[t].rgbGreen;
                    data[i * width + sub].R = color_table[t].rgbRed;
                }
            }
        }

        delete[]color_table;
    }

    else//没有颜色表,真彩色图24位,直接读bgr
    {
        BYTE bt;

        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                fread(&bt, 1, 1, fp);
                data[i * width + j].B = bt;
                fread(&bt, 1, 1, fp);
                data[i * width + j].G = bt;
                fread(&bt, 1, 1, fp);
                data[i * width + j].R = bt;
            }
            fseek(fp, line_byte - width * 3, SEEK_CUR);//跳过为了补齐的空数据
        }
    }

    if (readtype == 0)
    {
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                BYTE B_ = data[i * width + j].B;
                BYTE G_ = data[i * width + j].G;
                BYTE R_ = data[i * width + j].R;
                BYTE gray_ = 0.3 * R_ + 0.59 * G_ + 0.11 * B_;
                data[i * width + j].B = data[i * width + j].G = data[i * width + j].R = gray_;
            }
        }
    }

    fclose(fp);//关闭文件
    return dst;
}

LRESULT CALLBACK winproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    //按下Esc退出 其他的参考官网
    case WM_CHAR:           
        if(wParam == 0x1B)
            PostQuitMessage(0);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return 0;
}
int WINAPI bmpshow(const char* winname, BMP src, HINSTANCE hInstance = NULL)
{

    wchar_t* WinClass = to_wchar("ImageShow_window");
    wchar_t* WinTitle = to_wchar(winname);
    WNDCLASS wc;
    wc.style = CS_VREDRAW | CS_HREDRAW | CS_BYTEALIGNWINDOW;
    wc.lpfnWndProc = winproc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_CROSS);
    wc.hbrBackground = (HBRUSH)(COLOR_GRAYTEXT);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = WinClass;

    RegisterClass(&wc);

    DWORD defstyle = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_OVERLAPPED;
    HWND hWnd = CreateWindow(
        WinClass,
        WinTitle,
        defstyle,
        CW_USEDEFAULT, CW_USEDEFAULT,
        src.width + 15, src.height + 40,   //加上了菜单栏的高度和边界的宽度
        0, 0, hInstance, 0);

    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);

    HDC hdc, memdc;
    HBITMAP bmp, oldbmp;
    int height = src.height;
    int width = src.width;
    int r, g, b, pix;
    hdc = GetDC(hWnd);
    memdc = CreateCompatibleDC(hdc);
    bmp = CreateCompatibleBitmap(hdc, width, height);
    SelectObject(memdc, bmp);

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            b = src.data[i * width + j].B;
            g = src.data[i * width + j].G;
            r = src.data[i * width + j].R;
            pix = RGB(r, g, b);
            SetPixel(memdc, j, height - i - 1, pix);
        }
    }

    BitBlt(hdc, 0, 0, width, height, memdc, 0, 0, SRCCOPY);
    ReleaseDC(hWnd, hdc);


    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

代码不完善 请多指教 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/739763.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存