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; } }
image_t * decode_image (unsigned orig_width, unsigned orig_height, format_e format, unsigned *dec_timer, const wfa_t *wfa) /* * Compute image which is represented by the given 'wfa'. * 'orig_width'x'orig_height' gives the resolution of the image at * coding time. Use 4:2:0 subsampling or 4:4:4 'format' for color images. * If 'dec_timer' is given, accumulate running time statistics. * * Return value: * pointer to decoded image * * Side effects: * '*dectimer' is changed if 'dectimer' != NULL. */ { unsigned root_state [3]; /* root of bintree for each band */ unsigned width, height; /* computed image size */ image_t *frame; /* regenerated frame */ word_t **images; /* pointer to array of pointers to state images */ u_word_t *offsets; /* pointer to array of state image offsets */ unsigned max_level; /* max. level of state with approx. */ unsigned state; clock_t ptimer; prg_timer (&ptimer, START); /* * Compute root of bintree for each color band */ if (wfa->wfainfo->color) { root_state [Y] = wfa->tree [wfa->tree [wfa->root_state][0]][0]; root_state [Cb] = wfa->tree [wfa->tree [wfa->root_state][0]][1]; root_state [Cr] = wfa->tree [wfa->tree [wfa->root_state][1]][0]; } else root_state [GRAY] = wfa->root_state; /* * Compute maximum level of a linear combination */ for (max_level = 0, state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) max_level = max (max_level, wfa->level_of_state [state]); /* * Allocate frame buffer for decoded image */ compute_actual_size (format == FORMAT_4_2_0 ? root_state [Y] : MAXSTATES, &width, &height, wfa); width = max (width, orig_width); height = max (height, orig_height); frame = alloc_image (width, height, wfa->wfainfo->color, format); /* * Allocate buffers for intermediate state images */ if (wfa->wfainfo->color) { wfa->level_of_state [wfa->root_state] = 128; wfa->level_of_state [wfa->tree[wfa->root_state][0]] = 128; wfa->level_of_state [wfa->tree[wfa->root_state][1]] = 128; } alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, format, wfa); if (dec_timer) dec_timer [0] += prg_timer (&ptimer, STOP); /* * Decode all state images, forming the complete image. */ prg_timer (&ptimer, START); compute_state_images (max_level, images, offsets, wfa); if (dec_timer) dec_timer [1] += prg_timer (&ptimer, STOP); /* * Cleanup buffers used for intermediate state images */ prg_timer (&ptimer, START); free_state_images (max_level, frame->color, images, offsets, root_state, 0, format, wfa); /* * Crop decoded image if the image size differs. */ if (orig_width != width || orig_height != height) { frame->height = orig_height; frame->width = orig_width; if (orig_width != width) { color_e band; /* current color band */ word_t *src, *dst; /* source and destination pointers */ unsigned y; /* current row */ for (band = first_band (frame->color); band <= last_band (frame->color); band++) { src = dst = frame->pixels [band]; for (y = orig_height; y; y--) { memmove (dst, src, orig_width * sizeof (word_t)); dst += orig_width; src += width; } if (format == FORMAT_4_2_0 && band == Y) { orig_width >>= 1; orig_height >>= 1; width >>= 1; } }