11 changed files with 659 additions and 64 deletions
@ -0,0 +1,194 @@
|
||||
#ifndef magnum_accessorsForPixelFormat_h |
||||
#define magnum_accessorsForPixelFormat_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include <pybind11/pybind11.h> |
||||
#include <Corrade/Containers/Triple.h> |
||||
#include <Magnum/PixelFormat.h> |
||||
#include <Magnum/Math/Color.h> |
||||
#include <Magnum/Math/Half.h> |
||||
#include <Magnum/Math/Packing.h> |
||||
|
||||
#include "Magnum/StridedArrayViewPythonBindings.h" |
||||
|
||||
#include "magnum/bootstrap.h" |
||||
|
||||
/* This is used by both the root magnum module (Image, ImageView) and
|
||||
magnum.trade.ImageData. There's no easy way to call an exported symbol of |
||||
another module due to Python isolating their namespaces so it's duplicated |
||||
in both modules. */ |
||||
namespace magnum { namespace { |
||||
|
||||
Containers::Triple<const char*, py::object(*)(const char*), void(*)(char*, py::handle)> accessorsForPixelFormat(const PixelFormat format) { |
||||
switch(format) { |
||||
#define _c(format, type) \ |
||||
case PixelFormat::format: return { \
|
||||
Containers::Implementation::pythonFormatString<type>(), \
|
||||
[](const char* item) { \
|
||||
return py::cast(*reinterpret_cast<const type*>(item)); \
|
||||
}, \
|
||||
[](char* item, py::handle object) { \
|
||||
*reinterpret_cast<type*>(item) = py::cast<type>(object); \
|
||||
}}; |
||||
/* Types (such as half-floats) that need to be cast before passed
|
||||
from/to pybind that doesn't understand the type directly */ |
||||
#define _cc(format, type, castType) \ |
||||
case PixelFormat::format: return { \
|
||||
Containers::Implementation::pythonFormatString<type>(), \
|
||||
[](const char* item) { \
|
||||
return py::cast(castType(*reinterpret_cast<const type*>(item))); \
|
||||
}, \
|
||||
[](char* item, py::handle object) { \
|
||||
*reinterpret_cast<type*>(item) = type(py::cast<castType>(object)); \
|
||||
}}; |
||||
/* Normalized types that need to be packed/unpacked before passed
|
||||
from/to pybind */ |
||||
#define _cNormalized(format, type, unpackType) \ |
||||
case PixelFormat::format: return { \
|
||||
Containers::Implementation::pythonFormatString<type>(), \
|
||||
[](const char* item) { \
|
||||
return py::cast(Math::unpack<unpackType>(*reinterpret_cast<const type*>(item))); \
|
||||
}, \
|
||||
[](char* item, py::handle object) { \
|
||||
*reinterpret_cast<type*>(item) = Math::pack<type>(py::cast<unpackType>(object)); \
|
||||
}}; |
||||
/* LCOV_EXCL_START */ |
||||
_cNormalized(R8Unorm, UnsignedByte, Float) |
||||
_cNormalized(RG8Unorm, Vector2ub, Vector2) |
||||
_cNormalized(RGB8Unorm, Vector3ub, Vector3) |
||||
_cNormalized(RGBA8Unorm, Vector4ub, Vector4) |
||||
_cNormalized(R8Snorm, Byte, Float) |
||||
_cNormalized(RG8Snorm, Vector2b, Vector2) |
||||
_cNormalized(RGB8Snorm, Vector3b, Vector3) |
||||
_cNormalized(RGBA8Snorm, Vector4b, Vector4) |
||||
/* LCOV_EXCL_STOP */ |
||||
case PixelFormat::R8Srgb: return { |
||||
Containers::Implementation::pythonFormatString<UnsignedByte>(), |
||||
/** @todo have an (internal) API to convert just R/RG sRGB channels */ |
||||
[](const char* item) { |
||||
return py::cast(Color3::fromSrgb(Vector3ub{*reinterpret_cast<const UnsignedByte*>(item), 0, 0}).r()); |
||||
}, |
||||
[](char* item, py::handle object) { |
||||
*reinterpret_cast<UnsignedByte*>(item) = Color3{py::cast<Float>(object), 0.0f, 0.0f}.toSrgb<UnsignedByte>().r(); |
||||
}}; |
||||
case PixelFormat::RG8Srgb: return { |
||||
Containers::Implementation::pythonFormatString<Vector2ub>(), |
||||
/** @todo have an (internal) API to convert just R/RG sRGB channels */ |
||||
[](const char* item) { |
||||
return py::cast(Color3::fromSrgb(Vector3ub{*reinterpret_cast<const Vector2ub*>(item), 0}).rg()); |
||||
}, |
||||
[](char* item, py::handle object) { |
||||
*reinterpret_cast<Vector2ub*>(item) = Color3{py::cast<Vector2>(object), 0.0f}.toSrgb<UnsignedByte>().rg(); |
||||
}}; |
||||
case PixelFormat::RGB8Srgb: return { |
||||
Containers::Implementation::pythonFormatString<Vector3ub>(), |
||||
[](const char* item) { |
||||
return py::cast(Color3::fromSrgb(*reinterpret_cast<const Vector3ub*>(item))); |
||||
}, |
||||
[](char* item, py::handle object) { |
||||
*reinterpret_cast<Vector3ub*>(item) = py::cast<Color3>(object).toSrgb<UnsignedByte>(); |
||||
}}; |
||||
case PixelFormat::RGBA8Srgb: return { |
||||
Containers::Implementation::pythonFormatString<Vector4ub>(), |
||||
[](const char* item) { |
||||
return py::cast(Color4::fromSrgbAlpha(*reinterpret_cast<const Vector4ub*>(item))); |
||||
}, |
||||
[](char* item, py::handle object) { |
||||
*reinterpret_cast<Vector4ub*>(item) = py::cast<Color4>(object).toSrgbAlpha<UnsignedByte>(); |
||||
}}; |
||||
/* LCOV_EXCL_START */ |
||||
_cc(R8UI, UnsignedByte, UnsignedInt) |
||||
_cc(RG8UI, Vector2ub, Vector2ui) |
||||
_cc(RGB8UI, Vector3ub, Vector3ui) |
||||
_cc(RGBA8UI, Vector4ub, Vector4ui) |
||||
_cc(R8I, Byte, Int) |
||||
_cc(RG8I, Vector2b, Vector2i) |
||||
_cc(RGB8I, Vector3b, Vector3i) |
||||
_cc(RGBA8I, Vector4b, Vector4i) |
||||
_cNormalized(R16Unorm, UnsignedShort, Float) |
||||
_cNormalized(RG16Unorm, Vector2us, Vector2) |
||||
_cNormalized(RGB16Unorm, Vector3us, Vector3) |
||||
_cNormalized(RGBA16Unorm, Vector4us, Vector4) |
||||
_cNormalized(R16Snorm, Short, Float) |
||||
_cNormalized(RG16Snorm, Vector2s, Vector2) |
||||
_cNormalized(RGB16Snorm, Vector3s, Vector3) |
||||
_cNormalized(RGBA16Snorm, Vector4s, Vector4) |
||||
_cc(R16UI, UnsignedShort, UnsignedInt) |
||||
_cc(RG16UI, Vector2us, Vector2ui) |
||||
_cc(RGB16UI, Vector3us, Vector3ui) |
||||
_cc(RGBA16UI, Vector4us, Vector4ui) |
||||
_cc(R16I, Short, Int) |
||||
_cc(RG16I, Vector2s, Vector2i) |
||||
_cc(RGB16I, Vector3s, Vector3i) |
||||
_cc(RGBA16I, Vector4s, Vector4i) |
||||
_c(R32UI, UnsignedInt) |
||||
_c(RG32UI, Vector2ui) |
||||
_c(RGB32UI, Vector3ui) |
||||
_c(RGBA32UI, Vector4ui) |
||||
_c(R32I, Int) |
||||
_c(RG32I, Vector2i) |
||||
_c(RGB32I, Vector3i) |
||||
_c(RGBA32I, Vector4i) |
||||
_cc(R16F, Half, Float) |
||||
_cc(RG16F, Vector2h, Vector2) |
||||
_cc(RGB16F, Vector3h, Vector3) |
||||
_cc(RGBA16F, Vector4h, Vector4) |
||||
_c(R32F, Float) |
||||
_c(RG32F, Vector2) |
||||
_c(RGB32F, Vector3) |
||||
_c(RGBA32F, Vector4) |
||||
/* LCOV_EXCL_STOP */ |
||||
#undef _c |
||||
#undef _cc |
||||
#undef _cNormalized |
||||
|
||||
/** @todo handle depth/stencil types (yes, i'm lazy) */ |
||||
default: |
||||
return {}; |
||||
} |
||||
} |
||||
|
||||
template<UnsignedInt dimensions, class T> Containers::StridedArrayView<dimensions - 1, T> flattenPixelView(const Containers::ArrayView<T> data, const Containers::StridedArrayView<dimensions, T>& pixels) { |
||||
/** @todo have some builtin API for this, this is awful (pixels<void>()?
|
||||
flatten<dimensions>() that asserts the last dimension is contiguous and |
||||
of a POD type? transpose<3, 0, 1, 2>()[0], differently named to avoid |
||||
clashes, taking dimension order?) */ |
||||
Containers::Size<dimensions - 1> size{NoInit}; |
||||
Containers::Stride<dimensions - 1> stride{NoInit}; |
||||
for(std::size_t i = 0; i != dimensions - 1; ++i) { |
||||
size[i] = pixels.size()[i]; |
||||
stride[i] = pixels.stride()[i]; |
||||
} |
||||
return Containers::StridedArrayView<dimensions - 1, T>{ |
||||
data, |
||||
static_cast<T*>(pixels.data()), |
||||
size, |
||||
stride}; |
||||
} |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
Binary file not shown.
Loading…
Reference in new issue