Skip to content

Commit bf03325

Browse files
committed
Address #1663
1 parent 9560bb8 commit bf03325

3 files changed

Lines changed: 48 additions & 8 deletions

File tree

av/video/reformatter.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class Colorspace(IntEnum):
2727
fcc: int
2828
itu601: int
2929
itu624: int
30-
smpte240: int
30+
smpte170m: int
31+
smpte240m: int
3132
default: int
3233

3334
class ColorRange(IntEnum):

av/video/reformatter.pyx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ class ColorRange(IntEnum):
4545
NB: "Not part of ABI" = lib.AVCOL_RANGE_NB
4646

4747

48+
def _resolve_enum_value(value, enum_class, default):
49+
# Helper function to resolve enum values from different input types.
50+
if value is None:
51+
return default
52+
if isinstance(value, enum_class):
53+
return value.value
54+
if isinstance(value, int):
55+
return value
56+
if isinstance(value, str):
57+
return enum_class[value].value
58+
raise ValueError(f"Cannot convert {value} to {enum_class.__name__}")
59+
60+
4861
cdef class VideoReformatter:
4962
"""An object for reformatting size and pixel format of :class:`.VideoFrame`.
5063
@@ -83,11 +96,12 @@ cdef class VideoReformatter:
8396
"""
8497

8598
cdef VideoFormat video_format = VideoFormat(format if format is not None else frame.format)
86-
cdef int c_src_colorspace = (Colorspace[src_colorspace].value if src_colorspace is not None else frame.colorspace)
87-
cdef int c_dst_colorspace = (Colorspace[dst_colorspace].value if dst_colorspace is not None else frame.colorspace)
88-
cdef int c_interpolation = (Interpolation[interpolation] if interpolation is not None else Interpolation.BILINEAR).value
89-
cdef int c_src_color_range = (ColorRange[src_color_range].value if src_color_range is not None else 0)
90-
cdef int c_dst_color_range = (ColorRange[dst_color_range].value if dst_color_range is not None else 0)
99+
100+
cdef int c_src_colorspace = _resolve_enum_value(src_colorspace, Colorspace, frame.colorspace)
101+
cdef int c_dst_colorspace = _resolve_enum_value(dst_colorspace, Colorspace, frame.colorspace)
102+
cdef int c_interpolation = _resolve_enum_value(interpolation, Interpolation, int(Interpolation.BILINEAR))
103+
cdef int c_src_color_range = _resolve_enum_value(src_color_range, ColorRange, 0)
104+
cdef int c_dst_color_range = _resolve_enum_value(dst_color_range, ColorRange, 0)
91105

92106
return self._reformat(
93107
frame,

tests/test_videoframe.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import av
99
from av import VideoFrame
10+
from av.video.reformatter import ColorRange, Colorspace, Interpolation
1011

1112
from .common import (
1213
TestCase,
@@ -145,6 +146,24 @@ def test_roundtrip(self) -> None:
145146
img.save(self.sandboxed("roundtrip-high.jpg"))
146147
assertImagesAlmostEqual(image, img)
147148

149+
def test_interpolation(self) -> None:
150+
import PIL.Image as Image
151+
152+
image = Image.open(fate_png())
153+
frame = VideoFrame.from_image(image)
154+
assert frame.width == 330 and frame.height == 330
155+
156+
img = frame.to_image(width=200, height=100, interpolation=Interpolation.BICUBIC)
157+
assert img.width == 200 and img.height == 100
158+
159+
img = frame.to_image(width=200, height=100, interpolation="BICUBIC")
160+
assert img.width == 200 and img.height == 100
161+
162+
img = frame.to_image(
163+
width=200, height=100, interpolation=int(Interpolation.BICUBIC)
164+
)
165+
assert img.width == 200 and img.height == 100
166+
148167
def test_to_image_rgb24(self) -> None:
149168
sizes = [(318, 238), (320, 240), (500, 500)]
150169
for width, height in sizes:
@@ -838,14 +857,20 @@ def test_reformat_identity() -> None:
838857

839858

840859
def test_reformat_colorspace() -> None:
841-
# This is allowed.
842860
frame = VideoFrame(640, 480, "rgb24")
843861
frame.reformat(src_colorspace=None, dst_colorspace="smpte240m")
844862

845-
# I thought this was not allowed, but it seems to be.
863+
frame = VideoFrame(640, 480, "rgb24")
864+
frame.reformat(src_colorspace=None, dst_colorspace=Colorspace.smpte240m)
865+
846866
frame = VideoFrame(640, 480, "yuv420p")
847867
frame.reformat(src_colorspace=None, dst_colorspace="smpte240m")
848868

869+
frame = VideoFrame(640, 480, "rgb24")
870+
frame.colorspace = Colorspace.smpte240m
871+
assert frame.colorspace == int(Colorspace.smpte240m)
872+
assert frame.colorspace == Colorspace.smpte240m
873+
849874

850875
def test_reformat_pixel_format_align() -> None:
851876
height = 480

0 commit comments

Comments
 (0)