1 /*
2 * soft_image.h - soft image class
3 *
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #ifndef XCAM_SOFT_IMAGE_H
22 #define XCAM_SOFT_IMAGE_H
23
24 #include <xcam_std.h>
25 #include <video_buffer.h>
26 #include <vec_mat.h>
27 #include <file_handle.h>
28
29 namespace XCam {
30
31 typedef uint8_t Uchar;
32 typedef int8_t Char;
33 typedef Vector2<uint8_t> Uchar2;
34 typedef Vector2<int8_t> Char2;
35 typedef Vector2<float> Float2;
36 typedef Vector2<int> Int2;
37
38 enum BorderType {
39 BorderTypeNearest,
40 BorderTypeConst,
41 BorderTypeRewind,
42 };
43
44 template <typename T>
45 class SoftImage
46 {
47 public:
48 typedef T Type;
49 private:
50 uint8_t *_buf_ptr;
51 uint32_t _width;
52 uint32_t _height;
53 uint32_t _pitch;
54
55 SmartPtr<VideoBuffer> _bind;
56
57 public:
58 explicit SoftImage (const SmartPtr<VideoBuffer> &buf, const uint32_t plane);
59 explicit SoftImage (
60 const uint32_t width, const uint32_t height,
61 uint32_t aligned_width = 0);
62 explicit SoftImage (
63 const SmartPtr<VideoBuffer> &buf,
64 const uint32_t width, const uint32_t height, const uint32_t pictch, const uint32_t offset = 0);
65
~SoftImage()66 ~SoftImage () {
67 if (!_bind.ptr ()) {
68 xcam_free (_buf_ptr);
69 }
70 }
71
pixel_size()72 uint32_t pixel_size () const {
73 return sizeof (T);
74 }
75
get_width()76 uint32_t get_width () const {
77 return _width;
78 }
get_height()79 uint32_t get_height () const {
80 return _height;
81 }
get_pitch()82 uint32_t get_pitch () const {
83 return _pitch;
84 }
is_valid()85 bool is_valid () const {
86 return (_buf_ptr && _width && _height);
87 }
88
get_bind_buf()89 const SmartPtr<VideoBuffer> &get_bind_buf () const {
90 return _bind;
91 }
get_buf_ptr(int32_t x,int32_t y)92 T *get_buf_ptr (int32_t x, int32_t y) {
93 return (T *)(_buf_ptr + y * _pitch) + x;
94 }
get_buf_ptr(int32_t x,int32_t y)95 const T *get_buf_ptr (int32_t x, int32_t y) const {
96 return (const T *)(_buf_ptr + y * _pitch) + x;
97 }
98
read_data_no_check(int32_t x,int32_t y)99 inline T read_data_no_check (int32_t x, int32_t y) const {
100 const T *t_ptr = (const T *)(_buf_ptr + y * _pitch);
101 return t_ptr[x];
102 }
103
read_data(int32_t x,int32_t y)104 inline T read_data (int32_t x, int32_t y) const {
105 border_check (x, y);
106 return read_data_no_check (x, y);
107 }
108
109 template<typename O>
110 inline O read_interpolate_data (float x, float y) const;
111
112 template<typename O, uint32_t N>
113 inline void read_interpolate_array (Float2 *pos, O *array) const;
114
115 template<uint32_t N>
read_array_no_check(const int32_t x,const int32_t y,T * array)116 inline void read_array_no_check (const int32_t x, const int32_t y, T *array) const {
117 XCAM_ASSERT (N <= 8);
118 const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch)) + x;
119 memcpy (array, t_ptr, sizeof (T) * N);
120 }
121
122 template<typename O, uint32_t N>
read_array_no_check(const int32_t x,const int32_t y,O * array)123 inline void read_array_no_check (const int32_t x, const int32_t y, O *array) const {
124 XCAM_ASSERT (N <= 8);
125 const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch)) + x;
126 for (uint32_t i = 0; i < N; ++i) {
127 array[i] = t_ptr[i];
128 }
129 }
130
131 template<uint32_t N>
read_array(int32_t x,int32_t y,T * array)132 inline void read_array (int32_t x, int32_t y, T *array) const {
133 XCAM_ASSERT (N <= 8);
134 border_check_y (y);
135 if (x + N < _width) {
136 read_array_no_check<N> (x, y, array);
137 } else {
138 const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch));
139 for (uint32_t i = 0; i < N; ++i, ++x) {
140 border_check_x (x);
141 array[i] = t_ptr[x];
142 }
143 }
144 }
145
146 template<typename O, uint32_t N>
read_array(int32_t x,int32_t y,O * array)147 inline void read_array (int32_t x, int32_t y, O *array) const {
148 XCAM_ASSERT (N <= 8);
149 border_check_y (y);
150 const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch));
151 for (uint32_t i = 0; i < N; ++i, ++x) {
152 border_check_x (x);
153 array[i] = t_ptr[x];
154 }
155 }
156
write_data(int32_t x,int32_t y,const T & v)157 inline void write_data (int32_t x, int32_t y, const T &v) {
158 if (x < 0 || x >= (int32_t)_width)
159 return;
160 if (y < 0 || y >= (int32_t)_height)
161 return;
162 write_data_no_check (x, y, v);
163 }
164
write_data_no_check(int32_t x,int32_t y,const T & v)165 inline void write_data_no_check (int32_t x, int32_t y, const T &v) {
166 T *t_ptr = (T *)(_buf_ptr + y * _pitch);
167 t_ptr[x] = v;
168 }
169
170 template<uint32_t N>
write_array_no_check(int32_t x,int32_t y,const T * array)171 inline void write_array_no_check (int32_t x, int32_t y, const T *array) {
172 T *t_ptr = (T *)(_buf_ptr + y * _pitch);
173 memcpy (t_ptr + x, array, sizeof (T) * N);
174 }
175
176 template<uint32_t N>
write_array(int32_t x,int32_t y,const T * array)177 inline void write_array (int32_t x, int32_t y, const T *array) {
178 if (y < 0 || y >= (int32_t)_height)
179 return;
180
181 if (x >= 0 && x + N <= _width) {
182 write_array_no_check<N> (x, y, array);
183 } else {
184 T *t_ptr = ((T *)(_buf_ptr + y * _pitch));
185 for (uint32_t i = 0; i < N; ++i, ++x) {
186 if (x < 0 || x >= (int32_t)_width) continue;
187 t_ptr[x] = array[i];
188 }
189 }
190 }
191
192 private:
border_check_x(int32_t & x)193 inline void border_check_x (int32_t &x) const {
194 if (x < 0) x = 0;
195 else if (x >= (int32_t)_width) x = (int32_t)(_width - 1);
196 }
197
border_check_y(int32_t & y)198 inline void border_check_y (int32_t &y) const {
199 if (y < 0) y = 0;
200 else if (y >= (int32_t)_height) y = (int32_t)(_height - 1);
201 }
202
border_check(int32_t & x,int32_t & y)203 inline void border_check (int32_t &x, int32_t &y) const {
204 border_check_x (x);
205 border_check_y (y);
206 }
207 };
208
209
210 template <typename T>
SoftImage(const SmartPtr<VideoBuffer> & buf,const uint32_t plane)211 SoftImage<T>::SoftImage (const SmartPtr<VideoBuffer> &buf, const uint32_t plane)
212 : _buf_ptr (NULL)
213 , _width (0) , _height (0) , _pitch (0)
214 {
215 XCAM_ASSERT (buf.ptr ());
216 const VideoBufferInfo &info = buf->get_video_info ();
217 VideoBufferPlanarInfo planar;
218 if (!info.get_planar_info(planar, plane)) {
219 XCAM_LOG_ERROR (
220 "videobuf to soft image failed. buf format:%s, plane:%d", xcam_fourcc_to_string (info.format), plane);
221 return;
222 }
223 _buf_ptr = buf->map () + info.offsets[plane];
224 XCAM_ASSERT (_buf_ptr);
225 _pitch = info.strides[plane];
226 _height = planar.height;
227 _width = planar.pixel_bytes * planar.width / sizeof (T);
228 XCAM_ASSERT (_width * sizeof(T) == planar.pixel_bytes * planar.width);
229 _bind = buf;
230 }
231
232 template <typename T>
SoftImage(const uint32_t width,const uint32_t height,uint32_t aligned_width)233 SoftImage<T>::SoftImage (
234 const uint32_t width, const uint32_t height, uint32_t aligned_width)
235 : _buf_ptr (NULL)
236 , _width (0) , _height (0) , _pitch (0)
237 {
238 if (!aligned_width)
239 aligned_width = width;
240
241 XCAM_ASSERT (aligned_width >= width);
242 XCAM_ASSERT (width > 0 && height > 0);
243 _pitch = aligned_width * sizeof (T);
244 _buf_ptr = (uint8_t *)xcam_malloc (_pitch * height);
245 XCAM_ASSERT (_buf_ptr);
246 _width = width;
247 _height = height;
248 }
249
250 template <typename T>
SoftImage(const SmartPtr<VideoBuffer> & buf,const uint32_t width,const uint32_t height,const uint32_t pictch,const uint32_t offset)251 SoftImage<T>::SoftImage (
252 const SmartPtr<VideoBuffer> &buf,
253 const uint32_t width, const uint32_t height, const uint32_t pictch, const uint32_t offset)
254 : _buf_ptr (NULL)
255 , _width (width) , _height (height)
256 , _pitch (pictch)
257 , _bind (buf)
258 {
259 XCAM_ASSERT (buf.ptr ());
260 XCAM_ASSERT (buf->map ());
261 _buf_ptr = buf->map () + offset;
262 }
263
264 template <typename T>
convert_to_uchar(const T & v)265 inline Uchar convert_to_uchar (const T& v) {
266 if (v < 0.0f) return 0;
267 else if (v > 255.0f) return 255;
268 return (Uchar)(v + 0.5f);
269 }
270
271 template <typename T, uint32_t N>
convert_to_uchar_N(const T * in,Uchar * out)272 inline void convert_to_uchar_N (const T *in, Uchar *out) {
273 for (uint32_t i = 0; i < N; ++i) {
274 out[i] = convert_to_uchar<T> (in[i]);
275 }
276 }
277
278 template <typename Vec2>
convert_to_uchar2(const Vec2 & v)279 inline Uchar2 convert_to_uchar2 (const Vec2& v) {
280 return Uchar2 (convert_to_uchar(v.x), convert_to_uchar(v.y));
281 }
282
283 template <typename Vec2, uint32_t N>
convert_to_uchar2_N(const Vec2 * in,Uchar2 * out)284 inline void convert_to_uchar2_N (const Vec2 *in, Uchar2 *out) {
285 for (uint32_t i = 0; i < N; ++i) {
286 out[i].x = convert_to_uchar (in[i].x);
287 out[i].y = convert_to_uchar (in[i].y);
288 }
289 }
290
291 typedef SoftImage<Uchar> UcharImage;
292 typedef SoftImage<Uchar2> Uchar2Image;
293 typedef SoftImage<float> FloatImage;
294 typedef SoftImage<Float2> Float2Image;
295
296 template <class SoftImageT>
297 class SoftImageFile
298 : public FileHandle
299 {
300 public:
SoftImageFile()301 SoftImageFile () {}
SoftImageFile(const char * name,const char * option)302 explicit SoftImageFile (const char *name, const char *option)
303 : FileHandle (name, option)
304 {}
305
306 inline XCamReturn read_buf (const SmartPtr<SoftImageT> &buf);
307 inline XCamReturn write_buf (const SmartPtr<SoftImageT> &buf);
308 };
309
310 template <class SoftImageT>
311 inline XCamReturn
read_buf(const SmartPtr<SoftImageT> & buf)312 SoftImageFile<SoftImageT>::read_buf (const SmartPtr<SoftImageT> &buf)
313 {
314 XCAM_FAIL_RETURN (
315 WARNING, is_valid (), XCAM_RETURN_ERROR_PARAM,
316 "soft image file(%s) read buf failed, file is not open", XCAM_STR (get_file_name ()));
317
318 XCAM_FAIL_RETURN (
319 WARNING, buf->is_valid (), XCAM_RETURN_ERROR_PARAM,
320 "soft image file(%s) read buf failed, buf is not valid", XCAM_STR (get_file_name ()));
321
322 XCAM_ASSERT (is_valid ());
323 uint32_t height = buf->get_height ();
324 uint32_t line_bytes = buf->get_width () * buf->pixel_size ();
325
326 for (uint32_t index = 0; index < height; index++) {
327 uint8_t *line_ptr = buf->get_buf_ptr (0, index);
328 XCAM_FAIL_RETURN (
329 WARNING, fread (line_ptr, 1, line_bytes, _fp) == line_bytes, XCAM_RETURN_ERROR_FILE,
330 "soft image file(%s) read buf failed, image_line:%d", XCAM_STR (get_file_name ()), index);
331 }
332 return XCAM_RETURN_NO_ERROR;
333 }
334
335 template <class SoftImageT>
336 inline XCamReturn
write_buf(const SmartPtr<SoftImageT> & buf)337 SoftImageFile<SoftImageT>::write_buf (const SmartPtr<SoftImageT> &buf)
338 {
339 XCAM_FAIL_RETURN (
340 WARNING, is_valid (), XCAM_RETURN_ERROR_PARAM,
341 "soft image file(%s) write buf failed, file is not open", XCAM_STR (get_file_name ()));
342
343 XCAM_FAIL_RETURN (
344 WARNING, buf->is_valid (), XCAM_RETURN_ERROR_PARAM,
345 "soft image file(%s) write buf failed, buf is not valid", XCAM_STR (get_file_name ()));
346
347 XCAM_ASSERT (is_valid ());
348 uint32_t height = buf->get_height ();
349 uint32_t line_bytes = buf->get_width () * buf->pixel_size ();
350
351 for (uint32_t index = 0; index < height; index++) {
352 uint8_t *line_ptr = buf->get_buf_ptr (0, index);
353 XCAM_FAIL_RETURN (
354 WARNING, fwrite (line_ptr, 1, line_bytes, _fp) == line_bytes, XCAM_RETURN_ERROR_FILE,
355 "soft image file(%s) write buf failed, image_line:%d", XCAM_STR (get_file_name ()), index);
356 }
357 return XCAM_RETURN_NO_ERROR;
358 }
359
360 template <typename T> template <typename O>
361 O
read_interpolate_data(float x,float y)362 SoftImage<T>::read_interpolate_data (float x, float y) const
363 {
364 int32_t x0 = (int32_t)(x), y0 = (int32_t)(y);
365 float a = x - x0, b = y - y0;
366 O l0[2], l1[2];
367 read_array<O, 2> (x0, y0, l0);
368 read_array<O, 2> (x0, y0 + 1, l1);
369
370 return l1[1] * (a * b) + l0[0] * ((1 - a) * (1 - b)) +
371 l1[0] * ((1 - a) * b) + l0[1] * (a * (1 - b));
372 }
373
374 template <typename T> template<typename O, uint32_t N>
375 void
read_interpolate_array(Float2 * pos,O * array)376 SoftImage<T>::read_interpolate_array (Float2 *pos, O *array) const
377 {
378 for (uint32_t i = 0; i < N; ++i) {
379 array[i] = read_interpolate_data<O> (pos[i].x, pos[i].y);
380 }
381 }
382
383 }
384 #endif //XCAM_SOFT_IMAGE_H
385