首页
社区
课程
招聘
[原创]前几天写的一个位图转点阵的小工具
发表于: 2012-8-23 22:43 11252

[原创]前几天写的一个位图转点阵的小工具

2012-8-23 22:43
11252
前段时间一朋友要为女朋友写个七夕礼物,感觉字符模式太单调了,但是汇编对图形的支持不是不够方便,就写了个位图到点阵的转换工具,这样就可以用汇编做出"丰富多彩"的界面了.虽然dos下的东西有点过时了,或许有朋友需要也说不一定,就发上来了.Win-tc下通过.代码如下:
#include <io.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#ifndef __STDIO_DEF_/*区分VC和TC,因为是在VC上调试的*/
typedef  short bit16;
typedef  unsigned int   bit32 ;
#else
typedef int bit16  ;
typedef unsigned long bit32  ;
#endif
char *formatstring;
int file;
int bitget(char *bit,int i,int j)
{
    bit32  num;
    bit32 num2=0xffffffff;
    *(&num)=*(bit32 *)bit;/*不使用指针来赋值的话,*/
                /*vc使用movzx来把字节扩展到32位,那么在24位真彩模式下会有问题*/
    num>>=i%8;/*把数组当做一个bitset对象*/  
    num2>>=(32-j);/*只对比这么多位*/
    num&=num2;
    return num==num2?0:1;/*白色为0*/
}
void bmptochars(char *chars,char *dots,int count,int bitofdot)
{
    int i,j,k=(8/bitofdot)?(8/bitofdot-1):0;/*区分位图是1,4,8,24模式*/
    int l,num=(count-1)/8+1;/*num是需要多少字节来存放转换后的数据*/
    char Buffer[100];/*字符串缓冲区*/
    memset(dots,0,num+1);/*清零*/
    for(i=0,j=k;i<count;++i,--j)
    {
        if(j<0)j=k;
        if(bitget(chars+i*bitofdot/8,j*bitofdot,bitofdot))
            dots[i/8]|=(unsigned char)1<<i%8;
    }/*一次性把这一行都转换掉*/
    for(l=0;l<num;++l)
    {
        if(dots[l]==0)write(file,"0,",2);
        else
        write(file,Buffer,sprintf(Buffer,formatstring,dots[l]&255));
    }/*写入文件*/
    return ;
}

int main(int argc,char *argv[])
{
    bit32 Width,Height,bitoff;/*宽,高,位图文件的位图数据偏移*/
     bit16 fp,i,j,m,bitofdot,cflag=0;
     /*fp 位图文件句柄,bitofdot 位图中多少个位表示一个点,cflag 是否翻译成c格式*/
    char Buffer[200];/*文件名等缓冲区*/
    char *bit,*dots;/*用于保存从位图文件中读取的数据和转换后的数据,后面会为其分配内存*/
    printf("\t\t\t    www.asmedu.net\n\t\t\tCopyright (C) 2012-2012.\n");
     switch(argc)
     {
        case 1:printf("Input the file name:\n");
                scanf("%s",Buffer);
                break;
        case 2:
                if(!memicmp(argv[1],"/?",2))
                {
                    printf("bmptodot [/c] filename.bmp\n[/c] use the c language format\n%s%s",
                    "use the default assembly langusge format\n",
                    "the bitmap must height=width,background must white\n");
                    return 0;
                }
                else 
                    strcpy(Buffer,argv[1]);
                break;
        case 3:
        {
            if(!memicmp(argv[1],"/c",2))cflag=i=2;
            else if(!memicmp(argv[2],"/c",2))cflag=i=1;
            else {printf("error cmdline!\n");return -1;}
            strcpy(Buffer,argv[i]);
            break;
        }
        default:return -1;
    }/*处理命令行参数*/
    if(cflag)formatstring="%#x,";
    else formatstring="0%xh,";/*指定翻译格式*/
    if ((fp = open(Buffer, O_RDONLY|O_BINARY)) == -1)    /* 打开文件 */
    {
         printf("Can't open the file!\n");
        return -1;
    }/*文件打开失败的处理*/
    lseek(fp,10L,SEEK_SET);
    read(fp,&bitoff,4);/*得到数据区相对与BMP文件的开始位置偏移*/
    lseek(fp,18L,SEEK_SET);                                /* 读取文件宽高     */
    read(fp,&Width,4);/*宽(X)*/
    read(fp,&Height,4);/*高(Y)*/
    lseek(fp,0x1CL,SEEK_SET);
    read(fp,&bitofdot,2);/*每个像素需要多少位来存储*/
    Width*=bitofdot;/*得到图像每行需要的位数*/
    m=j=(Width-1)/8+1;/*得到字节数*/
    j=j%4?(j+4-j%4):j;/*补充为4字节倍数*/
    m=j-m;/*得到填补字节数*/
    bit=(char *)malloc(j+4);
    dots=(char*)malloc((Height-1)/8+2);/*分配内存*/
    if(!bit||!dots)exit(-1);
    memset(bit,0,j+4);
    strcpy(strrchr(Buffer,'.'),".txt");
    file=creat(Buffer,S_IWRITE);/*生成转换后的文件和位图文件同名*/
    if(file == -1)
    {
        printf("Can't create file!\n");
        return -1;
    }
    bitoff+=Height*j;/*得到文件的位图数据区最后偏移*/
    *strrchr(Buffer,'.')='\0';
    Buffer[7]='\0';/*如果文件名超出7个字符就截断,主要是想把一个缓冲区当两个用*/
    if(cflag)
        write(file,Buffer+8,sprintf(Buffer+8,"char bmp%s%d[]={ \n",Buffer,Height));
    else
        write(file,Buffer+8,sprintf(Buffer+8,"bmp%s%d \n",Buffer,Height));
    for (i = 1; i <=Height; ++i)
    {
         lseek(fp,bitoff-(bit32)i*j, SEEK_SET);     /*需要倒着读        */
         read(fp, bit,j);    /* 一次读取一行*/
         if(cflag)/*判断翻译格式*/
         bmptochars(bit,dots,Height,bitofdot);
         else
         {
              write(file,"db ",3);  
             bmptochars(bit,dots,Height,bitofdot);
             lseek(file,-1,SEEK_CUR);
        }
         write(file,"\n",1);/*换行*/
    }
    if(cflag)write(file,"};\n",4);
    close(fp);
    close(file);/*关闭文件*/
    return 0;
}

