blob: c1ec3ec5782e9035dd29d574538eafb3c6756e70 [file] [log] [blame]
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +00001/*
2 * Copyright (c) 2017-2018 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"
27#include "tests/validation/FixedPoint.h"
28#include "tests/validation/Helpers.h"
29
30namespace arm_compute
31{
32namespace test
33{
34namespace validation
35{
36namespace reference
37{
38namespace
39{
40template <typename T>
41inline std::vector<SimpleTensor<T>> create_image_planes(const TensorShape &shape, Format format)
42{
43 TensorShape image_shape = adjust_odd_shape(shape, format);
44
45 std::vector<SimpleTensor<T>> image_planes;
46
47 switch(format)
48 {
49 case Format::RGB888:
50 case Format::RGBA8888:
51 case Format::YUYV422:
52 case Format::UYVY422:
53 {
54 image_planes.emplace_back(image_shape, format);
55 break;
56 }
57 case Format::NV12:
58 case Format::NV21:
59 {
60 TensorShape shape_uv88 = calculate_subsampled_shape(image_shape, Format::UV88);
61
62 image_planes.emplace_back(image_shape, Format::U8);
63 image_planes.emplace_back(shape_uv88, Format::UV88);
64 break;
65 }
66 case Format::IYUV:
67 {
68 TensorShape shape_sub2 = calculate_subsampled_shape(image_shape, Format::IYUV);
69
70 image_planes.emplace_back(image_shape, Format::U8);
71 image_planes.emplace_back(shape_sub2, Format::U8);
72 image_planes.emplace_back(shape_sub2, Format::U8);
73 break;
74 }
75 case Format::YUV444:
76 {
77 image_planes.emplace_back(image_shape, Format::U8);
78 image_planes.emplace_back(image_shape, Format::U8);
79 image_planes.emplace_back(image_shape, Format::U8);
80 break;
81 }
82 default:
83 ARM_COMPUTE_ERROR("Not supported");
84 break;
85 }
86
87 return image_planes;
88}
89} // namespace
90
91template <typename T>
92std::vector<SimpleTensor<T>> channel_combine(const TensorShape &shape, const std::vector<SimpleTensor<T>> &image_planes, Format format)
93{
94 std::vector<SimpleTensor<T>> dst = create_image_planes<T>(shape, format);
95
96 for(unsigned int plane_idx = 0; plane_idx < dst.size(); ++plane_idx)
97 {
98 SimpleTensor<T> &dst_tensor = dst[plane_idx];
99
100 for(int element_idx = 0; element_idx < dst_tensor.num_elements(); ++element_idx)
101 {
102 Coordinates coord = index2coord(dst_tensor.shape(), element_idx);
103
104 switch(format)
105 {
106 case Format::RGB888:
107 case Format::RGBA8888:
108 {
109 // Copy R/G/B or A channel
110 for(int channel_idx = 0; channel_idx < dst_tensor.num_channels(); ++channel_idx)
111 {
112 const T &src_value = reinterpret_cast<const T *>(image_planes[channel_idx](coord))[0];
113 T &dst_value = reinterpret_cast<T *>(dst_tensor(coord))[channel_idx];
114
115 dst_value = src_value;
116 }
117 break;
118 }
119 case Format::YUYV422:
120 case Format::UYVY422:
121 {
122 // Find coordinates of the sub-sampled pixel
123 const Coordinates coord_hori(coord.x() / 2, coord.y());
124
125 const T &src0 = reinterpret_cast<const T *>(image_planes[0](coord))[0];
126 const T &src1 = reinterpret_cast<const T *>(image_planes[1](coord_hori))[0];
127
128 const int shift = (Format::YUYV422 == format) ? 1 : 0;
129 T &dst0 = reinterpret_cast<T *>(dst_tensor(coord))[1 - shift];
130 T &dst1 = reinterpret_cast<T *>(dst_tensor(coord))[0 + shift];
131
132 dst0 = src0;
133 dst1 = src1;
134
135 Coordinates coord2 = index2coord(dst_tensor.shape(), ++element_idx);
136
137 const T &src2 = reinterpret_cast<const T *>(image_planes[0](coord2))[0];
138 const T &src3 = reinterpret_cast<const T *>(image_planes[2](coord_hori))[0];
139
140 T &dst2 = reinterpret_cast<T *>(dst_tensor(coord2))[1 - shift];
141 T &dst3 = reinterpret_cast<T *>(dst_tensor(coord2))[0 + shift];
142
143 dst2 = src2;
144 dst3 = src3;
145
146 break;
147 }
148 case Format::NV12:
149 case Format::NV21:
150 {
151 if(0U == plane_idx)
152 {
153 // Get and combine Y channel from plane0 of destination multi-image
154 dst_tensor[element_idx] = image_planes[0][element_idx];
155 }
156 else
157 {
158 const int shift = (Format::NV12 == format) ? 0 : 1;
159
160 // Get U channel from plane1 and V channel from plane2 of the source
161 const T &src_u0 = reinterpret_cast<const T *>(image_planes[1](coord))[0];
162 const T &src_v0 = reinterpret_cast<const T *>(image_planes[2](coord))[0];
163
164 // Get U and V channel from plane1 of destination multi-image
165 T &dst_u0 = reinterpret_cast<T *>(dst_tensor(coord))[0 + shift];
166 T &dst_v0 = reinterpret_cast<T *>(dst_tensor(coord))[1 - shift];
167
168 // Combine channel U and V
169 dst_u0 = src_u0;
170 dst_v0 = src_v0;
171 }
172
173 break;
174 }
175 case Format::IYUV:
176 case Format::YUV444:
177 {
178 // Get Y/U/V element
179 const T &src = reinterpret_cast<const T *>(image_planes[plane_idx](coord))[0];
180 T &dst = reinterpret_cast<T *>(dst_tensor(coord))[0];
181
182 // Copy Y/U/V plane
183 dst = src;
184
185 break;
186 }
187 default:
188 ARM_COMPUTE_ERROR("Not supported");
189 break;
190 }
191 }
192 }
193
194 return dst;
195}
196
197template std::vector<SimpleTensor<uint8_t>> channel_combine(const TensorShape &shape, const std::vector<SimpleTensor<uint8_t>> &image_planes, Format format);
198} // namespace reference
199} // namespace validation
200} // namespace test
201} // namespace arm_compute