~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to plug-ins/common/sharpen.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * "$Id: sharpen.c,v 1.55 2004/12/23 23:58:35 weskaggs Exp $"
 
3
 *
 
4
 *   Sharpen filters for The GIMP -- an image manipulation program
 
5
 *
 
6
 *   Copyright 1997-1998 Michael Sweet (mike@easysw.com)
 
7
 *
 
8
 *   This program is free software; you can redistribute it and/or modify
 
9
 *   it under the terms of the GNU General Public License as published by
 
10
 *   the Free Software Foundation; either version 2 of the License, or
 
11
 *   (at your option) any later version.
 
12
 *
 
13
 *   This program is distributed in the hope that it will be useful,
 
14
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *   GNU General Public License for more details.
 
17
 *
 
18
 *   You should have received a copy of the GNU General Public License
 
19
 *   along with this program; if not, write to the Free Software
 
20
 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
21
 *
 
22
 */
 
23
 
 
24
#include "config.h"
 
25
 
 
26
#include <string.h>
 
27
 
 
28
#include <gtk/gtk.h>
 
29
 
 
30
#include <libgimp/gimp.h>
 
31
#include <libgimp/gimpui.h>
 
32
 
 
33
#include "libgimp/stdplugins-intl.h"
 
34
 
 
35
/*
 
36
 * Constants...
 
37
 */
 
38
 
 
39
#define PLUG_IN_NAME    "plug_in_sharpen"
 
40
#define PLUG_IN_VERSION "1.4.2 - 3 June 1998"
 
41
#define HELP_ID         "plug-in-sharpen"
 
42
#define SCALE_WIDTH     100
 
43
 
 
44
/*
 
45
 * Local functions...
 
46
 */
 
47
 
 
48
static void     query (void);
 
49
static void     run   (const gchar      *name,
 
50
                       gint              nparams,
 
51
                       const GimpParam  *param,
 
52
                       gint             *nreturn_vals,
 
53
                       GimpParam       **returm_vals);
 
54
 
 
55
static void     compute_luts   (void);
 
56
static void     sharpen        (GimpDrawable *drawable);
 
57
 
 
58
static gboolean sharpen_dialog (GimpDrawable *drawable);
 
59
 
 
60
static void     preview_update (GimpPreview  *preview);
 
61
 
 
62
typedef gint32 intneg;
 
63
typedef gint32 intpos;
 
64
 
 
65
static void     gray_filter  (int width, guchar *src, guchar *dst, intneg *neg0,
 
66
                              intneg *neg1, intneg *neg2);
 
67
static void     graya_filter (int width, guchar *src, guchar *dst, intneg *neg0,
 
68
                              intneg *neg1, intneg *neg2);
 
69
static void     rgb_filter   (int width, guchar *src, guchar *dst, intneg *neg0,
 
70
                              intneg *neg1, intneg *neg2);
 
71
static void     rgba_filter  (int width, guchar *src, guchar *dst, intneg *neg0,
 
72
                              intneg *neg1, intneg *neg2);
 
73
 
 
74
 
 
75
/*
 
76
 * Globals...
 
77
 */
 
78
 
 
79
GimpPlugInInfo PLUG_IN_INFO =
 
80
{
 
81
  NULL,  /* init_proc  */
 
82
  NULL,  /* quit_proc  */
 
83
  query, /* query_proc */
 
84
  run    /* run_proc   */
 
85
};
 
86
 
 
87
typedef struct
 
88
{
 
89
  gint     sharpen_percent;
 
90
  gboolean update_preview;
 
91
} SharpenParams;
 
92
 
 
93
static SharpenParams sharpen_params =
 
94
{
 
95
  10,
 
96
  TRUE
 
97
};
 
98
 
 
99
static intneg neg_lut[256];   /* Negative coefficient LUT */
 
100
static intpos pos_lut[256];   /* Positive coefficient LUT */
 
101
 
 
102
 
 
103
MAIN ()
 
