Пример #1
0
// ######################################################################
static void env_free_list_init(struct free_list* p, env_size_t size_check)
{
        ENV_ASSERT(p->node_list == 0);
        ENV_ASSERT(size_check >= sizeof(struct free_list_node));

        p->num_allocations = 0;
        p->alloc_size = size_check;
        p->num_active = 0;
}
Пример #2
0
/** If there are chunks available in the free list, one of those is
    returned; otherwise new memory is allocated with
    (*g_raw_alloc). */
static void* env_free_list_allocate(struct free_list* p, env_size_t bytes)
{
        ENV_ASSERT(bytes == p->alloc_size);
        if (p->node_list == 0)
        {
                ++p->num_allocations;
                ++p->num_active;
                ENV_ASSERT(g_raw_alloc != 0);
                void* const result = (*g_raw_alloc)(bytes);
                ENV_ASSERT2(result != 0, "Memory allocation failed");
                return result;
        }
        struct free_list_node* n = p->node_list;
        p->node_list = p->node_list->next;
        ++p->num_active;
        return (void*) n;
}
Пример #3
0
// ######################################################################
void env_c_inplace_normalize(intg32* const dst, const env_size_t sz,
                             const intg32 nmin, const intg32 nmax,
                             intg32* const actualmin_p,
                             intg32* const actualmax_p,
                             const intg32 rangeThresh)
{
        ENV_ASSERT(sz > 0);
        ENV_ASSERT(nmax >= nmin);

        intg32 mi, ma;
        env_c_get_min_max(dst, sz, &mi, &ma);
        const intg32 old_scale = ma - mi;
        if (old_scale == 0 || old_scale < rangeThresh) // input image is uniform
        { for (env_size_t i = 0; i < sz; ++i) dst[i] = 0; return; }
        const intg32 new_scale = nmax - nmin;

        if (new_scale == 0) // output range is uniform
        { for (env_size_t i = 0; i < sz; ++i) dst[i] = nmin; return; }


        intg32 actualmin, actualmax;

        if (old_scale == new_scale)
        {
                const intg32 add = nmin - mi;
                if (add != 0)
                        for (env_size_t i = 0; i < sz; ++i)
                                dst[i] += add;

                actualmin = nmin;
                actualmax = nmax;
        }
#if defined(ENV_INTG64_TYPE)
        else
        {
                for (env_size_t i = 0; i < sz; ++i)
                        dst[i] = nmin + ((((intg64)(dst[i] - mi)) * new_scale)
                                         / old_scale);

                actualmin = nmin;
                actualmax = nmin + ((((intg64)(old_scale)) * new_scale)
                                    / old_scale);
        }
#else
        else if (old_scale > new_scale)
Пример #4
0
// ######################################################################
static void env_free_list_cleanup(struct free_list* p)
{
        ENV_ASSERT(p->num_active == 0);

        while (p->node_list)
        {
                void* space = p->node_list;
                p->node_list = p->node_list->next;
                ENV_ASSERT(g_raw_dealloc != 0);
                (*g_raw_dealloc)(space);
                --p->num_allocations;
        }

        ENV_ASSERT(p->num_allocations == 0);
        ENV_ASSERT(p->node_list == 0);

        // now we are back to a pristine state, so forget our size:
        p->alloc_size = 0;
}
Пример #5
0
static void env_ori_subjob_run(void* p)
{
        struct env_ori_subjob_data* j = (struct env_ori_subjob_data*)(p);

        env_chan_steerable
                (j->channame, j->envp, j->imath, j->dims,
                 j->hipass9, j->thetaidx,
                 j->status_func, j->status_userdata, &j->chanOut);

        ENV_ASSERT(env_img_initialized(&j->chanOut));
}
// ######################################################################
void env_stdio_write_gray(const struct env_image* iimage,
                          const char* outstem, const char* name, int c)
{
        if (!env_img_initialized(iimage))
                return;

        // if outstem is the empty string, then the user wanted us to
        // suppress output:
        if (outstem[0] == '\0')
                return;

        char fname[256];
        snprintf(fname, sizeof(fname),
                 "%s-%s%06d.pnm", outstem, name, c);

        FILE* const f = fopen(fname, "wb");
        if (f == 0)
                lfatal("%s: couldn't open PNM file for writing (errno=%d, %s)",
                       fname, errno, strerror(errno));

        //REV: so they are P5 (binary, greyscale), dim * dim images, with max value 255.
        if (fprintf(f, "P5\n%d %d\n255\n",
                    (int) iimage->dims.w, (int) iimage->dims.h) < 0)
                lfatal("%s: fprintf() failed (errno=%d, %s)",
                       fname, errno, strerror(errno));

        const intg32* const src = env_img_pixels(iimage);
        const env_size_t sz = env_img_size(iimage);
        byte* bimage =
                (byte*) env_allocate(sz * sizeof(byte));

        for (env_size_t i = 0; i < sz; ++i)
        {
                // the caller is supposed to have already ensured that
                // the intg32 image has been downsampled to a [0,255]
                // range, so let's verify that:
                ENV_ASSERT(src[i] >= 0 && src[i] <= 255);
                bimage[i] = (byte) src[i];
        }
        
        //REV: they aren't using any newlines!
        if (fwrite(bimage, 1, sz, f) != sz)
        {
                env_deallocate(bimage);
                lfatal("%s: fwrite() failed (errno=%d, %s)",
                       fname, errno, strerror(errno));
        }

        env_deallocate(bimage);

        if (fclose(f) != 0)
                lfatal("%s: fclose() failed (errno=%d, %s)",
                       fname, errno, strerror(errno));
}
Пример #7
0
// ######################################################################
void env_c_get_min_max(const intg32* src, const env_size_t sz,
                       intg32* xmini, intg32* xmaxi)
{
        ENV_ASSERT(sz > 0);
        *xmini = *xmaxi = src[0];
        for (env_size_t i = 0; i < sz; ++i)
        {
                if (src[i] < *xmini) *xmini = src[i];
                else if (src[i] > *xmaxi) *xmaxi = src[i];
        }
}
// ######################################################################
void env_params_validate(const struct env_params* envp)
{
        ENV_ASSERT(envp->maxnorm_type == ENV_VCXNORM_NONE ||
                   envp->maxnorm_type == ENV_VCXNORM_MAXNORM);
        ENV_ASSERT((envp->scale_bits+1) < (8*sizeof(intg32)));
#ifdef ENV_WITH_DYNAMIC_CHANNELS
        ENV_ASSERT(envp->num_motion_directions <= 99);
#endif
        ENV_ASSERT(envp->num_orientations <= 99);

        ENV_ASSERT(envp->cs_lev_max >= envp->cs_lev_min);
        ENV_ASSERT(envp->cs_del_max >= envp->cs_del_min);

        ENV_ASSERT(env_total_weight(envp) > 0);
}
// ######################################################################
static void div2(const env_size_t numer, const env_size_t denom,
                 const env_size_t ndigits,
                 env_size_t* const whole, env_size_t* const fract)
{
  *whole = numer / denom;
  *fract = 0;
  env_size_t rem = numer - (*whole * denom);
  for (env_size_t i = 0; i < ndigits; ++i)
    {
      rem *= 10;
      const env_size_t newwhole = rem / denom;
      ENV_ASSERT(newwhole < 10);
      rem = rem - (newwhole * denom);
      *fract *= 10;
      *fract += newwhole;
    }
}
Пример #10
0
// ######################################################################
void env_c_lowpass_5_y_dec_y_fewbits_optim(const intg32* src,
                                           const env_size_t w,
                                           const env_size_t h,
                                           intg32* dst,
                                           const env_size_t h2)
{
        ENV_ASSERT(h2 == h/2);

        // ########## vertical pass  (even though we scan horiz for speedup)
        const env_size_t w2 = w + w, w3 = w2 + w; // speedup

        if (h == 2 || h == 3) //////////////////////////////////////////////////
        {
                // topmost points  ( [ (6^) 4 ] / 10 )^T
                for (env_size_t i = 0; i < w; ++i)
                {
                        *dst++ = (src[0] * 3 + src[w] * 2) / 5;
                        src++;
                }
                src -= w;  // go back to top-left
        }
        else  ///////////////////////////////// general case for height >= 4
        {
                // topmost points  ( [ (8^) 4 ] / 12 )^T
                for (env_size_t k = 0; k < w; ++k)
                {
                        *dst++ = (src[ 0] * 2 + src[ w]) / 3;
                        src++;
                }
                src -= w;  // go back to top-left

                // second point skipped

                // rest of the column except last 2 points ( [ .^ 4 (8) 4 ] / 16 )T
                for (env_size_t i = 0; i < h-3; i += 2)
                {
                        for (env_size_t k = 0; k < w; ++k)
                        {
                                *dst++ = (src[ w] + src[w3] + src[w2] * 2) >> 2;
                                src++;
                        }
                        src += w;
                }
        }
}
Пример #11
0
// ######################################################################
static void env_aligned_alloc_deallocate(struct aligned_alloc* p, void* user_addr)
{
        const struct alloc_info* const info =
                ((struct alloc_info*) user_addr) - 1;

        p->nbytes_current -= info->alloc_nbytes;
        --p->nallocations_current;

        // deallocate memory from the given free_list, otherwise free it
        // globally
        if (info->source != 0)
        {
                env_free_list_deallocate(info->source, info->alloc_addr);
        }
        else
        {
                ENV_ASSERT(g_raw_dealloc != 0);
                (*g_raw_dealloc)(info->alloc_addr);
        }
}
Пример #12
0
static void env_direction_job_run(void* p)
{
        struct env_direction_job_data* j = (struct env_direction_job_data*)(p);

        const env_size_t firstlevel = j->envp->cs_lev_min;
        const env_size_t depth = env_max_pyr_depth(j->envp);

        // theta = (360.0 * i) / chan->num_directions;
        const env_size_t thetaidx =
                (j->dir * ENV_TRIG_TABSIZ) / j->chan->num_directions;

        ENV_ASSERT(thetaidx < ENV_TRIG_TABSIZ);

        // create an empty pyramid
        struct env_pyr shiftedCur;
        env_pyr_init(&shiftedCur, depth);

        // fill the empty pyramid with the shifted version
        for (env_size_t i = firstlevel; i < depth; ++i)
        {
                env_img_resize_dims(env_pyr_imgw(&shiftedCur, i),
                                    env_pyr_img(j->unshiftedCur, i)->dims);
                env_shift_image(env_pyr_img(j->unshiftedCur, i),
                                j->imath->costab[thetaidx],
                                -j->imath->sintab[thetaidx],
                                ENV_TRIG_NBITS,
                                env_pyr_imgw(&shiftedCur, i));
        }

        env_chan_direction(j->channame, j->envp, j->imath,
                           j->inputdims,
                           &j->chan->unshifted_prev, j->unshiftedCur,
                           &j->chan->shifted_prev[j->dir], &shiftedCur,
                           j->status_func, j->status_userdata, &j->chanOut);

        env_pyr_swap(&j->chan->shifted_prev[j->dir], &shiftedCur);
        env_pyr_make_empty(&shiftedCur);
}
Пример #13
0
// ######################################################################
void env_c_lowpass_5_x_dec_x_fewbits_optim(const intg32* src,
                                           const env_size_t w,
                                           const env_size_t h,
                                           intg32* dst,
                                           const env_size_t w2)
{
        ENV_ASSERT(w2 == w/2);

        if (w == 2 || w == 3) //////////////////////////////////////////////////
                for (env_size_t j = 0; j < h; ++j)
                {
                        // leftmost point  [ (6^) 4 ] / 10
                        *dst++ = (src[0] * 3 + src[1] * 2) / 5;
                        src += w;  // src back to same position as dst
                }
        else  ////////////////////////////// general case for width() >= 4
                // *** unfolded version (all particular cases treated) for
                // max speed.
                // notations: in () is the position of dest ptr, and ^ is src ptr
                // ########## horizontal pass
                for (env_size_t j = 0; j < h; ++j)
                {
                        const intg32* src2 = src;
                        // leftmost point  [ (8^) 4 ] / 12
                        *dst++ = (src2[0] * 2 + src2[1]) / 3;

                        // skip second point

                        // rest of the line except last 2 points  [ .^ 4 (8) 4 ] / 16
                        for (env_size_t i = 0; i < w-3; i += 2)
                        {
                                *dst++ = (src2[1] + src2[3] + src2[2] * 2) >> 2;
                                src2 += 2;
                        }

                        src += w;
                }
}
Пример #14
0
// ######################################################################
void env_c_lowpass_9_x_fewbits_optim(const intg32* src,
                                     const env_size_t w,
                                     const env_size_t h,
                                     intg32* dst)
{
        ENV_ASSERT(w >= 9);

        // boundary conditions: truncated filter
        for (env_size_t j = 0; j < h; ++j)
        {
                // leftmost points
                *dst++ =                  // [ (72^) 56 28 8 ]
                        (src[0] * 72 +
                         src[1] * 56 +
                         src[2] * 28 +
                         src[3] *  8
                                ) / 164;
                *dst++ =                  // [ 56^ (72) 56 28 8 ]
                        ((src[0] + src[2]) * 56 +
                         src[1] * 72 +
                         src[3] * 28 +
                         src[4] *  8
                                ) / 220;
                *dst++ =                  // [ 28^ 56 (72) 56 28 8 ]
                        ((src[0] + src[4]) * 28 +
                         (src[1] + src[3]) * 56 +
                         src[2] * 72 +
                         src[5] *  8
                                ) / 248;

                // far from the borders
                for (env_size_t i = 0; i < w - 6; ++i)
                {
                        *dst++ =              // [ 8^ 28 56 (72) 56 28 8 ]
                                ((src[0] + src[6]) *  8 +
                                 (src[1] + src[5]) * 28 +
                                 (src[2] + src[4]) * 56 +
                                 src[3] * 72
                                        ) >> 8;
                        ++src;
                }

                // rightmost points
                *dst++ =                  // [ 8^ 28 56 (72) 56 28 ]
                        (src[0] *  8 +
                         (src[1] + src[5]) * 28 +
                         (src[2] + src[4]) * 56 +
                         src[3] * 72
                                ) / 248;
                ++src;
                *dst++ =                  // [ 8^ 28 56 (72) 56 ]
                        (src[0] *  8 +
                         src[1] * 28 +
                         (src[2] + src[4]) * 56 +
                         src[3] * 72
                                ) / 220;
                ++src;
                *dst++ =                  // [ 8^ 28 56 (72) ]
                        (src[0] *  8 +
                         src[1] * 28 +
                         src[2] * 56 +
                         src[3] * 72
                                ) / 164;
                src += 4;  // src back to same as dst (start of next line)
        }
}
Пример #15
0
// ######################################################################
void env_mt_motion_channel_input_and_consume_pyr(
        struct env_motion_channel* chan,
        const char* tagName,
        const struct env_params* envp,
        const struct env_math* imath,
        const struct env_dims inputdims,
        struct env_pyr* unshiftedCur,
        env_chan_status_func* status_func,
        void* status_userdata,
        struct env_image* result)
{
        env_img_make_empty(result);

        if (chan->num_directions != envp->num_motion_directions)
        {
                env_motion_channel_destroy(chan);
                env_motion_channel_init(chan, envp);
        }

        if (chan->num_directions == 0)
                return;

        char buf[17] =
                {
                        'r', 'e', 'i', 'c', 'h', 'a', 'r', 'd', 't', // 0--8
                        '(', '_', '_', // 9--11
                        '/', '_', '_', ')', '\0' // 12--16
                };

        ENV_ASSERT(chan->num_directions <= 99);

        buf[13] = '0' + (chan->num_directions / 10);
        buf[14] = '0' + (chan->num_directions % 10);

        struct env_job* jobs =
                env_allocate(chan->num_directions * sizeof(struct env_job));

        ENV_ASSERT2(jobs != 0, "env_allocate failed");

        struct env_direction_job_data* jobdata =
                env_allocate(chan->num_directions
                             * sizeof(struct env_direction_job_data));

        ENV_ASSERT2(jobdata != 0, "env_allocate failed");

        // compute Reichardt motion detection into several directions
        for (env_size_t dir = 0; dir < chan->num_directions; ++dir)
        {
                buf[10] = '0' + ((dir+1) / 10);
                buf[11] = '0' + ((dir+1) % 10);

                jobdata[dir].chan = chan;
                jobdata[dir].dir = dir;
                jobdata[dir].envp = envp;
                jobdata[dir].imath = imath;
                jobdata[dir].inputdims = inputdims;
                jobdata[dir].unshiftedCur = unshiftedCur;
                jobdata[dir].status_func = status_func;
                jobdata[dir].status_userdata = status_userdata;
                env_img_init_empty(&jobdata[dir].chanOut);
                for (env_size_t c = 0; c < sizeof(buf); ++c)
                        jobdata[dir].channame[c] = buf[c];

                jobs[dir].callback = &env_direction_job_run;
                jobs[dir].userdata = &jobdata[dir];
        }

        env_run_jobs(&jobs[0], chan->num_directions);

        for (env_size_t dir = 0; dir < chan->num_directions; ++dir)
        {
                struct env_image* chanOut = &jobdata[dir].chanOut;

                if (env_img_initialized(chanOut))
                {
                        if (!env_img_initialized(result))
                        {
                                env_img_resize_dims(result, chanOut->dims);
                                env_c_image_div_scalar
                                        (env_img_pixels(chanOut),
                                         env_img_size(chanOut),
                                         (intg32) chan->num_directions,
                                         env_img_pixelsw(result));
                        }
                        else
                        {
                                ENV_ASSERT
                                        (env_dims_equal(chanOut->dims,
                                                        result->dims));
                                env_c_image_div_scalar_accum
                                        (env_img_pixels(chanOut),
                                         env_img_size(chanOut),
                                         (intg32) chan->num_directions,
                                         env_img_pixelsw(result));
                        }
                }

                env_img_make_empty(chanOut);
        }

        if (env_img_initialized(result))
        {
                env_max_normalize_inplace(result,
                                          INTMAXNORMMIN, INTMAXNORMMAX,
                                          envp->maxnorm_type,
                                          envp->range_thresh);
                if (status_func)
                        (*status_func)(status_userdata, tagName, result);
        }

        env_pyr_swap(unshiftedCur, &chan->unshifted_prev);
        env_pyr_make_empty(unshiftedCur);

        env_deallocate(jobdata);
        env_deallocate(jobs);
}
Пример #16
0
// ######################################################################
void env_mt_chan_orientation(const char* tagName,
                             const struct env_params* envp,
                             const struct env_math* imath,
                             const struct env_image* img,
                             env_chan_status_func* status_func,
                             void* status_userdata,
                             struct env_image* result)
{
        env_img_make_empty(result);

        if (envp->num_orientations == 0)
                return;

        struct env_pyr hipass9;
        env_pyr_init(&hipass9, env_max_pyr_depth(envp));
        env_pyr_build_hipass_9(img,
                               envp->cs_lev_min,
                               imath,
                               &hipass9);

        char buf[17] =
                {
                        's', 't', 'e', 'e', 'r', 'a', 'b', 'l', 'e', // 0--8
                        '(', '_', '_', // 9--11
                        '/', '_', '_', ')', '\0' // 12--16
                };

        ENV_ASSERT(envp->num_orientations <= 99);

        buf[13] = '0' + (envp->num_orientations / 10);
        buf[14] = '0' + (envp->num_orientations % 10);

        struct env_job* jobs =
                env_allocate(envp->num_orientations * sizeof(struct env_job));

        ENV_ASSERT2(jobs != 0, "env_allocate failed");

        struct env_ori_subjob_data* jobdata =
                env_allocate(envp->num_orientations
                             * sizeof(struct env_ori_subjob_data));

        ENV_ASSERT2(jobdata != 0, "env_allocate failed");

        for (env_size_t i = 0; i < envp->num_orientations; ++i)
        {
                // theta = (180.0 * i) / envp->num_orientations +
                // 90.0, where ENV_TRIG_TABSIZ is equivalent to 360.0
                // or 2*pi
                const env_size_t thetaidx =
                        (ENV_TRIG_TABSIZ * i)
                        / (2 * envp->num_orientations)
                        + (ENV_TRIG_TABSIZ / 4);

                ENV_ASSERT(thetaidx < ENV_TRIG_TABSIZ);

                buf[10] = '0' + ((i+1) / 10);
                buf[11] = '0' + ((i+1) % 10);

                jobdata[i].envp = envp;
                jobdata[i].imath = imath;
                jobdata[i].dims = img->dims;
                jobdata[i].hipass9 = &hipass9;
                jobdata[i].thetaidx = thetaidx;
                jobdata[i].status_func = status_func;
                jobdata[i].status_userdata = status_userdata;
                env_img_init_empty(&jobdata[i].chanOut);
                for (env_size_t c = 0; c < sizeof(buf); ++c)
                        jobdata[i].channame[c] = buf[c];

                jobs[i].callback = &env_ori_subjob_run;
                jobs[i].userdata = &jobdata[i];
        }

        env_run_jobs(&jobs[0], envp->num_orientations);

        for (env_size_t i = 0; i < envp->num_orientations; ++i)
        {
                struct env_image* chanOut = &jobdata[i].chanOut;

                if (!env_img_initialized(result))
                {
                        env_img_resize_dims(result, chanOut->dims);
                        env_c_image_div_scalar
                                (env_img_pixels(chanOut),
                                 env_img_size(chanOut),
                                 (intg32) envp->num_orientations,
                                 env_img_pixelsw(result));
                }
                else
                {
                        ENV_ASSERT(env_dims_equal(chanOut->dims,
                                                  result->dims));
                        env_c_image_div_scalar_accum
                                (env_img_pixels(chanOut),
                                 env_img_size(chanOut),
                                 (intg32) envp->num_orientations,
                                 env_img_pixelsw(result));
                }

                env_img_make_empty(chanOut);
        }

        env_pyr_make_empty(&hipass9);

        ENV_ASSERT(env_img_initialized(result));

        env_max_normalize_inplace(result, INTMAXNORMMIN, INTMAXNORMMAX,
                                  envp->maxnorm_type,
                                  envp->range_thresh);

        if (status_func)
                (*status_func)(status_userdata, tagName, result);

        env_deallocate(jobdata);
        env_deallocate(jobs);
}
Пример #17
0
// ######################################################################
static void* env_aligned_alloc_allocate(struct aligned_alloc* p, env_size_t user_nbytes)
{
        struct alloc_info info = { 0, 0, 0, { 0 } };
        info.source = 0;

        // We request extra space beyond what the user wants -- NALIGN
        // extra bytes allow us to return an address to the user that
        // is aligned to a NALIGN-byte boundary, and sizeof(struct
        // alloc_info) extra bytes allow us to stick some auxiliary
        // info just ahead of the address that we return to the
        // user. Note that for convenience we have set things up so
        // that sizeof(struct alloc_info)==NALIGN, so the number of
        // extra bytes that we need is just 2*NALIGN.
        info.alloc_nbytes = user_nbytes+2*NALIGN;
        info.alloc_addr = 0;

        for (env_size_t i = 0; i < ENV_NCACHE; ++i)
        {
                if (p->cache[i].alloc_size > 0)
                {
                        // we found a filled slot, but if it doesn't
                        // match our requested size then we just skip
                        // over it:
                        if (p->cache[i].alloc_size != info.alloc_nbytes)
                                continue;
                }
                else
                {
                        // we found an empty slot, so let's initialize
                        // a new free list for our requested size:
                        env_free_list_init(&p->cache[i], info.alloc_nbytes);
                }

                // now, one way or the other we know that the slot
                // matches our requested size, so go ahead and request
                // an allocation:
                info.source = &p->cache[i];
                info.alloc_addr =
                        env_free_list_allocate(&p->cache[i], info.alloc_nbytes);
                break;
        }

        if (info.alloc_addr == 0)
        {
                info.source = 0;
                ENV_ASSERT(g_raw_alloc != 0);
                info.alloc_addr = (*g_raw_alloc)(info.alloc_nbytes);
                ENV_ASSERT2(info.alloc_addr != 0,
                            "Memory allocation failed");
        }

        /* We will set things up like this:

        +- address = value of info.alloc_addr
        |
        |                                        +- address = return value
        |                                        |     of this function
        v                                        v

        +---------------+------------------------+------------------------+
        | len==adjust   | len==NALIGN            | len==user_nbytes       |
        | contents:     | contents:              | contents:              |
        |   unused      |   struct alloc_info    |   empty space for user |
        | alignment:    | alignment:             | alignment:             |
        |   unknown     |   NALIGN-byte boundary |   NALIGN-byte boundary |
        +---------------+------------------------+------------------------+

        */

        void* const user_addr =
                ((char*) info.alloc_addr)
                + (2*NALIGN)
                - ((unsigned long) info.alloc_addr) % NALIGN;

        ((struct alloc_info*) user_addr)[-1] = info;

        p->nbytes_alltime += info.alloc_nbytes;
        ++p->nallocations_alltime;
        p->nbytes_current += info.alloc_nbytes;
        ++p->nallocations_current;

        return user_addr;
}
// ######################################################################
struct env_rgb_pixel* env_stdio_parse_rgb(const char* fname,
                                          struct env_dims* outdims)
{
        FILE* f = fopen(fname, "rb");

        if (f == 0)
                lfatal("Couldn't open file '%s' for reading.", fname);

        int c = getc(f);
        if (c != 'P')
                lfatal("Missing magic number in pnm file '%s'"
                       "(got '%c' [%d], expected '%c' [%d]).",
                       fname, c, c, 'P', 'P');

        int mode = -1;
        int ret = fscanf(f, "%d", &mode);
        if (ret > 0 && mode != 6)
                lfatal("Wrong pnm mode (got 'P%d', expected 'P6')", //REV: so they expect P6, i.e. binary rgb!
                       mode);

        while (1)
        {
                const int c = getc(f); //REV: they're getting one char at a time...removing all spaces...
                if (!isspace(c))
                { ungetc(c, f); break; }
        }

        // copy and concatenate optional comment line(s) starting with '#'
        // into comments string
        //REV: they're removing comments and such...we won't need to worry about this...

        while (1)
        {
                const int c = getc(f);
                if (c != '#')
                { ungetc(c, f); break; }
                else
                {
                        while (getc(f) != '\n')
                        { /* empty loop */ }
                }
        }

        int w = -1;
        int h = -1;
        int maxGrey = -1;
        ret = fscanf(f, "%d %d %d", &w, &h, &maxGrey); //REV: they get the dimensions... and the max grey value (wth?)
        ENV_ASSERT(ret > 0);
        ENV_ASSERT(w > 0);
        ENV_ASSERT(h > 0);
        ENV_ASSERT(maxGrey > 0);

        // read one more character of whitespace from the stream after maxGrey
        c = getc(f);
        if ( !isspace(c) )
                lfatal("Missing whitespace after maxGrey in pbm file '%s'.", fname);

        struct env_rgb_pixel* result = (struct env_rgb_pixel*) //REV: note RGB pixel is byte[3].
                env_allocate(w * h * sizeof(struct env_rgb_pixel));
        if (fread((char*) result, 3, w*h, f) != ((env_size_t)(w*h)))
                lfatal("%s: fread() failed", fname);
        outdims->w = w;
        outdims->h = h;
        return result;
}
Пример #19
0
// ######################################################################
void env_c_lowpass_9_y_fewbits_optim(const intg32* src,
                                     const env_size_t w,
                                     const env_size_t h,
                                     intg32* dst)
{
        ENV_ASSERT(h >= 9);

        // index computation speedup:
        const env_size_t w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w;

        // *** vertical pass ***
        for (env_size_t i = 0; i < w; ++i)
        {
                *dst++ =
                        (src[ 0] * 72 +
                         src[ w] * 56 +
                         src[w2] * 28 +
                         src[w3] *  8
                                ) / 164;
                ++src;
        }
        src -= w; // back to top-left
        for (env_size_t i = 0; i < w; ++i)
        {
                *dst++ =
                        ((src[ 0] + src[w2]) * 56 +
                         src[ w] * 72 +
                         src[w3] * 28 +
                         src[w4] *  8
                                ) / 220;
                ++src;
        }
        src -= w; // back to top-left
        for (env_size_t i = 0; i < w; ++i)
        {
                *dst++ =
                        ((src[ 0] + src[w4]) * 28 +
                         (src[ w] + src[w3]) * 56 +
                         src[w2] * 72 +
                         src[w5] *  8
                                ) / 248;
                ++src;
        }
        src -= w; // back to top-left

        for (env_size_t j = 0; j < h - 6; j ++)
                for (env_size_t i = 0; i < w; ++i)
                {
                        *dst++ =
                                ((src[ 0] + src[w6]) *  8 +
                                 (src[ w] + src[w5]) * 28 +
                                 (src[w2] + src[w4]) * 56 +
                                 src[w3]  * 72
                                        ) >> 8;
                        ++src;
                }

        for (env_size_t i = 0; i < w; ++i)
        {
                *dst++ =
                        (src[ 0] *  8 +
                         (src[ w] + src[w5]) * 28 +
                         (src[w2] + src[w4]) * 56 +
                         src[w3] * 72
                                ) / 248;
                ++src;
        }
        for (env_size_t i = 0; i < w; ++i)
        {
                *dst++ =
                        (src[ 0] *  8 +
                         src[ w] * 28 +
                         (src[w2] + src[w4]) * 56 +
                         src[w3] * 72
                                ) / 220;
                ++src;
        }
        for (env_size_t i = 0; i < w; ++i)
        {
                *dst++ =
                        (src[ 0] *  8 +
                         src[ w] * 28 +
                         src[w2] * 56 +
                         src[w3] * 72
                                ) / 164;
                ++src;
        }
}
// ######################################################################
void env_stdio_print_alloc_stats(const struct env_alloc_stats* p,
                                 const env_size_t block_size)
{
        env_size_t kiB_block_size_whole, kiB_block_size_fract;
        div2(block_size, 1024, 2,
             &kiB_block_size_whole, &kiB_block_size_fract);

        ENV_ASSERT(block_size > 0);

        env_size_t n_cache_blocks = 0;

        for (env_size_t i = 0; i < p->ncache_used; ++i)
        {
                const env_size_t nb =
                        (p->cache[i].num_allocations
                         * p->cache[i].alloc_size);

                n_cache_blocks += p->cache[i].num_allocations;

                env_size_t kiB_alloc_whole, kiB_alloc_fract;
                div2(nb, 1024, 2,
                     &kiB_alloc_whole, &kiB_alloc_fract);

                env_size_t kiB_alloc_size_whole, kiB_alloc_size_fract;
                div2(p->cache[i].alloc_size, 1024, 4,
                     &kiB_alloc_size_whole, &kiB_alloc_size_fract);

                env_size_t alloc_percent_whole, alloc_percent_fract;
                div2(nb*100, p->bytes_allocated, 2,
                     &alloc_percent_whole, &alloc_percent_fract);

                env_size_t block_ratio_whole, block_ratio_fract;
                char symbol;

                if (p->cache[i].alloc_size - p->overhead >= block_size
                    || p->cache[i].alloc_size - p->overhead <= 1)
                {
                        div2(p->cache[i].alloc_size - p->overhead,
                             block_size, 1,
                             &block_ratio_whole, &block_ratio_fract);
                        symbol = '*';
                }
                else
                {
                        div2(block_size,
                             p->cache[i].alloc_size - p->overhead, 1,
                             &block_ratio_whole, &block_ratio_fract);
                        symbol = '/';
                }

                fprintf(stderr,
                        "memstats: cache[%02lu/%02lu]: "
                        "%5lu.%02lukiB (%3lu.%02lu%%) "
                        "in %4lu allocations "
                        "(%2lu active) of %5lu.%04lukiB"
                        " (%lu.%02lukiB %c %5lu.%01lu + %2luB)\n",
                        i, ENV_NCACHE,
                        kiB_alloc_whole, kiB_alloc_fract,
                        alloc_percent_whole, alloc_percent_fract,
                        p->cache[i].num_allocations,
                        p->cache[i].num_active,
                        kiB_alloc_size_whole, kiB_alloc_size_fract,
                        kiB_block_size_whole, kiB_block_size_fract,
                        (int) symbol,
                        block_ratio_whole, block_ratio_fract,
                        p->overhead);
        }

        env_size_t kiB_alloc_whole, kiB_alloc_fract;
        div2(p->bytes_allocated, 1024, 2,
             &kiB_alloc_whole, &kiB_alloc_fract);

        env_size_t n_blocks_whole, n_blocks_fract;
        div2(p->bytes_allocated, block_size, 1,
             &n_blocks_whole, &n_blocks_fract);

        fprintf(stderr,
                "memstats: =====[TOTAL]: "
                "%5lu.%02lukiB (100.00%%) "
                "in %4lu allocations "
                "(%2lu active) ================"
                " (%lu.%02lukiB * %5lu.%01lu      )\n",
                kiB_alloc_whole, kiB_alloc_fract,
                n_cache_blocks,
                p->nallocations_current,
                kiB_block_size_whole, kiB_block_size_fract,
                n_blocks_whole, n_blocks_fract);

        fprintf(stderr,
                "memstats: %lu/%lu cache table entries in use\n",
                p->ncache_used, ENV_NCACHE);

        fprintf(stderr,
                "memstats: block alignment: %lu bytes\n", p->nalign);

        fprintf(stderr,
                "memstats: all-time: %llukiB in %lu requested allocations\n",
                p->nbytes_alltime/1024, p->nallocations_alltime);

        fprintf(stderr,
                "memstats: current: %lukiB in %lu active allocations\n",
                (unsigned long)(p->nbytes_current/1024),
                p->nallocations_current);
}