gimp/plug-ins/file-ico/ico.c

353 lines
11 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
*
* GIMP Plug-in for Windows Icon files.
* Copyright (C) 2002 Christian Kreibich <christian@whoop.org>.
*
* 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 <string.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
/* #define ICO_DBG */
#include "ico.h"
#include "ico-load.h"
#include "ico-save.h"
#include "libgimp/stdplugins-intl.h"
#define LOAD_PROC "file-ico-load"
#define LOAD_THUMB_PROC "file-ico-load-thumb"
#define SAVE_PROC "file-ico-save"
2019-08-14 06:06:22 +08:00
typedef struct _Ico Ico;
typedef struct _IcoClass IcoClass;
2019-08-14 06:06:22 +08:00
struct _Ico
{
GimpPlugIn parent_instance;
};
2019-08-14 06:06:22 +08:00
struct _IcoClass
{
2019-08-14 06:06:22 +08:00
GimpPlugInClass parent_class;
};
2019-08-14 06:06:22 +08:00
#define ICO_TYPE (ico_get_type ())
#define ICO (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ICO_TYPE, Ico))
GType ico_get_type (void) G_GNUC_CONST;
static GList * ico_query_procedures (GimpPlugIn *plug_in);
static GimpProcedure * ico_create_procedure (GimpPlugIn *plug_in,
const gchar *name);
static GimpValueArray * ico_load (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
const GimpValueArray *args,
gpointer run_data);
static GimpValueArray * ico_load_thumb (GimpProcedure *procedure,
GFile *file,
gint size,
2019-08-14 06:06:22 +08:00
const GimpValueArray *args,
gpointer run_data);
static GimpValueArray * ico_save (GimpProcedure *procedure,
GimpRunMode run_mode,
GimpImage *image,
GimpDrawable *drawable,
2019-08-14 06:06:22 +08:00
GFile *file,
const GimpValueArray *args,
gpointer run_data);
G_DEFINE_TYPE (Ico, ico, GIMP_TYPE_PLUG_IN)
GIMP_MAIN (ICO_TYPE)
static void
2019-08-14 06:06:22 +08:00
ico_class_init (IcoClass *klass)
{
2019-08-14 06:06:22 +08:00
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
plug_in_class->query_procedures = ico_query_procedures;
plug_in_class->create_procedure = ico_create_procedure;
}
static void
2019-08-14 06:06:22 +08:00
ico_init (Ico *ico)
{
2019-08-14 06:06:22 +08:00
}
2019-08-14 06:06:22 +08:00
static GList *
ico_query_procedures (GimpPlugIn *plug_in)
{
GList *list = NULL;
2019-08-14 06:06:22 +08:00
list = g_list_append (list, g_strdup (LOAD_PROC));
list = g_list_append (list, g_strdup (LOAD_THUMB_PROC));
list = g_list_append (list, g_strdup (SAVE_PROC));
2019-08-14 06:06:22 +08:00
return list;
}
2012-11-30 08:38:23 +08:00
2019-08-14 06:06:22 +08:00
static GimpProcedure *
ico_create_procedure (GimpPlugIn *plug_in,
const gchar *name)
{
GimpProcedure *procedure = NULL;
2019-08-14 06:06:22 +08:00
if (! strcmp (name, LOAD_PROC))
{
procedure = gimp_load_procedure_new (plug_in, name,
GIMP_PDB_PROC_TYPE_PLUGIN,
2019-08-14 06:06:22 +08:00
ico_load, NULL, NULL);
gimp_procedure_set_menu_label (procedure, N_("Microsoft Windows icon"));
gimp_procedure_set_icon_name (procedure, GIMP_ICON_BRUSH);
2019-08-14 06:06:22 +08:00
gimp_procedure_set_documentation (procedure,
"Loads files of Windows ICO file format",
"Loads files of Windows ICO file format",
name);
gimp_procedure_set_attribution (procedure,
"Christian Kreibich <christian@whoop.org>",
"Christian Kreibich <christian@whoop.org>",
"2002");
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
"image/x-ico");
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
"ico");
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
"0,string,\\000\\001\\000\\000,0,string,\\000\\002\\000\\000");
gimp_load_procedure_set_thumbnail_loader (GIMP_LOAD_PROCEDURE (procedure),
LOAD_THUMB_PROC);
}
2019-08-14 06:06:22 +08:00
else if (! strcmp (name, LOAD_THUMB_PROC))
{
procedure = gimp_thumbnail_procedure_new (plug_in, name,
GIMP_PDB_PROC_TYPE_PLUGIN,
ico_load_thumb, NULL, NULL);
2019-08-14 06:06:22 +08:00
gimp_procedure_set_documentation (procedure,
"Loads a preview from an Windows ICO file",
"",
name);
gimp_procedure_set_attribution (procedure,
"Dom Lachowicz, Sven Neumann",
"Sven Neumann <sven@gimp.org>",
"2005");
}
2019-08-14 06:06:22 +08:00
else if (! strcmp (name, SAVE_PROC))
{
procedure = gimp_save_procedure_new (plug_in, name,
GIMP_PDB_PROC_TYPE_PLUGIN,
2019-08-14 06:06:22 +08:00
ico_save, NULL, NULL);
2019-08-14 06:06:22 +08:00
gimp_procedure_set_image_types (procedure, "*");
2019-08-14 06:06:22 +08:00
gimp_procedure_set_menu_label (procedure, N_("Microsoft Windows icon"));
gimp_procedure_set_icon_name (procedure, GIMP_ICON_BRUSH);
2019-08-14 06:06:22 +08:00
gimp_procedure_set_documentation (procedure,
"Saves files in Windows ICO file format",
"Saves files in Windows ICO file format",
name);
gimp_procedure_set_attribution (procedure,
"Christian Kreibich <christian@whoop.org>",
"Christian Kreibich <christian@whoop.org>",
"2002");
2019-08-14 06:06:22 +08:00
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
"image/x-ico");
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
"ico");
}
2019-08-14 06:06:22 +08:00
return procedure;
}
2019-08-14 06:06:22 +08:00
static GimpValueArray *
ico_load (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
const GimpValueArray *args,
gpointer run_data)
{
GimpValueArray *return_vals;
gchar *filename;
GimpImage *image;
2019-08-14 06:06:22 +08:00
GError *error = NULL;
2019-08-14 06:06:22 +08:00
INIT_I18N ();
gegl_init (NULL, NULL);
2019-08-14 06:06:22 +08:00
filename = g_file_get_path (file);
image = ico_load_image (filename, &error);
2019-08-14 06:06:22 +08:00
g_free (filename);
if (! image)
2019-08-14 06:06:22 +08:00
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_EXECUTION_ERROR,
error);
return_vals = gimp_procedure_new_return_values (procedure,
GIMP_PDB_SUCCESS,
NULL);
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
2019-08-14 06:06:22 +08:00
return return_vals;
}
static GimpValueArray *
ico_load_thumb (GimpProcedure *procedure,
GFile *file,
gint size,
2019-08-14 06:06:22 +08:00
const GimpValueArray *args,
gpointer run_data)
{
GimpValueArray *return_vals;
gchar *filename;
2019-08-14 06:06:22 +08:00
gint width;
gint height;
GimpImage *image;
2019-08-14 06:06:22 +08:00
GError *error = NULL;
2019-08-14 06:06:22 +08:00
INIT_I18N ();
gegl_init (NULL, NULL);
filename = g_file_get_path (file);
width = size;
height = size;
2019-08-14 06:06:22 +08:00
image = ico_load_thumbnail_image (filename,
&width, &height, &error);
2019-08-14 06:06:22 +08:00
if (image)
2019-08-14 06:06:22 +08:00
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_EXECUTION_ERROR,
error);
return_vals = gimp_procedure_new_return_values (procedure,
GIMP_PDB_SUCCESS,
NULL);
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
GIMP_VALUES_SET_INT (return_vals, 2, width);
GIMP_VALUES_SET_INT (return_vals, 3, height);
2019-08-14 06:06:22 +08:00
gimp_value_array_truncate (return_vals, 4);
2019-08-14 06:06:22 +08:00
return return_vals;
}
2019-08-14 06:06:22 +08:00
static GimpValueArray *
ico_save (GimpProcedure *procedure,
GimpRunMode run_mode,
GimpImage *image,
GimpDrawable *drawable,
2019-08-14 06:06:22 +08:00
GFile *file,
const GimpValueArray *args,
gpointer run_data)
{
GimpPDBStatusType status;
gchar *filename;
GError *error = NULL;
INIT_I18N ();
gegl_init (NULL, NULL);
filename = g_file_get_path (file);
status = ico_save_image (filename, image, run_mode, &error);
2019-08-14 06:06:22 +08:00
g_free (filename);
return gimp_procedure_new_return_values (procedure, status, error);
}
2006-10-06 14:42:09 +08:00
gint
ico_rowstride (gint width,
gint bpp)
{
switch (bpp)
{
case 1:
if ((width % 32) == 0)
2006-10-06 14:42:09 +08:00
return width / 8;
else
2006-10-06 14:42:09 +08:00
return 4 * (width/32 + 1);
break;
case 4:
if ((width % 8) == 0)
2006-10-06 14:42:09 +08:00
return width / 2;
else
2006-10-06 14:42:09 +08:00
return 4 * (width/8 + 1);
break;
case 8:
if ((width % 4) == 0)
2006-10-06 14:42:09 +08:00
return width;
else
2006-10-06 14:42:09 +08:00
return 4 * (width/4 + 1);
break;
2006-10-06 14:42:09 +08:00
case 24:
if (((width*3) % 4) == 0)
return width * 3;
else
return 4 * (width*3/4+1);
2006-10-06 14:42:09 +08:00
case 32:
return width * 4;
2006-10-06 14:42:09 +08:00
default:
g_warning ("invalid bitrate: %d\n", bpp);
g_assert_not_reached ();
return width * (bpp/8);
}
}
2006-10-06 14:42:09 +08:00
guint8 *
ico_alloc_map (gint width,
gint height,
gint bpp,
gint *length)
{
2006-10-06 14:42:09 +08:00
gint len = 0;
guint8 *map = NULL;
2006-10-06 14:42:09 +08:00
len = ico_rowstride (width, bpp) * height;
2006-10-06 14:42:09 +08:00
*length = len;
map = g_new0 (guint8, len);
2006-10-06 14:42:09 +08:00
return map;
}