104
 
 
105
static void
 
106
query (void)
 
107
{
 
108
  static GimpParamDef   args[] =
 
109
  {
 
110
    { GIMP_PDB_INT32,    "run_mode", "Interactive, non-interactive"      },
 
111
    { GIMP_PDB_IMAGE,    "image",    "Input image"                       },
 
112
    { GIMP_PDB_DRAWABLE, "drawable", "Input drawable"                    },
 
113
    { GIMP_PDB_INT32,    "percent",  "Percent sharpening (default = 10)" }
 
114
  };
 
115
 
 
116
  gimp_install_procedure (PLUG_IN_NAME,
 
117
                          "Sharpen filter, typically used to 'sharpen' a "
 
118
                          "photographic image.",
 
119
                          "This plug-in selectively performs a convolution "
 
120
                          "filter on an image.",
 
121
                          "Michael Sweet <mike@easysw.com>",
 
122
                          "Copyright 1997-1998 by Michael Sweet",
 
123
                          PLUG_IN_VERSION,
 
124
                          N_("_Sharpen..."),
 
125
                          "RGB*, GRAY*",
 
126
                          GIMP_PLUGIN,
 
127
                          G_N_ELEMENTS (args), 0,
 
128
                          args, NULL);
 
129
 
 
130
  gimp_plugin_menu_register (PLUG_IN_NAME, "<Image>/Filters/Enhance");
 
131
}
 
132
 
 
133
static void
 
134
run (const gchar      *name,
 
135
     gint              nparams,
 
136
     const GimpParam  *param,
 
137
     gint             *nreturn_vals,
 
138
     GimpParam       **return_vals)
 
139
{
 
140
  GimpRunMode        run_mode;  /* Current run mode */
 
141
  GimpPDBStatusType  status;    /* Return status */
 
142
  GimpParam         *values;    /* Return values */
 
143
  GimpDrawable      *drawable;  /* Current image */
 
144
 
 
145
  /*
 
146
   * Initialize parameter data...
 
147
   */
 
148
 
 
149
  status   = GIMP_PDB_SUCCESS;
 
150
  run_mode = param[0].data.d_int32;
 
151
 
 
152
  INIT_I18N ();
 
153
 
 
154
  values = g_new (GimpParam, 1);
 
155
 
 
156
  *nreturn_vals = 1;
 
157
  *return_vals  = values;
 
158
 
 
159
  values[0].type          = GIMP_PDB_STATUS;
 
160
  values[0].data.d_status = status;
 
161
 
 
162
  /*
 
163
   * Get drawable information...
 
164
   */
 
165
 
 
166
  drawable = gimp_drawable_get (param[2].data.d_drawable);
 
167
  gimp_tile_cache_ntiles (2 * drawable->ntile_cols);
 
168
 
 
169
 
 
170
  /*
 
171
   * See how we will run
 
172
   */
 
173
 
 
174
  switch (run_mode)
 
175
    {
 
176
    case GIMP_RUN_INTERACTIVE:
 
177
      /*
 
178
       * Possibly retrieve data...
 
179
       */
 
180
      gimp_get_data (PLUG_IN_NAME, &sharpen_params);
 
181
 
 
182
      /*
 
183
       * Get information from the dialog...
 
184
       */
 
185
      if (!sharpen_dialog (drawable))
 
186
        return;
 
187
      break;
 
188
 
 
189
    case GIMP_RUN_NONINTERACTIVE:
 
190
      /*
 
191
       * Make sure all the arguments are present...
 
192
       */
 
193
      if (nparams != 4)
 
194
        status = GIMP_PDB_CALLING_ERROR;
 
195
      else
 
196
        sharpen_params.sharpen_percent = param[3].data.d_int32;
 
197
      break;
 
198
 
 
199
    case GIMP_RUN_WITH_LAST_VALS:
 
200
      /*
 
201
       * Possibly retrieve data...
 
202
       */
 
203
      gimp_get_data (PLUG_IN_NAME, &sharpen_params);
 
204
      break;
 
205
 
 
206
    default:
 
207
      status = GIMP_PDB_CALLING_ERROR;
 
208
      break;
 
209
    }
 
210
 
 
211
  /*
 
212
   * Sharpen the image...
 
213
   */
 
214
 
 
215
  if (status == GIMP_PDB_SUCCESS)
 
216
    {
 
217
      if ((gimp_drawable_is_rgb (drawable->drawable_id) ||
 
218
           gimp_drawable_is_gray (drawable->drawable_id)))
 
219
        {
 
220
          /*
 
221
           * Run!
 
222
           */
 
223
          sharpen (drawable);
 
224
 
 
225
          /*
 
226
           * If run mode is interactive, flush displays...
 
227
           */
 
228
          if (run_mode != GIMP_RUN_NONINTERACTIVE)
 
229
            gimp_displays_flush ();
 
230
 
 
231
          /*
 
232
           * Store data...
 
233
           */
 
234
          if (run_mode == GIMP_RUN_INTERACTIVE)
 
235
            gimp_set_data (PLUG_IN_NAME,
 
236
                           &sharpen_params, sizeof (SharpenParams));
 
237
        }
 
238
      else
 
239
        status = GIMP_PDB_EXECUTION_ERROR;
 
240
    }
 
241
 
 
242
  /*
 
243
   * Reset the current run status...
 
244
   */
 
245
  values[0].data.d_status = status;
 
246
 
 
247
  /*
 
248
   * Detach from the drawable...
 
249
   */
 
250
  gimp_drawable_detach (drawable);
 
251
}
 
