| /* |
| * soft_image.h - soft image class |
| * |
| * Copyright (c) 2017 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Author: Wind Yuan <[email protected]> |
| */ |
| |
| #ifndef XCAM_SOFT_IMAGE_H |
| #define XCAM_SOFT_IMAGE_H |
| |
| #include <xcam_std.h> |
| #include <video_buffer.h> |
| #include <vec_mat.h> |
| #include <file_handle.h> |
| |
| namespace XCam { |
| |
| typedef uint8_t Uchar; |
| typedef int8_t Char; |
| typedef Vector2<uint8_t> Uchar2; |
| typedef Vector2<int8_t> Char2; |
| typedef Vector2<float> Float2; |
| typedef Vector2<int> Int2; |
| |
| enum BorderType { |
| BorderTypeNearest, |
| BorderTypeConst, |
| BorderTypeRewind, |
| }; |
| |
| template <typename T> |
| class SoftImage |
| { |
| public: |
| typedef T Type; |
| private: |
| uint8_t *_buf_ptr; |
| uint32_t _width; |
| uint32_t _height; |
| uint32_t _pitch; |
| |
| SmartPtr<VideoBuffer> _bind; |
| |
| public: |
| explicit SoftImage (const SmartPtr<VideoBuffer> &buf, const uint32_t plane); |
| explicit SoftImage ( |
| const uint32_t width, const uint32_t height, |
| uint32_t aligned_width = 0); |
| explicit SoftImage ( |
| const SmartPtr<VideoBuffer> &buf, |
| const uint32_t width, const uint32_t height, const uint32_t pictch, const uint32_t offset = 0); |
| |
| ~SoftImage () { |
| if (!_bind.ptr ()) { |
| xcam_free (_buf_ptr); |
| } |
| } |
| |
| uint32_t pixel_size () const { |
| return sizeof (T); |
| } |
| |
| uint32_t get_width () const { |
| return _width; |
| } |
| uint32_t get_height () const { |
| return _height; |
| } |
| uint32_t get_pitch () const { |
| return _pitch; |
| } |
| bool is_valid () const { |
| return (_buf_ptr && _width && _height); |
| } |
| |
| const SmartPtr<VideoBuffer> &get_bind_buf () const { |
| return _bind; |
| } |
| T *get_buf_ptr (int32_t x, int32_t y) { |
| return (T *)(_buf_ptr + y * _pitch) + x; |
| } |
| const T *get_buf_ptr (int32_t x, int32_t y) const { |
| return (const T *)(_buf_ptr + y * _pitch) + x; |
| } |
| |
| inline T read_data_no_check (int32_t x, int32_t y) const { |
| const T *t_ptr = (const T *)(_buf_ptr + y * _pitch); |
| return t_ptr[x]; |
| } |
| |
| inline T read_data (int32_t x, int32_t y) const { |
| border_check (x, y); |
| return read_data_no_check (x, y); |
| } |
| |
| template<typename O> |
| inline O read_interpolate_data (float x, float y) const; |
| |
| template<typename O, uint32_t N> |
| inline void read_interpolate_array (Float2 *pos, O *array) const; |
| |
| template<uint32_t N> |
| inline void read_array_no_check (const int32_t x, const int32_t y, T *array) const { |
| XCAM_ASSERT (N <= 8); |
| const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch)) + x; |
| memcpy (array, t_ptr, sizeof (T) * N); |
| } |
| |
| template<typename O, uint32_t N> |
| inline void read_array_no_check (const int32_t x, const int32_t y, O *array) const { |
| XCAM_ASSERT (N <= 8); |
| const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch)) + x; |
| for (uint32_t i = 0; i < N; ++i) { |
| array[i] = t_ptr[i]; |
| } |
| } |
| |
| template<uint32_t N> |
| inline void read_array (int32_t x, int32_t y, T *array) const { |
| XCAM_ASSERT (N <= 8); |
| border_check_y (y); |
| if (x + N < _width) { |
| read_array_no_check<N> (x, y, array); |
| } else { |
| const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch)); |
| for (uint32_t i = 0; i < N; ++i, ++x) { |
| border_check_x (x); |
| array[i] = t_ptr[x]; |
| } |
| } |
| } |
| |
| template<typename O, uint32_t N> |
| inline void read_array (int32_t x, int32_t y, O *array) const { |
| XCAM_ASSERT (N <= 8); |
| border_check_y (y); |
| const T *t_ptr = ((const T *)(_buf_ptr + y * _pitch)); |
| for (uint32_t i = 0; i < N; ++i, ++x) { |
| border_check_x (x); |
| array[i] = t_ptr[x]; |
| } |
| } |
| |
| inline void write_data (int32_t x, int32_t y, const T &v) { |
| if (x < 0 || x >= (int32_t)_width) |
| return; |
| if (y < 0 || y >= (int32_t)_height) |
| return; |
| write_data_no_check (x, y, v); |
| } |
| |
| inline void write_data_no_check (int32_t x, int32_t y, const T &v) { |
| T *t_ptr = (T *)(_buf_ptr + y * _pitch); |
| t_ptr[x] = v; |
| } |
| |
| template<uint32_t N> |
| inline void write_array_no_check (int32_t x, int32_t y, const T *array) { |
| T *t_ptr = (T *)(_buf_ptr + y * _pitch); |
| memcpy (t_ptr + x, array, sizeof (T) * N); |
| } |
| |
| template<uint32_t N> |
| inline void write_array (int32_t x, int32_t y, const T *array) { |
| if (y < 0 || y >= (int32_t)_height) |
| return; |
| |
| if (x >= 0 && x + N <= _width) { |
| write_array_no_check<N> (x, y, array); |
| } else { |
| T *t_ptr = ((T *)(_buf_ptr + y * _pitch)); |
| for (uint32_t i = 0; i < N; ++i, ++x) { |
| if (x < 0 || x >= (int32_t)_width) continue; |
| t_ptr[x] = array[i]; |
| } |
| } |
| } |
| |
| private: |
| inline void border_check_x (int32_t &x) const { |
| if (x < 0) x = 0; |
| else if (x >= (int32_t)_width) x = (int32_t)(_width - 1); |
| } |
| |
| inline void border_check_y (int32_t &y) const { |
| if (y < 0) y = 0; |
| else if (y >= (int32_t)_height) y = (int32_t)(_height - 1); |
| } |
| |
| inline void border_check (int32_t &x, int32_t &y) const { |
| border_check_x (x); |
| border_check_y (y); |
| } |
| }; |
| |
| |
| template <typename T> |
| SoftImage<T>::SoftImage (const SmartPtr<VideoBuffer> &buf, const uint32_t plane) |
| : _buf_ptr (NULL) |
| , _width (0) , _height (0) , _pitch (0) |
| { |
| XCAM_ASSERT (buf.ptr ()); |
| const VideoBufferInfo &info = buf->get_video_info (); |
| VideoBufferPlanarInfo planar; |
| if (!info.get_planar_info(planar, plane)) { |
| XCAM_LOG_ERROR ( |
| "videobuf to soft image failed. buf format:%s, plane:%d", xcam_fourcc_to_string (info.format), plane); |
| return; |
| } |
| _buf_ptr = buf->map () + info.offsets[plane]; |
| XCAM_ASSERT (_buf_ptr); |
| _pitch = info.strides[plane]; |
| _height = planar.height; |
| _width = planar.pixel_bytes * planar.width / sizeof (T); |
| XCAM_ASSERT (_width * sizeof(T) == planar.pixel_bytes * planar.width); |
| _bind = buf; |
| } |
| |
| template <typename T> |
| SoftImage<T>::SoftImage ( |
| const uint32_t width, const uint32_t height, uint32_t aligned_width) |
| : _buf_ptr (NULL) |
| , _width (0) , _height (0) , _pitch (0) |
| { |
| if (!aligned_width) |
| aligned_width = width; |
| |
| XCAM_ASSERT (aligned_width >= width); |
| XCAM_ASSERT (width > 0 && height > 0); |
| _pitch = aligned_width * sizeof (T); |
| _buf_ptr = (uint8_t *)xcam_malloc (_pitch * height); |
| XCAM_ASSERT (_buf_ptr); |
| _width = width; |
| _height = height; |
| } |
| |
| template <typename T> |
| SoftImage<T>::SoftImage ( |
| const SmartPtr<VideoBuffer> &buf, |
| const uint32_t width, const uint32_t height, const uint32_t pictch, const uint32_t offset) |
| : _buf_ptr (NULL) |
| , _width (width) , _height (height) |
| , _pitch (pictch) |
| , _bind (buf) |
| { |
| XCAM_ASSERT (buf.ptr ()); |
| XCAM_ASSERT (buf->map ()); |
| _buf_ptr = buf->map () + offset; |
| } |
| |
| template <typename T> |
| inline Uchar convert_to_uchar (const T& v) { |
| if (v < 0.0f) return 0; |
| else if (v > 255.0f) return 255; |
| return (Uchar)(v + 0.5f); |
| } |
| |
| template <typename T, uint32_t N> |
| inline void convert_to_uchar_N (const T *in, Uchar *out) { |
| for (uint32_t i = 0; i < N; ++i) { |
| out[i] = convert_to_uchar<T> (in[i]); |
| } |
| } |
| |
| template <typename Vec2> |
| inline Uchar2 convert_to_uchar2 (const Vec2& v) { |
| return Uchar2 (convert_to_uchar(v.x), convert_to_uchar(v.y)); |
| } |
| |
| template <typename Vec2, uint32_t N> |
| inline void convert_to_uchar2_N (const Vec2 *in, Uchar2 *out) { |
| for (uint32_t i = 0; i < N; ++i) { |
| out[i].x = convert_to_uchar (in[i].x); |
| out[i].y = convert_to_uchar (in[i].y); |
| } |
| } |
| |
| typedef SoftImage<Uchar> UcharImage; |
| typedef SoftImage<Uchar2> Uchar2Image; |
| typedef SoftImage<float> FloatImage; |
| typedef SoftImage<Float2> Float2Image; |
| |
| template <class SoftImageT> |
| class SoftImageFile |
| : public FileHandle |
| { |
| public: |
| SoftImageFile () {} |
| explicit SoftImageFile (const char *name, const char *option) |
| : FileHandle (name, option) |
| {} |
| |
| inline XCamReturn read_buf (const SmartPtr<SoftImageT> &buf); |
| inline XCamReturn write_buf (const SmartPtr<SoftImageT> &buf); |
| }; |
| |
| template <class SoftImageT> |
| inline XCamReturn |
| SoftImageFile<SoftImageT>::read_buf (const SmartPtr<SoftImageT> &buf) |
| { |
| XCAM_FAIL_RETURN ( |
| WARNING, is_valid (), XCAM_RETURN_ERROR_PARAM, |
| "soft image file(%s) read buf failed, file is not open", XCAM_STR (get_file_name ())); |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, buf->is_valid (), XCAM_RETURN_ERROR_PARAM, |
| "soft image file(%s) read buf failed, buf is not valid", XCAM_STR (get_file_name ())); |
| |
| XCAM_ASSERT (is_valid ()); |
| uint32_t height = buf->get_height (); |
| uint32_t line_bytes = buf->get_width () * buf->pixel_size (); |
| |
| for (uint32_t index = 0; index < height; index++) { |
| uint8_t *line_ptr = buf->get_buf_ptr (0, index); |
| XCAM_FAIL_RETURN ( |
| WARNING, fread (line_ptr, 1, line_bytes, _fp) == line_bytes, XCAM_RETURN_ERROR_FILE, |
| "soft image file(%s) read buf failed, image_line:%d", XCAM_STR (get_file_name ()), index); |
| } |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| template <class SoftImageT> |
| inline XCamReturn |
| SoftImageFile<SoftImageT>::write_buf (const SmartPtr<SoftImageT> &buf) |
| { |
| XCAM_FAIL_RETURN ( |
| WARNING, is_valid (), XCAM_RETURN_ERROR_PARAM, |
| "soft image file(%s) write buf failed, file is not open", XCAM_STR (get_file_name ())); |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, buf->is_valid (), XCAM_RETURN_ERROR_PARAM, |
| "soft image file(%s) write buf failed, buf is not valid", XCAM_STR (get_file_name ())); |
| |
| XCAM_ASSERT (is_valid ()); |
| uint32_t height = buf->get_height (); |
| uint32_t line_bytes = buf->get_width () * buf->pixel_size (); |
| |
| for (uint32_t index = 0; index < height; index++) { |
| uint8_t *line_ptr = buf->get_buf_ptr (0, index); |
| XCAM_FAIL_RETURN ( |
| WARNING, fwrite (line_ptr, 1, line_bytes, _fp) == line_bytes, XCAM_RETURN_ERROR_FILE, |
| "soft image file(%s) write buf failed, image_line:%d", XCAM_STR (get_file_name ()), index); |
| } |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| template <typename T> template <typename O> |
| O |
| SoftImage<T>::read_interpolate_data (float x, float y) const |
| { |
| int32_t x0 = (int32_t)(x), y0 = (int32_t)(y); |
| float a = x - x0, b = y - y0; |
| O l0[2], l1[2]; |
| read_array<O, 2> (x0, y0, l0); |
| read_array<O, 2> (x0, y0 + 1, l1); |
| |
| return l1[1] * (a * b) + l0[0] * ((1 - a) * (1 - b)) + |
| l1[0] * ((1 - a) * b) + l0[1] * (a * (1 - b)); |
| } |
| |
| template <typename T> template<typename O, uint32_t N> |
| void |
| SoftImage<T>::read_interpolate_array (Float2 *pos, O *array) const |
| { |
| for (uint32_t i = 0; i < N; ++i) { |
| array[i] = read_interpolate_data<O> (pos[i].x, pos[i].y); |
| } |
| } |
| |
| } |
| #endif //XCAM_SOFT_IMAGE_H |