[{"id":33601,"web_url":"https://patchwork.libcamera.org/comment/33601/","msgid":"<174221493664.1463678.5797318255581763068@ping.linuxembedded.co.uk>","date":"2025-03-17T12:35:36","subject":"Re: [RFC PATCH v1] libcamera: {orientation,\n\ttransform}FromRotation(): Return `std::optional`","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Barnabás Pőcze (2025-01-28 08:35:33)\n> Return an empty `std::optional` on failure instead of\n> using a separate out parameter for signalling success.\n> \n\nOn the whole, this seems reasonable, I wonder why this was using a\nsuccess parameter in the first place? ... But again - I think we have a\npublic API/ABI breaking change here so we need to start definining a way\nto explicitly state that in the commit message.\n\nAny ideas?\n\nI guess we need to define some sort of standard tag like \n\nBreaking: ABI+API\n\nor\n\nABI: Changed parameter\n\nor something that means we can track this.\n\nI also wonder if we we should have a way to 'accept' API/ABI breaking\nchanges, but keep them separated until we are ready to make a new\nABI point release...\n\n\n\n> Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n> ---\n>  include/libcamera/orientation.h               |  3 ++-\n>  include/libcamera/transform.h                 |  4 +++-\n>  src/libcamera/orientation.cpp                 | 17 ++++-------------\n>  src/libcamera/sensor/camera_sensor_legacy.cpp |  8 ++++----\n>  src/libcamera/sensor/camera_sensor_raw.cpp    |  8 ++++----\n>  src/libcamera/transform.cpp                   | 17 ++++-------------\n>  src/py/libcamera/py_transform.cpp             | 15 +++++++--------\n>  7 files changed, 28 insertions(+), 44 deletions(-)\n> \n> diff --git a/include/libcamera/orientation.h b/include/libcamera/orientation.h\n> index a3b40e636..4e5b0f570 100644\n> --- a/include/libcamera/orientation.h\n> +++ b/include/libcamera/orientation.h\n> @@ -8,6 +8,7 @@\n>  #pragma once\n>  \n>  #include <iostream>\n> +#include <optional>\n>  \n>  namespace libcamera {\n>  \n> @@ -23,7 +24,7 @@ enum class Orientation {\n>         Rotate90,\n>  };\n>  \n> -Orientation orientationFromRotation(int angle, bool *success = nullptr);\n> +std::optional<Orientation> orientationFromRotation(int angle);\n>  \n>  std::ostream &operator<<(std::ostream &out, const Orientation &orientation);\n>  \n> diff --git a/include/libcamera/transform.h b/include/libcamera/transform.h\n> index 4517412a8..4769dc2e9 100644\n> --- a/include/libcamera/transform.h\n> +++ b/include/libcamera/transform.h\n> @@ -7,6 +7,8 @@\n>  \n>  #pragma once\n>  \n> +#include <optional>\n> +\n>  namespace libcamera {\n>  \n>  enum class Orientation;\n> @@ -68,7 +70,7 @@ constexpr Transform operator~(Transform t)\n>         return static_cast<Transform>(~static_cast<int>(t) & 7);\n>  }\n>  \n> -Transform transformFromRotation(int angle, bool *success = nullptr);\n> +std::optional<Transform> transformFromRotation(int angle);\n>  \n>  Transform operator/(const Orientation &o1, const Orientation &o2);\n>  Orientation operator*(const Orientation &o, const Transform &t);\n> diff --git a/src/libcamera/orientation.cpp b/src/libcamera/orientation.cpp\n> index 7d7d21ae8..9f118f834 100644\n> --- a/src/libcamera/orientation.cpp\n> +++ b/src/libcamera/orientation.cpp\n> @@ -59,21 +59,15 @@ namespace libcamera {\n>   * \\brief Return the orientation representing a rotation of the given angle\n>   * clockwise\n>   * \\param[in] angle The angle of rotation in a clockwise sense. Negative values\n> - * can be used to represent anticlockwise rotations\n> - * \\param[out] success Set to `true` if the angle is a multiple of 90 degrees,\n> - * otherwise `false`\n> - * \\return The orientation corresponding to the rotation if \\a success was set\n> - * to `true`, otherwise the `Rotate0` orientation\n> + * can be used to represent anticlockwise rotations. Must be a multiple of 90.\n> + * \\return The orientation corresponding to the rotation\n>   */\n> -Orientation orientationFromRotation(int angle, bool *success)\n> +std::optional<Orientation> orientationFromRotation(int angle)\n>  {\n>         angle = angle % 360;\n>         if (angle < 0)\n>                 angle += 360;\n>  \n> -       if (success != nullptr)\n> -               *success = true;\n> -\n>         switch (angle) {\n>         case 0:\n>                 return Orientation::Rotate0;\n> @@ -85,10 +79,7 @@ Orientation orientationFromRotation(int angle, bool *success)\n>                 return Orientation::Rotate270;\n>         }\n>  \n> -       if (success != nullptr)\n> -               *success = false;\n> -\n> -       return Orientation::Rotate0;\n> +       return {};\n>  }\n>  \n>  /**\n> diff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp\n> index b0c6abde4..d8c0bd41b 100644\n> --- a/src/libcamera/sensor/camera_sensor_legacy.cpp\n> +++ b/src/libcamera/sensor/camera_sensor_legacy.cpp\n> @@ -602,15 +602,15 @@ int CameraSensorLegacy::initProperties()\n>                  * Cache the Transform associated with the camera mounting\n>                  * rotation for later use in computeTransform().\n>                  */\n> -               bool success;\n> -               mountingOrientation_ = orientationFromRotation(propertyValue, &success);\n> -               if (!success) {\n> +               auto mountingOrientation = orientationFromRotation(propertyValue);\n> +               if (!mountingOrientation) {\n>                         LOG(CameraSensor, Warning)\n>                                 << \"Invalid rotation of \" << propertyValue\n>                                 << \" degrees - ignoring\";\n> -                       mountingOrientation_ = Orientation::Rotate0;\n>                 }\n>  \n> +               mountingOrientation_ = mountingOrientation.value_or(Orientation::Rotate0);\n> +\n>                 properties_.set(properties::Rotation, propertyValue);\n>         } else {\n>                 LOG(CameraSensor, Warning)\n> diff --git a/src/libcamera/sensor/camera_sensor_raw.cpp b/src/libcamera/sensor/camera_sensor_raw.cpp\n> index ab75b1f82..3a069ef9d 100644\n> --- a/src/libcamera/sensor/camera_sensor_raw.cpp\n> +++ b/src/libcamera/sensor/camera_sensor_raw.cpp\n> @@ -607,15 +607,15 @@ int CameraSensorRaw::initProperties()\n>                  * Cache the Transform associated with the camera mounting\n>                  * rotation for later use in computeTransform().\n>                  */\n> -               bool success;\n> -               mountingOrientation_ = orientationFromRotation(propertyValue, &success);\n> -               if (!success) {\n> +               auto mountingOrientation = orientationFromRotation(propertyValue);\n> +               if (!mountingOrientation) {\n>                         LOG(CameraSensor, Warning)\n>                                 << \"Invalid rotation of \" << propertyValue\n>                                 << \" degrees - ignoring\";\n> -                       mountingOrientation_ = Orientation::Rotate0;\n>                 }\n>  \n> +               mountingOrientation_ = mountingOrientation.value_or(Orientation::Rotate0);\n> +\n>                 properties_.set(properties::Rotation, propertyValue);\n>         } else {\n>                 LOG(CameraSensor, Warning)\n> diff --git a/src/libcamera/transform.cpp b/src/libcamera/transform.cpp\n> index 9fe8b5620..6636b23e4 100644\n> --- a/src/libcamera/transform.cpp\n> +++ b/src/libcamera/transform.cpp\n> @@ -269,21 +269,15 @@ Transform operator-(Transform t)\n>   * \\brief Return the transform representing a rotation of the given angle\n>   * clockwise\n>   * \\param[in] angle The angle of rotation in a clockwise sense. Negative values\n> - * can be used to represent anticlockwise rotations\n> - * \\param[out] success Set to `true` if the angle is a multiple of 90 degrees,\n> - * otherwise `false`\n> - * \\return The transform corresponding to the rotation if \\a success was set to\n> - * `true`, otherwise the `Identity` transform\n> + * can be used to represent anticlockwise rotations. Must be a multiple of 90.\n> + * \\return The transform corresponding to the rotation\n>   */\n> -Transform transformFromRotation(int angle, bool *success)\n> +std::optional<Transform> transformFromRotation(int angle)\n>  {\n>         angle = angle % 360;\n>         if (angle < 0)\n>                 angle += 360;\n>  \n> -       if (success != nullptr)\n> -               *success = true;\n> -\n>         switch (angle) {\n>         case 0:\n>                 return Transform::Identity;\n> @@ -295,10 +289,7 @@ Transform transformFromRotation(int angle, bool *success)\n>                 return Transform::Rot270;\n>         }\n>  \n> -       if (success != nullptr)\n> -               *success = false;\n> -\n> -       return Transform::Identity;\n> +       return {};\n>  }\n>  \n>  namespace {\n> diff --git a/src/py/libcamera/py_transform.cpp b/src/py/libcamera/py_transform.cpp\n> index 768260ffc..fc25d5a32 100644\n> --- a/src/py/libcamera/py_transform.cpp\n> +++ b/src/py/libcamera/py_transform.cpp\n> @@ -24,19 +24,18 @@ void init_py_transform(py::module &m)\n>  \n>         pyTransform\n>                 .def(py::init([](int rotation, bool hflip, bool vflip, bool transpose) {\n> -                       bool ok;\n> -\n> -                       Transform t = transformFromRotation(rotation, &ok);\n> -                       if (!ok)\n> +                       auto t = transformFromRotation(rotation);\n> +                       if (!t)\n>                                 throw std::invalid_argument(\"Invalid rotation\");\n>  \n>                         if (hflip)\n> -                               t ^= Transform::HFlip;\n> +                               *t ^= Transform::HFlip;\n>                         if (vflip)\n> -                               t ^= Transform::VFlip;\n> +                               *t ^= Transform::VFlip;\n>                         if (transpose)\n> -                               t ^= Transform::Transpose;\n> -                       return t;\n> +                               *t ^= Transform::Transpose;\n> +\n> +                       return *t;\n>                 }), py::arg(\"rotation\") = 0, py::arg(\"hflip\") = false,\n>                     py::arg(\"vflip\") = false, py::arg(\"transpose\") = false)\n>                 .def(py::init([](Transform &other) { return other; }))\n> -- \n> 2.48.1\n> \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 46217C32F5\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 17 Mar 2025 12:35:42 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EE1826894D;\n\tMon, 17 Mar 2025 13:35:40 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4E06268826\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 17 Mar 2025 13:35:39 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8F7968DB;\n\tMon, 17 Mar 2025 13:33:57 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"F86qHOzl\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1742214837;\n\tbh=ML3a5iVWllcmt7RDHBh7EcB6/3GjbZNgyDYzeFmiYf0=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=F86qHOzlDuUeiebKCI1Mtln6JW9yeSaHA3c8OEy+wKD90/NAcQLmaSMWX2fceOZ5j\n\tPWlzm6dfw0lshyyjlNYr/f2UQDhhECTfCnNsImeqxMov0GbXdmUIOf2PjCdh9D6Dpz\n\t0F/V2zfyuMwEQeHzMkWAhBlm02n1G/GXGeoJwmic=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20250128083530.351935-1-pobrn@protonmail.com>","References":"<20250128083530.351935-1-pobrn@protonmail.com>","Subject":"Re: [RFC PATCH v1] libcamera: {orientation,\n\ttransform}FromRotation(): Return `std::optional`","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <pobrn@protonmail.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 17 Mar 2025 12:35:36 +0000","Message-ID":"<174221493664.1463678.5797318255581763068@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":33694,"web_url":"https://patchwork.libcamera.org/comment/33694/","msgid":"<8bdb0614-51be-4aba-86c1-eb1646de8348@ideasonboard.com>","date":"2025-03-24T16:01:51","subject":"Re: [RFC PATCH v1] libcamera: {orientation,\n\ttransform}FromRotation(): Return `std::optional`","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"Hi\n\n\n2025. 03. 17. 13:35 keltezéssel, Kieran Bingham írta:\n> Quoting Barnabás Pőcze (2025-01-28 08:35:33)\n>> Return an empty `std::optional` on failure instead of\n>> using a separate out parameter for signalling success.\n>>\n> \n> On the whole, this seems reasonable, I wonder why this was using a\n> success parameter in the first place? ... But again - I think we have a\n> public API/ABI breaking change here so we need to start definining a way\n> to explicitly state that in the commit message.\n> \n> Any ideas?\n> \n> I guess we need to define some sort of standard tag like\n> \n> Breaking: ABI+API\n> \n> or\n> \n> ABI: Changed parameter\n> \n> or something that means we can track this.\n> \n> I also wonder if we we should have a way to 'accept' API/ABI breaking\n> changes, but keep them separated until we are ready to make a new\n> ABI point release...\n> \n\nI don't have a concrete idea, but I like the second one better.\nOr maybe something like `{Tag,Label}: api-break, abi-break`.\n\n\nRegards,\nBarnabás Pőcze\n\n> \n> \n>> Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>\n>> ---\n>>   include/libcamera/orientation.h               |  3 ++-\n>>   include/libcamera/transform.h                 |  4 +++-\n>>   src/libcamera/orientation.cpp                 | 17 ++++-------------\n>>   src/libcamera/sensor/camera_sensor_legacy.cpp |  8 ++++----\n>>   src/libcamera/sensor/camera_sensor_raw.cpp    |  8 ++++----\n>>   src/libcamera/transform.cpp                   | 17 ++++-------------\n>>   src/py/libcamera/py_transform.cpp             | 15 +++++++--------\n>>   7 files changed, 28 insertions(+), 44 deletions(-)\n>>\n>> diff --git a/include/libcamera/orientation.h b/include/libcamera/orientation.h\n>> index a3b40e636..4e5b0f570 100644\n>> --- a/include/libcamera/orientation.h\n>> +++ b/include/libcamera/orientation.h\n>> @@ -8,6 +8,7 @@\n>>   #pragma once\n>>   \n>>   #include <iostream>\n>> +#include <optional>\n>>   \n>>   namespace libcamera {\n>>   \n>> @@ -23,7 +24,7 @@ enum class Orientation {\n>>          Rotate90,\n>>   };\n>>   \n>> -Orientation orientationFromRotation(int angle, bool *success = nullptr);\n>> +std::optional<Orientation> orientationFromRotation(int angle);\n>>   \n>>   std::ostream &operator<<(std::ostream &out, const Orientation &orientation);\n>>   \n>> diff --git a/include/libcamera/transform.h b/include/libcamera/transform.h\n>> index 4517412a8..4769dc2e9 100644\n>> --- a/include/libcamera/transform.h\n>> +++ b/include/libcamera/transform.h\n>> @@ -7,6 +7,8 @@\n>>   \n>>   #pragma once\n>>   \n>> +#include <optional>\n>> +\n>>   namespace libcamera {\n>>   \n>>   enum class Orientation;\n>> @@ -68,7 +70,7 @@ constexpr Transform operator~(Transform t)\n>>          return static_cast<Transform>(~static_cast<int>(t) & 7);\n>>   }\n>>   \n>> -Transform transformFromRotation(int angle, bool *success = nullptr);\n>> +std::optional<Transform> transformFromRotation(int angle);\n>>   \n>>   Transform operator/(const Orientation &o1, const Orientation &o2);\n>>   Orientation operator*(const Orientation &o, const Transform &t);\n>> diff --git a/src/libcamera/orientation.cpp b/src/libcamera/orientation.cpp\n>> index 7d7d21ae8..9f118f834 100644\n>> --- a/src/libcamera/orientation.cpp\n>> +++ b/src/libcamera/orientation.cpp\n>> @@ -59,21 +59,15 @@ namespace libcamera {\n>>    * \\brief Return the orientation representing a rotation of the given angle\n>>    * clockwise\n>>    * \\param[in] angle The angle of rotation in a clockwise sense. Negative values\n>> - * can be used to represent anticlockwise rotations\n>> - * \\param[out] success Set to `true` if the angle is a multiple of 90 degrees,\n>> - * otherwise `false`\n>> - * \\return The orientation corresponding to the rotation if \\a success was set\n>> - * to `true`, otherwise the `Rotate0` orientation\n>> + * can be used to represent anticlockwise rotations. Must be a multiple of 90.\n>> + * \\return The orientation corresponding to the rotation\n>>    */\n>> -Orientation orientationFromRotation(int angle, bool *success)\n>> +std::optional<Orientation> orientationFromRotation(int angle)\n>>   {\n>>          angle = angle % 360;\n>>          if (angle < 0)\n>>                  angle += 360;\n>>   \n>> -       if (success != nullptr)\n>> -               *success = true;\n>> -\n>>          switch (angle) {\n>>          case 0:\n>>                  return Orientation::Rotate0;\n>> @@ -85,10 +79,7 @@ Orientation orientationFromRotation(int angle, bool *success)\n>>                  return Orientation::Rotate270;\n>>          }\n>>   \n>> -       if (success != nullptr)\n>> -               *success = false;\n>> -\n>> -       return Orientation::Rotate0;\n>> +       return {};\n>>   }\n>>   \n>>   /**\n>> diff --git a/src/libcamera/sensor/camera_sensor_legacy.cpp b/src/libcamera/sensor/camera_sensor_legacy.cpp\n>> index b0c6abde4..d8c0bd41b 100644\n>> --- a/src/libcamera/sensor/camera_sensor_legacy.cpp\n>> +++ b/src/libcamera/sensor/camera_sensor_legacy.cpp\n>> @@ -602,15 +602,15 @@ int CameraSensorLegacy::initProperties()\n>>                   * Cache the Transform associated with the camera mounting\n>>                   * rotation for later use in computeTransform().\n>>                   */\n>> -               bool success;\n>> -               mountingOrientation_ = orientationFromRotation(propertyValue, &success);\n>> -               if (!success) {\n>> +               auto mountingOrientation = orientationFromRotation(propertyValue);\n>> +               if (!mountingOrientation) {\n>>                          LOG(CameraSensor, Warning)\n>>                                  << \"Invalid rotation of \" << propertyValue\n>>                                  << \" degrees - ignoring\";\n>> -                       mountingOrientation_ = Orientation::Rotate0;\n>>                  }\n>>   \n>> +               mountingOrientation_ = mountingOrientation.value_or(Orientation::Rotate0);\n>> +\n>>                  properties_.set(properties::Rotation, propertyValue);\n>>          } else {\n>>                  LOG(CameraSensor, Warning)\n>> diff --git a/src/libcamera/sensor/camera_sensor_raw.cpp b/src/libcamera/sensor/camera_sensor_raw.cpp\n>> index ab75b1f82..3a069ef9d 100644\n>> --- a/src/libcamera/sensor/camera_sensor_raw.cpp\n>> +++ b/src/libcamera/sensor/camera_sensor_raw.cpp\n>> @@ -607,15 +607,15 @@ int CameraSensorRaw::initProperties()\n>>                   * Cache the Transform associated with the camera mounting\n>>                   * rotation for later use in computeTransform().\n>>                   */\n>> -               bool success;\n>> -               mountingOrientation_ = orientationFromRotation(propertyValue, &success);\n>> -               if (!success) {\n>> +               auto mountingOrientation = orientationFromRotation(propertyValue);\n>> +               if (!mountingOrientation) {\n>>                          LOG(CameraSensor, Warning)\n>>                                  << \"Invalid rotation of \" << propertyValue\n>>                                  << \" degrees - ignoring\";\n>> -                       mountingOrientation_ = Orientation::Rotate0;\n>>                  }\n>>   \n>> +               mountingOrientation_ = mountingOrientation.value_or(Orientation::Rotate0);\n>> +\n>>                  properties_.set(properties::Rotation, propertyValue);\n>>          } else {\n>>                  LOG(CameraSensor, Warning)\n>> diff --git a/src/libcamera/transform.cpp b/src/libcamera/transform.cpp\n>> index 9fe8b5620..6636b23e4 100644\n>> --- a/src/libcamera/transform.cpp\n>> +++ b/src/libcamera/transform.cpp\n>> @@ -269,21 +269,15 @@ Transform operator-(Transform t)\n>>    * \\brief Return the transform representing a rotation of the given angle\n>>    * clockwise\n>>    * \\param[in] angle The angle of rotation in a clockwise sense. Negative values\n>> - * can be used to represent anticlockwise rotations\n>> - * \\param[out] success Set to `true` if the angle is a multiple of 90 degrees,\n>> - * otherwise `false`\n>> - * \\return The transform corresponding to the rotation if \\a success was set to\n>> - * `true`, otherwise the `Identity` transform\n>> + * can be used to represent anticlockwise rotations. Must be a multiple of 90.\n>> + * \\return The transform corresponding to the rotation\n>>    */\n>> -Transform transformFromRotation(int angle, bool *success)\n>> +std::optional<Transform> transformFromRotation(int angle)\n>>   {\n>>          angle = angle % 360;\n>>          if (angle < 0)\n>>                  angle += 360;\n>>   \n>> -       if (success != nullptr)\n>> -               *success = true;\n>> -\n>>          switch (angle) {\n>>          case 0:\n>>                  return Transform::Identity;\n>> @@ -295,10 +289,7 @@ Transform transformFromRotation(int angle, bool *success)\n>>                  return Transform::Rot270;\n>>          }\n>>   \n>> -       if (success != nullptr)\n>> -               *success = false;\n>> -\n>> -       return Transform::Identity;\n>> +       return {};\n>>   }\n>>   \n>>   namespace {\n>> diff --git a/src/py/libcamera/py_transform.cpp b/src/py/libcamera/py_transform.cpp\n>> index 768260ffc..fc25d5a32 100644\n>> --- a/src/py/libcamera/py_transform.cpp\n>> +++ b/src/py/libcamera/py_transform.cpp\n>> @@ -24,19 +24,18 @@ void init_py_transform(py::module &m)\n>>   \n>>          pyTransform\n>>                  .def(py::init([](int rotation, bool hflip, bool vflip, bool transpose) {\n>> -                       bool ok;\n>> -\n>> -                       Transform t = transformFromRotation(rotation, &ok);\n>> -                       if (!ok)\n>> +                       auto t = transformFromRotation(rotation);\n>> +                       if (!t)\n>>                                  throw std::invalid_argument(\"Invalid rotation\");\n>>   \n>>                          if (hflip)\n>> -                               t ^= Transform::HFlip;\n>> +                               *t ^= Transform::HFlip;\n>>                          if (vflip)\n>> -                               t ^= Transform::VFlip;\n>> +                               *t ^= Transform::VFlip;\n>>                          if (transpose)\n>> -                               t ^= Transform::Transpose;\n>> -                       return t;\n>> +                               *t ^= Transform::Transpose;\n>> +\n>> +                       return *t;\n>>                  }), py::arg(\"rotation\") = 0, py::arg(\"hflip\") = false,\n>>                      py::arg(\"vflip\") = false, py::arg(\"transpose\") = false)\n>>                  .def(py::init([](Transform &other) { return other; }))\n>> -- \n>> 2.48.1\n>>\n>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 41867C0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Mar 2025 16:01:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 46E5C68945;\n\tMon, 24 Mar 2025 17:01:57 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B4D1E6893F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Mar 2025 17:01:55 +0100 (CET)","from [192.168.33.27] (185.221.143.221.nat.pool.zt.hu\n\t[185.221.143.221])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F065A455;\n\tMon, 24 Mar 2025 17:00:08 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"p8ojBj8b\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1742832009;\n\tbh=VDamtqYU2aCmTUcmgFZUPwnCD99pubFbrUCu/NrK7Go=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=p8ojBj8bMnO3SmL//VKRcZSxmb/g4QKnFR7dhOGLMBkBItMYwpWH7nmvqeVvYgFs2\n\tjVKzA4pSDTlgCpdMSG98nbJ4YntlTW/Xgl7Tm/srhDD6EYlAr/1Xbv8G98HuwEX+9F\n\tDhk4wH8GrzaGYtVaZpL/rCg+MePH66P3agZrnVWY=","Message-ID":"<8bdb0614-51be-4aba-86c1-eb1646de8348@ideasonboard.com>","Date":"Mon, 24 Mar 2025 17:01:51 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [RFC PATCH v1] libcamera: {orientation,\n\ttransform}FromRotation(): Return `std::optional`","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20250128083530.351935-1-pobrn@protonmail.com>\n\t<174221493664.1463678.5797318255581763068@ping.linuxembedded.co.uk>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<174221493664.1463678.5797318255581763068@ping.linuxembedded.co.uk>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]