예제 #1
0
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;
}
예제 #2
0
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));
}
예제 #3
0
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);
}