⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thinner.c

📁 就是将BMP文件转换为DXF格式的文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  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 + -