## Coverage Report

#### Created: 2026-04-14 20:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/liu/actions-runner/_work/ccv/ccv/lib/ccv_transform.c

    Line
    Count
    Source
    1
    #include "ccv.h"
    2
    #include "ccv_internal.h"
    3
    4
    void ccv_decimal_slice(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, float y, float x, int rows, int cols)
    5
    1
    {
    6
    1
      ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(128, "ccv_decimal_slice(%a,%a,%d,%d)", y, x, rows, cols), a->sig, CCV_EOF_SIGN);
    7
    1
      type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE0(type) | 0CCV_GET_CHANNEL0(a->type);
    8
    1
      ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
    9
    1
      ccv_object_return_if_cached(, db);
    10
    1
      int i, j, ch = CCV_GET_CHANNEL(a->type);
    11
    1
      int ix = (int)x, iy = (int)y;
    12
    1
      float xd = x - ix, yd = y - iy;
    13
    1
      float w00 = (1 - xd) * (1 - yd);
    14
    1
      float w01 = xd * (1 - yd);
    15
    1
      float w10 = (1 - xd) * yd;
    16
    1
      float w11 = xd * yd;
    17
    1
      int dx = 0, dy = 0;
    18
    1
      int rows_1 = 0, cols_1 = 0;
    19
      // it is going to be hard to deal with border efficiently, since this is used for tld, will ignore border for now
    20
    1
      if (!(iy >= 0 && iy + rows < a->rows && ix >= 0 && ix + cols < a->cols))
    21
    0
      {
    22
    0
        ccv_zero(db);
    23
    0
        if (iy < 0) { rows += iy; dy = -iy; iy = 0; }
    24
    0
        if (iy + rows >= a->rows)
    25
    0
        {
    26
    0
          rows = a->rows - iy - 1;
    27
    0
          if (iy + rows > a->rows)
    28
    0
            rows_1 = 1; // we need to do our best to padding the last row
    29
    0
        }
    30
    0
        if (ix < 0) { cols += ix; dx = -ix; ix = 0; }
    31
    0
        if (x + cols >= a->cols)
    32
    0
        {
    33
    0
          cols = a->cols - ix - 1;
    34
    0
          if (x + cols > a->cols)
    35
    0
            cols_1 = 1; // we need to do our best to padding the last col
    36
    0
        }
    37
    0
      }
    38
    1
      unsigned char* a_ptr = (unsigned char*)ccv_get_dense_matrix_cell(a, iy, ix, 0);
    39
    1
      unsigned char* b_ptr = (unsigned char*)ccv_get_dense_matrix_cell(db, dy, dx, 0);
    40
    1
    #define for_block(_for_set, _for_get) \
    41
    112
      for (i = 0; 1i < rows; i++111) \
    42
    111
      { \
    43
    30.4k
        for (j = 0; j < cols * ch; j++30.3k) \
    44
    30.3k
        { \
    45
    30.3k
          _for_set(b_ptr, j, (_for_get(a_ptr, j) * G00 + _for_get(a_ptr, j + ch) * G01 + _for_get(a_ptr + a->step, j) * G10 + _for_get(a_ptr + a->step, j + ch) * G11) / GALL); \
    46
    30.3k
        } \
    47
    111
        if (cols_1) \
    48
    111
          _for_set(b_ptr, j, (_for_get(a_ptr, j) * (G00 + G01) + _for_get(a_ptr + a->step, j) * G10 + _for_get(a_ptr + a->step, j + ch) * G11) / GALL); \
    49
    111
        a_ptr += a->step; \
    50
    111
        b_ptr += db->step; \
    51
    111
      } \
    52
    1
      if (rows_1) \
    53
    1
      { \
    54
    0
        for (j = 0; j < cols * ch; j++) \
    55
    0
        { \
    56
    0
          _for_set(b_ptr, j, (_for_get(a_ptr, j) * (G00 + G10) + _for_get(a_ptr, j + ch) * (G01 + G11)) / GALL); \
    57
    0
        } \
    58
    0
        if (cols_1) \
    59
    0
          _for_set(b_ptr, j, _for_get(a_ptr, j)); \
    60
    0
      }
    61
      /* unswitch in the manual way so that we can use integer interpolation */
    62
    1
      if ((a->type & CCV_8U) || (a->type & CCV_32S)0 || (a->type & CCV_64S)0)
    63
    1
      {
    64
    1
        const int W_BITS14 = 14;
    65
    1
        int iw00 = (int)(w00 * (1 << W_BITS14) + 0.5);
    66
    1
        int iw01 = (int)(w01 * (1 << W_BITS14) + 0.5);
    67
    1
        int iw10 = (int)(w10 * (1 << W_BITS14) + 0.5);
    68
    1
        int iw11 = (1 << W_BITS14) - iw00 - iw01 - iw10;
    69
    1
    #define G00 (iw00)
    70
    1
    #define G01 (iw01)
    71
    1
    #define G10 (iw10)
    72
    1
    #define G11 (iw11)
    73
    1
    #define GCOM (1 << (W_BITS14 - 1))
    74
    1
    #define GALL (1 << (W_BITS14))
    75
    1
        ccv_matrix_setter(db->type, ccv_matrix_getter_integer_only, a->type, for_block);
    76
    1
    #undef G00
    77
    1
    #undef G01
    78
    1
    #undef G10
    79
    1
    #undef G11
    80
    1
    #undef GCOM
    81
    1
    #undef GALL
    82
    1
      } else {
    83
    0
    #define G00 (w00)
    84
    0
    #define G01 (w01)
    85
    0
    #define G10 (w10)
    86
    0
    #define G11 (w11)
    87
    0
    #define GCOM (0)
    88
    0
    #define GALL (1)
    89
    0
        ccv_matrix_setter(db->type, ccv_matrix_getter_float_only, a->type, for_block);
    90
    0
    #undef G00
    91
    0
    #undef G01
    92
    0
    #undef G10
    93
    0
    #undef G11
    94
    0
    #undef GCOM
    95
    0
    #undef GALL
    96
    0
      }
    97
    1
    #undef for_block
    98
    1
    }
    99
    100
    ccv_decimal_point_t ccv_perspective_transform_apply(ccv_decimal_point_t point, ccv_size_t size, float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
    101
    0
    {
    102
    0
      m00 *= 1.0 / ccv_max(size.width, size.height);
    103
    0
      m01 *= 1.0 / ccv_max(size.width, size.height);
    104
    0
      m02 *= 1.0 / ccv_max(size.width, size.height);
    105
    0
      m10 *= 1.0 / ccv_max(size.width, size.height);
    106
    0
      m11 *= 1.0 / ccv_max(size.width, size.height);
    107
    0
      m12 *= 1.0 / ccv_max(size.width, size.height);
    108
    0
      m20 *= 1.0 / (ccv_max(size.width, size.height) * ccv_max(size.width, size.height));
    109
    0
      m21 *= 1.0 / (ccv_max(size.width, size.height) * ccv_max(size.width, size.height));
    110
    0
      m22 *= 1.0 / ccv_max(size.width, size.height);
    111
    0
      point.x -= size.width * 0.5;
    112
    0
      point.y -= size.height * 0.5;
    113
    0
      float wz = 1.0 / (point.x * m20 + point.y * m21 + m22);
    114
    0
      float wx = size.width * 0.5 + (point.x * m00 + point.y * m01 + m02) * wz;
    115
    0
      float wy = size.height * 0.5 + (point.x * m10 + point.y * m11 + m12) * wz;
    116
    0
      return ccv_decimal_point(wx, wy);
    117
    0
    }
    118
    119
    // this method is a merely baseline implementation and has no optimization effort ever put into it, if at all
    120
    void ccv_perspective_transform(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
    121
    1
    {
    122
    1
      ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(128, "ccv_perspective_transform(%a,%a,%a,%a,%a,%a,%a,%a,%a)", m00, m01, m02, m10, m11, m12, m20, m21, m22), a->sig, CCV_EOF_SIGN);
    123
    1
      type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE0(type) | 0CCV_GET_CHANNEL0(a->type);
    124
    1
      ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows, a->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
    125
    1
      ccv_object_return_if_cached(, db);
    126
      // with default of bilinear interpolation
    127
    1
      int i, j, k, ch = CCV_GET_CHANNEL(a->type);
    128
    1
      unsigned char* a_ptr = a->data.u8;
    129
    1
      unsigned char* b_ptr = db->data.u8;
    130
      // assume field of view is 60, modify the matrix value to reflect that
    131
      // (basically, apply x / ccv_max(a->rows, a->cols), y / ccv_max(a->rows, a->cols) before hand
    132
    1
      m00 *= 1.0 / ccv_max(a->rows, a->cols);
    133
    1
      m01 *= 1.0 / ccv_max(a->rows, a->cols);
    134
    1
      m02 *= 1.0 / ccv_max(a->rows, a->cols);
    135
    1
      m10 *= 1.0 / ccv_max(a->rows, a->cols);
    136
    1
      m11 *= 1.0 / ccv_max(a->rows, a->cols);
    137
    1
      m12 *= 1.0 / ccv_max(a->rows, a->cols);
    138
    1
      m20 *= 1.0 / (ccv_max(a->rows, a->cols) * ccv_max(a->rows, a->cols));
    139
    1
      m21 *= 1.0 / (ccv_max(a->rows, a->cols) * ccv_max(a->rows, a->cols));
    140
    1
      m22 *= 1.0 / ccv_max(a->rows, a->cols);
    141
    1
    #define for_block(_for_set, _for_get) \
    142
    501
      for (i = 0; 1i < db->rows; i++500) \
    143
    500
      { \
    144
    500
        float cy = i - db->rows * 0.5; \
    145
    500
        float crx = cy * m01 + m02; \
    146
    500
        float cry = cy * m11 + m12; \
    147
    500
        float crz = cy * m21 + m22; \
    148
    250k
        for (j = 0; j < db->cols; j++250k) \
    149
    250k
        { \
    150
    250k
          float cx = j - db->cols * 0.5; \
    151
    250k
          float wz = 1.0 / (cx * m20 + crz); \
    152
    250k
          float wx = a->cols * 0.5 + (cx * m00 + crx) * wz; \
    153
    250k
          float wy = a->rows * 0.5 + (cx * m10 + cry) * wz; \
    154
    250k
          int iwx = (int)wx; \
    155
    250k
          int iwy = (int)wy; \
    156
    250k
          wx = wx - iwx; \
    157
    250k
          wy = wy - iwy; \
    158
    250k
          int iwx1 = ccv_min(iwx + 1, a->cols - 1); \
    159
    250k
          int iwy1 = ccv_min(iwy + 1, a->rows - 1); \
    160
    250k
          if (iwx >= 0 && iwx < a->cols && iwy >= 0222k && iwy < a->rows208k) \
    161
    781k
            for (k = 0; 195kk < ch; k++586k) \
    162
    586k
              _for_set(b_ptr, j * ch + k, _for_get(a_ptr + iwy * a->step, iwx * ch + k) * (1 - wx) * (1 - wy) + \
    163
    250k
                            _for_get(a_ptr + iwy * a->step, iwx1 * ch + k) * wx * (1 - wy) + \
    164
    250k
                            _for_get(a_ptr + iwy1 * a->step, iwx * ch + k) * (1 - wx) * wy + \
    165
    250k
                            _for_get(a_ptr + iwy1 * a->step, iwx1 * ch + k) * wx * wy); \
    166
    250k
          else \
    167
    250k
            for (k = 0; 54.5kk < ch218k; k++163k) \
    168
    163k
              _for_set(b_ptr, j * ch + k, 0); \
    169
    250k
        } \
    170
    500
        b_ptr += db->step; \
    171
    500
      }
    172
    1
      ccv_matrix_setter(db->type, ccv_matrix_getter, a->type, for_block);
    173
    1
    #undef for_block
    174
    1
    }