[arrayfire] 222/408: YCbCr <-> RGB conversion functions

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:12:03 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/sid
in repository arrayfire.

commit b2592595d90b236deafba45dde5c4d66e53ee0f1
Author: pradeep <pradeep at arrayfire.com>
Date:   Mon Aug 10 11:24:35 2015 -0400

    YCbCr <-> RGB conversion functions
---
 include/af/defines.h      |   7 +++
 include/af/image.h        |  60 ++++++++++++++++++
 src/api/c/ycbcr_rgb.cpp   | 154 ++++++++++++++++++++++++++++++++++++++++++++++
 src/api/cpp/ycbcr_rgb.cpp |  31 ++++++++++
 4 files changed, 252 insertions(+)

diff --git a/include/af/defines.h b/include/af/defines.h
index a2aa7a9..b85e456 100644
--- a/include/af/defines.h
+++ b/include/af/defines.h
@@ -235,6 +235,12 @@ typedef enum {
 } af_match_type;
 
 typedef enum {
+    AF_YCC_601 = 601,  ///< ITU-R BT.601 (formerly CCIR 601) standard
+    AF_YCC_709 = 709,  ///< ITU-R BT.709 standard
+    AF_YCC_2020 = 2020  ///< ITU-R BT.2020 standard
+} af_ycc_std;
+
+typedef enum {
     AF_GRAY = 0, ///< Grayscale
     AF_RGB,      ///< 3-channel RGB
     AF_HSV       ///< 3-channel HSV
@@ -302,6 +308,7 @@ namespace af
     typedef af_mat_prop matProp;
     typedef af_colormap ColorMap;
     typedef af_norm_type normType;
+    typedef af_ycc_std YCCStd;
 }
 
 #endif
diff --git a/include/af/image.h b/include/af/image.h
index 841a4f5..4f7227c 100644
--- a/include/af/image.h
+++ b/include/af/image.h
@@ -501,6 +501,34 @@ AFAPI array unwrap(const array& in, const dim_t wx, const dim_t wy,
 */
 AFAPI array sat(const array& in);
 
+/**
+   C++ Interface for converting YCbCr to RGB
+
+   \param[in]  in is an array in the YCbCr colorspace
+   \param[in]  standard specifies the ITU-R BT "xyz" standard which determines the Kb, Kr values
+   used in colorspace conversion equation
+   \return     array in RGB colorspace
+
+   \note \p in must be three dimensional and values should lie in the range [0,1]
+
+   \ingroup image_func_ycbcr2rgb
+ */
+AFAPI array ycbcr2rgb(const array& in, const YCCStd standard=AF_YCC_601);
+
+/**
+   C++ Interface for converting RGB to YCbCr
+
+   \param[in]  in is an array in the RGB colorspace
+   \param[in]  standard specifies the ITU-R BT "xyz" standard which determines the Kb, Kr values
+   used in colorspace conversion equation
+   \return     array in YCbCr colorspace
+
+   \note \p in must be three dimensional and values should lie in the range [0,1]
+
+   \ingroup image_func_rgb2ycbcr
+ */
+AFAPI array rgb2ycbcr(const array& in, const YCCStd standard=AF_YCC_601);
+
 }
 #endif
 
