📄 decoder.c
字号:
u_word_t *offset, const unsigned *root_state, unsigned range_state, format_e format, const wfa_t *wfa)/* * Free memory of state images. * For more details refer to the inverse function 'alloc_state_images()'. * * No return value. * * Side effects: * arrays 'state_image' and 'offset' are discarded. */{ word_t marker; /* ptr is required as a marker */ unsigned level; if (range_state > 0) { state_image [range_state + max_level * wfa->states] = ▮ } else { unsigned state; /* * Initialize state image array with states at 'max_level' */ for (state = wfa->basis_states; state <= root_state [Y]; state++) if (wfa->level_of_state [state] == max_level) state_image [state + max_level * wfa->states] = ▮ if (color) { if (format == FORMAT_4_2_0) level = max_level - 2; else level = max_level; for (; state < wfa->states; state++) if (wfa->level_of_state [state] == level) state_image [state + level * wfa->states] = ▮ } } for (level = max_level; level > 0; level--) { int domain, child; unsigned state, label, edge; /* * Range approximation with child. */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) if (state_image [state + level * wfa->states]) for (label = 0; label < MAXLABELS; label++) if (ischild (child = wfa->tree[state][label])) { if (isedge (wfa->into[state][label][0]) && (state_image [child + (level - 1) * wfa->states] != &marker)) Free (state_image [child + (level - 1) * wfa->states]); state_image [child + (level - 1) * wfa->states] = ▮ } /* * Range approximation with linear combination */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) if (state_image [state + level * wfa->states]) for (label = 0; label < MAXLABELS; label++) for (edge = 0; isedge (domain = wfa->into[state][label][edge]); edge++) if (domain > 0 && (state_image [domain + (level - 1) * wfa->states] != NULL) && (state_image [domain + (level - 1) * wfa->states] != &marker)) { Free (state_image [domain + (level - 1) * wfa->states]); state_image [domain + (level - 1) * wfa->states] = ▮ } } Free (state_image); Free (offset);}static voidcompute_state_images (unsigned max_level, word_t **simg, const u_word_t *offset, const wfa_t *wfa)/* * Compute all state images of the 'wfa' at level {1, ... , 'max_level'} * which are marked in the array 'simg' (offsets of state images * are given by 'offset'). * * Warning: Several optimizations are used in this function making * it difficult to understand. * * No return value. * * Side effects: * state images (given by pointers in the array 'state_image') * are computed. */{ unsigned level, state; /* * Copy one-pixel images in case state_image pointer != &final distr. */ for (state = 1; state < wfa->states; state++) if (simg [state] != NULL) /* compute image at level 0 */ *simg [state] = (int) (wfa->final_distribution[state] * 8 + .5) * 2; /* * Compute images of states * Integer arithmetics are used rather than floating point operations. * 'weight' gives the weight in integer notation * 'src', 'dst', and 'idst' are pointers to the source and * destination pixels (short or integer format), respectively. * Short format : one operation per register (16 bit mode). * Integer format : two operations per register (32 bit mode). * 'src_offset', 'dst_offset', and 'dst_offset' give the number of * pixels which have to be omitted when jumping to the next image row. */ for (level = 1; level <= max_level; level++) { unsigned label; unsigned width = width_of_level (level - 1); unsigned height = height_of_level (level - 1); for (state = 1; state < wfa->states; state++) if (simg [state + level * wfa->states] != NULL) for (label = 0; label < MAXLABELS; label++) if (isedge (wfa->into [state][label][0])) { unsigned edge; int domain; word_t *range; /* address of current range */ bool_t prediction_used; /* ND prediction found ? */ /* * Compute address of range image */ if (level & 1) /* split vertically */ { range = simg [state + level * wfa->states] + label * (height_of_level (level - 1) * offset [state + level * wfa->states]); } else /* split horizontally */ { range = simg [state + level * wfa->states] + label * width_of_level (level - 1); } /* * Generate the state images by adding the corresponding * weighted state images: * subimage [label] = * weight_1 * image_1 + ... + weight_n * image_n */ if (!ischild (domain = wfa->tree[state][label])) prediction_used = NO; else { unsigned y; word_t *src; word_t *dst; unsigned src_offset; unsigned dst_offset; prediction_used = YES; /* * Copy child image */ src = simg [domain + (level - 1) * wfa->states]; src_offset = offset [domain + (level - 1) * wfa->states] ; dst = range; dst_offset = offset [state + level * wfa->states]; for (y = height; y; y--) { memcpy (dst, src, width * sizeof (word_t)); src += src_offset; dst += dst_offset; } } if (!prediction_used && isedge (domain = wfa->into[state][label][0])) { /* * If prediction is not used then the range is * filled with the first domain. No addition is needed. */ edge = 0; if (domain != 0) { int weight; word_t *src; unsigned src_offset; src = simg [domain + ((level - 1) * wfa->states)]; src_offset = offset [domain + ((level - 1) * wfa->states)] - width; weight = wfa->int_weight [state][label][edge]; if (width == 1) /* can't add two-pixels in a row */ { word_t *dst; unsigned dst_offset; dst = range; dst_offset = offset [state + level * wfa->states] - width;#ifdef HAVE_SIGNED_SHIFT *dst++ = ((weight * (int) *src++) >> 10) << 1;#else /* not HAVE_SIGNED_SHIFT */ *dst++ = ((weight * (int) *src++) / 1024) * 2;#endif /* not HAVE_SIGNED_SHIFT */ if (height == 2) { src += src_offset; dst += dst_offset;#ifdef HAVE_SIGNED_SHIFT *dst++ = ((weight * (int) *src++) >> 10) << 1;#else /* not HAVE_SIGNED_SHIFT */ *dst++ = ((weight * (int) *src++) / 1024) * 2;#endif /* not HAVE_SIGNED_SHIFT */ } } else { unsigned y; int *idst; unsigned idst_offset; idst = (int *) range; idst_offset = (offset [state + level * wfa->states] - width) / 2; for (y = height; y; y--) { int *comp_dst = idst + (width >> 1); for (; idst != comp_dst; ) { int tmp; /* temp. value of adjacent pixels */#ifdef HAVE_SIGNED_SHIFT# ifndef WORDS_BIGENDIAN tmp = (((weight * (int) src [1]) >> 10) << 17) | (((weight * (int) src [0]) >> 9) & 0xfffe);# else /* not WORDS_BIGENDIAN */ tmp = (((weight * (int) src [0]) >> 10) << 17) | (((weight * (int) src [1]) >> 9) & 0xfffe);# endif /* not WORDS_BIGENDIAN */#else /* not HAVE_SIGNED_SHIFT */# ifndef WORDS_BIGENDIAN tmp = (((weight * (int) src [1]) / 1024) * 131072) | (((weight * (int) src [0])/ 512) & 0xfffe);# else /* not WORDS_BIGENDIAN */ tmp = (((weight * (int) src [0]) / 1024) * 131072) | (((weight * (int) src [1]) / 512) & 0xfffe);# endif /* not WORDS_BIGENDIAN */#endif /* not HAVE_SIGNED_SHIFT */ src += 2; *idst++ = tmp & 0xfffefffe; } src += src_offset; idst += idst_offset; } } } else { int weight = (int) (wfa->weight[state][label][edge] * wfa->final_distribution[0] * 8 + .5) * 2; /* * Range needs domain 0 * (the constant function f(x, y) = 1), * hence a faster algorithm is used. */ if (width == 1) /* can't add two-pixels in a row */ { word_t *dst; unsigned dst_offset; dst = range; dst_offset = offset [state + level * wfa->states] - width; *dst++ = weight; if (height == 2) { dst += dst_offset; *dst++ = weight; } } else { unsigned x, y; int *idst; unsigned idst_offset; weight = (weight * 65536) | (weight & 0xffff); idst = (int *) range; idst_offset = offset [state + level * wfa->states] / 2; for (x = width >> 1; x; x--) *idst++ = weight & 0xfffefffe; idst += (offset [state + level * wfa->states] - width) / 2; for (y = height - 1; y; y--) { memcpy (idst, idst - idst_offset, width * sizeof (word_t)); idst += idst_offset; } } } edge = 1; } else edge = 0; /* * Add remaining weighted domain images to current range */ for (; isedge (domain = wfa->into[state][label][edge]); edge++) { if (domain != 0) { word_t *src; unsigned src_offset; int weight; src = simg [domain + (level - 1) * wfa->states]; src_offset = offset [domain + ((level - 1) * wfa->states)] - width; weight = wfa->int_weight [state][label][edge]; if (width == 1) /* can't add two-pixels in a row */ { word_t *dst; unsigned dst_offset; dst = range; dst_offset = offset [state + level * wfa->states] - width;#ifdef HAVE_SIGNED_SHIFT *dst++ += ((weight * (int) *src++) >> 10) << 1;#else /* not HAVE_SIGNED_SHIFT */ *dst++ += ((weight * (int) *src++) / 1024) * 2;#endif /* not HAVE_SIGNED_SHIFT */ if (height == 2) { src += src_offset; dst += dst_offset;#ifdef HAVE_SIGNED_SHIFT *dst++ += ((weight * (int) *src++) >> 10) << 1;#else /* not HAVE_SIGNED_SHIFT */ *dst++ += ((weight * (int) *src++) / 1024) * 2;#endif /* not HAVE_SIGNED_SHIFT */ } } else { int *idst; unsigned idst_offset; unsigned y; idst = (int *) range; idst_offset = (offset [state + level * wfa->states] - width) / 2; for (y = height; y; y--) { int *comp_dst = idst + (width >> 1); for (; idst != comp_dst;) { int tmp; /* temp. value of adjacent pixels */#ifdef HAVE_SIGNED_SHIFT# ifndef WORDS_BIGENDIAN tmp = (((weight * (int) src [1]) >> 10) << 17) | (((weight * (int) src [0]) >> 9) & 0xfffe);# else /* not WORDS_BIGENDIAN */ tmp = (((weight * (int)src [0]) >> 10) << 17) | (((weight * (int)src [1]) >> 9) & 0xfffe);# endif /* not WORDS_BIGENDIAN */#else /* not HAVE_SIGNED_SHIFT */# ifndef WORDS_BIGENDIAN tmp = (((weight * (int) src [1]) / 1024) * 131072) | (((weight * (int) src [0])/ 512) & 0xfffe);# else /* not WORDS_BIGENDIAN */ tmp = (((weight * (int) src [0]) / 1024) * 131072) | (((weight * (int) src [1])/ 512) & 0xfffe);# endif /* not WORDS_BIGENDIAN */#endif /* not HAVE_SIGNED_SHIFT */ src += 2; *idst = (*idst + tmp) & 0xfffefffe; idst++; } src += src_offset; idst += idst_offset; } } } else { int weight = (int) (wfa->weight[state][label][edge] * wfa->final_distribution[0] * 8 + .5) * 2; /* * Range needs domain 0 * (the constant function f(x, y) = 1), * hence a faster algorithm is used. */ if (width == 1) /* can't add two-pixels in a row */ { word_t *dst; unsigned dst_offset; dst = range; dst_offset = offset [state + level * wfa->states] - width; *dst++ += weight; if (height == 2) { dst += dst_offset; *dst++ += weight; } } else { int *idst; unsigned idst_offset; unsigned y; weight = (weight * 65536) | (weight & 0xffff); idst = (int *) range; idst_offset = (offset [state + level * wfa->states] - width) /2; for (y = height; y; y--) { int *comp_dst = idst + (width >> 1); for (; idst != comp_dst; ) { *idst = (*idst + weight) & 0xfffefffe; idst++; } idst += idst_offset; } } } } } }}static word_t *duplicate_state_image (const word_t *domain, unsigned offset, unsigned level)/* * Allocate new memory block 'pixels' and copy pixel values of 'domain' * (size and pixel offset are given by 'level' and 'offset') * to the lock 'pixels'. * * Return value: * pointer to the new domain block */{ word_t *dst, *pixels; int y, n; dst = pixels = Calloc (size_of_level (level), sizeof (word_t)); if (domain) for (y = height_of_level (level); y; y--) { memcpy (dst, domain, width_of_level (level) * sizeof (word_t)); dst += width_of_level (level); domain += offset; } else /* state 0 */ for (n = size_of_level (level); n; n--) *dst++ = (int) (128 * 8 + .5) * 2; return pixels;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -