Esempio n. 1
0
void
jpeg_exif_rotate_query (gint32 image_ID,
                        gint   orientation)
{
  GimpParasite *parasite;
  gboolean      query = load_interactive;

  if (orientation < 2 || orientation > 8)
    return;

  parasite = gimp_parasite_find (JPEG_EXIF_ROTATE_PARASITE);

  if (parasite)
    {
      if (strncmp (gimp_parasite_data (parasite), "yes",
                   gimp_parasite_data_size (parasite)) == 0)
        {
          query = FALSE;
        }
      else if (strncmp (gimp_parasite_data (parasite), "no",
                        gimp_parasite_data_size (parasite)) == 0)
        {
          gimp_parasite_free (parasite);
          return;
        }

      gimp_parasite_free (parasite);
    }

  if (query && ! jpeg_exif_rotate_query_dialog (image_ID))
    return;

  jpeg_exif_rotate (image_ID, orientation);
}
Esempio n. 2
0
GimpSymmetry *
gimp_symmetry_from_parasite (const GimpParasite *parasite,
                             GimpImage          *image,
                             GType               type)
{
  GimpSymmetry    *symmetry;
  gchar           *parasite_name;
  const gchar     *str;
  GError          *error = NULL;

  parasite_name = gimp_symmetry_parasite_name (type);

  g_return_val_if_fail (parasite != NULL, NULL);
  g_return_val_if_fail (strcmp (gimp_parasite_name (parasite),
                                parasite_name) == 0,
                        NULL);
  g_free (parasite_name);

  str = gimp_parasite_data (parasite);
  g_return_val_if_fail (str != NULL, NULL);

  symmetry = gimp_image_symmetry_new (image, type);

  if (! gimp_config_deserialize_string (GIMP_CONFIG (symmetry),
                                        str,
                                        gimp_parasite_data_size (parasite),
                                        NULL,
                                        &error))
    {
      g_warning ("Failed to deserialize symmetry parasite: %s", error->message);
      g_error_free (error);
    }

  return symmetry;
}
gboolean
gimp_image_validate_icc_parasite (GimpImage           *image,
                                  const GimpParasite  *icc_parasite,
                                  gboolean            *is_builtin,
                                  GError             **error)
{
  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
  g_return_val_if_fail (icc_parasite != NULL, FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (strcmp (gimp_parasite_name (icc_parasite),
              GIMP_ICC_PROFILE_PARASITE_NAME) != 0)
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("ICC profile validation failed: "
                             "Parasite's name is not 'icc-profile'"));
      return FALSE;
    }

  if (gimp_parasite_flags (icc_parasite) != (GIMP_PARASITE_PERSISTENT |
                                             GIMP_PARASITE_UNDOABLE))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("ICC profile validation failed: "
                             "Parasite's flags are not (PERSISTENT | UNDOABLE)"));
      return FALSE;
    }

  return gimp_image_validate_icc_profile (image,
                                          gimp_parasite_data (icc_parasite),
                                          gimp_parasite_data_size (icc_parasite),
                                          is_builtin,
                                          error);
}
Esempio n. 4
0
GimpGrid *
gimp_grid_from_parasite (const GimpParasite *parasite)
{
    GimpGrid    *grid;
    const gchar *str;
    GError      *error = NULL;

    g_return_val_if_fail (parasite != NULL, NULL);
    g_return_val_if_fail (strcmp (gimp_parasite_name (parasite),
                                  gimp_grid_parasite_name ()) == 0, NULL);

    str = gimp_parasite_data (parasite);
    g_return_val_if_fail (str != NULL, NULL);

    grid = g_object_new (GIMP_TYPE_GRID, NULL);

    if (! gimp_config_deserialize_string (GIMP_CONFIG (grid),
                                          str,
                                          gimp_parasite_data_size (parasite),
                                          NULL,
                                          &error))
    {
        g_warning ("Failed to deserialize grid parasite: %s", error->message);
        g_error_free (error);
    }

    return grid;
}
Esempio n. 5
0
gboolean
gimp_image_validate_icc_profile (GimpImage           *image,
                                 const GimpParasite  *icc_profile,
                                 GError             **error)
{
  GimpColorProfile *profile;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
  g_return_val_if_fail (icc_profile != NULL, FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (strcmp (gimp_parasite_name (icc_profile),
              GIMP_ICC_PROFILE_PARASITE_NAME) != 0)
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("ICC profile validation failed: "
                             "Parasite's name is not 'icc-profile'"));
      return FALSE;
    }

  if (gimp_parasite_flags (icc_profile) != (GIMP_PARASITE_PERSISTENT |
                                            GIMP_PARASITE_UNDOABLE))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("ICC profile validation failed: "
                             "Parasite's flags are not (PERSISTENT | UNDOABLE)"));
      return FALSE;
    }

  if (gimp_image_get_base_type (image) == GIMP_GRAY)
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("ICC profile validation failed: "
                             "Cannot attach a color profile to a GRAY image"));
      return FALSE;
    }

  profile = gimp_lcms_profile_open_from_data (gimp_parasite_data (icc_profile),
                                              gimp_parasite_data_size (icc_profile),
                                              error);

  if (! profile)
    {
      g_prefix_error (error, _("ICC profile validation failed: "));
      return FALSE;
    }

  if (! gimp_lcms_profile_is_rgb (profile))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("ICC profile validation failed: "
                             "Color profile is not for RGB color space"));
      cmsCloseProfile (profile);
      return FALSE;
    }

  cmsCloseProfile (profile);

  return TRUE;
}
Esempio n. 6
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam  values[2];
  GimpRunMode       run_mode;
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  GimpExportReturn  export = GIMP_EXPORT_CANCEL;

  run_mode = param[0].data.d_int32;

  *nreturn_vals = 1;
  *return_vals  = values;

  INIT_I18N ();

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;

  if (run_mode == GIMP_RUN_INTERACTIVE &&
      strcmp (name, SAVE_PROC) == 0)
    {
      gint32         image_ID    = param[1].data.d_int32;
      gint32         drawable_ID = param[2].data.d_int32;
      GimpParasite  *parasite;
      gchar         *x;
      GimpImageType  drawable_type = gimp_drawable_type (drawable_ID);

      gimp_get_data (SAVE_PROC, &config);
      config.prefixed_name = "gimp_image";
      config.comment       = NULL;

      config.file_name = param[3].data.d_string;
      config.alpha = (drawable_type == GIMP_RGBA_IMAGE ||
		      drawable_type == GIMP_GRAYA_IMAGE ||
		      drawable_type == GIMP_INDEXEDA_IMAGE);

      parasite = gimp_image_parasite_find (image_ID, "gimp-comment");
      if (parasite)
	{
	  config.comment = g_strndup (gimp_parasite_data (parasite),
                                      gimp_parasite_data_size (parasite));
	  gimp_parasite_free (parasite);
	}
      x = config.comment;

      gimp_ui_init (PLUG_IN_BINARY, FALSE);
      export = gimp_export_image (&image_ID, &drawable_ID, "C Source",
Esempio n. 7
0
static cmsHPROFILE
lcms_image_get_profile (GimpColorConfig *config,
                        gint32           image,
                        guchar          *checksum)
{
  GimpParasite *parasite;
  cmsHPROFILE   profile = NULL;

  g_return_val_if_fail (image != -1, NULL);

  parasite = gimp_image_get_parasite (image, "icc-profile");

  if (parasite)
    {
      profile = cmsOpenProfileFromMem ((gpointer) gimp_parasite_data (parasite),
                                       gimp_parasite_data_size (parasite));

      if (profile)
        {
          lcms_calculate_checksum (gimp_parasite_data (parasite),
                                   gimp_parasite_data_size (parasite),
                                   checksum);
        }
      else
        {
          g_message (_("Data attached as 'icc-profile' does not appear to "
                       "be an ICC color profile"));
        }

      gimp_parasite_free (parasite);
    }
  else if (config->rgb_profile)
    {
      profile = lcms_load_profile (config->rgb_profile, checksum);
    }

  return profile;
}
Esempio n. 8
0
GimpColorProfile *
gimp_image_get_color_profile (GimpImage *image)
{
  const GimpParasite *parasite;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);

  parasite = gimp_image_get_icc_parasite (image);

  if (parasite)
    return gimp_color_profile_new_from_icc_profile (gimp_parasite_data (parasite),
                                                    gimp_parasite_data_size (parasite),
                                                    NULL);

  return NULL;
}
Esempio n. 9
0
File: lcms.c Progetto: K-Sonoda/gimp
static cmsHPROFILE
lcms_image_get_profile (GimpColorConfig  *config,
                        gint32            image,
                        GError          **error)
{
  GimpParasite *parasite;
  cmsHPROFILE   profile = NULL;

  g_return_val_if_fail (image != -1, NULL);

  parasite = gimp_image_get_parasite (image, "icc-profile");

  if (parasite)
    {
      profile = gimp_lcms_profile_open_from_data (gimp_parasite_data (parasite),
                                                  gimp_parasite_data_size (parasite),
                                                  error);
      if (! profile)
        g_prefix_error (error, _("Error parsing 'icc-profile': "));

      gimp_parasite_free (parasite);
    }
  else if (config->rgb_profile)
    {
      GFile *file = g_file_new_for_path (config->rgb_profile);

      profile = gimp_lcms_profile_open_from_file (file, error);

      if (profile && ! gimp_lcms_profile_is_rgb (profile))
        {
          g_set_error (error, 0, 0,
                       _("Color profile '%s' is not for RGB color space"),
                       gimp_file_get_utf8_name (file));
          cmsCloseProfile (profile);
          profile = NULL;
        }

      g_object_unref (file);
    }

  return profile;
}
Esempio n. 10
0
static void
parasite_serialize (const gchar      *key,
                    GimpParasite     *parasite,
                    GimpConfigWriter *writer)
{
  if (! gimp_parasite_is_persistent (parasite))
    return;

  gimp_config_writer_open (writer, parasite_symbol);

  gimp_config_writer_printf (writer, "\"%s\" %lu %lu",
                             gimp_parasite_name (parasite),
                             gimp_parasite_flags (parasite),
                             gimp_parasite_data_size (parasite));

  gimp_config_writer_data (writer,
                           gimp_parasite_data_size (parasite),
                           gimp_parasite_data (parasite));

  gimp_config_writer_close (writer);
  gimp_config_writer_linefeed (writer);
}
const guint8 *
gimp_image_get_icc_profile (GimpImage *image,
                            gsize     *length)
{
  const GimpParasite *parasite;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);

  parasite = gimp_image_parasite_find (image, GIMP_ICC_PROFILE_PARASITE_NAME);

  if (parasite)
    {
      if (length)
        *length = gimp_parasite_data_size (parasite);

      return gimp_parasite_data (parasite);
    }

  if (length)
    *length = 0;

  return NULL;
}
Esempio n. 12
0
GimpColorProfile
gimp_image_get_profile (GimpImage  *image,
                        GError    **error)
{
  GimpColorConfig    *config;
  const GimpParasite *parasite;
  GimpColorProfile   *profile = NULL;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  config = image->gimp->config->color_management;

  parasite = gimp_image_get_icc_profile (image);

  if (parasite)
    {
      return gimp_lcms_profile_open_from_data (gimp_parasite_data (parasite),
                                               gimp_parasite_data_size (parasite),
                                               error);
    }
  else if (config->rgb_profile)
    {
      profile = gimp_lcms_profile_open_from_file (config->rgb_profile, error);

      if (profile && ! gimp_lcms_profile_is_rgb (profile))
        {
          g_set_error (error, GIMP_ERROR, GIMP_FAILED,
                       _("Color profile '%s' is not for RGB color space"),
                       gimp_filename_to_utf8 (config->rgb_profile));
          cmsCloseProfile (profile);
          profile = NULL;
        }
    }

  return profile;
}
Esempio n. 13
0
void
load_defaults (void)
{
  GimpParasite *parasite;
  gchar        *def_str;
  JpegSaveVals  tmpvals;
  gint          num_fields;
  gint          subsampling;

  jsvals.quality          = DEFAULT_QUALITY;
  jsvals.smoothing        = DEFAULT_SMOOTHING;
  jsvals.optimize         = DEFAULT_OPTIMIZE;
  jsvals.arithmetic_coding= DEFAULT_ARITHMETIC_CODING;
  jsvals.progressive      = DEFAULT_PROGRESSIVE;
  jsvals.baseline         = DEFAULT_BASELINE;
  jsvals.subsmp           = DEFAULT_SUBSMP;
  jsvals.restart          = DEFAULT_RESTART;
  jsvals.dct              = DEFAULT_DCT;
  jsvals.preview          = DEFAULT_PREVIEW;
  jsvals.save_exif        = DEFAULT_EXIF;
  jsvals.save_thumbnail   = DEFAULT_THUMBNAIL;
  jsvals.save_xmp         = DEFAULT_XMP;
  jsvals.save_iptc        = DEFAULT_IPTC;
  jsvals.use_orig_quality = DEFAULT_USE_ORIG_QUALITY;

  parasite = gimp_get_parasite (JPEG_DEFAULTS_PARASITE);

  if (! parasite)
    return;

  def_str = g_strndup (gimp_parasite_data (parasite),
                       gimp_parasite_data_size (parasite));

  gimp_parasite_free (parasite);

  num_fields = sscanf (def_str,
                       "%lf %lf %d %d %d %d %d %d %d %d %d %d %d %d %d",
                       &tmpvals.quality,
                       &tmpvals.smoothing,
                       &tmpvals.optimize,
                       &tmpvals.progressive,
                       &subsampling,
                       &tmpvals.baseline,
                       &tmpvals.restart,
                       &tmpvals.dct,
                       &tmpvals.preview,
                       &tmpvals.save_exif,
                       &tmpvals.save_thumbnail,
                       &tmpvals.save_xmp,
                       &tmpvals.use_orig_quality,
                       &tmpvals.save_iptc,
                       &tmpvals.arithmetic_coding);

  tmpvals.subsmp = subsampling;

  if (num_fields == 13 || num_fields == 14)
    {
      memcpy (&jsvals, &tmpvals, sizeof (tmpvals));
    }

  g_free (def_str);
}
Esempio n. 14
0
static void
draw_info_header (GtkPrintContext *context,
                  cairo_t         *cr,
                  PrintData       *data)
{
  PangoLayout          *layout;
  PangoFontDescription *desc;
  gdouble               text_height;
  gdouble               text_width;
  gdouble               fname_text_width;
  gint                  layout_height;
  gint                  layout_width;
  gchar                 date_buffer[100];
  GDate                *date;
  const gchar          *name_str;
  GimpParasite         *parasite;
  const gchar          *end_ptr;
  gchar                *filename;
  gdouble               cr_width;

  cairo_save (cr);

  cr_width  = gtk_print_context_get_width (context);
  cairo_rectangle (cr, 0, 0, cr_width, HEADER_HEIGHT);
  cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
  cairo_fill_preserve (cr);

  cairo_set_source_rgb (cr, 0, 0, 0);
  cairo_set_line_width (cr, 1);
  cairo_stroke (cr);

  layout = gtk_print_context_create_pango_layout (context);

  desc = pango_font_description_from_string ("sans 14");
  pango_layout_set_font_description (layout, desc);
  pango_font_description_free (desc);

  pango_layout_set_width (layout, -1);
  pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);

  /* image name */
  pango_layout_set_text (layout, gimp_image_get_name (data->image_id), -1);

  pango_layout_get_size (layout, &layout_width, &layout_height);
  text_height = (gdouble) layout_height / PANGO_SCALE;

  cairo_move_to (cr, 0.02 * cr_width,  (HEADER_HEIGHT - text_height) / 5);
  pango_cairo_show_layout (cr, layout);

  /* user name */
  name_str = g_get_real_name ();
  if (name_str && g_utf8_validate (name_str, -1, &end_ptr))
    {
      pango_layout_set_text (layout, name_str, -1);

      pango_layout_get_size (layout, &layout_width, &layout_height);
      text_height = (gdouble) layout_height / PANGO_SCALE;
      text_width = (gdouble) layout_width / PANGO_SCALE;

      cairo_move_to (cr, 0.5 * cr_width - 0.5 * text_width,
                     (HEADER_HEIGHT - text_height) / 5);
      pango_cairo_show_layout (cr, layout);
    }

  /* date */
  date = g_date_new ();
  g_date_set_time_t (date, time (NULL));
  g_date_strftime (date_buffer, 100, "%x", date);
  g_date_free (date);
  pango_layout_set_text (layout, date_buffer, -1);

  pango_layout_get_size (layout, &layout_width, &layout_height);
  text_height = (gdouble) layout_height / PANGO_SCALE;
  text_width = (gdouble) layout_width / PANGO_SCALE;

  cairo_move_to (cr,
                 0.98 * cr_width - text_width,
                 (HEADER_HEIGHT - text_height) / 5);
  pango_cairo_show_layout (cr, layout);

  /* file name if any */
  filename = gimp_image_get_filename (data->image_id);

  if (filename)
    {
      pango_layout_set_text (layout,
                             gimp_filename_to_utf8 (filename), -1);
      g_free (filename);

      pango_layout_get_size (layout, &layout_width, &layout_height);
      text_height = (gdouble) layout_height / PANGO_SCALE;
      fname_text_width = (gdouble) layout_width / PANGO_SCALE;

      cairo_move_to (cr,
                     0.02 * cr_width,  4 * (HEADER_HEIGHT - text_height) / 5);
      pango_cairo_show_layout (cr, layout);
    }
  else
    {
      fname_text_width = 0;
    }

  /* image comment if it is short */
  parasite = gimp_image_parasite_find (data->image_id, "gimp-comment");

  if (parasite)
    {
      pango_layout_set_text (layout, gimp_parasite_data (parasite), -1);

      pango_layout_get_size (layout, &layout_width, &layout_height);
      text_height = (gdouble) layout_height / PANGO_SCALE;
      text_width = (gdouble) layout_width / PANGO_SCALE;

      if (fname_text_width + text_width < 0.8 * cr_width &&
          text_height < 0.5 * HEADER_HEIGHT)
        {
          cairo_move_to (cr, 0.98 * cr_width - text_width,
                         4 * (HEADER_HEIGHT - text_height) / 5);
          pango_cairo_show_layout (cr, layout);
        }

      gimp_parasite_free (parasite);
    }

  g_object_unref (layout);

  cairo_restore (cr);
}
Esempio n. 15
0
/**
 * jpeg_restore_original_settings:
 * @image_ID: the image that may contain original jpeg settings in a parasite.
 * @quality: where to store the original jpeg quality.
 * @subsmp: where to store the original subsampling type.
 * @num_quant_tables: where to store the number of quantization tables found.
 *
 * Retrieve the original JPEG settings (quality, type of subsampling
 * and number of quantization tables) from the parasite attached to
 * @image_ID.  If the number of quantization tables is greater than
 * zero, then these tables can be retrieved from the parasite by
 * calling jpeg_restore_original_tables().
 *
 * Return Value: TRUE if a valid parasite was attached to the image
 */
