Cartoon can apply effect to entire image
This is now how the effect starts; painting now simply exposes the effect (to avoid artifacts that occurred when you'd paint different directions).
This commit is contained in:
parent
27b89d0dba
commit
a68ff27e84
1 changed files with 104 additions and 68 deletions
|
|
@ -23,7 +23,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
(See COPYING.txt)
|
||||
|
||||
Last updated: September 21, 2021
|
||||
Last updated: October 27, 2021
|
||||
$Id$
|
||||
*/
|
||||
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
/* Our globals: */
|
||||
|
||||
static Mix_Chunk *cartoon_snd;
|
||||
SDL_Surface * result_surf;
|
||||
|
||||
#define OUTLINE_THRESH 48
|
||||
|
||||
|
|
@ -50,6 +51,8 @@ SDL_Surface *cartoon_get_icon(magic_api * api, int which);
|
|||
char *cartoon_get_name(magic_api * api, int which);
|
||||
int cartoon_get_group(magic_api * api, int which);
|
||||
char *cartoon_get_description(magic_api * api, int which, int mode);
|
||||
void cartoon_apply_colors(magic_api * api, SDL_Surface * surf, int xx, int yy);
|
||||
void cartoon_apply_outline(magic_api * api, int xx, int yy);
|
||||
static void do_cartoon(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y);
|
||||
void cartoon_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||
SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect);
|
||||
|
|
@ -111,22 +114,71 @@ int cartoon_get_group(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUS
|
|||
}
|
||||
|
||||
// Return our descriptions, localized:
|
||||
char *cartoon_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
|
||||
char *cartoon_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode)
|
||||
{
|
||||
return (strdup(gettext_noop("Click and drag the mouse around to turn the picture into a cartoon.")));
|
||||
if (mode == MODE_PAINT)
|
||||
{
|
||||
return (strdup(gettext_noop("Click and drag the mouse around to turn the picture into a cartoon.")));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (strdup(gettext_noop("Click to turn the entire picture into a cartoon.")));
|
||||
}
|
||||
}
|
||||
|
||||
// Do the effect:
|
||||
|
||||
void cartoon_apply_colors(magic_api * api, SDL_Surface * surf, int xx, int yy) {
|
||||
Uint8 r, g, b;
|
||||
float hue, sat, val;
|
||||
|
||||
SDL_GetRGB(api->getpixel(surf, xx, yy), surf->format, &r, &g, &b);
|
||||
api->rgbtohsv(r, g, b, &hue, &sat, &val);
|
||||
|
||||
val = val - 0.5;
|
||||
val = val * 4;
|
||||
val = val + 0.5;
|
||||
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
else if (val > 1.0)
|
||||
val = 1.0;
|
||||
|
||||
val = floor(val * 4) / 4;
|
||||
hue = floor(hue * 4) / 4;
|
||||
sat = floor(sat * 4) / 4;
|
||||
|
||||
api->hsvtorgb(hue, sat, val, &r, &g, &b);
|
||||
api->putpixel(result_surf, xx, yy, SDL_MapRGB(result_surf->format, r, g, b));
|
||||
}
|
||||
|
||||
|
||||
void cartoon_apply_outline(magic_api * api, int xx, int yy) {
|
||||
Uint8 r, g, b;
|
||||
Uint8 r1, g1, b1, r2, g2, b2;
|
||||
|
||||
SDL_GetRGB(api->getpixel(result_surf, xx, yy), result_surf->format, &r, &g, &b);
|
||||
SDL_GetRGB(api->getpixel(result_surf, xx + 1, yy), result_surf->format, &r1, &g1, &b1);
|
||||
SDL_GetRGB(api->getpixel(result_surf, xx + 1, yy + 1), result_surf->format, &r2, &g2, &b2);
|
||||
|
||||
if (abs(((r + g + b) / 3) - (r1 + g1 + b1) / 3) > OUTLINE_THRESH
|
||||
|| abs(((r + g + b) / 3) - (r2 + g2 + b2) / 3) >
|
||||
OUTLINE_THRESH || abs(r - r1) > OUTLINE_THRESH
|
||||
|| abs(g - g1) > OUTLINE_THRESH
|
||||
|| abs(b - b1) > OUTLINE_THRESH
|
||||
|| abs(r - r2) > OUTLINE_THRESH || abs(g - g2) > OUTLINE_THRESH || abs(b - b2) > OUTLINE_THRESH)
|
||||
{
|
||||
api->putpixel(result_surf, xx - 1, yy, SDL_MapRGB(result_surf->format, 0, 0, 0));
|
||||
api->putpixel(result_surf, xx, yy - 1, SDL_MapRGB(result_surf->format, 0, 0, 0));
|
||||
api->putpixel(result_surf, xx - 1, yy - 1, SDL_MapRGB(result_surf->format, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void do_cartoon(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas, SDL_Surface * last, int x, int y)
|
||||
{
|
||||
magic_api *api = (magic_api *) ptr;
|
||||
int xx, yy;
|
||||
Uint8 r1, g1, b1, r2, g2, b2;
|
||||
Uint8 r, g, b;
|
||||
float hue, sat, val;
|
||||
|
||||
/* First, convert colors to more cartoony ones: */
|
||||
|
||||
for (yy = y - 16; yy < y + 16; yy = yy + 1)
|
||||
{
|
||||
|
|
@ -134,60 +186,7 @@ static void do_cartoon(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canv
|
|||
{
|
||||
if (api->in_circle(xx - x, yy - y, 16))
|
||||
{
|
||||
/* Get original color: */
|
||||
|
||||
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
|
||||
|
||||
api->rgbtohsv(r, g, b, &hue, &sat, &val);
|
||||
|
||||
val = val - 0.5;
|
||||
val = val * 4;
|
||||
val = val + 0.5;
|
||||
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
else if (val > 1.0)
|
||||
val = 1.0;
|
||||
|
||||
val = floor(val * 4) / 4;
|
||||
hue = floor(hue * 4) / 4;
|
||||
|
||||
sat = floor(sat * 4) / 4;
|
||||
|
||||
api->hsvtorgb(hue, sat, val, &r, &g, &b);
|
||||
|
||||
api->putpixel(canvas, xx, yy, SDL_MapRGB(canvas->format, r, g, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Then, draw dark outlines where there's a large contrast change */
|
||||
|
||||
for (yy = y - 16; yy < y + 16; yy++)
|
||||
{
|
||||
for (xx = x - 16; xx < x + 16; xx++)
|
||||
{
|
||||
if (api->in_circle(xx - x, yy - y, 16))
|
||||
{
|
||||
/* Get original color: */
|
||||
|
||||
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
|
||||
|
||||
SDL_GetRGB(api->getpixel(last, xx + 1, yy), last->format, &r1, &g1, &b1);
|
||||
|
||||
SDL_GetRGB(api->getpixel(last, xx + 1, yy + 1), last->format, &r2, &g2, &b2);
|
||||
|
||||
if (abs(((r + g + b) / 3) - (r1 + g1 + b1) / 3) > OUTLINE_THRESH
|
||||
|| abs(((r + g + b) / 3) - (r2 + g2 + b2) / 3) >
|
||||
OUTLINE_THRESH || abs(r - r1) > OUTLINE_THRESH
|
||||
|| abs(g - g1) > OUTLINE_THRESH
|
||||
|| abs(b - b1) > OUTLINE_THRESH
|
||||
|| abs(r - r2) > OUTLINE_THRESH || abs(g - g2) > OUTLINE_THRESH || abs(b - b2) > OUTLINE_THRESH)
|
||||
{
|
||||
api->putpixel(canvas, xx - 1, yy, SDL_MapRGB(canvas->format, 0, 0, 0));
|
||||
api->putpixel(canvas, xx, yy - 1, SDL_MapRGB(canvas->format, 0, 0, 0));
|
||||
api->putpixel(canvas, xx - 1, yy - 1, SDL_MapRGB(canvas->format, 0, 0, 0));
|
||||
}
|
||||
api->putpixel(canvas, xx, yy, api->getpixel(result_surf, xx, yy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,8 +196,6 @@ static void do_cartoon(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canv
|
|||
void cartoon_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||
SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect)
|
||||
{
|
||||
api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, do_cartoon);
|
||||
|
||||
if (ox > x)
|
||||
{
|
||||
int tmp = ox;
|
||||
|
|
@ -214,6 +211,8 @@ void cartoon_drag(magic_api * api, int which, SDL_Surface * canvas,
|
|||
y = tmp;
|
||||
}
|
||||
|
||||
api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, do_cartoon);
|
||||
|
||||
update_rect->x = ox - 16;
|
||||
update_rect->y = oy - 16;
|
||||
update_rect->w = (x + 16) - update_rect->x;
|
||||
|
|
@ -223,10 +222,36 @@ void cartoon_drag(magic_api * api, int which, SDL_Surface * canvas,
|
|||
}
|
||||
|
||||
// Affect the canvas on click:
|
||||
void cartoon_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
|
||||
void cartoon_click(magic_api * api, int which, int mode,
|
||||
SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect)
|
||||
{
|
||||
cartoon_drag(api, which, canvas, last, x, y, x, y, update_rect);
|
||||
for (y = 0; y < canvas->h; y++)
|
||||
{
|
||||
for (x = 0; x < canvas->w; x++)
|
||||
{
|
||||
cartoon_apply_colors(api, last, x, y);
|
||||
}
|
||||
}
|
||||
for (y = 0; y < canvas->h; y++)
|
||||
{
|
||||
for (x = 0; x < canvas->w; x++)
|
||||
{
|
||||
cartoon_apply_outline(api, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == MODE_PAINT)
|
||||
{
|
||||
cartoon_drag(api, which, canvas, last, x, y, x, y, update_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_BlitSurface(result_surf, NULL, canvas, NULL);
|
||||
update_rect->x = 0;
|
||||
update_rect->y = 0;
|
||||
update_rect->w = canvas->w;
|
||||
update_rect->h = canvas->h;
|
||||
}
|
||||
}
|
||||
|
||||
// Affect the canvas on release:
|
||||
|
|
@ -256,16 +281,27 @@ int cartoon_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUT
|
|||
}
|
||||
|
||||
void cartoon_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
|
||||
SDL_Surface * canvas ATTRIBUTE_UNUSED)
|
||||
SDL_Surface * canvas)
|
||||
{
|
||||
Uint32 amask;
|
||||
|
||||
amask = ~(canvas->format->Rmask | canvas->format->Gmask | canvas->format->Bmask);
|
||||
|
||||
result_surf = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
canvas->w,
|
||||
canvas->h,
|
||||
canvas->format->BitsPerPixel,
|
||||
canvas->format->Rmask, canvas->format->Gmask, canvas->format->Bmask, amask);
|
||||
}
|
||||
|
||||
void cartoon_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
|
||||
SDL_Surface * canvas ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (result_surf != NULL)
|
||||
SDL_FreeSurface(result_surf);
|
||||
}
|
||||
|
||||
int cartoon_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return (MODE_PAINT); /* FIXME - Can also be turned into a full-image effect */
|
||||
return (MODE_PAINT | MODE_FULLSCREEN);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue