configure.in plug-ins/Makefile.am plug-ins/winicon/Makefile.am

2004-04-15  Sven Neumann  <sven@gimp.org>

	* configure.in
	* plug-ins/Makefile.am
	* plug-ins/winicon/Makefile.am
	* plug-ins/winicon/icodialog.[ch]
	* plug-ins/winicon/icoload.[ch]
	* plug-ins/winicon/icosave.[ch]
	* plug-ins/winicon/main.[ch]: added plug-in to load and save
	Windows icon files. Plug-in written by Christian Kreibich, port to
	GIMP-2.0 API by Gregor Riepl, massive code cleanup by me. Fixes
	bug #139160.
This commit is contained in:
Sven Neumann 2004-04-15 18:39:48 +00:00 committed by Sven Neumann
parent 957190d750
commit 48bf883825
15 changed files with 2606 additions and 1 deletions

View file

@ -1,3 +1,16 @@
2004-04-15 Sven Neumann <sven@gimp.org>
* configure.in
* plug-ins/Makefile.am
* plug-ins/winicon/Makefile.am
* plug-ins/winicon/icodialog.[ch]
* plug-ins/winicon/icoload.[ch]
* plug-ins/winicon/icosave.[ch]
* plug-ins/winicon/main.[ch]: added plug-in to load and save
Windows icon files. Plug-in written by Christian Kreibich, port to
GIMP-2.0 API by Gregor Riepl, massive code cleanup by me. Fixes
bug #139160.
2004-04-15 Michael Natterer <mitch@gimp.org>
* app/widgets/gimpdnd.c (gimp_dnd_data_source_add)

View file

@ -1551,6 +1551,7 @@ plug-ins/rcm/Makefile
plug-ins/sel2path/Makefile
plug-ins/sgi/Makefile
plug-ins/twain/Makefile
plug-ins/winicon/Makefile
plug-ins/winsnap/Makefile
modules/Makefile
devel-docs/Makefile

View file

@ -53,6 +53,7 @@ SUBDIRS = \
rcm \
sgi \
sel2path \
winicon \
$(win32dirs) \
$(xjt) \
common

View file

@ -0,0 +1,6 @@
Makefile.in
Makefile
.deps
_libs
.libs
winicon

View file

@ -0,0 +1,44 @@
## Process this file with automake to produce Makefile.in
libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la
libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la
libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la
libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la
libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la
libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
if OS_WIN32
mwindows = -mwindows
endif
AM_LDFLAGS = $(mwindows)
libexecdir = $(gimpplugindir)/plug-ins
libexec_PROGRAMS = winicon
winicon_SOURCES = \
icodialog.c \
icodialog.h \
icoload.c \
icoload.h \
icosave.c \
icosave.h \
main.c \
main.h
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(libgimpui) \
$(libgimpwidgets) \
$(libgimp) \
$(libgimpcolor) \
$(libgimpmath) \
$(libgimpbase) \
$(GTK_LIBS) \
$(RT_LIBS) \
$(INTLLIBS)

View file