gboolean
jpeg_restore_original_settings (gint32  image_ID,
                                gint   *quality,
                                gint   *subsmp,
                                gint   *num_quant_tables)
{
  GimpParasite *parasite;
  const guchar *src;
  glong         src_size;
  gint          color_space;
  gint          q;
  gint          num_components;
  gint          num_tables;
  guchar        h[3];
  guchar        v[3];

  g_return_val_if_fail (quality != NULL, FALSE);
  g_return_val_if_fail (subsmp != NULL, FALSE);
  g_return_val_if_fail (num_quant_tables != NULL, FALSE);

  parasite = gimp_image_parasite_find (image_ID, "jpeg-settings");
  if (parasite)
    {
      src = gimp_parasite_data (parasite);
      src_size = gimp_parasite_data_size (parasite);
      if (src_size >= 4)
        {
          color_space      = *src++;
          q                = *src++;
          num_components   = *src++;
          num_tables       = *src++;

          if (src_size >= (4 + num_components * 2 + num_tables * 128)
              && q <= 100 && num_tables <= 4)
            {
              *quality = q;

              /* the current plug-in can only create grayscale or YCbCr JPEGs */
              if (color_space == JCS_GRAYSCALE || color_space == JCS_YCbCr)
                *num_quant_tables = num_tables;
              else
                *num_quant_tables = -1;

              /* the current plug-in can only use subsampling for YCbCr (3) */
              *subsmp = -1;
              if (num_components == 3)
                {
                  h[0] = *src++;
                  v[0] = *src++;
                  h[1] = *src++;
                  v[1] = *src++;
                  h[2] = *src++;
                  v[2] = *src++;

                  if (h[1] == 1 && v[1] == 1 && h[2] == 1 && v[2] == 1)
                    {
                      if (h[0] == 1 && v[0] == 1)
                        *subsmp = 2;
                      else if (h[0] == 2 && v[0] == 1)
                        *subsmp = 1;
                      else if (h[0] == 1 && v[0] == 2)
                        *subsmp = 3;
                      else if (h[0] == 2 && v[0] == 2)
                        *subsmp = 0;
                    }
                }
              gimp_parasite_free (parasite);
              return TRUE;
            }
        }
      gimp_parasite_free (parasite);
    }
  *quality = -1;
  *subsmp = -1;
  *num_quant_tables = 0;
  return FALSE;
}
Esempio n. 16
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam   values[4];
  gint32             image_ID;
  XMPModel          *xmp_model;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  GimpParasite      *parasite = NULL;

  *nreturn_vals = 1;
  *return_vals  = values;

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;

  INIT_I18N();

  if (! strcmp (name, EDITOR_PROC))
    image_ID = param[1].data.d_image;
  else
    image_ID = param[0].data.d_image;

  xmp_model = xmp_model_new ();

  /* if there is already a metadata parasite, load it */
  parasite = gimp_image_get_parasite (image_ID, METADATA_PARASITE);
  if (parasite)
    {
      GError *error = NULL;

      if (!! strncmp (gimp_parasite_data (parasite),
                      METADATA_MARKER, METADATA_MARKER_LEN)
          || ! xmp_model_parse_buffer (xmp_model,
                                       (const gchar *) gimp_parasite_data (parasite)
                                       + METADATA_MARKER_LEN,
                                       gimp_parasite_data_size (parasite)
                                       - METADATA_MARKER_LEN,
                                       TRUE, &error))
        {
          g_printerr ("\nMetadata parasite seems to be corrupt\n");
          /* continue anyway, we will attach a clean parasite later */
        }
      gimp_parasite_free (parasite);
    }

  /* If we have no metadata yet, try to find an XMP packet in the file
   * (but ignore errors if nothing is found).
   *
   * FIXME: This is a workaround until all file plug-ins do the right
   * thing when loading their files.
   */
  if (xmp_model_is_empty (xmp_model)
      && !! strcmp (name, DECODE_XMP_PROC))
    {
      const gchar *filename;
      GError      *error = NULL;

      filename = gimp_image_get_filename (image_ID);
      if (filename != NULL)
        if (xmp_model_parse_file (xmp_model, filename, &error))
          /* g_message ("XMP loaded from file '%s'\n", filename) */;
    }

  /* Now check what we are supposed to do */
  if (! strcmp (name, DECODE_XMP_PROC))
    {
      const gchar *buffer;
      GError      *error = NULL;

      buffer = param[1].data.d_string;
      if (! xmp_model_parse_buffer (xmp_model, buffer, strlen (buffer),
                                    FALSE, &error))
        status = GIMP_PDB_EXECUTION_ERROR;

    }
  else if (! strcmp (name, ENCODE_XMP_PROC))
    {
      /* done below together with the parasite */
    }
  else if (! strcmp (name, DECODE_EXIF_PROC))
    {
        GError      *error         = NULL;

        if (! xmp_merge_from_exifbuffer (xmp_model, image_ID, &error))
          {
            status = GIMP_PDB_EXECUTION_ERROR;
            g_printerr ("\nExif to XMP merge failed.\n");
          }
    }
  else if (! strcmp (name, GET_PROC))
    {
      g_printerr ("Not implemented yet (GET_PROC)\n"); /* FIXME */
      status = GIMP_PDB_EXECUTION_ERROR;
    }
  else if (! strcmp (name, SET_PROC))
    {
      g_printerr ("Not implemented yet (SET_PROC)\n"); /* FIXME */
      status = GIMP_PDB_EXECUTION_ERROR;
    }
  else if (! strcmp (name, GET_SIMPLE_PROC))
    {
      const gchar *schema_name;
      const gchar *property_name;
      const gchar *value;

      schema_name = param[1].data.d_string;
      property_name = param[2].data.d_string;
      value = xmp_model_get_scalar_property (xmp_model, schema_name,
                                             property_name);
      if (value)
        {
          *nreturn_vals = 2;
          values[1].type = GIMP_PDB_STRING;
          values[1].data.d_string = g_strdup (value);
        }
      else
        status = GIMP_PDB_EXECUTION_ERROR;
    }
  else if (! strcmp (name, SET_SIMPLE_PROC))
    {
      const gchar *schema_name;
      const gchar *property_name;
      const gchar *property_value;

      schema_name = param[1].data.d_string;
      property_name = param[2].data.d_string;
      property_value = param[3].data.d_string;
      if (! xmp_model_set_scalar_property (xmp_model, schema_name,
                                           property_name, property_value))
        status = GIMP_PDB_EXECUTION_ERROR;
    }
  else if (! strcmp (name, IMPORT_PROC))
    {
      const gchar *filename;
      gchar       *buffer;
      gsize        buffer_length;
      GError      *error = NULL;

      filename = param[1].data.d_string;
      if (! g_file_get_contents (filename, &buffer, &buffer_length, &error))
        {
          g_error_free (error);
          status = GIMP_PDB_EXECUTION_ERROR;
        }
      else if (! xmp_model_parse_buffer (xmp_model, buffer, buffer_length,
                                         TRUE, &error))
        {
          g_error_free (error);
          status = GIMP_PDB_EXECUTION_ERROR;
        }
      g_free (buffer);
    }
  else if (! strcmp (name, EXPORT_PROC))
    {
      /* FIXME: this is easy to implement, but the first thing to do is */
      /* to improve the code of export_dialog_response() in interface.c */
      g_printerr ("Not implemented yet (EXPORT_PROC)\n");
      status = GIMP_PDB_EXECUTION_ERROR;
    }
  else if (! strcmp (name, EDITOR_PROC))
    {
      GimpRunMode run_mode;

      run_mode = param[0].data.d_int32;
      if (run_mode == GIMP_RUN_INTERACTIVE)
        {
          if (! metadata_dialog (image_ID, xmp_model))
            status = GIMP_PDB_CANCEL;
        }

      g_printerr ("Not implemented yet (EDITOR_PROC)\n");
      status = GIMP_PDB_EXECUTION_ERROR;
    }
  else
    {
      status = GIMP_PDB_CALLING_ERROR;
    }

  if (status == GIMP_PDB_SUCCESS)
    {
      GString *buffer;

      /* Generate the updated parasite and attach it to the image */
      buffer = g_string_new (METADATA_MARKER);
      xmp_generate_packet (xmp_model, buffer);
      parasite = gimp_parasite_new (METADATA_PARASITE,
                                    GIMP_PARASITE_PERSISTENT,
                                    buffer->len,
                                    (gpointer) buffer->str);
      gimp_image_attach_parasite (image_ID, parasite);
      if (! strcmp (name, ENCODE_XMP_PROC))
        {
          *nreturn_vals = 2;
          values[1].type = GIMP_PDB_STRING;
          values[1].data.d_string = g_strdup (buffer->str
                                              + METADATA_MARKER_LEN);
        }
      g_string_free (buffer, TRUE);
    }

  g_object_unref (xmp_model);

  values[0].data.d_status = status;
}
Esempio n. 17
0
GimpSymmetry *
gimp_symmetry_from_parasite (const GimpParasite *parasite,
                             GimpImage          *image,
                             GType               type)
{
  GimpSymmetry    *symmetry;
  gchar           *parasite_name;
  const gchar     *str;
  GError          *error = NULL;

  parasite_name = gimp_symmetry_parasite_name (type);

  g_return_val_if_fail (parasite != NULL, NULL);
  g_return_val_if_fail (strcmp (gimp_parasite_name (parasite),
                                parasite_name) == 0,
                        NULL);

  str = gimp_parasite_data (parasite);

  if (! str)
    {
      g_warning ("Empty symmetry parasite \"%s\"", parasite_name);

      return NULL;
    }

  symmetry = gimp_image_symmetry_new (image, type);

  g_object_set (symmetry,
                "version", -1,
                NULL);

  if (! gimp_config_deserialize_string (GIMP_CONFIG (symmetry),
                                        str,
                                        gimp_parasite_data_size (parasite),
                                        NULL,
                                        &error))
    {
      g_printerr ("Failed to deserialize symmetry parasite: %s\n"
                  "\t- parasite name: %s\n\t- parasite data: %s\n",
                  error->message, parasite_name, str);
      g_error_free (error);

      g_object_unref (symmetry);
      symmetry = NULL;
    }
  g_free (parasite_name);

  if (symmetry)
    {
      gint version;

      g_object_get (symmetry,
                    "version", &version,
                    NULL);
      if (version == -1)
        {
          /* If version has not been updated, let's assume this parasite was
           * not representing symmetry settings.
           */
          g_object_unref (symmetry);
          symmetry = NULL;
        }
      else if (GIMP_SYMMETRY_GET_CLASS (symmetry)->update_version (symmetry) &&
               ! GIMP_SYMMETRY_GET_CLASS (symmetry)->update_version (symmetry))
        {
          g_object_unref (symmetry);
          symmetry = NULL;
        }
    }

  return symmetry;
}
Esempio n. 18
0
gboolean
save_image (const gchar  *filename,
            gint32        image_ID,
            gint32        drawable_ID,
            gint32        orig_image_ID,
            gboolean      preview,
            GError      **error)
{
  GimpImageType  drawable_type;
  GeglBuffer    *buffer = NULL;
  const Babl    *format;
  GimpParasite  *parasite;
  static struct jpeg_compress_struct cinfo;
  static struct my_error_mgr         jerr;
  JpegSubsampling             subsampling;
  FILE     * volatile outfile;
  guchar   *data;
  guchar   *src;
  gboolean  has_alpha;
  gint      rowstride, yend;

  drawable_type = gimp_drawable_type (drawable_ID);
  buffer = gimp_drawable_get_buffer (drawable_ID);

  if (! preview)
    gimp_progress_init_printf (_("Saving '%s'"),
                               gimp_filename_to_utf8 (filename));

  /* Step 1: allocate and initialize JPEG compression object */

  /* We have to set up the error handler first, in case the initialization
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
   * This routine fills in the contents of struct jerr, and returns jerr's
   * address which we place into the link field in cinfo.
   */
  cinfo.err = jpeg_std_error (&jerr.pub);
  jerr.pub.error_exit = my_error_exit;

  outfile = NULL;
  /* Establish the setjmp return context for my_error_exit to use. */
  if (setjmp (jerr.setjmp_buffer))
    {
      /* If we get here, the JPEG code has signaled an error.
       * We need to clean up the JPEG object, close the input file, and return.
       */
      jpeg_destroy_compress (&cinfo);
      if (outfile)
        fclose (outfile);
      if (buffer)
        g_object_unref (buffer);

      return FALSE;
    }

  /* Now we can initialize the JPEG compression object. */
  jpeg_create_compress (&cinfo);

  /* Step 2: specify data destination (eg, a file) */
  /* Note: steps 2 and 3 can be done in either order. */

  /* Here we use the library-supplied code to send compressed data to a
   * stdio stream.  You can also write your own code to do something else.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to write binary files.
   */
  if ((outfile = g_fopen (filename, "wb")) == NULL)
    {
      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
                   _("Could not open '%s' for writing: %s"),
                   gimp_filename_to_utf8 (filename), g_strerror (errno));
      return FALSE;
    }

  jpeg_stdio_dest (&cinfo, outfile);

  /* Get the input image and a pointer to its data.
   */
  switch (drawable_type)
    {
    case GIMP_RGB_IMAGE:
      /* # of color components per pixel */
      cinfo.input_components = 3;
      has_alpha = FALSE;
      format = babl_format ("R'G'B' u8");
      break;

    case GIMP_GRAY_IMAGE:
      /* # of color components per pixel */
      cinfo.input_components = 1;
      has_alpha = FALSE;
      format = babl_format ("Y' u8");
      break;

    case GIMP_RGBA_IMAGE:
      /* # of color components per pixel (minus the GIMP alpha channel) */
      cinfo.input_components = 4 - 1;
      has_alpha = TRUE;
      format = babl_format ("R'G'B' u8");
      break;

    case GIMP_GRAYA_IMAGE:
      /* # of color components per pixel (minus the GIMP alpha channel) */
      cinfo.input_components = 2 - 1;
      has_alpha = TRUE;
      format = babl_format ("Y' u8");
      break;

    case GIMP_INDEXED_IMAGE:
    default:
      return FALSE;
    }

  /* Step 3: set parameters for compression */

  /* First we supply a description of the input image.
   * Four fields of the cinfo struct must be filled in:
   */
  /* image width and height, in pixels */
  cinfo.image_width  = gegl_buffer_get_width (buffer);
  cinfo.image_height = gegl_buffer_get_height (buffer);
  /* colorspace of input image */
  cinfo.in_color_space = (drawable_type == GIMP_RGB_IMAGE ||
                          drawable_type == GIMP_RGBA_IMAGE)
    ? JCS_RGB : JCS_GRAYSCALE;
  /* Now use the library's routine to set default compression parameters.
   * (You must set at least cinfo.in_color_space before calling this,
   * since the defaults depend on the source color space.)
   */
  jpeg_set_defaults (&cinfo);

  jpeg_set_quality (&cinfo, (gint) (jsvals.quality + 0.5), jsvals.baseline);

  if (jsvals.use_orig_quality && num_quant_tables > 0)
    {
      guint **quant_tables;
      gint    t;

      /* override tables generated by jpeg_set_quality() with custom tables */
      quant_tables = jpeg_restore_original_tables (image_ID, num_quant_tables);
      if (quant_tables)
        {
          for (t = 0; t < num_quant_tables; t++)
            {
              jpeg_add_quant_table (&cinfo, t, quant_tables[t],
                                    100, jsvals.baseline);
              g_free (quant_tables[t]);
            }
          g_free (quant_tables);
        }
    }

  if (arithc_supported)
    {
      cinfo.arith_code = jsvals.arithmetic_coding;
      if (!jsvals.arithmetic_coding)
        cinfo.optimize_coding = jsvals.optimize;
    }
  else
    cinfo.optimize_coding = jsvals.optimize;

  subsampling = (gimp_drawable_is_rgb (drawable_ID) ?
                 jsvals.subsmp : JPEG_SUBSAMPLING_1x1_1x1_1x1);

  /*  smoothing is not supported with nonstandard sampling ratios  */
  if (subsampling != JPEG_SUBSAMPLING_2x1_1x1_1x1 &&
      subsampling != JPEG_SUBSAMPLING_1x2_1x1_1x1)
    {
      cinfo.smoothing_factor = (gint) (jsvals.smoothing * 100);
    }

  if (jsvals.progressive)
    {
      jpeg_simple_progression (&cinfo);
    }

  switch (subsampling)
    {
    case JPEG_SUBSAMPLING_2x2_1x1_1x1:
    default:
      cinfo.comp_info[0].h_samp_factor = 2;
      cinfo.comp_info[0].v_samp_factor = 2;
      cinfo.comp_info[1].h_samp_factor = 1;
      cinfo.comp_info[1].v_samp_factor = 1;
      cinfo.comp_info[2].h_samp_factor = 1;
      cinfo.comp_info[2].v_samp_factor = 1;
      break;

    case JPEG_SUBSAMPLING_2x1_1x1_1x1:
      cinfo.comp_info[0].h_samp_factor = 2;
      cinfo.comp_info[0].v_samp_factor = 1;
      cinfo.comp_info[1].h_samp_factor = 1;
      cinfo.comp_info[1].v_samp_factor = 1;
      cinfo.comp_info[2].h_samp_factor = 1;
      cinfo.comp_info[2].v_samp_factor = 1;
      break;

    case JPEG_SUBSAMPLING_1x1_1x1_1x1:
      cinfo.comp_info[0].h_samp_factor = 1;
      cinfo.comp_info[0].v_samp_factor = 1;
      cinfo.comp_info[1].h_samp_factor = 1;
      cinfo.comp_info[1].v_samp_factor = 1;
      cinfo.comp_info[2].h_samp_factor = 1;
      cinfo.comp_info[2].v_samp_factor = 1;
      break;

    case JPEG_SUBSAMPLING_1x2_1x1_1x1:
      cinfo.comp_info[0].h_samp_factor = 1;
      cinfo.comp_info[0].v_samp_factor = 2;
      cinfo.comp_info[1].h_samp_factor = 1;
      cinfo.comp_info[1].v_samp_factor = 1;
      cinfo.comp_info[2].h_samp_factor = 1;
      cinfo.comp_info[2].v_samp_factor = 1;
      break;
    }

  cinfo.restart_interval = 0;
  cinfo.restart_in_rows = jsvals.restart;

  switch (jsvals.dct)
    {
    case 0:
    default:
      cinfo.dct_method = JDCT_ISLOW;
      break;

    case 1:
      cinfo.dct_method = JDCT_IFAST;
      break;

    case 2:
      cinfo.dct_method = JDCT_FLOAT;
      break;
    }

  {
    gdouble xresolution;
    gdouble yresolution;

    gimp_image_get_resolution (orig_image_ID, &xresolution, &yresolution);

    if (xresolution > 1e-5 && yresolution > 1e-5)
      {
        gdouble factor;

        factor = gimp_unit_get_factor (gimp_image_get_unit (orig_image_ID));

        if (factor == 2.54 /* cm */ ||
            factor == 25.4 /* mm */)
          {
            cinfo.density_unit = 2;  /* dots per cm */

            xresolution /= 2.54;
            yresolution /= 2.54;
          }
        else
          {
            cinfo.density_unit = 1;  /* dots per inch */
          }

        cinfo.X_density = xresolution;
        cinfo.Y_density = yresolution;
      }
  }

  /* Step 4: Start compressor */

  /* TRUE ensures that we will write a complete interchange-JPEG file.
   * Pass TRUE unless you are very sure of what you're doing.
   */
  jpeg_start_compress (&cinfo, TRUE);

  /* Step 4.1: Write the comment out - pw */
  if (image_comment && *image_comment)
    {
#ifdef GIMP_UNSTABLE
      g_print ("jpeg-save: saving image comment (%d bytes)\n",
               (int) strlen (image_comment));
#endif
      jpeg_write_marker (&cinfo, JPEG_COM,
                         (guchar *) image_comment, strlen (image_comment));
    }

  /* Step 4.2: store the color profile if there is one */
  parasite = gimp_image_get_parasite (orig_image_ID, "icc-profile");
  if (parasite)
    {
      jpeg_icc_write_profile (&cinfo,
                              gimp_parasite_data (parasite),
                              gimp_parasite_data_size (parasite));
      gimp_parasite_free (parasite);
    }

  /* Step 5: while (scan lines remain to be written) */
  /*           jpeg_write_scanlines(...); */

  /* Here we use the library's state variable cinfo.next_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * To keep things simple, we pass one scanline per call; you can pass
   * more if you wish, though.
   */
  /* JSAMPLEs per row in image_buffer */
  rowstride = cinfo.input_components * cinfo.image_width;
  data = g_new (guchar, rowstride * gimp_tile_height ());

  /* fault if cinfo.next_scanline isn't initially a multiple of
   * gimp_tile_height */
  src = NULL;

  /*
   * sg - if we preview, we want this to happen in the background -- do
   * not duplicate code in the future; for now, it's OK
   */

  if (preview)
    {
      PreviewPersistent *pp = g_new (PreviewPersistent, 1);

      /* pass all the information we need */
      pp->cinfo       = cinfo;
      pp->tile_height = gimp_tile_height();
      pp->data        = data;
      pp->outfile     = outfile;
      pp->has_alpha   = has_alpha;
      pp->rowstride   = rowstride;
      pp->data        = data;
      pp->buffer      = buffer;
      pp->format      = format;
      pp->src         = NULL;
      pp->file_name   = filename;
      pp->abort_me    = FALSE;

      g_warn_if_fail (prev_p == NULL);
      prev_p = pp;

      pp->cinfo.err = jpeg_std_error(&(pp->jerr));
      pp->jerr.error_exit = background_error_exit;

      gtk_label_set_text (GTK_LABEL (preview_size),
                          _("Calculating file size..."));

      pp->source_id = g_idle_add ((GSourceFunc) background_jpeg_save, pp);

      /* background_jpeg_save() will cleanup as needed */
      return TRUE;
    }

  while (cinfo.next_scanline < cinfo.image_height)
    {
      if ((cinfo.next_scanline % gimp_tile_height ()) == 0)
        {
          yend = cinfo.next_scanline + gimp_tile_height ();
          yend = MIN (yend, cinfo.image_height);
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (0, cinfo.next_scanline,
                                           cinfo.image_width,
                                           (yend - cinfo.next_scanline)),
                           1.0,
                           format,
                           data,
                           GEGL_AUTO_ROWSTRIDE,
                           GEGL_ABYSS_NONE);
          src = data;
        }

      jpeg_write_scanlines (&cinfo, (JSAMPARRAY) &src, 1);
      src += rowstride;

      if ((cinfo.next_scanline % 32) == 0)
        gimp_progress_update ((gdouble) cinfo.next_scanline /
                              (gdouble) cinfo.image_height);
    }

  /* Step 6: Finish compression */
  jpeg_finish_compress (&cinfo);
  /* After finish_compress, we can close the output file. */
  fclose (outfile);

  /* Step 7: release JPEG compression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_compress (&cinfo);

  /* free the temporary buffer */
  g_free (data);

  /* And we're done! */
  gimp_progress_update (1.0);

  g_object_unref (buffer);

  return TRUE;
}
Esempio n. 19
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam   values[2];
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  gint32             image_ID;
  gint32             drawable_ID;
  GimpExportReturn   export = GIMP_EXPORT_CANCEL;
  GError            *error  = NULL;

  INIT_I18N ();
  gegl_init (NULL, NULL);

  run_mode = param[0].data.d_int32;

  *nreturn_vals = 1;
  *return_vals  = values;

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;

  if (strcmp (name, LOAD_PROC) == 0)
    {
      image_ID = load_image (g_file_new_for_uri (param[1].data.d_string),
                             &error);

      if (image_ID != -1)
        {
          *nreturn_vals = 2;
          values[1].type         = GIMP_PDB_IMAGE;
          values[1].data.d_image = image_ID;
        }
      else
        {
          status = GIMP_PDB_EXECUTION_ERROR;
        }
    }
  else if (strcmp (name, SAVE_PROC) == 0)
    {
      GFile        *file;
      GimpParasite *parasite;
      gint32        orig_image_ID;

      image_ID    = param[1].data.d_int32;
      drawable_ID = param[2].data.d_int32;
      file        = g_file_new_for_uri (param[3].data.d_string);

      orig_image_ID = image_ID;

      switch (run_mode)
        {
        case GIMP_RUN_INTERACTIVE:
        case GIMP_RUN_WITH_LAST_VALS:
          gimp_ui_init (PLUG_IN_BINARY, FALSE);

          export = gimp_export_image (&image_ID, &drawable_ID, "PAT",
                                      GIMP_EXPORT_CAN_HANDLE_GRAY    |
                                      GIMP_EXPORT_CAN_HANDLE_RGB     |
                                      GIMP_EXPORT_CAN_HANDLE_INDEXED |
                                      GIMP_EXPORT_CAN_HANDLE_ALPHA);

          if (export == GIMP_EXPORT_CANCEL)
            {
              values[0].data.d_status = GIMP_PDB_CANCEL;
              return;
            }

          /*  Possibly retrieve data  */
          gimp_get_data (SAVE_PROC, description);

          parasite = gimp_image_get_parasite (orig_image_ID,
                                              "gimp-pattern-name");
          if (parasite)
            {
              strncpy (description,
                       gimp_parasite_data (parasite),
                       MIN (sizeof (description),
                            gimp_parasite_data_size (parasite)));
              description[sizeof (description) - 1] = '\0';

              gimp_parasite_free (parasite);
            }
          else
            {
              gchar *name = g_path_get_basename (gimp_file_get_utf8_name (file));

              if (g_str_has_suffix (name, ".pat"))
                name[strlen (name) - 4] = '\0';

              if (strlen (name))
                {
                  strncpy (description, name, sizeof (description));
                  description[sizeof (description) - 1] = '\0';
                }

              g_free (name);
            }
          break;

        default:
          break;
        }