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 (at) 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 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 192 private: 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 210 template <typename T> 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> 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> 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> 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> 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> 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> 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: 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 310 template <class SoftImageT> 311 inline XCamReturn 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 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 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 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