gimp/app/gui/palette-import-dialog.c

1127 lines
30 KiB
C
Raw Normal View History

/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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 <gtk/gtk.h>
Makefile.am configure.in added stuff for the new library below. 2001-01-23 Michael Natterer <mitch@gimp.org> * Makefile.am * configure.in * gimptool.in: added stuff for the new library below. * libgimpcolor/.cvsignore * libgimpcolor/Makefile.am * libgimpcolor/gimpcolor.h * libgimpcolor/gimpcolorspace.c * libgimpcolor/gimpcolorspace.h * libgimpcolor/gimpcolortypes.h * libgimpcolor/gimphsv.c * libgimpcolor/gimphsv.h * libgimpcolor/gimprgb.c * libgimpcolor/gimprgb.h: new shared library which both the app and plug-ins link against. The library depends only on glib. * libgimpcolor/gimpcolor.def * libgimpcolor/makefile.mingw.in * libgimpcolor/makefile.msc: added Win32 build files which definitely don't work. * libgimp/Makefile.am * libgimp/gimpcolor.[ch] * libgimp/gimpcolorspace.[ch]: removed. * libgimp/gimp.h * libgimp/gimpadaptivesupersample.c * libgimp/gimpbilinear.c * libgimp/gimppalette.c * libgimp/gimptypes.h: include the stuff from libgimpcolor. Plug-Ins don't need to include <libgimpcolor/gimpcolor.h> explicitely. LibGimp depends on libgimpcolor and thus also includes it's headers. * libgimp/gimp.def * libgimp/makefile.mingw.in: fiddled around with Win32 stuff... * app/Makefile.am: link against libgimpcolor.la * app/apptypes.h: include "libgimpcolor/gimpcolortypes.h" * app/asupsample.c * app/channels_dialog.c * app/colormap_dialog.c * app/commands.c * app/convert.c * app/devices.c * app/disp_callbacks.c * app/drawable.c * app/gimpcontext.c * app/gimpdnd.c * app/gimpimage.c * app/gimppalette.c * app/gimprc.c * app/gradient.c * app/libgimp_glue.c * app/palette.c * app/palette_import.c * app/qmask.c * app/xcf.c * app/tools/paint_core.c * app/tools/paintbrush.c * app/tools/pencil.c: include "libgimpcolor/gimpcolor.h" before all gimp includes because it's a standalone library. * plug-ins/FractalExplorer/Makefile.am * plug-ins/Lighting/Makefile.am * plug-ins/MapObject/Makefile.am * plug-ins/bmp/Makefile.am * plug-ins/common/Makefile.am * plug-ins/common/mkgen.pl * plug-ins/dbbrowser/Makefile.am * plug-ins/faxg3/Makefile.am * plug-ins/fits/Makefile.am * plug-ins/flame/Makefile.am * plug-ins/fp/Makefile.am * plug-ins/gap/Makefile.am * plug-ins/gdyntext/Makefile.am * plug-ins/gfig/Makefile.am * plug-ins/gflare/Makefile.am * plug-ins/gfli/Makefile.am * plug-ins/gimpressionist/Makefile.am * plug-ins/helpbrowser/Makefile.am * plug-ins/ifscompose/Makefile.am * plug-ins/imagemap/Makefile.am * plug-ins/maze/Makefile.am * plug-ins/mosaic/Makefile.am * plug-ins/pagecurl/Makefile.am * plug-ins/print/Makefile.am * plug-ins/rcm/Makefile.am * plug-ins/script-fu/Makefile.am * plug-ins/sel2path/Makefile.am * plug-ins/sgi/Makefile.am * plug-ins/webbrowser/Makefile.am * plug-ins/xjt/Makefile.am: add libgimpcolor.la to LDADD. * INSTALL: don't recommend to --disable-shared for development. * TODO.xml: increased some percentages, added plug-in help stuff.
2001-01-24 02:49:44 +08:00
#include "libgimpcolor/gimpcolor.h"
#include "apptypes.h"
#include "appenv.h"
#include "gimage.h"
#include "gimpcontext.h"
#include "gimpimage.h"
#include "gimppalette.h"
#include "gimpui.h"
#include "gradient.h"
#include "gradient_header.h"
#include "gradient_select.h"
#include "palette.h"
#include "palette_import.h"
#include "pixel_region.h"
#include "temp_buf.h"
#include "pdb/procedural_db.h"
#include "libgimp/gimpintl.h"
/* New palette code... */
#define IMPORT_PREVIEW_WIDTH 80
#define IMPORT_PREVIEW_HEIGHT 80
#define MAX_IMAGE_COLORS (10000*2)
typedef enum
{
GRAD_IMPORT = 0,
IMAGE_IMPORT = 1,
INDEXED_IMPORT = 2
} ImportType;
typedef struct _ImportDialog ImportDialog;
struct _ImportDialog
{
GtkWidget *dialog;
GtkWidget *preview;
GtkWidget *entry;
GtkWidget *select_area;
GtkWidget *select;
GtkWidget *image_list;
GtkWidget *image_menu_item_image;
GtkWidget *image_menu_item_indexed;
GtkWidget *image_menu_item_gradient;
GtkWidget *optionmenu1_menu;
GtkWidget *type_option;
GtkWidget *threshold_scale;
GtkWidget *threshold_text;
GtkAdjustment *threshold;
GtkAdjustment *sample;
ImportType import_type;
GimpImage *gimage;
};
static ImportDialog *import_dialog = NULL;
/*****************************************************************************/
/* palette import dialog functions *****************************************/
/* functions to create & update the import dialog's gradient selection *****/
static void
palette_import_select_grad_callback (GtkWidget *widget,
gpointer data)
{
/* Popup grad edit box .... */
gradient_dialog_create ();
}
static void
palette_import_fill_grad_preview (GtkWidget *preview,
gradient_t *gradient)
{
guchar buffer[3*IMPORT_PREVIEW_WIDTH];
gint loop;
guchar *p = buffer;
gdouble dx, cur_x;
GimpRGB color;
dx = 1.0/ (IMPORT_PREVIEW_WIDTH - 1);
cur_x = 0;
for (loop = 0 ; loop < IMPORT_PREVIEW_WIDTH; loop++)
{
gradient_get_color_at (gradient, cur_x, &color);
*p++ = (guchar) (color.r * 255.999);
*p++ = (guchar) (color.g * 255.999);
*p++ = (guchar) (color.b * 255.999);
cur_x += dx;
}
for (loop = 0 ; loop < IMPORT_PREVIEW_HEIGHT; loop++)
{
gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, loop,
IMPORT_PREVIEW_WIDTH);
}
gtk_widget_draw (preview, NULL);
}
static void
palette_import_gradient_update (GimpContext *context,
gradient_t *gradient,
gpointer data)
{
if (import_dialog && import_dialog->import_type == GRAD_IMPORT)
{
/* redraw gradient */
palette_import_fill_grad_preview (import_dialog->preview, gradient);
gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), gradient->name);
}
}
/* functions to create & update the import dialog's image selection ********/
static void
palette_import_gimlist_cb (gpointer im,
gpointer data)
{
GSList **l;
l = (GSList**) data;
*l = g_slist_prepend (*l, im);
}
static void
palette_import_gimlist_indexed_cb (gpointer im,
gpointer data)
{
GimpImage *gimage = GIMP_IMAGE (im);
GSList **l;
if (gimp_image_base_type (gimage) == INDEXED)
{
l = (GSList**) data;
*l = g_slist_prepend (*l, im);
}
}
static void
palette_import_update_image_preview (GimpImage *gimage)
{
TempBuf *preview_buf;
gchar *src;
gchar *buf;
gint x, y, has_alpha;
gint sel_width, sel_height;
gint pwidth, pheight;
import_dialog->gimage = gimage;
/* Calculate preview size */
sel_width = gimage->width;
sel_height = gimage->height;
if (sel_width > sel_height)
{
pwidth = MIN (sel_width, IMPORT_PREVIEW_WIDTH);
pheight = sel_height * pwidth / sel_width;
}
else
{
pheight = MIN (sel_height, IMPORT_PREVIEW_HEIGHT);
pwidth = sel_width * pheight / sel_height;
}
/* Min size is 2 */
preview_buf = gimp_image_construct_composite_preview (gimage,
MAX (pwidth, 2),
MAX (pheight, 2));
gtk_preview_size (GTK_PREVIEW (import_dialog->preview),
preview_buf->width,
preview_buf->height);
buf = g_new (gchar, IMPORT_PREVIEW_WIDTH * 3);
src = (gchar *) temp_buf_data (preview_buf);
has_alpha = (preview_buf->bytes == 2 || preview_buf->bytes == 4);
for (y = 0; y <preview_buf->height ; y++)
{
if (preview_buf->bytes == (1+has_alpha))
for (x = 0; x < preview_buf->width; x++)
{
buf[x*3+0] = src[x];
buf[x*3+1] = src[x];
buf[x*3+2] = src[x];
}
else
for (x = 0; x < preview_buf->width; x++)
{
gint stride = 3 + has_alpha;
buf[x*3+0] = src[x*stride+0];
buf[x*3+1] = src[x*stride+1];
buf[x*3+2] = src[x*stride+2];
}
gtk_preview_draw_row (GTK_PREVIEW (import_dialog->preview),
(guchar *)buf, 0, y, preview_buf->width);
src += preview_buf->width * preview_buf->bytes;
}
g_free (buf);
temp_buf_free (preview_buf);
gtk_widget_hide (import_dialog->preview);
gtk_widget_draw (import_dialog->preview, NULL);
gtk_widget_show (import_dialog->preview);
}
static void
palette_import_image_sel_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
gchar *lab;
gimage = GIMP_IMAGE (data);
palette_import_update_image_preview (gimage);
lab = g_strdup_printf ("%s-%d",
g_basename (gimp_image_filename (import_dialog->gimage)),
pdb_image_to_id (import_dialog->gimage));
gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
g_free (lab);
}
static void
palette_import_image_menu_add (GimpImage *gimage)
{
GtkWidget *menuitem;
gchar *lab;
lab= g_strdup_printf ("%s-%d",
g_basename (gimp_image_filename (gimage)),
pdb_image_to_id (gimage));
menuitem = gtk_menu_item_new_with_label (lab);
g_free (lab);
gtk_widget_show (menuitem);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GTK_SIGNAL_FUNC (palette_import_image_sel_callback),
gimage);
gtk_menu_append (GTK_MENU (import_dialog->optionmenu1_menu), menuitem);
}
/* Last Param gives us control over what goes in the menu on a delete oper */
static void
palette_import_image_menu_activate (gint redo,
ImportType type,
GimpImage *del_image)
{
GSList *list = NULL;
gint num_images;
GimpImage *last_img = NULL;
GimpImage *first_img = NULL;
gint act_num = -1;
gint count = 0;
gchar *lab;
if (! import_dialog)
return;
if (import_dialog->import_type == type && !redo)
return;
/* Destroy existing widget if necessary */
if (import_dialog->image_list)
{
if (redo) /* Preserve settings in this case */
last_img = import_dialog->gimage;
gtk_widget_hide (import_dialog->image_list);
gtk_widget_destroy (import_dialog->image_list);
import_dialog->image_list = NULL;
}
import_dialog->import_type= type;
/* Get list of images */
if (import_dialog->import_type == INDEXED_IMPORT)
{
gimage_foreach (palette_import_gimlist_indexed_cb, &list);
}
else
{
gimage_foreach (palette_import_gimlist_cb, &list);
}
num_images = g_slist_length (list);
if (num_images)
{
GtkWidget *optionmenu1;
GtkWidget *optionmenu1_menu;
gint i;
import_dialog->image_list = optionmenu1 = gtk_option_menu_new ();
gtk_widget_set_usize (optionmenu1, IMPORT_PREVIEW_WIDTH, -1);
import_dialog->optionmenu1_menu = optionmenu1_menu = gtk_menu_new ();
for (i = 0; i < num_images; i++, list = g_slist_next (list))
{
if (GIMP_IMAGE (list->data) != del_image)
{
if (first_img == NULL)
first_img = GIMP_IMAGE (list->data);
palette_import_image_menu_add (GIMP_IMAGE (list->data));
if (last_img == GIMP_IMAGE (list->data))
act_num = count;
else
count++;
}
}
gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu1),
optionmenu1_menu);
gtk_widget_hide (import_dialog->select);
gtk_box_pack_start (GTK_BOX (import_dialog->select_area),
optionmenu1, FALSE, FALSE, 0);
if(last_img != NULL && last_img != del_image)
palette_import_update_image_preview (last_img);
else if (first_img != NULL)
palette_import_update_image_preview (first_img);
gtk_widget_show (optionmenu1);
/* reset to last one */
if (redo && act_num >= 0)
{
gchar *lab;
lab = g_strdup_printf ("%s-%d",
g_basename (gimp_image_filename (import_dialog->gimage)),
pdb_image_to_id (import_dialog->gimage));
gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu1), act_num);
gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
g_free (lab);
}
}
g_slist_free (list);
lab = g_strdup_printf ("%s-%d",
g_basename (gimp_image_filename (import_dialog->gimage)),
pdb_image_to_id (import_dialog->gimage));
gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
g_free (lab);
}
/* the import source menu item callbacks ***********************************/
static void
palette_import_grad_callback (GtkWidget *widget,
gpointer data)
{
if (import_dialog)
{
gradient_t *gradient;
gradient = gimp_context_get_gradient (gimp_context_get_user ());
import_dialog->import_type = GRAD_IMPORT;
if (import_dialog->image_list)
{
gtk_widget_hide (import_dialog->image_list);
gtk_widget_destroy (import_dialog->image_list);
import_dialog->image_list = NULL;
}
gtk_widget_show (import_dialog->select);
palette_import_fill_grad_preview (import_dialog->preview, gradient);
gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), gradient->name);
gtk_widget_set_sensitive (import_dialog->threshold_scale, FALSE);
gtk_widget_set_sensitive (import_dialog->threshold_text, FALSE);
}
}
static void
palette_import_image_callback (GtkWidget *widget,
gpointer data)
{
palette_import_image_menu_activate (FALSE, IMAGE_IMPORT, NULL);
gtk_widget_set_sensitive (import_dialog->threshold_scale, TRUE);
gtk_widget_set_sensitive (import_dialog->threshold_text, TRUE);
}
static void
palette_import_indexed_callback (GtkWidget *widget,
gpointer data)
{
palette_import_image_menu_activate (FALSE, INDEXED_IMPORT, NULL);
gtk_widget_set_sensitive (import_dialog->threshold_scale, FALSE);
gtk_widget_set_sensitive (import_dialog->threshold_text, FALSE);
}
/* functions & callbacks to keep the import dialog uptodate ****************/
static gint
palette_import_image_count (ImportType type)
{
GSList *list = NULL;
gint num_images = 0;
if (type == INDEXED_IMPORT)
{
gimage_foreach (palette_import_gimlist_indexed_cb, &list);
}
else
{
gimage_foreach (palette_import_gimlist_cb, &list);
}
num_images = g_slist_length (list);
g_slist_free (list);
return num_images;
}
static void
palette_import_image_new (GimpSet *set,
GimpImage *gimage,
gpointer data)
{
if (! import_dialog)
return;
if (! GTK_WIDGET_IS_SENSITIVE (import_dialog->image_menu_item_image))
{
gtk_widget_set_sensitive (import_dialog->image_menu_item_image, TRUE);
return;
}
if (! GTK_WIDGET_IS_SENSITIVE (import_dialog->image_menu_item_indexed) &&
gimp_image_base_type(gimage) == INDEXED)
{
gtk_widget_set_sensitive (import_dialog->image_menu_item_indexed, TRUE);
return;
}
/* Now fill in the names if image menu shown */
if (import_dialog->import_type == IMAGE_IMPORT ||
import_dialog->import_type == INDEXED_IMPORT)
{
palette_import_image_menu_activate (TRUE, import_dialog->import_type,
NULL);
}
}
static void
palette_import_image_destroyed (GimpSet *set,
GimpImage *gimage,
gpointer data)
{
if (! import_dialog)
return;
if (palette_import_image_count (import_dialog->import_type) <= 1)
{
/* Back to gradient type */
gtk_option_menu_set_history (GTK_OPTION_MENU (import_dialog->type_option), 0);
palette_import_grad_callback (NULL, NULL);
if (import_dialog->image_menu_item_image)
gtk_widget_set_sensitive (import_dialog->image_menu_item_image, FALSE);
return;
}
if (import_dialog->import_type == IMAGE_IMPORT ||
import_dialog->import_type == INDEXED_IMPORT)
{
palette_import_image_menu_activate (TRUE, import_dialog->import_type,
gimage);
}
}
void
palette_import_image_renamed (GimpImage* gimage)
{
/* Now fill in the names if image menu shown */
if (import_dialog &&
(import_dialog->import_type == IMAGE_IMPORT ||
import_dialog->import_type == INDEXED_IMPORT))
{
palette_import_image_menu_activate (TRUE, import_dialog->import_type,
NULL);
}
}
/* create a palette from a gradient ****************************************/
static void
palette_import_create_from_grad (gchar *name)
{
GimpPalette *palette;
gradient_t *gradient;
gradient = gimp_context_get_gradient (gimp_context_get_user ());
if (gradient)
{
/* Add names to entry */
gdouble dx, cur_x;
GimpRGB color;
gint sample_sz;
gint loop;
palette = gimp_palette_new (name);
sample_sz = (gint) import_dialog->sample->value;
dx = 1.0 / (sample_sz - 1);
cur_x = 0;
for (loop = 0; loop < sample_sz; loop++)
{
gradient_get_color_at (gradient, cur_x, &color);
cur_x += dx;
gimp_palette_add_entry (palette, NULL, &color);
}
palettes_list_insert (palette);
}
}
/* create a palette from a non-indexed image *******************************/
typedef struct _ImgColors ImgColors;
struct _ImgColors
{
guint count;
guint r_adj;
guint g_adj;
guint b_adj;
guchar r;
guchar g;
guchar b;
};
static gint count_color_entries = 0;
static GHashTable *
palette_import_store_colors (GHashTable *h_array,
guchar *colors,
guchar *colors_real,
gint sample_sz)
{
gpointer found_color = NULL;
ImgColors *new_color;
guint key_colors = colors[0] * 256 * 256 + colors[1] * 256 + colors[2];
if (h_array == NULL)
{
h_array = g_hash_table_new (g_direct_hash, g_direct_equal);
count_color_entries = 0;
}
else
{
found_color = g_hash_table_lookup (h_array, (gpointer) key_colors);
}
if (found_color == NULL)
{
if (count_color_entries > MAX_IMAGE_COLORS)
{
/* Don't add any more new ones */
return h_array;
}
count_color_entries++;
new_color = g_new (ImgColors, 1);
new_color->count = 1;
new_color->r_adj = 0;
new_color->g_adj = 0;
new_color->b_adj = 0;
new_color->r = colors[0];
new_color->g = colors[1];
new_color->b = colors[2];
g_hash_table_insert (h_array, (gpointer) key_colors, new_color);
}
else
{
new_color = (ImgColors *) found_color;
if(new_color->count < (G_MAXINT - 1))
new_color->count++;
/* Now do the adjustments ...*/
new_color->r_adj += (colors_real[0] - colors[0]);
new_color->g_adj += (colors_real[1] - colors[1]);
new_color->b_adj += (colors_real[2] - colors[2]);
/* Boundary conditions */
if(new_color->r_adj > (G_MAXINT - 255))
new_color->r_adj /= new_color->count;
if(new_color->g_adj > (G_MAXINT - 255))
new_color->g_adj /= new_color->count;
if(new_color->b_adj > (G_MAXINT - 255))
new_color->b_adj /= new_color->count;
}
return h_array;
}
static void
palette_import_create_sorted_list (gpointer key,
gpointer value,
gpointer user_data)
{
GSList **sorted_list = (GSList**) user_data;
ImgColors *color_tab = (ImgColors *) value;
*sorted_list = g_slist_prepend (*sorted_list, color_tab);
}
static gint
palette_import_sort_colors (gconstpointer a,
gconstpointer b)
{
ImgColors *s1 = (ImgColors *) a;
ImgColors *s2 = (ImgColors *) b;
if(s1->count > s2->count)
return -1;
if(s1->count < s2->count)
return 1;
return 0;
}
static void
palette_import_create_image_palette (gpointer data,
gpointer user_data)
{
GimpPalette *palette;
ImgColors *color_tab;
gint sample_sz;
gchar *lab;
GimpRGB color;
palette = (GimpPalette *) user_data;
color_tab = (ImgColors *) data;
sample_sz = (gint) import_dialog->sample->value;
if (palette->n_colors >= sample_sz)
return;
lab = g_strdup_printf ("%s (occurs %u)", _("Untitled"), color_tab->count);
/* Adjust the colors to the mean of the the sample */
gimp_rgba_set_uchar
(&color,
(guchar) color_tab->r + (color_tab->r_adj / color_tab->count),
(guchar) color_tab->g + (color_tab->g_adj / color_tab->count),
(guchar) color_tab->b + (color_tab->b_adj / color_tab->count),
255);
gimp_palette_add_entry (palette, lab, &color);
g_free (lab);
}
static gboolean
palette_import_color_print_remove (gpointer key,
gpointer value,
gpointer user_data)
{
g_free (value);
return TRUE;
}
static void
palette_import_image_make_palette (GHashTable *h_array,
guchar *name)
{
GimpPalette *palette;
GSList *sorted_list = NULL;
g_hash_table_foreach (h_array, palette_import_create_sorted_list,
&sorted_list);
sorted_list = g_slist_sort (sorted_list, palette_import_sort_colors);
palette = gimp_palette_new (name);
g_slist_foreach (sorted_list, palette_import_create_image_palette, palette);
/* Free up used memory
* Note the same structure is on both the hash list and the sorted
* list. So only delete it once.
*/
g_hash_table_freeze (h_array);
g_hash_table_foreach_remove (h_array,
palette_import_color_print_remove, NULL);
g_hash_table_thaw (h_array);
g_hash_table_destroy (h_array);
g_slist_free (sorted_list);
palettes_list_insert (palette);
}
static void
palette_import_create_from_image (GImage *gimage,
gchar *pname)
{
PixelRegion imagePR;
guchar *image_data;
guchar *idata;
guchar rgb[MAX_CHANNELS];
guchar rgb_real[MAX_CHANNELS];
gint has_alpha, indexed;
gint width, height;
gint bytes, alpha;
gint i, j;
void *pr;
gint d_type;
GHashTable *store_array = NULL;
gint sample_sz;
gint threshold = 1;
sample_sz = (gint) import_dialog->sample->value;
if (gimage == NULL)
return;
/* Get the image information */
bytes = gimp_image_composite_bytes (gimage);
d_type = gimp_image_composite_type (gimage);
has_alpha = (d_type == RGBA_GIMAGE ||
d_type == GRAYA_GIMAGE ||
d_type == INDEXEDA_GIMAGE);
indexed = d_type == INDEXEDA_GIMAGE || d_type == INDEXED_GIMAGE;
width = gimage->width;
height = gimage->height;
pixel_region_init (&imagePR, gimp_image_composite (gimage), 0, 0,
width, height, FALSE);
alpha = bytes - 1;
threshold = (gint) import_dialog->threshold->value;
if(threshold < 1)
threshold = 1;
/* iterate over the entire image */
for (pr = pixel_regions_register (1, &imagePR);
pr != NULL;
pr = pixel_regions_process (pr))
{
image_data = imagePR.data;
for (i = 0; i < imagePR.h; i++)
{
idata = image_data;
for (j = 0; j < imagePR.w; j++)
{
/* Get the rgb values for the color */
gimp_image_get_color (gimage, d_type, rgb, idata);
memcpy (rgb_real, rgb, MAX_CHANNELS); /* Structure copy */
rgb[0] = (rgb[0] / threshold) * threshold;
rgb[1] = (rgb[1] / threshold) * threshold;
rgb[2] = (rgb[2] / threshold) * threshold;
store_array =
palette_import_store_colors (store_array, rgb, rgb_real,
sample_sz);
idata += bytes;
}
image_data += imagePR.rowstride;
}
}
/* Make palette from the store_array */
palette_import_image_make_palette (store_array, pname);
}
/* create a palette from an indexed image **********************************/
static void
palette_import_create_from_indexed (GImage *gimage,
gchar *pname)
{
GimpPalette *palette;
gint samples;
gint count;
GimpRGB color;
samples = (gint) import_dialog->sample->value;
if (gimage == NULL)
return;
if (gimp_image_base_type (gimage) != INDEXED)
return;
palette = gimp_palette_new (pname);
for (count= 0; count < samples && count < gimage->num_cols; ++count)
{
gimp_rgba_set_uchar (&color,
gimage->cmap[count*3],
gimage->cmap[count*3+1],
gimage->cmap[count*3+2],
255);
gimp_palette_add_entry (palette, NULL, &color);
}
palettes_list_insert (palette);
}
/* the palette import action area callbacks ********************************/
static void
palette_import_close_callback (GtkWidget *widget,
gpointer data)
{
gtk_widget_destroy (import_dialog->dialog);
g_free (import_dialog);
import_dialog = NULL;
}
static void
palette_import_import_callback (GtkWidget *widget,
gpointer data)
{
gchar *pname;
if (! import_dialog)
return;
pname = gtk_entry_get_text (GTK_ENTRY (import_dialog->entry));
if (!pname || !strlen (pname))
pname = g_strdup ("tmp");
else
pname = g_strdup (pname);
switch (import_dialog->import_type)
{
case GRAD_IMPORT:
palette_import_create_from_grad (pname);
break;
case IMAGE_IMPORT:
palette_import_create_from_image (import_dialog->gimage, pname);
break;
case INDEXED_IMPORT:
palette_import_create_from_indexed (import_dialog->gimage, pname);
break;
default:
break;
}
palette_import_close_callback (NULL, NULL);
}
/* the palette import dialog constructor ***********************************/
static ImportDialog *
palette_import_dialog_new (void)
{
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *table;
GtkWidget *label;
GtkWidget *spinbutton;
GtkWidget *button;
GtkWidget *entry;
GtkWidget *optionmenu;
GtkWidget *optionmenu_menu;
GtkWidget *menuitem;
GtkWidget *image;
GtkWidget *hscale;
import_dialog = g_new (ImportDialog, 1);
import_dialog->image_list = NULL;
import_dialog->gimage = NULL;
import_dialog->dialog = dialog =
gimp_dialog_new (_("Import Palette"), "import_palette",
gimp_standard_help_func,
"dialogs/palette_editor/import_palette.html",
GTK_WIN_POS_NONE,
FALSE, TRUE, FALSE,
_("Import"), palette_import_import_callback,
import_dialog, NULL, NULL, FALSE, FALSE,
_("Close"), palette_import_close_callback,
import_dialog, NULL, NULL, TRUE, TRUE,
NULL);
/* The main hbox */
hbox = gtk_hbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show (hbox);
/* The "Import" frame */
frame = gtk_frame_new (_("Import"));
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
table = gtk_table_new (4, 2, FALSE);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
gtk_widget_show (table);
/* The source's name */
label = gtk_label_new (_("Name:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
gtk_widget_show (label);
entry = import_dialog->entry = gtk_entry_new ();
gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, 0, 1);
{
gradient_t* gradient;
gradient = gimp_context_get_gradient (gimp_context_get_current ());
gtk_entry_set_text (GTK_ENTRY (entry),
gradient ? gradient->name : _("new_import"));
}
gtk_widget_show (entry);
/* The source type */
label = gtk_label_new (_("Source:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
gtk_widget_show (label);
optionmenu = import_dialog->type_option = gtk_option_menu_new ();
optionmenu_menu = gtk_menu_new ();
gtk_table_attach_defaults (GTK_TABLE (table), optionmenu, 1, 2, 1, 2);
menuitem = import_dialog->image_menu_item_gradient =
gtk_menu_item_new_with_label (_("Gradient"));
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GTK_SIGNAL_FUNC (palette_import_grad_callback),
NULL);
gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
gtk_widget_show (menuitem);
menuitem = import_dialog->image_menu_item_image =
gtk_menu_item_new_with_label (_("Image"));
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GTK_SIGNAL_FUNC (palette_import_image_callback),
import_dialog);
gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
gtk_widget_show (menuitem);
gtk_widget_set_sensitive (menuitem,
palette_import_image_count (IMAGE_IMPORT) > 0);
menuitem = import_dialog->image_menu_item_indexed =
gtk_menu_item_new_with_label (_("Indexed Palette"));
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GTK_SIGNAL_FUNC (palette_import_indexed_callback),
import_dialog);
gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
gtk_widget_show (menuitem);
gtk_widget_set_sensitive (menuitem,
palette_import_image_count (INDEXED_IMPORT) > 0);
gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), optionmenu_menu);
gtk_widget_show (optionmenu);
/* The sample size */
label = gtk_label_new (_("Sample Size:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
gtk_widget_show (label);
import_dialog->sample =
GTK_ADJUSTMENT(gtk_adjustment_new (256, 2, 10000, 1, 10, 10));
spinbutton = gtk_spin_button_new (import_dialog->sample, 1, 0);
gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 2, 3);
gtk_widget_show (spinbutton);
/* The interval */
label = import_dialog->threshold_text = gtk_label_new (_("Interval:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_set_sensitive(label, FALSE);
gtk_widget_show (label);
import_dialog->threshold =
GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 128, 1, 1, 1));
hscale = import_dialog->threshold_scale =
gtk_hscale_new (import_dialog->threshold);
gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (hscale), 0);
gtk_table_attach_defaults (GTK_TABLE (table), hscale, 1, 2, 3, 4);
gtk_widget_set_sensitive (hscale, FALSE);
gtk_widget_show (hscale);
/* The preview frame */
frame = gtk_frame_new (_("Preview"));
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
vbox = import_dialog->select_area = gtk_vbox_new (FALSE, 2);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
image = import_dialog->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX);
gtk_preview_size (GTK_PREVIEW (image),
IMPORT_PREVIEW_WIDTH, IMPORT_PREVIEW_HEIGHT);
gtk_widget_set_usize (image, IMPORT_PREVIEW_WIDTH, IMPORT_PREVIEW_HEIGHT);
gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
gtk_widget_show (image);
button = import_dialog->select = gtk_button_new_with_label (_("Select"));
GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (palette_import_select_grad_callback),
image);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
/* Fill with the selected gradient */
palette_import_fill_grad_preview
(image, gimp_context_get_gradient (gimp_context_get_user ()));
import_dialog->import_type = GRAD_IMPORT;
gtk_signal_connect (GTK_OBJECT (gimp_context_get_user ()), "gradient_changed",
GTK_SIGNAL_FUNC (palette_import_gradient_update),
NULL);
/* keep the dialog up-to-date */
gtk_signal_connect (GTK_OBJECT (image_context), "add",
GTK_SIGNAL_FUNC (palette_import_image_new),
NULL);
gtk_signal_connect (GTK_OBJECT (image_context), "remove",
GTK_SIGNAL_FUNC (palette_import_image_destroyed),
NULL);
return import_dialog;
}
void
palette_import_dialog_show (void)
{
if (! import_dialog)
palette_import_dialog_new ();
if (! GTK_WIDGET_VISIBLE (import_dialog->dialog))
{
gtk_widget_show (import_dialog->dialog);
}
else if (import_dialog->dialog->window)
{
gdk_window_raise (import_dialog->dialog->window);
}
}
void
palette_import_dialog_destroy (void)
{
if (import_dialog)
{
gtk_widget_destroy (import_dialog->dialog);
g_free (import_dialog);
import_dialog = NULL;
}
}