Browse Source

python: expose various pixel format helpers.

next
Vladimír Vondruš 3 years ago
parent
commit
6d473cf2aa
  1. 28
      doc/python/magnum.rst
  2. 4
      doc/python/pages/changelog.rst
  3. 108
      src/python/magnum/magnum.cpp
  4. 62
      src/python/magnum/test/test.py

28
doc/python/magnum.rst

@ -38,6 +38,34 @@
:data TARGET_EGL: EGL target
:data TARGET_VK: Vulkan interoperability
.. py:enum:: magnum.PixelFormat
The ``size``, ``channel_format``, ``channel_count``, ``is_normalized``,
``is_integral``, ``is_floating_point``, ``is_srgb``,
``is_depth_or_stencil`` and ``is_implementation_specific`` properties match
:dox:`pixelFormatSize()`, :dox:`pixelFormatChannelFormat()` and other
helpers.
.. code:: pycon
>>> PixelFormat.RGB8_SRGB.channel_count
3
>>> PixelFormat.RGB16F.is_floating_point
True
.. py:enum:: magnum.CompressedPixelFormat
The ``block_size``, ``block_data_size`` and ``is_implementation_specific``
properties match :dox:`compressedPixelFormatBlockSize()`,
:dox:`compressedPixelFormatBlockDataSize()` and other helpers.
.. code:: pycon
>>> CompressedPixelFormat.ASTC_6X5_RGBA_SRGB.block_size
Vector(6, 5, 1)
>>> CompressedPixelFormat.ASTC_6X5_RGBA_SRGB.block_data_size
16
.. py:class:: magnum.Image1D
See :ref:`Image2D` for more information.

4
doc/python/pages/changelog.rst

@ -55,7 +55,9 @@ Changelog
:ref:`Matrix3.projection()`
- Exposed remaining vector/scalar, exponential and other functions in the
:ref:`math <magnum.math>` library
- Exposed the :ref:`CompressedPixelFormat` enum
- Exposed the :ref:`CompressedPixelFormat` enum, various pixel-format-related
helper APIs are now properties on :ref:`PixelFormat` and
:ref:`CompressedPixelFormat`
- Exposed :ref:`Color3.from_xyz()`, :ref:`Color3.from_linear_rgb_int()`,
:ref:`Color3.to_xyz()`, :ref:`Color3.to_linear_rgb_int()` and equivalent
APIs on :ref:`Color4`

108
src/python/magnum/magnum.cpp

