Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pixelformats: Use pixel groups instead of verticalsubsampling #2

Merged
merged 1 commit into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 54 additions & 54 deletions pixutils/formats/pixelformats.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from enum import Enum
from math import ceil
from typing import NamedTuple

from .fourcc_str import str_to_fourcc
Expand All @@ -16,20 +17,23 @@ class PixelColorEncoding(Enum):


class PixelFormatPlaneInfo(NamedTuple):
# plane's horizontal bytes in a line in a group
bytespergroup: int
verticalsubsampling: int
# plane's lines in a group
linespergroup: int


class PixelFormat:
def __init__(self, name: str,
drm_fourcc: None | str, v4l2_fourcc: None | str,
colorencoding: PixelColorEncoding, packed: bool,
pixelspergroup: int, planes) -> None:
pixelspergroup: tuple[int, int], planes) -> None:
self.name = name
self.drm_fourcc = str_to_fourcc(drm_fourcc) if drm_fourcc else None
self.v4l2_fourcc = str_to_fourcc(v4l2_fourcc) if v4l2_fourcc else None
self.color = colorencoding
self.packed = packed
# pixel group size (width-in-pixels, height-in-lines)
self.pixelspergroup = pixelspergroup
self.planes = [PixelFormatPlaneInfo(*p) for p in planes]

Expand All @@ -43,24 +47,20 @@ def stride(self, width: int, plane: int = 0, align: int = 1):
if plane >= len(self.planes):
raise RuntimeError()

# ceil(width / pixelsPerGroup) * bytesPerGroup
stride = (width + self.pixelspergroup - 1) // self.pixelspergroup * self.planes[plane].bytespergroup
stride = int(ceil(width / self.pixelspergroup[0])) * self.planes[plane].bytespergroup

# ceil(stride / align) * align
return (stride + align - 1) // align * align
return int(ceil((stride / align))) * align

def planesize(self, width: int, height: int, plane: int = 0, align: int = 1):
stride = self.stride(width, plane, align)
if stride == 0:
return 0

#return self.planeSize(height, plane, stride)
linespergroup = self.planes[plane].linespergroup

vertsubsample = self.planes[plane].verticalsubsampling

# stride * ceil(height / verticalSubSampling)
return stride * ((height + vertsubsample - 1) // vertsubsample)
assert self.pixelspergroup[1] % linespergroup == 0

return stride * int(ceil(height / (self.pixelspergroup[1] // linespergroup)))

# def planesize(self, height, plane, stride):
# vertSubSample = self.planes[plane].verticalSubSampling
Expand Down Expand Up @@ -109,31 +109,31 @@ def get_formats():
'RG16', 'RGBP',
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)
XRGB1555 = PixelFormat('XRGB1555',
'XR15', # DRM_FORMAT_XRGB1555
None,
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)
RGBX4444 = PixelFormat('RGBX4444',
'RX12', # DRM_FORMAT_RGBX4444
None,
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)
XRGB4444 = PixelFormat('XRGB4444',
'XR12', # DRM_FORMAT_XRGB4444
None,
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)

Expand All @@ -144,23 +144,23 @@ def get_formats():
None,
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)
RGBA4444 = PixelFormat('RGBA4444',
'RA12', # DRM_FORMAT_RGBA4444
None,
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)
ARGB4444 = PixelFormat('ARGB4444',
'AR12', # DRM_FORMAT_ARGB4444
None,
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 2, 1 ), ),
)

Expand All @@ -171,15 +171,15 @@ def get_formats():
'BGR3', # V4L2_PIX_FMT_BGR24
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 3, 1 ), ),
)
BGR888 = PixelFormat('BGR888',
'BG24', # DRM_FORMAT_BGR888
'RGB3', # V4L2_PIX_FMT_RGB24
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 3, 1 ), ),
)

Expand All @@ -190,31 +190,31 @@ def get_formats():
'XR24', # V4L2_PIX_FMT_XBGR32
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)
XBGR8888 = PixelFormat('XBGR8888',
'XB24', # DRM_FORMAT_XBGR8888
'XB24', # V4L2_PIX_FMT_RGBX32
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)
RGBX8888 = PixelFormat('RGBX8888',
'RX24', # DRM_FORMAT_RGBX8888
'RX24', # V4L2_PIX_FMT_BGRX32
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)
XBGR2101010 = PixelFormat('XBGR2101010',
'XB30', # DRM_FORMAT_XBGR2101010
'RX30', # V4L2_PIX_FMT_RGBX1010102
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)

Expand All @@ -225,23 +225,23 @@ def get_formats():
'AR24', # V4L2_PIX_FMT_ABGR32
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)
ABGR8888 = PixelFormat('ABGR8888',
'AB24', # DRM_FORMAT_ABGR8888
'AB24', # V4L2_PIX_FMT_RGBA32
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)
RGBA8888 = PixelFormat('RGBA8888',
'RA24', # DRM_FORMAT_RGBA8888
'RA24', # V4L2_PIX_FMT_BGRA32
PixelColorEncoding.RGB,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)

