Coverage Report

Created: 2019-07-03 22:50

/home/liu/buildslave/linux-x64-runtests/build/lib/ccv_resample.c
Line
Count
Source (jump to first uncovered line)
1
#include "ccv.h"
2
#include "ccv_internal.h"
3
4
/* area interpolation resample is adopted from OpenCV */
5
6
typedef struct {
7
  int si, di;
8
  unsigned int alpha;
9
} ccv_int_alpha;
10
11
static void _ccv_resample_area_8u(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
12
1
{
13
1
  assert(a->cols > 0 && b->cols > 0);
14
1
  ccv_int_alpha* xofs = (ccv_int_alpha*)alloca(sizeof(ccv_int_alpha) * a->cols * 2);
15
1
  int ch = ccv_clamp(CCV_GET_CHANNEL(a->type), 1, 4);
16
1
  double scale_x = (double)a->cols / b->cols;
17
1
  double scale_y = (double)a->rows / b->rows;
18
1
  // double scale = 1.f / (scale_x * scale_y);
19
1
  unsigned int inv_scale_256 = (int)(scale_x * scale_y * 0x10000);
20
1
  int dx, dy, sx, sy, i, k;
21
101
  for (dx = 0, k = 0; dx < b->cols; 
dx++100
)
22
100
  {
23
100
    double fsx1 = dx * scale_x, fsx2 = fsx1 + scale_x;
24
100
    int sx1 = (int)(fsx1 + 1.0 - 1e-6), sx2 = (int)(fsx2);
25
100
    sx1 = ccv_min(sx1, a->cols - 1);
26
100
    sx2 = ccv_min(sx2, a->cols - 1);
27
100
28
100
    if (sx1 > fsx1)
29
0
    {
30
0
      xofs[k].di = dx * ch;
31
0
      xofs[k].si = (sx1 - 1) * ch;
32
0
      xofs[k++].alpha = (unsigned int)((sx1 - fsx1) * 0x100);
33
0
    }
34
100
35
599
    for (sx = sx1; sx < sx2; 
sx++499
)
36
499
    {
37
499
      xofs[k].di = dx * ch;
38
499
      xofs[k].si = sx * ch;
39
499
      xofs[k++].alpha = 256;
40
499
    }
41
100
42
100
    if (fsx2 - sx2 > 1e-3)
43
1
    {
44
1
      xofs[k].di = dx * ch;
45
1
      xofs[k].si = sx2 * ch;
46
1
      xofs[k++].alpha = (unsigned int)((fsx2 - sx2) * 256);
47
1
    }
48
100
  }
49
1
  int xofs_count = k;
50
1
  unsigned int* buf = (unsigned int*)alloca(b->cols * ch * sizeof(unsigned int));
51
1
  unsigned int* sum = (unsigned int*)alloca(b->cols * ch * sizeof(unsigned int));
52
301
  for (dx = 0; dx < b->cols * ch; 
dx++300
)
53
300
    buf[dx] = sum[dx] = 0;
54
1
  dy = 0;
55
501
  for (sy = 0; sy < a->rows; 
sy++500
)
56
500
  {
57
500
    unsigned char* a_ptr = a->data.u8 + a->step * sy;
58
250k
    for (k = 0; k < xofs_count; 
k++250k
)
59
250k
    {
60
250k
      int dxn = xofs[k].di;
61
250k
      unsigned int alpha = xofs[k].alpha;
62
1.00M
      for (i = 0; i < ch; 
i++750k
)
63
750k
        buf[dxn + i] += a_ptr[xofs[k].si + i] * alpha;
64
250k
    }
65
500
    if ((dy + 1) * scale_y <= sy + 1 || 
sy == a->rows - 1400
)
66
100
    {
67
100
      unsigned int beta = (int)(ccv_max(sy + 1 - (dy + 1) * scale_y, 0.f) * 256);
68
100
      unsigned int beta1 = 256 - beta;
69
100
      unsigned char* b_ptr = b->data.u8 + b->step * dy;
70
100
      if (beta <= 0)
71
100
      {
72
30.1k
        for (dx = 0; dx < b->cols * ch; 
dx++30.0k
)
73
30.0k
        {
74
30.0k
          b_ptr[dx] = ccv_clamp((sum[dx] + buf[dx] * 256) / inv_scale_256, 0, 255);
75
30.0k
          sum[dx] = buf[dx] = 0;
76
30.0k
        }
77
100
      } else {
78
0
        for (dx = 0; dx < b->cols * ch; dx++)
79
0
        {
80
0
          b_ptr[dx] = ccv_clamp((sum[dx] + buf[dx] * beta1) / inv_scale_256, 0, 255);
81
0
          sum[dx] = buf[dx] * beta;
82
0
          buf[dx] = 0;
83
0
        }
84
0
      }
85
100
      dy++;
86
100
    }
87
400
    else
88
400
    {
89
120k
      for(dx = 0; dx < b->cols * ch; 
dx++120k
)
90
120k
      {
91
120k
        sum[dx] += buf[dx] * 256;
92
120k
        buf[dx] = 0;
93
120k
      }
94
400
    }
95
500
  }
96
1
}
97
98
typedef struct {
99
  int si, di;
100
  float alpha;
101
} ccv_area_alpha_t;
102
103
static void _ccv_resample_area(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
104
3
{
105
3
  assert(a->cols > 0 && b->cols > 0);
106
3
  ccv_area_alpha_t* xofs = (ccv_area_alpha_t*)alloca(sizeof(ccv_area_alpha_t) * a->cols * 2);
107
3
  int ch = CCV_GET_CHANNEL(a->type);
108
3
  double scale_x = (double)a->cols / b->cols;
109
3
  double scale_y = (double)a->rows / b->rows;
110
3
  double scale = 1.f / (scale_x * scale_y);
111
3
  int dx, dy, sx, sy, i, k;
112
801
  for (dx = 0, k = 0; dx < b->cols; 
dx++798
)
113
798
  {
114
798
    double fsx1 = dx * scale_x, fsx2 = fsx1 + scale_x;
115
798
    int sx1 = (int)(fsx1 + 1.0 - 1e-6), sx2 = (int)(fsx2);
116
798
    sx1 = ccv_min(sx1, a->cols - 1);
117
798
    sx2 = ccv_min(sx2, a->cols - 1);
118
798
119
798
    if (sx1 > fsx1)
120
792
    {
121
792
      xofs[k].di = dx * ch;
122
792
      xofs[k].si = (sx1 - 1) * ch;
123
792
      xofs[k++].alpha = (float)((sx1 - fsx1) * scale);
124
792
    }
125
798
126
1.76k
    for (sx = sx1; sx < sx2; 
sx++963
)
127
963
    {
128
963
      xofs[k].di = dx * ch;
129
963
      xofs[k].si = sx * ch;
130
963
      xofs[k++].alpha = (float)scale;
131
963
    }
132
798
133
798
    if (fsx2 - sx2 > 1e-3)
134
797
    {
135
797
      xofs[k].di = dx * ch;
136
797
      xofs[k].si = sx2 * ch;
137
797
      xofs[k++].alpha = (float)((fsx2 - sx2) * scale);
138
797
    }
139
798
  }
140
3
  int xofs_count = k;
141
3
  float* buf = (float*)alloca(b->cols * ch * sizeof(float));
142
3
  float* sum = (float*)alloca(b->cols * ch * sizeof(float));
143
2.39k
  for (dx = 0; dx < b->cols * ch; 
dx++2.39k
)
144
2.39k
    buf[dx] = sum[dx] = 0;
145
3
  dy = 0;
146
3
#define for_block(_for_get, _for_set) \
147
1.88k
  
for (sy = 0; 3
sy < a->rows;
sy++1.88k
) \
148
1.88k
  { \
149
1.88k
    unsigned char* a_ptr = a->data.u8 + a->step * sy; \
150
1.59M
    for (k = 0; k < xofs_count; 
k++1.59M
) \
151
1.59M
    { \
152
1.59M
      int dxn = xofs[k].di; \
153
1.59M
      float alpha = xofs[k].alpha; \
154
6.36M
      for (i = 0; i < ch; 
i++4.77M
) \
155
4.77M
        buf[dxn + i] += _for_get(a_ptr, xofs[k].si + i, 0) * alpha; \
156
1.59M
    } \
157
1.88k
    if ((dy + 1) * scale_y <= sy + 1 || 
sy == a->rows - 11.00k
) \
158
1.88k
    { \
159
874
      float beta = ccv_max(sy + 1 - (dy + 1) * scale_y, 0.f); \
160
874
      float beta1 = 1 - beta; \
161
874
      unsigned char* b_ptr = b->data.u8 + b->step * dy; \
162
874
      if (fabs(beta) < 1e-3) \
163
874
      { \
164
4.95k
        for (dx = 0; dx < b->cols * ch; 
dx++4.95k
) \
165
4.95k
        { \
166
4.95k
          _for_set(b_ptr, dx, sum[dx] + buf[dx], 0); \
167
4.95k
          sum[dx] = buf[dx] = 0; \
168
4.95k
        } \
169
868
      } else { \
170
685k
        for (dx = 0; dx < b->cols * ch; 
dx++684k
) \
171
684k
        { \
172
684k
          _for_set(b_ptr, dx, sum[dx] + buf[dx] * beta1, 0); \
173
684k
          sum[dx] = buf[dx] * beta; \
174
684k
          buf[dx] = 0; \
175
684k
        } \
176
868
      } \
177
874
      dy++; \
178
874
    } \
179
1.88k
    else \
180
1.88k
    { \
181
810k
      for(dx = 0; dx < b->cols * ch; 
dx++808k
) \
182
808k
      { \
183
808k
        sum[dx] += buf[dx]; \
184
808k
        buf[dx] = 0; \
185
808k
      } \
186
1.00k
    } \
187
1.88k
  }
188
3
  ccv_matrix_getter(a->type, ccv_matrix_setter, b->type, for_block);
189
3
#undef for_block
190
3
}
191
192
typedef struct {
193
  int si[4];
194
  float coeffs[4];
195
} ccv_cubic_coeffs_t;
196
197
typedef struct {
198
  int si[4];
199
  int coeffs[4];
200
} ccv_cubic_integer_coeffs_t;
201
202
static void _ccv_init_cubic_coeffs(int si, int sz, float s, ccv_cubic_coeffs_t* coeff)
203
0
{
204
0
  const float A = -0.75f;
205
0
  coeff->si[0] = ccv_max(si - 1, 0);
206
0
  coeff->si[1] = si;
207
0
  coeff->si[2] = ccv_min(si + 1, sz - 1);
208
0
  coeff->si[3] = ccv_min(si + 2, sz - 1);
209
0
  float x = s - si;
210
0
  coeff->coeffs[0] = ((A * (x + 1) - 5 * A) * (x + 1) + 8 * A) * (x + 1) - 4 * A;
211
0
  coeff->coeffs[1] = ((A + 2) * x - (A + 3)) * x * x + 1;
212
0
  coeff->coeffs[2] = ((A + 2) * (1 - x) - (A + 3)) * (1 - x) * (1 - x) + 1;
213
0
  coeff->coeffs[3] = 1.f - coeff->coeffs[0] - coeff->coeffs[1] - coeff->coeffs[2];
214
0
}
215
216
static void _ccv_resample_cubic_float_only(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
217
0
{
218
0
  assert(CCV_GET_DATA_TYPE(b->type) == CCV_32F || CCV_GET_DATA_TYPE(b->type) == CCV_64F);
219
0
  int i, j, k, ch = CCV_GET_CHANNEL(a->type);
220
0
  assert(b->cols > 0 && b->step > 0);
221
0
  ccv_cubic_coeffs_t* xofs = (ccv_cubic_coeffs_t*)alloca(sizeof(ccv_cubic_coeffs_t) * b->cols);
222
0
  float scale_x = (float)a->cols / b->cols;
223
0
  for (i = 0; i < b->cols; i++)
224
0
  {
225
0
    float sx = (i + 0.5) * scale_x - 0.5;
226
0
    _ccv_init_cubic_coeffs((int)sx, a->cols, sx, xofs + i);
227
0
  }
228
0
  float scale_y = (float)a->rows / b->rows;
229
0
  unsigned char* buf = (unsigned char*)alloca(b->step * 4);
230
#ifdef __clang_analyzer__
231
  memset(buf, 0, b->step * 4);
232
#endif
233
  unsigned char* a_ptr = a->data.u8;
234
0
  unsigned char* b_ptr = b->data.u8;
235
0
  int psi = -1, siy = 0;
236
0
#define for_block(_for_get, _for_set_b, _for_get_b) \
237
0
  for (i = 0; i < b->rows; i++) \
238
0
  { \
239
0
    ccv_cubic_coeffs_t yofs; \
240
0
    float sy = (i + 0.5) * scale_y - 0.5; \
241
0
    _ccv_init_cubic_coeffs((int)sy, a->rows, sy, &yofs); \
242
0
    if (yofs.si[3] > psi) \
243
0
    { \
244
0
      for (; siy <= yofs.si[3]; siy++) \
245
0
      { \
246
0
        unsigned char* row = buf + (siy & 0x3) * b->step; \
247
0
        for (j = 0; j < b->cols; j++) \
248
0
          for (k = 0; k < ch; k++) \
249
0
            _for_set_b(row, j * ch + k, _for_get(a_ptr, xofs[j].si[0] * ch + k, 0) * xofs[j].coeffs[0] + \
250
0
                          _for_get(a_ptr, xofs[j].si[1] * ch + k, 0) * xofs[j].coeffs[1] + \
251
0
                          _for_get(a_ptr, xofs[j].si[2] * ch + k, 0) * xofs[j].coeffs[2] + \
252
0
                          _for_get(a_ptr, xofs[j].si[3] * ch + k, 0) * xofs[j].coeffs[3], 0); \
253
0
        a_ptr += a->step; \
254
0
      } \
255
0
      psi = yofs.si[3]; \
256
0
    } \
257
0
    unsigned char* row[4] = { \
258
0
      buf + (yofs.si[0] & 0x3) * b->step, \
259
0
      buf + (yofs.si[1] & 0x3) * b->step, \
260
0
      buf + (yofs.si[2] & 0x3) * b->step, \
261
0
      buf + (yofs.si[3] & 0x3) * b->step, \
262
0
    }; \
263
0
    for (j = 0; j < b->cols * ch; j++) \
264
0
      _for_set_b(b_ptr, j, _for_get_b(row[0], j, 0) * yofs.coeffs[0] + _for_get_b(row[1], j, 0) * yofs.coeffs[1] + \
265
0
                 _for_get_b(row[2], j, 0) * yofs.coeffs[2] + _for_get_b(row[3], j, 0) * yofs.coeffs[3], 0); \
266
0
    b_ptr += b->step; \
267
0
  }
268
0
  ccv_matrix_getter(a->type, ccv_matrix_setter_getter_float_only, b->type, for_block);
269
0
#undef for_block
270
0
}
271
272
static void _ccv_init_cubic_integer_coeffs(int si, int sz, float s, ccv_cubic_integer_coeffs_t* coeff)
273
0
{
274
0
  const float A = -0.75f;
275
0
  coeff->si[0] = ccv_max(si - 1, 0);
276
0
  coeff->si[1] = si;
277
0
  coeff->si[2] = ccv_min(si + 1, sz - 1);
278
0
  coeff->si[3] = ccv_min(si + 2, sz - 1);
279
0
  float x = s - si;
280
0
  const int W_BITS = 1 << 6;
281
0
  coeff->coeffs[0] = (int)((((A * (x + 1) - 5 * A) * (x + 1) + 8 * A) * (x + 1) - 4 * A) * W_BITS + 0.5);
282
0
  coeff->coeffs[1] = (int)((((A + 2) * x - (A + 3)) * x * x + 1) * W_BITS + 0.5);
283
0
  coeff->coeffs[2] = (int)((((A + 2) * (1 - x) - (A + 3)) * (1 - x) * (1 - x) + 1) * W_BITS + 0.5);
284
0
  coeff->coeffs[3] = W_BITS - coeff->coeffs[0] - coeff->coeffs[1] - coeff->coeffs[2];
285
0
}
286
287
static void _ccv_resample_cubic_integer_only(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
288
0
{
289
0
  assert(CCV_GET_DATA_TYPE(b->type) == CCV_8U || CCV_GET_DATA_TYPE(b->type) == CCV_32S || CCV_GET_DATA_TYPE(b->type) == CCV_64S);
290
0
  int i, j, k, ch = CCV_GET_CHANNEL(a->type);
291
0
  int no_8u_type = (b->type & CCV_8U) ? CCV_32S : b->type;
292
0
  assert(b->cols > 0);
293
0
  ccv_cubic_integer_coeffs_t* xofs = (ccv_cubic_integer_coeffs_t*)alloca(sizeof(ccv_cubic_integer_coeffs_t) * b->cols);
294
0
  float scale_x = (float)a->cols / b->cols;
295
0
  for (i = 0; i < b->cols; i++)
296
0
  {
297
0
    float sx = (i + 0.5) * scale_x - 0.5;
298
0
    _ccv_init_cubic_integer_coeffs((int)sx, a->cols, sx, xofs + i);
299
0
  }
300
0
  float scale_y = (float)a->rows / b->rows;
301
0
  int bufstep = b->cols * ch * CCV_GET_DATA_TYPE_SIZE(no_8u_type);
302
0
  unsigned char* buf = (unsigned char*)alloca(bufstep * 4);
303
#ifdef __clang_analyzer__
304
  memset(buf, 0, bufstep * 4);
305
#endif
306
  unsigned char* a_ptr = a->data.u8;
307
0
  unsigned char* b_ptr = b->data.u8;
308
0
  int psi = -1, siy = 0;
309
0
#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
310
0
  for (i = 0; i < b->rows; i++) \
311
0
  { \
312
0
    ccv_cubic_integer_coeffs_t yofs; \
313
0
    float sy = (i + 0.5) * scale_y - 0.5; \
314
0
    _ccv_init_cubic_integer_coeffs((int)sy, a->rows, sy, &yofs); \
315
0
    if (yofs.si[3] > psi) \
316
0
    { \
317
0
      for (; siy <= yofs.si[3]; siy++) \
318
0
      { \
319
0
        unsigned char* row = buf + (siy & 0x3) * bufstep; \
320
0
        for (j = 0; j < b->cols; j++) \
321
0
          for (k = 0; k < ch; k++) \
322
0
            _for_set(row, j * ch + k, _for_get_a(a_ptr, xofs[j].si[0] * ch + k, 0) * xofs[j].coeffs[0] + \
323
0
                          _for_get_a(a_ptr, xofs[j].si[1] * ch + k, 0) * xofs[j].coeffs[1] + \
324
0
                          _for_get_a(a_ptr, xofs[j].si[2] * ch + k, 0) * xofs[j].coeffs[2] + \
325
0
                          _for_get_a(a_ptr, xofs[j].si[3] * ch + k, 0) * xofs[j].coeffs[3], 0); \
326
0
        a_ptr += a->step; \
327
0
      } \
328
0
      psi = yofs.si[3]; \
329
0
    } \
330
0
    unsigned char* row[4] = { \
331
0
      buf + (yofs.si[0] & 0x3) * bufstep, \
332
0
      buf + (yofs.si[1] & 0x3) * bufstep, \
333
0
      buf + (yofs.si[2] & 0x3) * bufstep, \
334
0
      buf + (yofs.si[3] & 0x3) * bufstep, \
335
0
    }; \
336
0
    for (j = 0; j < b->cols * ch; j++) \
337
0
      _for_set_b(b_ptr, j, ccv_descale(_for_get(row[0], j, 0) * yofs.coeffs[0] + _for_get(row[1], j, 0) * yofs.coeffs[1] + \
338
0
                       _for_get(row[2], j, 0) * yofs.coeffs[2] + _for_get(row[3], j, 0) * yofs.coeffs[3], 12), 0); \
339
0
    b_ptr += b->step; \
340
0
  }
341
0
  ccv_matrix_getter(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_integer_only, b->type, for_block);
342
0
#undef for_block
343
0
}
344
345
void ccv_resample(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int rows, int cols, int type)
346
3.47M
{
347
3.47M
  assert(rows > 0 && cols > 0);
348
3.47M
  
ccv_declare_derived_signature3.46M
(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_resample(%d,%d,%d)", rows, cols, type), a->sig, CCV_EOF_SIGN);
349
3.46M
  btype = (btype == 0) ? 
CCV_GET_DATA_TYPE1
(a->type) | 1
CCV_GET_CHANNEL1
(a->type) :
CCV_GET_DATA_TYPE3.46M
(btype) | 3.46M
CCV_GET_CHANNEL3.46M
(a->type);
350
3.46M
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), btype, sig);
351
3.46M
  ccv_object_return_if_cached(, db);
352
3.48M
  if (
a->rows == db->rows3.46M
&& a->cols == db->cols)
353
3.48M
  {
354
3.48M
    if (CCV_GET_CHANNEL(a->type) == CCV_GET_CHANNEL(db->type) && 
CCV_GET_DATA_TYPE3.47M
(db->type) == 3.47M
CCV_GET_DATA_TYPE3.47M
(a->type))
355
3.48M
      
memcpy(db->data.u8, a->data.u8, a->rows * a->step)3.47M
;
356
1.63k
    else {
357
1.63k
      ccv_shift(a, (ccv_matrix_t**)&db, 0, 0, 0);
358
1.63k
    }
359
3.48M
    return;
360
3.48M
  }
361
18.4E
  if ((type & CCV_INTER_AREA) && 
a->rows >= db->rows4
&&
a->cols >= db->cols4
)
362
4
  {
363
4
    /* using the fast alternative (fix point scale, 0x100 to avoid overflow) */
364
4
    if (CCV_GET_DATA_TYPE(a->type) == CCV_8U && CCV_GET_DATA_TYPE(db->type) == CCV_8U && 
a->rows * a->cols / (db->rows * db->cols) < 0x1001
)
365
1
      _ccv_resample_area_8u(a, db);
366
3
    else
367
3
      _ccv_resample_area(a, db);
368
18.4E
  } else if (type & CCV_INTER_CUBIC) {
369
0
    if (CCV_GET_DATA_TYPE(db->type) == CCV_32F || CCV_GET_DATA_TYPE(db->type) == CCV_64F)
370
0
      _ccv_resample_cubic_float_only(a, db);
371
0
    else
372
0
      _ccv_resample_cubic_integer_only(a, db);
373
18.4E
  } else if (type & CCV_INTER_LINEAR) {
374
0
    assert(0 && "CCV_INTER_LINEAR is not implemented");
375
18.4E
  } else if (type & CCV_INTER_LANCZOS) {
376
0
    assert(0 && "CCV_INTER_LANCZOS is not implemented");
377
18.4E
  } else {
378
18.4E
    assert(0 && "Not implemented");
379
18.4E
  }
380
18.4E
}
381
382
/* the following code is adopted from OpenCV cvPyrDown */
383
void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y)
384
1
{
385
1
  assert(src_x >= 0 && src_y >= 0);
386
1
  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);
387
1
  type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : 
CCV_GET_DATA_TYPE0
(type) | 0
CCV_GET_CHANNEL0
(a->type);
388
1
  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);
389
1
  ccv_object_return_if_cached(, db);
390
1
  int ch = CCV_GET_CHANNEL(a->type);
391
1
  int cols0 = db->cols - 1 - src_x;
392
1
  int dy, sy = -2 + src_y, sx = src_x * ch, dx, k;
393
1
  int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int));
