Source code for twain.windows

from __future__ import annotations

import ctypes as ct
import tempfile
import os
import warnings
import sys
from .utils import convert_dib_to_bmp


def _win_check(result, func, _):
    if func is GlobalFree:
        if result:
            raise ct.WinError()
        return None
    if func is GlobalUnlock:
        if not result and ct.GetLastError() != 0:
            raise ct.WinError()
        return result
    if func is GetMessage:
        if result == -1:
            raise ct.WinError()
        return result
    if func is TranslateMessage or func is DispatchMessage:
        return result
    if not result:
        raise ct.WinError()
    return result


if sys.platform == "win32":
    GlobalLock = ct.windll.kernel32.GlobalLock
    GlobalLock.argtypes = [ct.c_void_p]
    GlobalLock.restype = ct.c_void_p
    GlobalLock.errcheck = _win_check
    GlobalUnlock = ct.windll.kernel32.GlobalUnlock
    GlobalUnlock.argtypes = [ct.c_void_p]
    GlobalUnlock.errcheck = _win_check
    GlobalAlloc = ct.windll.kernel32.GlobalAlloc
    GlobalAlloc.restype = ct.c_void_p
    GlobalAlloc.errcheck = _win_check
    GlobalFree = ct.windll.kernel32.GlobalFree
    GlobalFree.argtypes = [ct.c_void_p]
    GlobalFree.errcheck = _win_check
    GlobalSize = ct.windll.kernel32.GlobalSize
    GlobalSize.argtypes = [ct.c_void_p]
    GlobalSize.restype = ct.c_size_t
    GlobalSize.errcheck = _win_check
    GetMessage = ct.windll.user32.GetMessageW
    TranslateMessage = ct.windll.user32.TranslateMessage
    TranslateMessage.errcheck = _win_check
    DispatchMessage = ct.windll.user32.DispatchMessageW
    DispatchMessage.errcheck = _win_check

GMEM_ZEROINIT = 0x0040


[docs] def dib_to_bm_file(handle, path: str | None = None) -> bytes | None: """Convert a DIB (Device Independent Bitmap) to a windows bitmap file format. The BitMap file is either returned as a string, or written to a file with the name given in the second argument. .. note:: Can only be used with lowlevel 1.x sources """ size = GlobalSize(handle) ptr = GlobalLock(handle) try: dib_bytes = (ct.c_char * size).from_address(ptr) bmp = convert_dib_to_bmp(dib_bytes) if path: with open(path, "wb") as f: f.write(bmp) else: return bmp finally: GlobalUnlock(handle) return None
[docs] def dib_to_xbm_file(handle, path: str | None = None): """Convert a DIB (Device Independent Bitmap) to an X-Windows bitmap file (XBM format). The XBM file is either returned as a string, or written to a file with the name given in the third argument. Parameters: :param handle: Handle to a global area containing a DIB, :param path: Path prefix to be used for the name and an optional filename for file only output. .. note:: Can only be used with lowlevel 1.x sources """ handle, bmppath = tempfile.mkstemp(".bmp") os.close(handle) dib_to_bm_file(handle, bmppath) try: # Needs fixing import Image # type: ignore except ImportError: from PIL import Image Image.open(bmppath).save(path, "xbm") os.remove(bmppath)
[docs] def global_handle_get_bytes(handle, offset: int, count: int) -> bytes: """Read a specified number of bytes from a global handle. Parameters: :param handle: Global handle :param offset: An index into the handle data :param count: The number of bytes to be returned .. note:: Can only be used with lowlevel 1.x sources """ size = GlobalSize(handle) ptr = GlobalLock(handle) try: char_ptr = ct.cast(ptr, ct.POINTER(ct.c_char)) return char_ptr[min(offset, size) : min(offset + count, size)] # type: ignore # needs fixing finally: GlobalUnlock(handle)
[docs] def global_handle_put_bytes(handle, offset: int, count: int, data: bytes): """Write a specified number of bytes to a global handle. Parameters: :param handle: Global handle :param offset: An index into the handle data :param count: The number of bytes to update :param data: String of data to be written .. note:: Can only be used with lowlevel 1.x sources """ size = GlobalSize(handle) ptr = GlobalLock(handle) try: char_ptr = ct.cast(ptr, ct.POINTER(ct.c_char)) offset = min(offset, size) end = min(offset + count, size) count = end - offset count = min(count, len(data)) for i in range(count): char_ptr[i + offset] = data[i] finally: GlobalUnlock(handle)
[docs] def global_handle_allocate(flags: int, size: int): """Allocate a specified number of bytes via a global handle. Parameters: :param size: The number of bytes to be allocated .. note:: Can only be used with lowlevel 1.x sources """ return GlobalAlloc(flags, size)
[docs] def global_handle_free(handle): """Free an allocated heap section via the global handle. Parameters: :param handle: Handle to memory to be freed .. note:: Can only be used with lowlevel 1.x sources """ return GlobalFree(handle)
# backward compatible aliases
[docs] def DIBToBMFile(handle, path=None): """Backward compatible alias for :func:`dib_to_bm_file`""" warnings.warn( "DIBToBMFile is deprecated, use dib_to_bm_file instead", DeprecationWarning ) return dib_to_bm_file(handle, path)
[docs] def DIBToXBMFile(handle, path=None): """Backward compatible alias for :func:`dib_to_xbm_file`""" warnings.warn( "DIBToXBMFile is deprecated, use dib_to_xbm_file instead", DeprecationWarning ) return dib_to_xbm_file(handle, path)
[docs] def GlobalHandleGetBytes(handle, offset, count): """Backward compatible alias for :func:`global_handle_get_bytes`""" warnings.warn( "GlobalHandleGetBytes is deprecated, use global_handle_get_bytes instead", DeprecationWarning, ) return global_handle_get_bytes(handle, offset, count)
[docs] def GlobalHandlePutBytes(handle, offset, count, data): """Backward compatible alias for :func:`global_handle_put_bytes`""" warnings.warn( "GlobalHandlePutBytes is deprecated, use global_handle_put_bytes instead", DeprecationWarning, ) return global_handle_put_bytes(handle, offset, count, data)
[docs] def GlobalHandleAllocate(flags, size): """Backward compatible alias for :func:`global_handle_allocate`""" warnings.warn( "GlobalHandleAllocate is deprecated, use global_handle_allocate instead", DeprecationWarning, ) return global_handle_allocate(flags, size)
[docs] def GlobalHandleFree(handle): """Backward compatible alias for :func:`global_handle_free`""" warnings.warn( "GlobalHandleFree is deprecated, use global_handle_free instead", DeprecationWarning, ) return global_handle_free(handle)