windows小程序-用文字堆垒单色BMP位图
#ifndef UNICODE #define UNICODE #endif #ifndef _UNICODE //#define _UNICODE #endif //#include <stdio.h> #include <windows.h> #include <assert.h> #include <malloc.h> LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) { static HWND hwndText = NULL; static HWND hwndButton = NULL; static WCHAR *pcnChar = NULL; switch(msg) { case WM_CREATE: pcnChar = (WCHAR*)((LPCREATESTRUCT)lParam)->lpCreateParams; hwndText = CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER, 1, 1, 60, 60, hwnd, (HMENU)0, ((LPCREATESTRUCT)(lParam))->hInstance, NULL); hwndButton = CreateWindow(L"BUTTON", L"OK", WS_CHILD | WS_VISIBLE | WS_BORDER, 65, 1, 60, 60, hwnd, (HMENU)1, ((LPCREATESTRUCT)(lParam))->hInstance, NULL); break; case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 1){ if(!GetWindowText(hwndText, pcnChar, 2) || *pcnChar < 0xFF){ MessageBox(0,L"请输入一个汉字!",0,0); break; } DestroyWindow(hwnd); } break; case WM_DESTROY: if(!*pcnChar && *pcnChar < 0xFF) { MessageBox(0,L"获取汉字失败,现在退出",0,0); exit(0); } PostQuitMessage(0); //GetWindowText(hwndText, pcnChar, 1); break; } return DefWindowProc(hwnd,msg,wParam,lParam); } typedef struct{ BYTE *byte_ptr; int bit_pointer; }BitPointer; void BitPointerInc(BitPointer *o) { assert(0 <= o->bit_pointer && o->bit_pointer < 8); if(o->bit_pointer == 7){ o->bit_pointer = 0; o->byte_ptr += 1; }else{ o->bit_pointer += 1; } } void SetBit(BitPointer *o) { assert(0 <= o->bit_pointer && o->bit_pointer < 8); *(o->byte_ptr) |= (1 << (7 - (o->bit_pointer))); //这里要注意比特的顺序…… } int GetBit(BitPointer *o) { assert(0 <= o->bit_pointer && o->bit_pointer < 8); return (*(o->byte_ptr)) & (1 << (7 - (o->bit_pointer))); //这里要注意比特的顺序…… } void JmpByte(BitPointer *o) { o->byte_ptr += 1; o->bit_pointer = 0; } int CountBits(BitPointer *o,BYTE *start) { return ((o->byte_ptr) - start) * 8 + (o->bit_pointer); } static WCHAR g_szClassName[] = L"MyWindowClass"; static HINSTANCE g_hInstance; int ReadBitmapData(BYTE *buffer,DWORD size,int nWidth,int nHeight,WCHAR **rslt) { DWORD bitLineLength = (nWidth % 32 == 0)? nWidth: 32 - nWidth % 32 + nWidth; WCHAR **bitLine = NULL; int i,j; bitLine = (WCHAR**)malloc(nHeight * sizeof(WCHAR*)); BitPointer ptr = { buffer, 0 }; for(i = nHeight - 1; i >= 0; --i) { bitLine[i] = (WCHAR*)malloc(nWidth * sizeof(WCHAR)); ZeroMemory(bitLine[i],nWidth * sizeof(WCHAR)); for(j = 0; j < nWidth; ++j,BitPointerInc(&ptr)) { bitLine[i][j] = !GetBit(&ptr); } while(CountBits(&ptr, buffer) % bitLineLength != 0) { JmpByte(&ptr); } } static WCHAR cnChar[2] = L"\0"; HWND hwnd = CreateWindow( g_szClassName, L"输入一个汉字", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 100, NULL, NULL, g_hInstance, cnChar); ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,NULL,0,0)){ TranslateMessage(&msg); DispatchMessage(&msg); } if(*cnChar == L'\0') { MessageBox(0,L"程序出错,请向程序作者报告这个错误",0,0); } for(i = 0; i < nHeight; ++i) { bitLine[i] = (WCHAR*)realloc(bitLine[i],(nWidth+2)*sizeof(WCHAR)); bitLine[i][nWidth] = L'\r'; bitLine[i][nWidth+1] = L'\n'; for(j = 0; j < nWidth; ++j) { if(bitLine[i][j])bitLine[i][j] = *cnChar; else bitLine[i][j] = L' '; } if(i > 0){ bitLine[0] = (WCHAR*)realloc(bitLine[0],(i + 1)*(2 + nWidth) * sizeof(WCHAR)); memcpy(bitLine[0] + ((i) * (2 + nWidth)),bitLine[i],(2 + nWidth) * sizeof(WCHAR)); free(bitLine[i]); } } int nRslt = 1 + (i)*(2 + nWidth); bitLine[0] = (WCHAR*)realloc(bitLine[0],nRslt * sizeof(WCHAR)); *(bitLine[0] + (i)*(2 + nWidth)) = 0;//terminate the unicode string #ifdef _DEBUG MessageBox(0,bitLine[0],0,0); #endif *rslt = bitLine[0]; free(bitLine); return nRslt; } void Process(PWSTR filename) { //MessageBox(0,filename,0,0); HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0); assert(hFile != INVALID_HANDLE_VALUE); static BYTE buffer[8192]; ZeroMemory(buffer,sizeof buffer); DWORD dwRead; assert(ReadFile(hFile, buffer, 2, &dwRead, NULL)); assert(2 == dwRead); if(!!strcmp("BM",(const char*)buffer)){ MessageBox(0,L"不是有效的BMP文件",0,0); exit(0); } assert(SetFilePointer(hFile,0x0E,0,FILE_BEGIN)); //跳过图像文件头 //读图像信息头的第一个项,Bitmap Header Size,占2个双字 assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead && 4 == sizeof(DWORD)); //************************************************* //测试计算机的字节序,暂时只支持小端对齐 { BYTE edian_test[4] = { 0xAa, 0xBb, 0xCc, 0xDd }; if((DWORD)0xDdCcBbAa != *(DWORD*)edian_test) { MessageBox(0,L"程序暂不支持大端的处理器\n" L"您可能在某些处理器上运行WinCE\n" L"或在ARM处理器上运行桌面版的Windows 8\n" L"本程序暂不处理这些情况,程序现在退出", L"程序的版本需要为此计算机更新",0); exit(0); } } //**************************************************/ // // if(*(DWORD*)buffer != 0x28) //图像信息头的大小应为0x28 { MessageBox(0,L"不认识这个类型的BMP文件," L"如无特别原因请用Windows自带画图程序生成单色BMP文件",0,0); exit(0); } assert(SetFilePointer(hFile,0x02,0,FILE_BEGIN)); assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead); if(GetFileSize(hFile,NULL) != *(DWORD*)buffer) { wsprintf((PWSTR)buffer,L"BMP文件具有错误的文件大小,应为%d字节,实际为%d字节", *(DWORD*)buffer,GetFileSize(hFile,NULL)); MessageBox(0,(PWSTR)buffer,L"图像文件破损",0); exit(0); } DWORD dwFileSize = *(DWORD*)buffer; assert(SetFilePointer(hFile,0x1C,0,FILE_BEGIN)); assert(ReadFile(hFile, buffer, 2, &dwRead, NULL)); assert(2 == dwRead); if(*(WORD*)buffer != 0x01) //mono BMP { MessageBox(0,L"这是一个正确的BMP文件,但本程序用于将单色BMP转为文字" L"如无特别原因请用Windows自带画图程序生成单色BMP文件\n" L"或使用Windows自带画图程序打开此图片后重新另存为单色BMP",0,0); exit(0); } assert(ReadFile(hFile, buffer, 2, &dwRead, NULL)); assert(2 == dwRead); if(*(WORD*)buffer != 0){ MessageBox(0,L"这是一个正确的单色BMP文件\n" L"但本程序暂时不处理此图片使用的RLE压缩方式\n" L"如无特别原因请用Windows自带画图程序生成单色BMP文件\n" L"或使用Windows自带画图程序打开此图片后重新另存为单色BMP", L"需要更新程序版本来支持此图片",0); exit(0); } assert(SetFilePointer(hFile,0x12,0,FILE_BEGIN)); DWORD nWidth,nHeight; assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead); nWidth = *(DWORD*)buffer; assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead); nHeight = *(DWORD*)buffer; assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead); if(0x00010001 != *(DWORD*)buffer) //小端字节序 { MessageBox(0,L"位面数和像素占用位数应为1", L"破损的单色BMP图片",0); exit(0); } DWORD dwStartOffset = 0; assert(SetFilePointer(hFile,0x0A,0,FILE_BEGIN)); assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead); dwStartOffset = *(DWORD*)buffer; assert(SetFilePointer(hFile,0x22,0,FILE_BEGIN)); assert(ReadFile(hFile, buffer, 4, &dwRead, NULL)); assert(4 == dwRead); DWORD dwBitmapDataSize = *(DWORD*)buffer; if(dwBitmapDataSize != dwFileSize - dwStartOffset) { MessageBox(0,L"BMP文件破损,数据不一致",0,0); exit(0); } assert(SetFilePointer(hFile,dwStartOffset,0,FILE_BEGIN)); BYTE *dataSpace = (BYTE*)malloc(dwBitmapDataSize); assert(dataSpace); assert(ReadFile(hFile, dataSpace, dwBitmapDataSize, &dwRead, NULL)); assert(dwBitmapDataSize == dwRead); WCHAR *rslt = NULL; int nRslt = ReadBitmapData(dataSpace,dwBitmapDataSize,nWidth,nHeight,&rslt); free(dataSpace); dataSpace = NULL; HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE,nRslt * sizeof(WCHAR)); void *p = GlobalLock(gData); assert(p); memcpy(p,rslt,nRslt * sizeof(WCHAR)); OpenClipboard(NULL); EmptyClipboard(); SetClipboardData(CF_UNICODETEXT,gData); CloseClipboard(); GlobalUnlock(gData); GlobalFree(gData); MessageBox(0,L"结果已保存到剪切板,现在可以把结果黏贴到任意位置了",L"",0); } int WINAPI WinMain(HINSTANCE hinst,HINSTANCE hpreInst,PSTR lpCmdLine,int nShow) { g_hInstance = hinst; OPENFILENAME ofn; WCHAR szFileName[MAX_PATH] = L""; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.lpstrFilter = L"Text Files (*.bmp)\0*.bmp\0All Files (*.*)\0*.*\0\0"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = L"bmp"; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(!GetOpenFileName(&ofn)){ MessageBox(0,L"查找文件失败",0,0); return 0; } WNDCLASS WndClass = {0}; WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); WndClass.lpfnWndProc = WndProc; WndClass.lpszClassName = g_szClassName; if(!RegisterClass(&WndClass)) { MessageBox(0, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL); return 0; } Process(szFileName); return 0; }
我把它叫做bmp-to-text.c程序呵呵~
gcc -o b2t bmp-to-text.c -finput-charset=gbk -mwindows
把BMP单色位图转换成文字。。。
例如做一个位图,在位图上画一个云字,可以产生下面的效果:
云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云云云云云云云云云云云云云云云云云云
云云云
云云云
云云云
云云云
云云云 云
云云云 云云云
云云云 云云云
云云云 云云云
云云云 云云云
云云云 云云云
云云云 云云云云
云云云 云云云
云云云云 云云云
云云云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云 云云云
云 云云云
云
也就是没事随便玩玩~