Expand All @@ -251,31 +251,31 @@ def get_formats():
'NV12', 'NM12',
PixelColorEncoding.YUV,
False,
2,
( ( 2, 1 ), ( 2, 2 ), ),
( 2, 2 ),
( ( 2, 2 ), ( 2, 1 ), ),
)

NV16 = PixelFormat('NV16',
'NV16', 'NM16',
PixelColorEncoding.YUV,
False,
2,
( 2, 1 ),
( ( 2, 1 ), ( 2, 1 ), ),
)

YUYV = PixelFormat('YUYV',
'YUYV', 'YUYV',
PixelColorEncoding.YUV,
False,
2,
( 2, 1 ),
( ( 4, 1 ), ),
)

UYVY = PixelFormat('UYVY',
'UYVY', 'UYVY',
PixelColorEncoding.YUV,
False,
2,
( 2, 1 ),
( ( 4, 1 ), ),
)

Expand All @@ -286,7 +286,7 @@ def get_formats():
'YUV3', # V4L2_PIX_FMT_YUV24
PixelColorEncoding.YUV,
False,
1,
( 1, 1 ),
( ( 3, 1 ), ),
)

Expand All @@ -295,7 +295,7 @@ def get_formats():
'YUVX', # V4L2_PIX_FMT_YUVX32
PixelColorEncoding.YUV,
False,
1,
( 1, 1 ),
( ( 4, 1 ), ),
)

Expand All @@ -305,7 +305,7 @@ def get_formats():
None, 'GREY',
PixelColorEncoding.YUV,
False,
1,
( 1, 1 ),
( ( 1, 1 ), ),
)

Expand All @@ -315,80 +315,80 @@ def get_formats():
None, 'BA81',
PixelColorEncoding.RAW,
False,
2,
( ( 2, 1 ), ),
( 2, 2 ),
( ( 2, 2 ), ),
)

SGBRG8 = PixelFormat('SGBRG8',
None, 'GBRG',
PixelColorEncoding.RAW,
False,
2,
( ( 2, 1 ), ),
( 2, 2 ),
( ( 2, 2 ), ),
)

SGRBG8 = PixelFormat('SGRBG8',
None, 'GRBG',
PixelColorEncoding.RAW,
False,
2,
( ( 2, 1 ), ),
( 2, 2 ),
( ( 2, 2 ), ),
)

SRGGB8 = PixelFormat('SRGGB8',
None, 'RGGB',
PixelColorEncoding.RAW,
False,
2,
( ( 2, 1 ), ),
( 2, 2 ),
( ( 2, 2 ), ),
)


SRGGB10 = PixelFormat('SRGGB10',
None, 'RG10',
PixelColorEncoding.RAW,
False,
2,
( ( 4, 1 ), ),
( 2, 2 ),
( ( 4, 2 ), ),
)

SBGGR10 = PixelFormat('SBGGR10',
None, 'BG10',
PixelColorEncoding.RAW,
False,
2,
( ( 4, 1 ), ),
( 2, 2 ),
( ( 4, 2 ), ),
)

SRGGB10P = PixelFormat('SRGGB10P',
None, 'pRAA',
PixelColorEncoding.RAW,
True,
4,
( ( 5, 1 ), ),
( 4, 2 ),
( ( 5, 2 ), ),
)

SRGGB12 = PixelFormat('SRGGB12',
None, 'RG12',
PixelColorEncoding.RAW,
False,
2,
( ( 4, 1 ), ),
( 2, 2 ),
( ( 4, 2 ), ),
)

SRGGB16 = PixelFormat('SRGGB16',
None, 'RG16',
PixelColorEncoding.RAW,
False,
2,
( ( 4, 1 ), ),
( 2, 2 ),
( ( 4, 2 ), ),
)

# Compressed formats
MJPEG = PixelFormat('MJPEG',
'MJPG', 'MJPG',
PixelColorEncoding.YUV,
False,
1,
( 1, 1 ),
( ( 1, 1 ), ),
)
2 changes: 1 addition & 1 deletion tests/print-fmts.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def main():
else:
v4l2_fourcc = ' '

planes = [f'bytespergroup:{p.bytespergroup} vsub:{p.verticalsubsampling}' for p in fmt.planes]
planes = [f'bytespergroup:{p.bytespergroup} linespergroup:{p.linespergroup}' for p in fmt.planes]

print(f'{fmt.name:15} {drm_fourcc:4} {v4l2_fourcc:4} pixelspergroup:{fmt.pixelspergroup} {planes}')

Expand Down