@ -0,0 +1,461 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <stdio.h>
#undef GTK_DISABLE_DEPRECATED
#include <gtk/gtkpreview.h>
#define GTK_DISABLE_DEPRECATED
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#define ICO_DBG
#include "icodialog.h"
#include "main.h"
#include "libgimp/stdplugins-intl.h"
static GtkWidget *ico_preview_new (gint32 layer);
static void ico_fill_preview_with_thumb (GtkWidget *widget,
gint32 drawable_ID);
static void on_1bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox);
static void on_4bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox);
static void on_8bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox);
static void on_32bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox);
static GtkWidget *
ico_preview_new(gint32 layer)
{
GtkWidget *icon_preview;
icon_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
ico_fill_preview_with_thumb (icon_preview, layer);
return icon_preview;
}
static void
ico_fill_preview_with_thumb (GtkWidget *widget,
gint32 drawable_ID)
{
guchar *drawable_data;
gint bpp;
gint x,y;
gint width;
gint height;
guchar *src;
gdouble r, g, b, a;
gdouble c0, c1;
guchar *p0, *p1;
guchar *even, *odd;
width = gimp_drawable_width (drawable_ID);
height = gimp_drawable_height (drawable_ID);
bpp = 0; /* Only returned */
if (width > 128)
width = 128;
if (height > 128)
height = 128;
drawable_data =
gimp_drawable_get_thumbnail_data (drawable_ID, &width, &height, &bpp);
if (width < 1 || height < 1)
return;
gtk_preview_size (GTK_PREVIEW (widget), width, height);
even = g_malloc (width * 3);
odd = g_malloc (width * 3);
src = drawable_data;
for (y = 0; y < height; y++)
{
p0 = even;
p1 = odd;
for (x = 0; x < width; x++)
{
if (bpp == 4)
{
r = ((gdouble) src[x*4 + 0]) / 255.0;
g = ((gdouble) src[x*4 + 1]) / 255.0;
b = ((gdouble) src[x*4 + 2]) / 255.0;
a = ((gdouble) src[x*4 + 3]) / 255.0;
}
else if (bpp == 3)
{
r = ((gdouble) src[x*3 + 0]) / 255.0;
g = ((gdouble) src[x*3 + 1]) / 255.0;
b = ((gdouble) src[x*3 + 2]) / 255.0;
a = 1.0;
}
else
{
r = ((gdouble) src[x*bpp + 0]) / 255.0;
g = b = r;
if (bpp == 2)
a = ((gdouble) src[x*2 + 1]) / 255.0;
else
a = 1.0;
}
if ((x / GIMP_CHECK_SIZE_SM) & 1)
{
c0 = GIMP_CHECK_LIGHT;
c1 = GIMP_CHECK_DARK;
}
else
{
c0 = GIMP_CHECK_DARK;
c1 = GIMP_CHECK_LIGHT;
}
*p0++ = (c0 + (r - c0) * a) * 255.0;
*p0++ = (c0 + (g - c0) * a) * 255.0;
*p0++ = (c0 + (b - c0) * a) * 255.0;
*p1++ = (c1 + (r - c1) * a) * 255.0;
*p1++ = (c1 + (g - c1) * a) * 255.0;
*p1++ = (c1 + (b - c1) * a) * 255.0;
}
if ((y / GIMP_CHECK_SIZE_SM) & 1)
gtk_preview_draw_row (GTK_PREVIEW (widget), odd, 0, y, width);
else
gtk_preview_draw_row (GTK_PREVIEW (widget), even, 0, y, width);
src += width * bpp;
}
g_free (even);
g_free (odd);
g_free (drawable_data);
}
/* This function creates and returns an hbox for an icon,
which then gets added to the dialog's main vbox. */
static GtkWidget*
ico_create_icon_hbox (GtkWidget *icon_preview,
gint32 layer,
gint layer_num)
{
GtkWidget *hbox;
GtkWidget *optionmenu;
GtkWidget *optionmenu_menu;
GtkWidget *menuitem;
hbox = gtk_hbox_new (FALSE, 0);
/* To make life easier for the callbacks, we store the
layer's ID and stacking number with the hbox. */
g_object_set_data (G_OBJECT (hbox),
"icon_layer", GINT_TO_POINTER (layer));
g_object_set_data (G_OBJECT (hbox),
"icon_layer_num", GINT_TO_POINTER (layer_num));
g_object_set_data (G_OBJECT (hbox), "icon_preview", icon_preview);
gtk_widget_show (icon_preview);
gtk_box_pack_start (GTK_BOX (hbox), icon_preview, TRUE, TRUE, 0);
optionmenu = gtk_option_menu_new ();
g_object_set_data (G_OBJECT (hbox), "icon_optionmenu", optionmenu);
gtk_widget_show (optionmenu);
gtk_box_pack_start (GTK_BOX (hbox), optionmenu, FALSE, FALSE, 0);
optionmenu_menu = gtk_menu_new ();
menuitem =
gtk_menu_item_new_with_label (_("1 bpp, 1-bit alpha, 2-slot palette"));
g_signal_connect (menuitem, "activate",
G_CALLBACK (on_1bpp_menu_selected),
hbox);
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (optionmenu_menu), menuitem);
menuitem =
gtk_menu_item_new_with_label (_("4 bpp, 1-bit alpha, 16-slot palette"));
g_signal_connect (menuitem, "activate",
G_CALLBACK (on_4bpp_menu_selected),
hbox);
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (optionmenu_menu), menuitem);
menuitem =
gtk_menu_item_new_with_label (_("8 bpp, 1-bit alpha, 256-slot palette"));
g_signal_connect (menuitem, "activate",
G_CALLBACK (on_8bpp_menu_selected),
hbox);
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (optionmenu_menu), menuitem);
menuitem =
gtk_menu_item_new_with_label (_("32 bpp, 8-bit alpha, no palette"));
g_signal_connect (menuitem, "activate",
G_CALLBACK (on_32bpp_menu_selected),
hbox);
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (optionmenu_menu), menuitem);
gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu),
optionmenu_menu);
gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 3);
return hbox;
}
GtkWidget*
ico_specs_dialog_new (gint num_layers)
{
GtkWidget *dialog;
GtkWidget *vbox;
GtkWidget *frame;
GtkWidget *scrolledwindow;
GtkWidget *viewport;
gint *icon_depths, i;
dialog = gimp_dialog_new (_("GIMP Windows Icon Plugin"), "winicon",
NULL, 0,
gimp_standard_help_func, "plug-in-winicon",
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
/* We store an array that holds each icon's requested bit depth
with the dialog. It's queried when the dialog is closed so the
save routine knows what colormaps etc to generate in the saved
file. We store twice the number necessary because in the second
set, the color depths that are automatically suggested are stored
for later comparison.
*/
icon_depths = g_new (gint, 2 * num_layers);
for (i = 0; i < 2 * num_layers; i++)
icon_depths[i] = 32;
g_object_set_data (G_OBJECT (dialog), "icon_depths", icon_depths);
vbox = GTK_DIALOG (dialog)->vbox;
frame = gtk_frame_new (_("Icon details"));
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame), 5);
gtk_widget_show (frame);
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow), 5);
gtk_container_add (GTK_CONTAINER (frame), scrolledwindow);
gtk_widget_show (scrolledwindow);
viewport = gtk_viewport_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (scrolledwindow), viewport);
gtk_widget_show (viewport);
vbox = gtk_vbox_new (TRUE, 0);
g_object_set_data (G_OBJECT (dialog), "icons_vbox", vbox);
gtk_container_add (GTK_CONTAINER (viewport), vbox);
gtk_widget_show (vbox);
return dialog;
}
static GtkWidget *
ico_specs_dialog_get_layer_preview (GtkWidget *dialog,
gint32 layer)
{
GtkWidget *preview;
GtkWidget *icon_hbox;
gchar key[MAXLEN];
g_snprintf (key, MAXLEN, "layer_%i_hbox", layer);
icon_hbox = g_object_get_data (G_OBJECT (dialog), key);
if (!icon_hbox)
{
D(("Something's wrong -- couldn't look up hbox by layer ID\n"));
return NULL;
}
preview = g_object_get_data (G_OBJECT (icon_hbox), "icon_preview");
if (!icon_hbox)
{
D(("Something's wrong -- couldn't look up preview from hbox\n"));
return NULL;
}
return preview;
}
void
ico_specs_dialog_add_icon (GtkWidget *dialog,
gint32 layer,
gint layer_num)
{
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *preview;
gchar key[MAXLEN];
vbox = g_object_get_data (G_OBJECT (dialog), "icons_vbox");
preview = ico_preview_new (layer);
hbox = ico_create_icon_hbox (preview, layer, layer_num);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 2);
gtk_widget_show (hbox);
/* Let's make the hbox accessible through the layer ID */
g_snprintf (key, MAXLEN, "layer_%i_hbox", layer);
g_object_set_data (G_OBJECT (dialog), key, hbox);
}
void
ico_specs_dialog_update_icon_preview (GtkWidget *dialog,
gint32 layer,
gint bpp)
{
GtkWidget *preview;
GimpPixelRgn src_pixel_rgn, dst_pixel_rgn;
gint32 tmp_image;
gint32 tmp_layer;
gint w, h;
guchar *buffer;
gboolean result;
tmp_image = gimp_image_new (gimp_drawable_width (layer),
gimp_drawable_height (layer),
GIMP_RGB);
w = gimp_drawable_width (layer);
h = gimp_drawable_height (layer);
tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h,
GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
gimp_image_add_layer (tmp_image, tmp_layer, 0);
gimp_pixel_rgn_init (&src_pixel_rgn, gimp_drawable_get (layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get (tmp_layer),
0, 0, w, h, TRUE, FALSE);
buffer = g_malloc (w * h * 4);
gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h);
gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
if (bpp < 32)
{
result = gimp_image_convert_indexed (tmp_image,
GIMP_FS_DITHER,
GIMP_MAKE_PALETTE,
1 << bpp,
TRUE,
FALSE,
"dummy");
}
preview = ico_specs_dialog_get_layer_preview (dialog, layer);
ico_fill_preview_with_thumb (preview, tmp_layer);
gtk_widget_queue_draw (preview);
gimp_image_delete (tmp_image);
g_free (buffer);
}
/* meta-callback for color depth changes in an icon */
static void
on_bpp_change (GtkWidget *icon_hbox,
gint bpp)
{
GtkWidget *dialog;
gint32 layer;
gint layer_num;
gint *icon_depths;
dialog = gtk_widget_get_toplevel (icon_hbox);
layer = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (icon_hbox),
"icon_layer"));
layer_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (icon_hbox),
"icon_layer_num"));
icon_depths = g_object_get_data (G_OBJECT (dialog), "icon_depths");
if (! icon_depths)
{
D(("Something's wrong -- can't get icon_depths array from dialog ...\n"));
return;
}
/* Update vector entry for later when we're actually saving,
and update the preview right away ... */
icon_depths[layer_num] = bpp;
ico_specs_dialog_update_icon_preview (dialog, layer, bpp);
}
static void
on_1bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox)
{
on_bpp_change (icon_hbox, 1);
item = NULL;
}
static void
on_4bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox)
{
on_bpp_change (icon_hbox, 4);
item = NULL;
}
static void
on_8bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox)
{
on_bpp_change (icon_hbox, 8);
item = NULL;
}
static void
on_32bpp_menu_selected (GtkWidget *item,
GtkWidget *icon_hbox)
{
on_bpp_change (icon_hbox, 32);
item = NULL;
}

View file

@ -0,0 +1,35 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ICO_DIALOG_H__
#define __ICO_DIALOG_H__
GtkWidget * ico_specs_dialog_new (gint num_layers);
void ico_specs_dialog_add_icon (GtkWidget *dialog,
gint32 layer,
gint layer_num);
void ico_specs_dialog_update_icon_preview (GtkWidget *dialog,
gint32 layer,
gint bpp);
#endif

537
plug-ins/winicon/icoload.c Normal file
View file

