Commit 1871d9cc authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

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.
parent f155bb6b
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];
if (mask)
{
if (has_alpha)
combined_opacity = opacity * src[alpha] * *mask / (255 * 255);
else
combined_opacity = opacity * *mask / 255;
mask++;
}
else
dest[alpha] = (rand_val > opacity) ? 0 : OPAQUE_OPACITY;
{
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;
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment