[{"id":12035,"web_url":"https://patchwork.libcamera.org/comment/12035/","msgid":"<20200819015609.GM2360@pendragon.ideasonboard.com>","date":"2020-08-19T01:56:09","subject":"Re: [libcamera-devel] [PATCH v2 1/5] libcamera: Add Transform enum\n\tto represet 2d plane transforms.","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi David,\n\nThank you for the patch.\n\ns/represet/represent/ in the subject line.\n\nOn Thu, Aug 06, 2020 at 05:36:35PM +0100, David Plowman wrote:\n> We implement 2d transforms as an enum class with 8 elements,\n\n2d or 2D ?\n\n> consisting of the usual 2d plane transformations (flips, rotations\n> etc.).\n> \n> The transform is made up of 3 bits, indicating whether the transform\n> includes: a transpose, a horizontal flip (mirror) and a vertical flip.\n\nMissing Signed-off-by line.\n\nOverall this looks good to me, please see below for a handful of small\ncomments.\n\n> ---\n>  include/libcamera/meson.build |  1 +\n>  include/libcamera/transform.h | 58 ++++++++++++++++++++++++\n>  src/libcamera/meson.build     |  1 +\n>  src/libcamera/transform.cpp   | 83 +++++++++++++++++++++++++++++++++++\n>  4 files changed, 143 insertions(+)\n>  create mode 100644 include/libcamera/transform.h\n>  create mode 100644 src/libcamera/transform.cpp\n> \n> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> index cdb8e03..7fae5e5 100644\n> --- a/include/libcamera/meson.build\n> +++ b/include/libcamera/meson.build\n> @@ -19,6 +19,7 @@ libcamera_public_headers = files([\n>      'span.h',\n>      'stream.h',\n>      'timer.h',\n> +    'transform.h',\n>  ])\n>  \n>  include_dir = join_paths(libcamera_include_dir, 'libcamera')\n> diff --git a/include/libcamera/transform.h b/include/libcamera/transform.h\n> new file mode 100644\n> index 0000000..658beb9\n> --- /dev/null\n> +++ b/include/libcamera/transform.h\n> @@ -0,0 +1,58 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2020, Raspberry Pi (Trading) Limited\n> + *\n> + * transform.h - Implementation of 2d plane transforms\n\ns/Implementation of //\n\n(same comment for the .cpp file)\n\n> + */\n> +\n> +#ifndef __LIBCAMERA_TRANSFORM_H__\n> +#define __LIBCAMERA_TRANSFORM_H__\n> +\n> +#include <string>\n> +\n> +namespace libcamera {\n> +\n> +enum class Transform : int {\n> +\tIdentity = 0,\n> +\tRot0 = Identity,\n> +\tHFlip = 1,\n> +\tVFlip = 2,\n> +\tHVFlip = HFlip | VFlip,\n> +\tRot180 = HVFlip,\n> +\tTranspose = 4,\n> +\tRot270 = HFlip | Transpose,\n> +\tRot90 = VFlip | Transpose,\n> +\tRot180Transpose = HFlip | VFlip | Transpose\n> +};\n> +\n> +constexpr Transform operator&(Transform t0, Transform t1)\n> +{\n> +\treturn static_cast<Transform>(static_cast<int>(t0) & static_cast<int>(t1));\n> +}\n> +\n> +constexpr Transform operator|(Transform t0, Transform t1)\n> +{\n> +\treturn static_cast<Transform>(static_cast<int>(t0) | static_cast<int>(t1));\n> +}\n> +\n> +constexpr Transform operator^(Transform t0, Transform t1)\n> +{\n> +\treturn static_cast<Transform>(static_cast<int>(t0) ^ static_cast<int>(t1));\n> +}\n> +\n> +Transform operator*(Transform t0, Transform t1);\n> +\n> +Transform operator-(Transform t);\n> +\n> +constexpr bool operator!(Transform t)\n> +{\n> +\treturn t == Transform::Identity;\n> +}\n> +\n> +Transform transformFromRotation(int angle, bool *success = nullptr);\n> +\n> +std::string transformToString(Transform t);\n\nA class would have allowed these to be member functions, but I think I\nagree that it's not worth the churn.\n\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif /* __LIBCAMERA_TRANSFORM_H__ */\n> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> index bada45b..b46247d 100644\n> --- a/src/libcamera/meson.build\n> +++ b/src/libcamera/meson.build\n> @@ -44,6 +44,7 @@ libcamera_sources = files([\n>      'sysfs.cpp',\n>      'thread.cpp',\n>      'timer.cpp',\n> +    'transform.cpp',\n>      'utils.cpp',\n>      'v4l2_controls.cpp',\n>      'v4l2_device.cpp',\n> diff --git a/src/libcamera/transform.cpp b/src/libcamera/transform.cpp\n> new file mode 100644\n> index 0000000..5f00a5c\n> --- /dev/null\n> +++ b/src/libcamera/transform.cpp\n> @@ -0,0 +1,83 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2020, Raspberry Pi (Trading) Limited\n> + *\n> + * transform.cpp - implementation of 2d plane transforms.\n> + */\n> +\n> +#include <libcamera/transform.h>\n> +\n> +/**\n> + * \\file transform.h\n> + * \\brief Enum to represent a 2d plane transforms.\n> + */\n> +\n> +namespace libcamera {\n> +\n> +Transform operator*(Transform t0, Transform t1)\n> +{\n> +\t/*\n> +\t * Reorder the operations so that we imagine doing t1's transpose\n> +\t * (if any) after t0's flips. The effect is to swap t0's hflips for\n> +\t * vflips and vice versa, after which we can just xor all the bits.\n> +\t */\n\nI need to wrap my head around this. Documentation would help, as nowhere\ndo we explicitly say in which direction rotations operate (clockwise or\ncounterclockwise) and whether transpose is applied before or after flip\nfor the transformations that have both set.\n\n> +\tTransform reordered = t0;\n> +\tif (!!(t1 & Transform::Transpose))\n> +\t\treordered = (t0 & Transform::Transpose) |\n> +\t\t\t    (!!(t0 & Transform::HFlip) ? Transform::VFlip : Transform::Identity) |\n> +\t\t\t    (!!(t0 & Transform::VFlip) ? Transform::HFlip : Transform::Identity);\n> +\n> +\treturn reordered ^ t1;\n> +}\n> +\n> +Transform operator-(Transform t)\n> +{\n> +\t/* All are self-inverses, except for Rot270 and Rot90. */\n> +\tstatic const Transform inverses[] = {\n> +\t\tTransform::Identity, Transform::HFlip, Transform::VFlip, Transform::HVFlip,\n> +\t\tTransform::Transpose, Transform::Rot90, Transform::Rot270, Transform::Rot180Transpose\n\nMaybe a few more line breaks to keep lines within the 80 columns limit ?\n\n> +\t};\n> +\n> +\treturn inverses[static_cast<int>(t)];\n> +}\n> +\n> +Transform transformFromRotation(int angle, bool *success)\n> +{\n> +\tangle = angle % 360;\n> +\tif (angle < 0)\n> +\t\tangle += 360;\n> +\n> +\tif (success != nullptr)\n> +\t\t*success = true;\n> +\n> +\tif (angle == 0)\n> +\t\treturn Transform::Identity;\n> +\telse if (angle == 90)\n> +\t\treturn Transform::Rot90;\n> +\telse if (angle == 180)\n> +\t\treturn Transform::Rot180;\n> +\telse if (angle == 270)\n> +\t\treturn Transform::Rot270;\n> +\telse if (success != nullptr)\n> +\t\t*success = false;\n\nMaybe a switch-case ?\n\n\tswitch (angle) {\n\tcase 0:\n\t\treturn Transform::Identity;\n\tcase 90:\n\t\treturn Transform::Rot90;\n\tcase 180:\n\t\treturn Transform::Rot180;\n\tcase 270:\n\t\treturn Transform::Rot270;\n\t}\n\n\tif (success != nullptr)\n\t\t*success = false;\n\n> +\n> +\treturn Transform::Identity;\n> +}\n> +\n> +std::string transformToString(Transform t)\n> +{\n> +\tstatic const char *strings[] = {\n> +\t\t\"identity\",\n> +\t\t\"hflip\",\n> +\t\t\"vflip\",\n> +\t\t\"hvflip\",\n> +\t\t\"transpose\",\n> +\t\t\"rot270\",\n> +\t\t\"rot90\",\n> +\t\t\"rot180transpose\"\n> +\t};\n> +\n> +\treturn strings[static_cast<int>(t)];\n\nHow about returning a const char * ? If that's what the caller needs it\nwill be cheaper, otherwise the caller can create an std::string()\n(mostly implicitly).\n\n> +}\n> +\n> +} /* namespace libcamera */","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 F1ABDBE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 19 Aug 2020 01:56:29 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 775A761E0E;\n\tWed, 19 Aug 2020 03:56:29 +0200 (CEST)","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 95BC660384\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 19 Aug 2020 03:56:27 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1CFF029E;\n\tWed, 19 Aug 2020 03:56:27 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"eir/Nxqi\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1597802187;\n\tbh=psuDXdvOi/ysCsdQ0yCTSyqXXoxcKtsLYL/CM8xdKu0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=eir/NxqiF7Rg5LHETmxc1V3NRCm8M0OjW7RaUtEvMuFzci85i6hxasfL5KB/4OOYk\n\t6vyZ9HCLHs1IrnMndZLNa7fewz9ab+9AnhS4oRyV1/CCV3aazbjvXWfhuie7JQFH5h\n\tHn6IT4jmdvbxNnwOcItui6Yyq08uaDn4YGXF4NVA=","Date":"Wed, 19 Aug 2020 04:56:09 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20200819015609.GM2360@pendragon.ideasonboard.com>","References":"<20200806163639.12971-1-david.plowman@raspberrypi.com>\n\t<20200806163639.12971-2-david.plowman@raspberrypi.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200806163639.12971-2-david.plowman@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v2 1/5] libcamera: Add Transform enum\n\tto represet 2d plane transforms.","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>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":12040,"web_url":"https://patchwork.libcamera.org/comment/12040/","msgid":"<CAHW6GYK0gbMnukjzzp+-6O4DTNfenet9s6X=O2kVVnt53Y0X2Q@mail.gmail.com>","date":"2020-08-19T07:14:00","subject":"Re: [libcamera-devel] [PATCH v2 1/5] libcamera: Add Transform enum\n\tto represet 2d plane transforms.","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi Laurent\n\nThanks for the review, much appreciated!. Those various suggestions\nall seem good to me so I'll prepare a v3 set that includes them. I'll\nalso add the missing documentation this time round and then hopefully\nwe'll be close!\n\nBest regards\nDavid\n\nOn Wed, 19 Aug 2020 at 02:56, Laurent Pinchart\n<laurent.pinchart@ideasonboard.com> wrote:\n>\n> Hi David,\n>\n> Thank you for the patch.\n>\n> s/represet/represent/ in the subject line.\n>\n> On Thu, Aug 06, 2020 at 05:36:35PM +0100, David Plowman wrote:\n> > We implement 2d transforms as an enum class with 8 elements,\n>\n> 2d or 2D ?\n>\n> > consisting of the usual 2d plane transformations (flips, rotations\n> > etc.).\n> >\n> > The transform is made up of 3 bits, indicating whether the transform\n> > includes: a transpose, a horizontal flip (mirror) and a vertical flip.\n>\n> Missing Signed-off-by line.\n>\n> Overall this looks good to me, please see below for a handful of small\n> comments.\n>\n> > ---\n> >  include/libcamera/meson.build |  1 +\n> >  include/libcamera/transform.h | 58 ++++++++++++++++++++++++\n> >  src/libcamera/meson.build     |  1 +\n> >  src/libcamera/transform.cpp   | 83 +++++++++++++++++++++++++++++++++++\n> >  4 files changed, 143 insertions(+)\n> >  create mode 100644 include/libcamera/transform.h\n> >  create mode 100644 src/libcamera/transform.cpp\n> >\n> > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > index cdb8e03..7fae5e5 100644\n> > --- a/include/libcamera/meson.build\n> > +++ b/include/libcamera/meson.build\n> > @@ -19,6 +19,7 @@ libcamera_public_headers = files([\n> >      'span.h',\n> >      'stream.h',\n> >      'timer.h',\n> > +    'transform.h',\n> >  ])\n> >\n> >  include_dir = join_paths(libcamera_include_dir, 'libcamera')\n> > diff --git a/include/libcamera/transform.h b/include/libcamera/transform.h\n> > new file mode 100644\n> > index 0000000..658beb9\n> > --- /dev/null\n> > +++ b/include/libcamera/transform.h\n> > @@ -0,0 +1,58 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2020, Raspberry Pi (Trading) Limited\n> > + *\n> > + * transform.h - Implementation of 2d plane transforms\n>\n> s/Implementation of //\n>\n> (same comment for the .cpp file)\n>\n> > + */\n> > +\n> > +#ifndef __LIBCAMERA_TRANSFORM_H__\n> > +#define __LIBCAMERA_TRANSFORM_H__\n> > +\n> > +#include <string>\n> > +\n> > +namespace libcamera {\n> > +\n> > +enum class Transform : int {\n> > +     Identity = 0,\n> > +     Rot0 = Identity,\n> > +     HFlip = 1,\n> > +     VFlip = 2,\n> > +     HVFlip = HFlip | VFlip,\n> > +     Rot180 = HVFlip,\n> > +     Transpose = 4,\n> > +     Rot270 = HFlip | Transpose,\n> > +     Rot90 = VFlip | Transpose,\n> > +     Rot180Transpose = HFlip | VFlip | Transpose\n> > +};\n> > +\n> > +constexpr Transform operator&(Transform t0, Transform t1)\n> > +{\n> > +     return static_cast<Transform>(static_cast<int>(t0) & static_cast<int>(t1));\n> > +}\n> > +\n> > +constexpr Transform operator|(Transform t0, Transform t1)\n> > +{\n> > +     return static_cast<Transform>(static_cast<int>(t0) | static_cast<int>(t1));\n> > +}\n> > +\n> > +constexpr Transform operator^(Transform t0, Transform t1)\n> > +{\n> > +     return static_cast<Transform>(static_cast<int>(t0) ^ static_cast<int>(t1));\n> > +}\n> > +\n> > +Transform operator*(Transform t0, Transform t1);\n> > +\n> > +Transform operator-(Transform t);\n> > +\n> > +constexpr bool operator!(Transform t)\n> > +{\n> > +     return t == Transform::Identity;\n> > +}\n> > +\n> > +Transform transformFromRotation(int angle, bool *success = nullptr);\n> > +\n> > +std::string transformToString(Transform t);\n>\n> A class would have allowed these to be member functions, but I think I\n> agree that it's not worth the churn.\n>\n> > +\n> > +} /* namespace libcamera */\n> > +\n> > +#endif /* __LIBCAMERA_TRANSFORM_H__ */\n> > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> > index bada45b..b46247d 100644\n> > --- a/src/libcamera/meson.build\n> > +++ b/src/libcamera/meson.build\n> > @@ -44,6 +44,7 @@ libcamera_sources = files([\n> >      'sysfs.cpp',\n> >      'thread.cpp',\n> >      'timer.cpp',\n> > +    'transform.cpp',\n> >      'utils.cpp',\n> >      'v4l2_controls.cpp',\n> >      'v4l2_device.cpp',\n> > diff --git a/src/libcamera/transform.cpp b/src/libcamera/transform.cpp\n> > new file mode 100644\n> > index 0000000..5f00a5c\n> > --- /dev/null\n> > +++ b/src/libcamera/transform.cpp\n> > @@ -0,0 +1,83 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2020, Raspberry Pi (Trading) Limited\n> > + *\n> > + * transform.cpp - implementation of 2d plane transforms.\n> > + */\n> > +\n> > +#include <libcamera/transform.h>\n> > +\n> > +/**\n> > + * \\file transform.h\n> > + * \\brief Enum to represent a 2d plane transforms.\n> > + */\n> > +\n> > +namespace libcamera {\n> > +\n> > +Transform operator*(Transform t0, Transform t1)\n> > +{\n> > +     /*\n> > +      * Reorder the operations so that we imagine doing t1's transpose\n> > +      * (if any) after t0's flips. The effect is to swap t0's hflips for\n> > +      * vflips and vice versa, after which we can just xor all the bits.\n> > +      */\n>\n> I need to wrap my head around this. Documentation would help, as nowhere\n> do we explicitly say in which direction rotations operate (clockwise or\n> counterclockwise) and whether transpose is applied before or after flip\n> for the transformations that have both set.\n>\n> > +     Transform reordered = t0;\n> > +     if (!!(t1 & Transform::Transpose))\n> > +             reordered = (t0 & Transform::Transpose) |\n> > +                         (!!(t0 & Transform::HFlip) ? Transform::VFlip : Transform::Identity) |\n> > +                         (!!(t0 & Transform::VFlip) ? Transform::HFlip : Transform::Identity);\n> > +\n> > +     return reordered ^ t1;\n> > +}\n> > +\n> > +Transform operator-(Transform t)\n> > +{\n> > +     /* All are self-inverses, except for Rot270 and Rot90. */\n> > +     static const Transform inverses[] = {\n> > +             Transform::Identity, Transform::HFlip, Transform::VFlip, Transform::HVFlip,\n> > +             Transform::Transpose, Transform::Rot90, Transform::Rot270, Transform::Rot180Transpose\n>\n> Maybe a few more line breaks to keep lines within the 80 columns limit ?\n>\n> > +     };\n> > +\n> > +     return inverses[static_cast<int>(t)];\n> > +}\n> > +\n> > +Transform transformFromRotation(int angle, bool *success)\n> > +{\n> > +     angle = angle % 360;\n> > +     if (angle < 0)\n> > +             angle += 360;\n> > +\n> > +     if (success != nullptr)\n> > +             *success = true;\n> > +\n> > +     if (angle == 0)\n> > +             return Transform::Identity;\n> > +     else if (angle == 90)\n> > +             return Transform::Rot90;\n> > +     else if (angle == 180)\n> > +             return Transform::Rot180;\n> > +     else if (angle == 270)\n> > +             return Transform::Rot270;\n> > +     else if (success != nullptr)\n> > +             *success = false;\n>\n> Maybe a switch-case ?\n>\n>         switch (angle) {\n>         case 0:\n>                 return Transform::Identity;\n>         case 90:\n>                 return Transform::Rot90;\n>         case 180:\n>                 return Transform::Rot180;\n>         case 270:\n>                 return Transform::Rot270;\n>         }\n>\n>         if (success != nullptr)\n>                 *success = false;\n>\n> > +\n> > +     return Transform::Identity;\n> > +}\n> > +\n> > +std::string transformToString(Transform t)\n> > +{\n> > +     static const char *strings[] = {\n> > +             \"identity\",\n> > +             \"hflip\",\n> > +             \"vflip\",\n> > +             \"hvflip\",\n> > +             \"transpose\",\n> > +             \"rot270\",\n> > +             \"rot90\",\n> > +             \"rot180transpose\"\n> > +     };\n> > +\n> > +     return strings[static_cast<int>(t)];\n>\n> How about returning a const char * ? If that's what the caller needs it\n> will be cheaper, otherwise the caller can create an std::string()\n> (mostly implicitly).\n>\n> > +}\n> > +\n> > +} /* namespace libcamera */\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","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 EC226BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 19 Aug 2020 07:14:15 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 73FD661B33;\n\tWed, 19 Aug 2020 09:14:15 +0200 (CEST)","from mail-ot1-x342.google.com (mail-ot1-x342.google.com\n\t[IPv6:2607:f8b0:4864:20::342])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 045BE60381\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 19 Aug 2020 09:14:13 +0200 (CEST)","by mail-ot1-x342.google.com with SMTP id 93so18333212otx.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 19 Aug 2020 00:14:13 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"iib7byuS\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=dvTgNwLzHeMxNyjM2frXGiqeLtlk40M7SSOAUhp+rZQ=;\n\tb=iib7byuSM/h2Fc5ti4jBuFJdaA8McWlVD99x9QADWH1wBhQkmddTF+u47lvXT1Xmwt\n\tTtayko5RH7liw4o9oamdSvMwxjFOpR11xRRPqoIVEUW5CpfCQKgykDEVlmbyp740xj/P\n\tBcz25kntMY1Mv4Vz0Skn+5F1phr+SqCC2DEjPvpO9a+hHXnj85qUO3qyOPl2D32f7vMY\n\tm8f7+6R2eXpWF3kJ7ljR5JzRANuusf7F5S9kW4weSs3j598SsCumOWfrPPGcZHGIO6Ap\n\tvOG4vxK326qHU3Kv6kxYMYnZgfMxHQZpqyjRw3DuMGfrguklWvaMvS+VwEmDWrrNy4Io\n\t/FrA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=dvTgNwLzHeMxNyjM2frXGiqeLtlk40M7SSOAUhp+rZQ=;\n\tb=NXw4wLlpb0sjBL0WaOJkp3hSjB5ewnyXL5FfyrSRWpsJYYe7jIJEshIPu5dKKSUKmb\n\ts6/gQf31kKIUYlQex1sWMlNXUq6RuSBcMuM9VYqmkK80T06fGJMvuzuPFqEqTnPiSE7d\n\tMqrm1SuyJTuon9XLWLlZM9D2Lwre33Hp/SKKQGIlYVjEzudHyNWPag7P7DeAq0CGgyIS\n\tLLwUAWLt4bWGsomeqvsQbTu+1bsm2XlJhL78JyUmQ6fT/rvkpSg6/SdsF0HWYH/LjFJk\n\tp4IU6/Bb4CEv9szzfFhr7E6LtWThhoL9swMjy7kXYat2U6rFyyV5wmGZTPatjiRu1iFs\n\twUEQ==","X-Gm-Message-State":"AOAM530gVnr04tlq5u2WW5Y2xXzr62PU4t9EadJbbUaYjF1XletFpfkU\n\tyJ9p7BKl5TLOSwKRk5TpMkP00YI9LKFU7TlBvaxgQA==","X-Google-Smtp-Source":"ABdhPJwzwDG3xNBATJzwkboG8v0ASFHf0SKBYIuuhGWc6cdoqdTFpM+mKg9F5NvMisYPOUJ5pd0JCWglrlhlvTfUhjc=","X-Received":"by 2002:a9d:6e8c:: with SMTP id\n\ta12mr5461877otr.166.1597821252442; \n\tWed, 19 Aug 2020 00:14:12 -0700 (PDT)","MIME-Version":"1.0","References":"<20200806163639.12971-1-david.plowman@raspberrypi.com>\n\t<20200806163639.12971-2-david.plowman@raspberrypi.com>\n\t<20200819015609.GM2360@pendragon.ideasonboard.com>","In-Reply-To":"<20200819015609.GM2360@pendragon.ideasonboard.com>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Wed, 19 Aug 2020 08:14:00 +0100","Message-ID":"<CAHW6GYK0gbMnukjzzp+-6O4DTNfenet9s6X=O2kVVnt53Y0X2Q@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v2 1/5] libcamera: Add Transform enum\n\tto represet 2d plane transforms.","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>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]