c++使用std_image.c来加载jpg,png,gif等格式图片

#include <windows.h>
#include <tchar.h>
#include <WindowsX.h>
HINSTANCE hInst;

#pragma comment(lib,"Msimg32.lib")
extern "C"
{
    extern unsigned char *stbi_load_from_memory(unsigned char const *buffer, int len, int *x, int *y,int *comp, int req_comp);
    extern void     stbi_image_free(void *retval_from_stbi_load);
};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam);

int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR,int nCmdShow)
{
    hInst = hInstance; // Store instance handle in our global variable

    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_BACKGROUND);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName    = _T("std_image.c");
    wcex.hIconSm        = NULL;
    if(!RegisterClassEx(&wcex)) return FALSE;

    HWND hWnd = CreateWindow(_T("std_image.c"), _T("std_image.c"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    DWORD dw = GetLastError();
    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);    
    MSG msg;
    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_PAINT:
        {
            OnPaint(hWnd,wParam,lParam);
        }break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

LRESULT OnPaint(HWND hWnd,WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;            
    HDC hdc = BeginPaint(hWnd, &ps);
    HANDLE hFile = ::CreateFile(_T("test.png"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \
        FILE_ATTRIBUTE_NORMAL, NULL);
    if( hFile == INVALID_HANDLE_VALUE ) return NULL;
    DWORD dwSize = ::GetFileSize(hFile, NULL);
    if( dwSize == 0 ) return NULL;

    DWORD dwRead = 0;
    LPBYTE pData = new BYTE[ dwSize ];
    ::ReadFile( hFile, pData, dwSize, &dwRead, NULL );
    ::CloseHandle( hFile );

    if( dwRead != dwSize ) {
        delete[] pData;
        return NULL;
    }

    LPBYTE pImage = NULL;
    int x,y,n;
    pImage = stbi_load_from_memory(pData, dwSize, &x, &y, &n, 4);
    delete[] pData;
    if( !pImage ) return NULL;

    BITMAPINFO bmi;
    ::ZeroMemory(&bmi, sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = x;
    bmi.bmiHeader.biHeight = -y;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biSizeImage = x * y * 4;

    bool bAlphaChannel = false;
    LPBYTE pDest = NULL;
    HBITMAP hBitmap = ::CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pDest, NULL, 0);
    if( !hBitmap ) return NULL;

//     for( int i = 0; i < x * y; i++ ) 
//     {
//         pDest[i*4 + 3] = pImage[i*4 + 3];
//         if( pDest[i*4 + 3] < 255 )//RGBA
//         {
//             pDest[i*4] = (BYTE)(DWORD(pImage[i*4 + 2])*pImage[i*4 + 3]/255);
//             pDest[i*4 + 1] = (BYTE)(DWORD(pImage[i*4 + 1])*pImage[i*4 + 3]/255);
//             pDest[i*4 + 2] = (BYTE)(DWORD(pImage[i*4])*pImage[i*4 + 3]/255); 
//             bAlphaChannel = true;
//         }
//         else // = 255
//         {
//             pDest[i*4] = pImage[i*4 + 2];
//             pDest[i*4 + 1] = pImage[i*4 + 1];
//             pDest[i*4 + 2] = pImage[i*4]; 
//         }
// 
//         if( *(DWORD*)(&pDest[i*4]) == 0 ) {
//             pDest[i*4] = (BYTE)0;
//             pDest[i*4 + 1] = (BYTE)0;
//             pDest[i*4 + 2] = (BYTE)0; 
//             pDest[i*4 + 3] = (BYTE)0;
//             bAlphaChannel = true;
//         }
//     }

    memcpy(pDest,pImage,bmi.bmiHeader.biSizeImage);
    stbi_image_free(pImage);

    HDC hMemdc = CreateCompatibleDC(hdc);
    SelectBitmap(hMemdc,hBitmap);

    BLENDFUNCTION ftn = { 0 };
    ftn.BlendOp = AC_SRC_OVER;                                                        // 目前只能设置这个值
    ftn.AlphaFormat = AC_SRC_ALPHA;                                                      // 也只能设置这个值
    ftn.BlendFlags = 0;                                                               // 必须为0
    ftn.SourceConstantAlpha = 255;                                                    // 指定源图片的alpha

    AlphaBlend(hdc,0,0,x,y,hMemdc,0,0,x,y,ftn);
    EndPaint(hWnd, &ps);

    return 0;
}

20121030更正: 上面屏蔽代码不能使用, 以下代码替代

memcpy(pDest,pImage,bmi.bmiHeader.biSizeImage);

因为源码说明 // if you set req_comp to 4, you will always get RGBA output, 所以我应该将其转换成位图的存储格式BGRA, 上次没有发现问题, 原因应该是测试的图片是灰度图片, RGB值是一样的



posted @ 2012-09-25 12:04  likebeta  阅读(15403)  评论(0编辑  收藏  举报