Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  file-icns-export.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
 *
 * file-icns-export.c
 * Copyright (C) 2004 Brion Vibber <brion@pobox.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "config.h"

#include <errno.h>
#include <string.h>

#include <glib/gstdio.h>

#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>

#include "file-icns.h"
#include "file-icns-data.h"
#include "file-icns-load.h"
#include "file-icns-export.h"

#include "libgimp/stdplugins-intl.h"

GtkWidget *        icns_dialog_new       (IcnsSaveInfo         *info,
                                          GimpImage            *image,
                                          GimpProcedure        *procedure,
                                          GimpProcedureConfig  *config);

static gboolean    icns_save_dialog      (IcnsSaveInfo         *info,
                                          GimpImage            *image,
                                          GimpProcedure        *procedure,
                                          GimpProcedureConfig  *config);

void               icns_dialog_add_icon  (GtkWidget            *dialog,
                                          GimpDrawable         *layer,
                                          gint                  layer_num,
                                          gint                  duplicates[]);

static GtkWidget * icns_preview_new      (GimpDrawable         *layer);

static GtkWidget * icns_create_icon_item (GtkWidget            *icon_preview,
                                          GimpDrawable         *layer,
                                          gint                  layer_num,
                                          IcnsSaveInfo         *info,
                                          gint                  duplicates[]);

static gint        icns_find_type        (gint                  width,
                                          gint                  height);
static gboolean    icns_check_dimensions (gint                  width,
                                          gint                  height);
static gboolean    icns_check_compat     (GtkWidget            *dialog,
                                          IcnsSaveInfo         *info);

GimpPDBStatusType  icns_export_image     (GFile                *file,
                                          IcnsSaveInfo         *info,
                                          GimpImage            *image,
                                          gboolean              include_color_profile,
                                          GError              **error);

static guchar    * icns_compress         (guint                 width,
                                          guint                 height,
                                          guchar               *rgba,
                                          gint                 *out_size);

static void        icns_save_info_free   (IcnsSaveInfo *info);

/* Referenced from plug-ins/file-ico/ico-dialog.c */
void
icns_dialog_add_icon (GtkWidget    *dialog,
                      GimpDrawable *layer,
                      gint          layer_num,
                      gint          duplicates[])
{
  GtkWidget    *flowbox;
  GtkWidget    *vbox_item;
  GtkWidget    *preview;
  gchar         key[ICNS_MAXBUF];
  IcnsSaveInfo *info;

  flowbox = g_object_get_data (G_OBJECT (dialog), "icons_flowbox");
  info    = g_object_get_data (G_OBJECT (dialog), "save_info");

  preview   = icns_preview_new (layer);
  vbox_item = icns_create_icon_item (preview, layer, layer_num, info,
                                     duplicates);
  gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), vbox_item, -1);
  gtk_widget_show (vbox_item);

  /* Let's make the vbox_item accessible through the layer ID */
  g_snprintf (key, sizeof (key), "layer_%i_hbox",
              gimp_item_get_id (GIMP_ITEM (layer)));
  g_object_set_data (G_OBJECT (dialog), key, vbox_item);

  icns_check_compat (dialog, info);
}

static GtkWidget *
icns_preview_new (GimpDrawable *layer)
{
  GtkWidget *image;
  GdkPixbuf *pixbuf;
  gint       width  = gimp_drawable_get_width (layer);
  gint       height = gimp_drawable_get_height (layer);

  pixbuf = gimp_drawable_get_thumbnail (layer,
                                        MIN (width, 128), MIN (height, 128),
                                        GIMP_PIXBUF_SMALL_CHECKS);
  image = gtk_image_new_from_pixbuf (pixbuf);

  g_object_unref (pixbuf);

  return image;
}

static gint
icns_find_type (gint width,
                gint height)
{
  gint match = -1;

  for (gint j = 0; iconTypes[j].type; j++)
    {
      /* TODO: Currently, this chooses the first "modern" ICNS format for a
       * ICNS file. This is because newer formats are not supported well in
       * non-native MacOS programs like Inkscape. It'd be nice to design
       * a GUI with enough information for users to make their own decisions
       */

      if (iconTypes[j].width == width   &&
          iconTypes[j].height == height &&
          iconTypes[j].isModern)
        {
          match = j;
          break;
        }
    }

  return match;
}

