static real_t nd_prediction (real_t max_costs, real_t price, unsigned band, int y_state, range_t *range, wfa_t *wfa, coding_t *c) { real_t costs; /* current approximation costs */ range_t lrange = *range; /* * Predict 'range' with DC component approximation */ { real_t x = get_ip_image_state (range->image, range->address, range->level, 0, c); real_t y = get_ip_state_state (0, 0, range->level, c); real_t w = btor (rtob (x / y, c->coeff->dc_rpf), c->coeff->dc_rpf); word_t s [2] = {0, -1}; lrange.into [0] = 0; lrange.into [1] = NO_EDGE; lrange.weight [0] = w; lrange.mv_coord_bits = 0; lrange.mv_tree_bits = 0; lrange.nd_tree_bits = tree_bits (LEAF, lrange.level, &c->p_tree); lrange.nd_weights_bits = 0; lrange.tree_bits = 0; lrange.matrix_bits = 0; lrange.weights_bits = c->coeff->bits (&w, s, range->level, c->coeff); } costs = price * (lrange.weights_bits + lrange.nd_tree_bits); /* * Recursive aproximation of difference image */ if (costs < max_costs) { unsigned state; range_t rrange; /* range: recursive subdivision */ unsigned last_state; /* last WFA state before recursion */ real_t *ipi [MAXSTATES]; /* inner products pointers */ unsigned width = width_of_level (range->level); unsigned height = height_of_level (range->level); real_t *pixels; /* * Generate difference image original - approximation */ { unsigned n; real_t *src, *dst; /* pointers to image data */ real_t w = - lrange.weight [0] * c->images_of_state [0][0]; src = c->pixels + range->address * size_of_level (range->level); dst = c->pixels = pixels = Calloc (width * height, sizeof (real_t)); for (n = width * height; n; n--) *dst++ = *src++ + w; } /* * Approximate difference recursively. */ rrange = *range; rrange.tree_bits = 0; rrange.matrix_bits = 0; rrange.weights_bits = 0; rrange.mv_coord_bits = 0; rrange.mv_tree_bits = 0; rrange.nd_tree_bits = 0; rrange.nd_weights_bits = 0; rrange.image = 0; rrange.address = 0; last_state = wfa->states - 1; for (state = 0; state <= last_state; state++) if (need_image (state, wfa)) { ipi [state] = c->ip_images_state[state]; c->ip_images_state[state] = Calloc (size_of_tree (c->products_level), sizeof (real_t)); } compute_ip_images_state (rrange.image, rrange.address, rrange.level, 1, 0, wfa, c); costs += subdivide (max_costs - costs, band, y_state, &rrange, wfa, c, NO, YES); Free (pixels); if (costs < max_costs && ischild (rrange.tree)) /* use prediction */ { unsigned img, adr; unsigned edge; img = range->image; adr = range->address; *range = rrange; range->image = img; range->address = adr; range->nd_tree_bits += lrange.nd_tree_bits; range->nd_weights_bits += lrange.weights_bits; for (edge = 0; isedge (lrange.into [edge]); edge++) { range->into [edge] = lrange.into [edge]; range->weight [edge] = lrange.weight [edge]; } range->into [edge] = NO_EDGE; range->prediction = edge; for (state = last_state + 1; state < wfa->states; state++) if (need_image (state, wfa)) memset (c->ip_images_state [state], 0, size_of_tree (c->products_level) * sizeof (real_t)); } else costs = MAXCOSTS; for (state = 0; state <= last_state; state++) if (need_image (state, wfa)) { Free (c->ip_images_state [state]); c->ip_images_state [state] = ipi [state]; } } else costs = MAXCOSTS; return costs; }
void restore_mc (int enlarge_factor, image_t *image, const image_t *past, const image_t *future, const wfa_t *wfa) /* * Restore motion compensated prediction of 'image' represented by 'wfa'. * If 'enlarge_factor' != 0 then enlarge image by given amount. * Reference frames are given by 'past' and 'future'. * * No return values. */ { unsigned state, label; unsigned root_state; word_t *mcblock1, *mcblock2; /* MC blocks */ #define FX(v) ((image->format == FORMAT_4_2_0) && band != Y ? ((v) / 2) : v) mcblock1 = Calloc (size_of_level (max ((int) wfa->wfainfo->p_max_level + 2 * enlarge_factor, 0)), sizeof (word_t)); mcblock2 = Calloc (size_of_level (max ((int) wfa->wfainfo->p_max_level + 2 * enlarge_factor, 0)), sizeof (word_t)); if (!image->color) root_state = wfa->root_state; else root_state = wfa->tree [wfa->tree [wfa->root_state][0]][0]; for (state = wfa->basis_states; state <= root_state; state++) for (label = 0; label < MAXLABELS; label++) if (wfa->mv_tree[state][label].type != NONE) { color_e band; unsigned level = wfa->level_of_state [state] - 1; unsigned width = width_of_level (level); unsigned height = height_of_level (level); unsigned offset = image->width - width; switch (wfa->mv_tree [state][label].type) { case FORWARD: for (band = first_band (image->color); band <= last_band (image->color); band++) { extract_mc_block (mcblock1, FX (width), FX (height), past->pixels [band], FX (past->width), wfa->wfainfo->half_pixel, FX (wfa->x [state][label]), FX (wfa->y [state][label]), FX (wfa->mv_tree [state][label].fx), FX (wfa->mv_tree [state][label].fy)); { word_t *mc1; /* current pixel in MC block */ word_t *orig; /* current pixel in original image */ unsigned x, y; /* pixel coordinates */ mc1 = mcblock1; orig = (word_t *) image->pixels [band] + FX (wfa->x[state][label]) + FX (wfa->y[state][label]) * FX (image->width); for (y = FX (height); y; y--) { for (x = FX (width); x; x--) *orig++ += *mc1++; orig += FX (offset); } } } break; case BACKWARD: for (band = first_band (image->color); band <= last_band (image->color); band++) { extract_mc_block (mcblock1, FX (width), FX (height), future->pixels [band], FX (future->width), wfa->wfainfo->half_pixel, FX (wfa->x [state][label]), FX (wfa->y [state][label]), FX (wfa->mv_tree [state][label].bx), FX (wfa->mv_tree [state][label].by)); { word_t *mc1; /* current pixel in MC block 1 */ word_t *orig; /* current pixel in original image */ unsigned x, y; /* pixel coordinates */ mc1 = mcblock1; orig = (word_t *) image->pixels [band] + FX (wfa->x[state][label]) + FX (wfa->y[state][label]) * FX (image->width); for (y = FX (height); y; y--) { for (x = FX (width); x; x--) *orig++ += *mc1++; orig += FX (offset); } } } break; case INTERPOLATED: for (band = first_band (image->color); band <= last_band (image->color); band++) { extract_mc_block (mcblock1, FX (width), FX (height), past->pixels [band], FX (past->width), wfa->wfainfo->half_pixel, FX (wfa->x[state][label]), FX (wfa->y[state][label]), FX (wfa->mv_tree[state][label].fx), FX (wfa->mv_tree[state][label].fy)); extract_mc_block (mcblock2, FX (width), FX (height), future->pixels [band], FX (future->width), wfa->wfainfo->half_pixel, FX (wfa->x[state][label]), FX (wfa->y[state][label]), FX (wfa->mv_tree[state][label].bx), FX (wfa->mv_tree[state][label].by)); { word_t *mc1; /* current pixel in MC block 1 */ word_t *mc2; /* current pixel in MC block 1 */ word_t *orig; /* current pixel in original image */ unsigned x, y; /* pixel coordinates */ mc1 = mcblock1; mc2 = mcblock2; orig = (word_t *) image->pixels [band] + FX (wfa->x[state][label]) + FX (wfa->y[state][label]) * FX (image->width); for (y = FX (height); y; y--) { for (x = FX (width); x; x--) #ifdef HAVE_SIGNED_SHIFT *orig++ += (*mc1++ + *mc2++) >> 1; #else /* not HAVE_SIGNED_SHIFT */ *orig++ += (*mc1++ + *mc2++) / 2; #endif /* not HAVE_SIGNED_SHIFT */ orig += FX (offset); } } } break; default: break; } }
static real_t mc_prediction (real_t max_costs, real_t price, unsigned band, int y_state, range_t *range, wfa_t *wfa, coding_t *c) { real_t costs; /* current approximation costs */ range_t prange = *range; unsigned width = width_of_level (range->level); unsigned height = height_of_level (range->level); word_t *mcpe = Calloc (width * height, sizeof (word_t)); /* * If we are at the bottom level of the mc tree: * Fill in the norms table */ if (prange.level == wfa->wfainfo->p_min_level) fill_norms_table (prange.x, prange.y, prange.level, wfa->wfainfo, c->mt); /* * Predict 'range' with motion compensation according to frame type. * MCPE is returned in 'c->mcpe' */ if (c->mt->frame_type == P_FRAME) find_P_frame_mc (mcpe, price, &prange, wfa->wfainfo, c->mt); else find_B_frame_mc (mcpe, price, &prange, wfa->wfainfo, c->mt); costs = (prange.mv_tree_bits + prange.mv_coord_bits) * price; if (costs < max_costs) /* motion vector not too expensive */ { unsigned last_state; /* last WFA state before recursion */ real_t *ipi [MAXSTATES]; /* inner products pointers */ unsigned state; real_t mvt, mvc; c->pixels = Calloc (width * height, sizeof (real_t)); cut_to_bintree (c->pixels, mcpe, width, height, 0, 0, width, height); /* * Approximate MCPE recursively. */ last_state = wfa->states - 1; for (state = 0; state <= last_state; state++) if (need_image (state, wfa)) { ipi [state] = c->ip_images_state[state]; c->ip_images_state[state] = Calloc (size_of_tree (c->products_level), sizeof (real_t)); } mvc = prange.mv_coord_bits; mvt = prange.mv_tree_bits; prange.image = 0; prange.address = 0; prange.tree_bits = 0; prange.matrix_bits = 0; prange.weights_bits = 0; prange.mv_coord_bits = 0; prange.mv_tree_bits = 0; prange.nd_weights_bits = 0; prange.nd_tree_bits = 0; compute_ip_images_state (prange.image, prange.address, prange.level, 1, 0, wfa, c); costs += subdivide (max_costs - costs, band, y_state, &prange, wfa, c, NO, YES); if (costs < max_costs) /* use motion compensation */ { unsigned img, adr; /* temp. values */ img = range->image; adr = range->address; *range = prange; range->image = img; range->address = adr; range->mv_coord_bits = mvc; range->mv_tree_bits = mvt; range->prediction = YES; for (state = last_state + 1; state < wfa->states; state++) if (need_image (state, wfa)) memset (c->ip_images_state [state], 0, size_of_tree (c->products_level) * sizeof (real_t)); costs = (range->tree_bits + range->matrix_bits + range->weights_bits + range->mv_tree_bits + range->mv_coord_bits + range->nd_tree_bits + range->nd_weights_bits) * price + range->err; } else costs = MAXCOSTS; for (state = 0; state <= last_state; state++) if (need_image (state, wfa)) { Free (c->ip_images_state[state]); c->ip_images_state[state] = ipi [state]; } Free (c->pixels); } else costs = MAXCOSTS; Free (mcpe); return costs; }
unsigned read_next_wfa (wfa_t *wfa, bitfile_t *input) /* * Read next WFA frame of the WFA stream 'input'. * WFA header information has to be already present in the 'wfainfo' struct. * (i.e. open_wfa must be called first!) * * No return value. * * Side effects: * wfa->into, wfa->weights, wfa->final_distribution, wfa->states * wfa->x, wfa->y, wfa->level_of_state, wfa->domain_type * mt->type, mt->number are filled with the values of the WFA file. */ { tiling_t tiling; /* tiling information */ unsigned frame_number; /* current frame number */ assert (wfa && input); /* * Frame header information */ { const unsigned rice_k = 8; /* parameter of Rice Code */ wfa->states = read_rice_code (rice_k, input); wfa->frame_type = read_rice_code (rice_k, input); frame_number = read_rice_code (rice_k, input); } if (wfa->wfainfo->release > 1) /* no alignment in version 1 */ { INPUT_BYTE_ALIGN (input); } /* * Read image tiling info */ if (get_bit (input)) /* tiling performed ? */ read_tiling (&tiling, wfa->wfainfo->width, wfa->wfainfo->height, wfa->wfainfo->level, input); else tiling.exponent = 0; INPUT_BYTE_ALIGN (input); read_tree (wfa, &tiling, input); /* * Compute domain pool. * Large images have not been used due to image tiling. */ { unsigned state; for (state = wfa->basis_states; state < wfa->states; state++) if ((!wfa->wfainfo->color || (int) state <= wfa->tree [wfa->tree [wfa->root_state][0]][0]) && (!tiling.exponent || wfa->level_of_state [state] <= (wfa->wfainfo->level - tiling.exponent)) && ((wfa->x [state][0] + width_of_level (wfa->level_of_state [state])) <= wfa->wfainfo->width) && ((wfa->y [state][0] + height_of_level (wfa->level_of_state [state])) <= wfa->wfainfo->height)) wfa->domain_type [state] = USE_DOMAIN_MASK; else wfa->domain_type [state] = 0; } if (tiling.exponent) Free (tiling.vorder); if (get_bit (input)) /* nondeterministic prediction used */ read_nd (wfa, input); if (wfa->frame_type != I_FRAME) /* motion compensation used */ read_mc (wfa->frame_type, wfa, input); locate_delta_images (wfa); /* * Read linear combinations (coefficients and indices) */ { unsigned edges = read_matrices (wfa, input); if (edges) read_weights (edges, wfa, input); } /* * Compute final distribution of all states */ { unsigned state; for (state = wfa->basis_states; state <= wfa->states; state++) wfa->final_distribution[state] = compute_final_distribution (state, wfa); } return frame_number; }