pfnc 0.1.0__cp311-cp311-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.
Files changed (31) hide show
  1. dataspree/pfnc/__about__.py +3 -0
  2. dataspree/pfnc/__init__.py +122 -0
  3. dataspree/pfnc/_internal/__init__.py +0 -0
  4. dataspree/pfnc/_internal/registry.cpython-311-x86_64-linux-gnu.so +0 -0
  5. dataspree/pfnc/_internal/registry.pyi +43 -0
  6. dataspree/pfnc/_internal/utils.cpython-311-x86_64-linux-gnu.so +0 -0
  7. dataspree/pfnc/_internal/utils.pyi +8 -0
  8. dataspree/pfnc/decoder_registry.cpython-311-x86_64-linux-gnu.so +0 -0
  9. dataspree/pfnc/decoder_registry.pyi +84 -0
  10. dataspree/pfnc/exceptions.cpython-311-x86_64-linux-gnu.so +0 -0
  11. dataspree/pfnc/exceptions.pyi +30 -0
  12. dataspree/pfnc/genicam/__init__.py +1 -0
  13. dataspree/pfnc/genicam/components.cpython-311-x86_64-linux-gnu.so +0 -0
  14. dataspree/pfnc/genicam/components.pyi +1077 -0
  15. dataspree/pfnc/genicam/data_types.cpython-311-x86_64-linux-gnu.so +0 -0
  16. dataspree/pfnc/genicam/data_types.pyi +115 -0
  17. dataspree/pfnc/genicam/interface_specifics.cpython-311-x86_64-linux-gnu.so +0 -0
  18. dataspree/pfnc/genicam/interface_specifics.pyi +102 -0
  19. dataspree/pfnc/genicam/number_of_bits.cpython-311-x86_64-linux-gnu.so +0 -0
  20. dataspree/pfnc/genicam/number_of_bits.pyi +53 -0
  21. dataspree/pfnc/genicam/packing_types.cpython-311-x86_64-linux-gnu.so +0 -0
  22. dataspree/pfnc/genicam/packing_types.pyi +81 -0
  23. dataspree/pfnc/genicam/pixel_format.cpython-311-x86_64-linux-gnu.so +0 -0
  24. dataspree/pfnc/genicam/pixel_format.pyi +95 -0
  25. dataspree/pfnc/pixel_format.cpython-311-x86_64-linux-gnu.so +0 -0
  26. dataspree/pfnc/pixel_format.pyi +40 -0
  27. dataspree/pfnc/py.typed +0 -0
  28. pfnc-0.1.0.dist-info/METADATA +134 -0
  29. pfnc-0.1.0.dist-info/RECORD +31 -0
  30. pfnc-0.1.0.dist-info/WHEEL +6 -0
  31. pfnc-0.1.0.dist-info/licenses/LICENSE.txt +21 -0
@@ -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."""
@@ -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
+ """
@@ -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
+ """
@@ -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
+ """
@@ -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
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
+ ![CI/CD](https://github.com/dataspree/dataspree-inspection/actions/workflows/ci.yml/badge.svg)
44
+ [![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm.fming.dev)
45
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](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-311-x86_64-linux-gnu.so,sha256=9l-9BKULsW1yrb19mtH01V4JDaqGGZK7izP9iRvJnF8,733416
4
+ dataspree/pfnc/decoder_registry.pyi,sha256=euwSAQE1XOs1pa3heiA9UQzaS9C43Wc4pEPInfIBXxs,2941
5
+ dataspree/pfnc/exceptions.cpython-311-x86_64-linux-gnu.so,sha256=MVcSxDN1zLGq-S15hC9Wngycz_9q-fqQF_lmxy2iy1Y,143784
6
+ dataspree/pfnc/exceptions.pyi,sha256=xo7I0D3rvE6kCm4joktO9T3SHQXTQzxFcZmTimzMQn8,1590
7
+ dataspree/pfnc/pixel_format.cpython-311-x86_64-linux-gnu.so,sha256=Voske6zvZuXqXRII5N-v9a_sDrO3MtjiwrBtuMf9SdM,561952
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-311-x86_64-linux-gnu.so,sha256=J0hfdVM8il8kIUJL3DYAsh-h3-q72vbj5MaW3JgUFtY,569584
12
+ dataspree/pfnc/_internal/registry.pyi,sha256=xRbKZTmYj2cLWbJJqMUUmEW23T3AYxQIVbrbfL5__78,1340
13
+ dataspree/pfnc/_internal/utils.cpython-311-x86_64-linux-gnu.so,sha256=0ZHx6nEaugJoUZt_tCm5il-dxYbPNNWTl_44ytBuaHA,408272
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-311-x86_64-linux-gnu.so,sha256=47l6Eu3IHmmo7Op7QwFNc2cQoFJ8G-U2sCGs0ZpRU0w,5762008
17
+ dataspree/pfnc/genicam/components.pyi,sha256=i8au1yfrWHphcsX2T8Jw3Gtp6f8_4EZUHVw7Ieg-JNY,39636
18
+ dataspree/pfnc/genicam/data_types.cpython-311-x86_64-linux-gnu.so,sha256=ROw8tN_kIQQnxEJeAGtSYkDNBIDihDQ5m3tLtzigCFw,1545360
19
+ dataspree/pfnc/genicam/data_types.pyi,sha256=32ucyWm3Ws4tyH1kfWRjWvNNWuJXNkJw_CnwxNYZL6c,4501
20
+ dataspree/pfnc/genicam/interface_specifics.cpython-311-x86_64-linux-gnu.so,sha256=FtvPtBWJeRZPVivBh-7DOLAzIl6-ASO3oRB15TW16XM,1037360
21
+ dataspree/pfnc/genicam/interface_specifics.pyi,sha256=J1l5sHxQC3Si1UdknQeVJ-naiITbIpGX1LhfGrt6aCA,4359
22
+ dataspree/pfnc/genicam/number_of_bits.cpython-311-x86_64-linux-gnu.so,sha256=LHBCRsglgGSyNG1JmXnpbsRF0UFQZyv6FtOkor1fdGQ,843816
23
+ dataspree/pfnc/genicam/number_of_bits.pyi,sha256=otqgOXw9OueBvMvYubSmuCeNS_pJZOEDTJMT8_9NaWA,1568
24
+ dataspree/pfnc/genicam/packing_types.cpython-311-x86_64-linux-gnu.so,sha256=BwKPoF9r-Hg3enpoa3OXVJFsiCPDLOcS29gpfxac7pE,1436616
25
+ dataspree/pfnc/genicam/packing_types.pyi,sha256=Wl4P2-8gtHlPcqZXa2PJVvsjcbxCXxXg5dsXZf6In3I,3165
26
+ dataspree/pfnc/genicam/pixel_format.cpython-311-x86_64-linux-gnu.so,sha256=t0-Xbd5Y7mc1GQKZS0Md_MryrneftEjlXXB9OeQfLfA,1762864
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=daP0MqGb5HgGG_e6YTHW1PKAHkmj2eMeFTxTkd_dPBg,148
30
+ pfnc-0.1.0.dist-info/RECORD,,
31
+ pfnc-0.1.0.dist-info/licenses/LICENSE.txt,sha256=zO7pALKLzkW8wkrMHQ1kJI6Bz9kEH5bxt4XB9i-YcsA,1072