Compute Library
 21.02
ChannelCombine.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "ChannelCombine.h"
25 
26 #include "arm_compute/core/Types.h"
28 
29 namespace arm_compute
30 {
31 namespace test
32 {
33 namespace validation
34 {
35 namespace reference
36 {
37 namespace
38 {
39 template <typename T>
40 inline std::vector<SimpleTensor<T>> create_image_planes(const TensorShape &shape, Format format)
41 {
42  TensorShape image_shape = adjust_odd_shape(shape, format);
43 
44  std::vector<SimpleTensor<T>> image_planes;
45 
46  switch(format)
47  {
48  case Format::RGB888:
49  case Format::RGBA8888:
50  case Format::YUYV422:
51  case Format::UYVY422:
52  {
53  image_planes.emplace_back(image_shape, format);
54  break;
55  }
56  case Format::NV12:
57  case Format::NV21:
58  {
59  TensorShape shape_uv88 = calculate_subsampled_shape(image_shape, Format::UV88);
60 
61  image_planes.emplace_back(image_shape, Format::U8);
62  image_planes.emplace_back(shape_uv88, Format::UV88);
63  break;
64  }
65  case Format::IYUV:
66  {
67  TensorShape shape_sub2 = calculate_subsampled_shape(image_shape, Format::IYUV);
68 
69  image_planes.emplace_back(image_shape, Format::U8);
70  image_planes.emplace_back(shape_sub2, Format::U8);
71  image_planes.emplace_back(shape_sub2, Format::U8);
72  break;
73  }
74  case Format::YUV444:
75  {
76  image_planes.emplace_back(image_shape, Format::U8);
77  image_planes.emplace_back(image_shape, Format::U8);
78  image_planes.emplace_back(image_shape, Format::U8);
79  break;
80  }
81  default:
82  ARM_COMPUTE_ERROR("Not supported");
83  break;
84  }
85 
86  return image_planes;
87 }
88 } // namespace
89 
90 template <typename T>
91 std::vector<SimpleTensor<T>> channel_combine(const TensorShape &shape, const std::vector<SimpleTensor<T>> &image_planes, Format format)
92 {
93  std::vector<SimpleTensor<T>> dst = create_image_planes<T>(shape, format);
94 
95 #if defined(_OPENMP)
96  #pragma omp parallel for
97 #endif /* _OPENMP */
98  for(unsigned int plane_idx = 0; plane_idx < dst.size(); ++plane_idx)
99  {
100  SimpleTensor<T> &dst_tensor = dst[plane_idx];
101  const uint32_t num_elements = dst_tensor.num_elements();
102 
103  for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
104  {
105  Coordinates coord = index2coord(dst_tensor.shape(), element_idx);
106 
107  switch(format)
108  {
109  case Format::RGB888:
110  case Format::RGBA8888:
111  {
112  // Copy R/G/B or A channel
113  for(int channel_idx = 0; channel_idx < dst_tensor.num_channels(); ++channel_idx)
114  {
115  const T &src_value = reinterpret_cast<const T *>(image_planes[channel_idx](coord))[0];
116  T &dst_value = reinterpret_cast<T *>(dst_tensor(coord))[channel_idx];
117 
118  dst_value = src_value;
119  }
120  break;
121  }
122  case Format::YUYV422:
123  case Format::UYVY422:
124  {
125  // Find coordinates of the sub-sampled pixel
126  const Coordinates coord_hori(coord.x() / 2, coord.y());
127 
128  const T &src0 = reinterpret_cast<const T *>(image_planes[0](coord))[0];
129  const T &src1 = reinterpret_cast<const T *>(image_planes[1](coord_hori))[0];
130 
131  const int shift = (Format::YUYV422 == format) ? 1 : 0;
132  T &dst0 = reinterpret_cast<T *>(dst_tensor(coord))[1 - shift];
133  T &dst1 = reinterpret_cast<T *>(dst_tensor(coord))[0 + shift];
134 
135  dst0 = src0;
136  dst1 = src1;
137 
138  Coordinates coord2 = index2coord(dst_tensor.shape(), ++element_idx);
139 
140  const T &src2 = reinterpret_cast<const T *>(image_planes[0](coord2))[0];
141  const T &src3 = reinterpret_cast<const T *>(image_planes[2](coord_hori))[0];
142 
143  T &dst2 = reinterpret_cast<T *>(dst_tensor(coord2))[1 - shift];
144  T &dst3 = reinterpret_cast<T *>(dst_tensor(coord2))[0 + shift];
145 
146  dst2 = src2;
147  dst3 = src3;
148 
149  break;
150  }
151  case Format::NV12:
152  case Format::NV21:
153  {
154  if(0U == plane_idx)
155  {
156  // Get and combine Y channel from plane0 of destination multi-image
157  dst_tensor[element_idx] = image_planes[0][element_idx];
158  }
159  else
160  {
161  const int shift = (Format::NV12 == format) ? 0 : 1;
162 
163  // Get U channel from plane1 and V channel from plane2 of the source
164  const T &src_u0 = reinterpret_cast<const T *>(image_planes[1](coord))[0];
165  const T &src_v0 = reinterpret_cast<const T *>(image_planes[2](coord))[0];
166 
167  // Get U and V channel from plane1 of destination multi-image
168  T &dst_u0 = reinterpret_cast<T *>(dst_tensor(coord))[0 + shift];
169  T &dst_v0 = reinterpret_cast<T *>(dst_tensor(coord))[1 - shift];
170 
171  // Combine channel U and V
172  dst_u0 = src_u0;
173  dst_v0 = src_v0;
174  }
175 
176  break;
177  }
178  case Format::IYUV:
179  case Format::YUV444:
180  {
181  // Get Y/U/V element
182  const T &src = reinterpret_cast<const T *>(image_planes[plane_idx](coord))[0];
183  T &dst = reinterpret_cast<T *>(dst_tensor(coord))[0];
184 
185  // Copy Y/U/V plane
186  dst = src;
187 
188  break;
189  }
190  default:
191  ARM_COMPUTE_ERROR("Not supported");
192  break;
193  }
194  }
195  }
196 
197  return dst;
198 }
199 
200 template std::vector<SimpleTensor<uint8_t>> channel_combine(const TensorShape &shape, const std::vector<SimpleTensor<uint8_t>> &image_planes, Format format);
201 } // namespace reference
202 } // namespace validation
203 } // namespace test
204 } // namespace arm_compute
A single plane of 32-bit macro pixel of U0, Y0, V0, Y1 byte.
Shape of a tensor.
Definition: TensorShape.h:39
TensorShape calculate_subsampled_shape(const TensorShape &shape, Format format, Channel channel=Channel::UNKNOWN)
Calculate subsampled shape for a given format and channel.
Definition: Utils.h:774
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
1 channel, 1 U8 per channel
A 2 plane YUV format of Luma (Y) and interleaved UV data at 4:2:0 sampling.
TensorShape shape() const override
Shape of the tensor.
Definition: SimpleTensor.h:320
A 2 plane YUV format of Luma (Y) and interleaved VU data at 4:2:0 sampling.
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2021 Arm Limited.
T x() const
Alias to access the size of the first dimension.
Definition: Dimensions.h:87
3 channels, 1 U8 per channel
Format
Image colour formats.
Definition: Types.h:54
Coordinates of an item.
Definition: Coordinates.h:37
std::vector< SimpleTensor< T > > channel_combine(const TensorShape &shape, const std::vector< SimpleTensor< T >> &image_planes, Format format)
A 3 plane of 8 bit 4:4:4 sampled Y, U, V planes.
Coordinates index2coord(const TensorShape &shape, int index)
Convert a linear index into n-dimensional coordinates.
Definition: Utils.h:460
TensorShape adjust_odd_shape(const TensorShape &shape, Format format)
Adjust tensor shape size if width or height are odd for a given multi-planar format.
Definition: Utils.h:747
A 3 plane of 8-bit 4:2:0 sampled Y, U, V planes.
Simple tensor object that stores elements in a consecutive chunk of memory.
Definition: SimpleTensor.h:58
int num_channels() const override
Number of channels of the tensor.
Definition: SimpleTensor.h:370
4 channels, 1 U8 per channel
2 channel, 1 U8 per channel
int num_elements() const override
Number of elements of the tensor.
Definition: SimpleTensor.h:406
T y() const
Alias to access the size of the second dimension.
Definition: Dimensions.h:92
A single plane of 32-bit macro pixel of Y0, U0, Y1, V0 bytes.