@ -0,0 +1,537 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
/* #define ICO_DBG */
#include "main.h"
#include "libgimp/stdplugins-intl.h"
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
#define A_VAL(p) ((guchar *)(p))[0]
#define R_VAL(p) ((guchar *)(p))[1]
#define G_VAL(p) ((guchar *)(p))[2]
#define B_VAL(p) ((guchar *)(p))[3]
#elif (G_BYTE_ORDER == G_LITTLE_ENDIAN)
#define A_VAL(p) ((guchar *)(p))[3]
#define R_VAL(p) ((guchar *)(p))[2]
#define G_VAL(p) ((guchar *)(p))[1]
#define B_VAL(p) ((guchar *)(p))[0]
#endif
static gint ico_read_int8 (FILE *fp, guint8 *data, gint count);
static gint ico_read_int16 (FILE *fp, guint16 *data, gint count);
static gint ico_read_int32 (FILE *fp, guint32 *data, gint count);
static gboolean ico_init (const gchar *filename, MsIcon *ico);
static void ico_read_entry (MsIcon *ico, MsIconEntry* entry);
static void ico_read_data (MsIcon *ico, gint icon_num);
static void ico_load (MsIcon *ico);
static gint32 ico_to_gimp (MsIcon *ico);
static gint
ico_read_int32 (FILE *fp,
guint32 *data,
gint count)
{
gint i, total;
total = count;
if (count > 0)
{
ico_read_int8 (fp, (guint8*) data, count * 4);
for (i = 0; i < count; i++)
data[i] = GUINT32_FROM_LE (data[i]);
}
return total * 4;
}
static gint
ico_read_int16 (FILE *fp,
guint16 *data,
gint count)
{
gint i, total;
total = count;
if (count > 0)
{
ico_read_int8 (fp, (guint8*) data, count * 2);
for (i = 0; i < count; i++)
data[i] = GUINT16_FROM_LE (data[i]);
}
return total * 2;
}
static gint
ico_read_int8 (FILE *fp,
guint8 *data,
gint count)
{
gint total;
gint bytes;
total = count;
while (count > 0)
{
bytes = fread ((gchar *) data, sizeof (gchar), count, fp);
if (bytes <= 0) /* something bad happened */
break;
count -= bytes;
data += bytes;
}
return total;
}
static gboolean
ico_init (const gchar *filename,
MsIcon *ico)
{
memset (ico, 0, sizeof (MsIcon));
if (! (ico->fp = fopen (filename, "r")))
{
g_message (_("Could not open '%s' for reading: %s"),
gimp_filename_to_utf8 (filename), g_strerror (errno));
return FALSE;
}
ico->filename = filename;
ico->cp += ico_read_int16 (ico->fp, &ico->reserved, 1);
ico->cp += ico_read_int16 (ico->fp, &ico->resource_type, 1);
/* Icon files use 1 as resource type, that's what I wrote this for.
From descriptions on the web it seems as if this loader should
also be able to handle Win 3.11 - Win 95 cursor files (.cur),
which use resource type 2. I haven't tested this though. */
if (ico->reserved != 0 ||
(ico->resource_type != 1 && ico->resource_type != 2))
{
ico_cleanup (ico);
return FALSE;
}
return TRUE;
}
static void
ico_read_entry (MsIcon *ico,
MsIconEntry *entry)
{
if (!ico || !entry)
return;
ico->cp += ico_read_int8 (ico->fp, &entry->width, 1);
ico->cp += ico_read_int8 (ico->fp, &entry->height, 1);
ico->cp += ico_read_int8 (ico->fp, &entry->num_colors, 1);
ico->cp += ico_read_int8 (ico->fp, &entry->reserved, 1);
ico->cp += ico_read_int16 (ico->fp, &entry->num_planes, 1);
ico->cp += ico_read_int16 (ico->fp, &entry->bpp, 1);
ico->cp += ico_read_int32 (ico->fp, &entry->size, 1);
ico->cp += ico_read_int32 (ico->fp, &entry->offset, 1);
D(("Read entry with w: "
"%i, h: %i, num_colors: %i, bpp: %i, size %i, offset %i\n",
entry->width, entry->height, entry->num_colors, entry->bpp,
entry->size, entry->offset));
}
static void
ico_read_data (MsIcon *ico,
gint icon_num)
{
MsIconData *data;
MsIconEntry *entry;
gint length;
if (!ico)
return;
D(("Reading data for icon %i ------------------------------\n", icon_num));
entry = &ico->icon_dir[icon_num];
data = &ico->icon_data[icon_num];
ico->cp = entry->offset;
if (fseek (ico->fp, entry->offset, SEEK_SET) < 0)
return;
D((" starting at offset %i\n", entry->offset));
ico->cp += ico_read_int32 (ico->fp, &data->header_size, 1);
ico->cp += ico_read_int32 (ico->fp, &data->width, 1);
ico->cp += ico_read_int32 (ico->fp, &data->height, 1);
ico->cp += ico_read_int16 (ico->fp, &data->planes, 1);
ico->cp += ico_read_int16 (ico->fp, &data->bpp, 1);
ico->cp += ico_read_int32 (ico->fp, &data->compression, 1);
ico->cp += ico_read_int32 (ico->fp, &data->image_size, 1);
ico->cp += ico_read_int32 (ico->fp, &data->x_res, 1);
ico->cp += ico_read_int32 (ico->fp, &data->y_res, 1);
ico->cp += ico_read_int32 (ico->fp, &data->used_clrs, 1);
ico->cp += ico_read_int32 (ico->fp, &data->important_clrs, 1);
D((" header size %i, "
"w %i, h %i, planes %i, size %i, bpp %i, used %i, imp %i.\n",
data->header_size, data->width, data->height,
data->planes, data->image_size, data->bpp,
data->used_clrs, data->important_clrs));
if (data->bpp <= 8)
{
if (data->used_clrs == 0)
data->used_clrs = (1 << data->bpp);
D((" allocating a %i-slot palette for %i bpp.\n",
data->used_clrs, data->bpp));
data->palette = g_new0 (guint32, data->used_clrs);
ico->cp += ico_read_int32 (ico->fp, data->palette, data->used_clrs);
}
data->xor_map = ico_alloc_map (entry->width, entry->height,
data->bpp, &length);
ico->cp += ico_read_int8 (ico->fp, data->xor_map, length);
D((" length of xor_map: %i\n", length));
/* Read in and_map. It's padded out to 32 bits per line: */
data->and_map = ico_alloc_map (entry->width, entry->height, 1, &length);
ico->cp += ico_read_int8 (ico->fp, data->and_map, length);
D((" length of and_map: %i\n", length));
}
static void
ico_load (MsIcon *ico)
{
gint i;
if (!ico)
return;
ico->cp += ico_read_int16 (ico->fp, &ico->icon_count, 1);
ico->icon_dir = g_new0 (MsIconEntry, ico->icon_count);
ico->icon_data = g_new0 (MsIconData, ico->icon_count);
D(("*** %s: Microsoft icon file, containing %i icon(s)\n",
ico->filename, ico->icon_count));
for (i = 0; i < ico->icon_count; i++)
ico_read_entry(ico, &ico->icon_dir[i]);
for (i = 0; i < ico->icon_count; i++)
ico_read_data(ico, i);
}
gint
ico_get_bit_from_data (guint8 *data,
gint line_width,
gint bit)
{
gint line;
gint width32;
gint offset;
gint result;
/* width per line in multiples of 32 bits */
width32 = (line_width % 32 == 0 ? line_width/32 : line_width/32 + 1);
line = bit / line_width;
offset = bit % line_width;
result = (data[line * width32 * 4 + offset/8] & (1 << (7 - (bit % 8))));
return (result ? 1 : 0);
}
gint
ico_get_nibble_from_data (guint8 *data,
gint line_width,
gint nibble)
{
gint line;
gint width32;
gint offset;
gint result;
/* width per line in multiples of 32 bits */
width32 = (line_width % 8 == 0 ? line_width/8 : line_width/8 + 1);
line = nibble / line_width;
offset = nibble % line_width;
result = (data[line * width32 * 4 + offset/2] & (0x0F << (4 * (1 - nibble % 2))));
if (nibble % 2 == 0)
result = result >> 4;
return result;
}
gint
ico_get_byte_from_data (guint8 *data,
gint line_width,
gint byte)
{
gint line;
gint width32;
gint offset;
/* width per line in multiples of 32 bits */
width32 = (line_width % 4 == 0 ? line_width/4 : line_width/4 + 1);
line = byte / line_width;
offset = byte % line_width;
return data[line * width32 * 4 + offset];
}
static gint32
ico_to_gimp (MsIcon *ico)
{
gint icon_nr, x, y, w, h, max_w, max_h;
guint8 *xor_map;
guint8 *and_map;
guint32 *palette;
MsIconData *idata;
MsIconEntry *ientry;
gint32 image, layer, first_layer = -1;
const char *layer_name = N_("Icon #%i");
char s[MAXLEN];
guint32 *dest_vec;
GimpDrawable *drawable;
/* Do a quick scan of the icons in the file to find the
largest icon contained ... */
max_w = 0; max_h = 0;
for (icon_nr = 0; icon_nr < ico->icon_count; icon_nr++)
{
if (ico->icon_dir[icon_nr].width > max_w)
max_w = ico->icon_dir[icon_nr].width;
if (ico->icon_dir[icon_nr].height > max_h)
max_h = ico->icon_dir[icon_nr].height;
}
/* Allocate the Gimp image */
image = gimp_image_new (max_w, max_h, GIMP_RGB);
gimp_image_set_filename (image, ico->filename);
/* Scan icons again and set up a layer for each icon */
for (icon_nr = 0; icon_nr < ico->icon_count; icon_nr++)
{
GimpPixelRgn pixel_rgn;
if (interactive_ico)
gimp_progress_update ((gdouble) icon_nr / (gdouble) ico->icon_count);
w = ico->icon_dir[icon_nr].width;
h = ico->icon_dir[icon_nr].height;
palette = ico->icon_data[icon_nr].palette;
xor_map = ico->icon_data[icon_nr].xor_map;
and_map = ico->icon_data[icon_nr].and_map;
idata = &ico->icon_data[icon_nr];
ientry = &ico->icon_dir[icon_nr];
g_snprintf (s, MAXLEN, gettext (layer_name), icon_nr + 1);
layer = gimp_layer_new (image, s, w, h,
GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
if (first_layer == -1)
first_layer = layer;
gimp_image_add_layer (image, layer, icon_nr);
drawable = gimp_drawable_get (layer);
dest_vec = g_malloc (w * h * 4);
switch (idata->bpp)
{
case 1:
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
guint32 color = palette[ico_get_bit_from_data (xor_map,
w, y * w + x)];
guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
B_VAL (dest) = R_VAL (&color);
G_VAL (dest) = G_VAL (&color);
R_VAL (dest) = B_VAL (&color);
if (ico_get_bit_from_data (and_map, w, y*w + x))
A_VAL (dest) = 0;
else
A_VAL (dest) = 255;
}
break;
case 4:
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
guint32 color = palette[ico_get_nibble_from_data (xor_map,
w, y * w + x)];
guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
B_VAL (dest) = R_VAL (&color);
G_VAL (dest) = G_VAL (&color);
R_VAL (dest) = B_VAL (&color);
if (ico_get_bit_from_data (and_map, w, y*w + x))
A_VAL (dest) = 0;
else
A_VAL (dest) = 255;
}
break;
case 8:
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
guint32 color = palette[ico_get_byte_from_data (xor_map,
w, y * w + x)];
guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
B_VAL (dest) = R_VAL (&color);
G_VAL (dest) = G_VAL (&color);
R_VAL (dest) = B_VAL (&color);
if (ico_get_bit_from_data (and_map, w, y*w + x))
A_VAL (dest) = 0;
else
A_VAL (dest) = 255;
}
break;
default:
{
int bytespp = idata->bpp/8;
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
R_VAL(dest) = xor_map[(y * w + x) * bytespp];
G_VAL(dest) = xor_map[(y * w + x) * bytespp + 1];
B_VAL(dest) = xor_map[(y * w + x) * bytespp + 2];
if (idata->bpp < 32)
{
if (ico_get_bit_from_data (and_map, w, y*w + x))
A_VAL (dest) = 0;
else
A_VAL (dest) = 255;
}
else
{
A_VAL (dest) = xor_map[(y * w + x) * bytespp + 3];
}
}
}
}
gimp_pixel_rgn_init (&pixel_rgn, drawable,
0, 0, drawable->width, drawable->height,
TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, (guchar*) dest_vec,
0, 0, drawable->width, drawable->height);
g_free(dest_vec);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
}
gimp_image_set_active_layer (image, first_layer);
if (interactive_ico)
gimp_progress_update (1.0);
return image;
}
gint32
LoadICO (const gchar *filename)
{
gint32 image_ID;
MsIcon ico;
if (interactive_ico)
{
guchar *temp = g_strdup_printf (_("Loading %s:"),
gimp_filename_to_utf8 (filename));
gimp_progress_init (temp);
g_free (temp);
}
if (! ico_init (filename, &ico))
return -1;
ico_load (&ico);
if ( (image_ID = ico_to_gimp (&ico)) < 0)
{
ico_cleanup (&ico);
return -1;
}
ico_cleanup (&ico);
D(("*** icon successfully loaded.\n\n"));
return image_ID;
}

View file

@ -0,0 +1,33 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ICO_LOAD_H__
#define __ICO_LOAD_H__
gint ico_get_bit_from_data (guint8 *data, gint line_width, gint bit);
gint ico_get_nibble_from_data (guint8 *data, gint line_width, gint nibble);
gint ico_get_byte_from_data (guint8 *data, gint line_width, gint byte);
gint32 LoadICO (const gchar *file_name);
#endif

798
plug-ins/winicon/icosave.c Normal file
View file

@ -0,0 +1,798 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
/* #define ICO_DBG */
#include "main.h"
#include "icoload.h"
#include "icodialog.h"
#include "libgimp/stdplugins-intl.h"
static gint ico_write_int8 (FILE *fp, guint8 *data, gint count);
static gint ico_write_int16 (FILE *fp, guint16 *data, gint count);
static gint ico_write_int32 (FILE *fp, guint32 *data, gint count);
static gint * ico_show_icon_dialog (gint32 image_ID, gint *num_icons);
/* Helpers to set bits in a *cleared* data chunk */
static void ico_set_bit_in_data (guint8 *data, gint line_width,
gint bit_num, gint bit_val);
static void ico_set_nibble_in_data (guint8 *data, gint line_width,
gint nibble_num, gint nibble_val);
static void ico_set_byte_in_data (guint8 *data, gint line_width,
gint byte_num, gint byte_val);
static gint
ico_write_int32 (FILE *fp,
guint32 *data,
gint count)
{
gint i, total;
total = count;
if (count > 0)
{
for (i = 0; i < count; i++)
data[i] = GUINT32_FROM_LE (data[i]);
ico_write_int8 (fp, (guint8*) data, count * 4);
}
return total * 4;
}
static gint
ico_write_int16 (FILE *fp,
guint16 *data,
gint count)
{
gint i, total;
total = count;
if (count > 0)
{
for (i = 0; i < count; i++)
data[i] = GUINT16_FROM_LE (data[i]);
ico_write_int8 (fp, (guint8*) data, count * 2);
}
return total * 2;
}
static gint
ico_write_int8 (FILE *fp,
guint8 *data,
gint count)
{
gint total;
gint bytes;
total = count;
while (count > 0)
{
bytes = fwrite ((gchar *) data, sizeof (gchar), count, fp);
if (bytes <= 0) /* something bad happened */
break;
count -= bytes;
data += bytes;
}
return total;
}
static gint*
ico_show_icon_dialog (gint32 image_ID,
gint *num_icons)
{
GtkWidget *dialog, *hbox;
GtkWidget *icon_optionmenu;
gint *layers, *icon_depths = NULL;
gint num_layers, i, num_colors;
gboolean uses_alpha_values;
gchar key[MAXLEN];
*num_icons = 0;
gimp_ui_init ("winicon", TRUE);
layers = gimp_image_get_layers (image_ID, &num_layers);
dialog = ico_specs_dialog_new (num_layers);
for (i = 0; i < num_layers; i++)
{
/* if (gimp_layer_get_visible(layers[i])) */
ico_specs_dialog_add_icon (dialog, layers[i], i);
}
/* Scale the thing to approximately fit its content, but not too large ... */
gtk_window_set_default_size (GTK_WINDOW (dialog),
350,
(num_layers > 5 ? 500 : num_layers * 100));
icon_depths = g_object_get_data (G_OBJECT (dialog), "icon_depths");
/* Limit the color depths to values that don't cause any color loss --
the user should pick these anyway, so we can save her some time.
If the user wants to lose some colors, the settings can always be changed
in the dialog: */
for (i = 0; i < num_layers; i++)
{
num_colors = ico_get_layer_num_colors (layers[i], &uses_alpha_values);
g_snprintf (key, MAXLEN, "layer_%i_hbox", layers[i]);
hbox = g_object_get_data (G_OBJECT (dialog), key);
icon_optionmenu = g_object_get_data (G_OBJECT(hbox), "icon_optionmenu");
if (!uses_alpha_values)
{
if (num_colors <= 2)
{
/* Let's suggest monochrome */
icon_depths[i] = 1;
icon_depths[num_layers + i] = 1;
ico_specs_dialog_update_icon_preview (dialog, layers[i], 2);
gtk_option_menu_set_history (GTK_OPTION_MENU (icon_optionmenu), 0);
}
else if (num_colors <= 16)
{
/* Let's suggest 4bpp */
icon_depths[i] = 4;
icon_depths[num_layers + i] = 4;
ico_specs_dialog_update_icon_preview (dialog, layers[i], 4);
gtk_option_menu_set_history (GTK_OPTION_MENU (icon_optionmenu), 1);
}
else if (num_colors <= 256)
{
/* Let's suggest 8bpp */
icon_depths[i] = 8;
icon_depths[num_layers + i] = 8;
ico_specs_dialog_update_icon_preview (dialog, layers[i], 8);
gtk_option_menu_set_history (GTK_OPTION_MENU (icon_optionmenu), 2);
}
}
/* Otherwise, or if real alpha levels are used, stick with 32bpp */
}
g_free (layers);
gtk_widget_show (dialog);
if (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK)
*num_icons = num_layers;
else
icon_depths = NULL;
gtk_widget_destroy (dialog);
return icon_depths;
}
static GimpPDBStatusType
ico_init (const gchar *filename,
MsIcon *ico,
gint num_icons)
{
memset (ico, 0, sizeof(MsIcon));
if (! (ico->fp = fopen (filename, "wb")))
{
g_message (_("Could not open '%s' for writing: %s"),
gimp_filename_to_utf8 (filename), g_strerror (errno));
return GIMP_PDB_EXECUTION_ERROR;
}
ico->filename = filename;
ico->reserved = 0;
ico->resource_type = GUINT16_FROM_LE (1);
ico->icon_count = num_icons;
ico->icon_dir = g_new0 (MsIconEntry, num_icons);
ico->icon_data = g_new0 (MsIconData, num_icons);
return GIMP_PDB_SUCCESS;
}
static void
ico_init_direntry (MsIconEntry *entry,
gint32 layer,
gint bpp)
{
/* Was calloc'd, so initialized to 0. */
entry->width = gimp_drawable_width (layer);
entry->height = gimp_drawable_height (layer);
if (bpp < 8)
entry->num_colors = (1 << bpp);
entry->num_planes = 1;
entry->bpp = bpp;
D(("Initialized entry to w %i, h %i, bpp %i\n",
gimp_drawable_width (layer), entry->width, entry->bpp));
/* We'll set size and offset when writing things out */
}
static void
ico_set_bit_in_data (guint8 *data,
gint line_width,
gint bit_num,
gint bit_val)
{
gint line;
gint width32;
gint offset;
/* width per line in multiples of 32 bits */
width32 = (line_width % 32 == 0 ? line_width/32 : line_width/32 + 1);
line = bit_num / line_width;
offset = bit_num % line_width;
bit_val = bit_val & 0x00000001;
data[line * width32 * 4 + offset/8] |= (bit_val << (7 - (bit_num % 8)));
}
static void
ico_set_nibble_in_data (guint8 *data,
gint line_width,
gint nibble_num,
gint nibble_val)
{
gint line;
gint width8;
gint offset;
/* width per line in multiples of 32 bits */
width8 = (line_width % 8 == 0 ? line_width/8 : line_width/8 + 1);
line = nibble_num / line_width;
offset = nibble_num % line_width;
nibble_val = nibble_val & 0x0000000F;
data[line * width8 * 4 + offset/2] |= (nibble_val << (4 * (1 - (nibble_num % 2))));
}
static void
ico_set_byte_in_data (guint8 *data,
gint line_width,
gint byte_num,
gint byte_val)
{
gint line;
gint width4;
gint offset;
gint byte;
/* width per line in multiples of 32 bits */
width4 = (line_width % 4 == 0 ? line_width/4 : line_width/4 + 1);
line = byte_num / line_width;
offset = byte_num % line_width;
byte = byte_val & 0x000000FF;
data[line * width4 * 4 + offset] = byte;
}
/* Create a colormap from the given buffer data */
static guint32 *
ico_create_palette(guchar *cmap,
gint num_colors,
gint num_colors_used,
gint *black_slot)
{
guchar *palette;
gint i;
palette = g_new0 (guchar, num_colors * 4);
*black_slot = -1;
for (i = 0; i < num_colors_used; i++)
{
palette[i * 4 + 2] = cmap[i * 3];
palette[i * 4 + 1] = cmap[i * 3 + 1];
palette[i * 4] = cmap[i * 3 + 2];
if ((cmap[i*3] == 0) &&
(cmap[i*3 + 1] == 0) &&
(cmap[i*3 + 2] == 0))
{
*black_slot = i;
}
}
if (*black_slot == -1)
{
if (num_colors_used == num_colors)
{
D(("WARNING -- no room for black, this shouldn't happen.\n"));
*black_slot = num_colors - 1;
palette[(num_colors-1) * 4] = 0;
palette[(num_colors-1) * 4 + 1] = 0;
palette[(num_colors-1) * 4 + 2] = 0;
}
else
{
*black_slot = num_colors_used;
}
}
return (guint32*) palette;
}
static GHashTable *
ico_create_color_to_palette_map (guint32 *palette,
gint num_colors)
{
GHashTable *hash;
gint i;
hash = g_hash_table_new (g_int_hash, g_int_equal);
for (i = 0; i < num_colors; i++)
{
gint *color, *slot;
guint8 *pixel = (guint8*) &palette[i];
color = g_new (gint, 1);
slot = g_new (gint, 1);
*color = (pixel[2] << 16 | pixel[1] << 8 | pixel[0]);
*slot = i;
g_hash_table_insert (hash, color, slot);
}
return hash;
}
static void
ico_free_hash_item (gpointer data1,
gpointer data2,
gpointer data3)
{
g_free (data1);
g_free (data2);
/* Shut up warnings: */
data3 = NULL;
}
static gint
ico_get_palette_index (GHashTable *hash,
gint red,
gint green,
gint blue)
{
gint color = 0;
gint *slot;
color = (red << 16 | green << 8 | blue);
slot = g_hash_table_lookup (hash, &color);
if (!slot)
{
return 0;
}
return *slot;
}
static void
ico_init_data (MsIcon *ico,
gint num_icon,
gint32 layer,
gint bpp)
{
MsIconEntry *entry;
MsIconData *data;
gint and_len, xor_len, palette_index, x, y;
gint num_colors = 0, num_colors_used = 0, buf_bpp, black_index;
guchar *buffer = NULL, *pixel;
guint32 *buffer32;
guchar *palette;
GHashTable *color_to_slot = NULL;
D(("Creating data structures for icon %i ------------------------\n", num_icon));
/* Shortcuts, for convenience */
entry = &ico->icon_dir[num_icon];
data = &ico->icon_data[num_icon];
/* Entries and data were calloc'd, so initialized to 0. */
data->header_size = 40;
data->width = gimp_drawable_width (layer);
data->height = 2 * gimp_drawable_height (layer);
data->planes = 1;
data->bpp = bpp;
num_colors = (1L << bpp);
D((" header size %i, w %i, h %i, planes %i, bpp %i\n",
data->header_size, data->width, data->height, data->planes, data->bpp));
/* Reduce colors in copy of image */
ico_image_get_reduced_buf (layer, bpp, &num_colors_used,
&palette, &buffer, &buf_bpp);
buffer32 = (guint32*) buffer;
/* Set up colormap and andmap when necessary: */
if (bpp <= 8)
{
/* Create a colormap */
data->palette = ico_create_palette (palette,
num_colors, num_colors_used,
&black_index);
data->palette_len = num_colors * 4;
color_to_slot = ico_create_color_to_palette_map (data->palette,
num_colors_used);
D((" created %i-slot colormap with %i colors, black at slot %i\n",
num_colors, num_colors_used, black_index));
}
/* Create and_map. It's padded out to 32 bits per line: */
data->and_map = ico_alloc_map (entry->width, entry->height, 1, &and_len);
data->and_len = and_len;
for (y = 0; y < entry->height; y++)
for (x = 0; x < entry->width; x++)
{
pixel = (guint8*) &buffer32[y * entry->width + x];
ico_set_bit_in_data (data->and_map, entry->width,
(entry->height-y-1) * entry->width + x,
(pixel[3] == 255 ? 0 : 1));
}
data->xor_map = ico_alloc_map(entry->width, entry->height, bpp, &xor_len);
data->xor_len = xor_len;
/* Now fill in the xor map */
switch (bpp)
{
case 1:
for (y = 0; y < entry->height; y++)
for (x = 0; x < entry->width; x++)
{
pixel = (guint8*) &buffer32[y * entry->width + x];
palette_index = ico_get_palette_index (color_to_slot,
pixel[0], pixel[1], pixel[2]);
if (ico_get_bit_from_data (data->and_map, entry->width,
(entry->height-y-1) * entry->width + x))
{
ico_set_bit_in_data (data->xor_map, entry->width,
(entry->height-y-1) * entry->width + x,
black_index);
}
else
{
ico_set_bit_in_data (data->xor_map, entry->width,
(entry->height-y-1) * entry->width + x,
palette_index);
}
}
break;
case 4:
for (y = 0; y < entry->height; y++)
for (x = 0; x < entry->width; x++)
{
pixel = (guint8*) &buffer32[y * entry->width + x];
palette_index = ico_get_palette_index(color_to_slot,
pixel[0], pixel[1], pixel[2]);
if (ico_get_bit_from_data (data->and_map, entry->width,
(entry->height-y-1) * entry->width + x))
{
ico_set_nibble_in_data (data->xor_map, entry->width,
(entry->height-y-1) * entry->width + x,
black_index);
}
else
{
ico_set_nibble_in_data (data->xor_map, entry->width,
(entry->height-y-1) * entry->width + x,
palette_index);
}
}
break;
case 8:
for (y = 0; y < entry->height; y++)
for (x = 0; x < entry->width; x++)
{
pixel = (guint8*) &buffer32[y * entry->width + x];
palette_index = ico_get_palette_index (color_to_slot,
pixel[0], pixel[1], pixel[2]);
if (ico_get_bit_from_data (data->and_map, entry->width,
(entry->height-y-1) * entry->width + x))
{
ico_set_byte_in_data (data->xor_map, entry->width,
(entry->height-y-1) * entry->width + x,
black_index);
}
else
{
ico_set_byte_in_data (data->xor_map, entry->width,
(entry->height-y-1) * entry->width + x,
palette_index);
}
}
break;
default:
for (y = 0; y < entry->height; y++)
for (x = 0; x < entry->width; x++)
{
pixel = (guint8*) &buffer32[y * entry->width + x];
((guint32*) data->xor_map)[(entry->height-y-1) * entry->width + x] =
((pixel[0] << 16) | (pixel[1] << 8) | pixel[2] | (pixel[3] << 24));
}
}
D((" filled and_map of length %i, xor_map of length %i\n",
data->and_len, data->xor_len));
if (color_to_slot)
{
g_hash_table_foreach (color_to_slot, ico_free_hash_item, NULL);
g_hash_table_destroy (color_to_slot);
}
g_free(palette);
g_free(buffer);
}
static void
ico_setup (MsIcon *ico,
gint32 image,
gint *icon_depths,
gint num_icons)
{
gint *layers;
gint i;
gint offset;
layers = gimp_image_get_layers(image, &num_icons);
/* Set up icon entries */
for (i = 0; i < num_icons; i++)
{
ico_init_direntry (&ico->icon_dir[i], layers[i], icon_depths[i]);
if (interactive_ico)
gimp_progress_update ((gdouble) i / (gdouble) num_icons * 0.3);
}
/* Set up data entries (the actual icons), and calculate each one's size */
for (i = 0; i < num_icons; i++)
{
ico_init_data (ico, i, layers[i], icon_depths[i]);
ico->icon_dir[i].size =
ico->icon_data[i].header_size +
ico->icon_data[i].palette_len +
ico->icon_data[i].xor_len +
ico->icon_data[i].and_len;
if (interactive_ico)
gimp_progress_update (0.3 + (gdouble) i / (gdouble) num_icons * 0.3);
}
/* Finally, calculate offsets for each icon and store them in each entry */
offset = 3 * sizeof (guint16) + ico->icon_count * sizeof (MsIconEntry);
for (i = 0; i < num_icons; i++)
{
ico->icon_dir[i].offset = offset;
offset += ico->icon_dir[i].size;
if (interactive_ico)
gimp_progress_update (0.6 + (gdouble) i / (gdouble) num_icons * 0.3);
}
if (interactive_ico)
gimp_progress_update (1.0);
g_free(layers);
}
static GimpPDBStatusType
ico_save (MsIcon *ico)
{
MsIconEntry *entry;
MsIconData *data;
int i;
ico->cp += ico_write_int16 (ico->fp, &ico->reserved, 3);
for (i = 0; i < ico->icon_count; i++)
{
entry = &ico->icon_dir[i];
ico->cp += ico_write_int8 (ico->fp, (guint8*) entry, 4);
ico->cp += ico_write_int16 (ico->fp, &entry->num_planes, 2);
ico->cp += ico_write_int32 (ico->fp, &entry->size, 2);
}
for (i = 0; i < ico->icon_count; i++)
{
data = &ico->icon_data[i];
ico->cp += ico_write_int32 (ico->fp, (guint32*) data, 3);
ico->cp += ico_write_int16 (ico->fp, &data->planes, 2);
ico->cp += ico_write_int32 (ico->fp, &data->compression, 6);
if (data->palette)
ico->cp += ico_write_int32 (ico->fp,
data->palette, data->palette_len / 4);
ico->cp += ico_write_int8 (ico->fp, data->xor_map, data->xor_len);
ico->cp += ico_write_int8 (ico->fp, data->and_map, data->and_len);
}
return GIMP_PDB_SUCCESS;
}
static void
ico_sync_image_to_ico (gint32 image,
gint *icon_depths)
{
gint *layers;
gint i, num_layers;
layers = gimp_image_get_layers(image, &num_layers);
for (i = 0; i < num_layers; i++)
{
if (icon_depths[i] < icon_depths[num_layers + i])
{
D(("Layer '%s' was reduced to %i bpp -- updating source image.\n",
gimp_layer_get_name (layers[i]), icon_depths[i]));
ico_image_reduce_layer_bpp (layers[i], icon_depths[i]);
}
}
g_free(layers);
}
static gboolean
ico_layers_too_big (gint32 image)
{
gint *layers;
gint i, num_layers;
layers = gimp_image_get_layers (image, &num_layers);
for (i = 0; i < num_layers; i++)
{
if ((gimp_drawable_width (layers[i]) > 255) ||
(gimp_drawable_height (layers[i]) > 255))
{
g_free (layers);
return TRUE;
}
}
g_free (layers);
return FALSE;
}
GimpPDBStatusType
SaveICO (const gchar *filename,
gint32 image)
{
MsIcon ico;
gint *icon_depths = NULL;
gint num_icons;
GimpPDBStatusType exit_state;
D(("*** Saving Microsoft icon file %s\n", filename));
if (ico_layers_too_big(image))
{
g_message (_("Windows icons cannot be higher or wider than 255 pixels."));
return GIMP_PDB_EXECUTION_ERROR;
}
if (gimp_image_base_type (image) != GIMP_RGB)
{
if (! gimp_image_convert_rgb (image))
return GIMP_PDB_EXECUTION_ERROR;
}
/* First, set up the icon specs dialog and show it: */
if ((icon_depths = ico_show_icon_dialog(image, &num_icons)) == NULL)
return GIMP_PDB_CANCEL;
if (interactive_ico)
{
guchar *temp_buf = g_strdup_printf (_("Saving %s:"),
gimp_filename_to_utf8 (filename));
gimp_progress_init (temp_buf);
g_free (temp_buf);
}
/* Okay, let's actually save the thing with the depths the
user specified. */
if ((exit_state = ico_init (filename, &ico, num_icons) != GIMP_PDB_SUCCESS))
return exit_state;
D(("icon initialized ...\n"));
ico_setup (&ico, image, icon_depths, num_icons);
D(("icon data created ...\n"));
if ( (exit_state = ico_save(&ico)) == GIMP_PDB_SUCCESS)
{
ico_sync_image_to_ico (image, icon_depths);
}
D(("*** icon saved, exit status %i.\n\n", exit_state));
ico_cleanup (&ico);
g_free (icon_depths);
return exit_state;
}

