Home | History | Annotate | Download | only in soft
      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