@@ -988,6 +1016,38 @@ extern "C" {
     */
     AFAPI af_err af_sat(af_array *out, const af_array in);
 
+    /**
+       C Interface for converting YCbCr to RGB
+
+       \param[out] out is an array in the RGB color space
+       \param[in]  in is an array in the YCbCr color space
+       \param[in]  standard specifies the ITU-R BT "xyz" standard which determines the Kb, Kr values
+       used in colorspace conversion equation
+       \return     \ref AF_SUCCESS if the color transformation is successful,
+       otherwise an appropriate error code is returned.
+
+       \note \p in must be three dimensional and values should lie in the range [0,1]
+
+       \ingroup image_func_ycbcr2rgb
+    */
+    AFAPI af_err af_ycbcr2rgb(af_array* out, const af_array in, const af_ycc_std standard);
+
+    /**
+       C Interface for converting RGB to YCbCr
+
+       \param[out] out is an array in the YCbCr color space
+       \param[in]  in is an array in the RGB color space
+       \param[in]  standard specifies the ITU-R BT "xyz" standard which determines the Kb, Kr values
+       used in colorspace conversion equation
+       \return     \ref AF_SUCCESS if the color transformation is successful,
+       otherwise an appropriate error code is returned.
+
+       \note \p in must be three dimensional and values should lie in the range [0,1]
+
+       \ingroup image_func_rgb2ycbcr
+    */
+    AFAPI af_err af_rgb2ycbcr(af_array* out, const af_array in, const af_ycc_std standard);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/api/c/ycbcr_rgb.cpp b/src/api/c/ycbcr_rgb.cpp
new file mode 100644
index 0000000..1477e27
--- /dev/null
+++ b/src/api/c/ycbcr_rgb.cpp
@@ -0,0 +1,154 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/defines.h>
+#include <af/dim4.hpp>
+#include <af/image.h>
+#include <af/index.h>
+#include <handle.hpp>
+#include <err_common.hpp>
+#include <backend.hpp>
+#include <arith.hpp>
+#include <copy.hpp>
+#include <join.hpp>
+#include <math.hpp>
+
+using af::dim4;
+using namespace detail;
+
+template<typename T>
+static Array<T> mix(const Array<T>& X, const Array<T>& Y,
+                double xf, double yf)
+{
+    dim4 dims = X.dims();
+    Array<T> fX = padArray<T, T>(X, dims, scalar<T>(0), xf);
+    Array<T> fY = padArray<T, T>(Y, dims, scalar<T>(0), yf);
+
+    return arithOp<T, af_add_t>(fX, fY, dims);
+}
+
+template<typename T>
+static Array<T> mix(const Array<T>& X, const Array<T>& Y, const Array<T>& Z,
+                double xf, double yf, double zf)
+{
+    dim4 dims = X.dims();
+    Array<T> fX = padArray<T, T>(X, dims, scalar<T>(0), xf);
+    Array<T> fY = padArray<T, T>(Y, dims, scalar<T>(0), yf);
+    Array<T> fZ = padArray<T, T>(Z, dims, scalar<T>(0), zf);
+
+    Array<T> fx_fy = arithOp<T, af_add_t>(fX, fY, dims);
+    return arithOp<T, af_add_t>(fx_fy, fZ, dims);
+}
+
+template<typename T>
+static Array<T> digitize(const Array<T> ch, const double scale, const double offset)
+{
+    dim4 dims = ch.dims();
+    Array<T> base = createValueArray<T>(dims, scalar<T>(offset));
+    Array<T> cnst = createValueArray<T>(dims, scalar<T>(scale));
+    Array<T> scl  = arithOp<T, af_mul_t>(ch, cnst, dims);
+    return arithOp<T, af_add_t>(scl, base, dims);
+}
+
+template<typename T, bool isYCbCr2RGB>
+static af_array convert(const af_array& in, const af_ycc_std standard)
+{
+    static const float INV_219 = 0.004566210;
+    static const float INV_112 = 0.008928571;
+    const static float k[6] = {
+        0.1140f, 0.2990f,
+        0.0722f, 0.2126f,
+        0.0593f, 0.2627f
+    };
+    unsigned stdIdx = 0; // Default standard is AF_YCC_601
+    switch(standard) {
+        case AF_YCC_709 : stdIdx = 2; break;
+        case AF_YCC_2020: stdIdx = 4; break;
+        default         : stdIdx = 0; break;
+    }
+    float kb = k[stdIdx];
+    float kr = k[stdIdx+1];
+    float kl = 1.0f - kb - kr;
+    float invKl = 1/kl;
+
+    // extract three channels as three slices
+    // prepare sequence objects
+    af_seq slice1[4] = { af_span, af_span, {0, 0, 1}, af_span };
+    af_seq slice2[4] = { af_span, af_span, {1, 1, 1}, af_span };
+    af_seq slice3[4] = { af_span, af_span, {2, 2, 1}, af_span };
+    // index the array for channels
+    af_array ch1Temp=0, ch2Temp=0, ch3Temp=0;
+    AF_CHECK(af_index(&ch1Temp, in, 4, slice1));
+    AF_CHECK(af_index(&ch2Temp, in, 4, slice2));
+    AF_CHECK(af_index(&ch3Temp, in, 4, slice3));
+    // get Array objects for corresponding channel views
+    Array<T> X = getArray<T>(ch1Temp);
+    Array<T> Y = getArray<T>(ch2Temp);
+    Array<T> Z = getArray<T>(ch3Temp);
+
+    if (isYCbCr2RGB) {
+        dim4 dims = X.dims();
+        Array<T> yc  = createValueArray<T>(dims, 16);
+        Array<T> cc  = createValueArray<T>(dims, 128);
+        Array<T> Y_  = arithOp<T, af_sub_t>(X, yc, dims);
+        Array<T> Cb_ = arithOp<T, af_sub_t>(Y, cc, dims);
+        Array<T> Cr_ = arithOp<T, af_sub_t>(Z, cc, dims);
+        Array<T> R   = mix<T>(Y_, Cr_, INV_219, INV_112*(1-kr));
+        Array<T> G   = mix<T>(Y_, Cr_, Cb_,
+                              INV_219,
+                              INV_112*(kr-1)*kr*invKl,
+                              INV_112*(kb-1)*kb*invKl);
+        Array<T> B   = mix<T>(Y_, Cb_, INV_219, INV_112*(1-kb));
+        // join channels
+        Array<T> RG = join<T, T>(2, R, G);
+        return getHandle(join<T, T>(2, RG, B));
+    } else {
+        Array<T> Ey  = mix<T>(X, Y, Z, kr, kl, kb);
+        Array<T> Ecr = mix<T>(X, Y, Z, 0.5, 0.5*kl/(kr-1), 0.5*kb/(kr-1));
+        Array<T> Ecb = mix<T>(X, Y, Z, 0.5*kr/(kb-1), 0.5*kl/(kb-1), 0.5);
+        Array<T> Y = digitize<T>(Ey, 219.0, 16.0);
+        Array<T> Cr = digitize<T>(Ecr, 224.0, 128.0);
+        Array<T> Cb = digitize<T>(Ecb, 224.0, 128.0);
+        // join channels
+        Array<T> YCb = join<T, T>(2, Y, Cb);
+        return getHandle(join<T, T>(2, YCb, Cr));
+    }
+}
+
+template<bool isYCbCr2RGB>
+af_err convert(af_array* out, const af_array& in, const af_ycc_std standard)
+{
+    try {
+        ArrayInfo info = getInfo(in);
+        af_dtype iType = info.getType();
+        af::dim4 inputDims = info.dims();
+
+        ARG_ASSERT(1, (inputDims.ndims() >= 3));
+
+        af_array output = 0;
+        switch (iType) {
+            case f64: output = convert<double, isYCbCr2RGB>(in, standard); break;
+            case f32: output = convert<float , isYCbCr2RGB>(in, standard); break;
+            default: TYPE_ERROR(1, iType); break;
+        }
+        std::swap(*out, output);
+    }
+    CATCHALL;
+    return AF_SUCCESS;
+}
+
+af_err af_ycbcr2rgb(af_array* out, const af_array in, const af_ycc_std standard)
+{
+    return convert<true>(out, in, standard);
+}
+
+af_err af_rgb2ycbcr(af_array* out, const af_array in, const af_ycc_std standard)
+{
+    return convert<false>(out, in, standard);
+}
diff --git a/src/api/cpp/ycbcr_rgb.cpp b/src/api/cpp/ycbcr_rgb.cpp
new file mode 100644
index 0000000..2716613
--- /dev/null
+++ b/src/api/cpp/ycbcr_rgb.cpp
@@ -0,0 +1,31 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/image.h>
+#include <af/array.h>
+#include "error.hpp"
+
+namespace af
+{
+
+array ycbcr2rgb(const array& in, const YCCStd standard)
+{
+    af_array temp = 0;
+    AF_THROW(af_ycbcr2rgb(&temp, in.get(), standard));
+    return array(temp);
+}
+
+array rgb2ycbcr(const array& in, const YCCStd standard)
+{
+    af_array temp = 0;
+    AF_THROW(af_rgb2ycbcr(&temp, in.get(), standard));
+    return array(temp);
+}
+
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git



More information about the debian-science-commits mailing list