252
 
 
253
 
 
254
static void
 
255
compute_luts (void)
 
256
{
 
257
  gint i;       /* Looping var */
 
258
  gint fact;    /* 1 - sharpness */
 
259
 
 
260
  fact = 100 - sharpen_params.sharpen_percent;
 
261
  if (fact < 1)
 
262
    fact = 1;
 
263
 
 
264
  for (i = 0; i < 256; i ++)
 
265
    {
 
266
      pos_lut[i] = 800 * i / fact;
 
267
      neg_lut[i] = (4 + pos_lut[i] - (i << 3)) >> 3;
 
268
    }
 
269
}
 
270
 
 
271
/*
 
272
 * 'sharpen()' - Sharpen an image using a convolution filter.
 
273
 */
 
274
 
 
275
static void
 
276
sharpen (GimpDrawable *drawable)
 
277
{
 
278
  GimpPixelRgn  src_rgn;        /* Source image region */
 
279
  GimpPixelRgn  dst_rgn;        /* Destination image region */
 
280
  guchar       *src_rows[4];    /* Source pixel rows */
 
281
  guchar       *src_ptr;        /* Current source pixel */
 
282
  guchar       *dst_row;        /* Destination pixel row */
 
283
  intneg       *neg_rows[4];    /* Negative coefficient rows */
 
284
  intneg       *neg_ptr;        /* Current negative coefficient */
 
285
  gint          i;              /* Looping vars */
 
286
  gint          y;              /* Current location in image */
 
287
  gint          row;            /* Current row in src_rows */
 
288
  gint          count;          /* Current number of filled src_rows */
 
289
  gint          width;          /* Byte width of the image */
 
290
  gint          x1;             /* Selection bounds */
 
291
  gint          y1;
 
292
  gint          x2;
 
293
  gint          y2;
 
294
  gint          sel_width;      /* Selection width */
 
295
  gint          sel_height;     /* Selection height */
 
296
  gint          img_bpp;        /* Bytes-per-pixel in image */
 
297
  void          (*filter)(int, guchar *, guchar *, intneg *, intneg *, intneg *);
 
298
 
 
299
  filter = NULL;
 
300
 
 
301
  gimp_drawable_mask_bounds (drawable->drawable_id,
 
302
                             &x1, &y1, &x2, &y2);
 
303
 
 
304
  sel_width  = x2 - x1;
 
305
  sel_height = y2 - y1;
 
306
  img_bpp    = gimp_drawable_bpp (drawable->drawable_id);
 
307
 
 
308
  /*
 
309
   * Let the user know what we're doing...
 
310
   */
 
311
  gimp_progress_init( _("Sharpening..."));
 
312
 
 
313
  /*
 
314
   * Setup for filter...
 
315
   */
 
316
 
 
317
  gimp_pixel_rgn_init (&src_rgn, drawable,
 
318
                       x1, y1, sel_width, sel_height, FALSE, FALSE);
 
319
  gimp_pixel_rgn_init (&dst_rgn, drawable,
 
320
                       x1, y1, sel_width, sel_height, TRUE, TRUE);
 
321
 
 
322
  compute_luts ();
 
323
 
 
324
  width = sel_width * img_bpp;
 
325
 
 
326
  for (row = 0; row < 4; row ++)
 
327
    {
 
328
      src_rows[row] = g_new (guchar, width);
 
329
      neg_rows[row] = g_new (intneg, width);
 
330
    }
 
331
 
 
332
  dst_row = g_new (guchar, width);
 
333
 
 
334
  /*
 
335
   * Pre-load the first row for the filter...
 
336
   */
 
337
 
 
338
  gimp_pixel_rgn_get_row (&src_rgn, src_rows[0], x1, y1, sel_width);
 
339
 
 
340
  for (i = width, src_ptr = src_rows[0], neg_ptr = neg_rows[0];
 
341
       i > 0;
 
342
       i --, src_ptr ++, neg_ptr ++)
 
343
    *neg_ptr = neg_lut[*src_ptr];
 
344
 
 
345
  row   = 1;
 
346
  count = 1;
 
347
 
 
348
  /*
 
349
   * Select the filter...
 
350
   */
 
351
 
 
352
  switch (img_bpp)
 
353
    {
 
354
    case 1 :
 
355
      filter = gray_filter;
 
356
      break;
 
357
    case 2 :
 
358
      filter = graya_filter;
 
359
      break;
 
360
    case 3 :
 
361
      filter = rgb_filter;
 
362
      break;
 
363
    case 4 :
 
364
      filter = rgba_filter;
 
365
      break;
 
366
    };
 
367
 
 
368
  /*
 
369
   * Sharpen...
 
370
   */
 
371
 
 
372
  for (y = y1; y < y2; y ++)
 
373
    {
 
374
      /*
 
375
       * Load the next pixel row...
 
376
       */
 
377
 
 
378
      if ((y + 1) < y2)
 
379
        {
 
380
          /*
 
381
           * Check to see if our src_rows[] array is overflowing yet...
 
382
           */
 
383
 
 
384
          if (count >= 3)
 
385
            count --;
 
386
 
 
387
          /*
 
388
           * Grab the next row...
 
389
           */
 
390
 
 
391
          gimp_pixel_rgn_get_row (&src_rgn, src_rows[row],
 
392
                                  x1, y + 1, sel_width);
 
393
          for (i = width, src_ptr = src_rows[row], neg_ptr = neg_rows[row];
 
394
               i > 0;
 
395
               i --, src_ptr ++, neg_ptr ++)
 
396
            *neg_ptr = neg_lut[*src_ptr];
 
397
 
 
398
          count ++;
 
399
          row = (row + 1) & 3;
 
400
        }
 
401
      else
 
402
        {
 
403
          /*
 
404
           * No more pixels at the bottom...  Drop the oldest samples...
 
405
           */
 
406
 
 
407
          count --;
 
408
        }
 
409
 
 
410
      /*
 
411
       * Now sharpen pixels and save the results...
 
412
       */
 
413
 
 
414
      if (count == 3)
 
415
        {
 
416
          (* filter) (sel_width, src_rows[(row + 2) & 3], dst_row,
 
417
                      neg_rows[(row + 1) & 3] + img_bpp,
 
418
                      neg_rows[(row + 2) & 3] + img_bpp,
 
419
                      neg_rows[(row + 3) & 3] + img_bpp);
 
420
 
 
421
          /*
 
422
           * Set the row...
 
423
           */
 
424
 
 
425
          gimp_pixel_rgn_set_row (&dst_rgn, dst_row, x1, y, sel_width);
 
426
        }
 
427
      else if (count == 2)
 
428
        {
 
429
          if (y == y1)      /* first row */
 
430
            gimp_pixel_rgn_set_row (&dst_rgn, src_rows[0],
 
431
                                    x1, y, sel_width);
 
432
          else                  /* last row  */
 
433
            gimp_pixel_rgn_set_row (&dst_rgn, src_rows[(sel_height - 1) & 3],
 
434
                                    x1, y, sel_width);
 
435
        }
 
436
 
 
437
      if ((y & 15) == 0)
 
438
        gimp_progress_update ((gdouble) (y - y1) / (gdouble) sel_height);
 
439
    }
 
440
 
 
441
  /*
 
442
   * OK, we're done.  Free all memory used...
 
443
   */
 
444
 
 
445
  for (row = 0; row < 4; row ++)
 
446
    {
 
447
      g_free (src_rows[row]);
 
448
      g_free (neg_rows[row]);
 
449
    }
 
450
 
 
451
  g_free (dst_row);
 
452
 
 
453
  /*
 
454
   * Update the screen...
 
455
   */
 
456
 
 
457
  gimp_drawable_flush (drawable);
 
458
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
 
459
  gimp_drawable_update (drawable->drawable_id,
 
460
                        x1, y1, sel_width, sel_height);
 
461
}
 
