static int pf_set_edge_mode(PyGimpPixelFetcher *self, PyObject *value, void *closure) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "cannot delete edge_mode"); return -1; } if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "type mismatch"); return -1; } self->edge_mode = PyInt_AsLong(value); gimp_pixel_fetcher_set_edge_mode(self->pf, self->edge_mode); return 0; }
static void lens_distort_preview (GimpDrawable *drawable, GimpPreview *preview) { guchar *dest; guchar *pixel; gint width, height, bpp; gint x, y; GimpPixelFetcher *pft; GimpRGB background; pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 0.0); gimp_pixel_fetcher_set_bg_color (pft, &background); gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_BACKGROUND); lens_setup_calc (drawable->width, drawable->height); dest = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview), &width, &height, &bpp); pixel = dest; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { gint sx, sy; gimp_preview_untransform (preview, x, y, &sx, &sy); lens_distort_func (sx, sy, pixel, bpp, pft); pixel += bpp; } } gimp_pixel_fetcher_destroy (pft); gimp_preview_draw_buffer (preview, dest, width * bpp); g_free (dest); }
static void polarize (GimpDrawable *drawable) { GimpRgnIterator *iter; GimpPixelFetcher *pft; GimpRGB background; pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 0.0); gimp_pixel_fetcher_set_bg_color (pft, &background); gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_SMEAR); gimp_progress_init (_("Polar coordinates")); iter = gimp_rgn_iterator_new (drawable, 0); gimp_rgn_iterator_dest (iter, polarize_func, pft); gimp_rgn_iterator_free (iter); gimp_pixel_fetcher_destroy (pft); }
static int pf_init(PyGimpPixelFetcher *self, PyObject *args, PyObject *kwargs) { PyGimpDrawable *drw; gboolean shadow = FALSE; GimpRGB bg_color = { 0.0, 0.0, 0.0, 1.0 }; GimpPixelFetcherEdgeMode edge_mode = GIMP_PIXEL_FETCHER_EDGE_NONE; static char *kwlist[] = { "drawable", "shadow", "bg_color", "edge_mode", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|iO&i:gimp.PixelFetcher.__init__", kwlist, &PyGimpDrawable_Type, &drw, &shadow, pygimp_rgb_from_pyobject, &bg_color, &edge_mode)) return -1; if(!drw->drawable) drw->drawable = gimp_drawable_get(drw->ID); self->pf = gimp_pixel_fetcher_new(drw->drawable, shadow); Py_INCREF(drw); self->drawable = drw; self->shadow = shadow; self->bg_color = bg_color; self->edge_mode = edge_mode; self->bpp = gimp_drawable_bpp(drw->drawable->drawable_id); gimp_pixel_fetcher_set_bg_color(self->pf, &bg_color); gimp_pixel_fetcher_set_edge_mode(self->pf, edge_mode); return 0; }
static void lens_distort (GimpDrawable *drawable) { GimpRgnIterator *iter; GimpPixelFetcher *pft; GimpRGB background; lens_setup_calc (drawable->width, drawable->height); pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 0.0); gimp_pixel_fetcher_set_bg_color (pft, &background); gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_BACKGROUND); gimp_progress_init (_("Lens distortion")); iter = gimp_rgn_iterator_new (drawable, 0); gimp_rgn_iterator_dest (iter, (GimpRgnFuncDest) lens_distort_func, pft); gimp_rgn_iterator_free (iter); gimp_pixel_fetcher_destroy (pft); }
static void dialog_update_preview (GimpDrawable *drawable, GimpPreview *preview) { gdouble cx, cy; gint x, y; gint sx, sy; gint width, height; guchar *pixel; guchar outside[4]; GimpRGB background; guchar *dest; gint j; gint bpp; GimpPixelFetcher *pft; guchar in_pixels[4][4]; guchar *in_values[4]; for (j = 0; j < 4; j++) in_values[j] = in_pixels[j]; pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 0.0); gimp_drawable_get_color_uchar (drawable->drawable_id, &background, outside); gimp_pixel_fetcher_set_bg_color (pft, &background); gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_SMEAR); dest = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview), &width, &height, &bpp); pixel = dest; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { gimp_preview_untransform (preview, x, y, &sx, &sy); if (calc_undistorted_coords ((gdouble)sx, (gdouble)sy, &cx, &cy)) { gimp_pixel_fetcher_get_pixel (pft, cx, cy, in_pixels[0]); gimp_pixel_fetcher_get_pixel (pft, cx + 1, cy, in_pixels[1]); gimp_pixel_fetcher_get_pixel (pft, cx, cy + 1, in_pixels[2]); gimp_pixel_fetcher_get_pixel (pft, cx + 1, cy + 1, in_pixels[3]); gimp_bilinear_pixels_8 (pixel, cx, cy, bpp, img_has_alpha, in_values); } else { for (j = 0; j < bpp; j++) pixel[j] = outside[j]; } pixel += bpp; } } gimp_pixel_fetcher_destroy (pft); gimp_preview_draw_buffer (preview, dest, width * bpp); g_free (dest); }
/* ---------------------------------------- * gap_edgeDetection * ---------------------------------------- * * returns the drawable id of a newly created channel * representing edges of the specified image. * * black pixels indicate areas of same or similar colors, * white indicates sharp edges. * */ gint32 gap_edgeDetection(gint32 refDrawableId , gdouble edgeColordiffThreshold , gint32 *countEdgePixels ) { GapEdgeContext edgeContext; GapEdgeContext *ectx; gdouble edgeOpacityThreshold; /* init context */ ectx = &edgeContext; ectx->refDrawable = gimp_drawable_get(refDrawableId); ectx->edgeDrawable = NULL; ectx->edgeColordiffThreshold = CLAMP(edgeColordiffThreshold, 0.0, 1.0); edgeOpacityThreshold = CLAMP((edgeColordiffThreshold * 255), 0, 255); ectx->edgeOpacityThreshold255 = edgeOpacityThreshold; ectx->edgeDrawableId = -1; ectx->countEdgePixels = 0; if(gap_debug) { printf("gap_edgeDetection START edgeColordiffThreshold:%.5f refDrawableId:%d\n" , (float)ectx->edgeColordiffThreshold , (int)refDrawableId ); } if(ectx->refDrawable != NULL) { ectx->pftRef = gimp_pixel_fetcher_new (ectx->refDrawable, FALSE /* shadow */); gimp_pixel_fetcher_set_edge_mode (ectx->pftRef, GIMP_PIXEL_FETCHER_EDGE_BLACK); p_edgeDetection(ectx); gimp_pixel_fetcher_destroy (ectx->pftRef); } if(ectx->refDrawable != NULL) { gimp_drawable_detach(ectx->refDrawable); ectx->refDrawable = NULL; } if(ectx->edgeDrawable != NULL) { gimp_drawable_detach(ectx->edgeDrawable); ectx->edgeDrawable = NULL; } *countEdgePixels = ectx->countEdgePixels; if(gap_debug) { printf("gap_edgeDetection END resulting edgeDrawableId:%d countEdgePixels:%d\n" , (int)ectx->edgeDrawableId , (int)*countEdgePixels ); } return (ectx->edgeDrawableId); } /* end gap_edgeDetection */
static void edge (GimpDrawable *drawable) { GimpPixelRgn src_rgn, dest_rgn; gpointer pr; GimpPixelFetcher *pft; guchar *srcrow, *src; guchar *destrow, *dest; guchar pix00[4], pix01[4], pix02[4]; guchar pix10[4], pix11[4], pix12[4]; guchar pix20[4], pix21[4], pix22[4]; glong width, height; gint alpha; gboolean has_alpha; gint chan; gint x, y; gint x1, y1, x2, y2; gint maxval; gint cur_progress; gint max_progress; gdouble per_progress; if (evals.amount < 1.0) evals.amount = 1.0; pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_pixel_fetcher_set_edge_mode (pft, evals.wrapmode); gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = gimp_drawable_width (drawable->drawable_id); height = gimp_drawable_height (drawable->drawable_id); alpha = gimp_drawable_bpp (drawable->drawable_id); has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); if (has_alpha) alpha--; maxval = 255; cur_progress = 0; per_progress = 0.0; max_progress = (x2 - x1) * (y2 - y1) / 100; gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, x2-x1, y2-y1, FALSE, FALSE); gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, x2-x1, y2-y1, TRUE, TRUE); for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { srcrow = src_rgn.data; destrow = dest_rgn.data; for (y = dest_rgn.y; y < (dest_rgn.y + dest_rgn.h); y++, srcrow += src_rgn.rowstride, destrow += dest_rgn.rowstride) { src = srcrow; dest = destrow; for (x = dest_rgn.x; x < (dest_rgn.x + dest_rgn.w); x++, src += src_rgn.bpp, dest += dest_rgn.bpp) { if (dest_rgn.x < x && x < dest_rgn.x + dest_rgn.w - 2 && dest_rgn.y < y && y < dest_rgn.y + dest_rgn.h - 2) { /* * 3x3 kernel is inside of the tile -- do fast * version */ for (chan = 0; chan < alpha; chan++) { /* get the 3x3 kernel into a guchar array, * and send it to edge_detect */ guchar kernel[9]; gint i,j; #define PIX(X,Y) src[ (Y-1)*(int)src_rgn.rowstride + (X-1)*(int)src_rgn.bpp + chan ] /* make convolution */ for(i = 0; i < 3; i++) for(j = 0; j < 3; j++) kernel[3*i + j] = PIX(i,j); #undef PIX dest[chan] = edge_detect (kernel); } } else { /* * The kernel is not inside of the tile -- do slow * version */ gimp_pixel_fetcher_get_pixel (pft, x-1, y-1, pix00); gimp_pixel_fetcher_get_pixel (pft, x , y-1, pix10); gimp_pixel_fetcher_get_pixel (pft, x+1, y-1, pix20); gimp_pixel_fetcher_get_pixel (pft, x-1, y , pix01); gimp_pixel_fetcher_get_pixel (pft, x , y , pix11); gimp_pixel_fetcher_get_pixel (pft, x+1, y , pix21); gimp_pixel_fetcher_get_pixel (pft, x-1, y+1, pix02); gimp_pixel_fetcher_get_pixel (pft, x , y+1, pix12); gimp_pixel_fetcher_get_pixel (pft, x+1, y+1, pix22); for (chan = 0; chan < alpha; chan++) { guchar kernel[9]; kernel[0] = pix00[chan]; kernel[1] = pix01[chan]; kernel[2] = pix02[chan]; kernel[3] = pix10[chan]; kernel[4] = pix11[chan]; kernel[5] = pix12[chan]; kernel[6] = pix20[chan]; kernel[7] = pix21[chan]; kernel[8] = pix22[chan]; dest[chan] = edge_detect (kernel); } } if (has_alpha) dest[alpha] = src[alpha]; } } cur_progress += dest_rgn.w * dest_rgn.h; if (cur_progress > max_progress) { cur_progress = cur_progress - max_progress; per_progress = per_progress + 0.01; gimp_progress_update (per_progress); } } gimp_progress_update (1.0); gimp_pixel_fetcher_destroy (pft); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1)); }
static void displace (GimpDrawable *drawable, GimpPreview *preview) { GimpDrawable *map_x = NULL; GimpDrawable *map_y = NULL; GimpPixelRgn dest_rgn; GimpPixelRgn map_x_rgn; GimpPixelRgn map_y_rgn; gpointer pr; GimpPixelFetcher *pft; gint width; gint height; gint bytes; guchar *destrow, *dest; guchar *mxrow, *mx; guchar *myrow, *my; guchar pixel[4][4]; gint x1, y1, x2, y2; gint x, y; gdouble cx, cy; gint progress, max_progress; gdouble amnt; gdouble needx, needy; gdouble radius, d_alpha; gint xi, yi; guchar values[4]; guchar val; gint k; gdouble xm_val, ym_val; gint xm_alpha = 0; gint ym_alpha = 0; gint xm_bytes = 1; gint ym_bytes = 1; guchar *buffer = NULL; gdouble pi; /* initialize */ /* get rid of uninitialized warnings */ cx = cy = needx = needy = radius = d_alpha = 0.0; pi = 4 * atan (1); mxrow = NULL; myrow = NULL; pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_pixel_fetcher_set_edge_mode (pft, dvals.displace_type); bytes = drawable->bpp; gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = x2 - x1; height = y2 - y1; if (dvals.mode == POLAR_MODE) { cx = x1 + width / 2.0; cy = y1 + height / 2.0; } if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); x2 = x1 + width; y2 = y1 + height; buffer = g_new (guchar, width * height * bytes); } progress = 0; max_progress = width * height; /* * The algorithm used here is simple - see * http://the-tech.mit.edu/KPT/Tips/KPT7/KPT7.html for a description. */ /* Get the drawables */ if (dvals.displace_map_x != -1 && dvals.do_x) { map_x = gimp_drawable_get (dvals.displace_map_x); gimp_pixel_rgn_init (&map_x_rgn, map_x, x1, y1, width, height, FALSE, FALSE); if (gimp_drawable_has_alpha (map_x->drawable_id)) xm_alpha = 1; xm_bytes = gimp_drawable_bpp (map_x->drawable_id); } if (dvals.displace_map_y != -1 && dvals.do_y) { map_y = gimp_drawable_get (dvals.displace_map_y); gimp_pixel_rgn_init (&map_y_rgn, map_y, x1, y1, width, height, FALSE, FALSE); if (gimp_drawable_has_alpha (map_y->drawable_id)) ym_alpha = 1; ym_bytes = gimp_drawable_bpp (map_y->drawable_id); } gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, width, height, preview == NULL, preview == NULL); /* Register the pixel regions */ if (dvals.do_x && dvals.do_y) pr = gimp_pixel_rgns_register (3, &dest_rgn, &map_x_rgn, &map_y_rgn); else if (dvals.do_x) pr = gimp_pixel_rgns_register (2, &dest_rgn, &map_x_rgn); else if (dvals.do_y) pr = gimp_pixel_rgns_register (2, &dest_rgn, &map_y_rgn); else pr = NULL; for (pr = pr; pr != NULL; pr = gimp_pixel_rgns_process (pr)) { destrow = dest_rgn.data; if (dvals.do_x) mxrow = map_x_rgn.data; if (dvals.do_y) myrow = map_y_rgn.data; for (y = dest_rgn.y; y < (dest_rgn.y + dest_rgn.h); y++) { if (preview) dest = buffer + ((y - y1) * width + (dest_rgn.x - x1)) * bytes; else dest = destrow; mx = mxrow; my = myrow; /* * We could move the displacement image address calculation * out of here, but when we can have different sized * displacement and destination images we'd have to move it * back anyway. */ for (x = dest_rgn.x; x < (dest_rgn.x + dest_rgn.w); x++) { if (dvals.do_x) { xm_val = displace_map_give_value(mx, xm_alpha, xm_bytes); amnt = dvals.amount_x * (xm_val - 127.5) / 127.5; /* CARTESIAN_MODE == 0 - performance important here */ if (! dvals.mode) { needx = x + amnt; } else { radius = sqrt (SQR (x - cx) + SQR (y - cy)) + amnt; } mx += xm_bytes; } else { if (! dvals.mode) needx = x; else radius = sqrt ((x - cx) * (x - cx) + (y - cy) * (y - cy)); } if (dvals.do_y) { ym_val = displace_map_give_value(my, ym_alpha, ym_bytes); amnt = dvals.amount_y * (ym_val - 127.5) / 127.5; if (! dvals.mode) { needy = y + amnt; } else { d_alpha = atan2 (x - cx, y - cy) + (dvals.amount_y / 180) * pi * (ym_val - 127.5) / 127.5; } my += ym_bytes; } else { if (! dvals.mode) needy = y; else d_alpha = atan2 (x - cx, y - cy); } if (dvals.mode) { needx = cx + radius * sin (d_alpha); needy = cy + radius * cos (d_alpha); } /* Calculations complete; now copy the proper pixel */ if (needx >= 0.0) xi = (int) needx; else xi = -((int) -needx + 1); if (needy >= 0.0) yi = (int) needy; else yi = -((int) -needy + 1); gimp_pixel_fetcher_get_pixel (pft, xi, yi, pixel[0]); gimp_pixel_fetcher_get_pixel (pft, xi + 1, yi, pixel[1]); gimp_pixel_fetcher_get_pixel (pft, xi, yi + 1, pixel[2]); gimp_pixel_fetcher_get_pixel (pft, xi + 1, yi + 1, pixel[3]); for (k = 0; k < bytes; k++) { values[0] = pixel[0][k]; values[1] = pixel[1][k]; values[2] = pixel[2][k]; values[3] = pixel[3][k]; val = gimp_bilinear_8 (needx, needy, values); *dest++ = val; } /* for */ } destrow += dest_rgn.rowstride; if (dvals.do_x) mxrow += map_x_rgn.rowstride; if (dvals.do_y) myrow += map_y_rgn.rowstride; } if (!preview) { progress += dest_rgn.w * dest_rgn.h; gimp_progress_update ((double) progress / (double) max_progress); } } /* for */ gimp_pixel_fetcher_destroy (pft); /* detach from the map drawables */ if (dvals.do_x) gimp_drawable_detach (map_x); if (dvals.do_y) gimp_drawable_detach (map_y); if (preview) { /* gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &dest_rgn);*/ gimp_preview_draw_buffer (preview, buffer, width * bytes); g_free (buffer); } else { /* update the region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } }
static void shift (GimpDrawable *drawable, GimpPreview *preview) { GimpPixelRgn dest_rgn; gpointer pr; GimpPixelFetcher *pft; gint width, height; gint bytes; guchar *destline; guchar *dest; gint x1, y1, x2, y2; gint x, y; gint progress, max_progress; gint i, n = 0; gint *offsets; GRand *gr; if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); } else { gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = x2 - x1; height = y2 - y1; } bytes = drawable->bpp; progress = 0; max_progress = width * height; /* Shift the image. It's a pretty simple algorithm. If horizontal is selected, then every row is shifted a random number of pixels in the range of -shift_amount/2 to shift_amount/2. The effect is just reproduced with columns if vertical is selected. */ n = (shvals.orientation == HORIZONTAL) ? height : width; offsets = g_new (gint, n); gr = g_rand_new (); for (i = 0; i < n; i++) offsets[i] = g_rand_int_range (gr, - (shvals.shift_amount + 1) / 2.0, + (shvals.shift_amount + 1) / 2.0); g_rand_free (gr); pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_WRAP); gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, width, height, (preview == NULL), TRUE); for (pr = gimp_pixel_rgns_register (1, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { destline = dest_rgn.data; switch (shvals.orientation) { case HORIZONTAL: for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) { dest = destline; for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) { gimp_pixel_fetcher_get_pixel (pft, x + offsets[y - y1], y, dest); dest += bytes; } destline += dest_rgn.rowstride; } break; case VERTICAL: for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) { dest = destline; for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) { gimp_pixel_fetcher_get_pixel (pft, x, y + offsets[x - x1], dest); dest += dest_rgn.rowstride; } destline += bytes; } break; } if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &dest_rgn); } else { progress += dest_rgn.w * dest_rgn.h; gimp_progress_update ((double) progress / (double) max_progress); } } gimp_pixel_fetcher_destroy (pft); g_free (offsets); if (! preview) { gimp_progress_update (1.0); /* update the region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } }
/* -------------------------------- * gap_moprhShapeDetectionEdgeBased * -------------------------------- * * generates morph workpoints via edge based shape detection. * This is done by edge detection in the source image * (specified via mgup->mgpp->osrc_layer_id) * * and picking workpoints on the detected edges * and locating the corresponding point in the destination image. * * IN: mgup->num_shapepoints specifies the number of workpoints to be generated. */ void gap_moprhShapeDetectionEdgeBased(GapMorphGUIParams *mgup, gboolean *cancelFlagPtr) { GapMorphShapeContext morphShapeContext; GapMorphShapeContext *msctx; gboolean deleteEdgeImage; GapMorphGlobalParams *mgpp; mgpp = mgup->mgpp; if(mgup->workpointGenerationBusy == TRUE) { return; } mgup->workpointGenerationBusy = TRUE; deleteEdgeImage = TRUE; /* init context */ msctx = &morphShapeContext; msctx->edgeColordiffThreshold = CLAMP(mgpp->edgeColordiffThreshold, 0.0, 1.0); msctx->locateColordiffThreshold = CLAMP(mgpp->locateColordiffThreshold, 0.0, 1.0); msctx->locateDetailShapeRadius = mgpp->locateDetailShapeRadius; msctx->locateDetailMoveRadius = mgpp->locateDetailMoveRadius; msctx->colorSensitivity = GAP_COLORDIFF_DEFAULT_SENSITIVITY; msctx->refLayerId = mgpp->osrc_layer_id; msctx->targetLayerId = mgpp->fdst_layer_id; msctx->numShapePoints = mgpp->numWorkpoints; msctx->countGeneratedPoints = 0; msctx->doProgress = TRUE; msctx->progressBar = mgup->progressBar; if(msctx->progressBar == NULL) { msctx->doProgress = FALSE; } msctx->cancelWorkpointGenerationPtr = cancelFlagPtr; if(gap_debug) { printf("gap_moprhShapeDetectionEdgeBased START edgeThres:%.5f locateThres:%.5f locateRadius:%d\n" , (float)msctx->edgeColordiffThreshold , (float)msctx->locateDetailMoveRadius , (int)msctx->locateDetailMoveRadius ); } msctx->edgeLayerId = gap_edgeDetection(mgup->mgpp->osrc_layer_id /* refDrawableId */ ,mgup->mgpp->edgeColordiffThreshold ,&msctx->countEdgePixels ); msctx->edgeImageId = gimp_drawable_get_image(msctx->edgeLayerId); if(gap_debug) { /* show the edge image for debug purpose * (this image is intended for internal processing usage) */ gimp_display_new(msctx->edgeImageId); deleteEdgeImage = FALSE; } msctx->edgeDrawable = gimp_drawable_get(msctx->edgeLayerId); if(msctx->edgeDrawable != NULL) { gint maxWidth; gint maxHeight; maxWidth = msctx->edgeDrawable->width-1; maxHeight = msctx->edgeDrawable->height-1; if((mgup->src_win.zoom < 1.0) && (mgup->src_win.zoom > 0.0)) { gdouble fwidth; gdouble fheight; gint width; gint height; fwidth = mgup->src_win.zoom * (gdouble)mgup->src_win.pv_ptr->pv_width; fheight = mgup->src_win.zoom * (gdouble)mgup->src_win.pv_ptr->pv_height; width = CLAMP((gint)fwidth, 1, maxWidth); height = CLAMP((gint)fheight, 1, maxHeight); msctx->sel1X = CLAMP(mgup->src_win.offs_x, 0, maxWidth); msctx->sel1Y = CLAMP(mgup->src_win.offs_y, 0, maxHeight); msctx->sel2X = CLAMP((msctx->sel1X + width), 0, maxWidth); msctx->sel2Y = CLAMP((msctx->sel1Y + height), 0, maxHeight); } else { msctx->sel1X = 0; msctx->sel1Y = 0; msctx->sel2X = maxWidth; msctx->sel2Y = maxHeight; } if(gap_debug) { printf("Boundaries: sel1: %d / %d sel2: %d / %d zoom:%.5f\n" , (int)msctx->sel1X , (int)msctx->sel1Y , (int)msctx->sel2X , (int)msctx->sel2Y , (float)mgup->src_win.zoom ); } msctx->pftEdge = gimp_pixel_fetcher_new (msctx->edgeDrawable, FALSE /* shadow */); gimp_pixel_fetcher_set_edge_mode (msctx->pftEdge, GIMP_PIXEL_FETCHER_EDGE_BLACK); p_generateWorkpoints(msctx, mgpp); gimp_pixel_fetcher_destroy (msctx->pftEdge); } if(msctx->edgeDrawable != NULL) { gimp_drawable_detach(msctx->edgeDrawable); msctx->edgeDrawable = NULL; } if(deleteEdgeImage == TRUE) { gap_image_delete_immediate(msctx->edgeImageId); } if(gap_debug) { printf("gap_moprhShapeDetectionEdgeBased END\n"); } mgup->workpointGenerationBusy = FALSE; return ; } /* end gap_moprhShapeDetectionEdgeBased */