394
513
  for (dx = 0; dx < a->cols + src_x + 2; 
dx++512
)
395
2.04k
    
for (k = 0; 512
k < ch;
k++1.53k
)
396
1.53k
      tab[dx * ch + k] = ((dx >= a->cols) ? 
a->cols * 2 - 1 - dx36
:
dx1.50k
) * ch + k;
397
1
  unsigned char* buf = (unsigned char*)alloca(5 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)));
398
1
  int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int));
399
#ifdef __clang_analyzer__
400
  memset(buf, 0, 5 * bufstep);
401
#endif
402
  unsigned char* b_ptr = db->data.u8;
403
1
  /* why is src_y * 4 in computing the offset of row?
404
1
   * Essentially, it means sy - src_y but in a manner that doesn't result negative number.
405
1
   * notice that we added src_y before when computing sy in the first place, however,
406
1
   * it is not desirable to have that offset when we try to wrap it into our 5-row buffer (
407
1
   * because in later rearrangement, we have no src_y to backup the arrangement). In
408
1
   * such micro scope, we managed to stripe 5 addition into one shift and addition. */
409
1
#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
410
251
  
for (dy = 0; 1
dy < db->rows;
dy++250
) \
411
250
  { \
412
753
    for(; sy <= dy * 2 + 2 + src_y; 
sy++503
) \
413
503
    { \
414
503
      unsigned char* row = buf + ((sy + src_y * 4 + 2) % 5) * bufstep; \
415
503
      int _sy = (sy < 0) ? 
-1 - sy0
: (sy >= a->rows) ?
a->rows * 2 - 1 - sy11
:
sy492
; \
416
503
      unsigned char* a_ptr = a->data.u8 + a->step * _sy; \
417
2.01k
      for (k = 0; k < ch; 
k++1.50k
) \
418
1.50k
        _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); \
419
120k
      for(dx = ch; dx < cols0 * ch; 
dx += ch119k
) \
420
478k
        
for (k = 0; 119k
k < ch;
k++359k
) \
421
359k
          _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); \