462
 
 
463
 
 
464
/*
 
465
 * 'sharpen_dialog()' - Popup a dialog window for the filter box size...
 
466
 */
 
467
 
 
468
static gboolean
 
469
sharpen_dialog (GimpDrawable *drawable)
 
470
{
 
471
  GtkWidget *dialog;
 
472
  GtkWidget *main_vbox;
 
473
  GtkWidget *preview;
 
474
  GtkWidget *table;
 
475
  GtkObject *adj;
 
476
  gboolean   run;
 
477
 
 
478
  gimp_ui_init ("sharpen", TRUE);
 
479
 
 
480
  dialog = gimp_dialog_new (_("Sharpen"), "Sharpen",
 
481
                            NULL, 0,
 
482
                            gimp_standard_help_func, HELP_ID,
 
483
 
 
484
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
485
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
 
486
 
 
487
                            NULL);
 
488
 
 
489
  main_vbox = gtk_vbox_new (FALSE, 12);
 
490
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
 
491
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
 
492
  gtk_widget_show (main_vbox);
 
493
 
 
494
  preview = gimp_drawable_preview_new (drawable,
 
495
                                       &sharpen_params.update_preview);
 
496
  gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
 
497
  gtk_widget_show (preview);
 
498
 
 
499
  g_signal_connect (preview, "invalidated",
 
500
                    G_CALLBACK (preview_update),
 
501
                    NULL);
 
502
 
 
503
  table = gtk_table_new (1, 3, FALSE);
 
504
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
 
505
  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
 
506
  gtk_widget_show (table);
 
507
 
 
508
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
 
509
                              _("_Sharpness:"), SCALE_WIDTH, 0,
 
510
                              sharpen_params.sharpen_percent,
 
511
                              1, 99, 1, 10, 0,
 
512
                              TRUE, 0, 0,
 
513
                              NULL, NULL);
 
514
  g_signal_connect (adj, "value_changed",
 
515
                    G_CALLBACK (gimp_int_adjustment_update),
 
516
                    &sharpen_params.sharpen_percent);
 
517
  g_signal_connect_swapped (adj, "value_changed",
 
518
                            G_CALLBACK (gimp_preview_invalidate),
 
519
                            preview);
 
520
 
 
521
  gtk_widget_show (dialog);
 
522
 
 
523
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
 
524
 
 
525
  gtk_widget_destroy (dialog);
 
526
 
 
527
  return run;
 
528
}
 
529
 
 
530
static void
 
531
preview_update (GimpPreview *preview)
 
532
{
 
533
  GimpDrawable *drawable;
 
534
  GimpPixelRgn  src_rgn;        /* Source image region */
 
535
  guchar       *src_ptr;        /* Current source pixel */
 
536
  guchar       *dst_ptr;        /* Current destination pixel */
 
537
  intneg       *neg_ptr;        /* Current negative pixel */
 
538
  gint          i;              /* Looping var */
 
539
  gint          y;              /* Current location in image */
 
540
  gint          width;          /* Byte width of the image */
 
541
  gint          x1, y1;
 
542
  gint          preview_width, preview_height;
 
543
  guchar       *preview_src, *preview_dst;
 
544
  intneg       *preview_neg;
 
545
  gint          img_bpp;        /* Bytes-per-pixel in image */
 
546
 
 
547
  void          (*filter)(int, guchar *, guchar *, intneg *, intneg *, intneg *);
 
548
 
 
549
  filter = NULL;
 
550
 
 
551
  compute_luts();
 
552
 
 
553
  gimp_preview_get_position (preview, &x1, &y1);
 
554
  gimp_preview_get_size (preview, &preview_width, &preview_height);
 
555
 
 
556
  drawable =
 
557
    gimp_drawable_preview_get_drawable (GIMP_DRAWABLE_PREVIEW (preview));
 
558
 
 
559
  img_bpp = gimp_drawable_bpp (drawable->drawable_id);
 
560
 
 
561
 
 
562
  preview_src = g_new (guchar, preview_width * preview_height * img_bpp);
 
563
  preview_neg = g_new (intneg, preview_width * preview_height * img_bpp);
 
564
  preview_dst = g_new (guchar, preview_width * preview_height * img_bpp);
 
565
 
 
566
  gimp_pixel_rgn_init (&src_rgn, drawable,
 
567
                       x1, y1, preview_width, preview_height,
 
568
                       FALSE, FALSE);
 
569
 
 
570
  width = preview_width * img_bpp;
 
571
 
 
572
  /*
 
573
   * Load the preview area...
 
574
   */
 
575
 
 
576
  gimp_pixel_rgn_get_rect (&src_rgn, preview_src, x1, y1,
 
577
                           preview_width, preview_height);
 
578
 
 
579
  for (i = width * preview_height, src_ptr = preview_src, neg_ptr = preview_neg;
 
580
       i > 0;
 
581
       i --)
 
582
    *neg_ptr++ = neg_lut[*src_ptr++];
 
583
 
 
584
  /*
 
585
   * Select the filter...
 
586
   */
 
587
 
 
588
  switch (img_bpp)
 
589
    {
 
590
    case 1:
 
591
      filter = gray_filter;
 
592
      break;
 
593
    case 2:
 
594
      filter = graya_filter;
 
595
      break;
 
596
    case 3:
 
597
      filter = rgb_filter;
 
598
      break;
 
599
    case 4:
 
600
      filter = rgba_filter;
 
601
      break;
 
602
    }
 
603
 
 
604
  /*
 
605
   * Sharpen...
 
606
   */
 
607
 
 
608
  memcpy (preview_dst, preview_src, width);
 
609
  memcpy (preview_dst + width * (preview_height - 1),
 
610
          preview_src + width * (preview_height - 1),
 
611
          width);
 
612
 
 
613
  for (y = preview_height - 2, src_ptr = preview_src + width,
 
614
           neg_ptr = preview_neg + width + img_bpp,
 
615
           dst_ptr = preview_dst + width;
 
616
       y > 0;
 
617
       y --, src_ptr += width, neg_ptr += width, dst_ptr += width)
 
618
    (*filter)(preview_width, src_ptr, dst_ptr, neg_ptr - width,
 
619
              neg_ptr, neg_ptr + width);
 
620
 
 
621
  gimp_preview_draw_buffer (preview, preview_dst, preview_width * img_bpp);
 
622
 
 
623
  g_free (preview_src);
 
624
  g_free (preview_neg);
 
625
  g_free (preview_dst);
 
626
}
 
627
 
 
628
/*
 
629
 * 'gray_filter()' - Sharpen grayscale pixels.
 
630
 */
 
631
 
 
632
static void
 
633
gray_filter (gint    width,     /* I - Width of line in pixels */
 
634
             guchar *src,       /* I - Source line */
 
635
             guchar *dst,       /* O - Destination line */
 
636
             intneg *neg0,      /* I - Top negative coefficient line */
 
637
             intneg *neg1,      /* I - Middle negative coefficient line */
 
638
             intneg *neg2)      /* I - Bottom negative coefficient line */
 
639
{
 
640
  intpos pixel;         /* New pixel value */
 
641
 
 
642
  *dst++ = *src++;
 
643
  width -= 2;
 
644
 
 
645
  while (width > 0)
 
646
    {
 
647
      pixel = (pos_lut[*src++] - neg0[-1] - neg0[0] - neg0[1] -
 
648
               neg1[-1] - neg1[1] -
 
649
               neg2[-1] - neg2[0] - neg2[1]);
 
650
      pixel = (pixel + 4) >> 3;
 
651
      *dst++ = CLAMP0255 (pixel);
 
652
 
 
653
      neg0 ++;
 
654
      neg1 ++;
 
655
      neg2 ++;
 
656
      width --;
 
657
    }
 
658
 
 
659
  *dst++ = *src++;
 
660
}
 
