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 29namespace XCam { 30 31typedef uint8_t Uchar; 32typedef int8_t Char; 33typedef Vector2<uint8_t> Uchar2; 34typedef Vector2<int8_t> Char2; 35typedef Vector2<float> Float2; 36typedef Vector2<int> Int2; 37 38enum BorderType { 39 BorderTypeNearest, 40 BorderTypeConst, 41 BorderTypeRewind, 42}; 43 44template <typename T> 45class SoftImage 46{ 47public: 48 typedef T Type; 49private: 50 uint8_t *_buf_ptr; 51 uint32_t _width; 52 uint32_t _height; 53 uint32_t _pitch; 54 55 SmartPtr<VideoBuffer> _bind; 56 57public: 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 66 ~SoftImage () { 67 if (!_bind.ptr ()) { 68 xcam_free (_buf_ptr); 69 } 70 } 71 72 uint32_t pixel_size () const { 73 return sizeof (T); 74 } 75 76 uint32_t get_width () const { 77 return _width; 78 } 79 uint32_t get_height () const { 80 return _height; 81 } 82 uint32_t get_pitch () const { 83 return _pitch; 84 } 85 bool is_valid () const { 86 return (_buf_ptr && _width && _height); 87 } 88 89 const SmartPtr<VideoBuffer> &get_bind_buf () const { 90 return _bind; 91 } 92 T *get_buf_ptr (int32_t x, int32_t y) { 93 return (T *)(_buf_ptr + y * _pitch) + x; 94 } 95 const T *get_buf_ptr (int32_t x, int32_t y) const { 96 return (const T *)(_buf_ptr + y * _pitch) + x; 97 } 98 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 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> 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> 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> 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> 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 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 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> 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> 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 192private: 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 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 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 210template <typename T> 211SoftImage<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 232template <typename T> 233SoftImage<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 250template <typename T> 251SoftImage<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 264template <typename T> 265inline 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 271template <typename T, uint32_t N> 272inline 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 278template <typename Vec2> 279inline Uchar2 convert_to_uchar2 (const Vec2& v) { 280 return Uchar2 (convert_to_uchar(v.x), convert_to_uchar(v.y)); 281} 282 283template <typename Vec2, uint32_t N> 284inline 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 291typedef SoftImage<Uchar> UcharImage; 292typedef SoftImage<Uchar2> Uchar2Image; 293typedef SoftImage<float> FloatImage; 294typedef SoftImage<Float2> Float2Image; 295 296template <class SoftImageT> 297class SoftImageFile 298 : public FileHandle 299{ 300public: 301 SoftImageFile () {} 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 310template <class SoftImageT> 311inline XCamReturn 312SoftImageFile<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 335template <class SoftImageT> 336inline XCamReturn 337SoftImageFile<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 360template <typename T> template <typename O> 361O 362SoftImage<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 374template <typename T> template<typename O, uint32_t N> 375void 376SoftImage<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