void
gimp_image_convert_precision (GimpImage     *image,
                              GimpPrecision  precision,
                              gint           layer_dither_type,
                              gint           text_layer_dither_type,
                              gint           mask_dither_type,
                              GimpProgress  *progress)
{
  GimpColorProfile *old_profile;
  GimpColorProfile *new_profile = NULL;
  const Babl       *old_format;
  const Babl       *new_format;
  GList            *all_drawables;
  GList            *list;
  const gchar      *undo_desc    = NULL;
  GimpProgress     *sub_progress = NULL;
  gint              nth_drawable, n_drawables;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (precision != gimp_image_get_precision (image));
  g_return_if_fail (precision == GIMP_PRECISION_U8_GAMMA ||
                    gimp_image_get_base_type (image) != GIMP_INDEXED);
  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));

  all_drawables = g_list_concat (gimp_image_get_layer_list (image),
                                 gimp_image_get_channel_list (image));

  n_drawables = g_list_length (all_drawables) + 1 /* + selection */;

  if (progress)
    sub_progress = gimp_sub_progress_new (progress);

  switch (precision)
    {
    case GIMP_PRECISION_U8_LINEAR:
      undo_desc = C_("undo-type", "Convert Image to 8 bit linear integer");
      break;
    case GIMP_PRECISION_U8_GAMMA:
      undo_desc = C_("undo-type", "Convert Image to 8 bit gamma integer");
      break;
    case GIMP_PRECISION_U16_LINEAR:
      undo_desc = C_("undo-type", "Convert Image to 16 bit linear integer");
      break;
    case GIMP_PRECISION_U16_GAMMA:
      undo_desc = C_("undo-type", "Convert Image to 16 bit gamma integer");
      break;
    case GIMP_PRECISION_U32_LINEAR:
      undo_desc = C_("undo-type", "Convert Image to 32 bit linear integer");
      break;
    case GIMP_PRECISION_U32_GAMMA:
      undo_desc = C_("undo-type", "Convert Image to 32 bit gamma integer");
      break;
    case GIMP_PRECISION_HALF_LINEAR:
      undo_desc = C_("undo-type", "Convert Image to 16 bit linear floating point");
      break;
    case GIMP_PRECISION_HALF_GAMMA:
      undo_desc = C_("undo-type", "Convert Image to 16 bit gamma floating point");
      break;
    case GIMP_PRECISION_FLOAT_LINEAR:
      undo_desc = C_("undo-type", "Convert Image to 32 bit linear floating point");
      break;
    case GIMP_PRECISION_FLOAT_GAMMA:
      undo_desc = C_("undo-type", "Convert Image to 32 bit gamma floating point");
      break;
    case GIMP_PRECISION_DOUBLE_LINEAR:
      undo_desc = C_("undo-type", "Convert Image to 64 bit linear floating point");
      break;
    case GIMP_PRECISION_DOUBLE_GAMMA:
      undo_desc = C_("undo-type", "Convert Image to 64 bit gamma floating point");
      break;
    }

  if (progress)
    gimp_progress_start (progress, FALSE, "%s", undo_desc);

  g_object_freeze_notify (G_OBJECT (image));

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_CONVERT,
                               undo_desc);

  /*  Push the image precision to the stack  */
  gimp_image_undo_push_image_precision (image, NULL);

  old_profile = gimp_image_get_color_profile (image);
  old_format  = gimp_image_get_layer_format (image, FALSE);

  /*  Set the new precision  */
  g_object_set (image, "precision", precision, NULL);

  new_format = gimp_image_get_layer_format (image, FALSE);

  if (old_profile &&
      gimp_babl_format_get_linear (old_format) !=
      gimp_babl_format_get_linear (new_format))
    {
      GimpColorProfile *new_profile;

      /* when converting between linear and gamma, we create a new
       * profile using the original profile's chromacities and
       * whitepoint, but a linear/sRGB-gamma TRC.
       */

      if (gimp_babl_format_get_linear (new_format))
        {
          new_profile =
            gimp_color_profile_new_linear_from_color_profile (old_profile);
        }
      else
        {
          new_profile =
            gimp_color_profile_new_srgb_trc_from_color_profile (old_profile);
        }

      /* if a new profile cannot be be generated, convert to the
       * builtin profile, which is better than leaving the user with
       * broken colors
       */
      if (! new_profile)
        {
          new_profile = gimp_image_get_builtin_color_profile (image);
          g_object_ref (new_profile);
        }
    }

  for (list = all_drawables, nth_drawable = 0;
       list;
       list = g_list_next (list), nth_drawable++)
    {
      GimpDrawable *drawable = list->data;
      gint          dither_type;

      if (gimp_item_is_text_layer (GIMP_ITEM (drawable)))
        dither_type = text_layer_dither_type;
      else
        dither_type = layer_dither_type;

      if (sub_progress)
        gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                    nth_drawable, n_drawables);

      gimp_drawable_convert_type (drawable, image,
                                  gimp_drawable_get_base_type (drawable),
                                  precision,
                                  new_profile,
                                  dither_type,
                                  mask_dither_type,
                                  TRUE, sub_progress);
    }

  g_list_free (all_drawables);

  if (old_profile)
    {
      gimp_image_set_color_profile (image, new_profile, NULL);
      g_object_unref (new_profile);
    }

  /*  convert the selection mask  */
  {
    GimpChannel *mask = gimp_image_get_mask (image);
    GeglBuffer  *buffer;

    if (sub_progress)
      gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                  nth_drawable, n_drawables);

    gimp_image_undo_push_mask_precision (image, NULL, mask);

    buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                              gimp_image_get_width  (image),
                                              gimp_image_get_height (image)),
                              gimp_image_get_mask_format (image));

    gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)), NULL,
                      GEGL_ABYSS_NONE,
                      buffer, NULL);

    gimp_drawable_set_buffer (GIMP_DRAWABLE (mask), FALSE, NULL, buffer);
    g_object_unref (buffer);

    nth_drawable++;
  }

  if (sub_progress)
    gimp_progress_set_value (sub_progress, 1.0);

  gimp_image_undo_group_end (image);

  gimp_image_precision_changed (image);
  g_object_thaw_notify (G_OBJECT (image));

  if (sub_progress)
    g_object_unref (sub_progress);

  if (progress)
    gimp_progress_end (progress);
}
示例#2
0
static void
gimp_thumb_box_create_thumbnails (GimpThumbBox *box,
                                  gboolean      force)
{
  Gimp           *gimp     = box->imagefile->gimp;
  GimpProgress   *progress = GIMP_PROGRESS (box);
  GimpFileDialog *dialog   = NULL;
  GtkWidget      *toplevel;
  GSList         *list;
  gint            n_uris;
  gint            i;

  if (gimp->config->thumbnail_size == GIMP_THUMBNAIL_SIZE_NONE)
    return;

  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));

  if (GIMP_IS_FILE_DIALOG (toplevel))
    dialog = GIMP_FILE_DIALOG (toplevel);

  gimp_set_busy (gimp);

  if (dialog)
    gimp_file_dialog_set_sensitive (dialog, FALSE);
  else
    gtk_widget_set_sensitive (toplevel, FALSE);

  if (box->uris)
    {
      gtk_widget_hide (box->info);
      gtk_widget_show (box->progress);
    }

  n_uris = g_slist_length (box->uris);

  if (n_uris > 1)
    {
      gchar *str;

      gimp_progress_start (GIMP_PROGRESS (box), "", TRUE);

      progress = gimp_sub_progress_new (GIMP_PROGRESS (box));

      gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), 0, n_uris);

      for (list = box->uris->next, i = 1;
           list;
           list = g_slist_next (list), i++)
        {
          str = g_strdup_printf (_("Thumbnail %d of %d"), i, n_uris);
          gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), str);
          g_free (str);

          gimp_progress_set_value (progress, 0.0);

          while (gtk_events_pending ())
            gtk_main_iteration ();

          gimp_thumb_box_create_thumbnail (box,
                                           list->data,
                                           gimp->config->thumbnail_size,
                                           force,
                                           progress);

          if (dialog && dialog->canceled)
            goto canceled;

          gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), i, n_uris);
        }

      str = g_strdup_printf (_("Thumbnail %d of %d"), n_uris, n_uris);
      gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), str);
      g_free (str);

      gimp_progress_set_value (progress, 0.0);

      while (gtk_events_pending ())
        gtk_main_iteration ();
    }

  if (box->uris)
    {
      gimp_thumb_box_create_thumbnail (box,
                                       box->uris->data,
                                       gimp->config->thumbnail_size,
                                       force,
                                       progress);

      gimp_progress_set_value (progress, 1.0);
    }

 canceled:

  if (n_uris > 1)
    {
      g_object_unref (progress);

      gimp_progress_end (GIMP_PROGRESS (box));
      gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), "");
    }

  if (box->uris)
    {
      gtk_widget_hide (box->progress);
      gtk_widget_show (box->info);
    }

  if (dialog)
    gimp_file_dialog_set_sensitive (dialog, TRUE);
  else
    gtk_widget_set_sensitive (toplevel, TRUE);

  gimp_unset_busy (gimp);
}
void
gimp_image_scale (GimpImage             *image,
                  gint                   new_width,
                  gint                   new_height,
                  GimpInterpolationType  interpolation_type,
                  GimpProgress          *progress)
{
    GimpProgress *sub_progress;
    GList        *all_layers;
    GList        *all_channels;
    GList        *all_vectors;
    GList        *list;
    gint          old_width;
    gint          old_height;
    gint          offset_x;
    gint          offset_y;
    gdouble       img_scale_w      = 1.0;
    gdouble       img_scale_h      = 1.0;
    gint          progress_steps;
    gint          progress_current = 0;

    g_return_if_fail (GIMP_IS_IMAGE (image));
    g_return_if_fail (new_width > 0 && new_height > 0);
    g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));

    gimp_set_busy (image->gimp);

    sub_progress = gimp_sub_progress_new (progress);

    all_layers   = gimp_image_get_layer_list (image);
    all_channels = gimp_image_get_channel_list (image);
    all_vectors  = gimp_image_get_vectors_list (image);

    progress_steps = (g_list_length (all_layers)   +
                      g_list_length (all_channels) +
                      g_list_length (all_vectors)  +
                      1 /* selection */);

    g_object_freeze_notify (G_OBJECT (image));

    gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
                                 C_("undo-type", "Scale Image"));

    old_width   = gimp_image_get_width  (image);
    old_height  = gimp_image_get_height (image);
    img_scale_w = (gdouble) new_width  / (gdouble) old_width;
    img_scale_h = (gdouble) new_height / (gdouble) old_height;

    offset_x = (old_width  - new_width)  / 2;
    offset_y = (old_height - new_height) / 2;

    /*  Push the image size to the stack  */
    gimp_image_undo_push_image_size (image,
                                     NULL,
                                     offset_x,
                                     offset_y,
                                     new_width,
                                     new_height);

    /*  Set the new width and height early, so below image item setters
     *  (esp. guides and sample points) don't choke about moving stuff
     *  out of the image
     */
    g_object_set (image,
                  "width",  new_width,
                  "height", new_height,
                  NULL);

    /*  Scale all channels  */
    for (list = all_channels; list; list = g_list_next (list))
    {
        GimpItem *item = list->data;

        gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                    progress_current++, progress_steps);

        gimp_item_scale (item,
                         new_width, new_height, 0, 0,
                         interpolation_type, sub_progress);
    }

    /*  Scale all vectors  */
    for (list = all_vectors; list; list = g_list_next (list))
    {
        GimpItem *item = list->data;

        gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                    progress_current++, progress_steps);

        gimp_item_scale (item,
                         new_width, new_height, 0, 0,
                         interpolation_type, sub_progress);
    }

    /*  Don't forget the selection mask!  */
    gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                progress_current++, progress_steps);

    gimp_item_scale (GIMP_ITEM (gimp_image_get_mask (image)),
                     new_width, new_height, 0, 0,
                     interpolation_type, sub_progress);

    /*  Scale all layers  */
    for (list = all_layers; list; list = g_list_next (list))
    {
        GimpItem *item = list->data;

        gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                    progress_current++, progress_steps);

        /*  group layers are updated automatically  */
        if (gimp_viewable_get_children (GIMP_VIEWABLE (item)))
        {
            gimp_group_layer_suspend_resize (GIMP_GROUP_LAYER (item), FALSE);
            continue;
        }

        if (! gimp_item_scale_by_factors (item,
                                          img_scale_w, img_scale_h,
                                          interpolation_type, sub_progress))
        {
            /* Since 0 < img_scale_w, img_scale_h, failure due to one or more
             * vanishing scaled layer dimensions. Implicit delete implemented
             * here. Upstream warning implemented in resize_check_layer_scaling(),
             * which offers the user the chance to bail out.
             */
            gimp_image_remove_layer (image, GIMP_LAYER (item), TRUE, NULL);
        }
    }

    for (list = all_layers; list; list = g_list_next (list))
        if (gimp_viewable_get_children (list->data))
            gimp_group_layer_resume_resize (list->data, FALSE);


    /*  Scale all Guides  */
    for (list = gimp_image_get_guides (image);
            list;
            list = g_list_next (list))
    {
        GimpGuide *guide    = list->data;
        gint       position = gimp_guide_get_position (guide);

        switch (gimp_guide_get_orientation (guide))
        {
        case GIMP_ORIENTATION_HORIZONTAL:
            gimp_image_move_guide (image, guide,
                                   (position * new_height) / old_height,
                                   TRUE);
            break;

        case GIMP_ORIENTATION_VERTICAL:
            gimp_image_move_guide (image, guide,
                                   (position * new_width) / old_width,
                                   TRUE);
            break;

        default:
            break;
        }
    }

    /*  Scale all sample points  */
    for (list = gimp_image_get_sample_points (image);
            list;
            list = g_list_next (list))
    {
        GimpSamplePoint *sample_point = list->data;

        gimp_image_move_sample_point (image, sample_point,
                                      sample_point->x * new_width  / old_width,
                                      sample_point->y * new_height / old_height,
                                      TRUE);
    }

    gimp_image_undo_group_end (image);

    g_list_free (all_layers);
    g_list_free (all_channels);
    g_list_free (all_vectors);

    g_object_unref (sub_progress);

    gimp_image_size_changed_detailed (image,
                                      -offset_x,
                                      -offset_y,
                                      old_width,
                                      old_height);

    g_object_thaw_notify (G_OBJECT (image));

    gimp_unset_busy (image->gimp);
}
static void
gimp_image_convert_profile_layers (GimpImage                *image,
                                   GimpColorProfile         *src_profile,
                                   GimpColorProfile         *dest_profile,
                                   GimpColorRenderingIntent  intent,
                                   gboolean                  bpc,
                                   GimpProgress             *progress)
{
  GList *layers;
  GList *list;
  gint   n_drawables  = 0;
  gint   nth_drawable = 0;

  layers = gimp_image_get_layer_list (image);

  for (list = layers; list; list = g_list_next (list))
    {
      if (! gimp_viewable_get_children (list->data))
        n_drawables++;
    }

  for (list = layers; list; list = g_list_next (list))
    {
      GimpDrawable *drawable     = list->data;
      GimpProgress *sub_progress = NULL;

      if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
        continue;

      if (progress)
        {
          sub_progress = gimp_sub_progress_new (progress);
          gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress),
                                      nth_drawable, n_drawables);
        }

      nth_drawable++;

      gimp_drawable_push_undo (drawable, NULL, NULL,
                               0, 0,
                               gimp_item_get_width  (GIMP_ITEM (drawable)),
                               gimp_item_get_height (GIMP_ITEM (drawable)));

      gimp_gegl_convert_color_profile (gimp_drawable_get_buffer (drawable),
                                       NULL,
                                       src_profile,
                                       gimp_drawable_get_buffer (drawable),
                                       NULL,
                                       dest_profile,
                                       intent, bpc,
                                       sub_progress);

      gimp_drawable_update (drawable, 0, 0,
                            gimp_item_get_width  (GIMP_ITEM (drawable)),
                            gimp_item_get_height (GIMP_ITEM (drawable)));

      if (sub_progress)
        g_object_unref (sub_progress);
    }

  g_list_free (layers);
}
示例#5
0
static void
gimp_warp_tool_animate (GimpWarpTool *wt)
{
  GimpTool        *tool    = GIMP_TOOL (wt);
  GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt);
  GimpImage       *orig_image;
  GimpImage       *image;
  GimpLayer       *layer;
  GimpLayer       *first_layer;
  GeglNode        *scale_node;
  GimpProgress    *progress;
  GtkWidget       *widget;
  gint             i;

  if (! gimp_warp_tool_get_undo_desc (tool, tool->display))
    {
      gimp_tool_message_literal (tool, tool->display,
                                 _("Please add some warp strokes first."));
      return;
    }

  /*  get rid of the image map so we can use wt->graph  */
  if (wt->image_map)
    {
      gimp_image_map_abort (wt->image_map);
      g_object_unref (wt->image_map);
      wt->image_map = NULL;
    }

  gimp_progress_start (GIMP_PROGRESS (tool), FALSE,
                       _("Rendering Frame %d"), 1);

  orig_image = gimp_item_get_image (GIMP_ITEM (tool->drawable));

  image = gimp_create_image (orig_image->gimp,
                             gimp_item_get_width  (GIMP_ITEM (tool->drawable)),
                             gimp_item_get_height (GIMP_ITEM (tool->drawable)),
                             gimp_drawable_get_base_type (tool->drawable),
                             gimp_drawable_get_precision (tool->drawable),
                             TRUE);

  /*  the first frame is always the unwarped image  */
  layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (tool->drawable), image,
                                         GIMP_TYPE_LAYER));
  gimp_object_take_name (GIMP_OBJECT (layer),
                         g_strdup_printf (_("Frame %d"), 1));

  gimp_item_set_offset (GIMP_ITEM (layer), 0, 0);
  gimp_item_set_visible (GIMP_ITEM (layer), TRUE, FALSE);
  gimp_layer_set_mode (layer, GIMP_NORMAL_MODE, FALSE);
  gimp_layer_set_opacity (layer, GIMP_OPACITY_OPAQUE, FALSE);
  gimp_image_add_layer (image, layer, NULL, 0, FALSE);

  first_layer = layer;

  scale_node = gegl_node_new_child (NULL,
                                    "operation",    "gimp:scalar-multiply",
                                    "n-components", 2,
                                    NULL);
  gimp_warp_tool_add_op (wt, scale_node);

  progress = gimp_sub_progress_new (GIMP_PROGRESS (tool));

  for (i = 1; i < options->n_animation_frames; i++)
    {
      gimp_progress_set_text (GIMP_PROGRESS (tool),
                              _("Rendering Frame %d"), i + 1);

      gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress),
                                  i, options->n_animation_frames);

      layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (first_layer),
                                               GIMP_TYPE_LAYER));
      gimp_object_take_name (GIMP_OBJECT (layer),
                             g_strdup_printf (_("Frame %d"), i + 1));

      gegl_node_set (scale_node,
                     "factor", (gdouble) i /
                               (gdouble) (options->n_animation_frames - 1),
                     NULL);

      gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (first_layer)),
                                 progress,
                                 _("Frame"),
                                 wt->graph,
                                 gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
                                 NULL);

      gimp_image_add_layer (image, layer, NULL, 0, FALSE);
    }

  g_object_unref (progress);

  gimp_warp_tool_remove_op (wt, scale_node);

  gimp_progress_end (GIMP_PROGRESS (tool));

  /*  recreate the image map  */
  gimp_warp_tool_create_image_map (wt, tool->drawable);
  gimp_image_map_apply (wt->image_map, NULL);

  widget = GTK_WIDGET (gimp_display_get_shell (tool->display));
  gimp_create_display (orig_image->gimp, image, GIMP_UNIT_PIXEL, 1.0,
                       G_OBJECT (gtk_widget_get_screen (widget)),
                       gimp_widget_get_monitor (widget));
  g_object_unref (image);
}