1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
import json import os from datetime import datetime from typing import Callable, Dict, List, Literal, Optional, Tuple
import twain from twain import exceptions from twain.lowlevel import constants
from utils.z_sys_utils import get_sys_bit from utils.zlog import logger
def acquire( save_folder: str, dpi: Optional[float] = None, pixel_type: Optional[Literal["bw", "gray", "color"]] = "color", bpp: Optional[int] = None, frame: Optional[Tuple[float, float, float, float]] = None, show_ui: bool = False, dsm_name: Optional[str] = None, modal: bool = True, on_scan_img: Optional[Callable[[str], None]] = None, on_scan_finish: Optional[Callable[[], None]] = None, on_scan_error: Optional[Callable[[Exception], None]] = None, ) -> Optional[List[Dict]]: sysbit = get_sys_bit() logger.info( f"开始acquire函数,参数: path={save_folder}, dpi={dpi}, pixel_type={pixel_type}, frame={frame}") if pixel_type: pixel_type_map = { "bw": constants.TWPT_BW, "gray": constants.TWPT_GRAY, "color": constants.TWPT_RGB, } twain_pixel_type = pixel_type_map[pixel_type] logger.info(f"设置像素类型: {pixel_type}") else: twain_pixel_type = None logger.info(f"使用扫描仪: {dsm_name}") sm = twain.SourceManager(0, dsm_name=f"dll\\twain\\{sysbit}\\TWAINDSM.dll") logger.info("创建SourceManager对象") page_number = 0 full_path = "" try: sd = sm.open_source(dsm_name) if not sd: logger.error("无法打开数据源") if on_scan_error is not None: on_scan_error(Exception("无法打开扫描仪")) return None logger.info("成功打开数据源") try: if twain_pixel_type: sd.set_capability( constants.ICAP_PIXELTYPE, constants.TWTY_UINT16, twain_pixel_type) sd.set_capability( constants.ICAP_UNITS, constants.TWTY_UINT16, constants.TWUN_INCHES) sd.set_capability( constants.CAP_DUPLEXENABLED, constants.TWTY_BOOL, True) if bpp: sd.set_capability( constants.ICAP_BITDEPTH, constants.TWTY_UINT16, bpp) if dpi: sd.set_capability( constants.ICAP_XRESOLUTION, constants.TWTY_FIX32, dpi) sd.set_capability( constants.ICAP_YRESOLUTION, constants.TWTY_FIX32, dpi) if frame: try: sd.set_image_layout(frame) except exceptions.CheckStatus: logger.warning("设置图像布局失败") logger.info("设置扫描参数完成") res: List[Dict] = []
def before(img_info: Dict) -> str: nonlocal page_number nonlocal full_path page_number += 1 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") file_name = f"scan_{timestamp}_{page_number:03d}.png" full_path = os.path.join(save_folder, file_name) res.append(img_info) logger.info(f"准备保存第 {page_number} 页,文件路径: {full_path}") return full_path
def after(more: int) -> None: logger.info(f"保存完毕-第 {page_number} 页,文件路径: {full_path}") if os.path.exists(full_path): if on_scan_img is not None: on_scan_img(full_path) if more == 0: logger.info("扫描完成,没有更多页面")
try: sd.acquire_file(before=before, after=after, show_ui=show_ui, modal=modal) logger.info("扫描结束") if on_scan_finish is not None: on_scan_finish() except Exception as e: logger.info("用户取消了扫描:"+str(e)) if on_scan_error is not None: on_scan_error(e) return None finally: sd.close() logger.info("关闭数据源") except Exception as e: on_scan_error(e) finally: sm.close() logger.info("关闭SourceManager") logger.info(f"扫描结果: {json.dumps(res)}") return res
def select_device() -> List[str]: sysbit = get_sys_bit() name_arr = [] sm = None try: sm = twain.SourceManager( 0, dsm_name=f"dll\\twain\\{sysbit}\\TWAINDSM.dll") s_list = sm.GetSourceList() for idx, name in enumerate(s_list): name_arr.append(name) finally: if sm is not None: sm.close() return name_arr
|