Introduction
This source code shows how to randomly access a certain bitmap from a package (which is made up of lots of mono bitmaps).
The demo package(decode\alphabet.zip) in the attachment which is made up of 26 mono bitmap files (6148 bytes), has been packaged to 5974 bytes, compressed to 3918 bytes.
And this source code can direct access 1 or some or all of them, without decompressing the package file.
Because we wrote in pure C, it can run in other platforms (singlechip, little endian or big endian).
Originally, it was written for singlechip. Reference to why it has to randomly access a certain bmp from a package which is made up of lots of bitmaps.
The source code (MultiPage_tif_decode.c) has been tested by borland c 4.0, visual c 6.0, tinycc 0.9, armCC 5.0, and even keil c51 7.5! Yes, keil c51.exe, version 7.5, not a mistake.
It has been compiled into MultiPage_tif_decode.dll, just 4k bytes. Very small code.
Using the Code
1. MultiPage_tif_decode.dll
It can be compiled by a single C file (decode\multiPage_tif_decode.c). At the front of the file, there are notes for how to compile it from C to DLL.
User can open vc6 project (decode\vc6.dsw) to compile it too.
This DLL exports 3 functions:
It is a constructor, read the zip_comment of user's tif.zip, return the page cnt
of it.
It is a destructor.
It gets all information of 1 page. After the img_content
is read out, it can be handled by the user to do any other thing, such as be rotated, be shown on LCD, be saved in disk....
2. Demo for How to Use the DLL
The demo is multiPage_rotate_tif_decode.exe. It can be compiled by a single C file (decode\multiPage_rotate_tif_decode.c). At the front of the file, there are notes for how to compile it from C to EXE.
User can open vc6 project (decode\vc6.dsw) to compile it too.
2.1. Show All bmp
In 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. Handle Menu
The demo has a menu:
Save 1 bmp
The "unzip 1...
" item, call 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; }
Save All bmp
The "unzip all" item, call 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
The demo has a status bar. When user selects a page of tif, this demo shows the information (which is got by tif_get_page_fail()
) of the page, and shows them:
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. How to Make a Zip Which Can Be Read by the DLL?
Use multiPage_rotate_tif_encode.exe please. It can be compiled by a single C file (encode\multiPage_rotate_tif_encode.c). At the front of the file, there are notes for how to compile it from C to EXE.
User can open vc6 project (encode\vc6.dsw) to compile it too.
3.1. Usage
In cmd
console, input "multiPage_rotate_tif_encode.exe
", we would get str_default[] ={"encode.exe [/r=R] [d=dst.zip] <file_1.bmp> [file_2.bmp ... file_n.bmp]
or encode.exe [/r=R] [d=dst.zip]
where R = 1...8
, means tif's orientation(tag=112h)..."};
e.g.1: We input "multiPage_rotate_tif_encode.exe x.bmp y.bmp
", and we would get multi.zip (which is a package include multi.tif, and tif is rotate x and y)
e.g.2: We input "multiPage_rotate_tif_encode.exe /d=xy.zip x.bmp y.bmp
", and we would get xy.zip (which is a package include xy.tif, and tif is rotate x and y)
e.g.3: We input "multiPage_rotate_tif_encode.exe /r=1 /d=xy.zip x.bmp y.bmp
", and we would get xy.zip (which is a package include xy.tif, and tif is x and y)
e.g.4: We create a tmp.txt, which content is 11 bytes "x.bmp y.bmp
". we use it as an @echo_file
, input "multiPage_rotate_tif_encode.exe /r=1 /d=xy.zip /s=tmp.txt
", and we would get xy.zip (which is a package include xy.tif, and tif is x and y, too)
e.g.5: We input "multiPage_rotate_tif_encode.exe /r=7 /d=..\decode\alphabet.zip /s=echo.txt
" will make a alphabet.zip , which is made up of 26 mono bitmap files(6148 bytes),into [..\decode] folder.
3.2. Description
In multiPage_rotate_tif_encode.c\main()
, we ...
- 3.2.1:
get_cmd_line(argc,argv);//calculates page_cnt by echo_file, gets rotate and str_tif_name by user's cmdLine
- 3.2.2:
traverse_bmp();//we gets all width and height of bmps(which names are appeared in echo_file)
- 3.2.3:
bmp2tif()
{alloc_tif();for(i=0;i<max_bmp;i++)
{init_tif_head(i); compress,frame_name, img_ofs,img_size) in tif_frame_header
rotate_bmp(i); }
}
- 3.2.4:
tif2zip()
unsigned char str_bmp[0x12000];
{deflate(); write_zip();}
The tif (which has big multi frame_headers
) file is too large, can be compressed to a zip file.
To avoid this compressed file waste, the decode.exe lots of time for unzipping, in this c_code
, we write some small frame info as zip_comment
at the zip file end.
The structure of frame info is struct{u16 w; u16 h; u24 img_ofs; u8 name_length;}, sizeof(it)==8 byte
.
The tail of comment is struct{u8 rotate; u8 page_cnt; u16 comment_size;}, sizeof(it)==4 byte
.
We write all frame_info
and tail into zip_comment
, sizeof(zip_comment)==page_cnt*8+4 byte
.
In this 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)
About the example of local_head
or central_dir
or end_dir
, can be seen at multiPage_rotate_tif_encode.c\local_file and cent_dir
and end_dir
, or multiPage_tif_decode.c\zip_local_dir and zip_cent_dir
and zip_end_dir
.
Points of Interest
Several years ago...
A client of my boss' software corporation wanted us to show Chinese letters in the panel of his electric_cooker
. But the design of his LED_circuit_board
was very bad: it showed rows vertically.
Art designer of the client gave us some mono bitmap of letters. We rotated them 90 degrees, translated them into const
data in our c_code
. Of course, we made index_table
to mark every [offset,length,width,height
].
After some days, the client wanted to show other letters. So some old letters' definition did NOT exist in code, and some new definitions would appear. We handled the code conflict for several hours.
After some days, the client came into our workshop, wanted to see some temporary effects of his many ideas. He changed his mind, and changed his Chinese letters so many times. I could not refuse, because my boss stood near him.
The client was very satisfied with my boss' corporation, he showed his next production (electric_kettle
) to my boss. The LED_circuit_board
showed rows vertically, in the OTHER direction.
So, I decided to store the bitmaps (after rotated) in the resource file, to separate the code and interface. And, that's the reason of the c_code
above.
History
- 5th August, 2019: Can be compiled with bc4.5 and keil c51 7.5. Submitted
- May, 2016: Can be compiled with vc6.0 and armCC