Implemented DISSOLVE_MODE the way it should have always been. Fixes bug
2003-06-02 Michael Natterer <mitch@gimp.org> Implemented DISSOLVE_MODE the way it should have always been. Fixes bug #107402. * app/paint-funcs-generic.h (struct apply_layer_mode_struct): added "guchar *mask" so it can be used by the layer mode. (dissolve_pixels): take an additional "mask" parameter and dissolve the pixels according to the *combined* opacity of the pixel's alpha, the opacity and the mask. Removed a wrong comment about why we call g_rand_int() x times before we start to use its values. (layer_dissolve_mode): pass the mask to dissolve_pixels(). No need to call add_alpha_pixels() since we overwrite the dest buffer entirely in disolve_pixels(). * app/paint-funcs.c (initial_sub_region, combine_sub_region): allocate the buffer large enough for DISSOLVE (which always needs an alpha channel). Pass the mask to the layer mode functions. Discard opacity and mask after applying DISSOLVE since it "consumes" all transparency.
This commit is contained in:

committed by
Michael Natterer

parent
f155bb6b4b
commit
1871d9ccef
24
ChangeLog
24
ChangeLog
@ -1,3 +1,27 @@
|
||||
2003-06-02 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
Implemented DISSOLVE_MODE the way it should have always been.
|
||||
Fixes bug #107402.
|
||||
|
||||
* app/paint-funcs-generic.h (struct apply_layer_mode_struct): added
|
||||
"guchar *mask" so it can be used by the layer mode.
|
||||
|
||||
(dissolve_pixels): take an additional "mask" parameter and
|
||||
dissolve the pixels according to the *combined* opacity of the
|
||||
pixel's alpha, the opacity and the mask. Removed a wrong comment
|
||||
about why we call g_rand_int() x times before we start to use its
|
||||
values.
|
||||
|
||||
(layer_dissolve_mode): pass the mask to dissolve_pixels(). No need
|
||||
to call add_alpha_pixels() since we overwrite the dest buffer
|
||||
entirely in disolve_pixels().
|
||||
|
||||
* app/paint-funcs.c (initial_sub_region, combine_sub_region):
|
||||
allocate the buffer large enough for DISSOLVE (which always needs
|
||||
an alpha channel). Pass the mask to the layer mode functions.
|
||||
Discard opacity and mask after applying DISSOLVE since it
|
||||
"consumes" all transparency.
|
||||
|
||||
2003-06-02 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* plug-ins/common/grid.c: fixed swapped horizontal/vertical
|
||||
|
@ -53,9 +53,10 @@
|
||||
struct apply_layer_mode_struct
|
||||
{
|
||||
guchar bytes1 : 3;
|
||||
guchar bytes2 : 3;
|
||||
guchar bytes2 : 3;
|
||||
guchar *src1;
|
||||
guchar *src2;
|
||||
guchar *mask;
|
||||
guchar **dest;
|
||||
gint x;
|
||||
gint y;
|
||||
@ -946,6 +947,7 @@ difference_pixels (const guchar *src1,
|
||||
|
||||
static inline void
|
||||
dissolve_pixels (const guchar *src,
|
||||
guchar *mask,
|
||||
guchar *dest,
|
||||
gint x,
|
||||
gint y,
|
||||
@ -955,17 +957,17 @@ dissolve_pixels (const guchar *src,
|
||||
gint db,
|
||||
guint has_alpha)
|
||||
{
|
||||
gint alpha, b;
|
||||
gint32 rand_val;
|
||||
GRand *gr;
|
||||
|
||||
gint alpha, b;
|
||||
gint32 rand_val;
|
||||
gint combined_opacity;
|
||||
GRand *gr;
|
||||
|
||||
gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]);
|
||||
|
||||
/* Ignore a few random values (this probably isn't necessary
|
||||
* when using g_rand_*) */
|
||||
|
||||
/* Ignore x random values so we get a deterministic result */
|
||||
for (b = 0; b < x; b ++)
|
||||
g_rand_int(gr);
|
||||
|
||||
g_rand_int (gr);
|
||||
|
||||
alpha = db - 1;
|
||||
|
||||
while (length--)
|
||||
@ -977,13 +979,27 @@ dissolve_pixels (const guchar *src,
|
||||
/* dissolve if random value is > opacity */
|
||||
rand_val = g_rand_int_range (gr, 0, 256);
|
||||
|
||||
if (has_alpha)
|
||||
dest[alpha] = (rand_val > src[alpha]) ? 0 : src[alpha];
|
||||
else
|
||||
dest[alpha] = (rand_val > opacity) ? 0 : OPAQUE_OPACITY;
|
||||
if (mask)
|
||||
{
|
||||
if (has_alpha)
|
||||
combined_opacity = opacity * src[alpha] * *mask / (255 * 255);
|
||||
else
|
||||
combined_opacity = opacity * *mask / 255;
|
||||
|
||||
mask++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_alpha)
|
||||
combined_opacity = opacity * src[alpha] / 255;
|
||||
else
|
||||
combined_opacity = opacity;
|
||||
}
|
||||
|
||||
dest[alpha] = (rand_val > combined_opacity) ? 0 : OPAQUE_OPACITY;
|
||||
|
||||
dest += db;
|
||||
src += sb;
|
||||
dest += db;
|
||||
}
|
||||
|
||||
g_rand_free (gr);
|
||||
@ -1591,15 +1607,21 @@ static void
|
||||
layer_dissolve_mode (struct apply_layer_mode_struct *alms)
|
||||
{
|
||||
const guint has_alpha1 = HAS_ALPHA (alms->bytes1);
|
||||
const guint has_alpha2 = HAS_ALPHA (alms->bytes2);
|
||||
const guint has_alpha2 = HAS_ALPHA (alms->bytes2);
|
||||
guint dest_bytes;
|
||||
|
||||
/* Since dissolve requires an alpha channel... */
|
||||
if (!has_alpha2)
|
||||
add_alpha_pixels (alms->src2, *(alms->dest), alms->length, alms->bytes2);
|
||||
if (has_alpha2)
|
||||
dest_bytes = alms->bytes2;
|
||||
else
|
||||
dest_bytes = alms->bytes2 + 1;
|
||||
|
||||
dissolve_pixels (alms->src2, alms->mask, *(alms->dest),
|
||||
alms->x, alms->y,
|
||||
alms->opacity, alms->length,
|
||||
alms->bytes2, dest_bytes,
|
||||
has_alpha2);
|
||||
|
||||
dissolve_pixels (alms->src2, *(alms->dest), alms->x, alms->y,
|
||||
alms->opacity, alms->length, alms->bytes2,
|
||||
(has_alpha2 ? alms->bytes2 : alms->bytes2 + 1), has_alpha2);
|
||||
alms->combine = has_alpha1 ? COMBINE_INTEN_A_INTEN_A : COMBINE_INTEN_INTEN_A;
|
||||
}
|
||||
|
||||
|
@ -4296,6 +4296,7 @@ initial_sub_region (struct initial_regions_struct *st,
|
||||
gboolean *affect;
|
||||
InitialMode type;
|
||||
|
||||
/* use src->bytes + 1 since DISSOLVE always needs a buffer with alpha */
|
||||
buf = alloca (MAX (src->w * (src->bytes + 1),
|
||||
dest->w * dest->bytes));
|
||||
data = st->data;
|
||||
@ -4306,7 +4307,7 @@ initial_sub_region (struct initial_regions_struct *st,
|
||||
|
||||
s = src->data;
|
||||
d = dest->data;
|
||||
m = (mask) ? mask->data : NULL;
|
||||
m = mask ? mask->data : NULL;
|
||||
|
||||
for (h = 0; h < src->h; h++)
|
||||
{
|
||||
@ -4329,10 +4330,12 @@ initial_sub_region (struct initial_regions_struct *st,
|
||||
case INITIAL_INTENSITY:
|
||||
if (mode == GIMP_DISSOLVE_MODE)
|
||||
{
|
||||
dissolve_pixels (s, buf, src->x, src->y + h, opacity, src->w, src->bytes,
|
||||
src->bytes + 1, 0);
|
||||
initial_inten_pixels (buf, d, m, opacity, affect,
|
||||
src->w, src->bytes);
|
||||
dissolve_pixels (s, m, buf, src->x, src->y + h,
|
||||
opacity, src->w,
|
||||
src->bytes, src->bytes + 1,
|
||||
FALSE);
|
||||
initial_inten_a_pixels (buf, d, NULL, OPAQUE_OPACITY, affect,
|
||||
src->w, src->bytes + 1);
|
||||
}
|
||||
else
|
||||
initial_inten_pixels (s, d, m, opacity, affect, src->w, src->bytes);
|
||||
@ -4341,9 +4344,11 @@ initial_sub_region (struct initial_regions_struct *st,
|
||||
case INITIAL_INTENSITY_ALPHA:
|
||||
if (mode == GIMP_DISSOLVE_MODE)
|
||||
{
|
||||
dissolve_pixels (s, buf, src->x, src->y + h, opacity, src->w, src->bytes,
|
||||
src->bytes, 1);
|
||||
initial_inten_a_pixels (buf, d, m, opacity, affect,
|
||||
dissolve_pixels (s, m, buf, src->x, src->y + h,
|
||||
opacity, src->w,
|
||||
src->bytes, src->bytes,
|
||||
TRUE);
|
||||
initial_inten_a_pixels (buf, d, NULL, OPAQUE_OPACITY, affect,
|
||||
src->w, src->bytes);
|
||||
}
|
||||
else
|
||||
@ -4439,6 +4444,8 @@ combine_sub_region (struct combine_regions_struct *st,
|
||||
{
|
||||
guchar *data;
|
||||
guint opacity;
|
||||
guint layer_mode_opacity;
|
||||
guchar *layer_mode_mask;
|
||||
GimpLayerModeEffects mode;
|
||||
gboolean *affect;
|
||||
guint h;
|
||||
@ -4452,9 +4459,11 @@ combine_sub_region (struct combine_regions_struct *st,
|
||||
gboolean transparency_quickskip_possible;
|
||||
TileRowHint hint;
|
||||
|
||||
/* use src2->bytes + 1 since DISSOLVE always needs a buffer with alpha */
|
||||
buf = alloca (MAX (MAX (src1->w * src1->bytes,
|
||||
src2->w * src2->bytes),
|
||||
src2->w * (src2->bytes + 1)),
|
||||
dest->w * dest->bytes));
|
||||
|
||||
opacity = st->opacity;
|
||||
mode = st->mode;
|
||||
affect = st->affect;
|
||||
@ -4469,7 +4478,7 @@ combine_sub_region (struct combine_regions_struct *st,
|
||||
s1 = src1->data;
|
||||
s2 = src2->data;
|
||||
d = dest->data;
|
||||
m = (mask) ? mask->data : NULL;
|
||||
m = mask ? mask->data : NULL;
|
||||
|
||||
if (transparency_quickskip_possible || opacity_quickskip_possible)
|
||||
{
|
||||
@ -4484,6 +4493,19 @@ combine_sub_region (struct combine_regions_struct *st,
|
||||
}
|
||||
/* else it's probably a brush-composite */
|
||||
|
||||
/* use separate variables for the combining opacity and the opacity
|
||||
* the layer mode is applied with since DISSLOVE_MODE "consumes"
|
||||
* all opacity and wants to be applied OPAQUE
|
||||
*/
|
||||
layer_mode_opacity = opacity;
|
||||
layer_mode_mask = m;
|
||||
|
||||
if (mode == GIMP_DISSOLVE_MODE)
|
||||
{
|
||||
opacity = OPAQUE_OPACITY;
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
for (h = 0; h < src1->h; h++)
|
||||
{
|
||||
hint = TILEROWHINT_UNDEFINED;
|
||||
@ -4530,24 +4552,27 @@ combine_sub_region (struct combine_regions_struct *st,
|
||||
{
|
||||
/* Now, apply the paint mode */
|
||||
struct apply_layer_mode_struct alms;
|
||||
alms.src1 = s1;
|
||||
alms.src2 = s2;
|
||||
alms.dest = &s;
|
||||
alms.x = src1->x;
|
||||
alms.y = src1->y + h;
|
||||
alms.opacity = opacity;
|
||||
|
||||
alms.src1 = s1;
|
||||
alms.src2 = s2;
|
||||
alms.mask = layer_mode_mask;
|
||||
alms.dest = &s;
|
||||
alms.x = src1->x;
|
||||
alms.y = src1->y + h;
|
||||
alms.opacity = layer_mode_opacity;
|
||||
alms.combine = combine;
|
||||
alms.length = src1->w;
|
||||
alms.bytes1 = src1->bytes;
|
||||
alms.bytes2 = src2->bytes;
|
||||
alms.length = src1->w;
|
||||
alms.bytes1 = src1->bytes;
|
||||
alms.bytes2 = src2->bytes;
|
||||
|
||||
/* Determine whether the alpha channel of the destination can be
|
||||
* affected by the specified mode--This keeps consistency with
|
||||
* varying opacities
|
||||
*/
|
||||
|
||||
mode_affect = layer_modes[mode].affect_alpha;
|
||||
layer_mode_funcs[mode](&alms);
|
||||
|
||||
layer_mode_funcs[mode] (&alms);
|
||||
|
||||
combine = (alms.combine == NO_COMBINATION) ? type : alms.combine;
|
||||
break;
|
||||
}
|
||||
@ -4698,7 +4723,12 @@ combine_sub_region (struct combine_regions_struct *st,
|
||||
s2 += src2->rowstride;
|
||||
d += dest->rowstride;
|
||||
if (mask)
|
||||
m += mask->rowstride;
|
||||
{
|
||||
layer_mode_mask += mask->rowstride;
|
||||
|
||||
if (m)
|
||||
m += mask->rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user