// ###################################################################### 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)); }
// ###################################################################### 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); }
// ###################################################################### 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); }