@ -302,7 +302,92 @@ void magnum(py::module_& m) {
.value("STENCIL8UI", PixelFormat::Stencil8UI)
.value("DEPTH16_UNORM_STENCIL8UI", PixelFormat::Depth16UnormStencil8UI)
.value("DEPTH24_UNORM_STENCIL8UI", PixelFormat::Depth24UnormStencil8UI)
.value("DEPTH32F_STENCIL8UI", PixelFormat::Depth32FStencil8UI);
.value("DEPTH32F_STENCIL8UI", PixelFormat::Depth32FStencil8UI)
.def_property_readonly("size", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine size of an implementation-specific format");
throw py::error_already_set{};
}
return pixelFormatSize(self);
}, "Size of given pixel format")
.def_property_readonly("channel_format", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine channel format of an implementation-specific format");
throw py::error_already_set{};
}
if(isPixelFormatDepthOrStencil(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine channel format of a depth/stencil format");
throw py::error_already_set{};
}
return pixelFormatChannelFormat(self);
}, "Channel format of given pixel format")
.def_property_readonly("channel_count", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine channel count of an implementation-specific format");
throw py::error_already_set{};
}
if(isPixelFormatDepthOrStencil(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine channel count of a depth/stencil format");
throw py::error_already_set{};
}
return pixelFormatChannelCount(self);
}, "Channel format of given pixel format")
.def_property_readonly("is_normalized", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of an implementation-specific format");
throw py::error_already_set{};
}
if(isPixelFormatDepthOrStencil(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of a depth/stencil format");
throw py::error_already_set{};
}
return isPixelFormatNormalized(self);
}, "Whether given pixel format is normalized")
.def_property_readonly("is_integral", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of an implementation-specific format");
throw py::error_already_set{};
}
if(isPixelFormatDepthOrStencil(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of a depth/stencil format");
throw py::error_already_set{};
}
return isPixelFormatIntegral(self);
}, "Whether given pixel format is integral")
.def_property_readonly("is_floating_point", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of an implementation-specific format");
throw py::error_already_set{};
}
if(isPixelFormatDepthOrStencil(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of a depth/stencil format");
throw py::error_already_set{};
}
return isPixelFormatFloatingPoint(self);
}, "Whether given pixel format is floating-point")
.def_property_readonly("is_srgb", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine colorspace of an implementation-specific format");
throw py::error_already_set{};
}
if(isPixelFormatDepthOrStencil(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine colorspace of a depth/stencil format");
throw py::error_already_set{};
}
return isPixelFormatSrgb(self);
}, "Whether given pixel format is sRGB")
.def_property_readonly("is_depth_or_stencil", [](PixelFormat self) {
if(isPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine type of an implementation-specific format");
throw py::error_already_set{};
}
return isPixelFormatDepthOrStencil(self);
}, "Whether given pixel format is depth or stencil")
.def_property_readonly("is_implementation_specific", [](PixelFormat self) {
return isPixelFormatImplementationSpecific(self);
}, "Whether given pixel format wraps an implementation-specific identifier")
/** @todo wrap/unwrap, similarly to custom MeshAttribute etc in Trade */
;
py::enum_<CompressedPixelFormat>{m, "CompressedPixelFormat", "Format of compressed pixel data"}
.value("BC1_RGB_UNORM", CompressedPixelFormat::Bc1RGBUnorm)
@ -410,7 +495,26 @@ void magnum(py::module_& m) {
.value("PVRTC_RGB_4PP_UNORM", CompressedPixelFormat::PvrtcRGB4bppUnorm)
.value("PVRTC_RGB_4PP_SRGB", CompressedPixelFormat::PvrtcRGB4bppSrgb)
.value("PVRTC_RGBA_4PP_UNORM", CompressedPixelFormat::PvrtcRGBA4bppUnorm)
.value("PVRTC_RGBA_4PP_SRGB", CompressedPixelFormat::PvrtcRGBA4bppSrgb);
.value("PVRTC_RGBA_4PP_SRGB", CompressedPixelFormat::PvrtcRGBA4bppSrgb)
.def_property_readonly("block_size", [](CompressedPixelFormat self) {
if(isCompressedPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine size of an implementation-specific format");
throw py::error_already_set{};
}
return compressedPixelFormatBlockSize(self);
}, "Block size of given compressed pixel format")
.def_property_readonly("block_data_size", [](CompressedPixelFormat self) {
if(isCompressedPixelFormatImplementationSpecific(self)) {
PyErr_SetString(PyExc_AssertionError, "can't determine size of an implementation-specific format");
throw py::error_already_set{};
}
return compressedPixelFormatBlockDataSize(self);
}, "Block data size of given compressed pixel format")
.def_property_readonly("is_implementation_specific", [](CompressedPixelFormat self) {
return isCompressedPixelFormatImplementationSpecific(self);
}, "Whether given compressed pixel format wraps an implementation-specific identifier")
/** @todo wrap/unwrap, similarly to custom MeshAttribute etc in Trade */
;
py::class_<PixelStorage>{m, "PixelStorage", "Pixel storage parameters"}
.def(py::init(), "Default constructor")

62
src/python/magnum/test/test.py

@ -32,6 +32,68 @@ from magnum import *
# tests also corrade.utility.copy() in UtilityCopy
class PixelFormat_(unittest.TestCase):
def test_properties(self):
self.assertEqual(PixelFormat.RGB16_SNORM.size, 3*2)
self.assertEqual(PixelFormat.RG32F.channel_format, PixelFormat.R32F)
self.assertEqual(PixelFormat.RGBA16_SNORM.channel_count, 4)
self.assertTrue(PixelFormat.RGBA8_UNORM.is_normalized)
self.assertFalse(PixelFormat.RGBA16F.is_normalized)
self.assertTrue(PixelFormat.RGB8I.is_integral)
self.assertFalse(PixelFormat.RGB8_SNORM.is_integral)
self.assertTrue(PixelFormat.RGB16F.is_floating_point)
self.assertFalse(PixelFormat.R8_SRGB.is_floating_point)
self.assertTrue(PixelFormat.RG8_SRGB.is_srgb)
self.assertFalse(PixelFormat.RG8_UNORM.is_srgb)
self.assertTrue(PixelFormat.DEPTH32F.is_depth_or_stencil)
self.assertFalse(PixelFormat.RG32I.is_depth_or_stencil)
self.assertTrue(PixelFormat(0x80000001).is_implementation_specific)
self.assertFalse(PixelFormat.RG32I.is_implementation_specific)
def test_properties_invalid(self):
with self.assertRaisesRegex(AssertionError, "can't determine size of an implementation-specific format"):
PixelFormat(0x80000000).size
with self.assertRaisesRegex(AssertionError, "can't determine channel format of an implementation-specific format"):
PixelFormat(0x80000000).channel_format
with self.assertRaisesRegex(AssertionError, "can't determine channel count of an implementation-specific format"):
PixelFormat(0x80000000).channel_count
with self.assertRaisesRegex(AssertionError, "can't determine type of an implementation-specific format"):
PixelFormat(0x80000000).is_normalized
with self.assertRaisesRegex(AssertionError, "can't determine type of an implementation-specific format"):
PixelFormat(0x80000000).is_integral
with self.assertRaisesRegex(AssertionError, "can't determine type of an implementation-specific format"):
PixelFormat(0x80000000).is_floating_point
with self.assertRaisesRegex(AssertionError, "can't determine colorspace of an implementation-specific format"):
PixelFormat(0x80000000).is_srgb
with self.assertRaisesRegex(AssertionError, "can't determine type of an implementation-specific format"):
PixelFormat(0x80000000).is_depth_or_stencil
with self.assertRaisesRegex(AssertionError, "can't determine channel format of a depth/stencil format"):
PixelFormat.DEPTH32F.channel_format
with self.assertRaisesRegex(AssertionError, "can't determine channel count of a depth/stencil format"):
PixelFormat.DEPTH32F.channel_count
with self.assertRaisesRegex(AssertionError, "can't determine type of a depth/stencil format"):
PixelFormat.DEPTH32F.is_normalized
with self.assertRaisesRegex(AssertionError, "can't determine type of a depth/stencil format"):
PixelFormat.DEPTH32F.is_integral
with self.assertRaisesRegex(AssertionError, "can't determine type of a depth/stencil format"):
PixelFormat.STENCIL8UI.is_floating_point
with self.assertRaisesRegex(AssertionError, "can't determine colorspace of a depth/stencil format"):
PixelFormat.DEPTH32F_STENCIL8UI.is_srgb
class CompressedPixelFormat_(unittest.TestCase):
def test_properties(self):
self.assertEqual(CompressedPixelFormat.ASTC_5X4_RGBA_UNORM.block_size, (5, 4, 1))
self.assertEqual(CompressedPixelFormat.ASTC_5X4_RGBA_UNORM.block_data_size, 128/8)
self.assertTrue(CompressedPixelFormat(0x80000001).is_implementation_specific)
self.assertFalse(CompressedPixelFormat.BC1_RGB_SRGB.is_implementation_specific)
def test_properties_invalid(self):
with self.assertRaisesRegex(AssertionError, "can't determine size of an implementation-specific format"):
CompressedPixelFormat(0x80000000).block_size
with self.assertRaisesRegex(AssertionError, "can't determine size of an implementation-specific format"):
CompressedPixelFormat(0x80000000).block_data_size
class PixelStorage_(unittest.TestCase):
def test_init(self):
a = PixelStorage()

Loading…
Cancel
Save