gboolean gimp_image_crop_auto_shrink (GimpImage *image, gint x1, gint y1, gint x2, gint y2, gboolean active_drawable_only, gint *shrunk_x1, gint *shrunk_y1, gint *shrunk_x2, gint *shrunk_y2) { GimpDrawable *active_drawable = NULL; GimpPickable *pickable; ColorsEqualFunc colors_equal_func; guchar bgcolor[MAX_CHANNELS] = { 0, 0, 0, 0 }; gboolean has_alpha; PixelRegion PR; guchar *buffer = NULL; gint width, height; GimpImageType type; gint bytes; gint x, y, abort; gboolean retval = FALSE; g_return_val_if_fail (image != NULL, FALSE); g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (shrunk_x1 != NULL, FALSE); g_return_val_if_fail (shrunk_y1 != NULL, FALSE); g_return_val_if_fail (shrunk_x2 != NULL, FALSE); g_return_val_if_fail (shrunk_y2 != NULL, FALSE); gimp_set_busy (image->gimp); /* You should always keep in mind that crop->tx2 and crop->ty2 are the NOT the coordinates of the bottomright corner of the area to be cropped. They point at the pixel located one to the right and one to the bottom. */ if (active_drawable_only) { active_drawable = gimp_image_get_active_drawable (image); if (! active_drawable) goto FINISH; pickable = GIMP_PICKABLE (active_drawable); } else { pickable = GIMP_PICKABLE (image->projection); } gimp_pickable_flush (pickable); type = gimp_pickable_get_image_type (pickable); bytes = GIMP_IMAGE_TYPE_BYTES (type); has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (type); switch (gimp_image_crop_guess_bgcolor (pickable, bytes, has_alpha, bgcolor, x1, x2-1, y1, y2-1)) { case AUTO_CROP_ALPHA: colors_equal_func = (ColorsEqualFunc) gimp_image_crop_colors_alpha; break; case AUTO_CROP_COLOR: colors_equal_func = (ColorsEqualFunc) gimp_image_crop_colors_equal; break; default: goto FINISH; break; } width = x2 - x1; height = y2 - y1; pixel_region_init (&PR, gimp_pickable_get_tiles (pickable), x1, y1, width, height, FALSE); /* The following could be optimized further by processing * the smaller side first instead of defaulting to width --Sven */ buffer = g_malloc ((width > height ? width : height) * bytes); /* Check how many of the top lines are uniform/transparent. */ abort = FALSE; for (y = y1; y < y2 && !abort; y++) { pixel_region_get_row (&PR, x1, y, width, buffer, 1); for (x = 0; x < width && !abort; x++) abort = !(colors_equal_func) (bgcolor, buffer + x * bytes, bytes); } if (y == y2 && !abort) goto FINISH; y1 = y - 1; /* Check how many of the bottom lines are uniform/transparent. */ abort = FALSE; for (y = y2; y > y1 && !abort; y--) { pixel_region_get_row (&PR, x1, y-1 , width, buffer, 1); for (x = 0; x < width && !abort; x++) abort = !(colors_equal_func) (bgcolor, buffer + x * bytes, bytes); } y2 = y + 1; /* compute a new height for the next operations */ height = y2 - y1; /* Check how many of the left lines are uniform/transparent. */ abort = FALSE; for (x = x1; x < x2 && !abort; x++) { pixel_region_get_col (&PR, x, y1, height, buffer, 1); for (y = 0; y < height && !abort; y++) abort = !(colors_equal_func) (bgcolor, buffer + y * bytes, bytes); } x1 = x - 1; /* Check how many of the right lines are uniform/transparent. */ abort = FALSE; for (x = x2; x > x1 && !abort; x--) { pixel_region_get_col (&PR, x-1, y1, height, buffer, 1); for (y = 0; y < height && !abort; y++) abort = !(colors_equal_func) (bgcolor, buffer + y * bytes, bytes); } x2 = x + 1; *shrunk_x1 = x1; *shrunk_y1 = y1; *shrunk_x2 = x2; *shrunk_y2 = y2; retval = TRUE; FINISH: g_free (buffer); gimp_unset_busy (image->gimp); return retval; }
static void gimp_brush_clipboard_buffer_changed (Gimp *gimp, GimpBrush *brush) { gint width; gint height; if (brush->mask) { temp_buf_free (brush->mask); brush->mask = NULL; } if (brush->pixmap) { temp_buf_free (brush->pixmap); brush->pixmap = NULL; } if (gimp->global_buffer) { TileManager *tiles = gimp_buffer_get_tiles (gimp->global_buffer); GimpImageType type = gimp_buffer_get_image_type (gimp->global_buffer); width = MIN (gimp_buffer_get_width (gimp->global_buffer), 1024); height = MIN (gimp_buffer_get_height (gimp->global_buffer), 1024); brush->mask = temp_buf_new (width, height, 1, 0, 0, NULL); brush->pixmap = temp_buf_new (width, height, 3, 0, 0, NULL); /* copy the alpha channel into the brush's mask */ if (GIMP_IMAGE_TYPE_HAS_ALPHA (type)) { PixelRegion bufferPR; PixelRegion maskPR; pixel_region_init (&bufferPR, tiles, 0, 0, width, height, FALSE); pixel_region_init_temp_buf (&maskPR, brush->mask, 0, 0, width, height); extract_alpha_region (&bufferPR, NULL, &maskPR); } else { PixelRegion maskPR; guchar opaque = OPAQUE_OPACITY; pixel_region_init_temp_buf (&maskPR, brush->mask, 0, 0, width, height); color_region (&maskPR, &opaque); } /* copy the color channels into the brush's pixmap */ if (GIMP_IMAGE_TYPE_IS_RGB (type)) { PixelRegion bufferPR; PixelRegion pixmapPR; pixel_region_init (&bufferPR, tiles, 0, 0, width, height, FALSE); pixel_region_init_temp_buf (&pixmapPR, brush->pixmap, 0, 0, width, height); if (GIMP_IMAGE_TYPE_HAS_ALPHA (type)) copy_color (&bufferPR, &pixmapPR); else copy_region (&bufferPR, &pixmapPR); } else { PixelRegion bufferPR; PixelRegion tempPR; TempBuf *temp = temp_buf_new (width, height, 1, 0, 0, NULL); pixel_region_init (&bufferPR, tiles, 0, 0, width, height, FALSE); pixel_region_init_temp_buf (&tempPR, temp, 0, 0, width, height); if (GIMP_IMAGE_TYPE_HAS_ALPHA (type)) copy_component (&bufferPR, &tempPR, 0); else copy_region (&bufferPR, &tempPR); temp_buf_copy (temp, brush->pixmap); temp_buf_free (temp); } } else { guchar color = 0; width = 17; height = 17; brush->mask = temp_buf_new (width, height, 1, 0, 0, &color); } brush->x_axis.x = width / 2; brush->x_axis.y = 0; brush->y_axis.x = 0; brush->y_axis.y = height / 2; gimp_data_dirty (GIMP_DATA (brush)); }
void gimp_display_shell_render (GimpDisplayShell *shell, gint x, gint y, gint w, gint h, GdkRectangle *highlight) { GimpProjection *projection; GimpImage *image; RenderInfo info; GimpImageType type; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (w > 0 && h > 0); image = shell->display->image; projection = image->projection; /* Initialize RenderInfo with values that don't change during the * call of this function. */ info.shell = shell; info.x = x + shell->offset_x; info.y = y + shell->offset_y; info.w = w; info.h = h; info.dest_bpp = 3; info.dest_bpl = info.dest_bpp * GIMP_RENDER_BUF_WIDTH; info.dest_width = info.dest_bpp * info.w; switch (GIMP_DISPLAY_CONFIG (image->gimp->config)->zoom_quality) { case GIMP_ZOOM_QUALITY_LOW: info.zoom_quality = GIMP_DISPLAY_ZOOM_FAST; break; case GIMP_ZOOM_QUALITY_HIGH: info.zoom_quality = GIMP_DISPLAY_ZOOM_PIXEL_AA; break; } if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_projection_get_image_type (projection))) { gdouble opacity = gimp_projection_get_opacity (projection); info.alpha = render_image_init_alpha (opacity * 255.999); } /* Setup RenderInfo for rendering a GimpProjection level. */ { TileManager *src_tiles; gint level; level = gimp_projection_get_level (projection, shell->scale_x, shell->scale_y); src_tiles = gimp_projection_get_tiles_at_level (projection, level); gimp_display_shell_render_info_scale (&info, shell, src_tiles, level); } /* Currently, only RGBA and GRAYA projection types are used. */ type = gimp_projection_get_image_type (projection); switch (type) { case GIMP_RGBA_IMAGE: render_image_rgb_a (&info); break; case GIMP_GRAYA_IMAGE: render_image_gray_a (&info); break; default: g_warning ("%s: unsupported projection type (%d)", G_STRFUNC, type); g_assert_not_reached (); } /* apply filters to the rendered projection */ if (shell->filter_stack) gimp_color_display_stack_convert (shell->filter_stack, shell->render_buf, w, h, 3, 3 * GIMP_RENDER_BUF_WIDTH); /* dim pixels outside the highlighted rectangle */ if (highlight) { gimp_display_shell_render_highlight (shell, x, y, w, h, highlight); } else if (shell->mask) { TileManager *src_tiles = gimp_drawable_get_tiles (shell->mask); /* The mask does not (yet) have an image pyramid, use 0 as level, */ gimp_display_shell_render_info_scale (&info, shell, src_tiles, 0); gimp_display_shell_render_mask (shell, &info); } /* put it to the screen */ gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER, x + shell->disp_xoffset, y + shell->disp_yoffset, w, h, shell->render_buf, 3 * GIMP_RENDER_BUF_WIDTH, shell->offset_x, shell->offset_y); }