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