pfnc 0.1.0__cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dataspree/pfnc/__about__.py +3 -0
- dataspree/pfnc/__init__.py +122 -0
- dataspree/pfnc/_internal/__init__.py +0 -0
- dataspree/pfnc/_internal/registry.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/_internal/registry.pyi +43 -0
- dataspree/pfnc/_internal/utils.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/_internal/utils.pyi +8 -0
- dataspree/pfnc/decoder_registry.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/decoder_registry.pyi +84 -0
- dataspree/pfnc/exceptions.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/exceptions.pyi +30 -0
- dataspree/pfnc/genicam/__init__.py +1 -0
- dataspree/pfnc/genicam/components.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/genicam/components.pyi +1077 -0
- dataspree/pfnc/genicam/data_types.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/genicam/data_types.pyi +115 -0
- dataspree/pfnc/genicam/interface_specifics.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/genicam/interface_specifics.pyi +102 -0
- dataspree/pfnc/genicam/number_of_bits.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/genicam/number_of_bits.pyi +53 -0
- dataspree/pfnc/genicam/packing_types.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/genicam/packing_types.pyi +81 -0
- dataspree/pfnc/genicam/pixel_format.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/genicam/pixel_format.pyi +95 -0
- dataspree/pfnc/pixel_format.cpython-312-x86_64-linux-gnu.so +0 -0
- dataspree/pfnc/pixel_format.pyi +40 -0
- dataspree/pfnc/py.typed +0 -0
- pfnc-0.1.0.dist-info/METADATA +134 -0
- pfnc-0.1.0.dist-info/RECORD +31 -0
- pfnc-0.1.0.dist-info/WHEEL +6 -0
- pfnc-0.1.0.dist-info/licenses/LICENSE.txt +21 -0
|
Binary file
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from .._internal.registry import MappingSnapshot as MappingSnapshot, Registry as Registry
|
|
2
|
+
from .._internal.utils import all_implementations as all_implementations
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
from abc import ABCMeta, abstractmethod
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import TypeGuard
|
|
7
|
+
|
|
8
|
+
logger: Incomplete
|
|
9
|
+
|
|
10
|
+
class DefaultDataType(Enum):
|
|
11
|
+
"""Enumeration for default data types."""
|
|
12
|
+
UNSIGNED = ''
|
|
13
|
+
SIGNED = 's'
|
|
14
|
+
FLOAT = 'f'
|
|
15
|
+
DataType = DefaultDataType | str
|
|
16
|
+
|
|
17
|
+
class DataTypeRegistry(Registry[str, DataType]):
|
|
18
|
+
"""Registry for data types with immutable defaults."""
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
"""Initialize the registry and register default data types."""
|
|
21
|
+
def register(self, name: str, value: DataType | None = None) -> None:
|
|
22
|
+
"""Register a custom single-letter data type."""
|
|
23
|
+
def restore(self, snap: MappingSnapshot[str, DataType]) -> None:
|
|
24
|
+
"""Restore a snapshot."""
|
|
25
|
+
@classmethod
|
|
26
|
+
def default_snapshot(cls) -> MappingSnapshot[str, DataType]:
|
|
27
|
+
"""Return a snapshot that is empty except for the default data types."""
|
|
28
|
+
|
|
29
|
+
DATA_TYPE_REGISTRY: DataTypeRegistry
|
|
30
|
+
|
|
31
|
+
def is_data_type(potential_data_type: object) -> TypeGuard[DataType]:
|
|
32
|
+
"""Checks if the given object is a valid data type.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
potential_data_type (Any): The object to check.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
bool: True if the object is a valid data type, False otherwise.
|
|
39
|
+
"""
|
|
40
|
+
def datatype_name(data_type: DataType, multiple_designators: bool = False) -> str:
|
|
41
|
+
"""Returns the string representation of a data type.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
data_type (DataType): The data type.
|
|
45
|
+
multiple_designators (bool): Whether to include the 'u' designator for unsigned.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
str: The string representation of the data type.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
class DataTypes(metaclass=ABCMeta):
|
|
52
|
+
"""Abstract base class for data type designations."""
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def designation(self) -> str:
|
|
55
|
+
"""Returns the string representation of the data type."""
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def __len__(self) -> int:
|
|
58
|
+
"""Returns the number of elements in the data type."""
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def __getitem__(self, item: int) -> DataType:
|
|
61
|
+
"""Returns the element at the specified index."""
|
|
62
|
+
@staticmethod
|
|
63
|
+
def create(full_designation: str, number_of_channels: int) -> list[tuple['DataTypes', str]]:
|
|
64
|
+
"""Creates instances of `DataTypes` based on a designation string.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
full_designation (str): The full designation string.
|
|
68
|
+
number_of_channels (int): The number of channels.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
List[Tuple[DataTypes, str]]: A list of parsed `DataTypes` instances and remaining designations.
|
|
72
|
+
"""
|
|
73
|
+
@staticmethod
|
|
74
|
+
def from_designation(full_designation: str, number_of_channels: int) -> list[tuple['DataTypes', str]]:
|
|
75
|
+
"""Parses a designation string into `DataTypes` instances.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
full_designation (str): The full designation string.
|
|
79
|
+
number_of_channels (int): The number of channels.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
List[Tuple[DataTypes, str]]: A list of parsed `DataTypes` instances and remaining designations.
|
|
83
|
+
"""
|
|
84
|
+
def __eq__(self, other: object) -> bool:
|
|
85
|
+
"""Returns `True` if `self` and `other` are equivalent."""
|
|
86
|
+
|
|
87
|
+
class CompoundDataTypes(DataTypes):
|
|
88
|
+
"""Represents a compound designation containing multiple data types."""
|
|
89
|
+
data_types: list[DataType]
|
|
90
|
+
def __init__(self, data_types: list[DataType]) -> None:
|
|
91
|
+
"""Initializes a `CompoundDataTypes` instance.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
data_types (List[DataType]): A list of data types in the compound designation.
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
PixelFormatValueReject: If `data_types` is invalid.
|
|
98
|
+
"""
|
|
99
|
+
def designation(self) -> str:
|
|
100
|
+
"""Returns the designation string for the compound data types."""
|
|
101
|
+
def __len__(self) -> int:
|
|
102
|
+
"""Returns the number of data types in the compound."""
|
|
103
|
+
def __getitem__(self, item: int) -> DataType:
|
|
104
|
+
"""Returns the data type at the specified index."""
|
|
105
|
+
@staticmethod
|
|
106
|
+
def from_designation(full_designation: str, number_of_channels: int) -> list[tuple['DataTypes', str]]:
|
|
107
|
+
"""Parses a compound data type designation.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
full_designation (str): The full designation string.
|
|
111
|
+
number_of_channels (int): The number of channels.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
List[Tuple[DataTypes, str]]: A list of parsed `CompoundDataTypes` and remaining designations.
|
|
115
|
+
"""
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
from .._internal.utils import all_implementations as all_implementations
|
|
2
|
+
from _typeshed import Incomplete
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from dataspree.pfnc.genicam.components import Components as Components
|
|
5
|
+
from dataspree.pfnc.genicam.number_of_bits import Size as Size
|
|
6
|
+
from typing_extensions import Self
|
|
7
|
+
|
|
8
|
+
logger: Incomplete
|
|
9
|
+
|
|
10
|
+
class InterfaceSpecific(metaclass=ABCMeta):
|
|
11
|
+
"""Abstract base class for interface-specific pixel format designations."""
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def designation(self) -> str:
|
|
14
|
+
"""Returns the designation of the interface-specific format."""
|
|
15
|
+
@staticmethod
|
|
16
|
+
def create(full_designation: str, components: Components, sizes: Size) -> list[tuple['InterfaceSpecific', str]]:
|
|
17
|
+
"""Creates instances of `InterfaceSpecific` based on the designation.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
full_designation (str): The full designation string.
|
|
21
|
+
components (Components): The pixel format components.
|
|
22
|
+
sizes (Size): The sizes of the components.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
List[Tuple[InterfaceSpecific, str]]: A list of tuples with `InterfaceSpecific` instances and remaining
|
|
26
|
+
designations.
|
|
27
|
+
"""
|
|
28
|
+
@classmethod
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def from_designation(cls, full_designation: str, components: Components, sizes: Size) -> list[tuple[Self, str]]:
|
|
31
|
+
"""Parses the designation into specific interface format instances.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
full_designation (str): The full designation string.
|
|
35
|
+
components (Components): The pixel format components.
|
|
36
|
+
sizes (Size): The sizes of the components.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
List[Tuple[InterfaceSpecific, str]]: A list of tuples with parsed instances and remaining designations.
|
|
40
|
+
"""
|
|
41
|
+
def __eq__(self, other: object) -> bool:
|
|
42
|
+
"""Checks equality with another object."""
|
|
43
|
+
|
|
44
|
+
class Planar(InterfaceSpecific):
|
|
45
|
+
"""Represents the planar interface-specific format."""
|
|
46
|
+
def designation(self) -> str:
|
|
47
|
+
"""Returns the planar designation."""
|
|
48
|
+
@classmethod
|
|
49
|
+
def from_designation(cls, full_designation: str, components: Components, sizes: Size) -> list[tuple[Self, str]]:
|
|
50
|
+
"""Parses planar-specific designations.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
full_designation (str): The full designation string.
|
|
54
|
+
components (Components): The pixel format components.
|
|
55
|
+
sizes (Size): The sizes of the components.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
List[Tuple[InterfaceSpecific, str]]: A list with a `Planar` instance if matched.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
class SemiPlanar(InterfaceSpecific):
|
|
62
|
+
"""Represents the semi-planar interface-specific format."""
|
|
63
|
+
def designation(self) -> str:
|
|
64
|
+
"""Returns the semi-planar designation."""
|
|
65
|
+
@classmethod
|
|
66
|
+
def from_designation(cls, full_designation: str, components: Components, sizes: Size) -> list[tuple[Self, str]]:
|
|
67
|
+
"""Parses semi-planar-specific designations.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
full_designation (str): The full designation string.
|
|
71
|
+
components (Components): The pixel format components.
|
|
72
|
+
sizes (Size): The sizes of the components.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
List[Tuple[InterfaceSpecific, str]]: A list with a `SemiPlanar` instance if matched.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
class ComponentsSequencing(InterfaceSpecific):
|
|
79
|
+
"""Represents an interface-specific format based on component sequencing."""
|
|
80
|
+
components: tuple[str, ...]
|
|
81
|
+
def __init__(self, components: tuple[str, ...]) -> None:
|
|
82
|
+
"""Initializes a `ComponentsSequencing` instance.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
components (Tuple[str, ...]): A tuple of component names.
|
|
86
|
+
"""
|
|
87
|
+
def designation(self) -> str:
|
|
88
|
+
"""Returns the component sequencing designation."""
|
|
89
|
+
@classmethod
|
|
90
|
+
def from_designation(cls, full_designation: str, components: Components, sizes: Size) -> list[tuple[Self, str]]:
|
|
91
|
+
"""Parses component sequencing-specific designations.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
full_designation (str): The full designation string.
|
|
95
|
+
components (Components): The pixel format components.
|
|
96
|
+
sizes (Size): The sizes of the components.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
List[Tuple[InterfaceSpecific, str]]: A list of parsed instances and remaining designations.
|
|
100
|
+
"""
|
|
101
|
+
def __eq__(self, other: object) -> bool:
|
|
102
|
+
"""Checks equality with another object."""
|
|
Binary file
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
@dataclass
|
|
4
|
+
class Size:
|
|
5
|
+
"""Represents the size of a pixel format.
|
|
6
|
+
|
|
7
|
+
Attributes:
|
|
8
|
+
sizes (list[int]): A list of sizes for each channel.
|
|
9
|
+
"""
|
|
10
|
+
sizes: list[int]
|
|
11
|
+
def __post_init__(self) -> None:
|
|
12
|
+
"""Check that the sizes are all coherent."""
|
|
13
|
+
def __len__(self) -> int:
|
|
14
|
+
"""Returns the number of sizes.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
int: The number of sizes.
|
|
18
|
+
"""
|
|
19
|
+
def __getitem__(self, item: int) -> int:
|
|
20
|
+
"""Gets the size at the specified index.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
item (int): The index of the size to retrieve.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
int: The size at the specified index.
|
|
27
|
+
"""
|
|
28
|
+
def __eq__(self, other: object) -> bool:
|
|
29
|
+
"""Checks if two Size instances are equal.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
other: The other Size instance to compare.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
bool: True if the instances are equal, False otherwise.
|
|
36
|
+
"""
|
|
37
|
+
def designation(self) -> str:
|
|
38
|
+
"""Computes the designation string for the Size instance.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
str: The designation string.
|
|
42
|
+
"""
|
|
43
|
+
@staticmethod
|
|
44
|
+
def from_designation(designation: str, number_of_channels: int) -> tuple['Size', str] | None:
|
|
45
|
+
"""Creates a Size instance from a designation string.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
designation (str): The designation string.
|
|
49
|
+
number_of_channels (int): The number of channels.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Optional[tuple[Size, str]]: A tuple containing the Size instance and the remaining substring.
|
|
53
|
+
"""
|
|
Binary file
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from .._internal.registry import MappingSnapshot as MappingSnapshot, Registry as Registry
|
|
2
|
+
from .._internal.utils import join_designators as join_designators
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
logger: Incomplete
|
|
7
|
+
|
|
8
|
+
class PaddingType(Enum):
|
|
9
|
+
"""Enumeration of padding types for pixel formats."""
|
|
10
|
+
PACKED = 'p'
|
|
11
|
+
GROUPED = 'g'
|
|
12
|
+
UNPACKED = ''
|
|
13
|
+
|
|
14
|
+
class PaddingTypeNameRegistry(Registry[str, PaddingType]):
|
|
15
|
+
"""Registry for padding type names with immutable defaults."""
|
|
16
|
+
def __init__(self) -> None:
|
|
17
|
+
"""Initialize the registry and register default padding type names."""
|
|
18
|
+
def register(self, name: str, value: PaddingType) -> None:
|
|
19
|
+
"""Register a padding type name, rejecting changes to defaults."""
|
|
20
|
+
def restore(self, snap: MappingSnapshot[str, PaddingType]) -> None:
|
|
21
|
+
"""Restore a snapshot, ensuring defaults are present and unchanged.
|
|
22
|
+
|
|
23
|
+
Raises:
|
|
24
|
+
ValueError: If the snapshot is missing defaults or changes their values.
|
|
25
|
+
"""
|
|
26
|
+
@classmethod
|
|
27
|
+
def default_snapshot(cls) -> MappingSnapshot[str, PaddingType]:
|
|
28
|
+
"""Return a snapshot that contains only the default padding type names."""
|
|
29
|
+
|
|
30
|
+
PADDING_TYPE_NAME_REGISTRY: PaddingTypeNameRegistry
|
|
31
|
+
|
|
32
|
+
class Packing:
|
|
33
|
+
"""Represents the packing configuration for pixel formats.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
padding_type_name (str): The name of the padding type.
|
|
37
|
+
lsb (bool): Indicates if the least significant bit is used.
|
|
38
|
+
alignment (Optional[int]): The alignment value.
|
|
39
|
+
cluster_marker (int): The cluster marker value.
|
|
40
|
+
"""
|
|
41
|
+
padding_type_name: str
|
|
42
|
+
lsb: bool
|
|
43
|
+
alignment: int | None
|
|
44
|
+
cluster_marker: int
|
|
45
|
+
def __init__(self, padding_type: PaddingType | str | None = None, lsb: bool = True, alignment: int | None = None, cluster_marker: int = 0) -> None:
|
|
46
|
+
"""Initializes a Packing instance.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
padding_type (Optional[Union[PaddingType, str]]): The type of padding. Defaults to None.
|
|
50
|
+
lsb (bool): Indicates if the least significant bit is used. Defaults to True.
|
|
51
|
+
alignment (Optional[int]): The alignment value. Defaults to None.
|
|
52
|
+
cluster_marker (int): The cluster marker value. Defaults to 0.
|
|
53
|
+
"""
|
|
54
|
+
@property
|
|
55
|
+
def padding_type(self) -> PaddingType:
|
|
56
|
+
"""Return the padding type."""
|
|
57
|
+
def __eq__(self, other: object) -> bool:
|
|
58
|
+
"""Checks if two Packing instances are equal.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
other: The other Packing instance to compare.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
bool: True if the instances are equal, False otherwise.
|
|
65
|
+
"""
|
|
66
|
+
def designation(self) -> str:
|
|
67
|
+
"""Computes the designation string for the Packing instance.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
str: The designation string.
|
|
71
|
+
"""
|
|
72
|
+
@staticmethod
|
|
73
|
+
def from_designation(full_designation: str) -> list[tuple['Packing', str]]:
|
|
74
|
+
"""Creates a list of possible Packing instances from a designation string.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
full_designation (str): The full designation string.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
list[tuple[Packing, str]]: A list of possible Packing instances and remaining substrings.
|
|
81
|
+
"""
|
|
Binary file
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .._internal.utils import join_designators as join_designators
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
from dataspree.pfnc.decoder_registry import PixelFormatDecoder
|
|
5
|
+
from dataspree.pfnc.genicam.components import Components, SizedColorSpaceStandard
|
|
6
|
+
from dataspree.pfnc.genicam.data_types import DataType as DataType, DataTypes
|
|
7
|
+
from dataspree.pfnc.genicam.interface_specifics import InterfaceSpecific
|
|
8
|
+
from dataspree.pfnc.genicam.number_of_bits import Size
|
|
9
|
+
from dataspree.pfnc.genicam.packing_types import Packing
|
|
10
|
+
from dataspree.pfnc.pixel_format import PixelFormat
|
|
11
|
+
from typing import Any, TypeGuard, TypeVar
|
|
12
|
+
|
|
13
|
+
logger: Incomplete
|
|
14
|
+
PF = TypeVar('PF', bound=PixelFormat)
|
|
15
|
+
|
|
16
|
+
class GenicamPixelFormat(PixelFormat):
|
|
17
|
+
'''Representation of a pixel format that complies with the genicam standard.
|
|
18
|
+
|
|
19
|
+
Detailed information about pixel formats can be found in the GenICam Pixel Format Naming Convention 2.1.
|
|
20
|
+
https://www.emva.org/wp-content/uploads/GenICam_PFNC_2_1.pdf.
|
|
21
|
+
|
|
22
|
+
The naming convention subdivides as it follows:
|
|
23
|
+
1. Components and Location (e.g., "RGB" / "Mono")
|
|
24
|
+
2. number of bits per component (e.g., "8")
|
|
25
|
+
3. [Optional] data type ("u" or "" for unsigned, "s" for signed, "f" for floating point)
|
|
26
|
+
4. [Optional] packing: @see Packing
|
|
27
|
+
5. [Optional] interface-specific
|
|
28
|
+
|
|
29
|
+
Consecutive fields must be separated by an underscore, iff (:= if, and only if) a pixel name
|
|
30
|
+
requires 2 numbers in its designation as part of consecutive fields.
|
|
31
|
+
Example: YCbCr709_422_8 for 8-bit per component Y’CbCr 4:2:2 using ITU-R BT.709.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
component (Components): The components of the pixel format.
|
|
36
|
+
size (Size): The size of the pixel format.
|
|
37
|
+
data_type (DataTypes): The data type of the pixel format.
|
|
38
|
+
packing (Packing): The packing type of the pixel format.
|
|
39
|
+
interface_specific (Optional[InterfaceSpecific]): The interface-specific part of the pixel format.
|
|
40
|
+
sized_color_space_standard (Optional[SizedColorSpaceStandard]): The sized color space standard.
|
|
41
|
+
'''
|
|
42
|
+
component: Components
|
|
43
|
+
storage_units: int
|
|
44
|
+
size: Size
|
|
45
|
+
sized_color_space_standard: SizedColorSpaceStandard | None
|
|
46
|
+
data_type: DataTypes
|
|
47
|
+
packing: Packing
|
|
48
|
+
interface_specific: InterfaceSpecific | None
|
|
49
|
+
def __init__(self, component: Components, size: Size | int | list[int], data_type: DataTypes | list[DataType] | DataType | None = None, packing: Packing | None = None, interface_specific: InterfaceSpecific | None = None, sized_color_space_standard: SizedColorSpaceStandard | None = None, storage_units: int | None = None) -> None:
|
|
50
|
+
"""Initializes a GenicamPixelFormat instance.
|
|
51
|
+
|
|
52
|
+
storage_units models how many storage elements per pixel the size/data_type vectors describe.
|
|
53
|
+
If omitted, it defaults to the number of logical channels (len(component)).
|
|
54
|
+
"""
|
|
55
|
+
def designation(self) -> str:
|
|
56
|
+
"""Compute designation."""
|
|
57
|
+
def __setattr__(self, key: str, value: Any) -> None:
|
|
58
|
+
"""Sets an attribute and clears the cached designation if necessary.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
key (str): The attribute name.
|
|
62
|
+
value: The attribute value.
|
|
63
|
+
"""
|
|
64
|
+
@classmethod
|
|
65
|
+
def from_designation(cls, full_designation: str) -> list[GenicamPixelFormat]:
|
|
66
|
+
"""Return list of compatible genicam pixel formats with the full designation."""
|
|
67
|
+
def __eq__(self, other: object) -> bool:
|
|
68
|
+
"""Check if components are equal."""
|
|
69
|
+
def numpy_dtype(self) -> np.dtype[Any]:
|
|
70
|
+
"""Return the numpy dtype for the unpacked storage representation."""
|
|
71
|
+
|
|
72
|
+
class UnpackedInterleavedStorageDecoder(PixelFormatDecoder):
|
|
73
|
+
"""Decode unpacked, interleaved storage layouts using the current GenicamPixelFormat logic."""
|
|
74
|
+
def __init__(self) -> None:
|
|
75
|
+
"""Initialize."""
|
|
76
|
+
def is_applicable(self, pixel_format: PixelFormat) -> TypeGuard[GenicamPixelFormat]:
|
|
77
|
+
"""Return True for unpacked interleaved layouts that the model says are supported."""
|
|
78
|
+
def decode(self, pixel_format: PixelFormat, buffer: bytes, *, width: int, height: int, stride: int, copy: bool = False) -> np.ndarray[Any, Any]:
|
|
79
|
+
"""Decode unpacked interleaved buffers into numpy arrays.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
pixel_format: Parsed GenICam pixel format instance.
|
|
83
|
+
buffer: Raw frame bytes (one image).
|
|
84
|
+
width: Image width in pixels.
|
|
85
|
+
height: Image height in pixels.
|
|
86
|
+
stride: Bytes per line (can be > width * bytes_per_pixel).
|
|
87
|
+
copy: If True, return a contiguous copy without line padding.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
np.ndarray: Array view or copy of shape (height, width) or (height, width, storage_units).
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If buffer/stride/format are inconsistent.
|
|
94
|
+
NotImplementedError: If the storage layout is not supported by this decoder.
|
|
95
|
+
"""
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from ._internal.utils import all_implementations as all_implementations
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
from abc import ABCMeta, abstractmethod
|
|
5
|
+
from typing import Any
|
|
6
|
+
from typing_extensions import Self
|
|
7
|
+
|
|
8
|
+
logger: Incomplete
|
|
9
|
+
|
|
10
|
+
class PixelFormat(metaclass=ABCMeta):
|
|
11
|
+
"""Abstraction for arbitrary pixel formats."""
|
|
12
|
+
@classmethod
|
|
13
|
+
def create(cls, full_designation: str) -> list[Self]:
|
|
14
|
+
"""Return all existing pixel format that accord with the designation.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
full_designation (str): the unique designation of the pixel format.
|
|
18
|
+
"""
|
|
19
|
+
@classmethod
|
|
20
|
+
def from_name(cls, full_designation: str) -> Self:
|
|
21
|
+
"""Return existing pixel format with the designation.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
full_designation (str): the unique designation of the pixel format.
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
DriverFeatureImplementationError if no corresponding pixel format was found / the
|
|
28
|
+
designation is not unique.
|
|
29
|
+
"""
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def designation(self) -> str:
|
|
32
|
+
"""Compute unique string representation (designation)."""
|
|
33
|
+
@classmethod
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def from_designation(cls, full_designation: str) -> list[Self]:
|
|
36
|
+
"""Return list of compatible genicam pixel formats with the full designation."""
|
|
37
|
+
def decode(self, buffer: bytes, *, width: int, height: int, stride: int, copy: bool = False) -> np.ndarray[Any, Any]:
|
|
38
|
+
"""Decode numpy image from buffer."""
|
|
39
|
+
|
|
40
|
+
DEFAULT_DECODER_REGISTRY: Incomplete
|
dataspree/pfnc/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pfnc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Parse and model GenICam PFNC pixel format designations and decode image buffers via extensible decoders.
|
|
5
|
+
Project-URL: Homepage, https://www.data-spree.com/
|
|
6
|
+
Project-URL: Documentation, https://github.com/dataspree/pfnc.git
|
|
7
|
+
Project-URL: Repository, https://github.com/dataspree/pfnc.git
|
|
8
|
+
Author-email: Data Spree GmbH <info@data-spree.com>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Data Spree GmbH
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE.txt
|
|
31
|
+
Keywords: binary-format,buffer-decoding,camera,dataspree,genicam,gig-e-vision,image-decoding,industrial-camera,machine-vision,numpy,parsing,pfnc,pixel-format
|
|
32
|
+
Requires-Python: >=3.10
|
|
33
|
+
Requires-Dist: numpy<3,>=1.24
|
|
34
|
+
Requires-Dist: typing-extensions>=4
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Data Spree PFNC Pixel Format
|
|
38
|
+
|
|
39
|
+
Parse and model GenICam PFNC pixel format designations and decode image buffers via extensible decoders.
|
|
40
|
+
We follow semantic versioning; breaking changes only occur in major versions.
|
|
41
|
+
Every public symbol defined under `pfnc.*` is stable.
|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
[](https://pdm.fming.dev)
|
|
45
|
+
[](https://github.com/pre-commit/pre-commit)
|
|
46
|
+
|
|
47
|
+
## Introduction
|
|
48
|
+
|
|
49
|
+
This library provides a structured representation of GenICam PFNC pixel format designations and a
|
|
50
|
+
pluggable system for decoding image buffers into numpy arrays.
|
|
51
|
+
|
|
52
|
+
It is intended for industrial camera and machine vision use cases where pixel formats are specified
|
|
53
|
+
using PFNC strings (e.g. `RGB8`, `Mono12Packed`, `BayerRG10`) and need to be parsed, inspected, or decoded
|
|
54
|
+
outside of a vendor-specific SDK.
|
|
55
|
+
|
|
56
|
+
The focus of this project is:
|
|
57
|
+
- correct parsing of PFNC designations
|
|
58
|
+
- explicit modeling of pixel format properties
|
|
59
|
+
- extensibility via registries (decoders, data types, components, packing, interface specifics)
|
|
60
|
+
|
|
61
|
+
This is not a general-purpose image processing library.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Getting Started
|
|
65
|
+
|
|
66
|
+
### Installation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install pfnc
|
|
70
|
+
```
|
|
71
|
+
or, when using pdm:
|
|
72
|
+
```
|
|
73
|
+
pdm add pfnc
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Basic Usage
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from dataspree.pfnc import PixelFormat
|
|
81
|
+
|
|
82
|
+
pf = PixelFormat.from_designation("RGB8")
|
|
83
|
+
|
|
84
|
+
image = pf.decode(
|
|
85
|
+
buffer,
|
|
86
|
+
width=256,
|
|
87
|
+
height=256,
|
|
88
|
+
copy=False,
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Extending the library
|
|
93
|
+
|
|
94
|
+
The library is designed to be extensible. You can register custom decoders or extend parsing behavior
|
|
95
|
+
for additional PFNC variants.
|
|
96
|
+
|
|
97
|
+
#### Registering a custom decoder
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from dataspree.pfnc import register_decoder, PixelFormatDecoder
|
|
101
|
+
|
|
102
|
+
class MyDecoder(PixelFormatDecoder):
|
|
103
|
+
priority = 10
|
|
104
|
+
|
|
105
|
+
def supports(self, pixel_format) -> bool:
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def decode(self, data, width, height, *, copy=False):
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
register_decoder(MyDecoder)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
#### Advanced extensions
|
|
116
|
+
|
|
117
|
+
Advanced users may extend:
|
|
118
|
+
|
|
119
|
+
- data types
|
|
120
|
+
- components
|
|
121
|
+
- packing rules
|
|
122
|
+
- interface specifics
|
|
123
|
+
|
|
124
|
+
These extension points are intentionally exposed.
|
|
125
|
+
|
|
126
|
+
## Scope and limitations
|
|
127
|
+
|
|
128
|
+
Parsing support covers common PFNC designations.
|
|
129
|
+
|
|
130
|
+
Decoding support depends on available decoders.
|
|
131
|
+
|
|
132
|
+
Not all packed or planar formats may be decodable out of the box.
|
|
133
|
+
|
|
134
|
+
See the documentation for details on supported formats.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
dataspree/pfnc/__about__.py,sha256=QMhOwNxON07egeyLGb5oy7jITHWH4oCZ9fi9gxX9iRA,47
|
|
2
|
+
dataspree/pfnc/__init__.py,sha256=qutwoTS63yEQIJDGE8D1J_vl_1NsBhY4r3hP7bTJuz8,3231
|
|
3
|
+
dataspree/pfnc/decoder_registry.cpython-312-x86_64-linux-gnu.so,sha256=uyjLYeUD1PuBQTj_o_yuMVRt_Qf6rgBHYoSk0vUz7xs,800224
|
|
4
|
+
dataspree/pfnc/decoder_registry.pyi,sha256=euwSAQE1XOs1pa3heiA9UQzaS9C43Wc4pEPInfIBXxs,2941
|
|
5
|
+
dataspree/pfnc/exceptions.cpython-312-x86_64-linux-gnu.so,sha256=EMrnKBN2SNkoeFCUlV68Vn9bKz7IbQ-J0OJWferOW7Y,152048
|
|
6
|
+
dataspree/pfnc/exceptions.pyi,sha256=xo7I0D3rvE6kCm4joktO9T3SHQXTQzxFcZmTimzMQn8,1590
|
|
7
|
+
dataspree/pfnc/pixel_format.cpython-312-x86_64-linux-gnu.so,sha256=ZHnIjQoaMoXJeFkyfkRYQrIOvRVOZWUSW3wPewPXUho,623008
|
|
8
|
+
dataspree/pfnc/pixel_format.pyi,sha256=W_VV4brua0eXogkjVF-RQw5DEDLUJi8k-EPVCPdyVfw,1536
|
|
9
|
+
dataspree/pfnc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
dataspree/pfnc/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
dataspree/pfnc/_internal/registry.cpython-312-x86_64-linux-gnu.so,sha256=R6-pUiUp2sC0Qi1RcLvF5nA1b5SHakXQvrZJ34KxVdk,625544
|
|
12
|
+
dataspree/pfnc/_internal/registry.pyi,sha256=xRbKZTmYj2cLWbJJqMUUmEW23T3AYxQIVbrbfL5__78,1340
|
|
13
|
+
dataspree/pfnc/_internal/utils.cpython-312-x86_64-linux-gnu.so,sha256=lDGExZSxdUANQr20l3bzhJCCX7UyTdv7ijci7fe-0gY,435368
|
|
14
|
+
dataspree/pfnc/_internal/utils.pyi,sha256=0r1OUqzRZeYOvBHK06OIDRTZ-k3fgs-zregPoJz_fZQ,319
|
|
15
|
+
dataspree/pfnc/genicam/__init__.py,sha256=A_weat-t9EL9vPZsi1zvwvZXrJiRaZNNGu5auFhdfHc,22
|
|
16
|
+
dataspree/pfnc/genicam/components.cpython-312-x86_64-linux-gnu.so,sha256=GPeZOtKs_XXeTHFsYvj1l481x5cYzfsd4hiB1_-QluU,5179280
|
|
17
|
+
dataspree/pfnc/genicam/components.pyi,sha256=i8au1yfrWHphcsX2T8Jw3Gtp6f8_4EZUHVw7Ieg-JNY,39636
|
|
18
|
+
dataspree/pfnc/genicam/data_types.cpython-312-x86_64-linux-gnu.so,sha256=EEu93BfUrEU5HGVMy0jWD4ZQzfz33bknPZoujJd8GHM,1397088
|
|
19
|
+
dataspree/pfnc/genicam/data_types.pyi,sha256=32ucyWm3Ws4tyH1kfWRjWvNNWuJXNkJw_CnwxNYZL6c,4501
|
|
20
|
+
dataspree/pfnc/genicam/interface_specifics.cpython-312-x86_64-linux-gnu.so,sha256=Vreubt5DweV5WDzwe4pONEHdqwF9_u6XMT36CvBLyqM,1100592
|
|
21
|
+
dataspree/pfnc/genicam/interface_specifics.pyi,sha256=J1l5sHxQC3Si1UdknQeVJ-naiITbIpGX1LhfGrt6aCA,4359
|
|
22
|
+
dataspree/pfnc/genicam/number_of_bits.cpython-312-x86_64-linux-gnu.so,sha256=t9UzHCRpeCCGdEdOfaGKxtNZwHGyCYzWuh2kOg4-N8A,892464
|
|
23
|
+
dataspree/pfnc/genicam/number_of_bits.pyi,sha256=otqgOXw9OueBvMvYubSmuCeNS_pJZOEDTJMT8_9NaWA,1568
|
|
24
|
+
dataspree/pfnc/genicam/packing_types.cpython-312-x86_64-linux-gnu.so,sha256=KaA6MM-hnQcxKLJW9pV7Uhaf7A6Pil0MRt6Mwo5lZIQ,1366336
|
|
25
|
+
dataspree/pfnc/genicam/packing_types.pyi,sha256=Wl4P2-8gtHlPcqZXa2PJVvsjcbxCXxXg5dsXZf6In3I,3165
|
|
26
|
+
dataspree/pfnc/genicam/pixel_format.cpython-312-x86_64-linux-gnu.so,sha256=4fywFVw6Q_2Nx_ei2ZNNEHfqWTkrA0vD7fON21e9cSQ,1692232
|
|
27
|
+
dataspree/pfnc/genicam/pixel_format.pyi,sha256=16Lb8OQCX0LM8EEgHvzqGh3-pr1ECE_IOPlZkYkmoGs,4851
|
|
28
|
+
pfnc-0.1.0.dist-info/METADATA,sha256=tqDlX3c7uNBUPd3SEC86aSZsvMrrQKa1_sS9e-fcXdU,4450
|
|
29
|
+
pfnc-0.1.0.dist-info/WHEEL,sha256=Dy6cbUsQpxl9TJBYfK0eu2S3Tei4GG2zO8xm1VGC13M,148
|
|
30
|
+
pfnc-0.1.0.dist-info/RECORD,,
|
|
31
|
+
pfnc-0.1.0.dist-info/licenses/LICENSE.txt,sha256=zO7pALKLzkW8wkrMHQ1kJI6Bz9kEH5bxt4XB9i-YcsA,1072
|