解码多页旋转tif.zip






2.88/5 (3投票s)
多页旋转tif.zip 的解码和编码
引言
此源代码演示了如何从一个由许多单色位图组成的包中随机访问特定位图。
附件中的演示包(decode\alphabet.zip) 由26个单色位图文件(6148字节)组成,打包后为5974字节,压缩后为3918字节。
而此源代码可以在不解压缩包文件的情况下,直接访问其中一个、几个或全部。
由于我们用纯C语言编写,它可以在其他平台(单片机、小端序或大端序)上运行。
最初,它是为单片机编写的。参考为什么需要从由许多位图组成的包中随机访问特定bmp。
源代码(MultiPage_tif_decode.c)已通过borland c 4.0、visual c 6.0、tinycc 0.9、armCC 5.0,甚至keil c51 7.5进行了测试!是的,keil c51.exe,7.5版本,没有错误。
它已被编译成MultiPage_tif_decode.dll,仅4k字节。代码非常小。
Using the Code
1. MultiPage_tif_decode.dll
它可以由一个C文件(decode\multiPage_tif_decode.c)编译。文件开头有关于如何从C编译为DLL的说明。
用户也可以打开vc6项目(decode\vc6.dsw)进行编译。
此DLL导出3个函数
1.1. int init_tif_fail(char* file_name, unsigned int* p_bmp_cnt);
这是一个构造函数,读取用户的tif.zip的zip_comment,并返回其中的页数cnt
。
1.2. int fini_tif(void);
这是一个析构函数。
1.3. int tif_get_page_fail(int page_enum, short*p_w,*p_h,*p_rot, long* p_img_ofs,* p_img_byte_cnt, int* p_page_name_leng, ...);
它获取一页的所有信息。在读出img_content
之后,用户可以对其进行任何其他处理,例如旋转、在LCD上显示、保存到磁盘等。
2. DLL使用演示
演示是multiPage_rotate_tif_decode.exe。它可以由一个C文件(decode\multiPage_rotate_tif_decode.c)编译。文件开头有关于如何从C编译为EXE的说明。
用户也可以打开vc6项目(decode\vc6.dsw)进行编译。
2.1. 显示所有bmp
在multiPage_rotate_tif_decode.c\WinMain()中
init_tif_fail(file_name,&tif_max_page);
for(i=0;i<tif_max_page;i++)
{tif_get_page_fail(i,
&(p_page->img_width), &(p_page->img_height), &(p_page->rot),
&(p_page->tif_ofs), &(p_page->tif_size), page_name_leng, str_tif_content, g_tif_name);
...
CreateBitmap(p_page->height,p_page->width,1,1, str_bmp_content);
}
fini_tif()
2.2. 处理菜单
保存1个bmp
"unzip 1...
"项,调用multiPage_rotate_tif_decode.c\int <a name="get_1_bmp_fail">get_1_bmp_fail</a>(unsigned int i)
if((ret=(tif_get_page_fail(i,
&(p_page->img_width),&(p_page->img_height),&(p_page->rot),
&(p_page->tif_ofs),&(p_page->tif_size), &page_name_leng, str_tif_content,g_tif_name
)) )!=0)
{;}
...
else {g_tif_name[page_name_leng]=0; ret=TIF_SUCCESS; }
保存所有bmp
"unzip all"项,调用multiPage_rotate_tif_decode.c\int save_all_bmp_fail(void)
for(i=0;i<tif_max_page;i++)
{err=get_1_bmp_fail(i);
...
}
2.3. set_status_bar
演示包含一个状态栏。当用户选择一个tif页面时,此演示将显示该页面的信息(通过tif_get_page_fail()
获取),并显示它们
if(tif_get_page_fail(i,
&(p_page->img_width),&(p_page->img_height),&(p_page->rot),
&(p_page->tif_ofs),&(p_page->tif_size), &page_name_leng,
NULL,NULL))
{...}
else
wsprintfA(str_bar_status,"w=%d, h=%d, rot=%d, byte_cnt=0x%x, in file [0x%X,0x%X] byte",
p_page->img_width,p_page->img_height,p_page->rot, p_page->tif_size,
p_page->tif_ofs,
p_page->tif_ofs+p_page->tif_size-1);
SetWindowTextA(hEdit,str_bar_status);
3. 如何制作一个可以被DLL读取的Zip文件?
请使用multiPage_rotate_tif_encode.exe。它可以由一个C文件(encode\multiPage_rotate_tif_encode.c)编译。文件开头有关于如何从C编译为EXE的说明。
用户也可以打开vc6项目(encode\vc6.dsw)进行编译。
3.1. 用法
在cmd
控制台中,输入"multiPage_rotate_tif_encode.exe
",我们将得到str_default[] ={"encode.exe [/r=R] [d=dst.zip] <file_1.bmp> [file_2.bmp ... file_n.bmp]
或encode.exe [/r=R] [d=dst.zip]
其中R = 1...8
,表示tif的方向(tag=112h)...";
例如1:我们输入"multiPage_rotate_tif_encode.exe x.bmp y.bmp
",我们将得到multi.zip(它是一个包含multi.tif的包,tif已旋转x和y)
例如2:我们输入"multiPage_rotate_tif_encode.exe /d=xy.zip x.bmp y.bmp
",我们将得到xy.zip(它是一个包含xy.tif的包,tif已旋转x和y)
例如3:我们输入"multiPage_rotate_tif_encode.exe /r=1 /d=xy.zip x.bmp y.bmp
",我们将得到xy.zip(它是一个包含xy.tif的包,tif是x和y)
例如4:我们创建一个tmp.txt,内容为11字节"x.bmp y.bmp
"。我们将其用作@echo_file
,输入"multiPage_rotate_tif_encode.exe /r=1 /d=xy.zip /s=tmp.txt
",我们将得到xy.zip(它是一个包含xy.tif的包,tif也是x和y)
例如5:我们输入"multiPage_rotate_tif_encode.exe /r=7 /d=..\decode\alphabet.zip /s=echo.txt
"将在[..\decode]文件夹中创建一个alphabet.zip,该文件由26个单色位图文件(6148字节)组成。
3.2. 描述
在multiPage_rotate_tif_encode.c\main()
中,我们...
- 3.2.1:
get_cmd_line(argc,argv);//通过echo_file计算page_cnt,获取用户cmdLine指定的rotate和str_tif_name
- 3.2.2:
traverse_bmp();//我们获取所有bmp的宽度和高度(这些bmp的名字出现在echo_file中)
- 3.2.3:
bmp2tif()
{alloc_tif();//malloc(tif_file_size);//the size consult above "tif data structure" for(i=0;i<max_bmp;i++) {init_tif_head(i);//setup 8 member(width,height, depth,rotate, compress,frame_name, img_ofs,img_size) in tif_frame_header rotate_bmp(i);//read bmp and rotate it } }//ifndef LOCAL_SIGNATURE, we can save the memory to tif file now.
- 3.2.4:
tif2zip()
unsigned char str_bmp[0x12000]; {deflate();//compress all tif_frame_header to head_compress_size bytes, into str_bmp[]. write_zip();//write local_head + central_dir + end_dir + zip_comment into zip file. }
3.2.4.1:zip_comment
tif文件(包含大量的
frame_headers
)太大,可以压缩成zip文件。
为了避免decode.exe
在解压这个压缩文件时浪费大量时间,在这个c_code
中,我们在zip文件末尾写入了一些小的帧信息作为zip_comment
。
帧信息结构为struct{u16 w; u16 h; u24 img_ofs; u8 name_length;}, sizeof(it)==8 byte
。
注释的尾部是struct{u8 rotate; u8 page_cnt; u16 comment_size;}, sizeof(it)==4 byte
。
我们将所有frame_info
和尾部写入zip_comment
,sizeof(zip_comment)==page_cnt*8+4 byte
。
在此c_code
中,zip_file= 0x1e byte(local_head) + zip_tif + 0x2e byte(central_dir) + 0x16 byte(end_dir) + (page_cnt*8+4) byte (zip_comment)
关于local_head
、central_dir
或end_dir
的示例,可以在multiPage_rotate_tif_encode.c\local_file和cent_dir
、end_dir
,或multiPage_tif_decode.c\zip_local_dir和zip_cent_dir
、zip_end_dir
中看到。
关注点
为什么需要从一个由许多位图组成的包中随机访问特定bmp
几年前...
我老板的公司的一个客户要求我们在他的电饭煲
面板上显示中文。但他的LED电路板
的设计非常糟糕:它垂直显示行。
客户的设计师给了我们一些字母的单色位图。我们将其旋转90度,并将其翻译成我们c_code
中的const
数据。当然,我们也做了index_table
来标记每个[offset,length,width,height
]。
几天后,客户想显示其他字母。因此,一些旧字母的定义不再代码中存在,而一些新定义将出现。我们花了几个小时处理代码冲突。
几天后,客户来到我们的工作室,想看他许多想法的一些临时效果。他改变了主意,多次更改了他的中文字符。我无法拒绝,因为我的老板就站在他旁边。
客户对我老板的公司非常满意,他向老板展示了他的下一个产品(电热水壶
)。LED电路板
以相反的方向垂直显示行。
因此,我决定将位图(旋转后)存储在资源文件中,以分离代码和界面。这就是上面c_code
的原因。
历史
- 2019年8月5日:可使用bc4.5和keil c51 7.5编译。提交
- 2016年5月:可使用vc6.0和armCC编译