static gboolean
icns_check_dimensions (gint width,
                       gint height)
{
  gboolean isValid = TRUE;

  if (width != height)
    {
      /* Only valid non-square size is 16x12 */
      if (! (width == 16 && height == 12))
        isValid = FALSE;
    }
  else
    {
      /* Valid square ICNS sizes */
      if (width != 16   &&
          width != 18   &&
          width != 24   &&
          width != 32   &&
          width != 36   &&
          width != 48   &&
          width != 64   &&
          width != 128  &&
          width != 256  &&
          width != 512  &&
          width != 1024)
        isValid = FALSE;
    }

  return isValid;
}

static GtkWidget *
icns_create_icon_item (GtkWidget    *icon_preview,
                       GimpDrawable *layer,
                       gint          layer_num,
                       IcnsSaveInfo *info,
                       gint          duplicates[])
{
  static GtkSizeGroup *size = NULL;

  GtkWidget *vbox_item;
  GtkWidget *frame;
  gchar     *frame_header;
  gint       match  = -1;
  gint       width  = gimp_drawable_get_width (layer);
  gint       height = gimp_drawable_get_height (layer);

  vbox_item = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);

  /* To make life easier for the callbacks, we store the
     layer's ID and stacking number with vbox_item. */


  g_object_set_data (G_OBJECT (vbox_item),
                     "icon_layer", layer);
  g_object_set_data (G_OBJECT (vbox_item),
                     "icon_layer_num", GINT_TO_POINTER (layer_num));

  frame_header = g_strdup_printf ("%dx%d", width, height);

  frame = gimp_frame_new (frame_header);
  gtk_box_pack_start (GTK_BOX (vbox_item), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);
  g_free (frame_header);

  g_object_set_data (G_OBJECT (vbox_item), "icon_preview", icon_preview);
  gtk_container_add (GTK_CONTAINER (frame), icon_preview);
  gtk_widget_show (icon_preview);

  if (! size)
    size = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);

  gtk_size_group_add_widget (size, icon_preview);

  match = icns_find_type (gimp_drawable_get_width (layer),
                          gimp_drawable_get_height (layer));

  if (! icns_check_dimensions (width, height) ||
      (match != -1 && duplicates[match] != 0))
    {
      GtkWidget *label;
      gchar     *warning;
      gchar     *markup;

      if (! icns_check_dimensions (width, height))
        warning = g_strdup_printf (_("Invalid icon size. \n"
                                     "It will not be exported"));
      else
        warning = g_strdup_printf (_("Duplicate layer size. \n"
                                     "It will not be exported"));

      markup = g_strdup_printf ("<i>%s</i>", warning);

      label = gtk_label_new (NULL);
      gtk_label_set_markup (GTK_LABEL (label), markup);
      g_free (markup);
      g_free (warning);

      gtk_box_pack_start (GTK_BOX (vbox_item), label, FALSE, FALSE, 0);
      gtk_widget_show (label);
      gtk_style_context_add_class (gtk_widget_get_style_context (vbox_item),
                                   "background");
    }

  if (match != -1)
    duplicates[match] = 1;

  return vbox_item;
}

static gboolean
icns_check_compat (GtkWidget    *dialog,
                   IcnsSaveInfo *info)
{
  GtkWidget *warning;
  GList     *iter;
  gboolean   warn = FALSE;
  gint       i;

  for (iter = info->layers, i = 0; iter; iter = iter->next, i++)
    {
      gint width  = gimp_drawable_get_width (iter->data);
      gint height = gimp_drawable_get_height (iter->data);

      warn = ! icns_check_dimensions (width, height);
      if (warn)
        break;
    }

  if (dialog)
    {
      warning = g_object_get_data (G_OBJECT (dialog), "warning");
      gtk_widget_set_visible (warning, warn);
    }

  return ! warn;
}

