From 70cec44587b7401c7afd8d91079c4ff6f79e6baa Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Mon, 19 Nov 2001 17:21:03 +0000 Subject: [PATCH] app/paint-funcs/paint-funcs.c app/paint-funcs/paint-funcs-generic.h 2001-11-19 Daniel Egger * app/paint-funcs/paint-funcs.c * app/paint-funcs/paint-funcs-generic.h * app/paint-funcs/paint-funcs.h: - Statified a few functions so they can be inlined. - Simplified function calls. - Unsignified variables and parameters where possible. - Reduced lookuptable size for add_pixels from 256*256*4 bytes to 2*256-1 bytes and O(n*n) function in paint_funcs_setup to O(n). Should reduce memory consumption by almost 1/4 Mb. This needs much more cleanup.... --- ChangeLog | 14 ++ app/paint-funcs/paint-funcs-generic.h | 9 +- app/paint-funcs/paint-funcs.c | 320 ++++++++++++-------------- app/paint-funcs/paint-funcs.h | 166 +++---------- 4 files changed, 207 insertions(+), 302 deletions(-) diff --git a/ChangeLog b/ChangeLog index bcbe13dbb1..f5b81abf73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2001-11-19 Daniel Egger + + * app/paint-funcs/paint-funcs.c + * app/paint-funcs/paint-funcs-generic.h + * app/paint-funcs/paint-funcs.h: + - Statified a few functions so they can be inlined. + - Simplified function calls. + - Unsignified variables and parameters where possible. + - Reduced lookuptable size for add_pixels from 256*256*4 bytes + to 2*256-1 bytes and O(n*n) function in paint_funcs_setup + to O(n). Should reduce memory consumption by almost 1/4 Mb. + + This needs much more cleanup.... + 2001-11-19 Daniel Egger * app/paint-funcs/paint-funcs-mmx.h: New file. Added glue code diff --git a/app/paint-funcs/paint-funcs-generic.h b/app/paint-funcs/paint-funcs-generic.h index 401be65216..43a2622534 100644 --- a/app/paint-funcs/paint-funcs-generic.h +++ b/app/paint-funcs/paint-funcs-generic.h @@ -61,11 +61,11 @@ struct apply_layer_mode_struct gint y; guint opacity; guint length; - guint combine; + CombinationMode combine; }; static const guchar no_mask = OPAQUE_OPACITY; -static gint add_lut[256][256]; +static guchar add_lut[511]; static gint random_table[RANDOM_TABLE_SIZE]; void @@ -755,10 +755,7 @@ add_pixels (const guchar *src1, while (length --) { for (b = 0; b < alpha; b++) - { - /* TODO: wouldn't it be better use a 1 dimensional lut ie. add_lut[src1+src2]; */ - dest[b] = add_lut[(src1[b])] [(src2[b])]; - } + dest[b] = add_lut[src1[b] + src2[b]]; if (has_alpha1 && has_alpha2) dest[alpha] = MIN (src1[alpha], src2[alpha]); diff --git a/app/paint-funcs/paint-funcs.c b/app/paint-funcs/paint-funcs.c index db2cf4ef74..901d9b473c 100644 --- a/app/paint-funcs/paint-funcs.c +++ b/app/paint-funcs/paint-funcs.c @@ -121,10 +121,6 @@ static LayerModeFunc layer_mode_funcs[] = static gint * make_curve (gdouble sigma, gint *length); -static void run_length_encode (guchar *src, - gint *dest, - gint w, - gint bytes); static gdouble cubic (gdouble dx, gint jm1, gint j, @@ -371,15 +367,15 @@ make_curve (gdouble sigma, } -static void -run_length_encode (guchar *src, - gint *dest, - gint w, - gint bytes) +static inline void +run_length_encode (const guchar *src, + guint *dest, + guint w, + guint bytes) { - gint start; - gint i; - gint j; + guint start; + guint i; + guint j; guchar last; last = *src; @@ -429,9 +425,7 @@ cubic (gdouble dx, void paint_funcs_setup (void) { - gint i; - gint j, k; - gint tmp_sum; + guint i; /* generate a table of random seeds */ srand (RANDOM_SEED); @@ -439,18 +433,11 @@ paint_funcs_setup (void) for (i = 0; i < RANDOM_TABLE_SIZE; i++) random_table[i] = rand (); - for (j = 0; j < 256; j++) - { /* rows */ - for (k = 0; k < 256; k++) - { /* column */ - tmp_sum = j + k; - - if (tmp_sum > 255) - tmp_sum = 255; - - add_lut[j][k] = tmp_sum; - } - } + for (i = 0; i < 256; i++) + add_lut[i] = i; + + for (i = 256; i <= 510; i++) + add_lut[i] = 255; #ifdef HAVE_ASM_MMX if (use_mmx) @@ -1389,7 +1376,12 @@ combine_inten_a_and_channel_selection_pixels (const guchar *src, } -void +/* paint "behind" the existing pixel row. + * This is similar in appearance to painting on a layer below + * the existing pixels. + */ + +static inline void behind_inten_pixels (const guchar *src1, const guchar *src2, guchar *dest, @@ -1397,12 +1389,12 @@ behind_inten_pixels (const guchar *src1, gint opacity, const gboolean *affect, gint length, - gint bytes1, - gint bytes2, - gint has_alpha1, - gint has_alpha2) + guint bytes1, + guint bytes2) { - gint alpha, b; + // FIXME: Is this supposed to be different than in the other functions? + const guint alpha = bytes1 - 1; + guint b; guchar src1_alpha; guchar src2_alpha; guchar new_alpha; @@ -1415,9 +1407,6 @@ behind_inten_pixels (const guchar *src1, else m = &no_mask; - /* the alpha channel */ - alpha = bytes1 - 1; - while (length --) { src1_alpha = src1[alpha]; @@ -1447,20 +1436,24 @@ behind_inten_pixels (const guchar *src1, } -void +/* paint "behind" the existing pixel row (for indexed images). + * This is similar in appearance to painting on a layer below + * the existing pixels. + */ + +static inline void behind_indexed_pixels (const guchar *src1, const guchar *src2, guchar *dest, const guchar *mask, - gint opacity, + guint opacity, const gboolean *affect, - gint length, - gint bytes1, - gint bytes2, - gint has_alpha1, - gint has_alpha2) + guint length, + guint bytes1, + guint bytes2) { - gint alpha, b; + const guint alpha = bytes1 - 1; + guint b; guchar src1_alpha; guchar src2_alpha; guchar new_alpha; @@ -1473,7 +1466,6 @@ behind_indexed_pixels (const guchar *src1, m = &no_mask; /* the alpha channel */ - alpha = bytes1 - 1; while (length --) { @@ -1495,22 +1487,26 @@ behind_indexed_pixels (const guchar *src1, } -void +/* replace the contents of one pixel row with the other + * The operation is still bounded by mask/opacity constraints + */ + +static inline void replace_inten_pixels (const guchar *src1, const guchar *src2, guchar *dest, const guchar *mask, - gint opacity, + guint opacity, const gboolean *affect, - gint length, - gint bytes1, - gint bytes2, - gint has_alpha1, - gint has_alpha2) + guint length, + guint bytes1, + guint bytes2) { - gint b; + const guint has_alpha1 = HAS_ALPHA (bytes1); + const guint has_alpha2 = HAS_ALPHA (bytes2); + const guint bytes = MIN (bytes1, bytes2); + guint b; gint tmp; - const gint bytes = MIN (bytes1, bytes2); if (mask) { @@ -1538,7 +1534,7 @@ replace_inten_pixels (const guchar *src1, } else { - static const guchar mask_alpha = OPAQUE_OPACITY ; + const guchar mask_alpha = OPAQUE_OPACITY; while (length --) { @@ -1557,23 +1553,27 @@ replace_inten_pixels (const guchar *src1, } } +/* replace the contents of one pixel row with the other + * The operation is still bounded by mask/opacity constraints + */ -void +static inline void replace_indexed_pixels (const guchar *src1, const guchar *src2, guchar *dest, const guchar *mask, - gint opacity, + guint opacity, const gboolean *affect, - gint length, - gint bytes1, - gint bytes2, - gint has_alpha1, - gint has_alpha2) + guint length, + guint bytes1, + guint bytes2) { - gint bytes, b; - guchar mask_alpha; + const guint has_alpha1 = HAS_ALPHA (bytes1); + const guint has_alpha2 = HAS_ALPHA (bytes2); + const guint bytes = MIN (bytes1, bytes2); const guchar *m; + guint b; + guchar mask_alpha; gint tmp; if (mask) @@ -1581,7 +1581,6 @@ replace_indexed_pixels (const guchar *src1, else m = &no_mask; - bytes = MIN (bytes1, bytes2); while (length --) { mask_alpha = INT_MULT(*m, opacity, tmp); @@ -1601,21 +1600,24 @@ replace_indexed_pixels (const guchar *src1, } } +/* apply source 2 to source 1, but in a non-additive way, + * multiplying alpha channels (works for intensity) + */ -void +static inline void erase_inten_pixels (const guchar *src1, const guchar *src2, guchar *dest, const guchar *mask, - gint opacity, + guint opacity, const gboolean *affect, - gint length, - gint bytes) + guint length, + guint bytes) { - gint b; + const guint alpha = bytes - 1; + guint b; guchar src2_alpha; glong tmp; - const gint alpha = bytes - 1; if (mask) { @@ -1656,27 +1658,31 @@ erase_inten_pixels (const guchar *src1, } -void +/* apply source 2 to source 1, but in a non-additive way, + * multiplying alpha channels (works for indexed) + */ + +static inline void erase_indexed_pixels (const guchar *src1, const guchar *src2, guchar *dest, const guchar *mask, - gint opacity, + guint opacity, const gboolean *affect, - gint length, - gint bytes) + guint length, + guint bytes) { - gint alpha, b; - guchar src2_alpha; + const guint alpha = bytes - 1; const guchar *m; - glong tmp; + guchar src2_alpha; + guint b; + glong tmp; if (mask) m = mask; else m = &no_mask; - alpha = bytes - 1; while (length --) { for (b = 0; b < alpha; b++) @@ -4019,10 +4025,10 @@ copy_gray_to_region (PixelRegion *src, struct initial_regions_struct { - gint opacity; + guint opacity; LayerModeEffects mode; gboolean *affect; - gint type; + InitialMode type; guchar *data; }; @@ -4036,10 +4042,10 @@ initial_sub_region (struct initial_regions_struct *st, guchar *s, *d, *m; guchar buf[512]; guchar *data; - gint opacity; + guint opacity; LayerModeEffects mode; gboolean *affect; - gint type; + InitialMode type; data = st->data; opacity = st->opacity; @@ -4112,7 +4118,7 @@ initial_region (PixelRegion *src, gint opacity, LayerModeEffects mode, gboolean *affect, - gint type) + InitialMode type) { struct initial_regions_struct st; @@ -4131,13 +4137,50 @@ struct combine_regions_struct gint opacity; LayerModeEffects mode; gboolean *affect; - gint type; + CombinationMode type; guchar *data; - gboolean has_alpha1, has_alpha2; + //gboolean has_alpha1, has_alpha2; gboolean opacity_quickskip_possible; gboolean transparency_quickskip_possible; }; +static inline CombinationMode +apply_indexed_layer_mode (guchar *src1, + guchar *src2, + guchar **dest, + LayerModeEffects mode, + CombinationMode cmode) +{ + /* assumes we're applying src2 TO src1 */ + switch (mode) + { + case REPLACE_MODE: + *dest = src2; + cmode = REPLACE_INDEXED; + break; + + case BEHIND_MODE: + *dest = src2; + if (cmode == COMBINE_INDEXED_A_INDEXED_A) + cmode = BEHIND_INDEXED; + else + cmode = NO_COMBINATION; + break; + + case ERASE_MODE: + *dest = src2; + /* If both sources have alpha channels, call erase function. + * Otherwise, just combine in the normal manner + */ + cmode = (cmode == COMBINE_INDEXED_A_INDEXED_A) ? ERASE_INDEXED : cmode; + break; + + default: + break; + } + + return cmode; +} void @@ -4148,13 +4191,12 @@ combine_sub_region (struct combine_regions_struct *st, PixelRegion *mask) { guchar *data; - gint opacity; + guint opacity; LayerModeEffects mode; gboolean *affect; - gint type; - gint h; - gboolean has_alpha1, has_alpha2; - guint combine = 0; + guint h; + CombinationMode combine = NO_COMBINATION; + CombinationMode type; guint mode_affect = 0; guchar *s, *s1, *s2; guchar *d, *m; @@ -4168,8 +4210,6 @@ combine_sub_region (struct combine_regions_struct *st, affect = st->affect; type = st->type; data = st->data; - has_alpha1 = st->has_alpha1; - has_alpha2 = st->has_alpha2; opacity_quickskip_possible = (st->opacity_quickskip_possible && src2->tiles); @@ -4233,8 +4273,7 @@ combine_sub_region (struct combine_regions_struct *st, case COMBINE_INDEXED_INDEXED_A: case COMBINE_INDEXED_A_INDEXED_A: /* Now, apply the paint mode--for indexed images */ - combine = apply_indexed_layer_mode (s1, s2, &s, mode, - has_alpha1, has_alpha2); + combine = apply_indexed_layer_mode (s1, s2, &s, mode, type); break; case COMBINE_INTEN_INTEN_A: @@ -4250,6 +4289,7 @@ combine_sub_region (struct combine_regions_struct *st, alms.x = src1->x; alms.y = src1->y + h; alms.opacity = opacity; + alms.combine = combine; alms.length = src1->w; alms.bytes1 = src1->bytes; alms.bytes2 = src2->bytes; @@ -4261,7 +4301,7 @@ combine_sub_region (struct combine_regions_struct *st, mode_affect = layer_modes[mode].affect_alpha; layer_mode_funcs[mode](&alms); - combine = (alms.combine == 0) ? type : alms.combine; + combine = (alms.combine == NO_COMBINATION) ? type : alms.combine; break; } @@ -4351,25 +4391,25 @@ combine_sub_region (struct combine_regions_struct *st, case BEHIND_INTEN: behind_inten_pixels (s1, s, d, m, opacity, affect, src1->w, src1->bytes, - src2->bytes, has_alpha1, has_alpha2); + src2->bytes); break; case BEHIND_INDEXED: behind_indexed_pixels (s1, s, d, m, opacity, affect, src1->w, src1->bytes, - src2->bytes, has_alpha1, has_alpha2); + src2->bytes); break; case REPLACE_INTEN: replace_inten_pixels (s1, s, d, m, opacity, affect, src1->w, src1->bytes, - src2->bytes, has_alpha1, has_alpha2); + src2->bytes); break; case REPLACE_INDEXED: replace_indexed_pixels (s1, s, d, m, opacity, affect, src1->w, src1->bytes, - src2->bytes, has_alpha1, has_alpha2); + src2->bytes); break; case ERASE_INTEN: @@ -4397,7 +4437,7 @@ combine_sub_region (struct combine_regions_struct *st, break; default: - g_warning("UNKNOWN COMBINATION"); + g_warning("UNKNOWN COMBINATION: %d", combine); break; } @@ -4417,13 +4457,13 @@ combine_regions (PixelRegion *src1, PixelRegion *dest, PixelRegion *mask, guchar *data, - gint opacity, + guint opacity, LayerModeEffects mode, gboolean *affect, - gint type) + CombinationMode type) { gboolean has_alpha1, has_alpha2; - gint i; + guint i; struct combine_regions_struct st; /* Determine which sources have alpha channels */ @@ -4455,8 +4495,6 @@ combine_regions (PixelRegion *src1, st.affect = affect; st.type = type; st.data = data; - st.has_alpha1 = has_alpha1; - st.has_alpha2 = has_alpha2; /* cheap and easy when the row of src2 is completely opaque/transparent and the wind is otherwise blowing in the right direction. @@ -4502,16 +4540,16 @@ combine_regions (PixelRegion *src1, } void -combine_regions_replace (PixelRegion *src1, - PixelRegion *src2, - PixelRegion *dest, - PixelRegion *mask, - guchar *data, - gint opacity, - gboolean *affect, - gint type) +combine_regions_replace (PixelRegion *src1, + PixelRegion *src2, + PixelRegion *dest, + PixelRegion *mask, + guchar *data, + guint opacity, + gboolean *affect, + CombinationMode type) { - gint h; + guint h; guchar *s1; guchar *s2; guchar *d; @@ -4543,58 +4581,6 @@ combine_regions_replace (PixelRegion *src1, } } - - -gint -apply_indexed_layer_mode (guchar *src1, - guchar *src2, - guchar **dest, - LayerModeEffects mode, - gboolean has_alpha1, /* has alpha */ - gboolean has_alpha2) /* has alpha */ -{ - gint combine; - - if (!has_alpha1 && !has_alpha2) - combine = COMBINE_INDEXED_INDEXED; - else if (!has_alpha1 && has_alpha2) - combine = COMBINE_INDEXED_INDEXED_A; - else if (has_alpha1 && has_alpha2) - combine = COMBINE_INDEXED_A_INDEXED_A; - else - combine = NO_COMBINATION; - - /* assumes we're applying src2 TO src1 */ - switch (mode) - { - case REPLACE_MODE: - *dest = src2; - combine = REPLACE_INDEXED; - break; - - case BEHIND_MODE: - *dest = src2; - if (has_alpha1) - combine = BEHIND_INDEXED; - else - combine = NO_COMBINATION; - break; - - case ERASE_MODE: - *dest = src2; - /* If both sources have alpha channels, call erase function. - * Otherwise, just combine in the normal manner - */ - combine = (has_alpha1 && has_alpha2) ? ERASE_INDEXED : combine; - break; - - default: - break; - } - - return combine; -} - static void apply_layer_mode_replace (guchar *src1, guchar *src2, diff --git a/app/paint-funcs/paint-funcs.h b/app/paint-funcs/paint-funcs.h index b7bf44b05e..f0f505f4b7 100644 --- a/app/paint-funcs/paint-funcs.h +++ b/app/paint-funcs/paint-funcs.h @@ -236,92 +236,6 @@ void combine_inten_a_and_channel_selection_pixels(const unsigned char *src, int length, int bytes); -/* paint "behind" the existing pixel row. - * This is similar in appearance to painting on a layer below - * the existing pixels. - */ -void behind_inten_pixels (const unsigned char *src1, - const unsigned char *src2, - unsigned char *dest, - const unsigned char *mask, - int opacity, - const int *affect, - int length, - int bytes1, - int bytes2, - int has_alpha1, - int has_alpha2); - -/* paint "behind" the existing pixel row (for indexed images). - * This is similar in appearance to painting on a layer below - * the existing pixels. - */ -void behind_indexed_pixels (const unsigned char *src1, - const unsigned char *src2, - unsigned char *dest, - const unsigned char *mask, - int opacity, - const int *affect, - int length, - int bytes1, - int bytes2, - int has_alpha1, - int has_alpha2); - -/* replace the contents of one pixel row with the other - * The operation is still bounded by mask/opacity constraints - */ -void replace_inten_pixels (const unsigned char *src1, - const unsigned char *src2, - unsigned char *dest, - const unsigned char *mask, - int opacity, - const int *affect, - int length, - int bytes1, - int bytes2, - int has_alpha1, - int has_alpha2); - -/* replace the contents of one pixel row with the other - * The operation is still bounded by mask/opacity constraints - */ -void replace_indexed_pixels (const unsigned char *src1, - const unsigned char *src2, - unsigned char *dest, - const unsigned char *mask, - int opacity, - const int *affect, - int length, - int bytes1, - int bytes2, - int has_alpha1, - int has_alpha2); - -/* apply source 2 to source 1, but in a non-additive way, - * multiplying alpha channels (works for intensity) - */ -void erase_inten_pixels (const unsigned char *src1, - const unsigned char *src2, - unsigned char *dest, - const unsigned char *mask, - int opacity, - const int *affect, - int length, - int bytes); - -/* apply source 2 to source 1, but in a non-additive way, - * multiplying alpha channels (works for indexed) - */ -void erase_indexed_pixels (const unsigned char *src1, - const unsigned char *src2, - unsigned char *dest, - const unsigned char *mask, - int opacity, - const int *affect, - int length, - int bytes); - /* extract information from intensity pixels based on * a mask. */ @@ -429,38 +343,44 @@ void copy_gray_to_region (PixelRegion *, PixelRegion *); * images, floating selections, selective display of intensity * channels, and display of arbitrary mask channels */ -#define INITIAL_CHANNEL_MASK 0 -#define INITIAL_CHANNEL_SELECTION 1 -#define INITIAL_INDEXED 2 -#define INITIAL_INDEXED_ALPHA 3 -#define INITIAL_INTENSITY 4 -#define INITIAL_INTENSITY_ALPHA 5 +typedef enum +{ +INITIAL_CHANNEL_MASK = 0, +INITIAL_CHANNEL_SELECTION, +INITIAL_INDEXED, +INITIAL_INDEXED_ALPHA, +INITIAL_INTENSITY, +INITIAL_INTENSITY_ALPHA, +} InitialMode; /* Combine two source regions with the help of an optional mask * region into a destination region. This is used for constructing * layer projections, and for applying image patches to an image */ -#define COMBINE_INDEXED_INDEXED 0 -#define COMBINE_INDEXED_INDEXED_A 1 -#define COMBINE_INDEXED_A_INDEXED_A 2 -#define COMBINE_INTEN_A_INDEXED_A 3 -#define COMBINE_INTEN_A_CHANNEL_MASK 4 -#define COMBINE_INTEN_A_CHANNEL_SELECTION 5 -#define COMBINE_INTEN_INTEN 6 -#define COMBINE_INTEN_INTEN_A 7 -#define COMBINE_INTEN_A_INTEN 8 -#define COMBINE_INTEN_A_INTEN_A 9 +typedef enum +{ + NO_COMBINATION = 0, + COMBINE_INDEXED_INDEXED, + COMBINE_INDEXED_INDEXED_A, + COMBINE_INDEXED_A_INDEXED_A, + COMBINE_INTEN_A_INDEXED_A, + COMBINE_INTEN_A_CHANNEL_MASK, + COMBINE_INTEN_A_CHANNEL_SELECTION, + COMBINE_INTEN_INTEN, + COMBINE_INTEN_INTEN_A, + COMBINE_INTEN_A_INTEN, + COMBINE_INTEN_A_INTEN_A, -/* Non-conventional combination modes */ -#define BEHIND_INTEN 20 -#define BEHIND_INDEXED 21 -#define REPLACE_INTEN 22 -#define REPLACE_INDEXED 23 -#define ERASE_INTEN 24 -#define ERASE_INDEXED 25 -#define ANTI_ERASE_INTEN 26 -#define ANTI_ERASE_INDEXED 27 -#define NO_COMBINATION 28 + /* Non-conventional combination modes */ + BEHIND_INTEN, + BEHIND_INDEXED, + REPLACE_INTEN, + REPLACE_INDEXED, + ERASE_INTEN, + ERASE_INDEXED, + ANTI_ERASE_INTEN, + ANTI_ERASE_INDEXED, +} CombinationMode; /* Opacities */ #define TRANSPARENT_OPACITY 0 @@ -468,30 +388,18 @@ void copy_gray_to_region (PixelRegion *, PixelRegion *); void initial_region (PixelRegion *, PixelRegion *, PixelRegion *, unsigned char *, - int, LayerModeEffects, int *, int); + int, LayerModeEffects, int *, + CombinationMode); void combine_regions (PixelRegion *, PixelRegion *, PixelRegion *, PixelRegion *, - unsigned char *, int, + unsigned char *, guint, LayerModeEffects, - int *, int); + int *, CombinationMode); void combine_regions_replace (PixelRegion *, PixelRegion *, PixelRegion *, PixelRegion *, unsigned char *, - int, int *, int); - - -/* Applying layer modes... */ -/* -int apply_layer_mode (unsigned char *, unsigned char *, - unsigned char **, int, int, int, - int, - LayerModeEffects, - int, int, int, int, int *); -*/ -int apply_indexed_layer_mode (unsigned char *, unsigned char *, - unsigned char **, - LayerModeEffects, int, int); + guint, int *, CombinationMode); #endif /* __PAINT_FUNCS_H__ */