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值是一样的