GtkWidget *
icns_dialog_new (IcnsSaveInfo        *info,
                 GimpImage           *image,
                 GimpProcedure       *procedure,
                 GimpProcedureConfig *config)
{
  GtkWidget     *dialog;
  GtkWidget     *main_vbox;
  GtkWidget     *frame;
  GtkWidget     *scrolled_window;
  GtkWidget     *viewport;
  GtkWidget     *flowbox;
  GtkWidget     *warning;

  dialog = gimp_export_procedure_dialog_new (GIMP_EXPORT_PROCEDURE (procedure),
                                             config, image);

  g_object_set_data (G_OBJECT (dialog), "save_info", info);

  main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
                      main_vbox, TRUE, TRUE, 0);
  gtk_widget_set_visible (main_vbox, TRUE);

  warning = g_object_new (GIMP_TYPE_HINT_BOX,
                          "icon-name", GIMP_ICON_DIALOG_WARNING,
                          "hint",
                          _("Valid ICNS icons sizes are:\n "
                            "16x12, 16x16, 18x18, 24x24, 32x32, 36x36, 48x48,\n"
                            "64x64, 128x128, 256x256, 512x512, and 1024x1024.\n"
                            "Any other sized layers will be ignored on export."),
                          NULL);
  gtk_box_pack_end (GTK_BOX (main_vbox), warning, FALSE, FALSE, 12);
  /* Don't show warning by default */

  frame = gimp_frame_new (_("Export Icons"));
  gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 4);
  gtk_widget_set_visible (frame, TRUE);

  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
  gtk_container_add (GTK_CONTAINER (frame), scrolled_window);
  gtk_widget_set_size_request (scrolled_window, -1, 256);
  gtk_widget_set_visible (scrolled_window, TRUE);

  viewport = gtk_viewport_new (NULL, NULL);
  gtk_container_add (GTK_CONTAINER (scrolled_window), viewport);
  gtk_widget_set_visible (viewport, TRUE);

  flowbox = gtk_flow_box_new ();
  gtk_flow_box_set_column_spacing (GTK_FLOW_BOX (flowbox), 6);
  gtk_flow_box_set_row_spacing (GTK_FLOW_BOX (flowbox), 6);
  gtk_flow_box_set_selection_mode (GTK_FLOW_BOX (flowbox), GTK_SELECTION_NONE);
  g_object_set_data (G_OBJECT (dialog), "icons_flowbox", flowbox);
  gtk_container_add (GTK_CONTAINER (viewport), flowbox);
  gtk_widget_set_visible (flowbox, TRUE);

  g_object_set_data (G_OBJECT (dialog), "warning", warning);

  return dialog;
}

static gboolean
icns_save_dialog (IcnsSaveInfo        *info,
                  GimpImage           *image,
                  GimpProcedure       *procedure,
                  GimpProcedureConfig *config)
{
  GtkWidget *dialog;
  GList     *iter;
  gint       i;
  gint       j;
  gboolean   response;
  gint       duplicates[ICNS_TYPE_NUM];
  gint       ordered[12] =
    {12, 16, 18, 24, 32, 36, 48, 64, 128, 256, 512, 1024};

  gimp_ui_init (PLUG_IN_BINARY);

  for (i = 0; i < ICNS_TYPE_NUM; i++)
    duplicates[i] = 0;

  dialog = icns_dialog_new (info, image, procedure, config);

  /* Add icons in order, smallest to largest */
  for (i = 0; i < 12; i++)
    {
      for (iter = info->layers, j = 0;
           iter;
           iter = g_list_next (iter), j++)
        {
          /* Put the icons in order in dialog */
          gint width  = gimp_drawable_get_width (iter->data);
          gint height = gimp_drawable_get_height (iter->data);

          if (height != ordered[i] || ! icns_check_dimensions (width, height))
            continue;

          icns_dialog_add_icon (dialog, iter->data, i, duplicates);
        }
    }

  /* Add any invalid icons at the end */
  for (iter = info->layers, i = 0;
       iter;
       iter = g_list_next (iter), i++)
    {
      if (! icns_check_dimensions (gimp_drawable_get_width (iter->data),
                                   gimp_drawable_get_height (iter->data)))
        icns_dialog_add_icon (dialog, iter->data, i, duplicates);
    }

  /* Scale the thing to approximately fit its content, but not too large ... */
  gtk_window_set_default_size (GTK_WINDOW (dialog),
                               200 + (info->num_icons > 4 ?
                                      500 : info->num_icons * 120),
                               200 + (info->num_icons > 4 ?
                                      250 : info->num_icons * 60));

  gtk_widget_set_visible (dialog, TRUE);

  response = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));

  gtk_widget_destroy (dialog);

  return response;
}