661
 
 
662
/*
 
663
 * 'graya_filter()' - Sharpen grayscale+alpha pixels.
 
664
 */
 
665
 
 
666
static void
 
667
graya_filter (gint   width,     /* I - Width of line in pixels */
 
668
              guchar *src,      /* I - Source line */
 
669
              guchar *dst,      /* O - Destination line */
 
670
              intneg *neg0,     /* I - Top negative coefficient line */
 
671
              intneg *neg1,     /* I - Middle negative coefficient line */
 
672
              intneg *neg2)     /* I - Bottom negative coefficient line */
 
673
{
 
674
  intpos pixel;         /* New pixel value */
 
675
 
 
676
  *dst++ = *src++;
 
677
  *dst++ = *src++;
 
678
  width -= 2;
 
679
 
 
680
  while (width > 0)
 
681
    {
 
682
      pixel = (pos_lut[*src++] - neg0[-2] - neg0[0] - neg0[2] -
 
683
               neg1[-2] - neg1[2] -
 
684
               neg2[-2] - neg2[0] - neg2[2]);
 
685
      pixel = (pixel + 4) >> 3;
 
686
      *dst++ = CLAMP0255 (pixel);
 
687
 
 
688
      *dst++ = *src++;
 
689
      neg0 += 2;
 
690
      neg1 += 2;
 
691
      neg2 += 2;
 
692
      width --;
 
693
    }
 
694
 
 
695
  *dst++ = *src++;
 
696
  *dst++ = *src++;
 
697
}
 
698
 
 
699
/*
 
700
 * 'rgb_filter()' - Sharpen RGB pixels.
 
701
 */
 
702
 
 
703
static void
 
704
rgb_filter (gint    width,      /* I - Width of line in pixels */
 
705
            guchar *src,        /* I - Source line */
 
706
            guchar *dst,        /* O - Destination line */
 
707
            intneg *neg0,       /* I - Top negative coefficient line */
 
708
            intneg *neg1,       /* I - Middle negative coefficient line */
 
709
            intneg *neg2)       /* I - Bottom negative coefficient line */
 
