/* Auntie Alias 0.92 --- image filter plug-in for The GIMP * * Copyright (C) 2005 Adam D. Moss (adam@gimp.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this plug-in (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject * to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* This plugin performs a pseudo-antialiasing effect on hard-edged source * material. It does this by performing a 'clever' edge extrapolation for * each pixel which is then resampled back to a single pixel for output. */ #include "config.h" #include #include #include #include #include "libgimp/stdplugins-intl.h" /* Constants */ #define PROCEDURE_NAME "gimp_plugin_auntiealias" /* Local function prototypes */ static void query (void); static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); /* Local variables */ GimpPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ }; MAIN () static void query (void) { static GimpParamDef args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_IMAGE, "image", "Input image" }, { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" } }; gimp_install_procedure (PROCEDURE_NAME, "Blurb - write me", "Help - write me", "Adam D. Moss ", "Adam D. Moss ", "2005", N_("/Filters/Enhance/_Auntie Alias..."), "RGB*, GRAY*", GIMP_PLUGIN, G_N_ELEMENTS (args), 0, args, NULL); } static int extrapolate9(const int bytes, unsigned char *E0, unsigned char *E1, unsigned char *E2, unsigned char *E3, unsigned char *E4, unsigned char *E5, unsigned char *E6, unsigned char *E7, unsigned char *E8, unsigned char *A, unsigned char *B, unsigned char *C, unsigned char *D, unsigned char *E, unsigned char *F, unsigned char *G, unsigned char *H, unsigned char *I) { #define PEQ(X,Y) (0==memcmp(X,Y,bytes)) #define PCPY(DST,SRC) do{memcpy(DST,SRC,bytes);}while(0) /* an implementation of the Scale3X edge-extrapolation algorithm */ if ( (!PEQ(B,H)) && (!PEQ(D,F)) ) { if (PEQ(D,B)) PCPY(E0,D); else PCPY(E0,E); if ((PEQ(D,B) && !PEQ(E,C)) || (PEQ(B,F) && !PEQ(E,A))) PCPY(E1,B); else PCPY(E1,E); if (PEQ(B,F)) PCPY(E2,F); else PCPY(E2,E); if ((PEQ(D,B) && !PEQ(E,G)) || (PEQ(D,H) && !PEQ(E,A))) PCPY(E3,D); else PCPY(E3,E); PCPY(E4,E); if ((PEQ(B,F) && !PEQ(E,I)) || (PEQ(H,F) && !PEQ(E,C))) PCPY(E5,F); else PCPY(E5,E); if (PEQ(D,H)) PCPY(E6,D); else PCPY(E6,E); if ((PEQ(D,H) && !PEQ(E,I)) || (PEQ(H,F) && !PEQ(E,G))) PCPY(E7,H); else PCPY(E7,E); if (PEQ(H,F)) PCPY(E8,F); else PCPY(E8,E); return 1; } else { return 0; } #undef PEQ #undef PCPY } void render (gint32 image_ID, GimpDrawable *drawable) { gint width, height, bytes; gint x1, y1, x2, y2; gint row,col,b; GimpPixelRgn srcPR, destPR; guchar *rowbefore; guchar *rowthis; guchar *rowafter; guchar *dest; guchar *ninepix; gboolean has_alpha; guint alpha; /* get bounds of working area */ gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = drawable->width; height = drawable->height; bytes = drawable->bpp; has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); alpha = bytes-1; gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE); rowbefore = g_new(guchar, (width+2)*bytes); rowthis = g_new(guchar, (width+2)*bytes); rowafter = g_new(guchar, (width+2)*bytes); dest = g_new(guchar, (width+2)*bytes); ninepix = g_new(guchar, (9)*bytes); gimp_pixel_rgn_get_row(&srcPR, &rowthis[bytes], 0, 0, width); memcpy(&rowthis[0], &rowthis[bytes], bytes); memcpy(&rowthis[(width+1)*bytes], &rowthis[(width)*bytes], bytes); memcpy(rowbefore, rowthis, (width+2)*bytes); memcpy(rowafter, rowthis, (width+2)*bytes); for (row=y1; row= (y2-1)) { srcrowafter = y2-1; } /* rotate pointers */ tmp = rowbefore; rowbefore = rowthis; rowthis = rowafter; rowafter = tmp; /* populate new after-row */ gimp_pixel_rgn_get_row(&srcPR, &rowafter[bytes], 0, srcrowafter, width); memcpy(&rowafter[0], &rowafter[bytes], bytes); memcpy(&rowafter[(width+1)*bytes], &rowafter[(width)*bytes], bytes); for (col=x1; coldrawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1)); g_free(rowbefore); g_free(rowthis); g_free(rowafter); g_free(dest); g_free(ninepix); } static void run (const gchar *name, gint n_params, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[1]; GimpDrawable *drawable; gint32 image_ID; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; *nreturn_vals = 1; *return_vals = values; run_mode = param[0].data.d_int32; image_ID = param[1].data.d_int32; drawable = gimp_drawable_get (param[2].data.d_drawable); if (strcmp (name, PROCEDURE_NAME) == 0) { switch (run_mode) { case GIMP_RUN_NONINTERACTIVE: if (n_params != 3) { status = GIMP_PDB_CALLING_ERROR; } else { /* okay */ } break; case GIMP_RUN_INTERACTIVE: /* okay */ break; case GIMP_RUN_WITH_LAST_VALS: /* okay */ break; default: break; } } else { status = GIMP_PDB_CALLING_ERROR; } if (status == GIMP_PDB_SUCCESS) { gimp_progress_init (_("Auntie Aliasing...")); gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1)); render (image_ID, drawable); if (run_mode != GIMP_RUN_NONINTERACTIVE) gimp_displays_flush (); gimp_drawable_detach (drawable); } values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; }