blob: a6c0557b79001903662debbc88fa9d076e9d8bd4 [file] [log] [blame]
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +00001/*
Michalis Spyroufae513c2019-10-16 17:41:33 +01002 * Copyright (c) 2017-2019 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
95 for(unsigned int plane_idx = 0; plane_idx < dst.size(); ++plane_idx)
96 {
Michalis Spyroufae513c2019-10-16 17:41:33 +010097 SimpleTensor<T> &dst_tensor = dst[plane_idx];
98 const uint32_t num_elements = dst_tensor.num_elements();
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +000099
Michalis Spyroufae513c2019-10-16 17:41:33 +0100100 for(uint32_t element_idx = 0; element_idx < num_elements; ++element_idx)
Ioan-Cristian Szaboae3c8ab2017-11-16 17:55:03 +0000101 {
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