422
503
      x_block(_for_get_a, _for_set, _for_get, _for_set_b); \
423
503
    } \
424
250
    unsigned char* rows[5]; \
425
1.50k
    for(k = 0; k < 5; 
k++1.25k
) \
426
1.25k
      rows[k] = buf + ((dy * 2 + k) % 5) * bufstep; \
427
187k
    for(dx = 0; dx < db->cols * ch; 
dx++187k
) \
428
187k
      _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); \
429
250
    b_ptr += db->step; \
430
250
  }
431
1
  int no_8u_type = (a->type & CCV_8U) ? CCV_32S : 
a->type0
;
432
1
  if (src_x > 0)
433
1
  {
434
1
#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
435
6.03k
    
for (dx = cols0 * ch; 503
dx < db->cols * ch;
dx += ch5.53k
) \
436
22.1k
      
for (k = 0; 5.53k
k < ch;
k++16.5k
) \
437
16.5k
        _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);
438
1
    ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
439
1
#undef x_block
440
1
  } else {
441
0
#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
442
0
    for (k = 0; k < ch; k++) \
443
0
      _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);
444
0
    ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
445
0
#undef x_block
446
0
  }
447
1
#undef for_block
448
1
}
449
450
void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y)
451
1
{
452
1
  assert(src_x >= 0 && src_y >= 0);
453
1
  ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_up(%d,%d)", src_x, src_y), a->sig, CCV_EOF_SIGN);
454
1
  type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : 
CCV_GET_DATA_TYPE0
(type) | 0
CCV_GET_CHANNEL0
(a->type);
455
1
  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);