GimpPDBStatusType
icns_export_image (GFile        *file,
                   IcnsSaveInfo *info,
                   GimpImage    *image,
                   gboolean      include_color_profile,
                   GError      **error)
{
  FILE           *fp;
  GList          *iter;
  gint            i;
  guint32         file_size   = 8;
  gint            duplicates[ICNS_TYPE_NUM];

  for (i = 0; i < ICNS_TYPE_NUM; i++)
    duplicates[i] = 0;

  fp = g_fopen (g_file_peek_path (file), "wb");

  if (! fp)
    {
      icns_save_info_free (info);
      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
                   _("Could not open '%s' for writing: %s"),
                   gimp_file_get_utf8_name (file), g_strerror (errno));
      return GIMP_PDB_EXECUTION_ERROR;
    }

  /* Write Header */
  fwrite ("icns", sizeof (gchar), 4, fp);
  fwrite ("\0\0\0\0", sizeof (gchar), 4, fp);  /* will be filled in later */

  /* Write Icon Data */
  for (iter = info->layers, i = 0;
       iter;
       iter = g_list_next (iter), i++)
    {
      gint match  = -1;
      gint width  = gimp_drawable_get_width (iter->data);
      gint height = gimp_drawable_get_height (iter->data);

      /* Don't export icons with invalid dimensions */
      if (! icns_check_dimensions (width, height))
        continue;

      match = icns_find_type (width, height);

      /* MacOS X format icons */
      if (match != -1 && duplicates[match] == 0)
        {
          gint temp_size;
          gint macos_size;

          /* icp4 - 6 types (16x16, 32x32 and 48x48 icons) do not render well
           * in applications if saved as PNGs. Therefore, we will save those
           * in the older format for compatibility. */

          if (! g_strcmp0 (iconTypes[match].type, "icp4") ||
              ! g_strcmp0 (iconTypes[match].type, "icp5") ||
              ! g_strcmp0 (iconTypes[match].type, "icp6"))
            {
              GeglBuffer *buffer;
              guchar     *pixels;
              guchar     *alpha     = NULL;
              guchar     *output    = NULL;
              gint        compat_id = -1;

              macos_size = 0;

              for (compat_id = 0; iconTypes[compat_id].type; compat_id++)
                {
                  if (iconTypes[compat_id].width == width   &&
                      iconTypes[compat_id].height == height &&
                      iconTypes[compat_id].bits == 32)
                    break;
                }

              fwrite (iconTypes[compat_id].type, sizeof (gchar), 4, fp);
              temp_size = width * height * 4;

              buffer = gimp_drawable_get_buffer (iter->data);
              pixels = g_malloc (temp_size);
              alpha  = g_malloc (width * height);

              gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height),
                               1.0, babl_format ("R'G'B'A u8"), pixels,
                               GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
              gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height),
                               1.0, babl_format ("A u8"), alpha,
                               GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

              output = icns_compress (width, height, pixels, &macos_size);

              /* ---------------------- */

              temp_size = GUINT32_TO_BE (macos_size + 8);
              fwrite (&temp_size, sizeof (temp_size), 1, fp);

              if (fwrite (output, 1, macos_size, fp) < macos_size)
                {
                  icns_save_info_free (info);
                  g_set_error (error, G_FILE_ERROR,
                               g_file_error_from_errno (errno),
                               _("Error writing icns: %s"),
                               g_strerror (errno));
                  return GIMP_PDB_EXECUTION_ERROR;
                }

              file_size += macos_size + 8;

              /* Write uncompressed mask */
              fwrite (iconTypes[compat_id].mask, sizeof (gchar), 4, fp);
              macos_size = GUINT32_TO_BE ((width * height) + 8);
              fwrite (&macos_size, sizeof (macos_size), 1, fp);
              macos_size = width * height;

              if (fwrite (alpha, 1, macos_size, fp) < macos_size)
                {
                  icns_save_info_free (info);
                  g_set_error (error, G_FILE_ERROR,
                               g_file_error_from_errno (errno),
                               _("Error writing icns: %s"),
                               g_strerror (errno));
                  return GIMP_PDB_EXECUTION_ERROR;
                }

              file_size += (width * height) + 8;

              g_free (pixels);
              g_free (alpha);
              g_object_unref (buffer);
            }
          else
            {
              GimpProcedure  *procedure;
              GimpValueArray *return_vals;
              GimpImage      *temp_image;
              GimpLayer      *temp_layer;
              GFile          *temp_file = NULL;
              FILE           *temp_fp;

              temp_file  = gimp_temp_file ("png");

              /* TODO: Use GimpExportOptions for this when available */
              temp_image = gimp_image_new (width, height,
                                           gimp_image_get_base_type (image));
              if (gimp_image_get_base_type (image) == GIMP_INDEXED)
                gimp_image_set_palette (temp_image,
                                        gimp_image_get_palette (image));

              temp_layer = gimp_layer_new_from_drawable (GIMP_DRAWABLE (iter->data),
                                                         temp_image);
              gimp_image_insert_layer (temp_image, temp_layer, NULL, 0);

              if (include_color_profile &&
                  gimp_image_get_color_profile (image))
                {
                  GimpColorProfile *profile;

                  profile =  gimp_image_get_color_profile (image);
                  gimp_image_set_color_profile (temp_image, profile);
                }

              procedure   = gimp_pdb_lookup_procedure (gimp_get_pdb (), "file-png-export");
              return_vals = gimp_procedure_run (procedure,
                                                "run-mode",              GIMP_RUN_NONINTERACTIVE,
                                                "image",                 temp_image,
                                                "file",                  temp_file,
                                                "interlaced",            FALSE,
                                                "compression",           9,
                                                "bkgd",                  FALSE,
                                                "offs",                  FALSE,
                                                "phys",                  FALSE,
                                                "time",                  FALSE,
                                                "save-transparent",      FALSE,
                                                "optimize-palette",      FALSE,
                                                "include-color-profile", include_color_profile,
                                                NULL);
              gimp_image_delete (temp_image);

              if (GIMP_VALUES_GET_ENUM (return_vals, 0) != GIMP_PDB_SUCCESS)
                {
                  icns_save_info_free (info);
                  g_set_error (error, 0, 0,
                               "Running procedure 'file-png-export' "
                               "for icns export failed: %s",
                               gimp_pdb_get_last_error (gimp_get_pdb ()));

                  return GIMP_PDB_EXECUTION_ERROR;
                }

              temp_fp = g_fopen (g_file_peek_path (temp_file), "rb");
              fseek (temp_fp, 0L, SEEK_END);
              temp_size = ftell (temp_fp);
              fseek (temp_fp, 0L, SEEK_SET);

              g_file_delete (temp_file, NULL, NULL);
              g_object_unref (temp_file);

              fwrite (iconTypes[match].type, sizeof (gchar), 4, fp);
              macos_size = GUINT32_TO_BE (temp_size + 8);
              fwrite (&macos_size, sizeof (macos_size), 1, fp);

              if (temp_size > 0)
                {
                  guchar buf[temp_size];

                  fread (buf, 1, sizeof (buf), temp_fp);

                  if (fwrite (buf, 1, temp_size, fp) < temp_size)
                    {
                      icns_save_info_free (info);
                      g_set_error (error, G_FILE_ERROR,
                                   g_file_error_from_errno (errno),
                                   _("Error writing icns: %s"),
                                   g_strerror (errno));
                      return GIMP_PDB_EXECUTION_ERROR;
                    }
                }
              fclose (temp_fp);

              file_size += temp_size + 8;
          }
          duplicates[match] = 1;
        }

      gimp_progress_update (i / info->num_icons);
    }

  /* Update header with full file size */
  file_size = GUINT32_TO_BE (file_size);
  fseek (fp, 4L, SEEK_SET);
  fwrite (&file_size, sizeof (file_size), 1, fp);

  gimp_progress_update (1.0);

  icns_save_info_free (info);
  fclose (fp);
  return GIMP_PDB_SUCCESS;
}

