📄 thinner.c
字号:
/*
* Ras2Vec by Davide Libenzi ( Raster to vector conversion program )
* Copyright (C) 1999 Davide Libenzi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Davide Libenzi <davidel@maticad.it>
*
*/
#include<windows.h>
#include<windowsx.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#include<math.h>
#include<float.h>
#include<time.h>
#include<limits.h>
#include"ras2vec.h"
#include"dbll_list.h"
#include"himage.h"
#include"thinner.h"
#include"log.h"
#include"util.h"
#define ASM_VERSION
#ifdef ASM_VERSION
#define get_mem_bits get_mem_bits_asm
#else
#define get_mem_bits get_mem_bits_c
#endif
static int do_thinning(bw_bmp_header * p_bmph, BYTE * p_img_mem, int back_ground,
BYTE * p_prev_mod_line, BYTE * p_curr_mod_line);
static int step_1_check_func(BYTE * pix);
static int step_2_check_func(BYTE * pix);
static int get_mem_bits_c(BYTE * p_line, int x_size, BYTE * p_bits, int back_ground,
int *p_switches);
static int get_mem_bits_asm_bFF(BYTE * p_line, int x_size, BYTE * p_bits,
int *p_switches);
static int get_mem_bits_asm_b00(BYTE * p_line, int x_size, BYTE * p_bits,
int *p_switches);
static int get_mem_bits_asm(BYTE * p_line, int x_size, BYTE * p_bits, int back_ground,
int *p_switches);
static int do_step(bw_bmp_header * p_bmph, BYTE * p_img_mem, int back_ground,
BYTE * p_prev_mod_line, BYTE * p_curr_mod_line,
int (*step_check_func) (BYTE *));
static BYTE bits[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
/* OK */
int thin_image_file(char *img_file_name)
{
int passes;
BYTE *p_img_mem;
img_data imgd;
if ((p_img_mem = (BYTE *) get_image(img_file_name, IMAGE_OPEN_READWRITE,
&imgd)) == NULL)
return (-1);
passes = thin_image(p_img_mem, NULL);
free_image(&imgd);
return (passes);
}
/* OK */
int thin_image(BYTE * p_img_mem, int *p_back_ground)
{
int passes = 0,
pixel_removed,
back_ground;
BYTE *p_mod_lines,
*p_curr_mod_line,
*p_prev_mod_line;
bw_bmp_header bmph;
time_t start_time,
end_time;
bmph = *((bw_bmp_header *) p_img_mem);
if ((bmph.bfh.bfType != *((WORD *) "BM")) || (bmph.bih.biSize != sizeof(BITMAPINFOHEADER)) ||
(bmph.bih.biCompression != BI_RGB) || (bmph.bih.biBitCount != 1) ||
(bmph.bih.biPlanes != 1))
return (-1);
if ((p_mod_lines = (BYTE *) malloc(2 * bmph.bih.biHeight)) == NULL)
return (-1);
p_prev_mod_line = p_mod_lines;
memset(p_prev_mod_line, 1, bmph.bih.biHeight);
p_curr_mod_line = p_prev_mod_line + bmph.bih.biHeight;
memset(p_curr_mod_line, 0, bmph.bih.biHeight);
back_ground = bmp_file_get_background(&bmph, p_img_mem, 100, 100);
time(&start_time);
while ((pixel_removed = do_thinning(&bmph, p_img_mem, back_ground, p_prev_mod_line,
p_curr_mod_line)) > 0)
{
BYTE *tmp_byte_ptr;
tmp_byte_ptr = p_prev_mod_line;
p_prev_mod_line = p_curr_mod_line;
p_curr_mod_line = tmp_byte_ptr;
memset(p_curr_mod_line, 0, bmph.bih.biHeight);
time(&end_time);
scr_printf("- pass %3d - removed %8d pixel(s) in %.0lf sec\n", passes + 1,
pixel_removed, difftime(end_time, start_time));
time(&start_time);
++passes;
}
time(&end_time);
scr_printf("- pass %3d - removed %8d pixel(s) in %.0lf sec\n", passes + 1,
pixel_removed, difftime(end_time, start_time));
free(p_mod_lines);
if (p_back_ground != NULL)
*p_back_ground = back_ground;
return (passes);
}
/* OK */
int bmp_file_get_background(bw_bmp_header * p_bmph, BYTE * p_img_mem,
int x_samples, int y_samples)
{
int xx,
yy,
num_ones = 0,
num_zeros = 0,
x_step,
y_step,
img_line_size = get_line_size(p_bmph->bih.biWidth);
BYTE *p_raw_ptr = bmp_get_raw_ptr(p_img_mem),
*p_file_curr_line;
x_step = max(1, p_bmph->bih.biWidth / x_samples);
y_step = max(1, p_bmph->bih.biHeight / y_samples);
for (yy = 0; yy < p_bmph->bih.biHeight; yy += y_step)
{
p_file_curr_line = get_raw_img_line(p_raw_ptr, img_line_size, yy);
for (xx = 0; xx < p_bmph->bih.biWidth; xx += x_step)
{
if (read_bit(p_file_curr_line, xx))
++num_ones;
else
++num_zeros;
}
}
return ((num_ones > num_zeros) ? 0xff : 0x00);
}
/* OK */
static int do_thinning(bw_bmp_header * p_bmph, BYTE * p_img_mem, int back_ground,
BYTE * p_prev_mod_line, BYTE * p_curr_mod_line)
{
int pixel_removed_1,
pixel_removed_2;
if ((pixel_removed_1 = do_step(p_bmph, p_img_mem, back_ground, p_prev_mod_line,
p_curr_mod_line, step_1_check_func)) < 0)
return (pixel_removed_1);
if ((pixel_removed_2 = do_step(p_bmph, p_img_mem, back_ground, p_prev_mod_line,
p_curr_mod_line, step_2_check_func)) < 0)
return (pixel_removed_2);
return (pixel_removed_1 + pixel_removed_2);
}
/* OK */
static int step_1_check_func(BYTE * pix)
{
return ((((pix[1] * pix[3] * pix[5]) == 0) && ((pix[3] * pix[5] * pix[7]) == 0)) ? TRUE : FALSE);
}
/* OK */
static int step_2_check_func(BYTE * pix)
{
return ((((pix[1] * pix[3] * pix[7]) == 0) && ((pix[1] * pix[5] * pix[7]) == 0)) ? TRUE : FALSE);
}
/* OK */
static int get_mem_bits_c(BYTE * p_line, int x_size, BYTE * p_bits, int back_ground,
int *p_switches)
{
int xx,
bit = 7,
num_switches = 0;
register BYTE curr_byte = *p_bits,
last_is_zero = TRUE;
BYTE *p_dw_ptr_limit = p_bits + (get_line_size(x_size) - 4);
memset(p_line, 0, x_size);
if (back_ground != 0)
{
for (xx = 0; xx < x_size; xx++)
{
if (!(curr_byte & bits[bit]))
{
p_line[xx] = 1;
if (last_is_zero)
p_switches[num_switches++] = xx, last_is_zero = FALSE;
}
else
last_is_zero = TRUE;
if ((--bit) < 0)
{
DWORD *p_dw_bits = (DWORD *)++ p_bits;
bit = 7;
while (((BYTE *) p_dw_bits < p_dw_ptr_limit) && (*p_dw_bits == 0xffffffff))
++p_dw_bits;
if ((BYTE *) p_dw_bits > p_bits)
{
xx += 8 * (int) ((BYTE *) p_dw_bits - p_bits);
p_bits = (BYTE *) p_dw_bits;
last_is_zero = TRUE;
}
if (xx < x_size)
curr_byte = *p_bits;
}
}
}
else
{
for (xx = 0; xx < x_size; xx++)
{
if (curr_byte & bits[bit])
{
p_line[xx] = 1;
if (last_is_zero)
p_switches[num_switches++] = xx, last_is_zero = FALSE;
}
else
last_is_zero = TRUE;
if ((--bit) < 0)
{
DWORD *p_dw_bits = (DWORD *)++ p_bits;
bit = 7;
while (((BYTE *) p_dw_bits < p_dw_ptr_limit) && (*p_dw_bits == 0x00000000))
++p_dw_bits;
if ((BYTE *) p_dw_bits > p_bits)
{
xx += 8 * (int) ((BYTE *) p_dw_bits - p_bits);
p_bits = (BYTE *) p_dw_bits;
last_is_zero = TRUE;
}
if (xx < x_size)
curr_byte = *p_bits;
}
}
}
return (num_switches);
}
/* OK */
static int get_mem_bits_asm_bFF(BYTE * p_line, int x_size, BYTE * p_bits,
int *p_switches)
{
int num_switches = 0;
BYTE *p_dw_ptr_limit = p_bits + (get_line_size(x_size) - 4);
/* INDENT OFF */
__asm{
push ebx;
push ecx;
push edx;
push edi;
push esi;
mov ecx,x_size;
mov esi,offset bits;
mov edi,p_bits;
mov bl,[edi];
mov bh,1;
mov edx,7;
xor eax,eax;
main_loop:
cmp eax,ecx;
jae exit_label;
test bl,byte ptr [esi+edx];
jnz no_set;
push esi;
mov esi,p_line;
mov byte ptr [esi+eax],1;
pop esi;
cmp bh,0;
je no_switch;
push edx;
push esi;
mov edx,num_switches;
inc num_switches;
mov esi,p_switches;
mov dword ptr[esi+edx*4],eax;
pop esi;
pop edx;
mov bh,0;
jmp no_switch;
no_set:
mov bh,1;
no_switch:
cmp edx,0;
je switch_bit;
dec edx;
inc eax;
jmp main_loop;
switch_bit:
mov edx,7;
inc edi;
push ecx;
push edx;
mov ecx,edi;
mov edx,p_dw_ptr_limit;
skip_loop:
cmp edi,edx;
jae skip_loop_exit;
cmp dword ptr [edi],0xffffffff;
jne small_loop_entry;
add edi,4;
jmp skip_loop;
small_loop:
cmp edi,edx;
jae skip_loop_exit;
small_loop_entry:
cmp byte ptr [edi],0xff;
jne skip_loop_exit;
inc edi;
jmp small_loop;
skip_loop_exit:
cmp edi,ecx;
jbe not_skipped;
push ebx;
mov ebx,edi;
sub ebx,ecx;
shl ebx,3;
add eax,ebx;
pop ebx;
mov bh,1;
not_skipped:
pop edx;
pop ecx;
cmp eax,ecx
jae exit_label;
mov bl,[edi];
inc eax;
jmp main_loop;
exit_label:
pop esi;
pop edi;
pop edx;
pop ecx;
pop ebx;
}
/* INDENT ON */
return (num_switches);
}
/* OK */
static int get_mem_bits_asm_b00(BYTE * p_line, int x_size, BYTE * p_bits,
int *p_switches)
{
int num_switches = 0;
BYTE *p_dw_ptr_limit = p_bits + (get_line_size(x_size) - 4);
/* INDENT OFF */
__asm{
push ebx;
push ecx;
push edx;
push edi;
push esi;
mov ecx,x_size;
mov esi,offset bits;
mov edi,p_bits;
mov bl,[edi];
mov bh,1;
mov edx,7;
xor eax,eax;
main_loop:
cmp eax,ecx;
jae exit_label;
test bl,byte ptr [esi+edx];
jz no_set;
push esi;
mov esi,p_line;
mov byte ptr [esi+eax],1;
pop esi;
cmp bh,0;
je no_switch;
push edx;
push esi;
mov edx,num_switches;
inc num_switches;
mov esi,p_switches;
mov dword ptr[esi+edx*4],eax;
pop esi;
pop edx;
mov bh,0;
jmp no_switch;
no_set:
mov bh,1;
no_switch:
cmp edx,0;
je switch_bit;
dec edx;
inc eax;
jmp main_loop;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -