blob: b76dcaca8c3cca3e80d293bec19c07fea8724f80 [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"
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 {
97 SimpleTensor<T> &dst_tensor = dst[plane_idx];
98
99 for(int element_idx = 0; element_idx < dst_tensor.num_elements(); ++element_idx)
100 {
101 Coordinates coord = index2coord(dst_tensor.shape(), element_idx);
102
103 switch(format)
104 {
105 case Format::RGB888:
106 case Format::RGBA8888:
107 {
108 // Copy R/G/B or A channel
109 for(int channel_idx = 0; channel_idx < dst_tensor.num_channels(); ++channel_idx)
110 {
111 const T &src_value = reinterpret_cast<const T *>(image_planes[channel_idx](coord))[0];
112 T &dst_value = reinterpret_cast<T *>(dst_tensor(coord))[channel_idx];
113
114 dst_value = src_value;
115 }
116 break;
117 }
118 case Format::YUYV422:
119 case Format::UYVY422:
120 {
121 // Find coordinates of the sub-sampled pixel
122 const Coordinates coord_hori(coord.x() / 2, coord.y());
123
124 const T &src0 = reinterpret_cast<const T *>(image_planes[0](coord))[0];
125 const T &src1 = reinterpret_cast<const T *>(image_planes[1](coord_hori))[0];
126
127 const int shift = (Format::YUYV422 == format) ? 1 : 0;
128 T &dst0 = reinterpret_cast<T *>(dst_tensor(coord))[1 - shift];
129 T &dst1 = reinterpret_cast<T *>(dst_tensor(coord))[0 + shift];
130
131 dst0 = src0;
132 dst1 = src1;
133
134 Coordinates coord2 = index2coord(dst_tensor.shape(), ++element_idx);
135
136 const T &src2 = reinterpret_cast<const T *>(image_planes[0](coord2))[0];
137 const T &src3 = reinterpret_cast<const T *>(image_planes[2](coord_hori))[0];
138
139 T &dst2 = reinterpret_cast<T *>(dst_tensor(coord2))[1 - shift];
140 T &dst3 = reinterpret_cast<T *>(dst_tensor(coord2))[0 + shift];
141
142 dst2 = src2;
143 dst3 = src3;
144
145 break;
146 }
147 case Format::NV12:
148 case Format::NV21:
149 {
150 if(0U == plane_idx)
151 {
152 // Get and combine Y channel from plane0 of destination multi-image
153 dst_tensor[element_idx] = image_planes[0][element_idx];
154 }
155 else
156 {
157 const int shift = (Format::NV12 == format) ? 0 : 1;
158
159 // Get U channel from plane1 and V channel from plane2 of the source
160 const T &src_u0 = reinterpret_cast<const T *>(image_planes[1](coord))[0];
161 const T &src_v0 = reinterpret_cast<const T *>(image_planes[2](coord))[0];
162
163 // Get U and V channel from plane1 of destination multi-image
164 T &dst_u0 = reinterpret_cast<T *>(dst_tensor(coord))[0 + shift];
165 T &dst_v0 = reinterpret_cast<T *>(dst_tensor(coord))[1 - shift];
166
167 // Combine channel U and V
168 dst_u0 = src_u0;
169 dst_v0 = src_v0;
170 }
171
172 break;
173 }
174 case Format::IYUV:
175 case Format::YUV444:
176 {
177 // Get Y/U/V element
178 const T &src = reinterpret_cast<const T *>(image_planes[plane_idx](coord))[0];
179 T &dst = reinterpret_cast<T *>(dst_tensor(coord))[0];
180
181 // Copy Y/U/V plane
182 dst = src;
183
184 break;
185 }
186 default:
187 ARM_COMPUTE_ERROR("Not supported");
188 break;
189 }
190 }
191 }
192
193 return dst;
194}
195
196template std::vector<SimpleTensor<uint8_t>> channel_combine(const TensorShape &shape, const std::vector<SimpleTensor<uint8_t>> &image_planes, Format format);
197} // namespace reference
198} // namespace validation
199} // namespace test
200} // namespace arm_compute