static guchar *
icns_compress (guint   width,
               guint   height,
               guchar *rgba,
               gint   *out_size)
{
  const guint npixels  = width * height;
  const guint max_size = (npixels * 3) + ((npixels * 3) / 4);

  const guint min_run = 3;   /* Shorter run must be stored as uncompressed */
  const guint max_run = 130; /* Longest same-value run that can be stored */
  const guint min_raw = 1;
  const guint max_raw = 128; /* Longest run of non-matching pixels */

  guint   i;
  guint   j;
  guint   size;
  guint   channel;
  guint   run;
  guint   marker;
  guchar *out_data;
  guchar *run_length;

  run_length = g_new (guchar, npixels);
  if (! run_length)
    {
      g_warning ("icns_compress: couldn't allocate run count buffer (%d bytes)", npixels);
      return NULL;
    }

  out_data = g_new (guchar, max_size);
  if (! out_data)
    {
      g_free (run_length);
      return NULL;
    }

  size = 0;
  /* For some reason 128x128 icons have an extra 4 bytes at the start */
  if (width == 128 && height == 128)
    {
      out_data[size++] = 0;
      out_data[size++] = 0;
      out_data[size++] = 0;
      out_data[size++] = 0;
    }

  for (channel = 0; channel < 3; channel++)
    {
      /* Count all run lengths */
      for (i = 0; i < npixels; i++)
        {
          for (run = 1; run < max_run && (run + i - 1) < npixels; run++)
            if (rgba[i * 4 + channel] != rgba[(i + run) * 4 + channel])
              break;

          run_length[i] = run;
        }

      for (i = 0; i < npixels; i++)
        {
          if (run_length[i] >= min_run)
            {
              /* Compressable! Store and skip ahead */
              out_data[size++] = (run_length[i] - min_run) | 0x80;
              out_data[size++] = rgba[i * 4 + channel];
              i += run_length[i] - 1;
            }
          else
            {
              /* Too short: stuff together as many as you can in a raw run */
              marker = size++;
              run = 0;
              while (run < max_raw && i < npixels && run_length[i] < min_run)
                {
                  for (j = 0; j < run_length[i]; j++)
                    {
                      out_data[size++] = rgba[(i + j) * 4 + channel];
                      run++;
                    }
                  i += run_length[i];
                }
              out_data[marker] = run - min_raw;
              i--;
            }
        }
    }

  g_free (run_length);
  *out_size = size;

  return out_data;
}