456
1
  ccv_object_return_if_cached(, db);
457
1
  int ch = CCV_GET_CHANNEL(a->type);
458
1
  int cols0 = a->cols - 1 - src_x;
459
1
  assert(a->cols > 0 && cols0 > 0);
460
1
  int y, x, sy = -1 + src_y, sx = src_x * ch, k;
461
1
  int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int));
462
513
  for (x = 0; x < a->cols + src_x + 2; 
x++512
)
463
2.04k
    
for (k = 0; 512
k < ch;
k++1.53k
)
464
1.53k
      tab[x * ch + k] = ((x >= a->cols) ? 
a->cols * 2 - 1 - x36
:
x1.50k
) * ch + k;
465
1
  unsigned char* buf = (unsigned char*)alloca(3 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)));
466
1
  int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int));
467
#ifdef __clang_analyzer__
468
  memset(buf, 0, 3 * bufstep);
469
#endif
470
  unsigned char* b_ptr = db->data.u8;
471
1
  /* why src_y * 2: the same argument as in ccv_sample_down */
472
1
#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
473
501
  
for (y = 0; 1
y < a->rows;
y++500
) \
474
500
  { \
475
1.00k
    for (; sy <= y + 1 + src_y; 
sy++502
) \
476
502
    { \
477
502
      unsigned char* row = buf + ((sy + src_y * 2 + 1) % 3) * bufstep; \
478
502
      int _sy = (sy < 0) ? 
-1 - sy0
: (sy >= a->rows) ?
a->rows * 2 - 1 - sy11
:
sy491
; \
479
502
      unsigned char* a_ptr = a->data.u8 + a->step * _sy; \
480
502
      if (a->cols == 1) \
481
502
      { \
482
0
        for (k = 0; k < ch; k++) \
483
0
        { \
484
0
          _for_set(row, k, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \
485
0
          _for_set(row, k + ch, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \
486
0
        } \
487
0
        continue; \
488
0
      } \
489
502
      if (sx == 0) \
490
502
      { \
491
0
        for (k = 0; k < ch; k++) \
492
0
        { \
493
0
          _for_set(row, k, _for_get_a(a_ptr, k + sx, 0) * (G025 + G075) + _for_get_a(a_ptr, k + sx + ch, 0) * G125, 0); \
494
0
          _for_set(row, k + ch, _for_get_a(a_ptr, k + sx, 0) * (G125 + G025) + _for_get_a(a_ptr, k + sx + ch, 0) * G075, 0); \
495
0
        } \
496
0
      } \
497
502
      /* some serious flaw in computing Gaussian weighting in previous version
498
502
       * specially, we are doing perfect upsampling (2x) so, it concerns a grid like:
499
502
       * XXYY
500
502
       * XXYY
501
502
       * in this case, to upsampling, the weight should be from distance 0.25 and 1.25, and 0.25 and 0.75
502
502
       * previously, it was mistakingly be 0.0 1.0, 0.5 0.5 (imperfect upsampling (2x - 1)) */ \
503
245k
      for (x = (sx == 0) ? 
ch0
:
0502
; x < cols0 * ch;
x += ch245k
) \
504
245k
      { \
505
981k
        for (k = 0; k < ch; 
k++736k
) \
506
736k
        { \
507
736k
          _for_set(row, x * 2 + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G075 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G125, 0); \
508
736k
          _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G125 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G075, 0); \
509
736k
        } \
510
245k
      } \
511
502
      x_block(_for_get_a, _for_set, _for_get, _for_set_b); \
512
502
    } \
513
500
    unsigned char* rows[3]; \
514
2.00k
    for (k = 0; k < 3; 
k++1.50k
) \
515
1.50k
      rows[k] = buf + ((y + k) % 3) * bufstep; \
516
1.50M
    for (x = 0; x < db->cols * ch; 
x++1.50M
) \
517
1.50M
    { \
518
1.50M
      _for_set_b(b_ptr, x, (_for_get(rows[0], x, 0) * G075 + _for_get(rows[1], x, 0) * G025 + _for_get(rows[2], x, 0) * G125) / GALL, 0); \
519
1.50M
      _for_set_b(b_ptr + db->step, x, (_for_get(rows[0], x, 0) * G125 + _for_get(rows[1], x, 0) * G025 + _for_get(rows[2], x, 0) * G075) / GALL, 0); \
520
1.50M
    } \
521
500
    b_ptr += 2 * db->step; \
522
500
  }
523
1
  int no_8u_type = (a->type & CCV_8U) ? CCV_32S : 
a->type0
;
524
1
  /* unswitch if condition in manual way */
525
1
  if ((a->type & CCV_8U) || 
(a->type & CCV_32S)0
||
(a->type & CCV_64S)0
)
526
1
  {
527
1
#define G025 (23)
528
1
#define G075 (8)
529
1
#define G125 (1)
530
1
#define GALL (1024)
531
1
    if (src_x > 0)
532
1
    {
533
1
#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
534
6.02k
      
for (x = cols0 * ch; 502
x < a->cols * ch;
x += ch5.52k
) \
535
22.0k
        
for (k = 0; 5.52k
k < ch;
k++16.5k
) \
536
16.5k
        { \
537
16.5k
          _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G075 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G125, 0); \
538
16.5k
          _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G125 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G075, 0); \
539
16.5k
      }
540
1
      ccv_matrix_getter_integer_only(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
541
1
#undef x_block
542
1
    } else {
543
0
#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
544
0
      for (k = 0; k < ch; k++) \
545
0
      { \
546
0
        _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G075 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G125), 0); \
547
0
        _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G125 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G075), 0); \