View file

@ -0,0 +1,30 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ICO_SAVE_H__
#define __ICO_SAVE_H__
GimpPDBStatusType SaveICO (const gchar *file_name,
gint32 image_ID);
#endif

526
plug-ins/winicon/main.c Normal file
View file

@ -0,0 +1,526 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
/* #define ICO_DBG */
#include "main.h"
#include "icoload.h"
#include "icosave.h"
#include "libgimp/stdplugins-intl.h"
gboolean interactive_ico = FALSE;
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
GimpPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN ()
static void
query (void)
{
static GimpParamDef load_args[] =
{
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
{ GIMP_PDB_STRING, "raw_filename", "The name entered" }
};
static GimpParamDef load_return_vals[] =
{
{ GIMP_PDB_IMAGE, "image", "Output image" },
};
static GimpParamDef save_args[] =
{
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
{ GIMP_PDB_IMAGE, "image", "Input image" },
{ GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
{ GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
{ GIMP_PDB_STRING, "raw_filename", "The name entered" },
};
gimp_install_procedure ("file_ico_load",
"Loads files of Windows ICO file format",
"Loads files of Windows ICO file format",
"Christian Kreibich <christian@whoop.org>",
"Christian Kreibich <christian@whoop.org>",
"2002",
N_("<Load>/ICO"),
NULL,
GIMP_PLUGIN,
G_N_ELEMENTS (load_args),
G_N_ELEMENTS (load_return_vals),
load_args, load_return_vals);
gimp_install_procedure ("file_ico_save",
"Saves files in Windows ICO file format",
"Saves files in Windows ICO file format",
"Christian Kreibich <christian@whoop.org>",
"Christian Kreibich <christian@whoop.org>",
"2002",
N_("<Save>/ICO"),
"INDEXEDA, GRAYA, RGBA",
GIMP_PLUGIN,
G_N_ELEMENTS (save_args), 0,
save_args, NULL);
gimp_register_magic_load_handler ("file_ico_load",
"ico,wico",
"",
"0,string,\\000\\001\\000\\000,0,string,\\000\\002\\000\\000");
gimp_register_save_handler ("file_ico_save",
"ico,wico",
"");
}
static void
run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
{
static GimpParam values[2];
gint32 image_ID;
gint32 drawable_ID;
GimpRunMode run_mode;
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpExportReturn export = GIMP_EXPORT_CANCEL;
INIT_I18N ();
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, "file_ico_load") == 0)
{
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
interactive_ico = TRUE;
break;
case GIMP_RUN_NONINTERACTIVE:
interactive_ico = FALSE;
if (nparams != 3)
status = GIMP_PDB_CALLING_ERROR;
break;
default:
break;
}
if (status == GIMP_PDB_SUCCESS)
{
image_ID = LoadICO (param[1].data.d_string);
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, "file_ico_save") == 0)
{
gchar *file_name;
image_ID = param[1].data.d_int32;
drawable_ID = param[2].data.d_int32;
file_name = param[3].data.d_string;
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
interactive_ico = TRUE;
break;
case GIMP_RUN_NONINTERACTIVE:
interactive_ico = FALSE;
/* Make sure all the arguments are there! */
if (nparams < 5)
status = GIMP_PDB_CALLING_ERROR;
break;
case GIMP_RUN_WITH_LAST_VALS:
interactive_ico = FALSE;
break;
default:
break;
}
if (status == GIMP_PDB_SUCCESS)
{
status = SaveICO (file_name, image_ID);
}
if (export == GIMP_EXPORT_EXPORT)
gimp_image_delete (image_ID);
}
else
{
status = GIMP_PDB_CALLING_ERROR;
}
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
}
guint8 *
ico_alloc_map(gint width,
gint height,
gint bpp,
gint *length)
{
gint len = 0;
guint8 *map = NULL;
switch (bpp)
{
case 1:
if ((width % 32) == 0)
len = (width * height / 8);
else
len = 4 * ((width/32 + 1) * height);
break;
case 4:
if ((width % 8) == 0)
len = (width * height / 2);
else
len = 4 * ((width/8 + 1) * height);
break;
case 8:
if ((width % 4) == 0)
len = width * height;
else
len = 4 * ((width/4 + 1) * height);
break;
default:
len = width * height * (bpp/8);
}
*length = len;
map = g_new0(guint8, len);
return map;
}
static gboolean
ico_cmap_contains_black (guchar *cmap,
gint num_colors)
{
gint i;
for (i = 0; i < num_colors; i++)
{
if ((cmap[3*i] == 0) &&
(cmap[3*i+1] == 0) &&
(cmap[3*i+2] == 0))
{
return TRUE;
}
}
return FALSE;
}
void
ico_image_reduce_layer_bpp (guint32 layer,
gint bpp)
{
GimpPixelRgn src_pixel_rgn, dst_pixel_rgn;
gint32 tmp_image;
gint32 tmp_layer;
gint w, h;
guchar *buffer;
w = gimp_drawable_width(layer);
h = gimp_drawable_height(layer);
if (bpp <= 8)
{
buffer = g_new (guchar, w * h * 4);
tmp_image = gimp_image_new (gimp_drawable_width (layer),
gimp_drawable_height (layer),
GIMP_RGB);
tmp_layer = gimp_layer_new (tmp_image, "tmp", w, h,
GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
gimp_pixel_rgn_init (&src_pixel_rgn, gimp_drawable_get(layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get(tmp_layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h);
gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
gimp_image_add_layer (tmp_image, tmp_layer, 0);
gimp_image_convert_indexed (tmp_image,
GIMP_FS_DITHER,
GIMP_MAKE_PALETTE,
1 << bpp,
TRUE,
FALSE,
"dummy");
gimp_image_convert_rgb (tmp_image);
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get (tmp_layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_get_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
gimp_pixel_rgn_set_rect (&src_pixel_rgn, buffer, 0, 0, w, h);
gimp_image_delete (tmp_image);
gimp_drawable_update (layer, 0, 0, w ,h);
/* WTF! What else can I do to make the layer dialog update??? */
g_free (buffer);
}
}
void
ico_image_get_reduced_buf (guint32 layer,
gint bpp,
gint *num_colors,
guchar **cmap_out,
guchar **buf_out,
gint *buf_bpp)
{
GimpPixelRgn src_pixel_rgn, dst_pixel_rgn;
gint32 tmp_image;
gint32 tmp_layer;
gint w, h;
guchar *buffer;
guchar *cmap;
gboolean result;
GimpDrawable *drawable;
w = gimp_drawable_width (layer);
h = gimp_drawable_height (layer);
*cmap_out = NULL;
*num_colors = 0;
buffer = g_new (guchar, w * h * 4);
if (bpp <= 8)
{
tmp_image = gimp_image_new (gimp_drawable_width (layer),
gimp_drawable_height (layer),
GIMP_RGB);
tmp_layer = gimp_layer_new (tmp_image, "tmp", w, h,
GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
gimp_pixel_rgn_init (&src_pixel_rgn, gimp_drawable_get(layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get(tmp_layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h);
gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
gimp_image_add_layer (tmp_image, tmp_layer, 0);
result = gimp_image_convert_indexed(tmp_image,
GIMP_FS_DITHER,
GIMP_MAKE_PALETTE,
1 << bpp,
TRUE,
FALSE,
"dummy");
cmap = gimp_image_get_cmap (tmp_image, num_colors);
if (*num_colors == (1 << bpp) &&
!ico_cmap_contains_black(cmap, *num_colors))
{
/* Damn. Windows icons with color maps need the color black.
We need to eliminate one more color to make room for black: */
result = gimp_image_convert_rgb(tmp_image);
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get(tmp_layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
result = gimp_image_convert_indexed(tmp_image,
GIMP_FS_DITHER,
GIMP_MAKE_PALETTE,
(1 << bpp) - 1,
TRUE,
FALSE,
"dummy");
}
cmap = gimp_image_get_cmap(tmp_image, num_colors);
*cmap_out = g_memdup (cmap, *num_colors * 3);
result = gimp_image_convert_rgb(tmp_image);
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get(tmp_layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_get_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
drawable = gimp_drawable_get(tmp_layer);
*buf_bpp = drawable->bpp;
gimp_image_delete(tmp_image);
}
else
{
gimp_pixel_rgn_init (&dst_pixel_rgn, gimp_drawable_get(layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_get_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
drawable = gimp_drawable_get (layer);
*buf_bpp = drawable->bpp;
}
*buf_out = buffer;
}
static void
ico_free_color_item (gpointer data1,
gpointer data2,
gpointer data3)
{
g_free (data1);
/* Shut up warnings: */
data2 = NULL;
data3 = NULL;
}
gint
ico_get_layer_num_colors (gint32 layer,
gboolean *uses_alpha_levels)
{
GimpPixelRgn pixel_rgn;
gint x, y, w, h, alpha, num_colors = 0;
guint32 *buffer = NULL, *color;
GHashTable *hash;
w = gimp_drawable_width (layer);
h = gimp_drawable_height (layer);
buffer = g_new (gint32, w * h);
gimp_pixel_rgn_init (&pixel_rgn, gimp_drawable_get (layer),
0, 0, w, h, TRUE, FALSE);
gimp_pixel_rgn_get_rect (&pixel_rgn, (guchar*) buffer, 0, 0, w, h);
hash = g_hash_table_new (g_int_hash, g_int_equal);
*uses_alpha_levels = FALSE;
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
{
color = g_new0 (guint32, 1);
*color = buffer[y * w + x];
alpha = ((guint8*) color)[3];
if (alpha != 0 && alpha != 255)
*uses_alpha_levels = TRUE;
g_hash_table_insert(hash, color, color);
}
num_colors = g_hash_table_size(hash);
g_hash_table_foreach (hash, ico_free_color_item, NULL);
g_hash_table_destroy (hash);
g_free(buffer);
return num_colors;
}
void
ico_cleanup (MsIcon *ico)
{
gint i;
if (!ico)
return;
if (ico->fp)
fclose(ico->fp);
if (ico->icon_dir)
g_free (ico->icon_dir);
if (ico->icon_data)
{
for (i = 0; i < ico->icon_count; i++)
{
g_free (ico->icon_data[i].palette);
g_free (ico->icon_data[i].xor_map);
g_free (ico->icon_data[i].and_map);
}
g_free (ico->icon_data);
}
}

115
plug-ins/winicon/main.h Normal file
View file

@ -0,0 +1,115 @@
/* The GIMP -- an 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __MAIN_H__
#define __MAIN_H__
extern gboolean interactive_ico;
#ifdef ICO_DBG
#define D(x) \
{ \
printf("ICO plugin: "); \
printf x; \
}
#else
#define D(x)
#endif
#define MAXLEN 4096
typedef struct _MsIconEntry
{
guint8 width; /* Width of icon in pixels */
guint8 height; /* Height of icon in pixels */
guint8 num_colors; /* Maximum number of colors */
guint8 reserved; /* Not used */
guint16 num_planes; /* Not used */
guint16 bpp;
guint32 size; /* Length of icon bitmap in bytes */
guint32 offset; /* Offset position of icon bitmap in file */
} MsIconEntry;
typedef struct _MsIconData
{
/* Bitmap header data */
guint32 header_size; /* = 40 Bytes */
guint32 width;
guint32 height;
guint16 planes;
guint16 bpp;
guint32 compression; /* not used for icons */
guint32 image_size; /* size of image */
guint32 x_res;
guint32 y_res;
guint32 used_clrs;
guint32 important_clrs;
guint32 *palette; /* Color palette, only if bpp <= 8. */
guint8 *xor_map; /* Icon bitmap */
guint8 *and_map; /* Display bit mask */
/* Only used when saving: */
gint palette_len;
gint xor_len;
gint and_len;
} MsIconData;
typedef struct _MsIcon
{
FILE *fp;
guint cp;
const gchar *filename;
guint16 reserved;
guint16 resource_type;
guint16 icon_count;
MsIconEntry *icon_dir;
MsIconData *icon_data;
} MsIcon;
/* Miscellaneous helper functions below: */
/* Allocates a 32-bit padded bitmap for various color depths.
Returns the allocated array directly, and the length of the
array in the len pointer */
guint8 * ico_alloc_map (gint width,
gint height,
gint bpp,
gint *len);
void ico_image_reduce_layer_bpp (guint32 layer,
gint bpp);
void ico_image_get_reduced_buf (guint32 layer,
gint bpp,
gint *num_colors,
guchar **cmap,
guchar **buffer,
gint *buf_bpp);
gint ico_get_layer_num_colors (gint32 layer,
gboolean *uses_alpha_levels);
void ico_cleanup (MsIcon *ico);
#endif

View file

@ -1,6 +1,7 @@
2004-04-15 Sven Neumann <sven@gimp.org>
* POTFILES.in: removed plug-ins/common/gicon.c.
* POTFILES.in: removed plug-ins/common/gicon.c; added new files
for winicon plug-in.
2004-04-13 Dmitry G. Mastrukov <dmitry@taurussoft.org>

View file

@ -248,5 +248,9 @@ plug-ins/sel2path/pxl-outline.c
plug-ins/sel2path/sel2path.c
plug-ins/sgi/sgi.c
plug-ins/twain/twain.c
plug-ins/winicon/icodialog.c
plug-ins/winicon/icoload.c
plug-ins/winicon/icosave.c
plug-ins/winicon/main.c
plug-ins/winsnap/winsnap.c
plug-ins/xjt/xjt.c