• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

windows小程序-用文字堆垒单色BMP位图

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
好久没更新了……贴一个最近做的图片转文字的大小东西吧=w=
#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单色位图转换成文字。。。

例如做一个位图,在位图上画一个云字,可以产生下面的效果:

     云云云云云云云云云云云云云云云云云云云云云云云            
     云云云云云云云云云云云云云云云云云云云云云云云            
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
  云云云云云云云云云云云云云云云云云云云云云云云云云云云云云         
  云云云云云云云云云云云云云云云云云云云云云云云云云云云云云         
             云云云                        
            云云云                         
            云云云                         
           云云云                          
           云云云       云                  
          云云云       云云云                 
          云云云        云云云                
         云云云         云云云                
        云云云           云云云               
        云云云            云云云              
       云云云             云云云云             
      云云云               云云云             
     云云云云                云云云            
    云云云云云云云云云云云云云云云云云云云云云云云云云           
     云云云云云云云云云云云云         云云云           
     云                     云云云          
                            云           

也就是没事随便玩玩~




鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
使用mpvue开发小程序教程(一)发布时间:2022-07-18
下一篇:
微信小程序数据分析之自定义分析发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap