source: tuxpaint/trunk/fuentes/magic/src/sharpen.c @ 219

Last change on this file since 219 was 219, checked in by mabarracus, 4 years ago

added sources from trusty

File size: 10.1 KB
Line 
1/*
2  sharpen.c
3
4  Sharpen, Trace Contour and Silhouette Magic Tool Plugin
5  Tux Paint - A simple drawing program for children.
6
7  Credits: Andrew Corcoran <akanewbie@gmail.com>
8
9  Copyright (c) 2002-2009 by Bill Kendrick and others; see AUTHORS.txt
10  bill@newbreedsoftware.com
11  http://www.tuxpaint.org/
12
13  This program is free software; you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation; either version 2 of the License, or
16  (at your option) any later version.
17
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22
23  You should have received a copy of the GNU General Public License
24  along with this program; if not, write to the Free Software
25  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  (See COPYING.txt)
27
28  Last updated: May 6, 2009
29  $Id: sharpen.c,v 1.22 2011/12/17 23:46:13 perepujal Exp $
30*/
31
32#include <stdio.h>
33#include <string.h>
34#include <libintl.h>
35#include "tp_magic_api.h"
36#include "SDL_image.h"
37#include "SDL_mixer.h"
38#include <math.h>
39#include <limits.h>
40
41#ifndef gettext_noop
42#define gettext_noop(String) String
43#endif
44
45/* Our globals: */
46
47enum {
48        TOOL_TRACE,
49        TOOL_SHARPEN,
50        TOOL_SILHOUETTE,
51        sharpen_NUM_TOOLS
52};
53
54static const int THRESHOLD = 50;
55
56static const int sharpen_RADIUS = 16;
57
58static const double SHARPEN = 0.5;
59
60static Mix_Chunk * sharpen_snd_effect[sharpen_NUM_TOOLS];
61
62const char * sharpen_snd_filenames[sharpen_NUM_TOOLS] = {
63  "edges.ogg",
64  "sharpen.ogg",
65  "silhouette.ogg"
66};
67const char * sharpen_icon_filenames[sharpen_NUM_TOOLS] = {
68  "edges.png",
69  "sharpen.png",
70  "silhouette.png"
71};
72const char * sharpen_names[sharpen_NUM_TOOLS] = {
73  gettext_noop("Edges"),
74  gettext_noop("Sharpen"),
75  gettext_noop("Silhouette")
76};
77const char * sharpen_descs[sharpen_NUM_TOOLS][2] = {
78  {gettext_noop("Click and move the mouse to trace edges in parts of your picture."),
79    gettext_noop("Click to trace edges in your entire picture."),},
80  {gettext_noop("Click and move the mouse to sharpen parts of your picture."),
81    gettext_noop("Click to sharpen the entire picture."),},
82  {gettext_noop("Click and move the mouse to create a black and white silhouette."),
83    gettext_noop("Click to create a black and white silhouette of your entire picture.")},
84};
85
86Uint32 sharpen_api_version(void);
87int sharpen_init(magic_api * api);
88int sharpen_get_tool_count(magic_api * api);
89SDL_Surface * sharpen_get_icon(magic_api * api, int which);
90char * sharpen_get_name(magic_api * api, int which);
91char * sharpen_get_description(magic_api * api, int which, int mode);
92static int sharpen_grey(Uint8 r1,Uint8 g1,Uint8 b1);
93static void do_sharpen_pixel(void * ptr, int which,
94                 SDL_Surface * canvas, SDL_Surface * last,
95                 int x, int y);
96static void do_sharpen_full(void * ptr,SDL_Surface * canvas, SDL_Surface * last, int which);
97static void do_sharpen_brush(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y);
98void sharpen_drag(magic_api * api, int which, SDL_Surface * canvas,
99                  SDL_Surface * last, int ox, int oy, int x, int y,
100                  SDL_Rect * update_rect);
101void sharpen_click(magic_api * api, int which, int mode,
102                    SDL_Surface * canvas, SDL_Surface * last,
103                    int x, int y, SDL_Rect * update_rect);
104
105void sharpen_release(magic_api * api, int which,
106                   SDL_Surface * canvas, SDL_Surface * last,
107                   int x, int y, SDL_Rect * update_rect);
108
109void sharpen_shutdown(magic_api * api);
110void sharpen_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
111int sharpen_requires_colors(magic_api * api, int which);
112void sharpen_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas);
113void sharpen_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas);
114int sharpen_modes(magic_api * api, int which);
115
116Uint32 sharpen_api_version(void) { return(TP_MAGIC_API_VERSION); }
117
118
119// No setup required:
120int sharpen_init(magic_api * api){
121 
122  int i;
123  char fname[1024];
124
125  for (i = 0; i < sharpen_NUM_TOOLS; i++){
126    snprintf(fname, sizeof(fname), "%s/sounds/magic/%s", api->data_directory, sharpen_snd_filenames[i]);
127    sharpen_snd_effect[i] = Mix_LoadWAV(fname);
128  }
129
130  return(1);
131}
132
133// We have multiple tools:
134int sharpen_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
135{
136  return(sharpen_NUM_TOOLS);
137}
138
139// Load our icons:
140SDL_Surface * sharpen_get_icon(magic_api * api, int which){
141  char fname[1024];
142  snprintf(fname, sizeof(fname), "%simages/magic/%s", api->data_directory, sharpen_icon_filenames[which]);
143  return(IMG_Load(fname));
144}
145
146// Return our names, localized:
147char * sharpen_get_name(magic_api * api ATTRIBUTE_UNUSED, int which){
148    return(strdup(gettext_noop(sharpen_names[which])));
149}
150
151// Return our descriptions, localized:
152char * sharpen_get_description(magic_api * api ATTRIBUTE_UNUSED, int which, int mode){
153  return(strdup(gettext_noop(sharpen_descs[which][mode-1])));
154}
155
156//Calculates the grey scale value for a rgb pixel
157static int sharpen_grey(Uint8 r1,Uint8 g1,Uint8 b1){
158        return 0.3*r1+.59*g1+0.11*b1;
159}
160
161// Do the effect:
162static void do_sharpen_pixel(void * ptr, int which,
163                 SDL_Surface * canvas, SDL_Surface * last,
164                 int x, int y){
165
166        magic_api * api = (magic_api *) ptr;
167
168        Uint8 r1, g1, b1;
169        int grey;
170        int i,j;
171        double sobel_1=0,sobel_2=0;
172        double temp;
173
174        //Sobel weighting masks
175        const int sobel_weights_1[3][3] = {     {1,2,1},
176                                      {0,0,0},
177                                      {-1,-2,-1}};
178        const int sobel_weights_2[3][3] = {     {-1,0,1},
179                                      {-2,0,2},
180                                      {-1,0,1}};
181
182                        sobel_1=0;
183                        sobel_2=0;
184                        for (i=-1;i<2;i++){
185                                for(j=-1; j<2; j++){
186                                        //No need to check if inside canvas, getpixel does it for us.
187                                        SDL_GetRGB(api->getpixel(last, x+i, y+j), last->format, &r1, &g1, &b1);
188                                        grey = sharpen_grey(r1,g1,b1);
189                                        sobel_1 += grey * sobel_weights_1[i+1][j+1];
190                                        sobel_2 += grey * sobel_weights_2[i+1][j+1];
191                                }
192                        }
193 
194  temp = sqrt(sobel_1*sobel_1 + sobel_2*sobel_2);
195  temp = (temp/1443)*255.0;
196
197        // set image to white where edge value is below THRESHOLD
198        if (which == TOOL_TRACE){
199                if (temp<THRESHOLD){
200                        api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format, 255, 255, 255));
201                }
202        }
203        //Simply display the edge values - provides a nice black and white silhouette image
204        else if (which == TOOL_SILHOUETTE){
205          api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format, temp, temp, temp));
206        }
207        //Add the edge values to the original image, creating a more distinct jump in contrast at edges
208        else if(which == TOOL_SHARPEN){
209                SDL_GetRGB(api->getpixel(last, x, y), last->format, &r1, &g1, &b1);
210                api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format, clamp(0.0, r1 + SHARPEN * temp, 255.0), 
211                                                                                                        clamp(0.0, g1 + SHARPEN * temp, 255.0), 
212                                                                                                        clamp(0.0, b1 + SHARPEN * temp, 255.0)));
213        }
214}
215
216// Do the effect for the full image
217static void do_sharpen_full(void * ptr,SDL_Surface * canvas, SDL_Surface * last, int which){
218
219        // magic_api * api = (magic_api *) ptr;
220
221        int x,y;
222
223        for (y = 0; y < last->h; y++){
224                for (x=0; x < last->w; x++){
225      do_sharpen_pixel(ptr, which, canvas, last, x, y);
226          }
227  }
228}
229
230//do the effect for the brush
231static void do_sharpen_brush(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y){
232  int xx, yy;
233  magic_api * api = (magic_api *) ptr;
234
235  for (yy = y - sharpen_RADIUS; yy < y + sharpen_RADIUS; yy++)
236  {
237    for (xx = x - sharpen_RADIUS; xx < x + sharpen_RADIUS; xx++)
238    {
239      if (api->in_circle(xx - x, yy - y, sharpen_RADIUS) &&
240          !api->touched(xx, yy))
241      {
242        do_sharpen_pixel(api, which, canvas, last, xx, yy);
243      }
244    }
245  }
246}
247
248// Affect the canvas on drag:
249void sharpen_drag(magic_api * api, int which, SDL_Surface * canvas,
250                  SDL_Surface * last, int ox, int oy, int x, int y,
251                  SDL_Rect * update_rect){
252
253  api->line((void *) api, which, canvas, last, ox, oy, x, y, 1, do_sharpen_brush);
254
255  api->playsound(sharpen_snd_effect[which], (x * 255) / canvas->w, 255);
256
257  if (ox > x) { int tmp = ox; ox = x; x = tmp; }
258  if (oy > y) { int tmp = oy; oy = y; y = tmp; }
259
260  update_rect->x = ox - sharpen_RADIUS;
261  update_rect->y = oy - sharpen_RADIUS;
262  update_rect->w = (x + sharpen_RADIUS) - update_rect->x;
263  update_rect->h = (y + sharpen_RADIUS) - update_rect->y;
264}
265
266// Affect the canvas on click:
267void sharpen_click(magic_api * api, int which, int mode,
268                    SDL_Surface * canvas, SDL_Surface * last,
269                    int x, int y, SDL_Rect * update_rect){
270  if (mode == MODE_PAINT)
271    sharpen_drag(api, which, canvas, last, x, y, x, y, update_rect);
272  else{
273    update_rect->x = 0;
274    update_rect->y = 0;
275    update_rect->w = canvas->w;
276    update_rect->h = canvas->h;
277    do_sharpen_full(api, canvas,  last, which);
278    api->playsound(sharpen_snd_effect[which], 128, 255);
279  }
280}
281
282// Affect the canvas on release:
283void sharpen_release(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
284                   SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED,
285                   int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
286{
287}
288
289// No setup happened:
290void sharpen_shutdown(magic_api * api ATTRIBUTE_UNUSED)
291{
292        //Clean up sounds
293        int i;
294        for(i=0; i<sharpen_NUM_TOOLS; i++){
295                if(sharpen_snd_effect[i] != NULL){
296                        Mix_FreeChunk(sharpen_snd_effect[i]);
297                }
298        }
299}
300
301// Record the color from Tux Paint:
302void sharpen_set_color(magic_api * api ATTRIBUTE_UNUSED, Uint8 r ATTRIBUTE_UNUSED, Uint8 g ATTRIBUTE_UNUSED, Uint8 b ATTRIBUTE_UNUSED)
303{
304}
305
306// Use colors:
307int sharpen_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
308{
309  return 0;
310}
311
312void sharpen_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED)
313{
314}
315
316void sharpen_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED)
317{
318}
319
320int sharpen_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
321{
322  return(MODE_FULLSCREEN|MODE_PAINT);
323}
Note: See TracBrowser for help on using the repository browser.