void ccv_add(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type) { ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); assert(da->rows == db->rows && da->cols == db->cols && CCV_GET_CHANNEL(da->type) == CCV_GET_CHANNEL(db->type)); ccv_declare_derived_signature(sig, da->sig != 0 && db->sig != 0, ccv_sign_with_literal("ccv_add"), da->sig, db->sig, CCV_EOF_SIGN); int no_8u_type = (da->type & CCV_8U) ? CCV_32S : da->type; type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(da->type); ccv_dense_matrix_t* dc = *c = ccv_dense_matrix_renew(*c, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); ccv_object_return_if_cached(, dc); int i, j, ch = CCV_GET_CHANNEL(da->type); unsigned char* aptr = da->data.u8; unsigned char* bptr = db->data.u8; unsigned char* cptr = dc->data.u8; #define for_block(_for_get_a, _for_get_b, _for_set) \ for (i = 0; i < da->rows; i++) \ { \ for (j = 0; j < da->cols * ch; j++) \ _for_set(cptr, j, _for_get_a(aptr, j, 0) + _for_get_b(bptr, j, 0), 0); \ aptr += da->step; \ bptr += db->step; \ cptr += dc->step; \ } ccv_matrix_getter_a(da->type, ccv_matrix_getter_b, db->type, ccv_matrix_setter, dc->type, for_block); #undef for_block }
/* the following code is adopted from OpenCV cvPyrDown */ void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y) { assert(src_x >= 0 && src_y >= 0); ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_down(%d,%d)", src_x, src_y), a->sig, CCV_EOF_SIGN); type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type); ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows / 2, a->cols / 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); ccv_object_return_if_cached(, db); int ch = CCV_GET_CHANNEL(a->type); int cols0 = db->cols - 1 - src_x; int dy, sy = -2 + src_y, sx = src_x * ch, dx, k; int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int)); for (dx = 0; dx < a->cols + src_x + 2; dx++) for (k = 0; k < ch; k++) tab[dx * ch + k] = ((dx >= a->cols) ? a->cols * 2 - 1 - dx : dx) * ch + k; unsigned char* buf = (unsigned char*)alloca(5 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int))); int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)); #ifdef __clang_analyzer__ memset(buf, 0, 5 * bufstep); #endif unsigned char* b_ptr = db->data.u8; /* why is src_y * 4 in computing the offset of row? * Essentially, it means sy - src_y but in a manner that doesn't result negative number. * notice that we added src_y before when computing sy in the first place, however, * it is not desirable to have that offset when we try to wrap it into our 5-row buffer ( * because in later rearrangement, we have no src_y to backup the arrangement). In * such micro scope, we managed to stripe 5 addition into one shift and addition. */ #define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (dy = 0; dy < db->rows; dy++) \ { \ for(; sy <= dy * 2 + 2 + src_y; sy++) \ { \ unsigned char* row = buf + ((sy + src_y * 4 + 2) % 5) * bufstep; \ int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \ unsigned char* a_ptr = a->data.u8 + a->step * _sy; \ for (k = 0; k < ch; k++) \ _for_set(row, k, _for_get_a(a_ptr, sx + k, 0) * 10 + _for_get_a(a_ptr, ch + sx + k, 0) * 5 + _for_get_a(a_ptr, 2 * ch + sx + k, 0), 0); \ for(dx = ch; dx < cols0 * ch; dx += ch) \ for (k = 0; k < ch; k++) \ _for_set(row, dx + k, _for_get_a(a_ptr, dx * 2 + sx + k, 0) * 6 + (_for_get_a(a_ptr, dx * 2 + sx + k - ch, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch, 0)) * 4 + _for_get_a(a_ptr, dx * 2 + sx + k - ch * 2, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch * 2, 0), 0); \ x_block(_for_get_a, _for_set, _for_get, _for_set_b); \ } \ unsigned char* rows[5]; \ for(k = 0; k < 5; k++) \ rows[k] = buf + ((dy * 2 + k) % 5) * bufstep; \ for(dx = 0; dx < db->cols * ch; dx++) \ _for_set_b(b_ptr, dx, (_for_get(rows[2], dx, 0) * 6 + (_for_get(rows[1], dx, 0) + _for_get(rows[3], dx, 0)) * 4 + _for_get(rows[0], dx, 0) + _for_get(rows[4], dx, 0)) / 256, 0); \ b_ptr += db->step; \ } int no_8u_type = (a->type & CCV_8U) ? CCV_32S : a->type; if (src_x > 0) { #define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (dx = cols0 * ch; dx < db->cols * ch; dx += ch) \ for (k = 0; k < ch; k++) \ _for_set(row, dx + k, _for_get_a(a_ptr, tab[dx * 2 + sx + k], 0) * 6 + (_for_get_a(a_ptr, tab[dx * 2 + sx + k - ch], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch], 0)) * 4 + _for_get_a(a_ptr, tab[dx * 2 + sx + k - ch * 2], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch * 2], 0), 0); ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block); #undef x_block } else { #define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \ for (k = 0; k < ch; k++) \ _for_set(row, (db->cols - 1) * ch + k, _for_get_a(a_ptr, a->cols * ch + sx - ch + k, 0) * 10 + _for_get_a(a_ptr, (a->cols - 2) * ch + sx + k, 0) * 5 + _for_get_a(a_ptr, (a->cols - 3) * ch + sx + k, 0), 0); ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block); #undef x_block } #undef for_block }