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单色位图转换成文字。。。
例如做一个位图,在位图上画一个云字,可以产生下面的效果:
云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云云云云云云云云云云云云云云云云云云
云云云
云云云
云云云
云云云
云云云 云
云云云 云云云
云云云 云云云
云云云 云云云
云云云 云云云
云云云 云云云
云云云 云云云云
云云云 云云云
云云云云 云云云
云云云云云云云云云云云云云云云云云云云云云云云云云
云云云云云云云云云云云云 云云云
云 云云云
云
也就是没事随便玩玩~
浙公网安备 33010602011771号