#include "c4d_general.h" #include "c4d_shader.h" #include "c4d_memory.h" #include "matrixutil.h" #include "matrixrotate.h" typedef Int32 TYPE_apply_matrix_effect (MATRIX_REF emr, void** src_rows, void* dst, Int32 width); struct MATRIX_PRIVATE { Int32 color_space; Int32 no_components; WEIGHT_FMATRIX_MAX effect_matrix; TYPE_apply_matrix_effect* apply_effect; }; static void change_effect_matrix(const WEIGHT_FMATRIX* input_matrix, WEIGHT_FMATRIX* effect_matrix, Float32 opacity, Bool scale_matrix, Float64 angle); static void matrix_lineC(MATRIX_PRIVATE* emr, PIX_C** src_rows, PIX_C* dst, Int32 width); static void matrix_lineW(MATRIX_PRIVATE* emr, PIX_W** src_rows, PIX_W* dst, Int32 width); static void matrix_lineF(MATRIX_PRIVATE* emr, PIX_F** src_rows, PIX_F* dst, Int32 width); static void matrix_block8_q3(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width); static void matrix_block8_q5(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width); static void matrix_block8_q7(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width); static void matrix_line_alphaC(MATRIX_PRIVATE* emr, PIX_C** src_rows, PIX_C* dst, Int32 width); static void matrix_line_alphaW(MATRIX_PRIVATE* emr, PIX_W** src_rows, PIX_W* dst, Int32 width); static void matrix_line_alphaF(MATRIX_PRIVATE* emr, PIX_F** src_rows, PIX_F* dst, Int32 width); static void matrix_block_alpha8_q3(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width); static void matrix_block_alpha8_q5(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width); static void matrix_block_alpha8_q7(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width); //---------------------------------------------------------------------------------------- // Create a matrix object and set up the proper functions // Function result: matrix object // input_matrix: convolution matrix // color_space: color space of the pixel data (used for alpha support, ...) // px_format: pixel format (bits per component, number of components, ..) // opacity: 0.0: result of the convolution is transparent 1.0: result of the convolution completly replaces the source pixel // scale_matrix: false: ignore overflows true: scale matrix elements so that the sum is 1.0 (unless they sum to 0) // angle: rotation angle of the matrix (0 ... 2pi) //---------------------------------------------------------------------------------------- MATRIX_REF new_effect_matrix(const WEIGHT_FMATRIX* input_matrix, Int32 color_space, UInt32 px_format, Float32 opacity, Bool scale_matrix, Float64 angle) { MATRIX_PRIVATE* emr; emr = NewMemClear(MATRIX_PRIVATE, 1); if (emr) { emr->color_space = color_space; emr->no_components = get_PX_CMPNTS(px_format); change_effect_matrix(input_matrix, (WEIGHT_FMATRIX*) &emr->effect_matrix, opacity, scale_matrix, angle); update_effect_matrix(emr, color_space, px_format); } return (MATRIX_REF) emr; } Int32 delete_effect_matrix(MATRIX_REF emr) { if (emr) DeleteMem(emr); return 0; } void update_effect_matrix(MATRIX_REF t_emr, Int32 color_space, UInt32 px_format) { if (t_emr) { MATRIX_PRIVATE* emr = (MATRIX_PRIVATE*)t_emr; emr->color_space = color_space; emr->no_components = get_PX_CMPNTS(px_format); switch (get_PX_DEPTH(px_format)) { case PX_DEPTH_8: if (color_space & CSPACE_ALPHA_FLAG) // take care of alpha? { emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_line_alphaC; if (emr->effect_matrix.no_matrix_rows == emr->effect_matrix.no_matrix_columns) // square matrix? { switch (emr->effect_matrix.no_matrix_rows) { case 3: emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_block_alpha8_q3; break; case 5: emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_block_alpha8_q5; break; case 7: emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_block_alpha8_q7; break; } } } else // color space without alpha { emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_lineC; if (emr->effect_matrix.no_matrix_rows == emr->effect_matrix.no_matrix_columns) // square matrix? { switch (emr->effect_matrix.no_matrix_rows) { case 3: emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_block8_q3; break; case 5: emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_block8_q5; break; case 7: emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_block8_q7; break; } } } break; case PX_DEPTH_16: if (color_space & CSPACE_ALPHA_FLAG) emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_line_alphaW; else emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_lineW; break; case PX_DEPTH_32: if (color_space & CSPACE_ALPHA_FLAG) emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_line_alphaF; else emr->apply_effect = (TYPE_apply_matrix_effect*) matrix_lineF; break; } } } Int32 apply_matrix_effect(MATRIX_REF emr, void** src_rows, void* dst, Int32 width) { if (!((MATRIX_PRIVATE*) emr)->apply_effect) return 0; ((MATRIX_PRIVATE*) emr)->apply_effect(emr, src_rows, dst, width); return 0; } Int32 get_effect_matrix_info(MATRIX_REF _emr, Int32* no_columns, Int32* no_rows, Int32* x_origin, Int32* y_origin) { MATRIX_PRIVATE* emr; emr = (MATRIX_PRIVATE*) _emr; if (no_columns) *no_columns = emr->effect_matrix.no_matrix_columns; if (no_rows) *no_rows = emr->effect_matrix.no_matrix_rows; if (x_origin) *x_origin = emr->effect_matrix.x_origin; if (y_origin) *y_origin = emr->effect_matrix.y_origin; return 0; } static void change_effect_matrix(const WEIGHT_FMATRIX* input_matrix, WEIGHT_FMATRIX* effect_matrix, Float32 opacity, Bool scale_matrix, Float64 angle) { #define MIN_VALUE 0.00001 // cutoff value for scaling Int32 no_elements; Int32 i; Int32 j; const Float32* src_value; Float32* dst_value; Float32 matrix_sum; Float32 v; *effect_matrix = *input_matrix; // copy the header src_value = input_matrix->matrix_values; dst_value = effect_matrix->matrix_values; matrix_sum = 0; for (j = 0; j < effect_matrix->no_matrix_rows; j++) { for (i = 0; i < effect_matrix->no_matrix_columns; i++) { v = *src_value++; *dst_value++ = v; matrix_sum += v; } } if (angle) // rotate matrix? { rotate_matrix(input_matrix, effect_matrix, angle); if (scale_matrix && (matrix_sum >= MIN_VALUE)) // rotation might have produced some rounding errors { matrix_sum = 0; dst_value = effect_matrix->matrix_values; // therefore build the sum again for (j = 0; j < effect_matrix->no_matrix_rows; j++) { for (i = 0; i < effect_matrix->no_matrix_columns; i++) matrix_sum += *dst_value++; } } } if (scale_matrix) // scale the matrix to avoid cutting off color values { if (matrix_sum < 0) matrix_sum = -matrix_sum; if (matrix_sum < MIN_VALUE) // avoid division by zero (take rounding errors into account) matrix_sum = 1.0; } else // no scaling, allow overflow { matrix_sum = 1.0; } no_elements = effect_matrix->no_matrix_rows * effect_matrix->no_matrix_columns; dst_value = effect_matrix->matrix_values; for (i = no_elements; i > 0; i--) // scale and blend matrix elements { v = (*dst_value / matrix_sum) * opacity; *dst_value++ = v; } dst_value = effect_matrix->matrix_values; dst_value += effect_matrix->y_origin * effect_matrix->no_matrix_columns; dst_value += effect_matrix->x_origin; v = 1.0 - opacity; // add amount of the source pixel *dst_value += v; #undef MIN_MVALUE } //---------------------------------------------------------------------------------------- // General matrix handling for pixels with 8 bits per component // Function result: - // emr: matrix data // src_rows: array with pointers to the source lines // dst: pointer to the dst line // no_components: number of color components per pixel //---------------------------------------------------------------------------------------- static void matrix_lineC(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; for (c = 0; c < no_components; c++, x_offset++) { Int32 my; Float32* matrix_values; Float32 n; n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { UChar* src; Int32 mx; src = src_rows[my] + x_offset; // select the right color component for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src; src += no_components; // next pixel } } if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } static void matrix_lineW(MATRIX_PRIVATE* emr, PIX_W** src_rows, PIX_W* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; for (c = 0; c < no_components; c++, x_offset++) { Int32 my; Float32* matrix_values; Float32 n; n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { PIX_W* src; Int32 mx; src = src_rows[my] + x_offset; // select the right color component for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src; src += no_components; // next pixel } } if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 65535.0) n = 65535.0; *dst++ = (PIX_W) (n + 0.5); } } } static void matrix_lineF(MATRIX_PRIVATE* emr, PIX_F** src_rows, PIX_F* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; for (c = 0; c < no_components; c++, x_offset++) { Int32 my; Float32* matrix_values; Float32 n; n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { PIX_F* src; Int32 mx; src = src_rows[my] + x_offset; // select the right color component for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src; src += no_components; // next pixel } } *dst++ = n; } } } // 3*3 matrix static void matrix_block8_q3(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; for (c = 0; c < no_components; c++, x_offset++) { Float32* matrix_values; Float32 n; UChar* src; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src = src_rows[1] + x_offset; // next line, select the right color component n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[2] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } // 5*5 matrix static void matrix_block8_q5(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; for (c = 0; c < no_components; c++, x_offset++) { Float32* matrix_values; Float32 n; UChar* src; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src = src_rows[1] + x_offset; // next line, select the right color component n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[2] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[3] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[4] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } // 7*7 matrix static void matrix_block8_q7(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; for (c = 0; c < no_components; c++, x_offset++) { Float32* matrix_values; Float32 n; UChar* src; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src = src_rows[1] + x_offset; // next line, select the right color component n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[2] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[3] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[4] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[5] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[6] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } //---------------------------------------------------------------------------------------- // Blur line with alpha channel // Function result: - // src_rows: array with pointers to the source lines // dst: pointer to the dst line // no_components: number of color components per pixel // matrix: //---------------------------------------------------------------------------------------- static void matrix_line_alphaC(MATRIX_PRIVATE* emr, PIX_C** src_rows, PIX_C* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; Int32 my; Float32* matrix_values; Float32 new_alpha; Float32 n; n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { UChar* src; Int32 mx; src = src_rows[my] + x_offset; for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src; src += no_components; // next pixel } } new_alpha = n; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); if (new_alpha == 0.0) // is the matrixred pixel invisible? new_alpha = 1.0; // avoid division by zero for (c = 1, x_offset++; c < no_components; c++, x_offset++) // weigh every color component with its alpha and matrix value { n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { UChar* src; UChar* alpha; Int32 mx; src = src_rows[my] + x_offset; // select the right color component alpha = src - c; for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel } } n /= new_alpha; // new color component of the matrixred pixel (has to take the sum of the alphas into account) if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } static void matrix_line_alphaW(MATRIX_PRIVATE* emr, PIX_W** src_rows, PIX_W* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; Int32 my; Float32* matrix_values; Float32 new_alpha; Float32 n; n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { PIX_W* src; Int32 mx; src = src_rows[my] + x_offset; for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src; src += no_components; // next pixel } } new_alpha = n; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 65535.0) n = 65535.0; *dst++ = (PIX_W) (n + 0.5); if (new_alpha == 0.0) // is the matrixred pixel invisible? new_alpha = 1.0; // avoid division by zero for (c = 1, x_offset++; c < no_components; c++, x_offset++) // weigh every color component with its alpha and matrix value { n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { PIX_W* src; PIX_W* alpha; Int32 mx; src = src_rows[my] + x_offset; // select the right color component alpha = src - c; for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel } } n /= new_alpha; // new color component of the matrixred pixel (has to take the sum of the alphas into account) if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 65535.0) n = 65535.0; *dst++ = (PIX_W) (n + 0.5); } } } static void matrix_line_alphaF(MATRIX_PRIVATE* emr, PIX_F** src_rows, PIX_F* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; Int32 my; Float32* matrix_values; Float32 new_alpha; Float32 n; n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { PIX_F* src; Int32 mx; src = src_rows[my] + x_offset; for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src; src += no_components; // next pixel } } new_alpha = n; *dst++ = n; if (new_alpha == 0.0) // is the matrixred pixel invisible? new_alpha = 1.0; // avoid division by zero for (c = 1, x_offset++; c < no_components; c++, x_offset++) // weigh every color component with its alpha and matrix value { n = 0; matrix_values = matrix->matrix_values; for (my = 0; my < matrix->no_matrix_rows; my++) { PIX_F* src; PIX_F* alpha; Int32 mx; src = src_rows[my] + x_offset; // select the right color component alpha = src - c; for (mx = matrix->no_matrix_columns; mx > 0; mx--) // weigh the components of a source line { n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel } } n /= new_alpha; // new color component of the matrixred pixel (has to take the sum of the alphas into account) *dst++ = n; } } } // 3*3 matrix static void matrix_block_alpha8_q3(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; Float32* matrix_values; Float32 new_alpha; Float32 n; UChar* src; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src = src_rows[1] + x_offset; // next line, select the right color component n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[2] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; new_alpha = n; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); if (new_alpha == 0.0) // is the matrixred pixel invisible? new_alpha = 1.0; // avoid division by zero for (c = 1, x_offset++; c < no_components; c++, x_offset++) // weigh every color component with its alpha and matrix value { UChar* src; UChar* alpha; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[1] + x_offset; // next line, select the right color component alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[2] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; n /= new_alpha; // new color component of the matrixred pixel (has to take the sum of the alphas into account) if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } // 5*5 matrix static void matrix_block_alpha8_q5(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; Float32* matrix_values; Float32 new_alpha; Float32 n; UChar* src; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src = src_rows[1] + x_offset; // next line, select the right color component n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[2] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[3] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[4] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; new_alpha = n; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); if (new_alpha == 0.0) // is the matrixed pixel invisible? new_alpha = 1.0; // avoid division by zero for (c = 1, x_offset++; c < no_components; c++, x_offset++) // weigh every color component with its alpha and matrix value { UChar* src; UChar* alpha; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[1] + x_offset; // next line, select the right color component alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[2] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[3] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[4] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; n /= new_alpha; // new color component of the matrixred pixel (has to take the sum of the alphas into account) if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } } // 7*7 matrix static void matrix_block_alpha8_q7(MATRIX_PRIVATE* emr, UChar** src_rows, UChar* dst, Int32 width) { WEIGHT_FMATRIX* matrix; Int32 no_components; Int32 x_offset; no_components = emr->no_components; matrix = (WEIGHT_FMATRIX*) &emr->effect_matrix; for (x_offset = 0; width > 0; width--) { Int32 c; Float32* matrix_values; Float32 new_alpha; Float32 n; UChar* src; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src += no_components; // next pixel n += *matrix_values++ *(Float32) * src; // weigh the components of a source line src = src_rows[1] + x_offset; // next line, select the right color component n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[2] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[3] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[4] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[5] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src = src_rows[6] + x_offset; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; src += no_components; n += *matrix_values++ *(Float32) * src; new_alpha = n; if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); if (new_alpha == 0.0) // is the matrixred pixel invisible? new_alpha = 1.0; // avoid division by zero for (c = 1, x_offset++; c < no_components; c++, x_offset++) // weigh every color component with its alpha and matrix value { UChar* src; UChar* alpha; n = 0; matrix_values = matrix->matrix_values; src = src_rows[0] + x_offset; // select the right color component alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; // next pixel src += no_components; // next pixel n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[1] + x_offset; // next line, select the right color component alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[2] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[3] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[4] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[5] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; src = src_rows[6] + x_offset; alpha = src - c; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; alpha += no_components; src += no_components; n += *matrix_values++ *(Float32) * src * (Float32) * alpha; n /= new_alpha; // new color component of the matrixred pixel (has to take the sum of the alphas into account) if (n < 0.0) // clamp component if the sum of the matrix elements is not 1.0 n = 0.0; if (n > 255.0) n = 255.0; *dst++ = (UChar) (n + 0.5); } } }