blob: dcd4cf551b570978789e0ed7b1f46f994f028307 [file] [log] [blame]
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +00001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2020 Arm Limited.
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +00003 *
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"
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +000027#include "tests/validation/Helpers.h"
28
29namespace arm_compute
30{
31namespace test
32{
33namespace validation
34{
35namespace reference
36{
37namespace
38{
39template <typename T>
40inline 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
90template <typename T>
91std::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
Michalis Spyroud1d77222020-04-08 14:10:15 +010095#if defined(_OPENMP)
96 #pragma omp parallel for
97#endif /* _OPENMP */
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +000098 for(unsigned int plane_idx = 0; plane_idx < dst.size(); ++plane_idx)
99 {
Michalis Spyroufae513c2019-10-16 17:41:33 +0100100 SimpleTensor<T> &dst_tensor = dst[plane_idx];
101 const uint32_t num_elements = dst_tensor.num_elements();
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000102
Michalis Spyroufae513c2019-10-16 17:41:33 +0100103 for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000104 {
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
200template 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