548
0
      }
549
0
      ccv_matrix_getter_integer_only(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
550
0
#undef x_block
551
0
    }
552
1
#undef GALL
553
1
#undef G125
554
1
#undef G075
555
1
#undef G025
556
1
  } else {
557
0
#define G025 (0.705385)
558
0
#define G075 (0.259496)
559
0
#define G125 (0.035119)
560
0
#define GALL (1)
561
0
    if (src_x > 0)
562
0
    {
563
0
#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
564
0
      for (x = cols0 * ch; x < a->cols * ch; x += ch) \
565
0
        for (k = 0; k < ch; k++) \
566
0
        { \
567
0
          _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G075 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G125, 0); \
568
0
          _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G125 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G075, 0); \
569
0
      }
570
0
      ccv_matrix_getter_float_only(a->type, ccv_matrix_setter_getter_float_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
571
0
#undef x_block
572
0
    } else {
573
0
#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
574
0
      for (k = 0; k < ch; k++) \
575
0
      { \
576
0
        _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G075 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G125), 0); \
577
0
        _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G125 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G075), 0); \
578
0
      }
579
0
      ccv_matrix_getter_float_only(a->type, ccv_matrix_setter_getter_float_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
580
0
#undef x_block
581
0
    }
582
0
#undef GALL
583
0
#undef G125
584
0
#undef G075
585
0
#undef G025
586
0
  }
587
1
#undef for_block
588
1
}