它有个/c参数,可以生成c格式的数组.
c的显示函数(改自Win-tc的 点阵字模工具编程辅助效果示例):
void drawmat(char *mat,int matsize,int x,int y,int color)
/*依次:字模指针、点阵大小、起始坐标(x,y)、颜色*/
{
  int i, j, k, n;
  n = (matsize - 1) / 8 + 1;
  for(j = 0; j < matsize; j++)
    for(i = 0; i < n; i++)
      for(k = 0;k < 8; k++)
        if(mat[j * n + i] & (1<<k))  /*测试为1的位则显示*/
          putpixel(x + i * 8 + k, y + j, color);
}

汇编版的显示子程序,由Me.song先生所写:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;按位写像素子程序(单图显示)
;
;参数:ds=DG  ds:bp=指定行数  ds:di=指定列数
;     al=颜色  cx=图像长度
;
;返回参数:si=下一图的首字节  bp=下一图行数  di=下一图列数
;
;
;功能:根据单色位图翻译工具生成的数据。来计算坐标并写像素。
;
tim    :push cx
     push dx
     push ax
     
     mov bx,ds:[bp]  
     mov ax,640
     mul bx
     add ax,word ptr ds:[di]
     adc dx,0    ;计算结果DX为页数,ax为偏移地址
     
     mov di,ax
     
     xor bx,bx
     mov ax,4f05h
     int 10h    ;设置页数
     
     add bp,2
     add di,2    ;指向下一图行列
     
     mov ax,cx
     mov cl,8
     div cl
     xor ah,ah
     mov bx,ax
     pop ax      ;计算字节数
     
tim1  :push cx
     mov cx,bx
     push bx
     xor bx,bx    ;初始化辅助偏移
     
tim2  :push cx
     mov cx,8    ;位数
     
     mov ah,[si]  ;取字节
     
     
tim3  :rcl ah,1
     jnc zero    ;检测每位
     
     mov es:[bx+di],al  ;当为1时,送入字节
     
zero  :inc bx      ;指向下一像素点
     loop tim3
     
     inc si      ;指向下一字节
     pop cx
     loop tim2
     
     
     pop bx
     
     add di,640    ;指向下一行
     pop cx
     loop tim1
     
     pop dx
     pop cx
     ret
     
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

希望对大家有用.

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (7)
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
高。。不错的……
2012-8-23 23:29
0
雪    币: 292
活跃值: (153)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
这个   BMPTODOT.EXE    是杂用的。。。。。
2012-8-23 23:55
0
雪    币: 1242
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
那个EXE好像不能在win64上运行哈
2012-8-24 09:30
0
雪    币: 324
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
确实想用汇编写界面。
谢谢LZ!~
2012-8-24 09:50
0
雪    币: 107
活跃值: (326)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
难道真是一行一行代码敲出来的??????????????????
2012-8-24 10:11
0
雪    币: 31
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
把代码用vc6编译一遍就可以在win7下运行了。压缩包里的那个exe是Win-tc编译的,是16位的。
它支持命令行参数,可以把文件名传进去,或者运行它再把文件名输入进去。/c命令行参数是生成c语言格式的数组,不加就转换成汇编格式的。
把那个批处理和exe再加上一些位图文件放到一个文件夹中,进行批量转换的,注意要以白色为背景,宽=高(如果需要,把位图文件18L处的那个双字做bmptochars第三个参数即可变成宽!=高)。
2012-8-24 10:13
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习了,真是辛苦
2012-8-24 18:08
0
游客
登录 | 注册 方可回帖
返回
//