static void
icns_save_info_free (IcnsSaveInfo *info)
{
  g_list_free (info->layers);
  memset (info, 0, sizeof (IcnsSaveInfo));
}

GimpPDBStatusType
icns_save_image (GFile                *file,
                 GimpImage            *image,
                 GimpProcedure        *procedure,
                 GimpProcedureConfig  *config,
                 gint32                run_mode,
                 GError              **error)
{
  IcnsSaveInfo  info;
  GList        *iter;
  gboolean      isValidLayers         = FALSE;
  gboolean      include_color_profile = FALSE;
  gint          i;

  info.layers    = gimp_image_list_layers (image);
  info.num_icons = g_list_length (info.layers);

  /* Initial check if we have any valid layers to export */
  for (iter = info.layers, i = 0; iter; iter = iter->next, i++)
    {
      gint width  = gimp_drawable_get_width (iter->data);
      gint height = gimp_drawable_get_height (iter->data);

      if (icns_check_dimensions (width, height))
        {
          isValidLayers = TRUE;
          break;
        }
    }
  if (! isValidLayers)
    {
      g_set_error (error, G_FILE_ERROR, 0,
                   _("No valid sized layers. Only valid layer sizes are "
                     "16x12, 16x16, 18x18, 24x24, 32x32, 36x36, 48x48, "
                     "64x64, 128x128, 256x256, 512x512, or 1024x1024."));

      return GIMP_PDB_EXECUTION_ERROR;
    }

  if (run_mode == GIMP_RUN_INTERACTIVE)
    {
      /* Allow user to override default values */
      if (! icns_save_dialog (&info, image, procedure, config))
        return GIMP_PDB_CANCEL;
    }
  else if (run_mode == GIMP_RUN_NONINTERACTIVE)
    {
      if (! icns_check_compat (NULL, &info))
        {
          g_set_error (error, G_FILE_ERROR, 0,
                       _("Invalid layer size(s). Only valid layer sizes are "
                         "16x12, 16x16, 18x18, 24x24, 32x32, 36x36, 48x48, "
                         "64x64, 128x128, 256x256, 512x512, or 1024x1024."));

          return GIMP_PDB_EXECUTION_ERROR;
        }
    }

  g_object_get (config,
                "include-color-profile", &include_color_profile,
                NULL);

  gimp_progress_init_printf (_("Exporting '%s'"),
                             gimp_file_get_utf8_name (file));

  return icns_export_image (file, &info, image, include_color_profile, error);
}

Messung
CHZG
869310092

¤ Dauer der Verarbeitung: 0.14 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104850
#Domains=416973