AVT相机arm版本SDK
This commit is contained in:
128
Vimba_6_0/VimbaPython/Source/vimba/__init__.py
Normal file
128
Vimba_6_0/VimbaPython/Source/vimba/__init__.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
# Suppress 'imported but unused' - Error from static style checker.
|
||||
# flake8: noqa: F401
|
||||
|
||||
__version__ = '1.2.1'
|
||||
|
||||
__all__ = [
|
||||
'Vimba',
|
||||
'Camera',
|
||||
'CameraChangeHandler',
|
||||
'CameraEvent',
|
||||
'AccessMode',
|
||||
'PersistType',
|
||||
'Interface',
|
||||
'InterfaceType',
|
||||
'InterfaceChangeHandler',
|
||||
'InterfaceEvent',
|
||||
'PixelFormat',
|
||||
'Frame',
|
||||
'FeatureTypes',
|
||||
'FrameHandler',
|
||||
'FrameStatus',
|
||||
'AllocationMode',
|
||||
'Debayer',
|
||||
'intersect_pixel_formats',
|
||||
'MONO_PIXEL_FORMATS',
|
||||
'BAYER_PIXEL_FORMATS',
|
||||
'RGB_PIXEL_FORMATS',
|
||||
'RGBA_PIXEL_FORMATS',
|
||||
'BGR_PIXEL_FORMATS',
|
||||
'BGRA_PIXEL_FORMATS',
|
||||
'YUV_PIXEL_FORMATS',
|
||||
'YCBCR_PIXEL_FORMATS',
|
||||
'COLOR_PIXEL_FORMATS',
|
||||
'OPENCV_PIXEL_FORMATS',
|
||||
|
||||
'VimbaSystemError',
|
||||
'VimbaCameraError',
|
||||
'VimbaInterfaceError',
|
||||
'VimbaFeatureError',
|
||||
'VimbaFrameError',
|
||||
'VimbaTimeout',
|
||||
|
||||
'IntFeature',
|
||||
'FloatFeature',
|
||||
'StringFeature',
|
||||
'BoolFeature',
|
||||
'EnumEntry',
|
||||
'EnumFeature',
|
||||
'CommandFeature',
|
||||
'RawFeature',
|
||||
|
||||
'LogLevel',
|
||||
'LogConfig',
|
||||
'Log',
|
||||
'LOG_CONFIG_TRACE_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_TRACE_FILE_ONLY',
|
||||
'LOG_CONFIG_TRACE',
|
||||
'LOG_CONFIG_INFO_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_INFO_FILE_ONLY',
|
||||
'LOG_CONFIG_INFO',
|
||||
'LOG_CONFIG_WARNING_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_WARNING_FILE_ONLY',
|
||||
'LOG_CONFIG_WARNING',
|
||||
'LOG_CONFIG_ERROR_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_ERROR_FILE_ONLY',
|
||||
'LOG_CONFIG_ERROR',
|
||||
'LOG_CONFIG_CRITICAL_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_CRITICAL_FILE_ONLY',
|
||||
'LOG_CONFIG_CRITICAL',
|
||||
|
||||
'TraceEnable',
|
||||
'ScopedLogEnable',
|
||||
'RuntimeTypeCheckEnable'
|
||||
]
|
||||
|
||||
# Import everything exported from the top level module
|
||||
from .vimba import Vimba
|
||||
|
||||
from .camera import AccessMode, PersistType, Camera, CameraChangeHandler, CameraEvent, FrameHandler
|
||||
|
||||
from .interface import Interface, InterfaceType, InterfaceChangeHandler, InterfaceEvent
|
||||
|
||||
from .frame import PixelFormat, Frame, Debayer, intersect_pixel_formats, MONO_PIXEL_FORMATS, \
|
||||
BAYER_PIXEL_FORMATS, RGB_PIXEL_FORMATS, RGBA_PIXEL_FORMATS, BGR_PIXEL_FORMATS, \
|
||||
BGRA_PIXEL_FORMATS, YUV_PIXEL_FORMATS, YCBCR_PIXEL_FORMATS, \
|
||||
COLOR_PIXEL_FORMATS, OPENCV_PIXEL_FORMATS, FrameStatus, FeatureTypes, \
|
||||
AllocationMode
|
||||
|
||||
from .error import VimbaSystemError, VimbaCameraError, VimbaInterfaceError, VimbaFeatureError, \
|
||||
VimbaFrameError, VimbaTimeout
|
||||
|
||||
from .feature import IntFeature, FloatFeature, StringFeature, BoolFeature, EnumEntry, EnumFeature, \
|
||||
CommandFeature, RawFeature
|
||||
|
||||
from .util import Log, LogLevel, LogConfig, LOG_CONFIG_TRACE_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_TRACE_FILE_ONLY, LOG_CONFIG_TRACE, LOG_CONFIG_INFO_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_INFO_FILE_ONLY, LOG_CONFIG_INFO, LOG_CONFIG_WARNING_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_WARNING_FILE_ONLY, LOG_CONFIG_WARNING, LOG_CONFIG_ERROR_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_ERROR_FILE_ONLY, LOG_CONFIG_ERROR, LOG_CONFIG_CRITICAL_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_CRITICAL_FILE_ONLY, LOG_CONFIG_CRITICAL, ScopedLogEnable, \
|
||||
TraceEnable, RuntimeTypeCheckEnable
|
||||
120
Vimba_6_0/VimbaPython/Source/vimba/c_binding/__init__.py
Normal file
120
Vimba_6_0/VimbaPython/Source/vimba/c_binding/__init__.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
NOTE: Vimba/Vmb naming convention.
|
||||
VimbaPython is based heavily on VimbaC, this submodule contains all wrapped types and functions
|
||||
of VimbaC. All VimbaC Types and Functions are prefixed with 'Vmb', this convention is kept for
|
||||
all python types interfacing with the C - Layer. VimbaC developers should be able to understand
|
||||
the interface to VimbaC and keeping the name convention helps a lot in that regard.
|
||||
|
||||
However prefixing everything with 'Vmb' is not required in VimbaPython, therefore most Types
|
||||
of the public API have no prefix.
|
||||
"""
|
||||
|
||||
# Suppress 'imported but unused' - Error from static style checker.
|
||||
# flake8: noqa: F401
|
||||
|
||||
__all__ = [
|
||||
# Exports from vimba_common
|
||||
'VmbInt8',
|
||||
'VmbUint8',
|
||||
'VmbInt16',
|
||||
'VmbUint16',
|
||||
'VmbInt32',
|
||||
'VmbUint32',
|
||||
'VmbInt64',
|
||||
'VmbUint64',
|
||||
'VmbHandle',
|
||||
'VmbBool',
|
||||
'VmbUchar',
|
||||
'VmbDouble',
|
||||
'VmbError',
|
||||
'VimbaCError',
|
||||
'VmbPixelFormat',
|
||||
'decode_cstr',
|
||||
'decode_flags',
|
||||
|
||||
# Exports from vimba_c
|
||||
'VmbInterface',
|
||||
'VmbAccessMode',
|
||||
'VmbFeatureData',
|
||||
'VmbFeaturePersist',
|
||||
'VmbFeatureVisibility',
|
||||
'VmbFeatureFlags',
|
||||
'VmbFrameStatus',
|
||||
'VmbFrameFlags',
|
||||
'VmbVersionInfo',
|
||||
'VmbInterfaceInfo',
|
||||
'VmbCameraInfo',
|
||||
'VmbFeatureInfo',
|
||||
'VmbFeatureEnumEntry',
|
||||
'VmbFrame',
|
||||
'VmbFeaturePersistSettings',
|
||||
'G_VIMBA_C_HANDLE',
|
||||
'VIMBA_C_VERSION',
|
||||
'EXPECTED_VIMBA_C_VERSION',
|
||||
'call_vimba_c',
|
||||
'build_callback_type',
|
||||
|
||||
# Exports from vimba_image_transform
|
||||
'VmbImage',
|
||||
'VmbImageInfo',
|
||||
'VmbDebayerMode',
|
||||
'VmbTransformInfo',
|
||||
'VIMBA_IMAGE_TRANSFORM_VERSION',
|
||||
'EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION',
|
||||
'call_vimba_image_transform',
|
||||
'PIXEL_FORMAT_TO_LAYOUT',
|
||||
'LAYOUT_TO_PIXEL_FORMAT',
|
||||
'PIXEL_FORMAT_CONVERTIBILITY_MAP',
|
||||
|
||||
# Exports from ctypes
|
||||
'byref',
|
||||
'sizeof',
|
||||
'create_string_buffer'
|
||||
]
|
||||
|
||||
from .vimba_common import VmbInt8, VmbUint8, VmbInt16, VmbUint16, VmbInt32, VmbUint32, \
|
||||
VmbInt64, VmbUint64, VmbHandle, VmbBool, VmbUchar, VmbDouble, VmbError, \
|
||||
VimbaCError, VmbPixelFormat, decode_cstr, decode_flags, \
|
||||
_select_vimba_home
|
||||
|
||||
from .vimba_c import VmbInterface, VmbAccessMode, VmbFeatureData, \
|
||||
VmbFeaturePersist, VmbFeatureVisibility, VmbFeatureFlags, VmbFrameStatus, \
|
||||
VmbFrameFlags, VmbVersionInfo, VmbInterfaceInfo, VmbCameraInfo, VmbFeatureInfo, \
|
||||
VmbFeatureEnumEntry, VmbFrame, VmbFeaturePersistSettings, \
|
||||
G_VIMBA_C_HANDLE, EXPECTED_VIMBA_C_VERSION, VIMBA_C_VERSION, call_vimba_c, \
|
||||
build_callback_type
|
||||
|
||||
from .vimba_image_transform import VmbImage, VmbImageInfo, VmbDebayerMode, \
|
||||
VIMBA_IMAGE_TRANSFORM_VERSION, \
|
||||
EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION, VmbTransformInfo, \
|
||||
call_vimba_image_transform, PIXEL_FORMAT_TO_LAYOUT, \
|
||||
LAYOUT_TO_PIXEL_FORMAT, PIXEL_FORMAT_CONVERTIBILITY_MAP
|
||||
|
||||
from ctypes import byref, sizeof, create_string_buffer
|
||||
772
Vimba_6_0/VimbaPython/Source/vimba/c_binding/vimba_c.py
Normal file
772
Vimba_6_0/VimbaPython/Source/vimba/c_binding/vimba_c.py
Normal file
@@ -0,0 +1,772 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import ctypes
|
||||
from typing import Callable, Any, Tuple
|
||||
from ctypes import c_void_p, c_char_p, byref, sizeof, POINTER as c_ptr, c_char_p as c_str
|
||||
from ..util import TraceEnable
|
||||
from ..error import VimbaSystemError
|
||||
from .vimba_common import Uint32Enum, Int32Enum, VmbInt32, VmbUint32, VmbInt64, VmbUint64, \
|
||||
VmbHandle, VmbBool, VmbDouble, VmbError, VimbaCError, VmbPixelFormat, \
|
||||
fmt_enum_repr, fmt_repr, fmt_flags_repr, load_vimba_lib
|
||||
|
||||
__version__ = None
|
||||
|
||||
__all__ = [
|
||||
'VmbPixelFormat',
|
||||
'VmbInterface',
|
||||
'VmbAccessMode',
|
||||
'VmbFeatureData',
|
||||
'VmbFeaturePersist',
|
||||
'VmbFeatureVisibility',
|
||||
'VmbFeatureFlags',
|
||||
'VmbFrameStatus',
|
||||
'VmbFrameFlags',
|
||||
'VmbVersionInfo',
|
||||
'VmbInterfaceInfo',
|
||||
'VmbCameraInfo',
|
||||
'VmbFeatureInfo',
|
||||
'VmbFeatureEnumEntry',
|
||||
'VmbFrame',
|
||||
'VmbFeaturePersistSettings',
|
||||
'G_VIMBA_C_HANDLE',
|
||||
'VIMBA_C_VERSION',
|
||||
'EXPECTED_VIMBA_C_VERSION',
|
||||
'call_vimba_c',
|
||||
'build_callback_type'
|
||||
]
|
||||
|
||||
|
||||
# Types
|
||||
class VmbInterface(Uint32Enum):
|
||||
"""
|
||||
Camera Interface Types:
|
||||
Unknown - Interface is not known to this version of the API
|
||||
Firewire - 1394
|
||||
Ethernet - GigE
|
||||
Usb - USB 3.0
|
||||
CL - Camera Link
|
||||
CSI2 - CSI-2
|
||||
"""
|
||||
Unknown = 0
|
||||
Firewire = 1
|
||||
Ethernet = 2
|
||||
Usb = 3
|
||||
CL = 4
|
||||
CSI2 = 5
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbAccessMode(Uint32Enum):
|
||||
"""
|
||||
Camera Access Mode:
|
||||
None_ - No access
|
||||
Full - Read and write access
|
||||
Read - Read-only access
|
||||
Config - Configuration access (GeV)
|
||||
Lite - Read and write access without feature access (only addresses)
|
||||
"""
|
||||
None_ = 0
|
||||
Full = 1
|
||||
Read = 2
|
||||
Config = 4
|
||||
Lite = 8
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbFeatureData(Uint32Enum):
|
||||
"""
|
||||
Feature Data Types
|
||||
Unknown - Unknown feature type
|
||||
Int - 64 bit integer feature
|
||||
Float - 64 bit floating point feature
|
||||
Enum - Enumeration feature
|
||||
String - String feature
|
||||
Bool - Boolean feature
|
||||
Command - Command feature
|
||||
Raw - Raw (direct register access) feature
|
||||
None_ - Feature with no data
|
||||
"""
|
||||
Unknown = 0
|
||||
Int = 1
|
||||
Float = 2
|
||||
Enum = 3
|
||||
String = 4
|
||||
Bool = 5
|
||||
Command = 6
|
||||
Raw = 7
|
||||
None_ = 8
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbFeaturePersist(Uint32Enum):
|
||||
"""
|
||||
Type of features that are to be saved (persisted) to the XML file
|
||||
when using VmbCameraSettingsSave
|
||||
|
||||
All - Save all features to XML, including look-up tables
|
||||
Streamable - Save only features marked as streamable, excluding
|
||||
look-up tables
|
||||
NoLUT - Save all features except look-up tables (default)
|
||||
"""
|
||||
All = 0
|
||||
Streamable = 1
|
||||
NoLUT = 2
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbFeatureVisibility(Uint32Enum):
|
||||
"""
|
||||
Feature Visibility
|
||||
Unknown - Feature visibility is not known
|
||||
Beginner - Feature is visible in feature list (beginner level)
|
||||
Expert - Feature is visible in feature list (expert level)
|
||||
Guru - Feature is visible in feature list (guru level)
|
||||
Invisible - Feature is not visible in feature list
|
||||
"""
|
||||
Unknown = 0
|
||||
Beginner = 1
|
||||
Expert = 2
|
||||
Guru = 3
|
||||
Invisible = 4
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbFeatureFlags(Uint32Enum):
|
||||
"""
|
||||
Feature Flags
|
||||
None_ - No additional information is provided
|
||||
Read - Static info about read access.
|
||||
Current status depends on access mode, check with
|
||||
VmbFeatureAccessQuery()
|
||||
Write - Static info about write access.
|
||||
Current status depends on access mode, check with
|
||||
VmbFeatureAccessQuery()
|
||||
Volatile - Value may change at any time
|
||||
ModifyWrite - Value may change after a write
|
||||
"""
|
||||
None_ = 0
|
||||
Read = 1
|
||||
Write = 2
|
||||
Undocumented = 4
|
||||
Volatile = 8
|
||||
ModifyWrite = 16
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbFrameStatus(Int32Enum):
|
||||
"""
|
||||
Frame transfer status
|
||||
Complete - Frame has been completed without errors
|
||||
Incomplete - Frame could not be filled to the end
|
||||
TooSmall - Frame buffer was too small
|
||||
Invalid - Frame buffer was invalid
|
||||
"""
|
||||
Complete = 0
|
||||
Incomplete = -1
|
||||
TooSmall = -2
|
||||
Invalid = -3
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbFrameFlags(Uint32Enum):
|
||||
"""
|
||||
Frame Flags
|
||||
None_ - No additional information is provided
|
||||
Dimension - Frame's dimension is provided
|
||||
Offset - Frame's offset is provided (ROI)
|
||||
FrameID - Frame's ID is provided
|
||||
Timestamp - Frame's timestamp is provided
|
||||
"""
|
||||
None_ = 0
|
||||
Dimension = 1
|
||||
Offset = 2
|
||||
FrameID = 4
|
||||
Timestamp = 8
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbVersionInfo(ctypes.Structure):
|
||||
"""
|
||||
Version Information
|
||||
Fields:
|
||||
major - Type: VmbUint32, Info: Major version number
|
||||
minor - Type: VmbUint32, Info: Minor version number
|
||||
patch - Type: VmbUint32, Info: Patch version number
|
||||
"""
|
||||
_fields_ = [
|
||||
("major", VmbUint32),
|
||||
("minor", VmbUint32),
|
||||
("patch", VmbUint32)
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return '{}.{}.{}'.format(self.major, self.minor, self.patch)
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbVersionInfo'
|
||||
rep += '(major=' + repr(self.major)
|
||||
rep += ',minor=' + repr(self.minor)
|
||||
rep += ',patch=' + repr(self.patch)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbInterfaceInfo(ctypes.Structure):
|
||||
"""
|
||||
Interface information. Holds read-only information about an interface.
|
||||
Fields:
|
||||
interfaceIdString - Type: c_char_p
|
||||
Info: Unique identifier for each interface
|
||||
interfaceType - Type: VmbInterface (VmbUint32)
|
||||
Info: Interface type, see VmbInterface
|
||||
interfaceName - Type: c_char_p
|
||||
Info: Interface name, given by transport layer
|
||||
serialString - Type: c_char_p
|
||||
Info: Serial number
|
||||
permittedAccess - Type: VmbAccessMode (VmbUint32)
|
||||
Info: Used access mode, see VmbAccessMode
|
||||
"""
|
||||
_fields_ = [
|
||||
("interfaceIdString", c_char_p),
|
||||
("interfaceType", VmbUint32),
|
||||
("interfaceName", c_char_p),
|
||||
("serialString", c_char_p),
|
||||
("permittedAccess", VmbUint32)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbInterfaceInfo'
|
||||
rep += fmt_repr('(interfaceIdString={}', self.interfaceIdString)
|
||||
rep += fmt_enum_repr(',interfaceType={}', VmbInterface, self.interfaceType)
|
||||
rep += fmt_repr(',interfaceName={}', self.interfaceName)
|
||||
rep += fmt_repr(',serialString={}', self.serialString)
|
||||
rep += fmt_flags_repr(',permittedAccess={}', VmbAccessMode, self.permittedAccess)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbCameraInfo(ctypes.Structure):
|
||||
"""
|
||||
Camera information. Holds read-only information about a camera.
|
||||
Fields:
|
||||
cameraIdString - Type: c_char_p
|
||||
Info: Unique identifier for each camera
|
||||
cameraName - Type: c_char_p
|
||||
Info: Name of the camera
|
||||
modelName - Type: c_char_p
|
||||
Info: Model name
|
||||
serialString - Type: c_char_p
|
||||
Info: Serial number
|
||||
permittedAccess - Type: VmbAccessMode (VmbUint32)
|
||||
Info: Used access mode, see VmbAccessMode
|
||||
interfaceIdString - Type: c_char_p
|
||||
Info: Unique value for each interface or bus
|
||||
"""
|
||||
_fields_ = [
|
||||
("cameraIdString", c_char_p),
|
||||
("cameraName", c_char_p),
|
||||
("modelName", c_char_p),
|
||||
("serialString", c_char_p),
|
||||
("permittedAccess", VmbUint32),
|
||||
("interfaceIdString", c_char_p)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbCameraInfo'
|
||||
rep += fmt_repr('(cameraIdString={}', self.cameraIdString)
|
||||
rep += fmt_repr(',cameraName={}', self.cameraName)
|
||||
rep += fmt_repr(',modelName={}', self.modelName)
|
||||
rep += fmt_repr(',serialString={}', self.serialString)
|
||||
rep += fmt_flags_repr(',permittedAccess={}', VmbAccessMode, self.permittedAccess)
|
||||
rep += fmt_repr(',interfaceIdString={}', self.interfaceIdString)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbFeatureInfo(ctypes.Structure):
|
||||
"""
|
||||
Feature information. Holds read-only information about a feature.
|
||||
Fields:
|
||||
name - Type: c_char_p
|
||||
Info: Name used in the API
|
||||
featureDataType - Type: VmbFeatureData (VmbUint32)
|
||||
Info: Data type of this feature
|
||||
featureFlags - Type: VmbFeatureFlags (VmbUint32)
|
||||
Info: Access flags for this feature
|
||||
category - Type: c_char_p
|
||||
Info: Category this feature can be found in
|
||||
displayName - Type: c_char_p
|
||||
Info: Feature name to be used in GUIs
|
||||
pollingTime - Type: VmbUint32
|
||||
Info: Predefined polling time for volatile
|
||||
features
|
||||
unit - Type: c_char_p
|
||||
Info: Measuring unit as given in the XML file
|
||||
representation - Type: c_char_p
|
||||
Info: Representation of a numeric feature
|
||||
visibility - Type: VmbFeatureVisibility (VmbUint32)
|
||||
Info: GUI visibility
|
||||
tooltip - Type: c_char_p
|
||||
Info: Short description, e.g. for a tooltip
|
||||
description - Type: c_char_p
|
||||
Info: Longer description
|
||||
sfncNamespace - Type: c_char_p
|
||||
Info: Namespace this feature resides in
|
||||
isStreamable - Type: VmbBool
|
||||
Info: Indicates if a feature can be stored
|
||||
to / loaded from a file
|
||||
hasAffectedFeatures - Type: VmbBool
|
||||
Info: Indicates if the feature potentially
|
||||
affects other features
|
||||
hasSelectedFeatures - Type: VmbBool
|
||||
Info: Indicates if the feature selects other
|
||||
features
|
||||
"""
|
||||
_fields_ = [
|
||||
("name", c_char_p),
|
||||
("featureDataType", VmbUint32),
|
||||
("featureFlags", VmbUint32),
|
||||
("category", c_char_p),
|
||||
("displayName", c_char_p),
|
||||
("pollingTime", VmbUint32),
|
||||
("unit", c_char_p),
|
||||
("representation", c_char_p),
|
||||
("visibility", VmbUint32),
|
||||
("tooltip", c_char_p),
|
||||
("description", c_char_p),
|
||||
("sfncNamespace", c_char_p),
|
||||
("isStreamable", VmbBool),
|
||||
("hasAffectedFeatures", VmbBool),
|
||||
("hasSelectedFeatures", VmbBool)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbFeatureInfo'
|
||||
rep += fmt_repr('(name={}', self.name)
|
||||
rep += fmt_enum_repr(',featureDataType={}', VmbFeatureData, self.featureDataType)
|
||||
rep += fmt_flags_repr(',featureFlags={}', VmbFeatureFlags, self.featureFlags)
|
||||
rep += fmt_repr(',category={}', self.category)
|
||||
rep += fmt_repr(',displayName={}', self.displayName)
|
||||
rep += fmt_repr(',pollingTime={}', self.pollingTime)
|
||||
rep += fmt_repr(',unit={}', self.unit)
|
||||
rep += fmt_repr(',representation={}', self.representation)
|
||||
rep += fmt_enum_repr(',visibility={}', VmbFeatureVisibility, self.visibility)
|
||||
rep += fmt_repr(',tooltip={}', self.tooltip)
|
||||
rep += fmt_repr(',description={}', self.description)
|
||||
rep += fmt_repr(',sfncNamespace={}', self.sfncNamespace)
|
||||
rep += fmt_repr(',isStreamable={}', self.isStreamable)
|
||||
rep += fmt_repr(',hasAffectedFeatures={}', self.hasAffectedFeatures)
|
||||
rep += fmt_repr(',hasSelectedFeatures={}', self.hasSelectedFeatures)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbFeatureEnumEntry(ctypes.Structure):
|
||||
"""
|
||||
Info about possible entries of an enumeration feature:
|
||||
Fields:
|
||||
name - Type: c_char_p
|
||||
Info: Name used in the API
|
||||
displayName - Type: c_char_p
|
||||
Info: Enumeration entry name to be used in GUIs
|
||||
visibility - Type: VmbFeatureVisibility (VmbUint32)
|
||||
Info: GUI visibility
|
||||
tooltip - Type: c_char_p
|
||||
Info: Short description, e.g. for a tooltip
|
||||
description - Type: c_char_p
|
||||
Info: Longer description
|
||||
sfncNamespace - Type: c_char_p
|
||||
Info: Namespace this feature resides in
|
||||
intValue - Type: VmbInt64
|
||||
Info: Integer value of this enumeration entry
|
||||
"""
|
||||
_fields_ = [
|
||||
("name", c_char_p),
|
||||
("displayName", c_char_p),
|
||||
("visibility", VmbUint32),
|
||||
("tooltip", c_char_p),
|
||||
("description", c_char_p),
|
||||
("sfncNamespace", c_char_p),
|
||||
("intValue", VmbInt64)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbFeatureEnumEntry'
|
||||
rep += fmt_repr('(name={}', self.name)
|
||||
rep += fmt_repr(',displayName={}', self.displayName)
|
||||
rep += fmt_enum_repr(',visibility={}', VmbFeatureVisibility, self.visibility)
|
||||
rep += fmt_repr(',tooltip={}', self.tooltip)
|
||||
rep += fmt_repr(',description={}', self.description)
|
||||
rep += fmt_repr(',sfncNamespace={}', self.sfncNamespace)
|
||||
rep += fmt_repr(',intValue={},', self.intValue)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbFrame(ctypes.Structure):
|
||||
"""
|
||||
Frame delivered by Camera
|
||||
Fields (in):
|
||||
buffer - Type: c_void_p
|
||||
Info: Comprises image and ancillary data
|
||||
bufferSize - Type: VmbUint32_t
|
||||
Info: Size of the data buffer
|
||||
context - Type: c_void_p[4]
|
||||
Info: 4 void pointers that can be employed by the user
|
||||
(e.g. for storing handles)
|
||||
|
||||
Fields (out):
|
||||
receiveStatus - Type: VmbFrameStatus (VmbInt32)
|
||||
Info: Resulting status of the receive operation
|
||||
receiveFlags - Type: VmbFrameFlags (VmbUint32)
|
||||
Info: Flags indicating which additional frame
|
||||
information is available
|
||||
imageSize - Type: VmbUint32
|
||||
Info: Size of the image data inside the data buffer
|
||||
ancillarySize - Type: VmbUint32
|
||||
Info: Size of the ancillary data inside the
|
||||
data buffer
|
||||
pixelFormat - Type: VmbPixelFormat (VmbUint32)
|
||||
Info: Pixel format of the image
|
||||
width - Type: VmbUint32
|
||||
Info: Width of an image
|
||||
height - Type: VmbUint32
|
||||
Info: Height of an image
|
||||
offsetX - Type: VmbUint32
|
||||
Info: Horizontal offset of an image
|
||||
offsetY - Type: VmbUint32
|
||||
Info: Vertical offset of an image
|
||||
frameID - Type: VmbUint64
|
||||
Info: Unique ID of this frame in this stream
|
||||
timestamp - Type: VmbUint64
|
||||
Info: Timestamp set by the camera
|
||||
"""
|
||||
_fields_ = [
|
||||
("buffer", c_void_p),
|
||||
("bufferSize", VmbUint32),
|
||||
("context", c_void_p * 4),
|
||||
("receiveStatus", VmbInt32),
|
||||
("receiveFlags", VmbUint32),
|
||||
("imageSize", VmbUint32),
|
||||
("ancillarySize", VmbUint32),
|
||||
("pixelFormat", VmbUint32),
|
||||
("width", VmbUint32),
|
||||
("height", VmbUint32),
|
||||
("offsetX", VmbUint32),
|
||||
("offsetY", VmbUint32),
|
||||
("frameID", VmbUint64),
|
||||
("timestamp", VmbUint64)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbFrame'
|
||||
rep += fmt_repr('(buffer={}', self.buffer)
|
||||
rep += fmt_repr(',bufferSize={}', self.bufferSize)
|
||||
rep += fmt_repr(',context={}', self.context)
|
||||
rep += fmt_enum_repr('receiveStatus: {}', VmbFrameStatus, self.receiveStatus)
|
||||
rep += fmt_flags_repr(',receiveFlags={}', VmbFrameFlags, self.receiveFlags)
|
||||
rep += fmt_repr(',imageSize={}', self.imageSize)
|
||||
rep += fmt_repr(',ancillarySize={}', self.ancillarySize)
|
||||
rep += fmt_enum_repr(',pixelFormat={}', VmbPixelFormat, self.pixelFormat)
|
||||
rep += fmt_repr(',width={}', self.width)
|
||||
rep += fmt_repr(',height={}', self.height)
|
||||
rep += fmt_repr(',offsetX={}', self.offsetX)
|
||||
rep += fmt_repr(',offsetY={}', self.offsetY)
|
||||
rep += fmt_repr(',frameID={}', self.frameID)
|
||||
rep += fmt_repr(',timestamp={}', self.timestamp)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
def deepcopy_skip_ptr(self, memo):
|
||||
result = VmbFrame()
|
||||
memo[id(self)] = result
|
||||
|
||||
result.buffer = None
|
||||
result.bufferSize = 0
|
||||
result.context = (None, None, None, None)
|
||||
|
||||
setattr(result, 'receiveStatus', copy.deepcopy(self.receiveStatus, memo))
|
||||
setattr(result, 'receiveFlags', copy.deepcopy(self.receiveFlags, memo))
|
||||
setattr(result, 'imageSize', copy.deepcopy(self.imageSize, memo))
|
||||
setattr(result, 'ancillarySize', copy.deepcopy(self.ancillarySize, memo))
|
||||
setattr(result, 'pixelFormat', copy.deepcopy(self.pixelFormat, memo))
|
||||
setattr(result, 'width', copy.deepcopy(self.width, memo))
|
||||
setattr(result, 'height', copy.deepcopy(self.height, memo))
|
||||
setattr(result, 'offsetX', copy.deepcopy(self.offsetX, memo))
|
||||
setattr(result, 'offsetY', copy.deepcopy(self.offsetY, memo))
|
||||
setattr(result, 'frameID', copy.deepcopy(self.frameID, memo))
|
||||
setattr(result, 'timestamp', copy.deepcopy(self.timestamp, memo))
|
||||
return result
|
||||
|
||||
|
||||
class VmbFeaturePersistSettings(ctypes.Structure):
|
||||
"""
|
||||
Parameters determining the operation mode of VmbCameraSettingsSave
|
||||
and VmbCameraSettingsLoad
|
||||
Fields:
|
||||
persistType - Type: VmbFeaturePersist (VmbUint32)
|
||||
Info: Type of features that are to be saved
|
||||
maxIterations - Type: VmbUint32
|
||||
Info: Number of iterations when loading settings
|
||||
loggingLevel - Type: VmbUint32
|
||||
Info: Determines level of detail for load/save
|
||||
settings logging
|
||||
"""
|
||||
_fields_ = [
|
||||
("persistType", VmbUint32),
|
||||
("maxIterations", VmbUint32),
|
||||
("loggingLevel", VmbUint32)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbFrame'
|
||||
rep += fmt_enum_repr('(persistType={}', VmbFeaturePersist, self.persistType)
|
||||
rep += fmt_repr(',maxIterations={}', self.maxIterations)
|
||||
rep += fmt_repr(',loggingLevel={}', self.loggingLevel)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
G_VIMBA_C_HANDLE = VmbHandle(1)
|
||||
|
||||
VIMBA_C_VERSION = None
|
||||
EXPECTED_VIMBA_C_VERSION = '1.9.0'
|
||||
|
||||
# For detailed information on the signatures see "VimbaC.h"
|
||||
# To improve readability, suppress 'E501 line too long (> 100 characters)'
|
||||
# check of flake8
|
||||
_SIGNATURES = {
|
||||
'VmbVersionQuery': (VmbError, [c_ptr(VmbVersionInfo), VmbUint32]),
|
||||
'VmbStartup': (VmbError, None),
|
||||
'VmbShutdown': (None, None),
|
||||
'VmbCamerasList': (VmbError, [c_ptr(VmbCameraInfo), VmbUint32, c_ptr(VmbUint32), VmbUint32]),
|
||||
'VmbCameraInfoQuery': (VmbError, [c_str, c_ptr(VmbCameraInfo), VmbUint32]),
|
||||
'VmbCameraOpen': (VmbError, [c_str, VmbAccessMode, c_ptr(VmbHandle)]),
|
||||
'VmbCameraClose': (VmbError, [VmbHandle]),
|
||||
'VmbFeaturesList': (VmbError, [VmbHandle, c_ptr(VmbFeatureInfo), VmbUint32, c_ptr(VmbUint32), VmbUint32]), # noqa: E501
|
||||
'VmbFeatureInfoQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbFeatureInfo), VmbUint32]),
|
||||
'VmbFeatureListAffected': (VmbError, [VmbHandle, c_str, c_ptr(VmbFeatureInfo), VmbUint32, c_ptr(VmbUint32), VmbUint32]), # noqa: E501
|
||||
'VmbFeatureListSelected': (VmbError, [VmbHandle, c_str, c_ptr(VmbFeatureInfo), VmbUint32, c_ptr(VmbUint32), VmbUint32]), # noqa: E501
|
||||
'VmbFeatureAccessQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbBool), c_ptr(VmbBool)]),
|
||||
'VmbFeatureIntGet': (VmbError, [VmbHandle, c_str, c_ptr(VmbInt64)]),
|
||||
'VmbFeatureIntSet': (VmbError, [VmbHandle, c_str, VmbInt64]),
|
||||
'VmbFeatureIntRangeQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbInt64), c_ptr(VmbInt64)]), # noqa: E501
|
||||
'VmbFeatureIntIncrementQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbInt64)]),
|
||||
'VmbFeatureFloatGet': (VmbError, [VmbHandle, c_str, c_ptr(VmbDouble)]),
|
||||
'VmbFeatureFloatSet': (VmbError, [VmbHandle, c_str, VmbDouble]),
|
||||
'VmbFeatureFloatRangeQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbDouble), c_ptr(VmbDouble)]),
|
||||
'VmbFeatureFloatIncrementQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbBool), c_ptr(VmbDouble)]), # noqa: E501
|
||||
'VmbFeatureEnumGet': (VmbError, [VmbHandle, c_str, c_ptr(c_str)]),
|
||||
'VmbFeatureEnumSet': (VmbError, [VmbHandle, c_str, c_str]),
|
||||
'VmbFeatureEnumRangeQuery': (VmbError, [VmbHandle, c_str, c_ptr(c_str), VmbUint32, c_ptr(VmbUint32)]), # noqa: E501
|
||||
'VmbFeatureEnumIsAvailable': (VmbError, [VmbHandle, c_str, c_str, c_ptr(VmbBool)]),
|
||||
'VmbFeatureEnumAsInt': (VmbError, [VmbHandle, c_str, c_str, c_ptr(VmbInt64)]),
|
||||
'VmbFeatureEnumAsString': (VmbError, [VmbHandle, c_str, VmbInt64, c_ptr(c_str)]),
|
||||
'VmbFeatureEnumEntryGet': (VmbError, [VmbHandle, c_str, c_str, c_ptr(VmbFeatureEnumEntry), VmbUint32]), # noqa: E501
|
||||
'VmbFeatureStringGet': (VmbError, [VmbHandle, c_str, c_str, VmbUint32, c_ptr(VmbUint32)]), # noqa: E501
|
||||
'VmbFeatureStringSet': (VmbError, [VmbHandle, c_str, c_str]),
|
||||
'VmbFeatureStringMaxlengthQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbUint32)]),
|
||||
'VmbFeatureBoolGet': (VmbError, [VmbHandle, c_str, c_ptr(VmbBool)]),
|
||||
'VmbFeatureBoolSet': (VmbError, [VmbHandle, c_str, VmbBool]),
|
||||
'VmbFeatureCommandRun': (VmbError, [VmbHandle, c_str]),
|
||||
'VmbFeatureCommandIsDone': (VmbError, [VmbHandle, c_str, c_ptr(VmbBool)]),
|
||||
'VmbFeatureRawGet': (VmbError, [VmbHandle, c_str, c_str, VmbUint32, c_ptr(VmbUint32)]),
|
||||
'VmbFeatureRawSet': (VmbError, [VmbHandle, c_str, c_str, VmbUint32]),
|
||||
'VmbFeatureRawLengthQuery': (VmbError, [VmbHandle, c_str, c_ptr(VmbUint32)]),
|
||||
'VmbFeatureInvalidationRegister': (VmbError, [VmbHandle, c_str, c_void_p, c_void_p]), # noqa: E501
|
||||
'VmbFeatureInvalidationUnregister': (VmbError, [VmbHandle, c_str, c_void_p]),
|
||||
'VmbFrameAnnounce': (VmbError, [VmbHandle, c_ptr(VmbFrame), VmbUint32]),
|
||||
'VmbFrameRevoke': (VmbError, [VmbHandle, c_ptr(VmbFrame)]),
|
||||
'VmbFrameRevokeAll': (VmbError, [VmbHandle]),
|
||||
'VmbCaptureStart': (VmbError, [VmbHandle]),
|
||||
'VmbCaptureEnd': (VmbError, [VmbHandle]),
|
||||
'VmbCaptureFrameQueue': (VmbError, [VmbHandle, c_ptr(VmbFrame), c_void_p]),
|
||||
'VmbCaptureFrameWait': (VmbError, [VmbHandle, c_ptr(VmbFrame), VmbUint32]),
|
||||
'VmbCaptureQueueFlush': (VmbError, [VmbHandle]),
|
||||
'VmbInterfacesList': (VmbError, [c_ptr(VmbInterfaceInfo), VmbUint32, c_ptr(VmbUint32), VmbUint32]), # noqa: E501
|
||||
'VmbInterfaceOpen': (VmbError, [c_str, c_ptr(VmbHandle)]),
|
||||
'VmbInterfaceClose': (VmbError, [VmbHandle]),
|
||||
'VmbAncillaryDataOpen': (VmbError, [c_ptr(VmbFrame), c_ptr(VmbHandle)]),
|
||||
'VmbAncillaryDataClose': (VmbError, [VmbHandle]),
|
||||
'VmbMemoryRead': (VmbError, [VmbHandle, VmbUint64, VmbUint32, c_str, c_ptr(VmbUint32)]),
|
||||
'VmbMemoryWrite': (VmbError, [VmbHandle, VmbUint64, VmbUint32, c_str, c_ptr(VmbUint32)]),
|
||||
'VmbRegistersRead': (VmbError, [VmbHandle, VmbUint32, c_ptr(VmbUint64), c_ptr(VmbUint64), c_ptr(VmbUint32)]), # noqa: E501
|
||||
'VmbRegistersWrite': (VmbError, [VmbHandle, VmbUint32, c_ptr(VmbUint64), c_ptr(VmbUint64), c_ptr(VmbUint32)]), # noqa: E501
|
||||
'VmbCameraSettingsSave': (VmbError, [VmbHandle, c_str, c_ptr(VmbFeaturePersistSettings), VmbUint32]), # noqa: E501
|
||||
'VmbCameraSettingsLoad': (VmbError, [VmbHandle, c_str, c_ptr(VmbFeaturePersistSettings), VmbUint32]) # noqa: E501
|
||||
}
|
||||
|
||||
|
||||
def _attach_signatures(lib_handle):
|
||||
global _SIGNATURES
|
||||
|
||||
for function_name, signature in _SIGNATURES.items():
|
||||
fn = getattr(lib_handle, function_name)
|
||||
fn.restype, fn.argtypes = signature
|
||||
fn.errcheck = _eval_vmberror
|
||||
|
||||
return lib_handle
|
||||
|
||||
|
||||
def _check_version(lib_handle):
|
||||
global EXPECTED_VIMBA_C_VERSION
|
||||
global VIMBA_C_VERSION
|
||||
|
||||
v = VmbVersionInfo()
|
||||
lib_handle.VmbVersionQuery(byref(v), sizeof(v))
|
||||
|
||||
VIMBA_C_VERSION = str(v)
|
||||
|
||||
loaded_version = (v.major, v.minor, v.patch)
|
||||
expected_version = tuple(map(int, EXPECTED_VIMBA_C_VERSION.split(".")))
|
||||
# major and minor version must be equal, patch version may be equal or greater
|
||||
if not(loaded_version[0:2] == expected_version[0:2] and
|
||||
loaded_version[2] >= expected_version[2]):
|
||||
msg = 'Invalid VimbaC Version: Expected: {}, Found:{}'
|
||||
raise VimbaSystemError(msg.format(EXPECTED_VIMBA_C_VERSION, VIMBA_C_VERSION))
|
||||
|
||||
return lib_handle
|
||||
|
||||
|
||||
def _eval_vmberror(result: VmbError, func: Callable[..., Any], *args: Tuple[Any, ...]):
|
||||
if result not in (VmbError.Success, None):
|
||||
raise VimbaCError(result)
|
||||
|
||||
|
||||
_lib_instance = _check_version(_attach_signatures(load_vimba_lib('VimbaC')))
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def call_vimba_c(func_name: str, *args):
|
||||
"""This function encapsulates the entire VimbaC access.
|
||||
|
||||
For Details on valid function signatures see the 'VimbaC.h'.
|
||||
|
||||
Arguments:
|
||||
func_name: The function name from VimbaC to be called.
|
||||
args: Varargs passed directly to the underlaying C-Function.
|
||||
|
||||
Raises:
|
||||
TypeError if given are do not match the signature of the function.
|
||||
AttributeError if func with name 'func_name' does not exist.
|
||||
VimbaCError if the function call is valid but neither None or VmbError.Success was returned.
|
||||
|
||||
The following functions of VimbaC can be executed:
|
||||
VmbVersionQuery
|
||||
VmbStartup
|
||||
VmbShutdown
|
||||
VmbCamerasList
|
||||
VmbCameraInfoQuery
|
||||
VmbCameraOpen
|
||||
VmbCameraClose
|
||||
VmbFeaturesList
|
||||
VmbFeatureInfoQuery
|
||||
VmbFeatureListAffected
|
||||
VmbFeatureListSelected
|
||||
VmbFeatureAccessQuery
|
||||
VmbFeatureIntGet
|
||||
VmbFeatureIntSet
|
||||
VmbFeatureIntRangeQuery
|
||||
VmbFeatureIntIncrementQuery
|
||||
VmbFeatureFloatGet
|
||||
VmbFeatureFloatSet
|
||||
VmbFeatureFloatRangeQuery
|
||||
VmbFeatureFloatIncrementQuery
|
||||
VmbFeatureEnumGet
|
||||
VmbFeatureEnumSet
|
||||
VmbFeatureEnumRangeQuery
|
||||
VmbFeatureEnumIsAvailable
|
||||
VmbFeatureEnumAsInt
|
||||
VmbFeatureEnumAsString
|
||||
VmbFeatureEnumEntryGet
|
||||
VmbFeatureStringGet
|
||||
VmbFeatureStringSet
|
||||
VmbFeatureStringMaxlengthQuery
|
||||
VmbFeatureBoolGet
|
||||
VmbFeatureBoolSet
|
||||
VmbFeatureCommandRun
|
||||
VmbFeatureCommandIsDone
|
||||
VmbFeatureRawGet
|
||||
VmbFeatureRawSet
|
||||
VmbFeatureRawLengthQuery
|
||||
VmbFeatureInvalidationRegister
|
||||
VmbFeatureInvalidationUnregister
|
||||
VmbFrameAnnounce
|
||||
VmbFrameRevoke
|
||||
VmbFrameRevokeAll
|
||||
VmbCaptureStart
|
||||
VmbCaptureEnd
|
||||
VmbCaptureFrameQueue
|
||||
VmbCaptureFrameWait
|
||||
VmbCaptureQueueFlush
|
||||
VmbInterfacesList
|
||||
VmbInterfaceOpen
|
||||
VmbInterfaceClose
|
||||
VmbAncillaryDataOpen
|
||||
VmbAncillaryDataClose
|
||||
VmbMemoryRead
|
||||
VmbMemoryWrite
|
||||
VmbRegistersRead
|
||||
VmbRegistersWrite
|
||||
VmbCameraSettingsSave
|
||||
VmbCameraSettingsLoad
|
||||
"""
|
||||
global _lib_instance
|
||||
getattr(_lib_instance, func_name)(*args)
|
||||
|
||||
|
||||
def build_callback_type(*args):
|
||||
global _lib_instance
|
||||
|
||||
lib_type = type(_lib_instance)
|
||||
|
||||
if lib_type == ctypes.CDLL:
|
||||
return ctypes.CFUNCTYPE(*args)
|
||||
|
||||
elif lib_type == ctypes.WinDLL:
|
||||
return ctypes.WINFUNCTYPE(*args)
|
||||
|
||||
else:
|
||||
raise VimbaSystemError('Unknown Library Type. Abort.')
|
||||
611
Vimba_6_0/VimbaPython/Source/vimba/c_binding/vimba_common.py
Normal file
611
Vimba_6_0/VimbaPython/Source/vimba/c_binding/vimba_common.py
Normal file
@@ -0,0 +1,611 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import enum
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
import functools
|
||||
from typing import Tuple, List
|
||||
from ..error import VimbaSystemError
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Int32Enum',
|
||||
'Uint32Enum',
|
||||
'VmbInt8',
|
||||
'VmbUint8',
|
||||
'VmbInt16',
|
||||
'VmbUint16',
|
||||
'VmbInt32',
|
||||
'VmbUint32',
|
||||
'VmbInt64',
|
||||
'VmbUint64',
|
||||
'VmbHandle',
|
||||
'VmbBool',
|
||||
'VmbUchar',
|
||||
'VmbFloat',
|
||||
'VmbDouble',
|
||||
'VmbError',
|
||||
'VimbaCError',
|
||||
'VmbPixelFormat',
|
||||
'decode_cstr',
|
||||
'decode_flags',
|
||||
'fmt_repr',
|
||||
'fmt_enum_repr',
|
||||
'fmt_flags_repr',
|
||||
'load_vimba_lib'
|
||||
]
|
||||
|
||||
|
||||
# Types
|
||||
class Int32Enum(enum.IntEnum):
|
||||
@classmethod
|
||||
def from_param(cls, obj):
|
||||
return ctypes.c_int(obj)
|
||||
|
||||
|
||||
class Uint32Enum(enum.IntEnum):
|
||||
@classmethod
|
||||
def from_param(cls, obj):
|
||||
return ctypes.c_uint(obj)
|
||||
|
||||
|
||||
# Aliases for vmb base types
|
||||
VmbInt8 = ctypes.c_byte
|
||||
VmbUint8 = ctypes.c_ubyte
|
||||
VmbInt16 = ctypes.c_short
|
||||
VmbUint16 = ctypes.c_ushort
|
||||
VmbInt32 = ctypes.c_int
|
||||
VmbUint32 = ctypes.c_uint
|
||||
VmbInt64 = ctypes.c_longlong
|
||||
VmbUint64 = ctypes.c_ulonglong
|
||||
VmbHandle = ctypes.c_void_p
|
||||
VmbBool = ctypes.c_bool
|
||||
VmbUchar = ctypes.c_char
|
||||
VmbFloat = ctypes.c_float
|
||||
VmbDouble = ctypes.c_double
|
||||
|
||||
|
||||
class VmbError(Int32Enum):
|
||||
"""
|
||||
Enum containing error types returned
|
||||
Success - No error
|
||||
InternalFault - Unexpected fault in VimbaC or driver
|
||||
ApiNotStarted - VmbStartup() was not called before the current
|
||||
command
|
||||
NotFound - The designated instance (camera, feature etc.)
|
||||
cannot be found
|
||||
BadHandle - The given handle is not valid
|
||||
DeviceNotOpen - Device was not opened for usage
|
||||
InvalidAccess - Operation is invalid with the current access mode
|
||||
BadParameter - One of the parameters is invalid (usually an illegal
|
||||
pointer)
|
||||
StructSize - The given struct size is not valid for this version
|
||||
of the API
|
||||
MoreData - More data available in a string/list than space is
|
||||
provided
|
||||
WrongType - Wrong feature type for this access function
|
||||
InvalidValue - The value is not valid; Either out of bounds or not
|
||||
an increment of the minimum
|
||||
Timeout - Timeout during wait
|
||||
Other - Other error
|
||||
Resources - Resources not available (e.g. memory)
|
||||
InvalidCall - Call is invalid in the current context (callback)
|
||||
NoTL - No transport layers are found
|
||||
NotImplemented_ - API feature is not implemented
|
||||
NotSupported - API feature is not supported
|
||||
Incomplete - A multiple registers read or write is partially
|
||||
completed
|
||||
IO - low level IO error in transport layer
|
||||
"""
|
||||
Success = 0
|
||||
InternalFault = -1
|
||||
ApiNotStarted = -2
|
||||
NotFound = -3
|
||||
BadHandle = -4
|
||||
DeviceNotOpen = -5
|
||||
InvalidAccess = -6
|
||||
BadParameter = -7
|
||||
StructSize = -8
|
||||
MoreData = -9
|
||||
WrongType = -10
|
||||
InvalidValue = -11
|
||||
Timeout = -12
|
||||
Other = -13
|
||||
Resources = -14
|
||||
InvalidCall = -15
|
||||
NoTL = -16
|
||||
NotImplemented_ = -17
|
||||
NotSupported = -18
|
||||
Incomplete = -19
|
||||
IO = -20
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class _VmbPixel(Uint32Enum):
|
||||
Mono = 0x01000000
|
||||
Color = 0x02000000
|
||||
|
||||
|
||||
class _VmbPixelOccupy(Uint32Enum):
|
||||
Bit8 = 0x00080000
|
||||
Bit10 = 0x000A0000
|
||||
Bit12 = 0x000C0000
|
||||
Bit14 = 0x000E0000
|
||||
Bit16 = 0x00100000
|
||||
Bit24 = 0x00180000
|
||||
Bit32 = 0x00200000
|
||||
Bit48 = 0x00300000
|
||||
Bit64 = 0x00400000
|
||||
|
||||
|
||||
class VmbPixelFormat(Uint32Enum):
|
||||
"""
|
||||
Enum containing Pixelformats
|
||||
Mono formats:
|
||||
Mono8 - Monochrome, 8 bits (PFNC:Mono8)
|
||||
Mono10 - Monochrome, 10 bits in 16 bits (PFNC:Mono10)
|
||||
Mono10p - Monochrome, 4x10 bits continuously packed in 40 bits
|
||||
(PFNC:Mono10p)
|
||||
Mono12 - Monochrome, 12 bits in 16 bits (PFNC:Mono12)
|
||||
Mono12Packed - Monochrome, 2x12 bits in 24 bits (GEV:Mono12Packed)
|
||||
Mono12p - Monochrome, 2x12 bits continuously packed in 24 bits
|
||||
(PFNC:Mono12p)
|
||||
Mono14 - Monochrome, 14 bits in 16 bits (PFNC:Mono14)
|
||||
Mono16 - Monochrome, 16 bits (PFNC:Mono16)
|
||||
|
||||
Bayer formats:
|
||||
BayerGR8 - Bayer-color, 8 bits, starting with GR line
|
||||
(PFNC:BayerGR8)
|
||||
BayerRG8 - Bayer-color, 8 bits, starting with RG line
|
||||
(PFNC:BayerRG8)
|
||||
BayerGB8 - Bayer-color, 8 bits, starting with GB line
|
||||
(PFNC:BayerGB8)
|
||||
BayerBG8 - Bayer-color, 8 bits, starting with BG line
|
||||
(PFNC:BayerBG8)
|
||||
BayerGR10 - Bayer-color, 10 bits in 16 bits, starting with GR
|
||||
line (PFNC:BayerGR10)
|
||||
BayerRG10 - Bayer-color, 10 bits in 16 bits, starting with RG
|
||||
line (PFNC:BayerRG10)
|
||||
BayerGB10 - Bayer-color, 10 bits in 16 bits, starting with GB
|
||||
line (PFNC:BayerGB10)
|
||||
BayerBG10 - Bayer-color, 10 bits in 16 bits, starting with BG
|
||||
line (PFNC:BayerBG10)
|
||||
BayerGR12 - Bayer-color, 12 bits in 16 bits, starting with GR
|
||||
line (PFNC:BayerGR12)
|
||||
BayerRG12 - Bayer-color, 12 bits in 16 bits, starting with RG
|
||||
line (PFNC:BayerRG12)
|
||||
BayerGB12 - Bayer-color, 12 bits in 16 bits, starting with GB
|
||||
line (PFNC:BayerGB12)
|
||||
BayerBG12 - Bayer-color, 12 bits in 16 bits, starting with BG
|
||||
line (PFNC:BayerBG12)
|
||||
BayerGR12Packed - Bayer-color, 2x12 bits in 24 bits, starting with GR
|
||||
line (GEV:BayerGR12Packed)
|
||||
BayerRG12Packed - Bayer-color, 2x12 bits in 24 bits, starting with RG
|
||||
line (GEV:BayerRG12Packed)
|
||||
BayerGB12Packed - Bayer-color, 2x12 bits in 24 bits, starting with GB
|
||||
line (GEV:BayerGB12Packed)
|
||||
BayerBG12Packed - Bayer-color, 2x12 bits in 24 bits, starting with BG
|
||||
line (GEV:BayerBG12Packed)
|
||||
BayerGR10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with GR line (PFNC:BayerGR10p)
|
||||
BayerRG10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with RG line (PFNC:BayerRG10p)
|
||||
BayerGB10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with GB line (PFNC:BayerGB10p)
|
||||
BayerBG10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with BG line (PFNC:BayerBG10p)
|
||||
BayerGR12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with GR line (PFNC:BayerGR12p)
|
||||
BayerRG12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with RG line (PFNC:BayerRG12p)
|
||||
BayerGB12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with GB line (PFNC:BayerGB12p)
|
||||
BayerBG12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with BG line (PFNC:BayerBG12p)
|
||||
BayerGR16 - Bayer-color, 16 bits, starting with GR line
|
||||
(PFNC:BayerGR16)
|
||||
BayerRG16 - Bayer-color, 16 bits, starting with RG line
|
||||
(PFNC:BayerRG16)
|
||||
BayerGB16 - Bayer-color, 16 bits, starting with GB line
|
||||
(PFNC:BayerGB16)
|
||||
BayerBG16 - Bayer-color, 16 bits, starting with BG line
|
||||
(PFNC:BayerBG16)
|
||||
|
||||
RGB formats:
|
||||
Rgb8 - RGB, 8 bits x 3 (PFNC:RGB8)
|
||||
Bgr8 - BGR, 8 bits x 3 (PFNC:Bgr8)
|
||||
Rgb10 - RGB, 10 bits in 16 bits x 3 (PFNC:RGB10)
|
||||
Bgr10 - BGR, 10 bits in 16 bits x 3 (PFNC:BGR10)
|
||||
Rgb12 - RGB, 12 bits in 16 bits x 3 (PFNC:RGB12)
|
||||
Bgr12 - BGR, 12 bits in 16 bits x 3 (PFNC:BGR12)
|
||||
Rgb14 - RGB, 14 bits in 16 bits x 3 (PFNC:RGB14)
|
||||
Bgr14 - BGR, 14 bits in 16 bits x 3 (PFNC:BGR14)
|
||||
Rgb16 - RGB, 16 bits x 3 (PFNC:RGB16)
|
||||
Bgr16 - BGR, 16 bits x 3 (PFNC:BGR16)
|
||||
|
||||
RGBA formats:
|
||||
Argb8 - ARGB, 8 bits x 4 (PFNC:RGBa8)
|
||||
Rgba8 - RGBA, 8 bits x 4, legacy name
|
||||
Bgra8 - BGRA, 8 bits x 4 (PFNC:BGRa8)
|
||||
Rgba10 - RGBA, 10 bits in 16 bits x 4
|
||||
Bgra10 - BGRA, 10 bits in 16 bits x 4
|
||||
Rgba12 - RGBA, 12 bits in 16 bits x 4
|
||||
Bgra12 - BGRA, 12 bits in 16 bits x 4
|
||||
Rgba14 - RGBA, 14 bits in 16 bits x 4
|
||||
Bgra14 - BGRA, 14 bits in 16 bits x 4
|
||||
Rgba16 - RGBA, 16 bits x 4
|
||||
Bgra16 - BGRA, 16 bits x 4
|
||||
|
||||
YUV/YCbCr formats:
|
||||
Yuv411 - YUV 411 with 8 bits (GEV:YUV411Packed)
|
||||
Yuv422 - YUV 422 with 8 bits (GEV:YUV422Packed)
|
||||
Yuv444 - YUV 444 with 8 bits (GEV:YUV444Packed)
|
||||
YCbCr411_8_CbYYCrYY - Y´CbCr 411 with 8 bits
|
||||
(PFNC:YCbCr411_8_CbYYCrYY) - identical to Yuv411
|
||||
YCbCr422_8_CbYCrY - Y´CbCr 422 with 8 bits
|
||||
(PFNC:YCbCr422_8_CbYCrY) - identical to Yuv422
|
||||
YCbCr8_CbYCr - Y´CbCr 444 with 8 bits
|
||||
(PFNC:YCbCr8_CbYCr) - identical to Yuv444
|
||||
"""
|
||||
None_ = 0
|
||||
Mono8 = _VmbPixel.Mono | _VmbPixelOccupy.Bit8 | 0x0001
|
||||
Mono10 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0003
|
||||
Mono10p = _VmbPixel.Mono | _VmbPixelOccupy.Bit10 | 0x0046
|
||||
Mono12 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0005
|
||||
Mono12Packed = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x0006
|
||||
Mono12p = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x0047
|
||||
Mono14 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0025
|
||||
Mono16 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0007
|
||||
BayerGR8 = _VmbPixel.Mono | _VmbPixelOccupy.Bit8 | 0x0008
|
||||
BayerRG8 = _VmbPixel.Mono | _VmbPixelOccupy.Bit8 | 0x0009
|
||||
BayerGB8 = _VmbPixel.Mono | _VmbPixelOccupy.Bit8 | 0x000A
|
||||
BayerBG8 = _VmbPixel.Mono | _VmbPixelOccupy.Bit8 | 0x000B
|
||||
BayerGR10 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x000C
|
||||
BayerRG10 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x000D
|
||||
BayerGB10 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x000E
|
||||
BayerBG10 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x000F
|
||||
BayerGR12 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0010
|
||||
BayerRG12 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0011
|
||||
BayerGB12 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0012
|
||||
BayerBG12 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0013
|
||||
BayerGR12Packed = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x002A
|
||||
BayerRG12Packed = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x002B
|
||||
BayerGB12Packed = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x002C
|
||||
BayerBG12Packed = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x002D
|
||||
BayerGR10p = _VmbPixel.Mono | _VmbPixelOccupy.Bit10 | 0x0056
|
||||
BayerRG10p = _VmbPixel.Mono | _VmbPixelOccupy.Bit10 | 0x0058
|
||||
BayerGB10p = _VmbPixel.Mono | _VmbPixelOccupy.Bit10 | 0x0054
|
||||
BayerBG10p = _VmbPixel.Mono | _VmbPixelOccupy.Bit10 | 0x0052
|
||||
BayerGR12p = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x0057
|
||||
BayerRG12p = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x0059
|
||||
BayerGB12p = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x0055
|
||||
BayerBG12p = _VmbPixel.Mono | _VmbPixelOccupy.Bit12 | 0x0053
|
||||
BayerGR16 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x002E
|
||||
BayerRG16 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x002F
|
||||
BayerGB16 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0030
|
||||
BayerBG16 = _VmbPixel.Mono | _VmbPixelOccupy.Bit16 | 0x0031
|
||||
Rgb8 = _VmbPixel.Color | _VmbPixelOccupy.Bit24 | 0x0014
|
||||
Bgr8 = _VmbPixel.Color | _VmbPixelOccupy.Bit24 | 0x0015
|
||||
Rgb10 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x0018
|
||||
Bgr10 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x0019
|
||||
Rgb12 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x001A
|
||||
Bgr12 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x001B
|
||||
Rgb14 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x005E
|
||||
Bgr14 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x004A
|
||||
Rgb16 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x0033
|
||||
Bgr16 = _VmbPixel.Color | _VmbPixelOccupy.Bit48 | 0x004B
|
||||
Argb8 = _VmbPixel.Color | _VmbPixelOccupy.Bit32 | 0x0016
|
||||
Rgba8 = Argb8
|
||||
Bgra8 = _VmbPixel.Color | _VmbPixelOccupy.Bit32 | 0x0017
|
||||
Rgba10 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x005F
|
||||
Bgra10 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x004C
|
||||
Rgba12 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x0061
|
||||
Bgra12 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x004E
|
||||
Rgba14 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x0063
|
||||
Bgra14 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x0050
|
||||
Rgba16 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x0064
|
||||
Bgra16 = _VmbPixel.Color | _VmbPixelOccupy.Bit64 | 0x0051
|
||||
Yuv411 = _VmbPixel.Color | _VmbPixelOccupy.Bit12 | 0x001E
|
||||
Yuv422 = _VmbPixel.Color | _VmbPixelOccupy.Bit16 | 0x001F
|
||||
Yuv444 = _VmbPixel.Color | _VmbPixelOccupy.Bit24 | 0x0020
|
||||
YCbCr411_8_CbYYCrYY = _VmbPixel.Color | _VmbPixelOccupy.Bit12 | 0x003C
|
||||
YCbCr422_8_CbYCrY = _VmbPixel.Color | _VmbPixelOccupy.Bit16 | 0x0043
|
||||
YCbCr8_CbYCr = _VmbPixel.Color | _VmbPixelOccupy.Bit24 | 0x003A
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VimbaCError(Exception):
|
||||
"""Error Type containing an error code from the C-Layer. This error code is highly context
|
||||
sensitive. All wrapped C-Functions that do not return VmbError.Success or None must
|
||||
raise a VimbaCError and the surrounding code must deal if the Error is possible.
|
||||
"""
|
||||
|
||||
def __init__(self, c_error: VmbError):
|
||||
super().__init__(repr(c_error))
|
||||
self.__c_error = c_error
|
||||
|
||||
def __str__(self):
|
||||
return repr(self)
|
||||
|
||||
def __repr__(self):
|
||||
return 'VimbaCError({})'.format(repr(self.__c_error))
|
||||
|
||||
def get_error_code(self) -> VmbError:
|
||||
""" Get contained Error Code """
|
||||
return self.__c_error
|
||||
|
||||
|
||||
# Utility Functions
|
||||
def _split_into_powers_of_two(num: int) -> Tuple[int, ...]:
|
||||
result = []
|
||||
for mask in [1 << i for i in range(32)]:
|
||||
if mask & num:
|
||||
result.append(mask)
|
||||
|
||||
if not result:
|
||||
result.append(0)
|
||||
|
||||
return tuple(result)
|
||||
|
||||
|
||||
def _split_flags_into_enum(num: int, enum_type):
|
||||
return [enum_type(val) for val in _split_into_powers_of_two(num)]
|
||||
|
||||
|
||||
def _repr_flags_list(enum_type, flag_val: int):
|
||||
values = _split_flags_into_enum(flag_val, enum_type)
|
||||
|
||||
if values:
|
||||
def fold_func(acc, arg):
|
||||
return '{} {}'.format(acc, repr(arg))
|
||||
|
||||
return functools.reduce(fold_func, values, '')
|
||||
|
||||
else:
|
||||
return '{}'.format(repr(enum_type(0)))
|
||||
|
||||
|
||||
def decode_cstr(val: bytes) -> str:
|
||||
"""Converts c_char_p stored in interface structures to a str.
|
||||
|
||||
Arguments:
|
||||
val - Byte sequence to convert into str.
|
||||
|
||||
Returns:
|
||||
str represented by 'val'
|
||||
"""
|
||||
return val.decode() if val else ''
|
||||
|
||||
|
||||
def decode_flags(enum_type, enum_val: int):
|
||||
"""Splits C-styled bit mask into a set of flags from a given Enumeration.
|
||||
|
||||
Arguments:
|
||||
enum_val - Bit mask to decode.
|
||||
enum_type - Enum Type represented within 'enum_val'
|
||||
|
||||
Returns:
|
||||
A set of all values of enum_type occurring in enum_val.
|
||||
|
||||
Raises:
|
||||
Attribute error a set value is not within the given 'enum_type'.
|
||||
"""
|
||||
|
||||
return tuple(_split_flags_into_enum(enum_val, enum_type))
|
||||
|
||||
|
||||
def fmt_repr(fmt: str, val):
|
||||
"""Append repr to a format string."""
|
||||
return fmt.format(repr(val))
|
||||
|
||||
|
||||
def fmt_enum_repr(fmt: str, enum_type, enum_val):
|
||||
"""Append repr of a given enum type to a format string.
|
||||
|
||||
Arguments:
|
||||
fmt - Format string
|
||||
enum_type - Enum Type to construct.
|
||||
enum_val - Enum value.
|
||||
|
||||
Returns:
|
||||
formatted string
|
||||
"""
|
||||
return fmt.format(repr(enum_type(enum_val)))
|
||||
|
||||
|
||||
def fmt_flags_repr(fmt: str, enum_type, enum_val):
|
||||
"""Append repr of a c-style flag value in the form of a set containing
|
||||
all bits set from a given enum_type.
|
||||
|
||||
Arguments:
|
||||
fmt - Format string
|
||||
enum_type - Enum Type to construct.
|
||||
enum_val - Enum value.
|
||||
|
||||
Returns:
|
||||
formatted string
|
||||
"""
|
||||
return fmt.format(_repr_flags_list(enum_type, enum_val))
|
||||
|
||||
|
||||
def load_vimba_lib(vimba_project: str):
|
||||
""" Load shared library shipped with the Vimba installation
|
||||
|
||||
Arguments:
|
||||
vimba_project - Library name without prefix or extension
|
||||
|
||||
Return:
|
||||
CDLL or WinDLL Handle on loaded library
|
||||
|
||||
Raises:
|
||||
VimbaSystemError if given library could not be loaded.
|
||||
"""
|
||||
|
||||
platform_handlers = {
|
||||
'linux': _load_under_linux,
|
||||
'win32': _load_under_windows
|
||||
}
|
||||
|
||||
if sys.platform not in platform_handlers:
|
||||
msg = 'Abort. Unsupported Platform ({}) detected.'
|
||||
raise VimbaSystemError(msg.format(sys.platform))
|
||||
|
||||
return platform_handlers[sys.platform](vimba_project)
|
||||
|
||||
|
||||
def _load_under_linux(vimba_project: str):
|
||||
# Construct VimbaHome based on TL installation paths
|
||||
path_list: List[str] = []
|
||||
tl32_path = os.environ.get('GENICAM_GENTL32_PATH', "")
|
||||
if tl32_path:
|
||||
path_list += tl32_path.split(':')
|
||||
tl64_path = os.environ.get('GENICAM_GENTL64_PATH', "")
|
||||
if tl64_path:
|
||||
path_list += tl64_path.split(':')
|
||||
|
||||
# Remove empty strings from path_list if there are any.
|
||||
# Necessary because the GENICAM_GENTLXX_PATH variable might start with a :
|
||||
path_list = [path for path in path_list if path]
|
||||
|
||||
# Early return if required variables are not set.
|
||||
if not path_list:
|
||||
raise VimbaSystemError('No TL detected. Please verify Vimba installation.')
|
||||
|
||||
vimba_home_candidates: List[str] = []
|
||||
for path in path_list:
|
||||
vimba_home = os.path.dirname(os.path.dirname(os.path.dirname(path)))
|
||||
|
||||
if vimba_home not in vimba_home_candidates:
|
||||
vimba_home_candidates.append(vimba_home)
|
||||
|
||||
# Select the most likely directory from the candidates
|
||||
vimba_home = _select_vimba_home(vimba_home_candidates)
|
||||
|
||||
arch = platform.machine()
|
||||
|
||||
# Linux x86 64 Bit (Requires additional interpreter version check)
|
||||
if arch == 'x86_64':
|
||||
dir_ = 'x86_64bit' if _is_python_64_bit() else 'x86_32bit'
|
||||
|
||||
# Linux x86 32 Bit
|
||||
elif arch in ('i386', 'i686'):
|
||||
dir_ = 'x86_32bit'
|
||||
|
||||
# Linux arm 64 Bit (Requires additional interpreter version check)
|
||||
elif arch == 'aarch64':
|
||||
dir_ = 'arm_64bit' if _is_python_64_bit() else 'arm_32bit'
|
||||
|
||||
# Linux arm 32 Bit:
|
||||
elif arch == 'armv7l':
|
||||
dir_ = 'arm_32bit'
|
||||
|
||||
else:
|
||||
raise VimbaSystemError('Unknown Architecture \'{}\'. Abort'.format(arch))
|
||||
|
||||
lib_name = 'lib{}.so'.format(vimba_project)
|
||||
lib_path = os.path.join(vimba_home, vimba_project, 'DynamicLib', dir_, lib_name)
|
||||
|
||||
try:
|
||||
lib = ctypes.cdll.LoadLibrary(lib_path)
|
||||
|
||||
except OSError as e:
|
||||
msg = 'Failed to load library \'{}\'. Please verify Vimba installation.'
|
||||
raise VimbaSystemError(msg.format(lib_path)) from e
|
||||
|
||||
return lib
|
||||
|
||||
|
||||
def _load_under_windows(vimba_project: str):
|
||||
vimba_home = os.environ.get('VIMBA_HOME')
|
||||
|
||||
if vimba_home is None:
|
||||
raise VimbaSystemError('Variable VIMBA_HOME not set. Please verify Vimba installation.')
|
||||
|
||||
load_64bit = True if (platform.machine() == 'AMD64') and _is_python_64_bit() else False
|
||||
lib_name = '{}.dll'.format(vimba_project)
|
||||
lib_path = os.path.join(vimba_home, vimba_project, 'Bin', 'Win64' if load_64bit else 'Win32',
|
||||
lib_name)
|
||||
|
||||
try:
|
||||
# Load Library with 64 Bit and use cdecl call convention
|
||||
if load_64bit:
|
||||
lib = ctypes.cdll.LoadLibrary(lib_path)
|
||||
|
||||
# Load Library with 32 Bit and use stdcall call convention
|
||||
else:
|
||||
# Tell mypy to ignore this line to allow type checking on both windows and linux as
|
||||
# windll is not available on linux and would therefore produce an error there
|
||||
lib = ctypes.windll.LoadLibrary(lib_path) # type: ignore
|
||||
|
||||
except OSError as e:
|
||||
msg = 'Failed to load library \'{}\'. Please verify Vimba installation.'
|
||||
raise VimbaSystemError(msg.format(lib_path)) from e
|
||||
|
||||
return lib
|
||||
|
||||
|
||||
def _select_vimba_home(candidates: List[str]) -> str:
|
||||
"""
|
||||
Select the most likely candidate for VIMBA_HOME from the given list of
|
||||
candidates
|
||||
|
||||
Arguments:
|
||||
candidates - List of strings pointing to possible vimba home directories
|
||||
|
||||
Return:
|
||||
Path that represents the most likely VIMBA_HOME directory
|
||||
|
||||
Raises:
|
||||
VimbaSystemError if multiple VIMBA_HOME directories were found in candidates
|
||||
"""
|
||||
most_likely_candidates = []
|
||||
for candidate in candidates:
|
||||
if 'vimba' in candidate.lower():
|
||||
most_likely_candidates.append(candidate)
|
||||
|
||||
if len(most_likely_candidates) == 0:
|
||||
raise VimbaSystemError('No suitable Vimba installation found. The following paths '
|
||||
'were considered: {}'.format(candidates))
|
||||
elif len(most_likely_candidates) > 1:
|
||||
raise VimbaSystemError('Multiple Vimba installations found. Can\'t decide which to select: '
|
||||
'{}'.format(most_likely_candidates))
|
||||
|
||||
return most_likely_candidates[0]
|
||||
|
||||
|
||||
def _is_python_64_bit() -> bool:
|
||||
# Query if the currently running python interpreter is build as 64 bit binary.
|
||||
# The default method of getting this information seems to be rather hacky
|
||||
# (check if maxint > 2^32) but it seems to be the way to do this....
|
||||
return True if sys.maxsize > 2**32 else False
|
||||
@@ -0,0 +1,569 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
from ctypes import byref, sizeof, c_char_p, POINTER as c_ptr
|
||||
from typing import Callable, Any, Tuple, Dict, List
|
||||
|
||||
from ..error import VimbaSystemError
|
||||
from ..util import TraceEnable
|
||||
from .vimba_common import Uint32Enum, VmbUint32, VmbInt32, VmbError, VmbFloat, VimbaCError, \
|
||||
VmbPixelFormat, load_vimba_lib, fmt_repr, fmt_enum_repr
|
||||
|
||||
|
||||
__all__ = [
|
||||
'VmbBayerPattern',
|
||||
'VmbEndianness',
|
||||
'VmbAligment',
|
||||
'VmbAPIInfo',
|
||||
'VmbPixelLayout',
|
||||
'VmbDebayerMode',
|
||||
'VmbImage',
|
||||
'VmbImageInfo',
|
||||
'VmbTransformInfo',
|
||||
'VIMBA_IMAGE_TRANSFORM_VERSION',
|
||||
'EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION',
|
||||
'call_vimba_image_transform',
|
||||
'PIXEL_FORMAT_TO_LAYOUT',
|
||||
'LAYOUT_TO_PIXEL_FORMAT',
|
||||
'PIXEL_FORMAT_CONVERTIBILITY_MAP'
|
||||
]
|
||||
|
||||
|
||||
class VmbBayerPattern(Uint32Enum):
|
||||
"""Enum defining BayerPatterns
|
||||
Values:
|
||||
RGGB - RGGB pattern, red pixel comes first
|
||||
GBRG - RGGB pattern, green pixel of blue row comes first
|
||||
GRBG - RGGB pattern, green pixel of red row comes first
|
||||
BGGR - RGGB pattern, blue pixel comes first
|
||||
CYGM - CYGM pattern, cyan pixel comes first in the first row, green in the second row
|
||||
GMCY - CYGM pattern, green pixel comes first in the first row, cyan in the second row
|
||||
CYMG - CYGM pattern, cyan pixel comes first in the first row, magenta in the second row
|
||||
MGCY - CYGM pattern, magenta pixel comes first in the first row, cyan in the second row
|
||||
LAST - Indicator for end of defined range
|
||||
"""
|
||||
RGGB = 0
|
||||
GBRG = 1
|
||||
GRBG = 2
|
||||
BGGR = 3
|
||||
CYGM = 128
|
||||
GMCY = 129
|
||||
CYMG = 130
|
||||
MGCY = 131
|
||||
LAST = 255
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbEndianness(Uint32Enum):
|
||||
"""Enum defining Endian Formats
|
||||
Values:
|
||||
LITTLE - Little Endian
|
||||
BIG - Big Endian
|
||||
LAST - Indicator for end of defined range
|
||||
"""
|
||||
LITTLE = 0
|
||||
BIG = 1
|
||||
LAST = 255
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbAligment(Uint32Enum):
|
||||
"""Enum defining image alignment
|
||||
Values:
|
||||
MSB - Alignment (pppp pppp pppp ....)
|
||||
LSB - Alignment (.... pppp pppp pppp)
|
||||
LAST - Indicator for end of defined range
|
||||
"""
|
||||
MSB = 0
|
||||
LSB = 1
|
||||
LAST = 255
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbAPIInfo(Uint32Enum):
|
||||
"""API Info Types
|
||||
Values:
|
||||
ALL - All Infos
|
||||
PLATFORM - Platform the API was built for
|
||||
BUILD - Build Types (debug or release)
|
||||
TECHNOLOGY - Special technology info
|
||||
LAST - Indicator for end of defined range
|
||||
"""
|
||||
ALL = 0
|
||||
PLATFORM = 1
|
||||
BUILD = 2
|
||||
TECHNOLOGY = 3
|
||||
LAST = 4
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbPixelLayout(Uint32Enum):
|
||||
"""Image Pixel Layout Information. C Header offers no further documentation."""
|
||||
Mono = 0
|
||||
MonoPacked = 1
|
||||
Raw = 2
|
||||
RawPacked = 3
|
||||
RGB = 4
|
||||
BGR = 5
|
||||
RGBA = 6
|
||||
BGRA = 7
|
||||
YUV411 = 8
|
||||
YUV422 = 9
|
||||
YUV444 = 10
|
||||
MonoP = 11
|
||||
MonoPl = 12
|
||||
RawP = 13
|
||||
RawPl = 14
|
||||
YYCbYYCr411 = 15
|
||||
CbYYCrYY411 = YUV411,
|
||||
YCbYCr422 = 16
|
||||
CbYCrY422 = YUV422
|
||||
YCbCr444 = 17
|
||||
CbYCr444 = YUV444
|
||||
LAST = 19
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbColorSpace(Uint32Enum):
|
||||
"""Image Color space. C Header offers no further documentation."""
|
||||
Undefined = 0
|
||||
ITU_BT709 = 1
|
||||
ITU_BT601 = 2
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbDebayerMode(Uint32Enum):
|
||||
"""Debayer Mode. C Header offers no further documentation."""
|
||||
Mode_2x2 = 0
|
||||
Mode_3x3 = 1
|
||||
Mode_LCAA = 2
|
||||
Mode_LCAAV = 3
|
||||
Mode_YUV422 = 4
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbTransformType(Uint32Enum):
|
||||
"""TransformType Mode. C Header offers no further documentation."""
|
||||
None_ = 0
|
||||
DebayerMode = 1
|
||||
ColorCorrectionMatrix = 2
|
||||
GammaCorrection = 3
|
||||
Offset = 4
|
||||
Gain = 5
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
|
||||
class VmbPixelInfo(ctypes.Structure):
|
||||
"""Structure containing pixel information. Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('BitsPerPixel', VmbUint32),
|
||||
('BitsUsed', VmbUint32),
|
||||
('Alignment', VmbUint32),
|
||||
('Endianness', VmbUint32),
|
||||
('PixelLayout', VmbUint32),
|
||||
('BayerPattern', VmbUint32),
|
||||
('Reserved', VmbUint32)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbPixelInfo'
|
||||
rep += fmt_repr('(BitsPerPixel={}', self.BitsPerPixel)
|
||||
rep += fmt_repr(',BitsUsed={}', self.BitsUsed)
|
||||
rep += fmt_enum_repr(',Alignment={}', VmbAligment, self.Alignment)
|
||||
rep += fmt_enum_repr(',Endianness={}', VmbEndianness, self.Endianness)
|
||||
rep += fmt_enum_repr(',PixelLayout={}', VmbPixelLayout, self.PixelLayout)
|
||||
rep += fmt_enum_repr(',BayerPattern={}', VmbBayerPattern, self.BayerPattern)
|
||||
rep += fmt_enum_repr(',Reserved={}', VmbColorSpace, self.Reserved)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbImageInfo(ctypes.Structure):
|
||||
"""Structure containing image information. Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Width', VmbUint32),
|
||||
('Height', VmbUint32),
|
||||
('Stride', VmbInt32),
|
||||
('PixelInfo', VmbPixelInfo)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbImageInfo'
|
||||
rep += fmt_repr('(Width={}', self.Width)
|
||||
rep += fmt_repr(',Height={}', self.Height)
|
||||
rep += fmt_repr(',Stride={}', self.Stride)
|
||||
rep += fmt_repr(',PixelInfo={}', self.PixelInfo)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbImage(ctypes.Structure):
|
||||
"""Structure containing image. Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Size', VmbUint32),
|
||||
('Data', ctypes.c_void_p),
|
||||
('ImageInfo', VmbImageInfo)
|
||||
]
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'VmbImage'
|
||||
rep += fmt_repr('(Size={}', self.Size)
|
||||
rep += fmt_repr(',Data={}', self.Data)
|
||||
rep += fmt_repr(',ImageInfo={}', self.ImageInfo)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
|
||||
class VmbTransformParameterMatrix3x3(ctypes.Structure):
|
||||
"""Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Matrix', VmbFloat * 9)
|
||||
]
|
||||
|
||||
|
||||
class VmbTransformParameterGamma(ctypes.Structure):
|
||||
"""Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Gamma', VmbFloat)
|
||||
]
|
||||
|
||||
|
||||
class VmbTransformParameterDebayer(ctypes.Structure):
|
||||
"""Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Method', VmbUint32)
|
||||
]
|
||||
|
||||
|
||||
class VmbTransformParameterOffset(ctypes.Structure):
|
||||
"""Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Offset', VmbInt32)
|
||||
]
|
||||
|
||||
|
||||
class VmbTransformParameterGain(ctypes.Structure):
|
||||
"""Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Gain', VmbUint32)
|
||||
]
|
||||
|
||||
|
||||
class VmbTransformParameter(ctypes.Union):
|
||||
"""Sadly c_header contains no more documentation"""
|
||||
_fields_ = [
|
||||
('Matrix3x3', VmbTransformParameterMatrix3x3),
|
||||
('Debayer', VmbTransformParameterDebayer),
|
||||
('Gamma', VmbTransformParameterGamma),
|
||||
('Offset', VmbTransformParameterOffset),
|
||||
('Gain', VmbTransformParameterGain)
|
||||
]
|
||||
|
||||
|
||||
class VmbTransformInfo(ctypes.Structure):
|
||||
"""Struct holding transformation information"""
|
||||
_fields_ = [
|
||||
('TransformType', VmbUint32),
|
||||
('Parameter', VmbTransformParameter)
|
||||
]
|
||||
|
||||
|
||||
# API
|
||||
VIMBA_IMAGE_TRANSFORM_VERSION = None
|
||||
if sys.platform == 'linux':
|
||||
EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION = '1.0'
|
||||
|
||||
else:
|
||||
EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION = '1.6'
|
||||
|
||||
# For detailed information on the signatures see "VimbaImageTransform.h"
|
||||
# To improve readability, suppress 'E501 line too long (> 100 characters)'
|
||||
# check of flake8
|
||||
_SIGNATURES = {
|
||||
'VmbGetVersion': (VmbError, [c_ptr(VmbUint32)]),
|
||||
'VmbGetErrorInfo': (VmbError, [VmbError, c_char_p, VmbUint32]),
|
||||
'VmbGetApiInfoString': (VmbError, [VmbAPIInfo, c_char_p, VmbUint32]),
|
||||
'VmbSetDebayerMode': (VmbError, [VmbDebayerMode, c_ptr(VmbTransformInfo)]),
|
||||
'VmbSetColorCorrectionMatrix3x3': (VmbError, [c_ptr(VmbFloat), c_ptr(VmbTransformInfo)]),
|
||||
'VmbSetGammaCorrection': (VmbError, [VmbFloat, c_ptr(VmbTransformInfo)]),
|
||||
'VmbSetImageInfoFromPixelFormat': (VmbError, [VmbPixelFormat, VmbUint32, VmbUint32, c_ptr(VmbImage)]), # noqa: E501
|
||||
'VmbSetImageInfoFromString': (VmbError, [c_char_p, VmbUint32, VmbUint32, VmbUint32, c_ptr(VmbImage)]), # noqa: E501
|
||||
'VmbSetImageInfoFromInputParameters': (VmbError, [VmbPixelFormat, VmbUint32, VmbUint32, VmbPixelLayout, VmbUint32, c_ptr(VmbImage)]), # noqa: E501
|
||||
'VmbSetImageInfoFromInputImage': (VmbError, [c_ptr(VmbImage), VmbPixelLayout, VmbUint32, c_ptr(VmbImage)]), # noqa: E501
|
||||
'VmbImageTransform': (VmbError, [c_ptr(VmbImage), c_ptr(VmbImage), c_ptr(VmbTransformInfo), VmbUint32]) # noqa: E501
|
||||
}
|
||||
|
||||
|
||||
def _attach_signatures(lib_handle):
|
||||
global _SIGNATURES
|
||||
|
||||
for function_name, signature in _SIGNATURES.items():
|
||||
fn = getattr(lib_handle, function_name)
|
||||
fn.restype, fn.argtypes = signature
|
||||
fn.errcheck = _eval_vmberror
|
||||
|
||||
return lib_handle
|
||||
|
||||
|
||||
def _check_version(lib_handle):
|
||||
global EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION
|
||||
global VIMBA_IMAGE_TRANSFORM_VERSION
|
||||
|
||||
v = VmbUint32()
|
||||
lib_handle.VmbGetVersion(byref(v))
|
||||
|
||||
VIMBA_IMAGE_TRANSFORM_VERSION = '{}.{}'.format((v.value >> 24) & 0xff, (v.value >> 16) & 0xff)
|
||||
|
||||
loaded_version = tuple(map(int, VIMBA_IMAGE_TRANSFORM_VERSION.split(".")))
|
||||
expected_version = tuple(map(int, EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION.split(".")))
|
||||
# Major version must match. minor version may be equal or greater
|
||||
if not(loaded_version[0] == expected_version[0] and
|
||||
loaded_version[1] >= expected_version[1]):
|
||||
msg = 'Invalid VimbaImageTransform Version: Expected: {}, Found:{}'
|
||||
raise VimbaSystemError(msg.format(EXPECTED_VIMBA_IMAGE_TRANSFORM_VERSION,
|
||||
VIMBA_IMAGE_TRANSFORM_VERSION))
|
||||
|
||||
return lib_handle
|
||||
|
||||
|
||||
def _eval_vmberror(result: VmbError, func: Callable[..., Any], *args: Tuple[Any, ...]):
|
||||
if result not in (VmbError.Success, None):
|
||||
raise VimbaCError(result)
|
||||
|
||||
|
||||
_lib_instance = _check_version(_attach_signatures(load_vimba_lib('VimbaImageTransform')))
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def call_vimba_image_transform(func_name: str, *args):
|
||||
"""This function encapsulates the entire VimbaImageTransform access.
|
||||
|
||||
For Details on valid function signatures see the 'VimbaImageTransform.h'.
|
||||
|
||||
Arguments:
|
||||
func_name: The function name from VimbaImageTransform to be called.
|
||||
args: Varargs passed directly to the underlaying C-Function.
|
||||
|
||||
Raises:
|
||||
TypeError if given are do not match the signature of the function.
|
||||
AttributeError if func with name 'func_name' does not exist.
|
||||
VimbaCError if the function call is valid but neither None or VmbError.Success was returned.
|
||||
|
||||
The following functions of VimbaImageTransform can be executed:
|
||||
VmbGetVersion
|
||||
VmbGetTechnoInfo
|
||||
VmbGetErrorInfo
|
||||
VmbGetApiInfoString
|
||||
VmbSetDebayerMode
|
||||
VmbSetColorCorrectionMatrix3x3
|
||||
VmbSetGammaCorrection
|
||||
VmbSetImageInfoFromPixelFormat
|
||||
VmbSetImageInfoFromString
|
||||
VmbSetImageInfoFromInputParameters
|
||||
VmbSetImageInfoFromInputImage
|
||||
VmbImageTransform
|
||||
"""
|
||||
|
||||
global _lib_instance
|
||||
getattr(_lib_instance, func_name)(*args)
|
||||
|
||||
|
||||
PIXEL_FORMAT_TO_LAYOUT: Dict[VmbPixelFormat, Tuple[VmbPixelLayout, int]] = {
|
||||
VmbPixelFormat.Mono8: (VmbPixelLayout.Mono, 8),
|
||||
VmbPixelFormat.Mono10: (VmbPixelLayout.Mono, 16),
|
||||
VmbPixelFormat.Mono12: (VmbPixelLayout.Mono, 16),
|
||||
VmbPixelFormat.Mono14: (VmbPixelLayout.Mono, 16),
|
||||
VmbPixelFormat.Mono16: (VmbPixelLayout.Mono, 16),
|
||||
VmbPixelFormat.BayerGR8: (VmbPixelLayout.Raw, 8),
|
||||
VmbPixelFormat.BayerRG8: (VmbPixelLayout.Raw, 8),
|
||||
VmbPixelFormat.BayerGB8: (VmbPixelLayout.Raw, 8),
|
||||
VmbPixelFormat.BayerBG8: (VmbPixelLayout.Raw, 8),
|
||||
VmbPixelFormat.BayerGR10: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerRG10: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerGB10: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerBG10: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerGR12: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerRG12: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerGB12: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerBG12: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerGR16: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerRG16: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerGB16: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.BayerBG16: (VmbPixelLayout.Raw, 16),
|
||||
VmbPixelFormat.Rgb8: (VmbPixelLayout.RGB, 8),
|
||||
VmbPixelFormat.Rgb10: (VmbPixelLayout.RGB, 16),
|
||||
VmbPixelFormat.Rgb12: (VmbPixelLayout.RGB, 16),
|
||||
VmbPixelFormat.Rgb14: (VmbPixelLayout.RGB, 16),
|
||||
VmbPixelFormat.Rgb16: (VmbPixelLayout.RGB, 16),
|
||||
VmbPixelFormat.Bgr8: (VmbPixelLayout.BGR, 8),
|
||||
VmbPixelFormat.Bgr10: (VmbPixelLayout.BGR, 16),
|
||||
VmbPixelFormat.Bgr12: (VmbPixelLayout.BGR, 16),
|
||||
VmbPixelFormat.Bgr14: (VmbPixelLayout.BGR, 16),
|
||||
VmbPixelFormat.Bgr16: (VmbPixelLayout.BGR, 16),
|
||||
VmbPixelFormat.Rgba8: (VmbPixelLayout.RGBA, 8),
|
||||
VmbPixelFormat.Rgba10: (VmbPixelLayout.RGBA, 16),
|
||||
VmbPixelFormat.Rgba12: (VmbPixelLayout.RGBA, 16),
|
||||
VmbPixelFormat.Rgba14: (VmbPixelLayout.RGBA, 16),
|
||||
VmbPixelFormat.Rgba16: (VmbPixelLayout.RGBA, 16),
|
||||
VmbPixelFormat.Bgra8: (VmbPixelLayout.BGRA, 8),
|
||||
VmbPixelFormat.Bgra10: (VmbPixelLayout.BGRA, 16),
|
||||
VmbPixelFormat.Bgra12: (VmbPixelLayout.BGRA, 16),
|
||||
VmbPixelFormat.Bgra14: (VmbPixelLayout.BGRA, 16),
|
||||
VmbPixelFormat.Bgra16: (VmbPixelLayout.BGRA, 16)
|
||||
}
|
||||
|
||||
LAYOUT_TO_PIXEL_FORMAT = dict([(v, k) for k, v in PIXEL_FORMAT_TO_LAYOUT.items()])
|
||||
|
||||
|
||||
def _query_compatibility(pixel_format: VmbPixelFormat) -> Tuple[VmbPixelFormat, ...]:
|
||||
global LAYOUT_TO_PIXEL_FORMAT
|
||||
|
||||
# Query compatible formats from ImageTransform
|
||||
output_pixel_layouts = (VmbPixelLayout.Mono, VmbPixelLayout.MonoPacked, VmbPixelLayout.Raw,
|
||||
VmbPixelLayout.RawPacked, VmbPixelLayout.RGB, VmbPixelLayout.BGR,
|
||||
VmbPixelLayout.RGBA, VmbPixelLayout.BGRA)
|
||||
|
||||
output_bits_per_pixel = (8, 16)
|
||||
output_layouts = tuple([(layouts, bits)
|
||||
for layouts in output_pixel_layouts
|
||||
for bits in output_bits_per_pixel])
|
||||
|
||||
result: List[VmbPixelFormat] = []
|
||||
|
||||
src_image = VmbImage()
|
||||
src_image.Size = sizeof(src_image)
|
||||
|
||||
call_vimba_image_transform('VmbSetImageInfoFromPixelFormat', pixel_format, 0, 0,
|
||||
byref(src_image))
|
||||
|
||||
dst_image = VmbImage()
|
||||
dst_image.Size = sizeof(dst_image)
|
||||
|
||||
for layout, bits in output_layouts:
|
||||
|
||||
try:
|
||||
call_vimba_image_transform('VmbSetImageInfoFromInputImage', byref(src_image), layout,
|
||||
bits, byref(dst_image))
|
||||
|
||||
fmt = LAYOUT_TO_PIXEL_FORMAT[(layout, bits)]
|
||||
|
||||
if fmt not in result:
|
||||
result.append(fmt)
|
||||
|
||||
except VimbaCError as e:
|
||||
if e.get_error_code() not in (VmbError.NotImplemented_, VmbError.BadParameter):
|
||||
raise e
|
||||
|
||||
return tuple(result)
|
||||
|
||||
|
||||
PIXEL_FORMAT_CONVERTIBILITY_MAP: Dict[VmbPixelFormat, Tuple[VmbPixelFormat, ...]] = {
|
||||
VmbPixelFormat.Mono8: _query_compatibility(VmbPixelFormat.Mono8),
|
||||
VmbPixelFormat.Mono10: _query_compatibility(VmbPixelFormat.Mono10),
|
||||
VmbPixelFormat.Mono10p: _query_compatibility(VmbPixelFormat.Mono10p),
|
||||
VmbPixelFormat.Mono12: _query_compatibility(VmbPixelFormat.Mono12),
|
||||
VmbPixelFormat.Mono12Packed: _query_compatibility(VmbPixelFormat.Mono12Packed),
|
||||
VmbPixelFormat.Mono12p: _query_compatibility(VmbPixelFormat.Mono12p),
|
||||
VmbPixelFormat.Mono14: _query_compatibility(VmbPixelFormat.Mono14),
|
||||
VmbPixelFormat.Mono16: _query_compatibility(VmbPixelFormat.Mono16),
|
||||
|
||||
VmbPixelFormat.BayerGR8: _query_compatibility(VmbPixelFormat.BayerGR8),
|
||||
VmbPixelFormat.BayerRG8: _query_compatibility(VmbPixelFormat.BayerRG8),
|
||||
VmbPixelFormat.BayerGB8: _query_compatibility(VmbPixelFormat.BayerGB8),
|
||||
VmbPixelFormat.BayerBG8: _query_compatibility(VmbPixelFormat.BayerBG8),
|
||||
VmbPixelFormat.BayerGR10: _query_compatibility(VmbPixelFormat.BayerGR10),
|
||||
VmbPixelFormat.BayerRG10: _query_compatibility(VmbPixelFormat.BayerRG10),
|
||||
VmbPixelFormat.BayerGB10: _query_compatibility(VmbPixelFormat.BayerGB10),
|
||||
VmbPixelFormat.BayerBG10: _query_compatibility(VmbPixelFormat.BayerBG10),
|
||||
VmbPixelFormat.BayerGR12: _query_compatibility(VmbPixelFormat.BayerGR12),
|
||||
VmbPixelFormat.BayerRG12: _query_compatibility(VmbPixelFormat.BayerRG12),
|
||||
VmbPixelFormat.BayerGB12: _query_compatibility(VmbPixelFormat.BayerGB12),
|
||||
VmbPixelFormat.BayerBG12: _query_compatibility(VmbPixelFormat.BayerBG12),
|
||||
VmbPixelFormat.BayerGR12Packed: _query_compatibility(VmbPixelFormat.BayerGR12Packed),
|
||||
VmbPixelFormat.BayerRG12Packed: _query_compatibility(VmbPixelFormat.BayerRG12Packed),
|
||||
VmbPixelFormat.BayerGB12Packed: _query_compatibility(VmbPixelFormat.BayerGB12Packed),
|
||||
VmbPixelFormat.BayerBG12Packed: _query_compatibility(VmbPixelFormat.BayerBG12Packed),
|
||||
VmbPixelFormat.BayerGR10p: _query_compatibility(VmbPixelFormat.BayerGR10p),
|
||||
VmbPixelFormat.BayerRG10p: _query_compatibility(VmbPixelFormat.BayerRG10p),
|
||||
VmbPixelFormat.BayerGB10p: _query_compatibility(VmbPixelFormat.BayerGB10p),
|
||||
VmbPixelFormat.BayerBG10p: _query_compatibility(VmbPixelFormat.BayerBG10p),
|
||||
VmbPixelFormat.BayerGR12p: _query_compatibility(VmbPixelFormat.BayerGR12p),
|
||||
VmbPixelFormat.BayerRG12p: _query_compatibility(VmbPixelFormat.BayerRG12p),
|
||||
VmbPixelFormat.BayerGB12p: _query_compatibility(VmbPixelFormat.BayerGB12p),
|
||||
VmbPixelFormat.BayerBG12p: _query_compatibility(VmbPixelFormat.BayerBG12p),
|
||||
VmbPixelFormat.BayerGR16: _query_compatibility(VmbPixelFormat.BayerGR16),
|
||||
VmbPixelFormat.BayerRG16: _query_compatibility(VmbPixelFormat.BayerRG16),
|
||||
VmbPixelFormat.BayerGB16: _query_compatibility(VmbPixelFormat.BayerGB16),
|
||||
VmbPixelFormat.BayerBG16: _query_compatibility(VmbPixelFormat.BayerBG16),
|
||||
|
||||
VmbPixelFormat.Rgb8: _query_compatibility(VmbPixelFormat.Rgb8),
|
||||
VmbPixelFormat.Bgr8: _query_compatibility(VmbPixelFormat.Bgr8),
|
||||
VmbPixelFormat.Rgb10: _query_compatibility(VmbPixelFormat.Rgb10),
|
||||
VmbPixelFormat.Bgr10: _query_compatibility(VmbPixelFormat.Bgr10),
|
||||
VmbPixelFormat.Rgb12: _query_compatibility(VmbPixelFormat.Rgb12),
|
||||
VmbPixelFormat.Bgr12: _query_compatibility(VmbPixelFormat.Bgr12),
|
||||
VmbPixelFormat.Rgb14: _query_compatibility(VmbPixelFormat.Rgb14),
|
||||
VmbPixelFormat.Bgr14: _query_compatibility(VmbPixelFormat.Bgr14),
|
||||
VmbPixelFormat.Rgb16: _query_compatibility(VmbPixelFormat.Rgb16),
|
||||
VmbPixelFormat.Bgr16: _query_compatibility(VmbPixelFormat.Bgr16),
|
||||
VmbPixelFormat.Argb8: _query_compatibility(VmbPixelFormat.Argb8),
|
||||
VmbPixelFormat.Rgba8: _query_compatibility(VmbPixelFormat.Rgba8),
|
||||
VmbPixelFormat.Bgra8: _query_compatibility(VmbPixelFormat.Bgra8),
|
||||
VmbPixelFormat.Rgba10: _query_compatibility(VmbPixelFormat.Rgba10),
|
||||
VmbPixelFormat.Bgra10: _query_compatibility(VmbPixelFormat.Bgra10),
|
||||
VmbPixelFormat.Rgba12: _query_compatibility(VmbPixelFormat.Rgba12),
|
||||
VmbPixelFormat.Bgra12: _query_compatibility(VmbPixelFormat.Bgra12),
|
||||
VmbPixelFormat.Rgba14: _query_compatibility(VmbPixelFormat.Rgba14),
|
||||
VmbPixelFormat.Bgra14: _query_compatibility(VmbPixelFormat.Bgra14),
|
||||
VmbPixelFormat.Rgba16: _query_compatibility(VmbPixelFormat.Rgba16),
|
||||
VmbPixelFormat.Bgra16: _query_compatibility(VmbPixelFormat.Bgra16),
|
||||
|
||||
VmbPixelFormat.Yuv411: _query_compatibility(VmbPixelFormat.Yuv411),
|
||||
VmbPixelFormat.Yuv422: _query_compatibility(VmbPixelFormat.Yuv422),
|
||||
VmbPixelFormat.Yuv444: _query_compatibility(VmbPixelFormat.Yuv444),
|
||||
VmbPixelFormat.YCbCr411_8_CbYYCrYY: _query_compatibility(VmbPixelFormat.YCbCr411_8_CbYYCrYY),
|
||||
VmbPixelFormat.YCbCr422_8_CbYCrY: _query_compatibility(VmbPixelFormat.YCbCr422_8_CbYCrY),
|
||||
VmbPixelFormat.YCbCr8_CbYCr: _query_compatibility(VmbPixelFormat.YCbCr8_CbYCr)
|
||||
}
|
||||
1078
Vimba_6_0/VimbaPython/Source/vimba/camera.py
Normal file
1078
Vimba_6_0/VimbaPython/Source/vimba/camera.py
Normal file
File diff suppressed because it is too large
Load Diff
95
Vimba_6_0/VimbaPython/Source/vimba/error.py
Normal file
95
Vimba_6_0/VimbaPython/Source/vimba/error.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
from .util import Log
|
||||
|
||||
__all__ = [
|
||||
'VimbaSystemError',
|
||||
'VimbaCameraError',
|
||||
'VimbaInterfaceError',
|
||||
'VimbaFeatureError',
|
||||
'VimbaFrameError',
|
||||
'VimbaTimeout'
|
||||
]
|
||||
|
||||
|
||||
class _LoggedError(Exception):
|
||||
def __init__(self, msg: str):
|
||||
super().__init__(msg)
|
||||
Log.get_instance().error(msg)
|
||||
|
||||
|
||||
class VimbaSystemError(_LoggedError):
|
||||
"""Errors related to the underlying Vimba System
|
||||
|
||||
Error type to indicate system-wide errors like:
|
||||
- Incomplete Vimba installation
|
||||
- Incompatible version of the underlying C-Layer
|
||||
- An unsupported OS
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class VimbaCameraError(_LoggedError):
|
||||
"""Errors related to cameras
|
||||
|
||||
Error Type to indicated camera-related errors like:
|
||||
- Access of a disconnected Camera object
|
||||
- Lookup of non-existing cameras
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class VimbaInterfaceError(_LoggedError):
|
||||
"""Errors related to Interfaces
|
||||
|
||||
Error Type to indicated interface-related errors like:
|
||||
- Access on a disconnected Interface object
|
||||
- Lookup of a non-existing Interface
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class VimbaFeatureError(_LoggedError):
|
||||
"""Error related to Feature access.
|
||||
|
||||
Error type to indicate invalid Feature access like:
|
||||
- Invalid access mode on Feature access.
|
||||
- Out of range values upon setting a value.
|
||||
- Failed lookup of features.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class VimbaFrameError(_LoggedError):
|
||||
"""Error related to Frame data"""
|
||||
pass
|
||||
|
||||
|
||||
class VimbaTimeout(_LoggedError):
|
||||
"""Indicates that an operation timed out."""
|
||||
pass
|
||||
1273
Vimba_6_0/VimbaPython/Source/vimba/feature.py
Normal file
1273
Vimba_6_0/VimbaPython/Source/vimba/feature.py
Normal file
File diff suppressed because it is too large
Load Diff
923
Vimba_6_0/VimbaPython/Source/vimba/frame.py
Normal file
923
Vimba_6_0/VimbaPython/Source/vimba/frame.py
Normal file
@@ -0,0 +1,923 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import enum
|
||||
import ctypes
|
||||
import copy
|
||||
import functools
|
||||
|
||||
from typing import Optional, Tuple
|
||||
from .c_binding import byref, sizeof, decode_flags
|
||||
from .c_binding import call_vimba_c, call_vimba_image_transform, VmbFrameStatus, VmbFrameFlags, \
|
||||
VmbFrame, VmbHandle, VmbPixelFormat, VmbImage, VmbDebayerMode, \
|
||||
VmbTransformInfo, PIXEL_FORMAT_CONVERTIBILITY_MAP, PIXEL_FORMAT_TO_LAYOUT
|
||||
from .feature import FeaturesTuple, FeatureTypes, FeatureTypeTypes, discover_features
|
||||
from .shared import filter_features_by_name, filter_features_by_type, filter_features_by_category, \
|
||||
attach_feature_accessors, remove_feature_accessors
|
||||
from .util import TraceEnable, RuntimeTypeCheckEnable, EnterContextOnCall, LeaveContextOnCall, \
|
||||
RaiseIfOutsideContext
|
||||
from .error import VimbaFrameError, VimbaFeatureError
|
||||
|
||||
try:
|
||||
import numpy # type: ignore
|
||||
|
||||
except ModuleNotFoundError:
|
||||
numpy = None # type: ignore
|
||||
|
||||
|
||||
__all__ = [
|
||||
'PixelFormat',
|
||||
'MONO_PIXEL_FORMATS',
|
||||
'BAYER_PIXEL_FORMATS',
|
||||
'RGB_PIXEL_FORMATS',
|
||||
'RGBA_PIXEL_FORMATS',
|
||||
'BGR_PIXEL_FORMATS',
|
||||
'BGRA_PIXEL_FORMATS',
|
||||
'YUV_PIXEL_FORMATS',
|
||||
'YCBCR_PIXEL_FORMATS',
|
||||
'COLOR_PIXEL_FORMATS',
|
||||
'OPENCV_PIXEL_FORMATS',
|
||||
'FrameStatus',
|
||||
'Debayer',
|
||||
'Frame',
|
||||
'FrameTuple',
|
||||
'FormatTuple',
|
||||
'intersect_pixel_formats'
|
||||
]
|
||||
|
||||
|
||||
# Forward declarations
|
||||
FrameTuple = Tuple['Frame', ...]
|
||||
FormatTuple = Tuple['PixelFormat', ...]
|
||||
|
||||
|
||||
class PixelFormat(enum.IntEnum):
|
||||
"""Enum specifying all PixelFormats. Note: Not all Cameras support all Pixelformats.
|
||||
|
||||
Mono formats:
|
||||
Mono8 - Monochrome, 8 bits (PFNC:Mono8)
|
||||
Mono10 - Monochrome, 10 bits in 16 bits (PFNC:Mono10)
|
||||
Mono10p - Monochrome, 4x10 bits continuously packed in 40 bits
|
||||
(PFNC:Mono10p)
|
||||
Mono12 - Monochrome, 12 bits in 16 bits (PFNC:Mono12)
|
||||
Mono12Packed - Monochrome, 2x12 bits in 24 bits (GEV:Mono12Packed)
|
||||
Mono12p - Monochrome, 2x12 bits continuously packed in 24 bits
|
||||
(PFNC:Mono12p)
|
||||
Mono14 - Monochrome, 14 bits in 16 bits (PFNC:Mono14)
|
||||
Mono16 - Monochrome, 16 bits (PFNC:Mono16)
|
||||
|
||||
Bayer formats:
|
||||
BayerGR8 - Bayer-color, 8 bits, starting with GR line
|
||||
(PFNC:BayerGR8)
|
||||
BayerRG8 - Bayer-color, 8 bits, starting with RG line
|
||||
(PFNC:BayerRG8)
|
||||
BayerGB8 - Bayer-color, 8 bits, starting with GB line
|
||||
(PFNC:BayerGB8)
|
||||
BayerBG8 - Bayer-color, 8 bits, starting with BG line
|
||||
(PFNC:BayerBG8)
|
||||
BayerGR10 - Bayer-color, 10 bits in 16 bits, starting with GR
|
||||
line (PFNC:BayerGR10)
|
||||
BayerRG10 - Bayer-color, 10 bits in 16 bits, starting with RG
|
||||
line (PFNC:BayerRG10)
|
||||
BayerGB10 - Bayer-color, 10 bits in 16 bits, starting with GB
|
||||
line (PFNC:BayerGB10)
|
||||
BayerBG10 - Bayer-color, 10 bits in 16 bits, starting with BG
|
||||
line (PFNC:BayerBG10)
|
||||
BayerGR12 - Bayer-color, 12 bits in 16 bits, starting with GR
|
||||
line (PFNC:BayerGR12)
|
||||
BayerRG12 - Bayer-color, 12 bits in 16 bits, starting with RG
|
||||
line (PFNC:BayerRG12)
|
||||
BayerGB12 - Bayer-color, 12 bits in 16 bits, starting with GB
|
||||
line (PFNC:BayerGB12)
|
||||
BayerBG12 - Bayer-color, 12 bits in 16 bits, starting with BG
|
||||
line (PFNC:BayerBG12)
|
||||
BayerGR12Packed - Bayer-color, 2x12 bits in 24 bits, starting with GR
|
||||
line (GEV:BayerGR12Packed)
|
||||
BayerRG12Packed - Bayer-color, 2x12 bits in 24 bits, starting with RG
|
||||
line (GEV:BayerRG12Packed)
|
||||
BayerGB12Packed - Bayer-color, 2x12 bits in 24 bits, starting with GB
|
||||
line (GEV:BayerGB12Packed)
|
||||
BayerBG12Packed - Bayer-color, 2x12 bits in 24 bits, starting with BG
|
||||
line (GEV:BayerBG12Packed)
|
||||
BayerGR10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with GR line (PFNC:BayerGR10p)
|
||||
BayerRG10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with RG line (PFNC:BayerRG10p)
|
||||
BayerGB10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with GB line (PFNC:BayerGB10p)
|
||||
BayerBG10p - Bayer-color, 4x10 bits continuously packed in 40
|
||||
bits, starting with BG line (PFNC:BayerBG10p)
|
||||
BayerGR12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with GR line (PFNC:BayerGR12p)
|
||||
BayerRG12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with RG line (PFNC:BayerRG12p)
|
||||
BayerGB12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with GB line (PFNC:BayerGB12p)
|
||||
BayerBG12p - Bayer-color, 2x12 bits continuously packed in 24
|
||||
bits, starting with BG line (PFNC:BayerBG12p)
|
||||
BayerGR16 - Bayer-color, 16 bits, starting with GR line
|
||||
(PFNC:BayerGR16)
|
||||
BayerRG16 - Bayer-color, 16 bits, starting with RG line
|
||||
(PFNC:BayerRG16)
|
||||
BayerGB16 - Bayer-color, 16 bits, starting with GB line
|
||||
(PFNC:BayerGB16)
|
||||
BayerBG16 - Bayer-color, 16 bits, starting with BG line
|
||||
(PFNC:BayerBG16)
|
||||
|
||||
RGB formats:
|
||||
Rgb8 - RGB, 8 bits x 3 (PFNC:RGB8)
|
||||
Bgr8 - BGR, 8 bits x 3 (PFNC:Bgr8)
|
||||
Rgb10 - RGB, 10 bits in 16 bits x 3 (PFNC:RGB10)
|
||||
Bgr10 - BGR, 10 bits in 16 bits x 3 (PFNC:BGR10)
|
||||
Rgb12 - RGB, 12 bits in 16 bits x 3 (PFNC:RGB12)
|
||||
Bgr12 - BGR, 12 bits in 16 bits x 3 (PFNC:BGR12)
|
||||
Rgb14 - RGB, 14 bits in 16 bits x 3 (PFNC:RGB14)
|
||||
Bgr14 - BGR, 14 bits in 16 bits x 3 (PFNC:BGR14)
|
||||
Rgb16 - RGB, 16 bits x 3 (PFNC:RGB16)
|
||||
Bgr16 - BGR, 16 bits x 3 (PFNC:BGR16)
|
||||
|
||||
RGBA formats:
|
||||
Argb8 - ARGB, 8 bits x 4 (PFNC:RGBa8)
|
||||
Rgba8 - RGBA, 8 bits x 4, legacy name
|
||||
Bgra8 - BGRA, 8 bits x 4 (PFNC:BGRa8)
|
||||
Rgba10 - RGBA, 10 bits in 16 bits x 4
|
||||
Bgra10 - BGRA, 10 bits in 16 bits x 4
|
||||
Rgba12 - RGBA, 12 bits in 16 bits x 4
|
||||
Bgra12 - BGRA, 12 bits in 16 bits x 4
|
||||
Rgba14 - RGBA, 14 bits in 16 bits x 4
|
||||
Bgra14 - BGRA, 14 bits in 16 bits x 4
|
||||
Rgba16 - RGBA, 16 bits x 4
|
||||
Bgra16 - BGRA, 16 bits x 4
|
||||
|
||||
YUV/YCbCr formats:
|
||||
Yuv411 - YUV 411 with 8 bits (GEV:YUV411Packed)
|
||||
Yuv422 - YUV 422 with 8 bits (GEV:YUV422Packed)
|
||||
Yuv444 - YUV 444 with 8 bits (GEV:YUV444Packed)
|
||||
YCbCr411_8_CbYYCrYY - Y´CbCr 411 with 8 bits
|
||||
(PFNC:YCbCr411_8_CbYYCrYY) - identical to Yuv411
|
||||
YCbCr422_8_CbYCrY - Y´CbCr 422 with 8 bits
|
||||
(PFNC:YCbCr422_8_CbYCrY) - identical to Yuv422
|
||||
YCbCr8_CbYCr - Y´CbCr 444 with 8 bits
|
||||
(PFNC:YCbCr8_CbYCr) - identical to Yuv444
|
||||
"""
|
||||
# Mono Formats
|
||||
Mono8 = VmbPixelFormat.Mono8
|
||||
Mono10 = VmbPixelFormat.Mono10
|
||||
Mono10p = VmbPixelFormat.Mono10p
|
||||
Mono12 = VmbPixelFormat.Mono12
|
||||
Mono12Packed = VmbPixelFormat.Mono12Packed
|
||||
Mono12p = VmbPixelFormat.Mono12p
|
||||
Mono14 = VmbPixelFormat.Mono14
|
||||
Mono16 = VmbPixelFormat.Mono16
|
||||
|
||||
# Bayer Formats
|
||||
BayerGR8 = VmbPixelFormat.BayerGR8
|
||||
BayerRG8 = VmbPixelFormat.BayerRG8
|
||||
BayerGB8 = VmbPixelFormat.BayerGB8
|
||||
BayerBG8 = VmbPixelFormat.BayerBG8
|
||||
BayerGR10 = VmbPixelFormat.BayerGR10
|
||||
BayerRG10 = VmbPixelFormat.BayerRG10
|
||||
BayerGB10 = VmbPixelFormat.BayerGB10
|
||||
BayerBG10 = VmbPixelFormat.BayerBG10
|
||||
BayerGR12 = VmbPixelFormat.BayerGR12
|
||||
BayerRG12 = VmbPixelFormat.BayerRG12
|
||||
BayerGB12 = VmbPixelFormat.BayerGB12
|
||||
BayerBG12 = VmbPixelFormat.BayerBG12
|
||||
BayerGR12Packed = VmbPixelFormat.BayerGR12Packed
|
||||
BayerRG12Packed = VmbPixelFormat.BayerRG12Packed
|
||||
BayerGB12Packed = VmbPixelFormat.BayerGB12Packed
|
||||
BayerBG12Packed = VmbPixelFormat.BayerBG12Packed
|
||||
BayerGR10p = VmbPixelFormat.BayerGR10p
|
||||
BayerRG10p = VmbPixelFormat.BayerRG10p
|
||||
BayerGB10p = VmbPixelFormat.BayerGB10p
|
||||
BayerBG10p = VmbPixelFormat.BayerBG10p
|
||||
BayerGR12p = VmbPixelFormat.BayerGR12p
|
||||
BayerRG12p = VmbPixelFormat.BayerRG12p
|
||||
BayerGB12p = VmbPixelFormat.BayerGB12p
|
||||
BayerBG12p = VmbPixelFormat.BayerBG12p
|
||||
BayerGR16 = VmbPixelFormat.BayerGR16
|
||||
BayerRG16 = VmbPixelFormat.BayerRG16
|
||||
BayerGB16 = VmbPixelFormat.BayerGB16
|
||||
BayerBG16 = VmbPixelFormat.BayerBG16
|
||||
|
||||
# RGB Formats
|
||||
Rgb8 = VmbPixelFormat.Rgb8
|
||||
Bgr8 = VmbPixelFormat.Bgr8
|
||||
Rgb10 = VmbPixelFormat.Rgb10
|
||||
Bgr10 = VmbPixelFormat.Bgr10
|
||||
Rgb12 = VmbPixelFormat.Rgb12
|
||||
Bgr12 = VmbPixelFormat.Bgr12
|
||||
Rgb14 = VmbPixelFormat.Rgb14
|
||||
Bgr14 = VmbPixelFormat.Bgr14
|
||||
Rgb16 = VmbPixelFormat.Rgb16
|
||||
Bgr16 = VmbPixelFormat.Bgr16
|
||||
|
||||
# RGBA Formats
|
||||
Rgba8 = VmbPixelFormat.Rgba8
|
||||
Bgra8 = VmbPixelFormat.Bgra8
|
||||
Argb8 = VmbPixelFormat.Argb8
|
||||
Rgba10 = VmbPixelFormat.Rgba10
|
||||
Bgra10 = VmbPixelFormat.Bgra10
|
||||
Rgba12 = VmbPixelFormat.Rgba12
|
||||
Bgra12 = VmbPixelFormat.Bgra12
|
||||
Rgba14 = VmbPixelFormat.Rgba14
|
||||
Bgra14 = VmbPixelFormat.Bgra14
|
||||
Rgba16 = VmbPixelFormat.Rgba16
|
||||
Bgra16 = VmbPixelFormat.Bgra16
|
||||
Yuv411 = VmbPixelFormat.Yuv411
|
||||
Yuv422 = VmbPixelFormat.Yuv422
|
||||
Yuv444 = VmbPixelFormat.Yuv444
|
||||
|
||||
# YCbCr Formats
|
||||
YCbCr411_8_CbYYCrYY = VmbPixelFormat.YCbCr411_8_CbYYCrYY
|
||||
YCbCr422_8_CbYCrY = VmbPixelFormat.YCbCr422_8_CbYCrY
|
||||
YCbCr8_CbYCr = VmbPixelFormat.YCbCr8_CbYCr
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
def __repr__(self):
|
||||
return 'PixelFormat.{}'.format(str(self))
|
||||
|
||||
def get_convertible_formats(self) -> Tuple['PixelFormat', ...]:
|
||||
formats = PIXEL_FORMAT_CONVERTIBILITY_MAP[VmbPixelFormat(self)]
|
||||
return tuple([PixelFormat(fmt) for fmt in formats])
|
||||
|
||||
|
||||
MONO_PIXEL_FORMATS = (
|
||||
PixelFormat.Mono8,
|
||||
PixelFormat.Mono10,
|
||||
PixelFormat.Mono10p,
|
||||
PixelFormat.Mono12,
|
||||
PixelFormat.Mono12Packed,
|
||||
PixelFormat.Mono12p,
|
||||
PixelFormat.Mono14,
|
||||
PixelFormat.Mono16
|
||||
)
|
||||
|
||||
|
||||
BAYER_PIXEL_FORMATS = (
|
||||
PixelFormat.BayerGR8,
|
||||
PixelFormat.BayerRG8,
|
||||
PixelFormat.BayerGB8,
|
||||
PixelFormat.BayerBG8,
|
||||
PixelFormat.BayerGR10,
|
||||
PixelFormat.BayerRG10,
|
||||
PixelFormat.BayerGB10,
|
||||
PixelFormat.BayerBG10,
|
||||
PixelFormat.BayerGR12,
|
||||
PixelFormat.BayerRG12,
|
||||
PixelFormat.BayerGB12,
|
||||
PixelFormat.BayerBG12,
|
||||
PixelFormat.BayerGR12Packed,
|
||||
PixelFormat.BayerRG12Packed,
|
||||
PixelFormat.BayerGB12Packed,
|
||||
PixelFormat.BayerBG12Packed,
|
||||
PixelFormat.BayerGR10p,
|
||||
PixelFormat.BayerRG10p,
|
||||
PixelFormat.BayerGB10p,
|
||||
PixelFormat.BayerBG10p,
|
||||
PixelFormat.BayerGR12p,
|
||||
PixelFormat.BayerRG12p,
|
||||
PixelFormat.BayerGB12p,
|
||||
PixelFormat.BayerBG12p,
|
||||
PixelFormat.BayerGR16,
|
||||
PixelFormat.BayerRG16,
|
||||
PixelFormat.BayerGB16,
|
||||
PixelFormat.BayerBG16
|
||||
)
|
||||
|
||||
|
||||
RGB_PIXEL_FORMATS = (
|
||||
PixelFormat.Rgb8,
|
||||
PixelFormat.Rgb10,
|
||||
PixelFormat.Rgb12,
|
||||
PixelFormat.Rgb14,
|
||||
PixelFormat.Rgb16
|
||||
)
|
||||
|
||||
|
||||
RGBA_PIXEL_FORMATS = (
|
||||
PixelFormat.Rgba8,
|
||||
PixelFormat.Argb8,
|
||||
PixelFormat.Rgba10,
|
||||
PixelFormat.Rgba12,
|
||||
PixelFormat.Rgba14,
|
||||
PixelFormat.Rgba16
|
||||
)
|
||||
|
||||
|
||||
BGR_PIXEL_FORMATS = (
|
||||
PixelFormat.Bgr8,
|
||||
PixelFormat.Bgr10,
|
||||
PixelFormat.Bgr12,
|
||||
PixelFormat.Bgr14,
|
||||
PixelFormat.Bgr16
|
||||
)
|
||||
|
||||
|
||||
BGRA_PIXEL_FORMATS = (
|
||||
PixelFormat.Bgra8,
|
||||
PixelFormat.Bgra10,
|
||||
PixelFormat.Bgra12,
|
||||
PixelFormat.Bgra14,
|
||||
PixelFormat.Bgra16
|
||||
)
|
||||
|
||||
|
||||
YUV_PIXEL_FORMATS = (
|
||||
PixelFormat.Yuv411,
|
||||
PixelFormat.Yuv422,
|
||||
PixelFormat.Yuv444
|
||||
)
|
||||
|
||||
|
||||
YCBCR_PIXEL_FORMATS = (
|
||||
PixelFormat.YCbCr411_8_CbYYCrYY,
|
||||
PixelFormat.YCbCr422_8_CbYCrY,
|
||||
PixelFormat.YCbCr8_CbYCr
|
||||
)
|
||||
|
||||
|
||||
COLOR_PIXEL_FORMATS = BAYER_PIXEL_FORMATS + RGB_PIXEL_FORMATS + RGBA_PIXEL_FORMATS + \
|
||||
BGR_PIXEL_FORMATS + BGRA_PIXEL_FORMATS + YUV_PIXEL_FORMATS + \
|
||||
YCBCR_PIXEL_FORMATS
|
||||
|
||||
|
||||
OPENCV_PIXEL_FORMATS = (
|
||||
PixelFormat.Mono8,
|
||||
PixelFormat.Bgr8,
|
||||
PixelFormat.Bgra8,
|
||||
PixelFormat.Mono16,
|
||||
PixelFormat.Bgr16,
|
||||
PixelFormat.Bgra16
|
||||
)
|
||||
|
||||
|
||||
class Debayer(enum.IntEnum):
|
||||
"""Enum specifying debayer modes.
|
||||
|
||||
Enum values:
|
||||
Mode2x2 - 2x2 with green averaging (this is the default if no debayering algorithm
|
||||
is added as transformation option).
|
||||
Mode3x3 - 3x3 with equal green weighting per line (8-bit images only).
|
||||
ModeLCAA - Debayering with horizontal local color anti-aliasing (8-bit images only).
|
||||
ModeLCAAV - Debayering with horizontal and vertical local color anti-aliasing
|
||||
( 8-bit images only).
|
||||
ModeYuv422 - Debayering with YUV422-alike sub-sampling (8-bit images only).
|
||||
"""
|
||||
Mode2x2 = VmbDebayerMode.Mode_2x2
|
||||
Mode3x3 = VmbDebayerMode.Mode_3x3
|
||||
ModeLCAA = VmbDebayerMode.Mode_LCAA
|
||||
ModeLCAAV = VmbDebayerMode.Mode_LCAAV
|
||||
ModeYuv422 = VmbDebayerMode.Mode_YUV422
|
||||
|
||||
def __str__(self):
|
||||
return 'DebayerMode.{}'.format(self._name_)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
|
||||
class FrameStatus(enum.IntEnum):
|
||||
"""Enum specifying the current status of internal Frame data.
|
||||
|
||||
Enum values:
|
||||
Complete - Frame data is complete without errors.
|
||||
Incomplete - Frame could not be filled to the end.
|
||||
TooSmall - Frame buffer was too small.
|
||||
Invalid - Frame buffer was invalid.
|
||||
"""
|
||||
|
||||
Complete = VmbFrameStatus.Complete
|
||||
Incomplete = VmbFrameStatus.Incomplete
|
||||
TooSmall = VmbFrameStatus.TooSmall
|
||||
Invalid = VmbFrameStatus.Invalid
|
||||
|
||||
|
||||
class AllocationMode(enum.IntEnum):
|
||||
"""Enum specifying the supported frame allocation modes.
|
||||
|
||||
Enum values:
|
||||
AnnounceFrame - The buffer is allocated by VimbaPython
|
||||
AllocAndAnnounceFrame - The buffer is allocated by the Transport Layer
|
||||
"""
|
||||
AnnounceFrame = 0
|
||||
AllocAndAnnounceFrame = 1
|
||||
|
||||
|
||||
class AncillaryData:
|
||||
"""Ancillary Data are created after enabling a Cameras 'ChunkModeActive' Feature.
|
||||
Ancillary Data are Features stored within a Frame.
|
||||
"""
|
||||
@TraceEnable()
|
||||
@LeaveContextOnCall()
|
||||
def __init__(self, handle: VmbFrame):
|
||||
"""Do not call directly. Get Object via Frame access method"""
|
||||
self.__handle: VmbFrame = handle
|
||||
self.__data_handle: VmbHandle = VmbHandle()
|
||||
self.__feats: FeaturesTuple = ()
|
||||
self.__context_cnt: int = 0
|
||||
|
||||
@TraceEnable()
|
||||
def __enter__(self):
|
||||
if not self.__context_cnt:
|
||||
self._open()
|
||||
|
||||
self.__context_cnt += 1
|
||||
return self
|
||||
|
||||
@TraceEnable()
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
self.__context_cnt -= 1
|
||||
|
||||
if not self.__context_cnt:
|
||||
self._close()
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
def get_all_features(self) -> FeaturesTuple:
|
||||
"""Get all features in ancillary data.
|
||||
|
||||
Returns:
|
||||
A set of all currently features stored in Ancillary Data.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
"""
|
||||
return self.__feats
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_by_type(self, feat_type: FeatureTypeTypes) -> FeaturesTuple:
|
||||
"""Get all features in ancillary data of a specific type.
|
||||
|
||||
Valid FeatureTypes are: IntFeature, FloatFeature, StringFeature, BoolFeature,
|
||||
EnumFeature, CommandFeature, RawFeature
|
||||
|
||||
Arguments:
|
||||
feat_type - FeatureType used find features of that type.
|
||||
|
||||
Returns:
|
||||
A all features of type 'feat_type'.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
return filter_features_by_type(self.__feats, feat_type)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_by_category(self, category: str) -> FeaturesTuple:
|
||||
"""Get all features in ancillary data of a specific category.
|
||||
|
||||
Arguments:
|
||||
category - Category that should be used for filtering.
|
||||
|
||||
Returns:
|
||||
A all features of category 'category'.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
return filter_features_by_category(self.__feats, category)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_feature_by_name(self, feat_name: str) -> FeatureTypes:
|
||||
"""Get a features in ancillary data by its name.
|
||||
|
||||
Arguments:
|
||||
feat_name - Name used to find a feature.
|
||||
|
||||
Returns:
|
||||
Feature with the associated name.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
TypeError if parameters do not match their type hint.
|
||||
VimbaFeatureError if no feature is associated with 'feat_name'.
|
||||
"""
|
||||
feat = filter_features_by_name(self.__feats, feat_name)
|
||||
|
||||
if not feat:
|
||||
raise VimbaFeatureError('Feature \'{}\' not found.'.format(feat_name))
|
||||
|
||||
return feat
|
||||
|
||||
@TraceEnable()
|
||||
@EnterContextOnCall()
|
||||
def _open(self):
|
||||
call_vimba_c('VmbAncillaryDataOpen', byref(self.__handle), byref(self.__data_handle))
|
||||
|
||||
self.__feats = _replace_invalid_feature_calls(discover_features(self.__data_handle))
|
||||
attach_feature_accessors(self, self.__feats)
|
||||
|
||||
@TraceEnable()
|
||||
@LeaveContextOnCall()
|
||||
def _close(self):
|
||||
remove_feature_accessors(self, self.__feats)
|
||||
self.__feats = ()
|
||||
|
||||
call_vimba_c('VmbAncillaryDataClose', self.__data_handle)
|
||||
self.__data_handle = VmbHandle()
|
||||
|
||||
|
||||
def _replace_invalid_feature_calls(feats: FeaturesTuple) -> FeaturesTuple:
|
||||
# AncillaryData are basically "lightweight" features. Calling most feature related
|
||||
# Functions with a AncillaryData - Handle leads to VimbaC Errors. This method decorates
|
||||
# all Methods that are unsafe to call with a decorator raising a RuntimeError.
|
||||
to_wrap = [
|
||||
'get_access_mode',
|
||||
'is_readable',
|
||||
'is_writeable',
|
||||
'register_change_handler',
|
||||
'get_increment',
|
||||
'get_range',
|
||||
'set'
|
||||
]
|
||||
|
||||
# Decorator raising a RuntimeError instead of delegating call to inner function.
|
||||
def invalid_call(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
msg = 'Calling \'{}\' is invalid for AncillaryData Features.'
|
||||
raise RuntimeError(msg.format(func.__name__))
|
||||
|
||||
return wrapper
|
||||
|
||||
# Replace original implementation by injecting a surrounding decorator and
|
||||
# binding the resulting function as a method to the Feature instance.
|
||||
for f, a in [(f, a) for f in feats for a in to_wrap]:
|
||||
try:
|
||||
fn = invalid_call(getattr(f, a))
|
||||
setattr(f, a, fn.__get__(f))
|
||||
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return feats
|
||||
|
||||
|
||||
class Frame:
|
||||
"""This class allows access to Frames acquired by a camera. The Frame is basically
|
||||
a buffer that wraps image data and some metadata.
|
||||
"""
|
||||
def __init__(self, buffer_size: int, allocation_mode: AllocationMode):
|
||||
"""Do not call directly. Create Frames via Camera methods instead."""
|
||||
self._allocation_mode = allocation_mode
|
||||
|
||||
# Allocation is not necessary for the AllocAndAnnounce case. In that case the Transport
|
||||
# Layer will take care of buffer allocation. The self._buffer variable will be updated after
|
||||
# the frame is announced and memory has been allocated.
|
||||
if self._allocation_mode == AllocationMode.AnnounceFrame:
|
||||
self._buffer = (ctypes.c_ubyte * buffer_size)()
|
||||
self._frame: VmbFrame = VmbFrame()
|
||||
|
||||
# Setup underlaying Frame
|
||||
if self._allocation_mode == AllocationMode.AnnounceFrame:
|
||||
self._frame.buffer = ctypes.cast(self._buffer, ctypes.c_void_p)
|
||||
self._frame.bufferSize = sizeof(self._buffer)
|
||||
elif self._allocation_mode == AllocationMode.AllocAndAnnounceFrame:
|
||||
# Set buffer pointer to NULL and inform Transport Layer of size it should allocate
|
||||
self._frame.buffer = None
|
||||
self._frame.bufferSize = buffer_size
|
||||
|
||||
def __str__(self):
|
||||
msg = 'Frame(id={}, status={}, buffer={})'
|
||||
return msg.format(self._frame.frameID, str(FrameStatus(self._frame.receiveStatus)),
|
||||
hex(self._frame.buffer))
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
cls = self.__class__
|
||||
result = cls.__new__(cls)
|
||||
memo[id(self)] = result
|
||||
|
||||
# VmbFrame contains Pointers and ctypes.Structure with Pointers can't be copied.
|
||||
# As a workaround VmbFrame contains a deepcopy-like Method performing deep copy of all
|
||||
# Attributes except PointerTypes. Those must be set manually after the copy operation.
|
||||
setattr(result, '_buffer', copy.deepcopy(self._buffer, memo))
|
||||
setattr(result, '_frame', self._frame.deepcopy_skip_ptr(memo))
|
||||
|
||||
result._frame.buffer = ctypes.cast(result._buffer, ctypes.c_void_p)
|
||||
result._frame.bufferSize = sizeof(result._buffer)
|
||||
|
||||
return result
|
||||
|
||||
def _set_buffer(self, buffer: ctypes.c_void_p):
|
||||
"""Set self._buffer to memory pointed to by passed buffer pointer
|
||||
|
||||
Useful if frames were allocated with AllocationMode.AllocAndAnnounce
|
||||
"""
|
||||
self._buffer = ctypes.cast(buffer,
|
||||
ctypes.POINTER(ctypes.c_ubyte * self._frame.bufferSize)).contents
|
||||
|
||||
def get_buffer(self) -> ctypes.Array:
|
||||
"""Get internal buffer object containing image data."""
|
||||
return self._buffer
|
||||
|
||||
def get_buffer_size(self) -> int:
|
||||
"""Get byte size of internal buffer."""
|
||||
return self._frame.bufferSize
|
||||
|
||||
def get_image_size(self) -> int:
|
||||
"""Get byte size of image data stored in buffer."""
|
||||
return self._frame.imageSize
|
||||
|
||||
def get_ancillary_data(self) -> Optional[AncillaryData]:
|
||||
"""Get AncillaryData.
|
||||
|
||||
Frames acquired with cameras where Feature ChunkModeActive is enabled can contain
|
||||
ancillary data within the image data.
|
||||
|
||||
Returns:
|
||||
None if Frame contains no ancillary data.
|
||||
AncillaryData if Frame contains ancillary data.
|
||||
"""
|
||||
if not self._frame.ancillarySize:
|
||||
return None
|
||||
|
||||
return AncillaryData(self._frame)
|
||||
|
||||
def get_status(self) -> FrameStatus:
|
||||
"""Returns current frame status."""
|
||||
return FrameStatus(self._frame.receiveStatus)
|
||||
|
||||
def get_pixel_format(self) -> PixelFormat:
|
||||
"""Get format of the acquired image data"""
|
||||
return PixelFormat(self._frame.pixelFormat)
|
||||
|
||||
def get_height(self) -> Optional[int]:
|
||||
"""Get image height in pixels.
|
||||
|
||||
Returns:
|
||||
Image height in pixels if dimension data is provided by the camera.
|
||||
None if dimension data is not provided by the camera.
|
||||
"""
|
||||
flags = decode_flags(VmbFrameFlags, self._frame.receiveFlags)
|
||||
|
||||
if VmbFrameFlags.Dimension not in flags:
|
||||
return None
|
||||
|
||||
return self._frame.height
|
||||
|
||||
def get_width(self) -> Optional[int]:
|
||||
"""Get image width in pixels.
|
||||
|
||||
Returns:
|
||||
Image width in pixels if dimension data is provided by the camera.
|
||||
None if dimension data is not provided by the camera.
|
||||
"""
|
||||
flags = decode_flags(VmbFrameFlags, self._frame.receiveFlags)
|
||||
|
||||
if VmbFrameFlags.Dimension not in flags:
|
||||
return None
|
||||
|
||||
return self._frame.width
|
||||
|
||||
def get_offset_x(self) -> Optional[int]:
|
||||
"""Get horizontal offset in pixels.
|
||||
|
||||
Returns:
|
||||
Horizontal offset in pixel if offset data is provided by the camera.
|
||||
None if offset data is not provided by the camera.
|
||||
"""
|
||||
flags = decode_flags(VmbFrameFlags, self._frame.receiveFlags)
|
||||
|
||||
if VmbFrameFlags.Offset not in flags:
|
||||
return None
|
||||
|
||||
return self._frame.offsetX
|
||||
|
||||
def get_offset_y(self) -> Optional[int]:
|
||||
"""Get vertical offset in pixels.
|
||||
|
||||
Returns:
|
||||
Vertical offset in pixels if offset data is provided by the camera.
|
||||
None if offset data is not provided by the camera.
|
||||
"""
|
||||
flags = decode_flags(VmbFrameFlags, self._frame.receiveFlags)
|
||||
|
||||
if VmbFrameFlags.Offset not in flags:
|
||||
return None
|
||||
|
||||
return self._frame.offsetY
|
||||
|
||||
def get_id(self) -> Optional[int]:
|
||||
"""Get Frame ID.
|
||||
|
||||
Returns:
|
||||
Frame ID if the id is provided by the camera.
|
||||
None if frame id is not provided by the camera.
|
||||
"""
|
||||
flags = decode_flags(VmbFrameFlags, self._frame.receiveFlags)
|
||||
|
||||
if VmbFrameFlags.FrameID not in flags:
|
||||
return None
|
||||
|
||||
return self._frame.frameID
|
||||
|
||||
def get_timestamp(self) -> Optional[int]:
|
||||
"""Get Frame timestamp.
|
||||
|
||||
Returns:
|
||||
Timestamp if provided by the camera.
|
||||
None if timestamp is not provided by the camera.
|
||||
"""
|
||||
flags = decode_flags(VmbFrameFlags, self._frame.receiveFlags)
|
||||
|
||||
if VmbFrameFlags.Timestamp not in flags:
|
||||
return None
|
||||
|
||||
return self._frame.timestamp
|
||||
|
||||
@RuntimeTypeCheckEnable()
|
||||
def convert_pixel_format(self, target_fmt: PixelFormat,
|
||||
debayer_mode: Optional[Debayer] = None):
|
||||
"""Convert internal pixel format to given format.
|
||||
|
||||
Note: This method allocates a new buffer for internal image data leading to some
|
||||
runtime overhead. For performance reasons, it might be better to set the value
|
||||
of the camera's 'PixelFormat' feature instead. In addition, a non-default debayer mode
|
||||
can be specified.
|
||||
|
||||
Arguments:
|
||||
target_fmt - PixelFormat to convert to.
|
||||
debayer_mode - Non-default algorithm used to debayer images in Bayer Formats. If
|
||||
no mode is specified, default debayering mode 'Mode2x2' is applied. If
|
||||
the current format is no Bayer format, this parameter is silently
|
||||
ignored.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
ValueError if the current format can't be converted into 'target_fmt'. Convertible
|
||||
Formats can be queried via get_convertible_formats() of PixelFormat.
|
||||
AssertionError if image width or height can't be determined.
|
||||
"""
|
||||
|
||||
global BAYER_PIXEL_FORMATS
|
||||
|
||||
# 1) Perform sanity checking
|
||||
fmt = self.get_pixel_format()
|
||||
|
||||
if fmt == target_fmt:
|
||||
return
|
||||
|
||||
if target_fmt not in fmt.get_convertible_formats():
|
||||
raise ValueError('Current PixelFormat can\'t be converted into given format.')
|
||||
|
||||
# 2) Specify Transformation Input Image
|
||||
height = self._frame.height
|
||||
width = self._frame.width
|
||||
|
||||
c_src_image = VmbImage()
|
||||
c_src_image.Size = sizeof(c_src_image)
|
||||
c_src_image.Data = ctypes.cast(self._buffer, ctypes.c_void_p)
|
||||
|
||||
call_vimba_image_transform('VmbSetImageInfoFromPixelFormat', fmt, width, height,
|
||||
byref(c_src_image))
|
||||
|
||||
# 3) Specify Transformation Output Image
|
||||
c_dst_image = VmbImage()
|
||||
c_dst_image.Size = sizeof(c_dst_image)
|
||||
|
||||
layout, bits = PIXEL_FORMAT_TO_LAYOUT[VmbPixelFormat(target_fmt)]
|
||||
|
||||
call_vimba_image_transform('VmbSetImageInfoFromInputImage', byref(c_src_image), layout,
|
||||
bits, byref(c_dst_image))
|
||||
|
||||
# 4) Allocate Buffer and perform transformation
|
||||
img_size = int(height * width * c_dst_image.ImageInfo.PixelInfo.BitsPerPixel / 8)
|
||||
anc_size = self._frame.ancillarySize
|
||||
|
||||
buf = (ctypes.c_ubyte * (img_size + anc_size))()
|
||||
c_dst_image.Data = ctypes.cast(buf, ctypes.c_void_p)
|
||||
|
||||
# 5) Setup Debayering mode if given.
|
||||
transform_info = VmbTransformInfo()
|
||||
if debayer_mode and (fmt in BAYER_PIXEL_FORMATS):
|
||||
call_vimba_image_transform('VmbSetDebayerMode', VmbDebayerMode(debayer_mode),
|
||||
byref(transform_info))
|
||||
|
||||
# 6) Perform Transformation
|
||||
call_vimba_image_transform('VmbImageTransform', byref(c_src_image), byref(c_dst_image),
|
||||
byref(transform_info), 1)
|
||||
|
||||
# 7) Copy ancillary data if existing
|
||||
if anc_size:
|
||||
src = ctypes.addressof(self._buffer) + self._frame.imageSize
|
||||
dst = ctypes.addressof(buf) + img_size
|
||||
|
||||
ctypes.memmove(dst, src, anc_size)
|
||||
|
||||
# 8) Update frame metadata
|
||||
self._buffer = buf
|
||||
self._frame.buffer = ctypes.cast(self._buffer, ctypes.c_void_p)
|
||||
self._frame.bufferSize = sizeof(self._buffer)
|
||||
self._frame.imageSize = img_size
|
||||
self._frame.pixelFormat = target_fmt
|
||||
|
||||
def as_numpy_ndarray(self) -> 'numpy.ndarray':
|
||||
"""Construct numpy.ndarray view on VimbaFrame.
|
||||
|
||||
Returns:
|
||||
numpy.ndarray on internal image buffer.
|
||||
|
||||
Raises:
|
||||
ImportError if numpy is not installed.
|
||||
VimbaFrameError if current PixelFormat can't be converted to a numpy.ndarray.
|
||||
"""
|
||||
if numpy is None:
|
||||
raise ImportError('\'Frame.as_opencv_image()\' requires module \'numpy\'.')
|
||||
|
||||
# Construct numpy overlay on underlaying image buffer
|
||||
height = self._frame.height
|
||||
width = self._frame.width
|
||||
fmt = self._frame.pixelFormat
|
||||
|
||||
c_image = VmbImage()
|
||||
c_image.Size = sizeof(c_image)
|
||||
|
||||
call_vimba_image_transform('VmbSetImageInfoFromPixelFormat', fmt, width, height,
|
||||
byref(c_image))
|
||||
|
||||
layout = PIXEL_FORMAT_TO_LAYOUT.get(fmt)
|
||||
|
||||
if not layout:
|
||||
msg = 'Can\'t construct numpy.ndarray for Pixelformat {}. ' \
|
||||
'Use \'frame.convert_pixel_format()\' to convert to a different Pixelformat.'
|
||||
raise VimbaFrameError(msg.format(str(self.get_pixel_format())))
|
||||
|
||||
bits_per_channel = layout[1]
|
||||
channels_per_pixel = c_image.ImageInfo.PixelInfo.BitsPerPixel // bits_per_channel
|
||||
|
||||
return numpy.ndarray(shape=(height, width, channels_per_pixel),
|
||||
buffer=self._buffer, # type: ignore
|
||||
dtype=numpy.uint8 if bits_per_channel == 8 else numpy.uint16)
|
||||
|
||||
def as_opencv_image(self) -> 'numpy.ndarray':
|
||||
"""Construct OpenCV compatible view on VimbaFrame.
|
||||
|
||||
Returns:
|
||||
OpenCV compatible numpy.ndarray
|
||||
|
||||
Raises:
|
||||
ImportError if numpy is not installed.
|
||||
ValueError if current pixel format is not compatible with opencv. Compatible
|
||||
formats are in OPENCV_PIXEL_FORMATS.
|
||||
"""
|
||||
global OPENCV_PIXEL_FORMATS
|
||||
|
||||
if numpy is None:
|
||||
raise ImportError('\'Frame.as_opencv_image()\' requires module \'numpy\'.')
|
||||
|
||||
fmt = self._frame.pixelFormat
|
||||
|
||||
if fmt not in OPENCV_PIXEL_FORMATS:
|
||||
raise ValueError('Current Format \'{}\' is not in OPENCV_PIXEL_FORMATS'.format(
|
||||
str(PixelFormat(self._frame.pixelFormat))))
|
||||
|
||||
return self.as_numpy_ndarray()
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def intersect_pixel_formats(fmts1: FormatTuple, fmts2: FormatTuple) -> FormatTuple:
|
||||
"""Build intersection of two sets containing PixelFormat.
|
||||
|
||||
Arguments:
|
||||
fmts1 - PixelFormats to intersect with fmts2
|
||||
fmts2 - PixelFormats to intersect with fmts1
|
||||
|
||||
Returns:
|
||||
Set of PixelFormats that occur in fmts1 and fmts2
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
return tuple(set(fmts1).intersection(set(fmts2)))
|
||||
391
Vimba_6_0/VimbaPython/Source/vimba/interface.py
Normal file
391
Vimba_6_0/VimbaPython/Source/vimba/interface.py
Normal file
@@ -0,0 +1,391 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import enum
|
||||
from typing import Tuple, List, Callable, Dict
|
||||
from .c_binding import call_vimba_c, byref, sizeof, decode_cstr
|
||||
from .c_binding import VmbInterface, VmbInterfaceInfo, VmbHandle, VmbUint32
|
||||
from .feature import discover_features, FeatureTypes, FeaturesTuple, FeatureTypeTypes
|
||||
from .shared import filter_features_by_name, filter_features_by_type, filter_affected_features, \
|
||||
filter_selected_features, filter_features_by_category, \
|
||||
attach_feature_accessors, remove_feature_accessors, read_memory, \
|
||||
write_memory, read_registers, write_registers
|
||||
from .util import TraceEnable, RuntimeTypeCheckEnable, EnterContextOnCall, LeaveContextOnCall, \
|
||||
RaiseIfOutsideContext
|
||||
from .error import VimbaFeatureError
|
||||
|
||||
|
||||
__all__ = [
|
||||
'InterfaceType',
|
||||
'Interface',
|
||||
'InterfaceEvent',
|
||||
'InterfaceChangeHandler',
|
||||
'InterfacesTuple',
|
||||
'InterfacesList',
|
||||
'discover_interfaces',
|
||||
'discover_interface'
|
||||
]
|
||||
|
||||
|
||||
# Forward declarations
|
||||
InterfaceChangeHandler = Callable[['Interface', 'InterfaceEvent'], None]
|
||||
InterfacesTuple = Tuple['Interface', ...]
|
||||
InterfacesList = List['Interface']
|
||||
|
||||
|
||||
class InterfaceType(enum.IntEnum):
|
||||
"""Enum specifying all interface types.
|
||||
|
||||
Enum values:
|
||||
Unknown - Interface is not known to this VimbaPython version.
|
||||
Firewire - 1394
|
||||
Ethernet - Gigabit Ethernet
|
||||
Usb - USB 3.0
|
||||
CL - Camera Link
|
||||
CSI2 - CSI-2
|
||||
"""
|
||||
Unknown = VmbInterface.Unknown
|
||||
Firewire = VmbInterface.Firewire
|
||||
Ethernet = VmbInterface.Ethernet
|
||||
Usb = VmbInterface.Usb
|
||||
CL = VmbInterface.CL
|
||||
CSI2 = VmbInterface.CSI2
|
||||
|
||||
|
||||
class InterfaceEvent(enum.IntEnum):
|
||||
"""Enum specifying an Interface Event
|
||||
|
||||
Enum values:
|
||||
Missing - A known interface disappeared from the bus
|
||||
Detected - A new interface was discovered
|
||||
Reachable - A known interface can be accessed
|
||||
Unreachable - A known interface cannot be accessed anymore
|
||||
"""
|
||||
Missing = 0
|
||||
Detected = 1
|
||||
Reachable = 2
|
||||
Unreachable = 3
|
||||
|
||||
|
||||
class Interface:
|
||||
"""This class allows access to an interface such as USB detected by Vimba.
|
||||
Interface is meant to be used in conjunction with the "with" - statement. On entering a context,
|
||||
all Interface features are detected and can be accessed within the context. Static Interface
|
||||
properties like Name can be accessed outside the context.
|
||||
"""
|
||||
|
||||
@TraceEnable()
|
||||
@LeaveContextOnCall()
|
||||
def __init__(self, info: VmbInterfaceInfo):
|
||||
"""Do not call directly. Access Interfaces via vimba.Vimba instead."""
|
||||
self.__handle: VmbHandle = VmbHandle(0)
|
||||
self.__info: VmbInterfaceInfo = info
|
||||
self.__feats: FeaturesTuple = ()
|
||||
self.__context_cnt: int = 0
|
||||
|
||||
@TraceEnable()
|
||||
def __enter__(self):
|
||||
if not self.__context_cnt:
|
||||
self._open()
|
||||
|
||||
self.__context_cnt += 1
|
||||
return self
|
||||
|
||||
@TraceEnable()
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
self.__context_cnt -= 1
|
||||
|
||||
if not self.__context_cnt:
|
||||
self._close()
|
||||
|
||||
def __str__(self):
|
||||
return 'Interface(id={})'.format(self.get_id())
|
||||
|
||||
def __repr__(self):
|
||||
rep = 'Interface'
|
||||
rep += '(__handle=' + repr(self.__handle)
|
||||
rep += ',__info=' + repr(self.__info)
|
||||
rep += ')'
|
||||
return rep
|
||||
|
||||
def get_id(self) -> str:
|
||||
"""Get Interface Id such as VimbaUSBInterface_0x0."""
|
||||
return decode_cstr(self.__info.interfaceIdString)
|
||||
|
||||
def get_type(self) -> InterfaceType:
|
||||
"""Get Interface Type such as InterfaceType.Usb."""
|
||||
return InterfaceType(self.__info.interfaceType)
|
||||
|
||||
def get_name(self) -> str:
|
||||
"""Get Interface Name such as Vimba USB Interface."""
|
||||
return decode_cstr(self.__info.interfaceName)
|
||||
|
||||
def get_serial(self) -> str:
|
||||
"""Get Interface Serial or '' if not set."""
|
||||
return decode_cstr(self.__info.serialString)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def read_memory(self, addr: int, max_bytes: int) -> bytes: # coverage: skip
|
||||
"""Read a byte sequence from a given memory address.
|
||||
|
||||
Arguments:
|
||||
addr: Starting address to read from.
|
||||
max_bytes: Maximum number of bytes to read from addr.
|
||||
|
||||
Returns:
|
||||
Read memory contents as bytes.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
ValueError if addr is negative.
|
||||
ValueError if max_bytes is negative.
|
||||
ValueError if the memory access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return read_memory(self.__handle, addr, max_bytes)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def write_memory(self, addr: int, data: bytes): # coverage: skip
|
||||
"""Write a byte sequence to a given memory address.
|
||||
|
||||
Arguments:
|
||||
addr: Address to write the content of 'data' to.
|
||||
data: Byte sequence to write at address 'addr'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
ValueError if addr is negative.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return write_memory(self.__handle, addr, data)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def read_registers(self, addrs: Tuple[int, ...]) -> Dict[int, int]: # coverage: skip
|
||||
"""Read contents of multiple registers.
|
||||
|
||||
Arguments:
|
||||
addrs: Sequence of addresses that should be read iteratively.
|
||||
|
||||
Returns:
|
||||
Dictionary containing a mapping from given address to the read register values.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
ValueError if any address in addrs is negative.
|
||||
ValueError if the register access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return read_registers(self.__handle, addrs)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def write_registers(self, addrs_values: Dict[int, int]): # coverage: skip
|
||||
"""Write data to multiple registers.
|
||||
|
||||
Arguments:
|
||||
addrs_values: Mapping between register addresses and the data to write.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
ValueError if any address in addrs_values is negative.
|
||||
ValueError if the register access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return write_registers(self.__handle, addrs_values)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
def get_all_features(self) -> FeaturesTuple:
|
||||
"""Get access to all discovered features of this Interface.
|
||||
|
||||
Returns:
|
||||
A set of all currently detected features.
|
||||
|
||||
Raises:
|
||||
RuntimeError if called outside "with" - statement.
|
||||
"""
|
||||
return self.__feats
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_affected_by(self, feat: FeatureTypes) -> FeaturesTuple:
|
||||
"""Get all features affected by a specific interface feature.
|
||||
|
||||
Arguments:
|
||||
feat - Feature to find features that are affected by 'feat'.
|
||||
|
||||
Returns:
|
||||
A set of features affected by changes on 'feat'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
VimbaFeatureError if 'feat' is not a feature of this interface.
|
||||
"""
|
||||
return filter_affected_features(self.__feats, feat)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_selected_by(self, feat: FeatureTypes) -> FeaturesTuple:
|
||||
"""Get all features selected by a specific interface feature.
|
||||
|
||||
Arguments:
|
||||
feat - Feature to find features that are selected by 'feat'.
|
||||
|
||||
Returns:
|
||||
A set of features selected by changes on 'feat'.
|
||||
|
||||
Raises:
|
||||
TypeError if 'feat' is not of any feature type.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
VimbaFeatureError if 'feat' is not a feature of this interface.
|
||||
"""
|
||||
return filter_selected_features(self.__feats, feat)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_by_type(self, feat_type: FeatureTypeTypes) -> FeaturesTuple:
|
||||
"""Get all interface features of a specific feature type.
|
||||
|
||||
Valid FeatureTypes are: IntFeature, FloatFeature, StringFeature, BoolFeature,
|
||||
EnumFeature, CommandFeature, RawFeature
|
||||
|
||||
Arguments:
|
||||
feat_type - FeatureType used find features of that type.
|
||||
|
||||
Returns:
|
||||
A set of features of type 'feat_type'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
"""
|
||||
return filter_features_by_type(self.__feats, feat_type)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_by_category(self, category: str) -> FeaturesTuple:
|
||||
"""Get all interface features of a specific category.
|
||||
|
||||
Arguments:
|
||||
category - category for filtering.
|
||||
|
||||
Returns:
|
||||
A set of features of category 'category'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
"""
|
||||
return filter_features_by_category(self.__feats, category)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_feature_by_name(self, feat_name: str) -> FeatureTypes:
|
||||
"""Get an interface feature by its name.
|
||||
|
||||
Arguments:
|
||||
feat_name - Name to find a feature.
|
||||
|
||||
Returns:
|
||||
Feature with the associated name.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called outside "with" - statement.
|
||||
VimbaFeatureError if no feature is associated with 'feat_name'.
|
||||
"""
|
||||
feat = filter_features_by_name(self.__feats, feat_name)
|
||||
|
||||
if not feat:
|
||||
raise VimbaFeatureError('Feature \'{}\' not found.'.format(feat_name))
|
||||
|
||||
return feat
|
||||
|
||||
@TraceEnable()
|
||||
@EnterContextOnCall()
|
||||
def _open(self):
|
||||
call_vimba_c('VmbInterfaceOpen', self.__info.interfaceIdString, byref(self.__handle))
|
||||
|
||||
self.__feats = discover_features(self.__handle)
|
||||
attach_feature_accessors(self, self.__feats)
|
||||
|
||||
@TraceEnable()
|
||||
@LeaveContextOnCall()
|
||||
def _close(self):
|
||||
for feat in self.__feats:
|
||||
feat.unregister_all_change_handlers()
|
||||
|
||||
remove_feature_accessors(self, self.__feats)
|
||||
self.__feats = ()
|
||||
|
||||
call_vimba_c('VmbInterfaceClose', self.__handle)
|
||||
|
||||
self.__handle = VmbHandle(0)
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def discover_interfaces() -> InterfacesList:
|
||||
"""Do not call directly. Access Interfaces via vimba.System instead."""
|
||||
|
||||
result = []
|
||||
inters_count = VmbUint32(0)
|
||||
|
||||
call_vimba_c('VmbInterfacesList', None, 0, byref(inters_count), sizeof(VmbInterfaceInfo))
|
||||
|
||||
if inters_count:
|
||||
inters_found = VmbUint32(0)
|
||||
inters_infos = (VmbInterfaceInfo * inters_count.value)()
|
||||
|
||||
call_vimba_c('VmbInterfacesList', inters_infos, inters_count, byref(inters_found),
|
||||
sizeof(VmbInterfaceInfo))
|
||||
|
||||
for info in inters_infos[:inters_found.value]:
|
||||
result.append(Interface(info))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def discover_interface(id_: str) -> Interface:
|
||||
"""Do not call directly. Access Interfaces via vimba.System instead."""
|
||||
|
||||
# Since there is no function to query a single interface, discover all interfaces and
|
||||
# extract the Interface with the matching ID.
|
||||
inters = discover_interfaces()
|
||||
return [i for i in inters if id_ == i.get_id()].pop()
|
||||
357
Vimba_6_0/VimbaPython/Source/vimba/shared.py
Normal file
357
Vimba_6_0/VimbaPython/Source/vimba/shared.py
Normal file
@@ -0,0 +1,357 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import itertools
|
||||
|
||||
from typing import Dict, Tuple
|
||||
from .c_binding import VmbUint32, VmbUint64, VmbHandle, VmbFeatureInfo
|
||||
from .c_binding import call_vimba_c, byref, sizeof, create_string_buffer, VimbaCError
|
||||
from .feature import FeaturesTuple, FeatureTypes, FeatureTypeTypes
|
||||
from .error import VimbaFeatureError
|
||||
from .util import TraceEnable
|
||||
|
||||
__all__ = [
|
||||
'filter_affected_features',
|
||||
'filter_selected_features',
|
||||
'filter_features_by_name',
|
||||
'filter_features_by_type',
|
||||
'filter_features_by_category',
|
||||
'attach_feature_accessors',
|
||||
'remove_feature_accessors',
|
||||
'read_memory',
|
||||
'write_memory',
|
||||
'read_registers',
|
||||
'write_registers'
|
||||
]
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def filter_affected_features(feats: FeaturesTuple, feat: FeatureTypes) -> FeaturesTuple:
|
||||
"""Search for all Features affected by a given feature within a feature set.
|
||||
|
||||
Arguments:
|
||||
feats: Feature set to search in.
|
||||
feat: Feature that might affect Features within 'feats'.
|
||||
|
||||
Returns:
|
||||
A set of all features that are affected by 'feat'.
|
||||
|
||||
Raises:
|
||||
VimbaFeatureError if 'feat' is not stored within 'feats'.
|
||||
"""
|
||||
|
||||
if feat not in feats:
|
||||
raise VimbaFeatureError('Feature \'{}\' not in given Features'.format(feat.get_name()))
|
||||
|
||||
result = []
|
||||
|
||||
if feat.has_affected_features():
|
||||
feats_count = VmbUint32()
|
||||
feats_handle = feat._handle
|
||||
feats_name = feat._info.name
|
||||
|
||||
# Query affected features from given Feature
|
||||
call_vimba_c('VmbFeatureListAffected', feats_handle, feats_name, None, 0,
|
||||
byref(feats_count), sizeof(VmbFeatureInfo))
|
||||
|
||||
feats_found = VmbUint32(0)
|
||||
feats_infos = (VmbFeatureInfo * feats_count.value)()
|
||||
|
||||
call_vimba_c('VmbFeatureListAffected', feats_handle, feats_name, feats_infos, feats_count,
|
||||
byref(feats_found), sizeof(VmbFeatureInfo))
|
||||
|
||||
# Search affected features in given feature set
|
||||
for info, feature in itertools.product(feats_infos[:feats_found.value], feats):
|
||||
if info.name == feature._info.name:
|
||||
result.append(feature)
|
||||
|
||||
return tuple(result)
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def filter_selected_features(feats: FeaturesTuple, feat: FeatureTypes) -> FeaturesTuple:
|
||||
"""Search for all Features selected by a given feature within a feature set.
|
||||
|
||||
Arguments:
|
||||
feats: Feature set to search in.
|
||||
feat: Feature that might select Features within 'feats'.
|
||||
|
||||
Returns:
|
||||
A set of all features that are selected by 'feat'.
|
||||
|
||||
Raises:
|
||||
VimbaFeatureError if 'feat' is not stored within 'feats'.
|
||||
"""
|
||||
if feat not in feats:
|
||||
raise VimbaFeatureError('Feature \'{}\' not in given Features'.format(feat.get_name()))
|
||||
|
||||
result = []
|
||||
|
||||
if feat.has_selected_features():
|
||||
feats_count = VmbUint32()
|
||||
feats_handle = feat._handle
|
||||
feats_name = feat._info.name
|
||||
|
||||
# Query selected features from given feature
|
||||
call_vimba_c('VmbFeatureListSelected', feats_handle, feats_name, None, 0,
|
||||
byref(feats_count), sizeof(VmbFeatureInfo))
|
||||
|
||||
feats_found = VmbUint32(0)
|
||||
feats_infos = (VmbFeatureInfo * feats_count.value)()
|
||||
|
||||
call_vimba_c('VmbFeatureListSelected', feats_handle, feats_name, feats_infos, feats_count,
|
||||
byref(feats_found), sizeof(VmbFeatureInfo))
|
||||
|
||||
# Search selected features in given feature set
|
||||
for info, feature in itertools.product(feats_infos[:feats_found.value], feats):
|
||||
if info.name == feature._info.name:
|
||||
result.append(feature)
|
||||
|
||||
return tuple(result)
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def filter_features_by_name(feats: FeaturesTuple, feat_name: str):
|
||||
"""Search for a feature with a specific name within a feature set.
|
||||
|
||||
Arguments:
|
||||
feats: Feature set to search in.
|
||||
feat_name: Feature name to look for.
|
||||
|
||||
Returns:
|
||||
The Feature with the name 'feat_name' or None if lookup failed
|
||||
"""
|
||||
filtered = [feat for feat in feats if feat_name == feat.get_name()]
|
||||
return filtered.pop() if filtered else None
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def filter_features_by_type(feats: FeaturesTuple, feat_type: FeatureTypeTypes) -> FeaturesTuple:
|
||||
"""Search for all features with a specific type within a given feature set.
|
||||
|
||||
Arguments:
|
||||
feats: Feature set to search in.
|
||||
feat_type: Feature Type to search for
|
||||
|
||||
Returns:
|
||||
A set of all features of type 'feat_type' in 'feats'. If no matching type is found an
|
||||
empty set is returned.
|
||||
"""
|
||||
return tuple([feat for feat in feats if type(feat) == feat_type])
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def filter_features_by_category(feats: FeaturesTuple, category: str) -> FeaturesTuple:
|
||||
"""Search for all features of a given category.
|
||||
|
||||
Arguments:
|
||||
feats: Feature set to search in.
|
||||
category: Category to filter for
|
||||
|
||||
Returns:
|
||||
A set of all features of category 'category' in 'feats'. If no matching type is found an
|
||||
empty set is returned.
|
||||
"""
|
||||
return tuple([feat for feat in feats if feat.get_category() == category])
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def attach_feature_accessors(obj, feats: FeaturesTuple):
|
||||
"""Attach all Features in feats to obj under the feature name.
|
||||
|
||||
Arguments:
|
||||
obj: Object feats should be attached on.
|
||||
feats: Features to attach.
|
||||
"""
|
||||
BLACKLIST = (
|
||||
'PixelFormat', # PixelFormats have special access methods.
|
||||
)
|
||||
|
||||
for feat in feats:
|
||||
feat_name = feat.get_name()
|
||||
if feat_name not in BLACKLIST:
|
||||
setattr(obj, feat_name, feat)
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def remove_feature_accessors(obj, feats: FeaturesTuple):
|
||||
"""Remove all Features in feats from obj.
|
||||
|
||||
Arguments:
|
||||
obj: Object, feats should be removed from.
|
||||
feats: Features to remove.
|
||||
"""
|
||||
for feat in feats:
|
||||
try:
|
||||
delattr(obj, feat.get_name())
|
||||
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def read_memory(handle: VmbHandle, addr: int, max_bytes: int) -> bytes: # coverage: skip
|
||||
"""Read a byte sequence from a given memory address.
|
||||
|
||||
Arguments:
|
||||
handle: Handle on entity that allows raw memory access.
|
||||
addr: Starting address to read from.
|
||||
max_bytes: Maximum number of bytes to read from addr.
|
||||
|
||||
Returns:
|
||||
Read memory contents as bytes.
|
||||
|
||||
Raises:
|
||||
ValueError if addr is negative
|
||||
ValueError if max_bytes is negative.
|
||||
ValueError if the memory access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
_verify_addr(addr)
|
||||
_verify_size(max_bytes)
|
||||
|
||||
buf = create_string_buffer(max_bytes)
|
||||
bytesRead = VmbUint32()
|
||||
|
||||
try:
|
||||
call_vimba_c('VmbMemoryRead', handle, addr, max_bytes, buf, byref(bytesRead))
|
||||
|
||||
except VimbaCError as e:
|
||||
msg = 'Memory read access at {} failed with C-Error: {}.'
|
||||
raise ValueError(msg.format(hex(addr), repr(e.get_error_code()))) from e
|
||||
|
||||
return buf.raw[:bytesRead.value]
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def write_memory(handle: VmbHandle, addr: int, data: bytes): # coverage: skip
|
||||
""" Write a byte sequence to a given memory address.
|
||||
|
||||
Arguments:
|
||||
handle: Handle on entity that allows raw memory access.
|
||||
addr: Address to write the content of 'data' too.
|
||||
data: Byte sequence to write at address 'addr'.
|
||||
|
||||
Raises:
|
||||
ValueError if addr is negative.
|
||||
ValueError if the memory access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
_verify_addr(addr)
|
||||
|
||||
bytesWrite = VmbUint32()
|
||||
|
||||
try:
|
||||
call_vimba_c('VmbMemoryWrite', handle, addr, len(data), data, byref(bytesWrite))
|
||||
|
||||
except VimbaCError as e:
|
||||
msg = 'Memory write access at {} failed with C-Error: {}.'
|
||||
raise ValueError(msg.format(hex(addr), repr(e.get_error_code()))) from e
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def read_registers(handle: VmbHandle, addrs: Tuple[int, ...]) -> Dict[int, int]: # coverage: skip
|
||||
"""Read contents of multiple registers.
|
||||
|
||||
Arguments:
|
||||
handle: Handle on entity providing registers to access.
|
||||
addrs: Sequence of addresses that should be read iteratively.
|
||||
|
||||
Return:
|
||||
Dictionary containing a mapping from given address to the read register values.
|
||||
|
||||
Raises:
|
||||
ValueError if any address in addrs is negative.
|
||||
ValueError if the register access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
for addr in addrs:
|
||||
_verify_addr(addr)
|
||||
|
||||
size = len(addrs)
|
||||
valid_reads = VmbUint32()
|
||||
|
||||
c_addrs = (VmbUint64 * size)()
|
||||
c_values = (VmbUint64 * size)()
|
||||
|
||||
for i, addr in enumerate(addrs):
|
||||
c_addrs[i] = addr
|
||||
|
||||
try:
|
||||
call_vimba_c('VmbRegistersRead', handle, size, c_addrs, c_values, byref(valid_reads))
|
||||
|
||||
except VimbaCError as e:
|
||||
msg = 'Register read access failed with C-Error: {}.'
|
||||
raise ValueError(msg.format(repr(e.get_error_code()))) from e
|
||||
|
||||
return dict(zip(c_addrs, c_values))
|
||||
|
||||
|
||||
@TraceEnable()
|
||||
def write_registers(handle: VmbHandle, addrs_values: Dict[int, int]): # coverage: skip
|
||||
"""Write data to multiple Registers.
|
||||
|
||||
Arguments:
|
||||
handle: Handle on entity providing registers to access.
|
||||
addrs_values: Mapping between Register addresses and the data to write.
|
||||
|
||||
Raises:
|
||||
ValueError if any address in addrs_values is negative.
|
||||
ValueError if the register access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
for addr in addrs_values:
|
||||
_verify_addr(addr)
|
||||
|
||||
size = len(addrs_values)
|
||||
valid_writes = VmbUint32()
|
||||
|
||||
addrs = (VmbUint64 * size)()
|
||||
values = (VmbUint64 * size)()
|
||||
|
||||
for i, addr in enumerate(addrs_values):
|
||||
addrs[i] = addr
|
||||
values[i] = addrs_values[addr]
|
||||
|
||||
try:
|
||||
call_vimba_c('VmbRegistersWrite', handle, size, addrs, values, byref(valid_writes))
|
||||
|
||||
except VimbaCError as e:
|
||||
msg = 'Register write access failed with C-Error: {}.'
|
||||
raise ValueError(msg.format(repr(e.get_error_code()))) from e
|
||||
|
||||
|
||||
def _verify_addr(addr: int): # coverage: skip
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
if addr < 0:
|
||||
raise ValueError('Given Address {} is negative'.format(addr))
|
||||
|
||||
|
||||
def _verify_size(size: int): # coverage: skip
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
if size < 0:
|
||||
raise ValueError('Given size {} is negative'.format(size))
|
||||
72
Vimba_6_0/VimbaPython/Source/vimba/util/__init__.py
Normal file
72
Vimba_6_0/VimbaPython/Source/vimba/util/__init__.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
# Suppress 'imported but unused' - Error from static style checker.
|
||||
# flake8: noqa: F401
|
||||
|
||||
__all__ = [
|
||||
'LogLevel',
|
||||
'LogConfig',
|
||||
'Log',
|
||||
'LOG_CONFIG_TRACE_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_TRACE_FILE_ONLY',
|
||||
'LOG_CONFIG_TRACE',
|
||||
'LOG_CONFIG_INFO_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_INFO_FILE_ONLY',
|
||||
'LOG_CONFIG_INFO',
|
||||
'LOG_CONFIG_WARNING_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_WARNING_FILE_ONLY',
|
||||
'LOG_CONFIG_WARNING',
|
||||
'LOG_CONFIG_ERROR_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_ERROR_FILE_ONLY',
|
||||
'LOG_CONFIG_ERROR',
|
||||
'LOG_CONFIG_CRITICAL_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_CRITICAL_FILE_ONLY',
|
||||
'LOG_CONFIG_CRITICAL',
|
||||
|
||||
# Decorators
|
||||
'TraceEnable',
|
||||
'ScopedLogEnable',
|
||||
'RuntimeTypeCheckEnable',
|
||||
'EnterContextOnCall',
|
||||
'LeaveContextOnCall',
|
||||
'RaiseIfInsideContext',
|
||||
'RaiseIfOutsideContext'
|
||||
]
|
||||
|
||||
from .log import Log, LogLevel, LogConfig, LOG_CONFIG_TRACE_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_TRACE_FILE_ONLY, LOG_CONFIG_TRACE, LOG_CONFIG_INFO_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_INFO_FILE_ONLY, LOG_CONFIG_INFO, LOG_CONFIG_WARNING_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_WARNING_FILE_ONLY, LOG_CONFIG_WARNING, LOG_CONFIG_ERROR_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_ERROR_FILE_ONLY, LOG_CONFIG_ERROR, LOG_CONFIG_CRITICAL_CONSOLE_ONLY, \
|
||||
LOG_CONFIG_CRITICAL_FILE_ONLY, LOG_CONFIG_CRITICAL
|
||||
|
||||
from .tracer import TraceEnable
|
||||
from .scoped_log import ScopedLogEnable
|
||||
from .runtime_type_check import RuntimeTypeCheckEnable
|
||||
from .context_decorator import EnterContextOnCall, LeaveContextOnCall, RaiseIfInsideContext, \
|
||||
RaiseIfOutsideContext
|
||||
96
Vimba_6_0/VimbaPython/Source/vimba/util/context_decorator.py
Normal file
96
Vimba_6_0/VimbaPython/Source/vimba/util/context_decorator.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import functools
|
||||
|
||||
__all__ = [
|
||||
'EnterContextOnCall',
|
||||
'LeaveContextOnCall',
|
||||
'RaiseIfInsideContext',
|
||||
'RaiseIfOutsideContext'
|
||||
]
|
||||
|
||||
|
||||
class EnterContextOnCall:
|
||||
"""Decorator setting/injecting flag used for checking the context."""
|
||||
def __call__(self, func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
args[0]._context_entered = True
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class LeaveContextOnCall:
|
||||
"""Decorator clearing/injecting flag used for checking the context."""
|
||||
def __call__(self, func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
result = func(*args, **kwargs)
|
||||
args[0]._context_entered = False
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class RaiseIfInsideContext:
|
||||
"""Raising RuntimeError is decorated Method is called inside with-statement.
|
||||
|
||||
Note This Decorator shall work only on Object implementing a Context Manger.
|
||||
For this to work object must offer a boolean attribute called _context_entered
|
||||
"""
|
||||
def __call__(self, func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if args[0]._context_entered:
|
||||
msg = 'Called \'{}()\' inside of \'with\' - statement scope.'
|
||||
msg = msg.format('{}'.format(func.__qualname__))
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class RaiseIfOutsideContext:
|
||||
"""Raising RuntimeError is decorated Method is called outside with-statement.
|
||||
|
||||
Note This Decorator shall work only on Object implementing a Context Manger.
|
||||
For this to work object must offer a boolean attribute called __context_entered
|
||||
"""
|
||||
def __call__(self, func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if not args[0]._context_entered:
|
||||
msg = 'Called \'{}()\' outside of \'with\' - statement scope.'
|
||||
msg = msg.format('{}'.format(func.__qualname__))
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
295
Vimba_6_0/VimbaPython/Source/vimba/util/log.py
Normal file
295
Vimba_6_0/VimbaPython/Source/vimba/util/log.py
Normal file
@@ -0,0 +1,295 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import os
|
||||
import enum
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
__all__ = [
|
||||
'LogLevel',
|
||||
'LogConfig',
|
||||
'Log',
|
||||
'LOG_CONFIG_TRACE_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_TRACE_FILE_ONLY',
|
||||
'LOG_CONFIG_TRACE',
|
||||
'LOG_CONFIG_INFO_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_INFO_FILE_ONLY',
|
||||
'LOG_CONFIG_INFO',
|
||||
'LOG_CONFIG_WARNING_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_WARNING_FILE_ONLY',
|
||||
'LOG_CONFIG_WARNING',
|
||||
'LOG_CONFIG_ERROR_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_ERROR_FILE_ONLY',
|
||||
'LOG_CONFIG_ERROR',
|
||||
'LOG_CONFIG_CRITICAL_CONSOLE_ONLY',
|
||||
'LOG_CONFIG_CRITICAL_FILE_ONLY',
|
||||
'LOG_CONFIG_CRITICAL'
|
||||
]
|
||||
|
||||
|
||||
class LogLevel(enum.IntEnum):
|
||||
"""Enum containing all LogLevels.
|
||||
|
||||
Enum values are:
|
||||
Trace - Show Tracing information. Show all messages.
|
||||
Info - Show Informational, Warning, Error, and Critical Events.
|
||||
Warning - Show Warning, Error, and Critical Events.
|
||||
Error - Show Errors and Critical Events.
|
||||
Critical - Show Critical Events only.
|
||||
"""
|
||||
Trace = logging.DEBUG
|
||||
Info = logging.INFO
|
||||
Warning = logging.WARNING
|
||||
Error = logging.ERROR
|
||||
Critical = logging.CRITICAL
|
||||
|
||||
def __str__(self):
|
||||
return self._name_
|
||||
|
||||
def as_equal_len_str(self) -> str:
|
||||
return _LEVEL_TO_EQUAL_LEN_STR[self]
|
||||
|
||||
|
||||
_LEVEL_TO_EQUAL_LEN_STR = {
|
||||
LogLevel.Trace: 'Trace ',
|
||||
LogLevel.Info: 'Info ',
|
||||
LogLevel.Warning: 'Warning ',
|
||||
LogLevel.Error: 'Error ',
|
||||
LogLevel.Critical: 'Critical'
|
||||
}
|
||||
|
||||
|
||||
class LogConfig:
|
||||
"""The LogConfig is a builder to configure various specialized logging configurations.
|
||||
The constructed LogConfig must set via vimba.Vimba or the ScopedLogEnable Decorator
|
||||
to start logging.
|
||||
"""
|
||||
|
||||
__ENTRY_FORMAT = logging.Formatter('%(asctime)s | %(message)s')
|
||||
|
||||
def __init__(self):
|
||||
self.__handlers: List[logging.Handler] = []
|
||||
self.__max_msg_length: Optional[int] = None
|
||||
|
||||
def add_file_log(self, level: LogLevel) -> 'LogConfig':
|
||||
"""Add a new Log file to the Config Builder.
|
||||
|
||||
Arguments:
|
||||
level: LogLevel of the added log file.
|
||||
|
||||
Returns:
|
||||
Reference to the LogConfig instance (builder pattern).
|
||||
"""
|
||||
log_ts = datetime.datetime.today().strftime('%Y-%m-%d_%H-%M-%S')
|
||||
log_file = 'VimbaPython_{}_{}.log'.format(log_ts, str(level))
|
||||
log_file = os.path.join(os.getcwd(), log_file)
|
||||
|
||||
handler = logging.FileHandler(log_file, delay=True)
|
||||
handler.setLevel(level)
|
||||
handler.setFormatter(LogConfig.__ENTRY_FORMAT)
|
||||
|
||||
self.__handlers.append(handler)
|
||||
return self
|
||||
|
||||
def add_console_log(self, level: LogLevel) -> 'LogConfig':
|
||||
"""Add a new Console Log to the Config Builder.
|
||||
|
||||
Arguments:
|
||||
level: LogLevel of the added console log file.
|
||||
|
||||
Returns:
|
||||
Reference to the LogConfig instance (builder pattern).
|
||||
"""
|
||||
handler = logging.StreamHandler()
|
||||
handler.setLevel(level)
|
||||
handler.setFormatter(LogConfig.__ENTRY_FORMAT)
|
||||
|
||||
self.__handlers.append(handler)
|
||||
return self
|
||||
|
||||
def set_max_msg_length(self, max_msg_length: int):
|
||||
"""Set max length of a log entry. Messages longer than this entry will be cut off."""
|
||||
self.__max_msg_length = max_msg_length
|
||||
|
||||
def get_max_msg_length(self) -> Optional[int]:
|
||||
"""Get configured max message length"""
|
||||
return self.__max_msg_length
|
||||
|
||||
def get_handlers(self) -> List[logging.Handler]:
|
||||
"""Get all configured log handlers"""
|
||||
return self.__handlers
|
||||
|
||||
|
||||
class Log:
|
||||
class __Impl:
|
||||
"""This class is wraps the logging Facility. Since this is as Singleton
|
||||
Use Log.get_instace(), to access the log.
|
||||
"""
|
||||
def __init__(self):
|
||||
"""Do not call directly. Use Log.get_instance() instead."""
|
||||
self.__logger: Optional[logging.Logger] = None
|
||||
self.__config: Optional[LogConfig] = None
|
||||
self._test_buffer: Optional[List[str]] = None
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.__logger)
|
||||
|
||||
def enable(self, config: LogConfig):
|
||||
"""Enable global VimbaPython logging mechanism.
|
||||
|
||||
Arguments:
|
||||
config: The configuration to apply.
|
||||
"""
|
||||
self.disable()
|
||||
|
||||
logger = logging.getLogger('VimbaPythonLog')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
for handler in config.get_handlers():
|
||||
logger.addHandler(handler)
|
||||
|
||||
self.__config = config
|
||||
self.__logger = logger
|
||||
|
||||
def disable(self):
|
||||
"""Disable global VimbaPython logging mechanism."""
|
||||
if self.__logger and self.__config:
|
||||
for handler in self.__config.get_handlers():
|
||||
handler.close()
|
||||
self.__logger.removeHandler(handler)
|
||||
|
||||
self.__logger = None
|
||||
self.__config = None
|
||||
|
||||
def get_config(self) -> Optional[LogConfig]:
|
||||
""" Get log configuration
|
||||
|
||||
Returns:
|
||||
Configuration if the log is enabled. In case the log is disabled return None.
|
||||
"""
|
||||
return self.__config
|
||||
|
||||
def trace(self, msg: str):
|
||||
"""Add an entry of LogLevel.Trace to the log. Does nothing is the log is disabled.
|
||||
|
||||
Arguments:
|
||||
msg - The message that should be added to the Log.
|
||||
"""
|
||||
if self.__logger:
|
||||
self.__logger.debug(self.__build_msg(LogLevel.Trace, msg))
|
||||
|
||||
def info(self, msg: str):
|
||||
"""Add an entry of LogLevel.Info to the log. Does nothing is the log is disabled.
|
||||
|
||||
Arguments:
|
||||
msg - The message that should be added to the Log.
|
||||
"""
|
||||
if self.__logger:
|
||||
self.__logger.info(self.__build_msg(LogLevel.Info, msg))
|
||||
|
||||
def warning(self, msg: str):
|
||||
"""Add an entry of LogLevel.Warning to the log. Does nothing is the log is disabled.
|
||||
|
||||
Arguments:
|
||||
msg - The message that should be added to the Log.
|
||||
"""
|
||||
if self.__logger:
|
||||
self.__logger.warning(self.__build_msg(LogLevel.Warning, msg))
|
||||
|
||||
def error(self, msg: str):
|
||||
"""Add an entry of LogLevel.Error to the log. Does nothing is the log is disabled.
|
||||
|
||||
Arguments:
|
||||
msg - The message that should be added to the Log.
|
||||
"""
|
||||
if self.__logger:
|
||||
self.__logger.error(self.__build_msg(LogLevel.Error, msg))
|
||||
|
||||
def critical(self, msg: str):
|
||||
"""Add an entry of LogLevel.Critical to the log. Does nothing is the log is disabled.
|
||||
|
||||
Arguments:
|
||||
msg - The message that should be added to the Log.
|
||||
"""
|
||||
if self.__logger:
|
||||
self.__logger.critical(self.__build_msg(LogLevel.Critical, msg))
|
||||
|
||||
def __build_msg(self, loglevel: LogLevel, msg: str) -> str:
|
||||
msg = '{} | {}'.format(loglevel.as_equal_len_str(), msg)
|
||||
max_len = self.__config.get_max_msg_length() if self.__config else None
|
||||
|
||||
if max_len and (max_len < len(msg)):
|
||||
suffix = ' ...'
|
||||
msg = msg[:max_len - len(suffix)] + suffix
|
||||
|
||||
if self._test_buffer is not None:
|
||||
self._test_buffer.append(msg)
|
||||
|
||||
return msg
|
||||
|
||||
__instance = __Impl()
|
||||
|
||||
@staticmethod
|
||||
def get_instance() -> '__Impl':
|
||||
"""Get Log instance."""
|
||||
return Log.__instance
|
||||
|
||||
|
||||
def _build_cfg(console_level: Optional[LogLevel], file_level: Optional[LogLevel]) -> LogConfig:
|
||||
cfg = LogConfig()
|
||||
|
||||
cfg.set_max_msg_length(200)
|
||||
|
||||
if console_level:
|
||||
cfg.add_console_log(console_level)
|
||||
|
||||
if file_level:
|
||||
cfg.add_file_log(file_level)
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
# Exported Default Log configurations.
|
||||
LOG_CONFIG_TRACE_CONSOLE_ONLY = _build_cfg(LogLevel.Trace, None)
|
||||
LOG_CONFIG_TRACE_FILE_ONLY = _build_cfg(None, LogLevel.Trace)
|
||||
LOG_CONFIG_TRACE = _build_cfg(LogLevel.Trace, LogLevel.Trace)
|
||||
LOG_CONFIG_INFO_CONSOLE_ONLY = _build_cfg(LogLevel.Info, None)
|
||||
LOG_CONFIG_INFO_FILE_ONLY = _build_cfg(None, LogLevel.Info)
|
||||
LOG_CONFIG_INFO = _build_cfg(LogLevel.Info, LogLevel.Info)
|
||||
LOG_CONFIG_WARNING_CONSOLE_ONLY = _build_cfg(LogLevel.Warning, None)
|
||||
LOG_CONFIG_WARNING_FILE_ONLY = _build_cfg(None, LogLevel.Warning)
|
||||
LOG_CONFIG_WARNING = _build_cfg(LogLevel.Warning, LogLevel.Warning)
|
||||
LOG_CONFIG_ERROR_CONSOLE_ONLY = _build_cfg(LogLevel.Error, None)
|
||||
LOG_CONFIG_ERROR_FILE_ONLY = _build_cfg(None, LogLevel.Error)
|
||||
LOG_CONFIG_ERROR = _build_cfg(LogLevel.Error, LogLevel.Error)
|
||||
LOG_CONFIG_CRITICAL_CONSOLE_ONLY = _build_cfg(LogLevel.Critical, None)
|
||||
LOG_CONFIG_CRITICAL_FILE_ONLY = _build_cfg(None, LogLevel.Critical)
|
||||
LOG_CONFIG_CRITICAL = _build_cfg(LogLevel.Critical, LogLevel.Critical)
|
||||
223
Vimba_6_0/VimbaPython/Source/vimba/util/runtime_type_check.py
Normal file
223
Vimba_6_0/VimbaPython/Source/vimba/util/runtime_type_check.py
Normal file
@@ -0,0 +1,223 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import collections.abc
|
||||
|
||||
from inspect import isfunction, ismethod, signature
|
||||
from functools import wraps
|
||||
from typing import get_type_hints, Union
|
||||
from .log import Log
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RuntimeTypeCheckEnable'
|
||||
]
|
||||
|
||||
|
||||
class RuntimeTypeCheckEnable:
|
||||
"""Decorator adding runtime type checking to the wrapped callable.
|
||||
|
||||
Each time the callable is executed, all arguments are checked if they match with the given
|
||||
type hints. If all checks are passed, the wrapped function is executed, if the given
|
||||
arguments to not match a TypeError is raised.
|
||||
Note: This decorator is no replacement for a feature complete TypeChecker. It supports only
|
||||
a subset of all types expressible by type hints.
|
||||
"""
|
||||
_log = Log.get_instance()
|
||||
|
||||
def __call__(self, func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
full_args, hints = self.__dismantle_sig(func, *args, **kwargs)
|
||||
|
||||
for arg_name in hints:
|
||||
self.__verify_arg(func, hints[arg_name], (arg_name, full_args[arg_name]))
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
def __dismantle_sig(self, func, *args, **kwargs):
|
||||
# Get merge args, kwargs and defaults to complete argument list.
|
||||
full_args = signature(func).bind(*args, **kwargs)
|
||||
full_args.apply_defaults()
|
||||
|
||||
# Get available type hints, remove return value.
|
||||
hints = get_type_hints(func)
|
||||
hints.pop('return', None)
|
||||
|
||||
return (full_args.arguments, hints)
|
||||
|
||||
def __verify_arg(self, func, type_hint, arg_spec):
|
||||
arg_name, arg = arg_spec
|
||||
|
||||
if (self.__matches(type_hint, arg)):
|
||||
return
|
||||
|
||||
msg = '\'{}\' called with unexpected argument type. Argument\'{}\'. Expected type: {}.'
|
||||
msg = msg.format(func.__qualname__, arg_name, type_hint)
|
||||
|
||||
RuntimeTypeCheckEnable._log.error(msg)
|
||||
raise TypeError(msg)
|
||||
|
||||
def __matches(self, type_hint, arg) -> bool:
|
||||
if self.__matches_base_types(type_hint, arg):
|
||||
return True
|
||||
|
||||
elif self.__matches_type_types(type_hint, arg):
|
||||
return True
|
||||
|
||||
elif self.__matches_union_types(type_hint, arg):
|
||||
return True
|
||||
|
||||
elif self.__matches_tuple_types(type_hint, arg):
|
||||
return True
|
||||
|
||||
elif self.__matches_dict_types(type_hint, arg):
|
||||
return True
|
||||
|
||||
else:
|
||||
return self.__matches_callable(type_hint, arg)
|
||||
|
||||
def __matches_base_types(self, type_hint, arg) -> bool:
|
||||
return type_hint == type(arg)
|
||||
|
||||
def __matches_type_types(self, type_hint, arg) -> bool:
|
||||
try:
|
||||
if not type_hint.__origin__ == type:
|
||||
return False
|
||||
|
||||
hint_args = type_hint.__args__
|
||||
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
return arg in hint_args
|
||||
|
||||
def __matches_union_types(self, type_hint, arg) -> bool:
|
||||
try:
|
||||
if not type_hint.__origin__ == Union:
|
||||
return False
|
||||
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
# If Matches if true for an Union hint:
|
||||
for hint in type_hint.__args__:
|
||||
if self.__matches(hint, arg):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def __matches_tuple_types(self, type_hint, arg) -> bool:
|
||||
try:
|
||||
if not (type_hint.__origin__ == tuple and type(arg) == tuple):
|
||||
return False
|
||||
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
if arg == ():
|
||||
return True
|
||||
|
||||
if Ellipsis in type_hint.__args__:
|
||||
fn = self.__matches_var_length_tuple
|
||||
|
||||
else:
|
||||
fn = self.__matches_fixed_size_tuple
|
||||
|
||||
return fn(type_hint, arg)
|
||||
|
||||
def __matches_fixed_size_tuple(self, type_hint, arg) -> bool:
|
||||
# To pass, the entire tuple must match in length and all types
|
||||
expand_hint = type_hint.__args__
|
||||
|
||||
if len(expand_hint) != len(arg):
|
||||
return False
|
||||
|
||||
for hint, value in zip(expand_hint, arg):
|
||||
if not self.__matches(hint, value):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __matches_var_length_tuple(self, type_hint, arg) -> bool:
|
||||
# To pass a tuple can be empty or all contents must match the given type.
|
||||
hint, _ = type_hint.__args__
|
||||
|
||||
for value in arg:
|
||||
if not self.__matches(hint, value):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __matches_dict_types(self, type_hint, arg) -> bool:
|
||||
# To pass the hint must be a Dictionary and arg must match the given types.
|
||||
try:
|
||||
if not (type_hint.__origin__ == dict and type(arg) == dict):
|
||||
return False
|
||||
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
key_type, val_type = type_hint.__args__
|
||||
|
||||
for k, v in arg.items():
|
||||
if type(k) != key_type or type(v) != val_type:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __matches_callable(self, type_hint, arg) -> bool:
|
||||
# Return if the given hint is no callable
|
||||
try:
|
||||
if not type_hint.__origin__ == collections.abc.Callable:
|
||||
return False
|
||||
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
# Verify that are is some form of callable.:
|
||||
# 1) Check if it is either a function or a method
|
||||
# 2) If it is an object, check if it has a __call__ method. If so use call for checks.
|
||||
if not (isfunction(arg) or ismethod(arg)):
|
||||
|
||||
try:
|
||||
arg = getattr(arg, '__call__')
|
||||
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
# Examine signature of given callable
|
||||
sig_args = signature(arg).parameters
|
||||
hint_args = type_hint.__args__
|
||||
|
||||
# Verify Parameter list length
|
||||
if len(sig_args) != len(hint_args[:-1]):
|
||||
return False
|
||||
|
||||
return True
|
||||
80
Vimba_6_0/VimbaPython/Source/vimba/util/scoped_log.py
Normal file
80
Vimba_6_0/VimbaPython/Source/vimba/util/scoped_log.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
from functools import wraps
|
||||
from typing import Any, Callable, Tuple, Optional
|
||||
from .log import LogConfig, Log
|
||||
|
||||
|
||||
__all__ = [
|
||||
'ScopedLogEnable'
|
||||
]
|
||||
|
||||
|
||||
class _ScopedLog:
|
||||
__log = Log.get_instance()
|
||||
|
||||
def __init__(self, config: LogConfig):
|
||||
self.__config: LogConfig = config
|
||||
self.__old_config: Optional[LogConfig] = None
|
||||
|
||||
def __enter__(self):
|
||||
self.__old_config = _ScopedLog.__log.get_config()
|
||||
_ScopedLog.__log.enable(self.__config)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
if self.__old_config:
|
||||
_ScopedLog.__log.enable(self.__old_config)
|
||||
|
||||
else:
|
||||
_ScopedLog.__log.disable()
|
||||
|
||||
|
||||
class ScopedLogEnable:
|
||||
"""Decorator: Enables logging facility before execution of the wrapped function
|
||||
and disables logging after exiting the wrapped function. This allows more specific
|
||||
logging of a code section compared to enabling or disabling the global logging mechanism.
|
||||
|
||||
Arguments:
|
||||
config: The configuration the log should be enabled with.
|
||||
"""
|
||||
def __init__(self, config: LogConfig):
|
||||
"""Add scoped logging to a Callable.
|
||||
|
||||
Arguments:
|
||||
config: The configuration the log should be enabled with.
|
||||
"""
|
||||
self.__config = config
|
||||
|
||||
def __call__(self, func: Callable[..., Any]):
|
||||
@wraps(func)
|
||||
def wrapper(*args: Tuple[Any, ...]):
|
||||
with _ScopedLog(self.__config):
|
||||
return func(*args)
|
||||
|
||||
return wrapper
|
||||
136
Vimba_6_0/VimbaPython/Source/vimba/util/tracer.py
Normal file
136
Vimba_6_0/VimbaPython/Source/vimba/util/tracer.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
from functools import reduce, wraps
|
||||
from inspect import signature
|
||||
from .log import Log
|
||||
|
||||
|
||||
__all__ = [
|
||||
'TraceEnable'
|
||||
]
|
||||
|
||||
|
||||
_FMT_MSG_ENTRY: str = 'Enter | {}'
|
||||
_FMT_MSG_LEAVE: str = 'Leave | {}'
|
||||
_FMT_MSG_RAISE: str = 'Raise | {}, {}'
|
||||
_FMT_ERROR: str = 'ErrorType: {}, ErrorValue: {}'
|
||||
_INDENT_PER_LEVEL: str = ' '
|
||||
|
||||
|
||||
def _args_to_str(func, *args, **kwargs) -> str:
|
||||
# Expand function signature
|
||||
sig = signature(func).bind(*args, **kwargs)
|
||||
sig.apply_defaults()
|
||||
full_args = sig.arguments
|
||||
|
||||
# Early return if there is nothing to print
|
||||
if not full_args:
|
||||
return '(None)'
|
||||
|
||||
def fold(args_as_str: str, arg):
|
||||
name, value = arg
|
||||
|
||||
if name == 'self':
|
||||
arg_str = 'self'
|
||||
|
||||
else:
|
||||
arg_str = str(value)
|
||||
|
||||
return '{}{}, '.format(args_as_str, arg_str)
|
||||
|
||||
return '({})'.format(reduce(fold, full_args.items(), '')[:-2])
|
||||
|
||||
|
||||
def _get_indent(level: int) -> str:
|
||||
return _INDENT_PER_LEVEL * level
|
||||
|
||||
|
||||
def _create_enter_msg(name: str, level: int, args_str: str) -> str:
|
||||
msg = '{}{}{}'.format(_get_indent(level), name, args_str)
|
||||
return _FMT_MSG_ENTRY.format(msg)
|
||||
|
||||
|
||||
def _create_leave_msg(name: str, level: int, ) -> str:
|
||||
msg = '{}{}'.format(_get_indent(level), name)
|
||||
return _FMT_MSG_LEAVE.format(msg)
|
||||
|
||||
|
||||
def _create_raise_msg(name: str, level: int, exc_type: Exception, exc_value: str) -> str:
|
||||
msg = '{}{}'.format(_get_indent(level), name)
|
||||
exc = _FMT_ERROR.format(exc_type, exc_value)
|
||||
return _FMT_MSG_RAISE.format(msg, exc)
|
||||
|
||||
|
||||
class _Tracer:
|
||||
__log = Log.get_instance()
|
||||
__level: int = 0
|
||||
|
||||
@staticmethod
|
||||
def is_log_enabled() -> bool:
|
||||
return bool(_Tracer.__log)
|
||||
|
||||
def __init__(self, func, *args, **kwargs):
|
||||
self.__full_name: str = '{}.{}'.format(func.__module__, func.__qualname__)
|
||||
self.__full_args: str = _args_to_str(func, *args, **kwargs)
|
||||
|
||||
def __enter__(self):
|
||||
msg = _create_enter_msg(self.__full_name, _Tracer.__level, self.__full_args)
|
||||
|
||||
_Tracer.__log.trace(msg)
|
||||
_Tracer.__level += 1
|
||||
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
_Tracer.__level -= 1
|
||||
|
||||
if exc_type:
|
||||
msg = _create_raise_msg(self.__full_name, _Tracer.__level, exc_type, exc_value)
|
||||
|
||||
else:
|
||||
msg = _create_leave_msg(self.__full_name, _Tracer.__level)
|
||||
|
||||
_Tracer.__log.trace(msg)
|
||||
|
||||
|
||||
class TraceEnable:
|
||||
"""Decorator: Adds an entry of LogLevel. Trace on entry and exit of the wrapped function.
|
||||
On exit, the log entry contains information if the function was left normally or with an
|
||||
exception.
|
||||
"""
|
||||
def __call__(self, func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if _Tracer.is_log_enabled():
|
||||
with _Tracer(func, *args, **kwargs):
|
||||
result = func(*args, **kwargs)
|
||||
|
||||
return result
|
||||
|
||||
else:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
600
Vimba_6_0/VimbaPython/Source/vimba/vimba.py
Normal file
600
Vimba_6_0/VimbaPython/Source/vimba/vimba.py
Normal file
@@ -0,0 +1,600 @@
|
||||
"""BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Allied Vision Technologies GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import threading
|
||||
from typing import List, Dict, Tuple
|
||||
from .c_binding import call_vimba_c, VIMBA_C_VERSION, VIMBA_IMAGE_TRANSFORM_VERSION, \
|
||||
G_VIMBA_C_HANDLE
|
||||
from .feature import discover_features, FeatureTypes, FeaturesTuple, FeatureTypeTypes, EnumFeature
|
||||
from .shared import filter_features_by_name, filter_features_by_type, filter_affected_features, \
|
||||
filter_selected_features, filter_features_by_category, \
|
||||
attach_feature_accessors, remove_feature_accessors, read_memory, \
|
||||
write_memory, read_registers, write_registers
|
||||
from .interface import Interface, InterfaceChangeHandler, InterfaceEvent, InterfacesTuple, \
|
||||
InterfacesList, discover_interfaces, discover_interface
|
||||
from .camera import Camera, CamerasList, CameraChangeHandler, CameraEvent, CamerasTuple, \
|
||||
discover_cameras, discover_camera
|
||||
from .util import Log, LogConfig, TraceEnable, RuntimeTypeCheckEnable, EnterContextOnCall, \
|
||||
LeaveContextOnCall, RaiseIfInsideContext, RaiseIfOutsideContext
|
||||
from .error import VimbaCameraError, VimbaInterfaceError, VimbaFeatureError
|
||||
from . import __version__ as VIMBA_PYTHON_VERSION
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Vimba',
|
||||
]
|
||||
|
||||
|
||||
class Vimba:
|
||||
class __Impl:
|
||||
"""This class allows access to the entire Vimba System.
|
||||
Vimba is meant be used in conjunction with the "with" - Statement, upon
|
||||
entering the context, all system features, connected cameras and interfaces are detected
|
||||
and can be used.
|
||||
"""
|
||||
|
||||
@TraceEnable()
|
||||
@LeaveContextOnCall()
|
||||
def __init__(self):
|
||||
"""Do not call directly. Use Vimba.get_instance() instead."""
|
||||
self.__feats: FeaturesTuple = ()
|
||||
|
||||
self.__inters: InterfacesList = ()
|
||||
self.__inters_lock: threading.Lock = threading.Lock()
|
||||
self.__inters_handlers: List[InterfaceChangeHandler] = []
|
||||
self.__inters_handlers_lock: threading.Lock = threading.Lock()
|
||||
|
||||
self.__cams: CamerasList = ()
|
||||
self.__cams_lock: threading.Lock = threading.Lock()
|
||||
self.__cams_handlers: List[CameraChangeHandler] = []
|
||||
self.__cams_handlers_lock: threading.Lock = threading.Lock()
|
||||
|
||||
self.__nw_discover: bool = True
|
||||
self.__context_cnt: int = 0
|
||||
|
||||
@TraceEnable()
|
||||
def __enter__(self):
|
||||
if not self.__context_cnt:
|
||||
self._startup()
|
||||
|
||||
self.__context_cnt += 1
|
||||
return self
|
||||
|
||||
@TraceEnable()
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
self.__context_cnt -= 1
|
||||
|
||||
if not self.__context_cnt:
|
||||
self._shutdown()
|
||||
|
||||
def get_version(self) -> str:
|
||||
""" Returns version string of VimbaPython and underlaying dependencies."""
|
||||
msg = 'VimbaPython: {} (using VimbaC: {}, VimbaImageTransform: {})'
|
||||
return msg.format(VIMBA_PYTHON_VERSION, VIMBA_C_VERSION, VIMBA_IMAGE_TRANSFORM_VERSION)
|
||||
|
||||
@RaiseIfInsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def set_network_discovery(self, enable: bool):
|
||||
"""Enable/Disable network camera discovery.
|
||||
|
||||
Arguments:
|
||||
enable - If 'True' VimbaPython tries to detect cameras connected via Ethernet
|
||||
on entering the 'with' statement. If set to 'False', no network
|
||||
discover occurs.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError if called inside with-statement.
|
||||
"""
|
||||
self.__nw_discover = enable
|
||||
|
||||
@RuntimeTypeCheckEnable()
|
||||
def enable_log(self, config: LogConfig):
|
||||
"""Enable VimbaPython's logging mechanism.
|
||||
|
||||
Arguments:
|
||||
config - Configuration for the logging mechanism.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
Log.get_instance().enable(config)
|
||||
|
||||
def disable_log(self):
|
||||
"""Disable VimbaPython's logging mechanism."""
|
||||
Log.get_instance().disable()
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def read_memory(self, addr: int, max_bytes: int) -> bytes: # coverage: skip
|
||||
"""Read a byte sequence from a given memory address.
|
||||
|
||||
Arguments:
|
||||
addr: Starting address to read from.
|
||||
max_bytes: Maximum number of bytes to read from addr.
|
||||
|
||||
Returns:
|
||||
Read memory contents as bytes.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
ValueError if addr is negative
|
||||
ValueError if max_bytes is negative.
|
||||
ValueError if the memory access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return read_memory(G_VIMBA_C_HANDLE, addr, max_bytes)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def write_memory(self, addr: int, data: bytes): # coverage: skip
|
||||
""" Write a byte sequence to a given memory address.
|
||||
|
||||
Arguments:
|
||||
addr: Address to write the content of 'data' too.
|
||||
data: Byte sequence to write at address 'addr'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
ValueError if addr is negative.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return write_memory(G_VIMBA_C_HANDLE, addr, data)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def read_registers(self, addrs: Tuple[int, ...]) -> Dict[int, int]: # coverage: skip
|
||||
"""Read contents of multiple registers.
|
||||
|
||||
Arguments:
|
||||
addrs: Sequence of addresses that should be read iteratively.
|
||||
|
||||
Return:
|
||||
Dictionary containing a mapping from given address to the read register values.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
ValueError if any address in addrs_values is negative.
|
||||
ValueError if the register access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return read_registers(G_VIMBA_C_HANDLE, addrs)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def write_registers(self, addrs_values: Dict[int, int]): # coverage: skip
|
||||
"""Write data to multiple Registers.
|
||||
|
||||
Arguments:
|
||||
addrs_values: Mapping between Register addresses and the data to write.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
ValueError if any address in addrs is negative.
|
||||
ValueError if the register access was invalid.
|
||||
"""
|
||||
# Note: Coverage is skipped. Function is untestable in a generic way.
|
||||
return write_registers(G_VIMBA_C_HANDLE, addrs_values)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
def get_all_interfaces(self) -> InterfacesTuple:
|
||||
"""Get access to all discovered Interfaces:
|
||||
|
||||
Returns:
|
||||
A set of all currently detected Interfaces.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
"""
|
||||
with self.__inters_lock:
|
||||
return tuple(self.__inters)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_interface_by_id(self, id_: str) -> Interface:
|
||||
"""Lookup Interface with given ID.
|
||||
|
||||
Arguments:
|
||||
id_ - Interface Id to search for.
|
||||
|
||||
Returns:
|
||||
Interface associated with given Id.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
VimbaInterfaceError if interface with id_ can't be found.
|
||||
"""
|
||||
with self.__inters_lock:
|
||||
inter = [inter for inter in self.__inters if id_ == inter.get_id()]
|
||||
|
||||
if not inter:
|
||||
raise VimbaInterfaceError('Interface with ID \'{}\' not found.'.format(id_))
|
||||
|
||||
return inter.pop()
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
def get_all_cameras(self) -> CamerasTuple:
|
||||
"""Get access to all discovered Cameras.
|
||||
|
||||
Returns:
|
||||
A set of all currently detected Cameras.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
"""
|
||||
with self.__cams_lock:
|
||||
return tuple(self.__cams)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_camera_by_id(self, id_: str) -> Camera:
|
||||
"""Lookup Camera with given ID.
|
||||
|
||||
Arguments:
|
||||
id_ - Camera Id to search for. For GigE - Cameras, the IP and MAC-Address
|
||||
can be used to Camera lookup
|
||||
|
||||
Returns:
|
||||
Camera associated with given Id.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
VimbaCameraError if camera with id_ can't be found.
|
||||
"""
|
||||
with self.__cams_lock:
|
||||
# Search for given Camera Id in all currently detected cameras.
|
||||
for cam in self.__cams:
|
||||
if id_ == cam.get_id():
|
||||
return cam
|
||||
|
||||
# If a search by ID fails, the given id_ is almost certain an IP or MAC - Address.
|
||||
# Try to query this Camera.
|
||||
try:
|
||||
cam_info = discover_camera(id_)
|
||||
|
||||
# Since cam_info is newly constructed, search in existing cameras for a Camera
|
||||
for cam in self.__cams:
|
||||
if cam_info.get_id() == cam.get_id():
|
||||
return cam
|
||||
|
||||
except VimbaCameraError:
|
||||
pass
|
||||
|
||||
raise VimbaCameraError('No Camera with Id \'{}\' available.'.format(id_))
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
def get_all_features(self) -> FeaturesTuple:
|
||||
"""Get access to all discovered system features:
|
||||
|
||||
Returns:
|
||||
A set of all currently detected Features.
|
||||
|
||||
Raises:
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
"""
|
||||
return self.__feats
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_affected_by(self, feat: FeatureTypes) -> FeaturesTuple:
|
||||
"""Get all system features affected by a specific system feature.
|
||||
|
||||
Arguments:
|
||||
feat - Feature used find features that are affected by feat.
|
||||
|
||||
Returns:
|
||||
A set of features affected by changes on 'feat'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
VimbaFeatureError if 'feat' is not a system feature.
|
||||
"""
|
||||
return filter_affected_features(self.__feats, feat)
|
||||
|
||||
@TraceEnable()
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_selected_by(self, feat: FeatureTypes) -> FeaturesTuple:
|
||||
"""Get all system features selected by a specific system feature.
|
||||
|
||||
Arguments:
|
||||
feat - Feature used find features that are selected by feat.
|
||||
|
||||
Returns:
|
||||
A set of features selected by 'feat'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
VimbaFeatureError if 'feat' is not a system feature.
|
||||
"""
|
||||
return filter_selected_features(self.__feats, feat)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_by_type(self, feat_type: FeatureTypeTypes) -> FeaturesTuple:
|
||||
"""Get all system features of a specific feature type.
|
||||
|
||||
Valid FeatureTypes are: IntFeature, FloatFeature, StringFeature, BoolFeature,
|
||||
EnumFeature, CommandFeature, RawFeature
|
||||
|
||||
Arguments:
|
||||
feat_type - FeatureType used find features of that type.
|
||||
|
||||
Returns:
|
||||
A set of features of type 'feat_type'.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
"""
|
||||
return filter_features_by_type(self.__feats, feat_type)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_features_by_category(self, category: str) -> FeaturesTuple:
|
||||
"""Get all system features of a specific category.
|
||||
|
||||
Arguments:
|
||||
category - Category that should be used for filtering.
|
||||
|
||||
Returns:
|
||||
A set of features of category 'category'.
|
||||
|
||||
Returns:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
"""
|
||||
return filter_features_by_category(self.__feats, category)
|
||||
|
||||
@RaiseIfOutsideContext()
|
||||
@RuntimeTypeCheckEnable()
|
||||
def get_feature_by_name(self, feat_name: str) -> FeatureTypes:
|
||||
"""Get a system feature by its name.
|
||||
|
||||
Arguments:
|
||||
feat_name - Name used to find a feature.
|
||||
|
||||
Returns:
|
||||
Feature with the associated name.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
RuntimeError then called outside of "with" - statement.
|
||||
VimbaFeatureError if no feature is associated with 'feat_name'.
|
||||
"""
|
||||
feat = filter_features_by_name(self.__feats, feat_name)
|
||||
|
||||
if not feat:
|
||||
raise VimbaFeatureError('Feature \'{}\' not found.'.format(feat_name))
|
||||
|
||||
return feat
|
||||
|
||||
@RuntimeTypeCheckEnable()
|
||||
def register_camera_change_handler(self, handler: CameraChangeHandler):
|
||||
"""Add Callable what is executed on camera connect/disconnect
|
||||
|
||||
Arguments:
|
||||
handler - The change handler that shall be added.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
with self.__cams_handlers_lock:
|
||||
if handler not in self.__cams_handlers:
|
||||
self.__cams_handlers.append(handler)
|
||||
|
||||
def unregister_all_camera_change_handlers(self):
|
||||
"""Remove all currently registered camera change handlers"""
|
||||
with self.__cams_handlers_lock:
|
||||
if self.__cams_handlers:
|
||||
self.__cams_handlers.clear()
|
||||
|
||||
@RuntimeTypeCheckEnable()
|
||||
def unregister_camera_change_handler(self, handler: CameraChangeHandler):
|
||||
"""Remove previously registered camera change handler
|
||||
|
||||
Arguments:
|
||||
handler - The change handler that shall be removed.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
with self.__cams_handlers_lock:
|
||||
if handler in self.__cams_handlers:
|
||||
self.__cams_handlers.remove(handler)
|
||||
|
||||
@RuntimeTypeCheckEnable()
|
||||
def register_interface_change_handler(self, handler: InterfaceChangeHandler):
|
||||
"""Add Callable what is executed on interface connect/disconnect
|
||||
|
||||
Arguments:
|
||||
handler - The change handler that shall be added.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
with self.__inters_handlers_lock:
|
||||
if handler not in self.__inters_handlers:
|
||||
self.__inters_handlers.append(handler)
|
||||
|
||||
def unregister_all_interface_change_handlers(self):
|
||||
"""Remove all currently registered interface change handlers"""
|
||||
with self.__inters_handlers_lock:
|
||||
if self.__inters_handlers:
|
||||
self.__inters_handlers.clear()
|
||||
|
||||
@RuntimeTypeCheckEnable()
|
||||
def unregister_interface_change_handler(self, handler: InterfaceChangeHandler):
|
||||
"""Remove previously registered interface change handler
|
||||
|
||||
Arguments:
|
||||
handler - The change handler that shall be removed.
|
||||
|
||||
Raises:
|
||||
TypeError if parameters do not match their type hint.
|
||||
"""
|
||||
with self.__inters_handlers_lock:
|
||||
if handler in self.__inters_handlers:
|
||||
self.__inters_handlers.remove(handler)
|
||||
|
||||
@TraceEnable()
|
||||
@EnterContextOnCall()
|
||||
def _startup(self):
|
||||
Log.get_instance().info('Starting {}'.format(self.get_version()))
|
||||
|
||||
call_vimba_c('VmbStartup')
|
||||
|
||||
self.__inters = discover_interfaces()
|
||||
self.__cams = discover_cameras(self.__nw_discover)
|
||||
self.__feats = discover_features(G_VIMBA_C_HANDLE)
|
||||
attach_feature_accessors(self, self.__feats)
|
||||
|
||||
feat = self.get_feature_by_name('DiscoveryInterfaceEvent')
|
||||
feat.register_change_handler(self.__inter_cb_wrapper)
|
||||
|
||||
feat = self.get_feature_by_name('DiscoveryCameraEvent')
|
||||
feat.register_change_handler(self.__cam_cb_wrapper)
|
||||
|
||||
@TraceEnable()
|
||||
@LeaveContextOnCall()
|
||||
def _shutdown(self):
|
||||
self.unregister_all_camera_change_handlers()
|
||||
self.unregister_all_interface_change_handlers()
|
||||
|
||||
for feat in self.__feats:
|
||||
feat.unregister_all_change_handlers()
|
||||
|
||||
remove_feature_accessors(self, self.__feats)
|
||||
self.__feats = ()
|
||||
self.__cams_handlers = []
|
||||
self.__cams = ()
|
||||
self.__inters_handlers = []
|
||||
self.__inters = ()
|
||||
|
||||
call_vimba_c('VmbShutdown')
|
||||
|
||||
def __cam_cb_wrapper(self, cam_event: EnumFeature): # coverage: skip
|
||||
# Skip coverage because it can't be measured. This is called from C-Context
|
||||
event = CameraEvent(int(cam_event.get()))
|
||||
cam = None
|
||||
cam_id = self.get_feature_by_name('DiscoveryCameraIdent').get()
|
||||
log = Log.get_instance()
|
||||
|
||||
# New camera found: Add it to camera list
|
||||
if event == CameraEvent.Detected:
|
||||
cam = discover_camera(cam_id)
|
||||
|
||||
with self.__cams_lock:
|
||||
self.__cams.append(cam)
|
||||
|
||||
log.info('Added camera \"{}\" to active cameras'.format(cam_id))
|
||||
|
||||
# Existing camera lost. Remove it from active cameras
|
||||
elif event == CameraEvent.Missing:
|
||||
with self.__cams_lock:
|
||||
cam = [c for c in self.__cams if cam_id == c.get_id()].pop()
|
||||
cam._disconnected = True
|
||||
self.__cams.remove(cam)
|
||||
|
||||
log.info('Removed camera \"{}\" from active cameras'.format(cam_id))
|
||||
|
||||
else:
|
||||
cam = self.get_camera_by_id(cam_id)
|
||||
|
||||
with self.__cams_handlers_lock:
|
||||
for handler in self.__cams_handlers:
|
||||
try:
|
||||
handler(cam, event)
|
||||
|
||||
except Exception as e:
|
||||
msg = 'Caught Exception in handler: '
|
||||
msg += 'Type: {}, '.format(type(e))
|
||||
msg += 'Value: {}, '.format(e)
|
||||
msg += 'raised by: {}'.format(handler)
|
||||
Log.get_instance().error(msg)
|
||||
raise e
|
||||
|
||||
def __inter_cb_wrapper(self, inter_event: EnumFeature): # coverage: skip
|
||||
# Skip coverage because it can't be measured. This is called from C-Context
|
||||
event = InterfaceEvent(int(inter_event.get()))
|
||||
inter = None
|
||||
inter_id = self.get_feature_by_name('DiscoveryInterfaceIdent').get()
|
||||
log = Log.get_instance()
|
||||
|
||||
# New interface found: Add it to interface list
|
||||
if event == InterfaceEvent.Detected:
|
||||
inter = discover_interface(inter_id)
|
||||
|
||||
with self.__inters_lock:
|
||||
self.__inters.append(inter)
|
||||
|
||||
log.info('Added interface \"{}\" to active interfaces'.format(inter_id))
|
||||
|
||||
# Existing interface lost. Remove it from active interfaces
|
||||
elif event == InterfaceEvent.Missing:
|
||||
with self.__inters_lock:
|
||||
inter = [i for i in self.__inters if inter_id == i.get_id()].pop()
|
||||
self.__inters.remove(inter)
|
||||
|
||||
log.info('Removed interface \"{}\" from active interfaces'.format(inter_id))
|
||||
|
||||
else:
|
||||
inter = self.get_interface_by_id(inter_id)
|
||||
|
||||
with self.__inters_handlers_lock:
|
||||
for handler in self.__inters_handlers:
|
||||
try:
|
||||
handler(inter, event)
|
||||
|
||||
except Exception as e:
|
||||
msg = 'Caught Exception in handler: '
|
||||
msg += 'Type: {}, '.format(type(e))
|
||||
msg += 'Value: {}, '.format(e)
|
||||
msg += 'raised by: {}'.format(handler)
|
||||
Log.get_instance().error(msg)
|
||||
raise e
|
||||
|
||||
__instance = __Impl()
|
||||
|
||||
@staticmethod
|
||||
@TraceEnable()
|
||||
def get_instance() -> '__Impl':
|
||||
"""Get VimbaSystem Singleton."""
|
||||
return Vimba.__instance
|
||||
Reference in New Issue
Block a user