710
{
 
711
  intpos pixel;         /* New pixel value */
 
712
 
 
713
  *dst++ = *src++;
 
714
  *dst++ = *src++;
 
715
  *dst++ = *src++;
 
716
  width -= 2;
 
717
 
 
718
  while (width > 0)
 
719
    {
 
720
      pixel = (pos_lut[*src++] - neg0[-3] - neg0[0] - neg0[3] -
 
721
               neg1[-3] - neg1[3] -
 
722
               neg2[-3] - neg2[0] - neg2[3]);
 
723
      pixel = (pixel + 4) >> 3;
 
724
      *dst++ = CLAMP0255 (pixel);
 
725
 
 
726
      pixel = (pos_lut[*src++] - neg0[-2] - neg0[1] - neg0[4] -
 
727
               neg1[-2] - neg1[4] -
 
728
               neg2[-2] - neg2[1] - neg2[4]);
 
729
      pixel = (pixel + 4) >> 3;
 
730
      *dst++ = CLAMP0255 (pixel);
 
731
 
 
732
      pixel = (pos_lut[*src++] - neg0[-1] - neg0[2] - neg0[5] -
 
733
               neg1[-1] - neg1[5] -
 
734
               neg2[-1] - neg2[2] - neg2[5]);
 
735
      pixel = (pixel + 4) >> 3;
 
736
      *dst++ = CLAMP0255 (pixel);
 
737
 
 
738
      neg0 += 3;
 
739
      neg1 += 3;
 
740
      neg2 += 3;
 
741
      width --;
 
742
    }
 
743
 
 
744
  *dst++ = *src++;
 
745
  *dst++ = *src++;
 
746
  *dst++ = *src++;
 
747
}
 
748
 
 
749
/*
 
750
 * 'rgba_filter()' - Sharpen RGBA pixels.
 
751
 */
 
752
 
 
753
static void
 
754
rgba_filter (gint   width,      /* I - Width of line in pixels */
 
755
             guchar *src,       /* I - Source line */
 
756
             guchar *dst,       /* O - Destination line */
 
757
             intneg *neg0,      /* I - Top negative coefficient line */
 
758
             intneg *neg1,      /* I - Middle negative coefficient line */
 
759
             intneg *neg2)      /* I - Bottom negative coefficient line */
 
760
{
 
761
  intpos pixel;         /* New pixel value */
 
762
 
 
763
  *dst++ = *src++;
 
764
  *dst++ = *src++;
 
765
  *dst++ = *src++;
 
766
  *dst++ = *src++;
 
767
  width -= 2;
 
768
 
 
769
  while (width > 0)
 
770
    {
 
771
      pixel = (pos_lut[*src++] - neg0[-4] - neg0[0] - neg0[4] -
 
772
               neg1[-4] - neg1[4] -
 
773
               neg2[-4] - neg2[0] - neg2[4]);
 
774
      pixel = (pixel + 4) >> 3;
 
775
      *dst++ = CLAMP0255 (pixel);
 
776
 
 
777
      pixel = (pos_lut[*src++] - neg0[-3] - neg0[1] - neg0[5] -
 
778
               neg1[-3] - neg1[5] -
 
779
               neg2[-3] - neg2[1] - neg2[5]);
 
780
      pixel = (pixel + 4) >> 3;
 
781
      *dst++ = CLAMP0255 (pixel);
 
782
 
 
783
      pixel = (pos_lut[*src++] - neg0[-2] - neg0[2] - neg0[6] -
 
784
               neg1[-2] - neg1[6] -
 
785
               neg2[-2] - neg2[2] - neg2[6]);
 
786
      pixel = (pixel + 4) >> 3;
 
787
      *dst++ = CLAMP0255 (pixel);
 
788
 
 
789
      *dst++ = *src++;
 
790
 
 
791
      neg0 += 4;
 
792
      neg1 += 4;
 
793
      neg2 += 4;
 
794
      width --;
 
795
    }
 
796
 
 
797
  *dst++ = *src++;
 
798
  *dst++ = *src++;
 
799
  *dst++ = *src++;
 
800
  *dst++ = *src++;
 
801
}