summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in3
-rw-r--r--src/xsane-back-gtk.c616
-rw-r--r--src/xsane-back-gtk.h31
-rw-r--r--src/xsane-batch-scan.c24
-rw-r--r--src/xsane-batch-scan.h2
-rw-r--r--src/xsane-device-preferences.c26
-rw-r--r--src/xsane-device-preferences.h2
-rw-r--r--src/xsane-email-project.c91
-rw-r--r--src/xsane-email-project.h2
-rw-r--r--src/xsane-fax-project.c93
-rw-r--r--src/xsane-fax-project.h2
-rw-r--r--src/xsane-fixedtext.h2
-rw-r--r--src/xsane-front-gtk.c90
-rw-r--r--src/xsane-front-gtk.h8
-rw-r--r--src/xsane-gamma.c23
-rw-r--r--src/xsane-gamma.h2
-rw-r--r--src/xsane-gimp-1_0-compat.h2
-rw-r--r--src/xsane-gtk-1_x-compat.h4
-rw-r--r--src/xsane-icons.c38
-rw-r--r--src/xsane-icons.h3
-rw-r--r--src/xsane-multipage-project.c101
-rw-r--r--src/xsane-multipage-project.h2
-rw-r--r--src/xsane-preferences.c29
-rw-r--r--src/xsane-preferences.h21
-rw-r--r--src/xsane-preview.c266
-rw-r--r--src/xsane-preview.h11
-rw-r--r--src/xsane-rc-io.c28
-rw-r--r--src/xsane-rc-io.h4
-rw-r--r--src/xsane-save.c2482
-rw-r--r--src/xsane-save.c.orig5801
-rw-r--r--src/xsane-save.h40
-rw-r--r--src/xsane-scan.c64
-rw-r--r--src/xsane-scan.h2
-rw-r--r--src/xsane-setup.c715
-rw-r--r--src/xsane-setup.h2
-rw-r--r--src/xsane-text.h769
-rw-r--r--src/xsane-viewer.c1090
-rw-r--r--src/xsane-viewer.h19
-rw-r--r--src/xsane.c333
-rw-r--r--src/xsane.h95
-rw-r--r--src/xsaneopts.h2
41 files changed, 5918 insertions, 7022 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 5debbbb..4ea7a66 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -108,7 +108,7 @@ clean:
rm -rf .libs
distclean: clean
- rm -f Makefile $(PROGRAMS)
+ rm -f Makefile $(PROGRAMS)
depend:
makedepend $(INCLUDES) *.c
@@ -232,6 +232,7 @@ xsane-multipage-project.o: xsane-front-gtk.h
xsane-multipage-project.o: xsane-preferences.h
xsane-multipage-project.o: xsane-multipage-project.h
xsane-multipage-project.o: xsane-text.h
+xsane-multipage-project.o: xsane-save.h
xsane-fax-project.o: xsane.h
xsane-fax-project.o: xsane-back-gtk.h
diff --git a/src/xsane-back-gtk.c b/src/xsane-back-gtk.c
index 10ac0b3..6ed24a4 100644
--- a/src/xsane-back-gtk.c
+++ b/src/xsane-back-gtk.c
@@ -3,7 +3,7 @@
xsane-back-gtk.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -470,7 +470,7 @@ void xsane_back_gtk_set_option(int opt_num, void *val, SANE_Action action)
SANE_Status status;
SANE_Int info;
char buf[TEXTBUFSIZE];
- int old_colors = xsane.xsane_colors;
+ int old_channels = xsane.xsane_channels;
int update_gamma = FALSE;
DBG(DBG_proc, "xsane_back_gtk_set_option\n");
@@ -505,7 +505,7 @@ void xsane_back_gtk_set_option(int opt_num, void *val, SANE_Action action)
/* XXXXXXXXXXXXXX this also has to be handled XXXXXXXXXXXXXXX */
}
- if (xsane.xsane_colors != old_colors)
+ if (xsane.xsane_channels != old_channels)
{
/* we have to update gamma tables and histogram because medium settings */
/* may have changed */
@@ -734,7 +734,7 @@ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar
button = gtk_button_new_with_label(oktext);
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_back_gtk_decision_ok_callback, (void *) decision_flag_ptr);
- gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5);
+ gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, TRUE, 5);
gtk_widget_grab_default(button);
gtk_widget_show(button);
@@ -743,7 +743,7 @@ gint xsane_back_gtk_decision(gchar *title, gchar **xpm_d, gchar *message, gchar
{
button = gtk_button_new_with_label(rejecttext);
g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_back_gtk_decision_reject_callback, (void *) decision_flag_ptr);
- gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5);
+ gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, TRUE, 5);
gtk_widget_show(button);
}
@@ -871,59 +871,6 @@ void xsane_back_gtk_info(gchar *info, int wait)
/* ---------------------------------------------------------------------------------------------------------------------- */
-GtkWidget *fileselection;
-char *fileselection_filetype = NULL;
-
-static void xsane_back_gtk_filetype_callback(GtkWidget *widget, gpointer data)
-{
- char *extension, *filename;
- char buffer[PATH_MAX];
- char *new_filetype = (char *) data;
-
- DBG(DBG_proc, "xsane_filetype_callback\n");
-
- filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection)));
-
- if ((new_filetype) && (*new_filetype))
- {
- extension = strrchr(filename, '.');
-
- if ((extension) && (extension != filename))
- {
- if ( (!strcasecmp(extension, ".pnm")) || (!strcasecmp(extension, ".raw"))
- || (!strcasecmp(extension, ".png")) || (!strcasecmp(extension, ".ps"))
- || (!strcasecmp(extension, ".pdf")) || (!strcasecmp(extension, ".rgba"))
- || (!strcasecmp(extension, ".tiff")) || (!strcasecmp(extension, ".tif"))
- || (!strcasecmp(extension, ".text")) || (!strcasecmp(extension, ".txt"))
- || (!strcasecmp(extension, ".jpg")) || (!strcasecmp(extension, ".jpeg"))
- ) /* remove filetype extension */
- {
- *extension = 0; /* remove extension */
- }
- }
- snprintf(buffer, sizeof(buffer), "%s%s", filename, new_filetype);
- free(filename);
- filename = strdup(buffer);
- }
-
- if (fileselection_filetype)
- {
- free(fileselection_filetype);
- fileselection_filetype = NULL;
- }
-
- if (data)
- {
- fileselection_filetype = strdup(new_filetype);
- }
-
- gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection), filename);
-
- free(filename);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
void xsane_back_gtk_filetype_menu_set_history(GtkWidget *xsane_filetype_option_menu, char *filetype)
{
int filetype_nr;
@@ -940,6 +887,13 @@ void xsane_back_gtk_filetype_menu_set_history(GtkWidget *xsane_filetype_option_m
}
#endif
+ filetype_nr++;
+ if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PDF)) )
+ {
+ select_item = filetype_nr;
+ }
+
+
#ifdef HAVE_LIBPNG
#ifdef HAVE_LIBZ
filetype_nr++;
@@ -962,12 +916,6 @@ void xsane_back_gtk_filetype_menu_set_history(GtkWidget *xsane_filetype_option_m
select_item = filetype_nr;
}
- filetype_nr++;
- if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_PDF)) )
- {
- select_item = filetype_nr;
- }
-
#ifdef SUPPORT_RGBA
filetype_nr++;
if ( (filetype) && (!strcasecmp(filetype, XSANE_FILETYPE_RGBA)) )
@@ -1112,6 +1060,475 @@ GtkWidget *xsane_back_gtk_filetype_menu_new(char *filetype, GtkSignalFunc filety
/* ----------------------------------------------------------------------------------------------------------------- */
+GtkWidget *xsane_back_gtk_cms_function_menu_new(int select_cms_function, GtkSignalFunc cms_function_menu_callback)
+{
+ GtkWidget *xsane_cms_function_menu, *xsane_cms_function_item;
+ GtkWidget *xsane_cms_function_option_menu;
+
+ xsane_cms_function_menu = gtk_menu_new();
+
+ xsane_cms_function_item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE);
+ if (cms_function_menu_callback)
+ {
+ g_signal_connect(GTK_OBJECT(xsane_cms_function_item), "activate", (GtkSignalFunc) cms_function_menu_callback, (void *) XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE);
+ }
+ gtk_container_add(GTK_CONTAINER(xsane_cms_function_menu), xsane_cms_function_item);
+ gtk_widget_show(xsane_cms_function_item);
+
+ xsane_cms_function_item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_FUNCTION_CONVERT_TO_SRGB);
+ if (cms_function_menu_callback)
+ {
+ g_signal_connect(GTK_OBJECT(xsane_cms_function_item), "activate", (GtkSignalFunc) cms_function_menu_callback, (void *) XSANE_CMS_FUNCTION_CONVERT_TO_SRGB);
+ }
+ gtk_container_add(GTK_CONTAINER(xsane_cms_function_menu), xsane_cms_function_item);
+ gtk_widget_show(xsane_cms_function_item);
+
+ xsane_cms_function_item = gtk_menu_item_new_with_label(MENU_ITEM_FUNCTION_CONVERT_TO_WORKING_CS);
+ if (cms_function_menu_callback)
+ {
+ g_signal_connect(GTK_OBJECT(xsane_cms_function_item), "activate", (GtkSignalFunc) cms_function_menu_callback, (void *) XSANE_CMS_FUNCTION_CONVERT_TO_WORKING_CS);
+ }
+ gtk_container_add(GTK_CONTAINER(xsane_cms_function_menu), xsane_cms_function_item);
+ gtk_widget_show(xsane_cms_function_item);
+
+ xsane_cms_function_option_menu = gtk_option_menu_new();
+ xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_cms_function_option_menu, DESC_CMS_FUNCTION);
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_cms_function_option_menu), xsane_cms_function_menu);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_cms_function_option_menu), select_cms_function);
+
+ return (xsane_cms_function_option_menu);
+}
+
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+#ifdef __GTK_FILE_CHOOSER_H__
+
+GtkWidget *filechooser;
+char *filechooser_filetype = NULL;
+
+static void xsane_back_gtk_filetype2_callback(GtkWidget *widget, gpointer data)
+{
+ char *extension, *chooser_filename;
+ char filename[PATH_MAX];
+ char *basename;
+ char *new_filetype = (char *) data;
+ int pos;
+
+ DBG(DBG_proc, "xsane_filetype2_callback\n");
+
+ chooser_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
+
+ if ((new_filetype) && (*new_filetype))
+ {
+ extension = strrchr(chooser_filename, '.');
+
+ if ((extension) && (extension != chooser_filename))
+ {
+ if ( (!strcasecmp(extension, ".pnm")) || (!strcasecmp(extension, ".raw"))
+ || (!strcasecmp(extension, ".png")) || (!strcasecmp(extension, ".ps"))
+ || (!strcasecmp(extension, ".pdf")) || (!strcasecmp(extension, ".rgba"))
+ || (!strcasecmp(extension, ".tiff")) || (!strcasecmp(extension, ".tif"))
+ || (!strcasecmp(extension, ".text")) || (!strcasecmp(extension, ".txt"))
+ || (!strcasecmp(extension, ".jpg")) || (!strcasecmp(extension, ".jpeg"))
+ ) /* remove filetype extension */
+ {
+ *extension = 0; /* remove extension */
+ }
+ }
+ snprintf(filename, sizeof(filename), "%s%s", chooser_filename, new_filetype);
+ }
+
+ if (filechooser_filetype)
+ {
+ free(filechooser_filetype);
+ filechooser_filetype = NULL;
+ }
+
+ if (data)
+ {
+ filechooser_filetype = strdup(new_filetype);
+ }
+
+
+ basename = filename;
+
+ for (pos = strlen(filename) - 1; pos > 0; pos--)
+ {
+ if (filename[pos] == '/')
+ {
+ filename[pos]=0;
+
+ basename = filename+pos+1;
+ break;
+ }
+ }
+
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filechooser), basename);
+
+ g_free(chooser_filename);
+}
+
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, char **filetype, int *cms_function,
+ XsaneFileChooserAction action, int show_extra_widgets, int enable_filters, int activate_filter)
+{
+ int ok = 0;
+ GtkWidget *xsane_filetype_option_menu;
+ GtkWidget *xsane_cms_function_option_menu = xsane_cms_function_option_menu;
+ gint result;
+ const gchar *accept_text = NULL;
+ const gchar *reject_text = NULL;
+ GtkFileChooserAction chooser_action = GTK_FILE_CHOOSER_ACTION_OPEN;
+ GtkResponseType accept_code;
+ GtkResponseType reject_code;
+ char buf[PATH_MAX];
+
+
+ DBG(DBG_proc, "xsane_back_gtk_get_filename\n");
+
+ if (filechooser)
+ {
+ gdk_beep();
+ return -1; /* cancel => do not allow to open more than one filechooser dialog */
+ }
+
+ switch (action)
+ {
+ default:
+ case XSANE_FILE_CHOOSER_ACTION_OPEN:
+ chooser_action = GTK_FILE_CHOOSER_ACTION_OPEN;
+ accept_text = GTK_STOCK_OPEN;
+ accept_code = GTK_RESPONSE_ACCEPT;
+ reject_text = GTK_STOCK_CANCEL;
+ reject_code = GTK_RESPONSE_CANCEL;
+ break;
+
+ case XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN:
+ chooser_action = GTK_FILE_CHOOSER_ACTION_OPEN;
+ accept_text = GTK_STOCK_OK;
+ accept_code = GTK_RESPONSE_ACCEPT;
+ reject_text = GTK_STOCK_CANCEL;
+ reject_code = GTK_RESPONSE_CANCEL;
+ break;
+
+ case XSANE_FILE_CHOOSER_ACTION_SAVE:
+ chooser_action = GTK_FILE_CHOOSER_ACTION_SAVE;
+ accept_text = GTK_STOCK_SAVE;
+ accept_code = GTK_RESPONSE_ACCEPT;
+ reject_text = GTK_STOCK_CANCEL;
+ reject_code = GTK_RESPONSE_CANCEL;
+ break;
+
+ case XSANE_FILE_CHOOSER_ACTION_SELECT_SAVE:
+ chooser_action = GTK_FILE_CHOOSER_ACTION_SAVE;
+ accept_text = GTK_STOCK_OK;
+ accept_code = GTK_RESPONSE_ACCEPT;
+ reject_text = GTK_STOCK_CANCEL;
+ reject_code = GTK_RESPONSE_CANCEL;
+ break;
+
+ case XSANE_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ chooser_action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
+ accept_text = GTK_STOCK_OK;
+ accept_code = GTK_RESPONSE_ACCEPT;
+ reject_text = GTK_STOCK_CANCEL;
+ reject_code = GTK_RESPONSE_CANCEL;
+ break;
+
+ case XSANE_FILE_CHOOSER_ACTION_SELECT_PROJECT:
+ chooser_action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
+ accept_text = GTK_STOCK_OK;
+ accept_code = GTK_RESPONSE_NO; /* when we would use ACCEPT, OK, YES or APPLY then the filechooser_dialog would create non existant directories */
+ reject_text = GTK_STOCK_CANCEL;
+ reject_code = GTK_RESPONSE_CANCEL;
+ break;
+ }
+
+ filechooser = gtk_file_chooser_dialog_new (label,
+ NULL,
+ chooser_action,
+ reject_text, reject_code,
+ accept_text, accept_code,
+ NULL);
+
+ xsane_set_window_icon(filechooser, 0);
+
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(filechooser), TRUE);
+
+
+ /* add paths to filechooser */
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ snprintf(buf, sizeof(buf)-2, "%s", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)));
+ gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(filechooser), buf, NULL);
+ }
+
+ if (getcwd(buf, sizeof(buf)))
+ {
+ gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(filechooser), buf, NULL);
+ }
+
+
+ if (enable_filters & XSANE_FILE_FILTER_ALL) /* filter: all files */
+ {
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(filter, "*");
+
+ gtk_file_filter_set_name(filter, FILE_FILTER_ALL_FILES);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
+
+ if (activate_filter == XSANE_FILE_FILTER_ALL)
+ {
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(filechooser), filter);
+ }
+ }
+
+ if (enable_filters & XSANE_FILE_FILTER_DRC) /* filter: device rc */
+ {
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(filter, "*.[dD][rR][cC]");
+
+ gtk_file_filter_set_name(filter, FILE_FILTER_DRC);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
+
+ if (activate_filter == XSANE_FILE_FILTER_DRC)
+ {
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(filechooser), filter);
+ }
+
+ /* add path to filechooser */
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(filechooser), getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), NULL);
+ }
+ }
+
+ if (enable_filters & XSANE_FILE_FILTER_ICM) /* filter: color management profiles */
+ {
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(filter, "*.[iI][cC][cCmM]");
+
+ gtk_file_filter_set_name(filter, FILE_FILTER_ICM);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
+
+ if (activate_filter == XSANE_FILE_FILTER_ICM)
+ {
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(filechooser), filter);
+ }
+
+ /* add path to filechooser */
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c.color%cicc", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), SLASH, SLASH);
+ gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(filechooser), buf, NULL);
+ }
+ gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(filechooser), "/usr/share/color/icc", NULL);
+ }
+
+ if (enable_filters & XSANE_FILE_FILTER_IMAGES) /* filter: images */
+ {
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(filter, "*.[jJ][pP][gG]");
+ gtk_file_filter_add_pattern(filter, "*.[jJ][pP][eE][gG]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][nN][gG]");
+ gtk_file_filter_add_pattern(filter, "*.[tT][iI][fF]");
+ gtk_file_filter_add_pattern(filter, "*.[tT][iI][fF][fF]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][sS]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][dD][fF]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][nN][mM]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][bB][mM]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][gG][mM]");
+ gtk_file_filter_add_pattern(filter, "*.[pP][pP][mM]");
+
+ gtk_file_filter_set_name(filter, FILE_FILTER_IMAGES);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
+
+ if (activate_filter == XSANE_FILE_FILTER_IMAGES)
+ {
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(filechooser), filter);
+ }
+ }
+
+ if (enable_filters & XSANE_FILE_FILTER_BATCHLIST) /* filter: color management profiles */
+ {
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(filter, "*.[xX][bV][lL]");
+
+ gtk_file_filter_set_name(filter, FILE_FILTER_XBL);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
+
+ if (activate_filter == XSANE_FILE_FILTER_BATCHLIST)
+ {
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(filechooser), filter);
+ }
+ }
+
+ /* set default filename */
+ if (default_name) /* select file */
+ {
+ const char *basename = default_name;
+ char *path;
+ int pos;
+
+ DBG(DBG_info, "xsane_back_gtk_get_filename: default_name =%s\n", default_name);
+
+ path = strdup(default_name);
+ for (pos = strlen(path)-1; pos > 0; pos--)
+ {
+ if (path[pos] == '/')
+ {
+ path[pos]=0;
+
+ basename = path+pos+1;
+ break;
+ }
+ }
+
+ if (pos)
+ {
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filechooser), path);
+ }
+
+ if ((action == XSANE_FILE_CHOOSER_ACTION_SAVE) || (action == XSANE_FILE_CHOOSER_ACTION_SELECT_SAVE))
+ {
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filechooser), (char *) basename);
+ }
+ else
+ {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(filechooser), (char *) default_name);
+ }
+ }
+
+
+ /* add filetype menu */
+
+ if (show_extra_widgets)
+ {
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ vbox = gtk_vbox_new(FALSE, 15);
+ gtk_widget_show(vbox);
+
+ if (show_extra_widgets & XSANE_GET_FILENAME_SHOW_FILETYPE)
+ {
+ DBG(DBG_info, "xsane_back_gtk_get_filename: showing filetype menu\n");
+
+ if (filechooser_filetype)
+ {
+ free(filechooser_filetype);
+ }
+
+ if ((filetype) && (*filetype))
+ {
+ filechooser_filetype = strdup(*filetype);
+ }
+ else
+ {
+ filechooser_filetype = NULL;
+ }
+
+ hbox = gtk_hbox_new(FALSE, 2);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new(TEXT_FILETYPE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ xsane_filetype_option_menu = xsane_back_gtk_filetype_menu_new(filechooser_filetype, (GtkSignalFunc) xsane_back_gtk_filetype2_callback);
+ gtk_box_pack_start(GTK_BOX(hbox), xsane_filetype_option_menu, TRUE, TRUE, 2);
+ gtk_widget_show(xsane_filetype_option_menu);
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function) && (show_extra_widgets & XSANE_GET_FILENAME_SHOW_CMS_FUNCTION))
+ {
+ hbox = gtk_hbox_new(FALSE, 2);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new(TEXT_CMS_FUNCTION);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ xsane_cms_function_option_menu = xsane_back_gtk_cms_function_menu_new(*cms_function, NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), xsane_cms_function_option_menu, TRUE, TRUE, 2);
+ gtk_widget_show(xsane_cms_function_option_menu);
+ }
+#endif
+
+ gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(filechooser), vbox);
+ }
+
+
+ gtk_widget_show(filechooser);
+
+ result = gtk_dialog_run(GTK_DIALOG(filechooser));
+
+ DBG(DBG_info, "xsane_back_gtk_get_filename: gtk_dialog_run() returned with result=%d\n", result);
+
+ if (result == accept_code)
+ {
+ char *chooser_filename;
+
+ if ((filetype) && (*filetype))
+ {
+ free(*filetype);
+ *filetype = NULL;
+ }
+
+ if (filechooser_filetype)
+ {
+ if (filetype)
+ {
+ *filetype = strdup(filechooser_filetype);
+ }
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function) && (show_extra_widgets & XSANE_GET_FILENAME_SHOW_CMS_FUNCTION))
+ {
+ *cms_function = gtk_option_menu_get_history(GTK_OPTION_MENU(xsane_cms_function_option_menu));
+
+ DBG(DBG_info, "selected cms_function = %d\n", *cms_function);
+ }
+#endif
+
+ chooser_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
+ strncpy(filename, chooser_filename, max_len - 1);
+ g_free(chooser_filename);
+
+ filename[max_len - 1] = '\0';
+
+ ok = TRUE;
+ }
+
+ gtk_widget_destroy(filechooser);
+ filechooser = NULL;
+
+ return ok ? 0 : -1;
+}
+
+#else
+
+GtkWidget *fileselection;
+char *fileselection_filetype = NULL;
+
+/* ----------------------------------------------------------------------------------------------------------------- */
+
static void xsane_back_gtk_get_filename_button_clicked(GtkWidget *w, gpointer data)
{
int *clicked = data;
@@ -1122,12 +1539,73 @@ static void xsane_back_gtk_get_filename_button_clicked(GtkWidget *w, gpointer da
/* ----------------------------------------------------------------------------------------------------------------- */
-int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, char **filetype,
- int show_fileopts, int shorten_path, int select_directory, int show_filetype_menu)
+static void xsane_back_gtk_filetype_callback(GtkWidget *widget, gpointer data)
+{
+ char *extension, *filename;
+ char buffer[PATH_MAX];
+ char *new_filetype = (char *) data;
+
+ DBG(DBG_proc, "xsane_filetype_callback\n");
+
+ filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection)));
+
+ if ((new_filetype) && (*new_filetype))
+ {
+ extension = strrchr(filename, '.');
+
+ if ((extension) && (extension != filename))
+ {
+ if ( (!strcasecmp(extension, ".pnm")) || (!strcasecmp(extension, ".raw"))
+ || (!strcasecmp(extension, ".png")) || (!strcasecmp(extension, ".ps"))
+ || (!strcasecmp(extension, ".pdf")) || (!strcasecmp(extension, ".rgba"))
+ || (!strcasecmp(extension, ".tiff")) || (!strcasecmp(extension, ".tif"))
+ || (!strcasecmp(extension, ".text")) || (!strcasecmp(extension, ".txt"))
+ || (!strcasecmp(extension, ".jpg")) || (!strcasecmp(extension, ".jpeg"))
+ ) /* remove filetype extension */
+ {
+ *extension = 0; /* remove extension */
+ }
+ }
+ snprintf(buffer, sizeof(buffer), "%s%s", filename, new_filetype);
+ free(filename);
+ filename = strdup(buffer);
+ }
+
+ if (fileselection_filetype)
+ {
+ free(fileselection_filetype);
+ fileselection_filetype = NULL;
+ }
+
+ if (data)
+ {
+ fileselection_filetype = strdup(new_filetype);
+ }
+
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection), filename);
+
+ free(filename);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, char **filetype, int *cms_function,
+ XsaneFileChooserAction action, int show_filetype_menu, int enable_filters, int activate_filter)
{
int cancel = 0, ok = 0, destroy = 0;
GtkAccelGroup *accelerator_group;
GtkWidget *xsane_filetype_option_menu;
+ int show_fileopts = 0;
+ int select_directory = 0;
+
+ if (action == XSANE_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ select_directory = TRUE;
+ }
+ else
+ {
+ show_fileopts = TRUE;
+ }
DBG(DBG_proc, "xsane_back_gtk_get_filename\n");
@@ -1277,11 +1755,6 @@ int xsane_back_gtk_get_filename(const char *label, const char *default_name, siz
cwd[cwd_len] = '\0';
DBG(DBG_info, "xsane_back_gtk_get_filename: full path filename = %s\n", filename);
- if (shorten_path && (strncmp(filename, cwd, cwd_len) == 0))
- {
- memcpy(filename, filename + cwd_len, len - cwd_len + 1);
- DBG(DBG_info, "xsane_back_gtk_get_filename: short path filename = %s\n", filename);
- }
}
if (!destroy)
@@ -1293,6 +1766,7 @@ int xsane_back_gtk_get_filename(const char *label, const char *default_name, siz
return ok ? 0 : -1;
}
+#endif
/* ----------------------------------------------------------------------------------------------------------------- */
diff --git a/src/xsane-back-gtk.h b/src/xsane-back-gtk.h
index 584e6d5..a1a49bf 100644
--- a/src/xsane-back-gtk.h
+++ b/src/xsane-back-gtk.h
@@ -3,7 +3,7 @@
xsane-back-gtk.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -43,6 +43,30 @@ CornerCoordinates;
/* ---------------------------------------------------------------------------------------------------------------------- */
+#define XSANE_FILE_FILTER_ALL 1
+#define XSANE_FILE_FILTER_IMAGES 2
+#define XSANE_FILE_FILTER_DRC 4
+#define XSANE_FILE_FILTER_BATCHLIST 8
+#define XSANE_FILE_FILTER_ICM 16
+
+#define XSANE_GET_FILENAME_SHOW_NOTHING 0
+#define XSANE_GET_FILENAME_SHOW_FILETYPE 1
+#define XSANE_GET_FILENAME_SHOW_CMS_FUNCTION 2
+
+
+typedef enum
+ {
+ XSANE_FILE_CHOOSER_ACTION_OPEN = 1,
+ XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN,
+ XSANE_FILE_CHOOSER_ACTION_SAVE,
+ XSANE_FILE_CHOOSER_ACTION_SELECT_SAVE,
+ XSANE_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ XSANE_FILE_CHOOSER_ACTION_SELECT_PROJECT
+ }
+XsaneFileChooserAction;
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
extern int xsane_back_gtk_message_dialog_active;
/* ---------------------------------------------------------------------------------------------------------------------- */
@@ -63,8 +87,9 @@ extern void xsane_back_gtk_warning(gchar *warning_message, int wait);
extern void xsane_back_gtk_info(gchar *info_message, int wait);
extern void xsane_back_gtk_filetype_menu_set_history(GtkWidget *xsane_filetype_option_menu, char *filetype);
extern GtkWidget *xsane_back_gtk_filetype_menu_new(char *filetype, GtkSignalFunc filetype_callback);
-extern int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, char **filetype,
- int show_fileopts, int shorten_path, int hide_file_list, int show_filetype_menu);
+extern GtkWidget *xsane_back_gtk_cms_function_menu_new(int cms_select_function, GtkSignalFunc cms_function_menu_callback);
+extern int xsane_back_gtk_get_filename(const char *label, const char *default_name, size_t max_len, char *filename, char **filetype, int *cms_function,
+ XsaneFileChooserAction action, int show_filetype_menu, int enable_filters, int activate_filter);
extern void xsane_back_gtk_update_vector(int opt_num, SANE_Int *vector);
extern void xsane_back_gtk_refresh_dialog(void);
diff --git a/src/xsane-batch-scan.c b/src/xsane-batch-scan.c
index 604e052..ff07e0c 100644
--- a/src/xsane-batch-scan.c
+++ b/src/xsane-batch-scan.c
@@ -3,7 +3,7 @@
xsane-batch-scan.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -345,7 +345,7 @@ static void xsane_batch_scan_load_list(void)
sprintf(windowname, "%s %s %s", xsane.prog_name, WINDOW_LOAD_BATCH_LIST, xsane.device_text);
xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", "batch-lists", 0, "default", ".xbl", XSANE_PATH_LOCAL_SANE);
- if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, FALSE, FALSE, FALSE, FALSE))
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_BATCHLIST, XSANE_FILE_FILTER_BATCHLIST))
{
if (xsane_batch_scan_load_list_from_file(filename)) /* error while loading file ? */
{
@@ -396,7 +396,7 @@ static void xsane_batch_scan_save_list(void)
sprintf(windowname, "%s %s %s", xsane.prog_name, WINDOW_SAVE_BATCH_LIST, xsane.device_text);
xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", "batch-lists", 0, "default", ".xbl", XSANE_PATH_LOCAL_SANE);
- if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, FALSE, FALSE, FALSE, FALSE))
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SAVE, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_BATCHLIST, XSANE_FILE_FILTER_BATCHLIST));
{
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
@@ -893,27 +893,29 @@ static void xsane_batch_scan_rename_callback(GtkWidget *widget, gpointer data)
gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 4);
gtk_widget_show(text);
+
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
- button = gtk_button_new_with_label(BUTTON_OK);
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
- GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_batch_scan_rename_button_callback, (void *) 1);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_batch_scan_rename_button_callback, (void *) -1);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
- gtk_widget_grab_default(button);
gtk_widget_show(button);
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
+ button = gtk_button_new_with_label(BUTTON_OK);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_batch_scan_rename_button_callback, (void *) -1);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_batch_scan_rename_button_callback, (void *) 1);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
+ gtk_widget_grab_default(button);
gtk_widget_show(button);
+
xsane_batch_scan_rename = 0;
while (xsane_batch_scan_rename == 0)
diff --git a/src/xsane-batch-scan.h b/src/xsane-batch-scan.h
index 03b018d..82aad85 100644
--- a/src/xsane-batch-scan.h
+++ b/src/xsane-batch-scan.h
@@ -3,7 +3,7 @@
xsane-batch-scan.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-device-preferences.c b/src/xsane-device-preferences.c
index 003cb77..41293e6 100644
--- a/src/xsane-device-preferences.c
+++ b/src/xsane-device-preferences.c
@@ -3,7 +3,7 @@
xsane-device-preferences.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -102,6 +102,10 @@ desc_xsane_device[] =
{"xsane-enhancement-rgb-default", xsane_rc_pref_int, DPOFFSET(enhancement_rgb_default)},
{"xsane-negative", xsane_rc_pref_int, DPOFFSET(negative)},
{"xsane-show-preview", xsane_rc_pref_int, DPOFFSET(show_preview)},
+
+ {"xsane-enable-color-management", xsane_rc_pref_int, DPOFFSET(enable_color_management)},
+ {"xsane-scanner-default-color-icm-profile", xsane_rc_pref_string, DPOFFSET(scanner_default_color_icm_profile)},
+ {"xsane-scanner-default-gray-icm-profile", xsane_rc_pref_string, DPOFFSET(scanner_default_gray_icm_profile)},
};
/* ---------------------------------------------------------------------------------------------------------------- */
@@ -109,7 +113,7 @@ desc_xsane_device[] =
static int xsane_device_preferences_load_values(Wire *w, SANE_Handle device)
{
const SANE_Option_Descriptor *opt;
- SANE_Word *word_array;
+ char *word_array;
SANE_String name, str;
u_long *caused_reload;
SANE_Int num_options;
@@ -193,12 +197,12 @@ static int xsane_device_preferences_load_values(Wire *w, SANE_Handle device)
}
else /* array */
{
- SANE_Int len;
+ SANE_Int len;
- xsane_rc_io_w_array(w, &len, (void **) &word_array, (WireCodecFunc) xsane_rc_io_w_word, sizeof(SANE_Word));
+ xsane_rc_io_w_array(w, &len, &word_array, (WireCodecFunc) xsane_rc_io_w_word, sizeof(SANE_Word));
status = xsane_control_option(device, i, SANE_ACTION_SET_VALUE, word_array, &info);
w->direction = WIRE_FREE;
- xsane_rc_io_w_array(w, &len, (void **) &word_array, (WireCodecFunc) xsane_rc_io_w_word, sizeof(SANE_Word));
+ xsane_rc_io_w_array(w, &len, &word_array, (WireCodecFunc) xsane_rc_io_w_word, sizeof(SANE_Word));
w->direction = WIRE_DECODE;
}
break;
@@ -239,7 +243,7 @@ static int xsane_device_preferences_save_values(Wire *w, SANE_Handle device)
{
const SANE_Option_Descriptor *opt;
size_t word_array_size = 0;
- SANE_Word *word_array = 0;
+ char *word_array = 0;
size_t str_size = 0;
SANE_String str = 0;
SANE_Word word;
@@ -308,7 +312,7 @@ static int xsane_device_preferences_save_values(Wire *w, SANE_Handle device)
}
xsane_rc_io_w_string(w, (SANE_String *) &opt->name);
- xsane_rc_io_w_array(w, &len, (void **) &word_array, (WireCodecFunc) xsane_rc_io_w_word, sizeof(SANE_Word));
+ xsane_rc_io_w_array(w, &len, &word_array, (WireCodecFunc) xsane_rc_io_w_word, sizeof(SANE_Word));
}
break;
@@ -580,6 +584,10 @@ void xsane_device_preferences_load_file(char *filename)
gtk_window_set_default_size(GTK_WINDOW(xsane.preview->top), xsane.preview_dialog_width, xsane.preview_dialog_height);
#endif
+#ifdef HAVE_LIBLCMS
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.enable_color_management_widget), xsane.enable_color_management);
+#endif
+
xsane_update_param(0);
xsane_refresh_dialog();
xsane_enhancement_by_gamma();
@@ -621,7 +629,7 @@ void xsane_device_preferences_load(void)
sprintf(windowname, "%s %s %s", xsane.prog_name, WINDOW_LOAD_SETTINGS, xsane.device_text);
xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, 0, xsane.device_set_filename, ".drc", XSANE_PATH_LOCAL_SANE);
- if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, FALSE, FALSE, FALSE, FALSE))
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_OPEN, FALSE, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_DRC, XSANE_FILE_FILTER_DRC))
{
xsane_device_preferences_load_file(filename);
}
@@ -772,7 +780,7 @@ void xsane_device_preferences_save(void)
sprintf(windowname, "%s %s %s", xsane.prog_name, WINDOW_SAVE_SETTINGS, xsane.device_text);
xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, 0, xsane.device_set_filename, ".drc", XSANE_PATH_LOCAL_SANE);
- if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, FALSE, FALSE, FALSE, FALSE))
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SAVE, FALSE, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_DRC, XSANE_FILE_FILTER_DRC))
{
xsane_device_preferences_save_file(filename);
}
diff --git a/src/xsane-device-preferences.h b/src/xsane-device-preferences.h
index e980d47..ab705c0 100644
--- a/src/xsane-device-preferences.h
+++ b/src/xsane-device-preferences.h
@@ -3,7 +3,7 @@
xsane-device-preferences.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-email-project.c b/src/xsane-email-project.c
index 79df15b..b36dd59 100644
--- a/src/xsane-email-project.c
+++ b/src/xsane-email-project.c
@@ -3,7 +3,7 @@
xsane-email-project.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -64,6 +64,7 @@ static gint xsane_email_dialog_delete();
static void xsane_email_filetype_callback(GtkWidget *filetype_option_menu, char *filetype);
static void xsane_email_receiver_changed_callback(GtkWidget *widget, gpointer data);
static void xsane_email_subject_changed_callback(GtkWidget *widget, gpointer data);
+static void xsane_email_project_browse_filename_callback(GtkWidget *widget, gpointer data);
static void xsane_email_project_changed_callback(GtkWidget *widget, gpointer data);
static void xsane_email_html_mode_callback(GtkWidget *widget);
static void xsane_email_project_display_status(void);
@@ -150,10 +151,14 @@ void xsane_email_dialog()
gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
gtk_box_pack_start(GTK_BOX(email_scan_vbox), hbox, FALSE, FALSE, 1);
+#if 0
pixmap = gdk_pixmap_create_from_xpm_d(xsane.dialog->window, &mask, xsane.bg_trans, (gchar **) email_xpm);
pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
gdk_drawable_unref(pixmap);
+#endif
+ button = xsane_button_new_with_pixmap(xsane.dialog->window, hbox, email_xpm, DESC_EMAIL_PROJECT_BROWSE,
+ (GtkSignalFunc) xsane_email_project_browse_filename_callback, NULL);
text = gtk_entry_new();
xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_EMAIL_PROJECT);
@@ -165,7 +170,7 @@ void xsane_email_dialog()
xsane.project_entry = text;
xsane.project_entry_box = hbox;
- gtk_widget_show(pixmapwidget);
+// gtk_widget_show(pixmapwidget);
gtk_widget_show(text);
gtk_widget_show(hbox);
@@ -1073,6 +1078,64 @@ static void xsane_email_subject_changed_callback(GtkWidget *widget, gpointer dat
/* ---------------------------------------------------------------------------------------------------------------------- */
+void xsane_email_project_set_filename(gchar *filename)
+{
+ g_signal_handlers_block_by_func(GTK_OBJECT(xsane.project_entry), (GtkSignalFunc) xsane_email_project_changed_callback, NULL);
+ gtk_entry_set_text(GTK_ENTRY(xsane.project_entry), (char *) filename); /* update filename in entry */
+ gtk_entry_set_position(GTK_ENTRY(xsane.project_entry), strlen(filename)); /* set cursor to right position of filename */
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(xsane.project_entry), (GtkSignalFunc) xsane_email_project_changed_callback, NULL);
+}
+
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_email_project_browse_filename_callback(GtkWidget *widget, gpointer data)
+{
+ char filename[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_email_project_browse_filename_callback\n");
+
+ xsane_set_sensitivity(FALSE);
+
+ if (preferences.email_project) /* make sure a correct filename is defined */
+ {
+ strncpy(filename, preferences.email_project, sizeof(filename));
+ filename[sizeof(filename) - 1] = '\0';
+ }
+ else /* no filename given, take standard filename */
+ {
+ strcpy(filename, OUT_FILENAME);
+ }
+
+ snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_EMAIL_PROJECT_BROWSE, xsane.device_text);
+
+ umask((mode_t) preferences.directory_umask); /* define new file permissions */
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_PROJECT, XSANE_GET_FILENAME_SHOW_NOTHING, 0, 0))
+ {
+
+ if (preferences.email_project)
+ {
+ free((void *) preferences.email_project);
+ }
+
+ preferences.email_project = strdup(filename);
+
+ xsane_set_sensitivity(TRUE);
+ xsane_email_project_set_filename(filename);
+
+ xsane_email_project_load();
+ }
+ else
+ {
+ xsane_set_sensitivity(TRUE);
+ }
+ umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
+
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
static void xsane_email_project_changed_callback(GtkWidget *widget, gpointer data)
{
DBG(DBG_proc, "xsane_email_project_changed_callback\n");
@@ -1277,20 +1340,20 @@ static void xsane_email_entry_rename_callback(GtkWidget *widget, gpointer list)
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
- button = gtk_button_new_with_label(BUTTON_OK);
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_button_callback, (void *) 1);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_button_callback,(void *) -1);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_widget_show(button);
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
+ button = gtk_button_new_with_label(BUTTON_OK);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_button_callback,(void *) -1);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_email_entry_rename_button_callback, (void *) 1);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_widget_show(button);
@@ -1595,7 +1658,7 @@ static void xsane_create_email(int fd)
/* doc files like ps and pdf can not be displayed inline in html email */
if (display_images_inline)
{
- snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\n", content_id);
+ snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\r\n", content_id);
}
write(fd, buf, strlen(buf));
}
@@ -1605,7 +1668,7 @@ static void xsane_create_email(int fd)
}
else if (*email_text_pos == 10) /* new line */
{
- snprintf(buf, sizeof(buf), "<br>\n");
+ snprintf(buf, sizeof(buf), "<br>\r\n");
write(fd, buf, strlen(buf));
}
else
@@ -1624,12 +1687,12 @@ static void xsane_create_email(int fd)
/* doc files like ps and pdf can not be displayed inline in html email */
if (display_images_inline)
{
- snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\n", content_id);
+ snprintf(buf, sizeof(buf), "<p><img SRC=\"cid:%s\">\r\n", content_id);
}
write(fd, buf, strlen(buf));
}
- snprintf(buf, sizeof(buf), "</html>\n");
+ snprintf(buf, sizeof(buf), "</html>\r\n");
write(fd, buf, strlen(buf));
@@ -1666,7 +1729,7 @@ static void xsane_create_email(int fd)
write_email_mime_ascii(fd, boundary);
write(fd, email_text, strlen(email_text));
- write(fd, "\n\n", 2);
+ write(fd, "\r\n\r\n", 4);
for (i=0; i<attachments; i++)
{
@@ -1856,7 +1919,7 @@ static void xsane_email_send()
free(type);
DBG(DBG_info, "converting %s to %s\n", source_filename, email_filename);
output_format = xsane_identify_output_format(email_filename, NULL, NULL);
- xsane_save_image_as(email_filename, source_filename, output_format, xsane.project_progress_bar, &cancel_save);
+ xsane_save_image_as(email_filename, source_filename, output_format, xsane.enable_color_management, preferences.cms_function, preferences.cms_intent, preferences.cms_bpc, xsane.project_progress_bar, &cancel_save);
list = list->next;
xsane.email_progress_size += xsane_get_filesize(email_filename);
}
diff --git a/src/xsane-email-project.h b/src/xsane-email-project.h
index 2148ef2..8bc44b8 100644
--- a/src/xsane-email-project.h
+++ b/src/xsane-email-project.h
@@ -3,7 +3,7 @@
xsane-email-project.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-fax-project.c b/src/xsane-fax-project.c
index 8f23bf2..4b7b770 100644
--- a/src/xsane-fax-project.c
+++ b/src/xsane-fax-project.c
@@ -3,7 +3,7 @@
xsane-fax-project.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -57,6 +57,7 @@ void xsane_fax_dialog(void);
void xsane_fax_project_save(void);
static gint xsane_fax_dialog_delete();
+static void xsane_fax_project_browse_filename_callback(GtkWidget *widget, gpointer data);
static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data);
static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data);
static void xsane_fax_fine_mode_callback(GtkWidget *widget);
@@ -86,8 +87,9 @@ void xsane_fax_dialog()
GtkWidget *fax_dialog, *fax_scan_vbox, *fax_project_vbox, *hbox, *fax_project_exists_hbox, *button;
GtkWidget *scrolled_window, *list;
char buf[64];
- GtkWidget *pixmapwidget, *text;
+ GtkWidget *text;
GtkWidget *pages_frame;
+ GtkWidget *pixmapwidget;
GdkBitmap *mask;
GdkPixmap *pixmap;
@@ -119,10 +121,8 @@ void xsane_fax_dialog()
gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
gtk_box_pack_start(GTK_BOX(fax_scan_vbox), hbox, FALSE, FALSE, 1);
- pixmap = gdk_pixmap_create_from_xpm_d(xsane.dialog->window, &mask, xsane.bg_trans, (gchar **) fax_xpm);
- pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
- gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
- gdk_drawable_unref(pixmap);
+ button = xsane_button_new_with_pixmap(xsane.dialog->window, hbox, fax_xpm, DESC_FAX_PROJECT_BROWSE,
+ (GtkSignalFunc) xsane_fax_project_browse_filename_callback, NULL);
text = gtk_entry_new();
xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_FAXPROJECT);
@@ -134,7 +134,6 @@ void xsane_fax_dialog()
xsane.project_entry = text;
xsane.project_entry_box = hbox;
- gtk_widget_show(pixmapwidget);
gtk_widget_show(text);
gtk_widget_show(hbox);
@@ -582,6 +581,64 @@ static void xsane_fax_receiver_changed_callback(GtkWidget *widget, gpointer data
gtk_progress_bar_update(GTK_PROGRESS_BAR(xsane.project_progress_bar), 0.0);
}
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+void xsane_fax_project_set_filename(gchar *filename)
+{
+ g_signal_handlers_block_by_func(GTK_OBJECT(xsane.project_entry), (GtkSignalFunc) xsane_fax_project_changed_callback, NULL);
+ gtk_entry_set_text(GTK_ENTRY(xsane.project_entry), (char *) filename); /* update filename in entry */
+ gtk_entry_set_position(GTK_ENTRY(xsane.project_entry), strlen(filename)); /* set cursor to right position of filename */
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(xsane.project_entry), (GtkSignalFunc) xsane_fax_project_changed_callback, NULL);
+}
+
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_fax_project_browse_filename_callback(GtkWidget *widget, gpointer data)
+{
+ char filename[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_fax_project_browse_filename_callback\n");
+
+ xsane_set_sensitivity(FALSE);
+
+ if (preferences.fax_project) /* make sure a correct filename is defined */
+ {
+ strncpy(filename, preferences.fax_project, sizeof(filename));
+ filename[sizeof(filename) - 1] = '\0';
+ }
+ else /* no filename given, take standard filename */
+ {
+ strcpy(filename, OUT_FILENAME);
+ }
+
+ snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_FAX_PROJECT_BROWSE, xsane.device_text);
+
+ umask((mode_t) preferences.directory_umask); /* define new file permissions */
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_PROJECT, FALSE, 0, 0))
+ {
+
+ if (preferences.fax_project)
+ {
+ free((void *) preferences.fax_project);
+ }
+
+ preferences.fax_project = strdup(filename);
+
+ xsane_set_sensitivity(TRUE);
+ xsane_fax_project_set_filename(filename);
+
+ xsane_fax_project_load();
+ }
+ else
+ {
+ xsane_set_sensitivity(TRUE);
+ }
+ umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
+
+}
+
/* ---------------------------------------------------------------------------------------------------------------------- */
static void xsane_fax_project_changed_callback(GtkWidget *widget, gpointer data)
@@ -761,20 +818,21 @@ static void xsane_fax_entry_rename_callback(GtkWidget *widget, gpointer list)
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
- button = gtk_button_new_with_label(BUTTON_OK);
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) 1);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) -1);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_widget_show(button);
+
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
+ button = gtk_button_new_with_label(BUTTON_OK);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) -1);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_fax_entry_rename_button_callback, (void *) 1);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_widget_show(button);
@@ -833,7 +891,7 @@ static void xsane_fax_entry_insert_callback(GtkWidget *widget, gpointer list)
umask((mode_t) preferences.directory_umask); /* define new file permissions */
- if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, TRUE, FALSE, FALSE, FALSE)) /* filename is selected */
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_OPEN, FALSE, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES)) /* filename is selected */
{
FILE *sourcefile;
@@ -1082,7 +1140,12 @@ static int xsane_fax_convert_pnm_to_ps(char *source_filename, char *fax_filename
preferences.fax_width * 72.0/MM_PER_INCH, /* paper_width */
preferences.fax_height * 72.0/MM_PER_INCH, /* paper_height */
0 /* portrait top left */,
- preferences.fax_ps_flatdecoded, /* use ps level 3 zlib compression */
+ preferences.fax_ps_flatedecoded, /* use ps level 3 zlib compression */
+ NULL, /* hTransform */
+ 0 /* do not apply ICM profile */,
+ 0, NULL, /* no CSA */
+ 0, NULL, 0, /* no CRD */
+ 0, /* intent */
xsane.project_progress_bar,
&cancel_save);
fclose(outfile);
diff --git a/src/xsane-fax-project.h b/src/xsane-fax-project.h
index 775aafc..cca541e 100644
--- a/src/xsane-fax-project.h
+++ b/src/xsane-fax-project.h
@@ -3,7 +3,7 @@
xsane-fax-project.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-fixedtext.h b/src/xsane-fixedtext.h
index d655d34..d207450 100644
--- a/src/xsane-fixedtext.h
+++ b/src/xsane-fixedtext.h
@@ -3,7 +3,7 @@
xsane-fixedtext.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-front-gtk.c b/src/xsane-front-gtk.c
index a11779e..3d98a5b 100644
--- a/src/xsane-front-gtk.c
+++ b/src/xsane-front-gtk.c
@@ -3,7 +3,7 @@
xsane-front-gtk.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -67,14 +67,14 @@ void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val,
void *option_menu_callback, SANE_Int settable, const gchar *widget_name);
void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
char *str_list[], const char *val,
- GtkObject **data, int option,
+ GtkWidget **data, int option,
void *option_menu_callback, SANE_Int settable, const gchar *widget_name);
void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
float min, float max, float quant, float page_step,
- int digits, double *val, GtkObject **data, void *xsane_range_callback, SANE_Int settable);
+ int digits, double *val, GtkWidget **data, void *xsane_range_callback, SANE_Int settable);
void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
float min, float max, float quant, float page_step, int digits,
- double *val, GtkObject **data, int option, void *xsane_range_callback, SANE_Int settable);
+ double *val, GtkWidget **data, int option, void *xsane_range_callback, SANE_Int settable);
static void xsane_outputfilename_changed_callback(GtkWidget *widget, gpointer data);
void xsane_set_filename(gchar *filename);
void xsane_separator_new(GtkWidget *xsane_parent, int dist);
@@ -411,7 +411,7 @@ void xsane_define_maximum_output_size()
if ( (opt) && (opt->unit== SANE_UNIT_MM) )
{
- switch(preferences.xsane_mode)
+ switch(xsane.xsane_mode)
{
case XSANE_SAVE:
@@ -662,6 +662,15 @@ gint xsane_authorization_callback(SANE_String_Const resource,
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 10); /* y-space around buttons */
#ifdef HAVE_GTK2
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+#else
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
+#endif
+ g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(xsane_authorization_button_callback), (void *) -1);
+ gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10); /* x-space around cancel-button */
+ gtk_widget_show(button);
+
+#ifdef HAVE_GTK2
button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
button = gtk_button_new_with_label(BUTTON_OK);
@@ -672,15 +681,6 @@ gint xsane_authorization_callback(SANE_String_Const resource,
gtk_widget_grab_default(button);
gtk_widget_show(button);
-#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
-#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
-#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(xsane_authorization_button_callback), (void *) -1);
- gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10); /* x-space around cancel-button */
- gtk_widget_show(button);
-
gtk_widget_show(hbox);
gtk_widget_show(authorize_dialog);
@@ -1032,7 +1032,7 @@ void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const char *val,
void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
char *str_list[], const char *val,
- GtkObject **data, int option,
+ GtkWidget **data, int option,
void *option_menu_callback, SANE_Int settable, const gchar *widget_name)
{
GtkWidget *hbox;
@@ -1071,7 +1071,7 @@ static void xsane_range_display_value_right_callback(GtkAdjustment *adjust, gpoi
void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
float min, float max, float quant, float page_step,
- int digits, double *val, GtkObject **data, void *xsane_range_callback, SANE_Int settable)
+ int digits, double *val, GtkWidget **data, void *xsane_range_callback, SANE_Int settable)
{
GtkWidget *hbox;
GtkWidget *label;
@@ -1087,7 +1087,7 @@ void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
label = gtk_label_new(labeltext);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1);
- *data = gtk_adjustment_new(*val, min, max, quant, page_step, (max-min) * 1e-30);
+ *data = (GtkWidget *) gtk_adjustment_new(*val, min, max, quant, page_step, (max-min) * 1e-30);
/* 1e-30 => hscrollbar has an unwanted side effect: the maximum is not the maximum */
/* of the given range, it is reduced by the page_size, so it has to be very small */
@@ -1159,7 +1159,7 @@ void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
float min, float max, float quant, float page_step,
- int digits, double *val, GtkObject **data, int option, void *xsane_range_callback, SANE_Int settable)
+ int digits, double *val, GtkWidget **data, int option, void *xsane_range_callback, SANE_Int settable)
{
GtkWidget *hbox;
GtkWidget *slider = NULL;
@@ -1180,7 +1180,7 @@ void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *
gtk_widget_show(pixmapwidget);
gdk_drawable_unref(pixmap);
- *data = gtk_adjustment_new(*val, min, max, quant, page_step, (max-min) * 1e-30);
+ *data = (GtkWidget *) gtk_adjustment_new(*val, min, max, quant, page_step, (max-min) * 1e-30);
/* 1e-30 => hscrollbar has an unwanted side effect: the maximum is not the maximum */
/* of the given range, it is reduced by the page_size, so it has to be very small */
@@ -1251,7 +1251,7 @@ void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *
DialogElement *elem;
elem=xsane.element + option;
- elem->data = *data;
+ elem->data = (GtkObject *) *data;
elem->widget = slider;
}
}
@@ -1262,6 +1262,7 @@ static void xsane_browse_filename_callback(GtkWidget *widget, gpointer data)
{
char filename[PATH_MAX];
char windowname[TEXTBUFSIZE];
+ int show_extra_widgets;
DBG(DBG_proc, "xsane_browse_filename_callback\n");
@@ -1277,10 +1278,17 @@ static void xsane_browse_filename_callback(GtkWidget *widget, gpointer data)
strcpy(filename, OUT_FILENAME);
}
+ show_extra_widgets = XSANE_GET_FILENAME_SHOW_FILETYPE;
+ if (xsane.enable_color_management)
+ {
+ show_extra_widgets |= XSANE_GET_FILENAME_SHOW_CMS_FUNCTION;
+ }
+
+
snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_OUTPUT_FILENAME, xsane.device_text);
umask((mode_t) preferences.directory_umask); /* define new file permissions */
- xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, &preferences.filetype, TRUE, TRUE, FALSE, TRUE);
+ xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, &preferences.filetype, &preferences.cms_function, XSANE_FILE_CHOOSER_ACTION_SELECT_SAVE, show_extra_widgets, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES);
umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
if (preferences.filename)
@@ -1294,6 +1302,10 @@ static void xsane_browse_filename_callback(GtkWidget *widget, gpointer data)
xsane_back_gtk_filetype_menu_set_history(xsane.filetype_option_menu, preferences.filetype);
+#ifdef HAVE_LIBLCMS
+ gtk_option_menu_set_history(GTK_OPTION_MENU(xsane.cms_function_option_menu), preferences.cms_function);
+#endif
+
/* correct length of filename counter if it is shorter than minimum length */
xsane_update_counter_in_filename(&preferences.filename, FALSE, 0, preferences.filename_counter_len);
@@ -1629,17 +1641,17 @@ void xsane_update_param(void *arg)
if (xsane.param.format == SANE_FRAME_GRAY)
{
- xsane.xsane_colors = 1;
+ xsane.xsane_channels = 1;
}
#ifdef SUPPORT_RGBA
else if (xsane.param.format == SANE_FRAME_RGBA)
{
- xsane.xsane_colors = 4;
+ xsane.xsane_channels = 4;
}
#endif
else /* RGB */
{
- xsane.xsane_colors = 3;
+ xsane.xsane_channels = 3;
}
}
else
@@ -1785,6 +1797,7 @@ int xsane_identify_output_format(char *filename, char *filetype, char **ext)
/* ---------------------------------------------------------------------------------------------------------------------- */
+#if 0
void xsane_change_working_directory(void)
{
char filename[PATH_MAX];
@@ -1797,7 +1810,7 @@ void xsane_change_working_directory(void)
sprintf(windowname, "%s %s %s", xsane.prog_name, WINDOW_CHANGE_WORKING_DIR, xsane.device_text);
if (getcwd(filename, sizeof(filename)))
{
- xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, TRUE, FALSE, TRUE, FALSE);
+// xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, TRUE, FALSE, TRUE, FALSE);
if (chdir(filename))
{
char buf[TEXTBUFSIZE];
@@ -1819,6 +1832,7 @@ void xsane_change_working_directory(void)
xsane_set_sensitivity(TRUE);
}
+#endif
/* ---------------------------------------------------------------------------------------------------------------------- */
@@ -2019,11 +2033,6 @@ int xsane_display_eula(int ask_for_accept)
if (ask_for_accept) /* show accept + not accept buttons */
{
- button = gtk_button_new_with_label(BUTTON_ACCEPT);
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_eula_button_callback, (void *) 0 /* accept */);
- gtk_container_add(GTK_CONTAINER(hbox), button);
- gtk_widget_show(button);
-
button = gtk_button_new_with_label(BUTTON_NOT_ACCEPT);
gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED);
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
@@ -2031,6 +2040,11 @@ int xsane_display_eula(int ask_for_accept)
gtk_container_add(GTK_CONTAINER(hbox), button);
gtk_widget_grab_default(button);
gtk_widget_show(button);
+
+ button = gtk_button_new_with_label(BUTTON_ACCEPT);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_eula_button_callback, (void *) 0 /* accept */);
+ gtk_container_add(GTK_CONTAINER(hbox), button);
+ gtk_widget_show(button);
}
else /* show close button */
{
@@ -2397,22 +2411,22 @@ int xsane_front_gtk_getname_dialog(const char *dialog_title, const char *desc_te
gtk_window_add_accel_group(GTK_WINDOW(getname_dialog), accelerator_group);
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
- button = gtk_button_new_with_label(BUTTON_OK);
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) 1);
- GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) -1);
+ gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED); /* ESC */
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_widget_show(button);
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
+ button = gtk_button_new_with_label(BUTTON_OK);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) -1);
- gtk_widget_add_accelerator(button, "clicked", accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED); /* ESC */
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_front_gtk_getname_button_callback, (void *) 1);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
gtk_widget_show(button);
diff --git a/src/xsane-front-gtk.h b/src/xsane-front-gtk.h
index 1db2b7b..b7752bf 100644
--- a/src/xsane-front-gtk.h
+++ b/src/xsane-front-gtk.h
@@ -3,7 +3,7 @@
xsane-front-gtk.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -57,14 +57,14 @@ extern void xsane_option_menu_new(GtkWidget *parent, char *str_list[], const cha
void *option_menu_callback, SANE_Int settable, const gchar *widget_name);
extern void xsane_option_menu_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
char *str_list[], const char *val,
- GtkObject **data, int option,
+ GtkWidget **data, int option,
void *option_menu_callback, SANE_Int settable, const gchar *widget_name);
extern void xsane_range_new(GtkBox *parent, char *labeltext, const char *desc,
float min, float max, float quant, float page_step,
- int digits, double *val, GtkObject **data, void *xsane_range_callback, SANE_Int settable);
+ int digits, double *val, GtkWidget **data, void *xsane_range_callback, SANE_Int settable);
extern void xsane_range_new_with_pixmap(GdkWindow *window, GtkBox *parent, const char *xpm_d[], const char *desc,
float min, float max, float quant, float page_step, int digits,
- double *val, GtkObject **data, int option, void *xsane_range_callback, SANE_Int settable);
+ double *val, GtkWidget **data, int option, void *xsane_range_callback, SANE_Int settable);
extern void xsane_set_filename(gchar *filename);
extern void xsane_outputfilename_new(GtkWidget *vbox);
extern void xsane_separator_new(GtkWidget *xsane_parent, int dist);
diff --git a/src/xsane-gamma.c b/src/xsane-gamma.c
index 40fe835..8304f07 100644
--- a/src/xsane-gamma.c
+++ b/src/xsane-gamma.c
@@ -3,7 +3,7 @@
xsane-gamma.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -132,7 +132,7 @@ static void xsane_draw_histogram_with_points(XsanePixmap *hist,
{
inten = show_inten * count[i] * scale;
- if (xsane.xsane_colors > 1)
+ if (xsane.xsane_channels > 1)
{
red = show_red * count_red[i] * scale;
green = show_green * count_green[i] * scale;
@@ -208,7 +208,7 @@ static void xsane_draw_histogram_with_lines(XsanePixmap *hist,
{
inten = show_inten * count[i] * scale;
- if (xsane.xsane_colors > 1)
+ if (xsane.xsane_channels > 1)
{
red = show_red * count_red[i] * scale;
green = show_green * count_green[i] * scale;
@@ -518,7 +518,7 @@ void xsane_update_sliders()
xsane_update_slider(&xsane.slider_gray);
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) )
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) && (!xsane.enable_color_management))
{
xsane_update_slider(&xsane.slider_red);
xsane_update_slider(&xsane.slider_green);
@@ -539,7 +539,7 @@ void xsane_update_sliders()
xsane.slider_green.active = XSANE_SLIDER_INACTIVE; /* mark slider inactive */
xsane.slider_blue.active = XSANE_SLIDER_INACTIVE; /* mark slider inactive */
- if (xsane.param.depth == 1)
+ if ((xsane.param.depth == 1) || (xsane.enable_color_management))
{
xsane_draw_slider_level(&xsane.slider_gray); /* remove slider */
xsane.slider_gray.active = XSANE_SLIDER_INACTIVE; /* mark slider inactive */
@@ -1599,7 +1599,7 @@ void xsane_update_gamma_curve(int update_raw)
xsane.brightness + xsane.brightness_blue,
xsane.contrast + xsane.contrast_blue , xsane.preview_gamma_size, 255);
#else
- if ( ( ( (xsane.xsane_colors > 1) && xsane.scanner_gamma_color ) || /* color scan and gamma table for red, green and blue available */
+ if ( ( ( (xsane.xsane_channels > 1) && xsane.scanner_gamma_color ) || /* color scan and gamma table for red, green and blue available */
xsane.scanner_gamma_gray ) && /* grayscale scan and gamma table for gray available */
(!xsane.no_preview_medium_gamma) ) /* do not use gamma table when disabled */
{
@@ -1663,7 +1663,7 @@ void xsane_update_gamma_curve(int update_raw)
xsane.preview_gamma_size);
}
}
- else if (xsane.xsane_colors > 1) /* color scan, no color scanner gamma tables available */
+ else if (xsane.xsane_channels > 1) /* color scan, no color scanner gamma tables available */
{
DBG(DBG_info, "creating preview gamma tables with medium correction\n");
@@ -1826,13 +1826,18 @@ static void xsane_enhancement_update(void)
return;
}
+ if (xsane.enable_color_management) /* color management? no gamma */
+ {
+ return;
+ }
+
xsane.block_enhancement_update = TRUE;
gtk_adjustment_set_value(GTK_ADJUSTMENT(xsane.gamma_widget), xsane.gamma);
gtk_adjustment_set_value(GTK_ADJUSTMENT(xsane.brightness_widget), xsane.brightness);
gtk_adjustment_set_value(GTK_ADJUSTMENT(xsane.contrast_widget), xsane.contrast);
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) )
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) )
{
gtk_adjustment_set_value(GTK_ADJUSTMENT(xsane.gamma_red_widget), xsane.gamma_red);
gtk_adjustment_set_value(GTK_ADJUSTMENT(xsane.brightness_red_widget), xsane.brightness_red);
@@ -2107,7 +2112,7 @@ void xsane_enhancement_by_histogram(int update_gamma)
xsane.contrast = gray_contrast;
}
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) ) /* rgb sliders active */
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) ) /* rgb sliders active */
{
if ((xsane.slider_gray.active == XSANE_SLIDER_ACTIVE) ||
(xsane.slider_gray.active == XSANE_SLIDER_INACTIVE)) /* gray slider not moved */
diff --git a/src/xsane-gamma.h b/src/xsane-gamma.h
index e948a92..b40249f 100644
--- a/src/xsane-gamma.h
+++ b/src/xsane-gamma.h
@@ -3,7 +3,7 @@
xsane-gamma.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-gimp-1_0-compat.h b/src/xsane-gimp-1_0-compat.h
index 1bdc758..141bd42 100644
--- a/src/xsane-gimp-1_0-compat.h
+++ b/src/xsane-gimp-1_0-compat.h
@@ -3,7 +3,7 @@
xsane-gimp-1_0-compat.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 2000-2005 Oliver Rauch
+ Copyright (C) 2000-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-gtk-1_x-compat.h b/src/xsane-gtk-1_x-compat.h
index 1653c33..fea9c18 100644
--- a/src/xsane-gtk-1_x-compat.h
+++ b/src/xsane-gtk-1_x-compat.h
@@ -3,7 +3,7 @@
xsane-gtk-1_x-compat.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 2002-2005 Oliver Rauch
+ Copyright (C) 2002-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -64,5 +64,5 @@
gtk_window_set_policy(widget, FALSE, resizable, FALSE)
# define gtk_image_new_from_pixmap(pixmap, mask) \
gtk_pixmap_new(pixmap, mask)
-
+# define gtk_progress_bar_set_ellipsize() /* empty */
#endif
diff --git a/src/xsane-icons.c b/src/xsane-icons.c
index f06e3cd..ba76144 100644
--- a/src/xsane-icons.c
+++ b/src/xsane-icons.c
@@ -3,7 +3,7 @@
xsane-icons.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -2910,6 +2910,42 @@ const char *resolution_y_xpm[] =
/* --------------------------------------------------- */
+const char *cms_xpm[] =
+{
+/* width height num_colors chars_per_pixel */
+" 20 20 6 1",
+/* colors */
+". c #000000",
+" none",
+"w c #ffffff",
+"r c #ff0000",
+"g c #00ff00",
+"b c #0000ff",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" rrrr g g bbbb ",
+"rrrrrr gg gg bbbbbb",
+"rr r gggggg bb b",
+"rr gggggg bb ",
+"rr gg gg bbbbb ",
+"rr gg gg bbbb ",
+"rr gg gg bb",
+"rr r gg gg b bb",
+"rrrrrr gg gg bbbbbb",
+" rrrr gg gg bbbb ",
+" ",
+" ",
+" ",
+" ",
+};
+
+/* --------------------------------------------------- */
+
const char *scanner_xpm[] =
{
/* width height num_colors chars_per_pixel */
diff --git a/src/xsane-icons.h b/src/xsane-icons.h
index 1e4e1a1..6f38cfb 100644
--- a/src/xsane-icons.h
+++ b/src/xsane-icons.h
@@ -3,7 +3,7 @@
xsane-icons.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -119,6 +119,7 @@ extern const char *zoom_y_xpm[];
extern const char *resolution_xpm[];
extern const char *resolution_x_xpm[];
extern const char *resolution_y_xpm[];
+extern const char *cms_xpm[];
extern const char *scanner_xpm[];
extern const char *intensity_xpm[];
extern const char *red_xpm[];
diff --git a/src/xsane-multipage-project.c b/src/xsane-multipage-project.c
index 20a1cc3..3721faa 100644
--- a/src/xsane-multipage-project.c
+++ b/src/xsane-multipage-project.c
@@ -3,7 +3,7 @@
xsane-multipage-project.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 2005 Oliver Rauch
+ Copyright (C) 2005-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -55,6 +55,7 @@ void xsane_multipage_dialog_close(void);
void xsane_multipage_project_save(void);
static gint xsane_multipage_dialog_delete();
static void xsane_multipage_filetype_callback(GtkWidget *filetype_option_menu, char *filetype);
+static void xsane_multipage_project_browse_filename_callback(GtkWidget *widget, gpointer data);
static void xsane_multipage_project_changed_callback(GtkWidget *widget, gpointer data);
static void xsane_multipage_project_load(void);
static void xsane_multipage_project_delete(void);
@@ -94,13 +95,11 @@ void xsane_multipage_dialog()
GtkWidget *multipage_project_exists_hbox, *button;
GtkWidget *hbox;
GtkWidget *scrolled_window, *list;
- GtkWidget *pixmapwidget, *text;
+ GtkWidget *text;
GtkWidget *pages_frame;
GtkWidget *label;
GtkWidget *filetype_menu, *filetype_item;
GtkWidget *filetype_option_menu;
- GdkPixmap *pixmap;
- GdkBitmap *mask;
char buf[64];
int filetype_nr;
int select_item;
@@ -133,10 +132,8 @@ void xsane_multipage_dialog()
gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
gtk_box_pack_start(GTK_BOX(multipage_scan_vbox), hbox, FALSE, FALSE, 1);
- pixmap = gdk_pixmap_create_from_xpm_d(xsane.dialog->window, &mask, xsane.bg_trans, (gchar **) multipage_xpm);
- pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
- gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
- gdk_drawable_unref(pixmap);
+ button = xsane_button_new_with_pixmap(xsane.dialog->window, hbox, multipage_xpm, DESC_MULTIPAGE_PROJECT_BROWSE,
+ (GtkSignalFunc) xsane_multipage_project_browse_filename_callback, NULL);
text = gtk_entry_new();
xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_MULTIPAGE_PROJECT);
@@ -148,7 +145,6 @@ void xsane_multipage_dialog()
xsane.project_entry = text;
xsane.project_entry_box = hbox;
- gtk_widget_show(pixmapwidget);
gtk_widget_show(text);
gtk_widget_show(hbox);
@@ -579,6 +575,65 @@ static void xsane_multipage_project_create()
/* ---------------------------------------------------------------------------------------------------------------------- */
+void xsane_multipage_project_set_filename(gchar *filename)
+{
+ g_signal_handlers_block_by_func(GTK_OBJECT(xsane.project_entry), (GtkSignalFunc) xsane_multipage_project_changed_callback, NULL);
+ gtk_entry_set_text(GTK_ENTRY(xsane.project_entry), (char *) filename); /* update filename in entry */
+ gtk_entry_set_position(GTK_ENTRY(xsane.project_entry), strlen(filename)); /* set cursor to right position of filename */
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(xsane.project_entry), (GtkSignalFunc) xsane_multipage_project_changed_callback, NULL);
+}
+
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_multipage_project_browse_filename_callback(GtkWidget *widget, gpointer data)
+{
+ char filename[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_multipage_project_browse_filename_callback\n");
+
+ xsane_set_sensitivity(FALSE);
+
+ if (preferences.multipage_project) /* make sure a correct filename is defined */
+ {
+ strncpy(filename, preferences.multipage_project, sizeof(filename));
+ filename[sizeof(filename) - 1] = '\0';
+ }
+ else /* no filename given, take standard filename */
+ {
+ strcpy(filename, OUT_FILENAME);
+ }
+
+ snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_MULTIPAGE_PROJECT_BROWSE, xsane.device_text);
+
+ umask((mode_t) preferences.directory_umask); /* define new file permissions */
+ if (!xsane_back_gtk_get_filename(windowname, filename, sizeof(filename), filename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_PROJECT, XSANE_GET_FILENAME_SHOW_NOTHING, 0, 0))
+ {
+
+ if (preferences.multipage_project)
+ {
+ free((void *) preferences.multipage_project);
+ }
+
+ preferences.multipage_project = strdup(filename);
+
+ xsane_set_sensitivity(TRUE);
+ xsane_multipage_project_set_filename(filename);
+
+ xsane_multipage_project_load();
+ }
+ else
+ {
+ xsane_set_sensitivity(TRUE);
+ }
+ umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
+
+}
+
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
static void xsane_multipage_project_changed_callback(GtkWidget *widget, gpointer data)
{
DBG(DBG_proc, "xsane_multipage_project_changed_callback\n");
@@ -913,11 +968,11 @@ static void xsane_multipage_save_file()
if (output_format == XSANE_PS)
{
- xsane_save_ps_create_document_header(outfile, pages, preferences.save_ps_flatdecoded);
+ xsane_save_ps_create_document_header(outfile, pages, preferences.save_ps_flatedecoded);
}
else if (output_format == XSANE_PDF)
{
- xsane_save_pdf_create_document_header(outfile, &xref, pages, preferences.save_pdf_flatdecoded);
+ xsane_save_pdf_create_document_header(outfile, &xref, pages, preferences.save_pdf_flatedecoded);
}
}
#ifdef HAVE_LIBTIFF
@@ -1032,7 +1087,8 @@ static void xsane_multipage_save_file()
xsane_save_ps_page(outfile, page,
imagefile, &image_info, imagewidth, imageheight,
0, 0, imagewidth, imageheight, 0 /* portrait top left */,
- preferences.save_ps_flatdecoded,
+ preferences.save_ps_flatedecoded,
+ NULL /* hTransform */, 0 /* embed_scanner_icm_profile */,
xsane.project_progress_bar, &cancel_save);
}
else if (output_format == XSANE_PDF)
@@ -1043,14 +1099,31 @@ static void xsane_multipage_save_file()
xsane_save_pdf_page(outfile, &xref, page,
imagefile, &image_info, imagewidth, imageheight,
0, 0, imagewidth, imageheight, 0 /* portrait top left */,
- preferences.save_pdf_flatdecoded,
+ preferences.save_pdf_flatedecoded,
+ NULL /* hTransform */, 0 /* embed_scanner_icm_profile */, 0 /* icc_object */,
xsane.project_progress_bar, &cancel_save);
}
#ifdef HAVE_LIBTIFF
else if (output_format == XSANE_TIFF)
{
- xsane_save_tiff_page(tiffile, page, pages, imagefile, &image_info, preferences.jpeg_quality,
+ cmsHTRANSFORM hTransform = NULL;
+
+#ifdef HAVE_LIBLCMS
+ if ( (preferences.cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && xsane.enable_color_management )
+ {
+ hTransform = xsane_create_cms_transform(&image_info, preferences.cms_function, preferences.cms_intent, preferences.cms_bpc);
+ }
+#endif
+
+ xsane_save_tiff_page(tiffile, page, pages, preferences.jpeg_quality, imagefile, &image_info,
+ hTransform, xsane.enable_color_management, preferences.cms_function,
xsane.project_progress_bar, &cancel_save);
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ cmsDeleteTransform(hTransform);
+ }
+#endif
}
#endif
diff --git a/src/xsane-multipage-project.h b/src/xsane-multipage-project.h
index 5f945eb..090ebc3 100644
--- a/src/xsane-multipage-project.h
+++ b/src/xsane-multipage-project.h
@@ -3,7 +3,7 @@
xsane-multipage-project.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 2005 Oliver Rauch
+ Copyright (C) 2005-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-preferences.c b/src/xsane-preferences.c
index 011e802..2705477 100644
--- a/src/xsane-preferences.c
+++ b/src/xsane-preferences.c
@@ -3,7 +3,7 @@
xsane-preferences.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -55,6 +55,9 @@ Preferences preferences =
0, /* default working_directory */
0, /* no default filename */
0, /* no default filetype */
+ 0, /* default cms_function: embed scanner profile */
+ 0, /* default cms_intent: perceptual */
+ 0, /* default cms_bpc (black point compensation) off */
0137, /* image umask (permission mask for -rw-r------) */
0027, /* directory umask (permission mask for -rwxr-x----) */
0, /* no fax project */
@@ -69,7 +72,7 @@ Preferences preferences =
0.0, /* fax_leftoffset */
0.0, /* fax_bottomoffset */
1, /* fax_fine_mode */
- 1, /* fax_ps_flatdecoded */
+ 1, /* fax_ps_flatedecoded */
#ifdef XSANE_ACTIVATE_EMAIL
0, /* no default from email address */
0, /* no default reply to email address */
@@ -101,8 +104,8 @@ Preferences preferences =
1, /* save_devprefs_at_exit */
1, /* overwrite_warning */
1, /* skip_existing_numbers */
- 1, /* save_ps_flatdecoded */
- 1, /* save_pdf_flatdecoded */
+ 1, /* save_ps_flatedecoded */
+ 1, /* save_pdf_flatedecoded */
0, /* save_pnm16_as_ascii */
0, /* reduce_16bit_to_8bit */
1, /* filename_counter_step */
@@ -168,6 +171,9 @@ desc[] =
{"working-directory", xsane_rc_pref_string, POFFSET(working_directory)},
{"filename", xsane_rc_pref_string, POFFSET(filename)},
{"filetype", xsane_rc_pref_string, POFFSET(filetype)},
+ {"cms-function", xsane_rc_pref_int, POFFSET(cms_function)},
+ {"cms-intent", xsane_rc_pref_int, POFFSET(cms_intent)},
+ {"cms-bpc", xsane_rc_pref_int, POFFSET(cms_bpc)},
{"image-umask", xsane_rc_pref_int, POFFSET(image_umask)},
{"directory-umask", xsane_rc_pref_int, POFFSET(directory_umask)},
{"fax-project", xsane_rc_pref_string, POFFSET(fax_project)},
@@ -182,7 +188,7 @@ desc[] =
{"fax-left-offset", xsane_rc_pref_double, POFFSET(fax_leftoffset)},
{"fax-bottom-offset", xsane_rc_pref_double, POFFSET(fax_bottomoffset)},
{"fax-fine-mode", xsane_rc_pref_int, POFFSET(fax_fine_mode)},
- {"fax-ps-flatdecoded", xsane_rc_pref_int, POFFSET(fax_ps_flatdecoded)},
+ {"fax-ps-flatedecoded", xsane_rc_pref_int, POFFSET(fax_ps_flatedecoded)},
#ifdef XSANE_ACTIVATE_EMAIL
{"e-mail-from", xsane_rc_pref_string, POFFSET(email_from)},
{"e-mail-reply-to", xsane_rc_pref_string, POFFSET(email_reply_to)},
@@ -214,8 +220,8 @@ desc[] =
{"save-devprefs-at-exit", xsane_rc_pref_int, POFFSET(save_devprefs_at_exit)},
{"overwrite-warning", xsane_rc_pref_int, POFFSET(overwrite_warning)},
{"skip-existing-numbers", xsane_rc_pref_int, POFFSET(skip_existing_numbers)},
- {"save-ps-flatdecoded", xsane_rc_pref_int, POFFSET(save_ps_flatdecoded)},
- {"save-pdf-flatdecoded", xsane_rc_pref_int, POFFSET(save_pdf_flatdecoded)},
+ {"save-ps-flatedecoded", xsane_rc_pref_int, POFFSET(save_ps_flatedecoded)},
+ {"save-pdf-flatedecoded", xsane_rc_pref_int, POFFSET(save_pdf_flatedecoded)},
{"save-pnm16-as-ascii", xsane_rc_pref_int, POFFSET( save_pnm16_as_ascii)},
{"reduce-16bit-to8bit", xsane_rc_pref_int, POFFSET(reduce_16bit_to_8bit)},
{"filename-counter-step", xsane_rc_pref_int, POFFSET(filename_counter_step)},
@@ -231,6 +237,9 @@ desc[] =
{"show-resolution-list", xsane_rc_pref_int, POFFSET(show_resolution_list)},
{"length-unit", xsane_rc_pref_double, POFFSET(length_unit)},
{"main-window-fixed", xsane_rc_pref_int, POFFSET(main_window_fixed)},
+ {"display-icm-profile", xsane_rc_pref_string, POFFSET(display_icm_profile)},
+ {"custom-proofing-icm-profile", xsane_rc_pref_string, POFFSET(custom_proofing_icm_profile)},
+ {"working-color-space-icm-profile", xsane_rc_pref_string, POFFSET(working_color_space_icm_profile)},
{"preview-own-cmap", xsane_rc_pref_int, POFFSET(preview_own_cmap)},
{"preview-oversampling", xsane_rc_pref_double, POFFSET(preview_oversampling)},
{"preview-gamma", xsane_rc_pref_double, POFFSET(preview_gamma)},
@@ -289,7 +298,11 @@ desc_printer[] =
{"printer-gamma-red", xsane_rc_pref_double, PRTOFFSET(gamma_red)},
{"printer-gamma-green", xsane_rc_pref_double, PRTOFFSET(gamma_green)},
{"printer-gamma-blue", xsane_rc_pref_double, PRTOFFSET(gamma_blue)},
- {"printer-ps-flatdecoded", xsane_rc_pref_int, PRTOFFSET(ps_flatdecoded)}
+ {"printer-icm-profile", xsane_rc_pref_string, PRTOFFSET(icm_profile)},
+ {"printer-ps-flatedecoded", xsane_rc_pref_int, PRTOFFSET(ps_flatedecoded)},
+ {"printer-embed-csa", xsane_rc_pref_int, PRTOFFSET(embed_csa)},
+ {"printer-embed-crd", xsane_rc_pref_int, PRTOFFSET(embed_crd)},
+ {"printer-bpc", xsane_rc_pref_int, PRTOFFSET(blackpointcompensation)}
};
/* --------------------------------------------------------------------- */
diff --git a/src/xsane-preferences.h b/src/xsane-preferences.h
index 9f0e442..916df37 100644
--- a/src/xsane-preferences.h
+++ b/src/xsane-preferences.h
@@ -3,7 +3,7 @@
xsane-preferences.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -48,7 +48,11 @@ typedef struct
double gamma_red; /* printer gamma red */
double gamma_green; /* printer gamma green */
double gamma_blue; /* printer gamma blue */
- int ps_flatdecoded; /* flatdecode (zlib compression), ps level 3 */
+ char *icm_profile; /* printer ICM profile */
+ int ps_flatedecoded; /* flatedecode (zlib compression), ps level 3 */
+ int embed_csa; /* CSA = scanner ICM profile for postscript files */
+ int embed_crd; /* CRD = printer ICM profile for postscript files */
+ int blackpointcompensation; /* bpc */
}
Preferences_printer_t;
@@ -93,6 +97,9 @@ typedef struct
char *working_directory; /* directory where xsane saves images etc */
char *filename; /* default filename */
char *filetype; /* default filetype */
+ int cms_function; /* cms function (embed/srgb/working cs) */
+ int cms_intent; /* cms rendering intent */
+ int cms_bpc; /* cms black point compensation */
int image_umask; /* image umask (permisson mask) */
int directory_umask; /* directory umask (permisson mask) */
@@ -108,7 +115,7 @@ typedef struct
double fax_leftoffset; /* left offset of fax paper in mm */
double fax_bottomoffset; /* bottom offset of fax paper in mm */
int fax_fine_mode; /* use fine or normal mode */
- int fax_ps_flatdecoded; /* use postscript level 3 zlib compression */
+ int fax_ps_flatedecoded; /* use postscript level 3 zlib compression */
#ifdef XSANE_ACTIVATE_EMAIL
char *email_from; /* email address of sender */
@@ -144,8 +151,8 @@ typedef struct
int save_devprefs_at_exit; /* save device preferences at exit */
int overwrite_warning; /* warn if file exists */
int skip_existing_numbers; /* skip used filenames when automatically increase counter */
- int save_ps_flatdecoded; /* use zlib to for postscript compression (flatdecode) */
- int save_pdf_flatdecoded; /* use zlib to for pdf compression (flatdecode) */
+ int save_ps_flatedecoded; /* use zlib to for postscript compression (flatedecode) */
+ int save_pdf_flatedecoded; /* use zlib to for pdf compression (flatedecode) */
int save_pnm16_as_ascii; /* selection if pnm 16 bit is saved as ascii or binary file */
int reduce_16bit_to_8bit; /* reduce images with 16 bits/color to 8 bits/color */
int filename_counter_step; /* filename_counter += filename_counter_step; */
@@ -192,6 +199,10 @@ typedef struct
int gtk_update_policy;
int medium_nr;
+ char *display_icm_profile;
+ char *custom_proofing_icm_profile;
+ char *working_color_space_icm_profile;
+
int paper_orientation; /* image position on printer and page orientation */
int printernr; /* number of printers */
int printerdefinitions;
diff --git a/src/xsane-preview.c b/src/xsane-preview.c
index 46d8611..45679f1 100644
--- a/src/xsane-preview.c
+++ b/src/xsane-preview.c
@@ -3,7 +3,7 @@
xsane-preview.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -196,7 +196,9 @@ static void preview_establish_ratio(Preview *p);
static void preview_ratio_callback(GtkWidget *widget, gpointer data);
static void preview_autoselect_scanarea_callback(GtkWidget *window, gpointer data);
+void preview_display_with_correction(Preview *p);
void preview_do_gamma_correction(Preview *p);
+int preview_do_color_correction(Preview *p);
void preview_calculate_raw_histogram(Preview *p, SANE_Int *count_raw, SANE_Int *count_raw_red, SANE_Int *count_raw_green, SANE_Int *count_raw_blue);
void preview_calculate_enh_histogram(Preview *p, SANE_Int *count, SANE_Int *count_red, SANE_Int *count_green, SANE_Int *count_blue);
void preview_gamma_correction(Preview *p, int gamma_input_bits,
@@ -1276,7 +1278,7 @@ static void preview_display_image(Preview *p)
assert(p->image_data_enh);
}
- preview_do_gamma_correction(p);
+ preview_display_with_correction(p);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
@@ -1452,8 +1454,9 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
{
SANE_Status status;
Preview *p = data;
- u_char buf[8192];
- guint16 *buf16 = (guint16 *) buf;
+ char buf[TEXTBUFSIZE];
+ u_char imagebuf8[8192];
+ guint16 *imagebuf16 = (guint16 *) imagebuf8;
SANE_Handle dev;
SANE_Int len;
int i, j;
@@ -1465,26 +1468,26 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
{
if ((p->params.depth == 1) || (p->params.depth == 8))
{
- status = sane_read(dev, buf, sizeof(buf), &len);
+ status = sane_read(dev, imagebuf8, sizeof(imagebuf8), &len);
}
else if (p->params.depth == 16)
{
if (p->read_offset_16)
{
- buf[0] = p->last_offset_16_byte;
- /* use buf and sizeof(buf) here because sizeof(buf16) returns the size of a pointer */
- status = sane_read(dev, buf+1, sizeof(buf) - 1, &len);
+ imagebuf8[0] = p->last_offset_16_byte;
+ /* use imagebuf8 and sizeof(imagebuf8) here because sizeof(imagebuf16) returns the size of a pointer */
+ status = sane_read(dev, imagebuf8+1, sizeof(imagebuf8) - 1, &len);
len++;
}
else
{
- status = sane_read(dev, (SANE_Byte *) buf16, sizeof(buf), &len);
+ status = sane_read(dev, (SANE_Byte *) imagebuf16, sizeof(imagebuf8), &len);
}
if (len % 2) /* odd number of bytes */
{
len--;
- p->last_offset_16_byte = buf16[len];
+ p->last_offset_16_byte = imagebuf16[len];
p->read_offset_16 = 1;
}
else /* even number of bytes */
@@ -1576,8 +1579,8 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
return; /* backend sends too much image data */
}
- p->image_data_raw[p->image_offset] = buf[i] * 256;
- p->image_data_enh[p->image_offset++] = buf[i];
+ p->image_data_raw[p->image_offset] = imagebuf8[i] * 256;
+ p->image_data_enh[p->image_offset++] = imagebuf8[i];
if (p->image_offset%3 == 0)
{
@@ -1599,8 +1602,8 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
return; /* backend sends too much image data */
}
- p->image_data_raw[p->image_offset] = buf16[i];
- p->image_data_enh[p->image_offset++] = (u_char) (buf16[i]/256);
+ p->image_data_raw[p->image_offset] = imagebuf16[i];
+ p->image_data_enh[p->image_offset++] = (u_char) (imagebuf16[i]/256);
if (p->image_offset%3 == 0)
{
@@ -1627,7 +1630,7 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
case 1:
for (i = 0; i < len; ++i)
{
- u_char mask = buf[i];
+ u_char mask = imagebuf8[i];
if (preview_test_image_y(p))
{
@@ -1662,7 +1665,7 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
case 8:
for (i = 0; i < len; ++i)
{
- u_char gray = buf[i];
+ u_char gray = imagebuf8[i];
if (preview_test_image_y(p))
{
@@ -1687,20 +1690,20 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
case 16:
for (i = 0; i < len/2; ++i)
{
- u_char gray = buf16[i]/256;
+ u_char gray = imagebuf16[i]/256;
if (preview_test_image_y(p))
{
return; /* backend sends too much image data */
}
- p->image_data_raw[p->image_offset] = buf16[i];
+ p->image_data_raw[p->image_offset] = imagebuf16[i];
p->image_data_enh[p->image_offset++] = gray;
- p->image_data_raw[p->image_offset] = buf16[i];
+ p->image_data_raw[p->image_offset] = imagebuf16[i];
p->image_data_enh[p->image_offset++] = gray;
- p->image_data_raw[p->image_offset] = buf16[i];
+ p->image_data_raw[p->image_offset] = imagebuf16[i];
p->image_data_enh[p->image_offset++] = gray;
if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
@@ -1726,7 +1729,7 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
case 1:
for (i = 0; i < len; ++i)
{
- u_char mask = buf[i];
+ u_char mask = imagebuf8[i];
if (preview_test_image_y(p))
{
@@ -1758,8 +1761,8 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
return; /* backend sends too much image data */
}
- p->image_data_raw[p->image_offset] = buf[i] * 256;
- p->image_data_enh[p->image_offset] = buf[i];
+ p->image_data_raw[p->image_offset] = imagebuf8[i] * 256;
+ p->image_data_enh[p->image_offset] = imagebuf8[i];
p->image_offset += 3;
if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
@@ -1777,8 +1780,8 @@ static void preview_read_image_data(gpointer data, gint source, GdkInputConditio
return; /* backend sends too much image data */
}
- p->image_data_raw[p->image_offset] = buf16[i];
- p->image_data_enh[p->image_offset] = (u_char) (buf16[i]/256);
+ p->image_data_raw[p->image_offset] = imagebuf16[i];
+ p->image_data_enh[p->image_offset] = (u_char) (imagebuf16[i]/256);
p->image_offset += 3;
if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
@@ -1880,7 +1883,7 @@ static void preview_scan_done(Preview *p, int save_image)
xsane_update_histogram(TRUE /* update_raw */); /* update histogram (necessary because overwritten by preview_update_surface) */
}
- if ((preferences.auto_correct_colors) && (!xsane.medium_calibration))
+ if ((preferences.auto_correct_colors) && (!xsane.medium_calibration) && (!xsane.enable_color_management))
{
xsane_calculate_raw_histogram();
xsane_set_auto_enhancement();
@@ -2418,6 +2421,7 @@ void preview_create_batch_icon(Preview *p, Batch_Scan_Parameters *parameters)
if (in)
{
quality = preview_create_batch_icon_from_file(xsane.preview, in, parameters, quality, &time);
+ fclose(in);
}
}
}
@@ -2426,19 +2430,14 @@ void preview_create_batch_icon(Preview *p, Batch_Scan_Parameters *parameters)
{
char filename[PATH_MAX];
- if (in)
- {
- fclose(in);
- }
-
xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, "xsane-startimage", 0, ".pnm", XSANE_PATH_SYSTEM);
in = fopen(filename, "rb"); /* read binary (b for win32) */
if (in)
{
preview_create_batch_icon_from_file(xsane.preview, in, parameters, -1, &time);
+ fclose(in);
}
}
- fclose(in);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
@@ -2767,7 +2766,7 @@ static void preview_display_zoom(Preview *p, int x, int y, int zoom)
int r, g, b;
int px, py;
int i;
- char *row;
+ u_char *row;
DBG(DBG_proc, "preview_display_zoom");
@@ -4241,7 +4240,7 @@ Preview *preview_new(void)
p->maximum_output_height = INF; /* full output height */
p->block_update_maximum_output_size_clipping = FALSE;
- p->preview_colors = -1;
+ p->preview_channels = -1;
p->invalid = TRUE; /* no valid preview */
p->ratio = 0.0;
@@ -4563,7 +4562,6 @@ Preview *preview_new(void)
gtk_widget_show(p->invalid_pixmap);
gdk_drawable_unref(pixmap);
-
/* Start button */
p->start = gtk_button_new_with_label(BUTTON_PREVIEW_ACQUIRE);
xsane_back_gtk_set_tooltip(xsane.tooltips, p->start, DESC_PREVIEW_ACQUIRE);
@@ -4853,7 +4851,7 @@ void preview_update_surface(Preview *p, int surface_changed)
DBG(DBG_info, "preview_update_surface: establish new surface\n");
preview_area_correct(p); /* calculate preview_width and height */
preview_area_resize(p); /* correct rulers */
- preview_do_gamma_correction(p); /* draw preview */
+ preview_display_with_correction(p); /* draw preview */
xsane_update_histogram(TRUE /* update raw */);
p->previous_selection.active = FALSE;
@@ -5013,7 +5011,7 @@ void preview_scan(Preview *p)
gamma_data = malloc(gamma_gray_size * sizeof(SANE_Int));
- if ((xsane.xsane_colors > 1) || (xsane.no_preview_medium_gamma)) /* color scan or medium preview gamma disabled */
+ if ((xsane.xsane_channels > 1) || (xsane.no_preview_medium_gamma)) /* color scan or medium preview gamma disabled */
{
xsane_create_gamma_curve(gamma_data, 0, 1.0, 0.0, 0.0, 0.0, 100.0, 1.0, gamma_gray_size, gamma_gray_max);
}
@@ -5089,7 +5087,7 @@ void preview_scan(Preview *p)
xsane.block_update_param = FALSE;
- p->preview_colors = xsane.xsane_colors;
+ p->preview_channels = xsane.xsane_channels;
p->scan_incomplete = FALSE;
p->invalid = TRUE; /* no valid preview */
p->scanning = TRUE;
@@ -6204,6 +6202,29 @@ static void preview_autoselect_scanarea_callback(GtkWidget *window, gpointer dat
/* ---------------------------------------------------------------------------------------------------------------------- */
+void preview_display_with_correction(Preview *p)
+{
+#ifdef HAVE_LIBLCMS
+ if (xsane.enable_color_management)
+ {
+ preview_do_color_correction(p);
+ gtk_widget_set_sensitive(p->pipette_white, FALSE); /* disable pipette buttons */
+ gtk_widget_set_sensitive(p->pipette_gray, FALSE); /* disable pipette buttons */
+ gtk_widget_set_sensitive(p->pipette_black, FALSE); /* disable pipette buttons */
+
+ }
+ else
+#endif
+ {
+ preview_do_gamma_correction(p);
+ gtk_widget_set_sensitive(p->pipette_white, TRUE); /* enable pipette buttons */
+ gtk_widget_set_sensitive(p->pipette_gray, TRUE); /* enable pipette buttons */
+ gtk_widget_set_sensitive(p->pipette_black, TRUE); /* enable pipette buttons */
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
void preview_do_gamma_correction(Preview *p)
{
int x,y;
@@ -6212,7 +6233,7 @@ void preview_do_gamma_correction(Preview *p)
guint16 *image_data_rawp = NULL;
int rotate = 16 - preview_gamma_input_bits;
- DBG(DBG_proc, "preview_do_gamma_correction\n");
+ DBG(DBG_proc, "preview_display_with_correction\n");
if ((p->image_data_raw) && (p->params.depth > 1) && (preview_gamma_data_red))
{
@@ -6239,7 +6260,7 @@ void preview_do_gamma_correction(Preview *p)
{
while (gtk_events_pending())
{
- DBG(DBG_info, "preview_do_gamma_correction: calling gtk_main_iteration\n");
+ DBG(DBG_info, "preview_display_with_correction: calling gtk_main_iteration\n");
gtk_main_iteration();
}
}
@@ -6288,6 +6309,167 @@ void preview_do_gamma_correction(Preview *p)
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+int preview_do_color_correction(Preview *p)
+{
+ int y;
+ u_char *image_data_enhp = NULL;
+ guint16 *image_data_rawp = NULL;
+ cmsHPROFILE hInProfile = NULL;
+ cmsHPROFILE hOutProfile = NULL;
+ cmsHPROFILE hProofProfile = NULL;
+ cmsHTRANSFORM hTransform = NULL;
+ DWORD input_format, output_format;
+ DWORD cms_flags = 0;
+ int proof = 0;
+ char *cms_proof_icm_profile = NULL;
+ int linesize = 0;
+
+
+ DBG(DBG_proc, "preview_do_color_correction\n");
+
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ if (preferences.cms_bpc)
+ {
+ cms_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+ }
+
+ switch (p->cms_proofing)
+ {
+ default:
+ case 0: /* display */
+ proof = 0;
+ break;
+
+ case 1: /* proof printer */
+ cms_proof_icm_profile = preferences.printer[preferences.printernr]->icm_profile;
+ proof = 1;
+ break;
+
+ case 2: /* proof custom proofing */
+ cms_proof_icm_profile = preferences.custom_proofing_icm_profile;
+ proof = 1;
+ break;
+ }
+
+ if ( (xsane.param.format == SANE_FRAME_RGB) || /* color preview */
+ (xsane.param.format == SANE_FRAME_RED) ||
+ (xsane.param.format == SANE_FRAME_GREEN) ||
+ (xsane.param.format == SANE_FRAME_BLUE) )
+ {
+ input_format = TYPE_RGB_16;
+ output_format = TYPE_RGB_8;
+ linesize = p->image_width * 3;
+ }
+ else
+ {
+ input_format = TYPE_GRAY_16;
+ output_format = TYPE_GRAY_8;
+ linesize = p->image_width;
+ }
+
+ hInProfile = cmsOpenProfileFromFile(xsane.scanner_default_color_icm_profile, "r");
+ if (!hInProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_SCANNER_ICM, xsane.scanner_default_color_icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+ hOutProfile = cmsOpenProfileFromFile(preferences.display_icm_profile, "r");
+ if (!hOutProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_DISPLAY_ICM, preferences.display_icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+ if (proof == 0)
+ {
+ hTransform = cmsCreateTransform(hInProfile, input_format,
+ hOutProfile, output_format,
+ preferences.cms_intent, cms_flags);
+ }
+ else /* proof */
+ {
+ cms_flags |= cmsFLAGS_SOFTPROOFING;
+
+ if (p->cms_gamut_check)
+ {
+ cms_flags |= cmsFLAGS_GAMUTCHECK;
+ }
+
+ hProofProfile = cmsOpenProfileFromFile(cms_proof_icm_profile, "r");
+ if (!hProofProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+ cmsCloseProfile(hOutProfile);
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_PROOF_ICM, cms_proof_icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+ hTransform = cmsCreateProofingTransform(hInProfile, input_format,
+ hOutProfile, output_format,
+ hProofProfile,
+ preferences.cms_intent, p->cms_proofing_intent, cms_flags);
+ }
+
+ if (!hTransform)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+ cmsCloseProfile(hOutProfile);
+ if (proof)
+ {
+ cmsCloseProfile(hProofProfile);
+ }
+
+ snprintf(buf, sizeof(buf), "%s\n%s\n", ERR_CMS_CONVERSION, ERR_CMS_CREATE_TRANSFORM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+
+ for (y=0; y < p->image_height; y++)
+ {
+ image_data_rawp = p->image_data_raw + linesize * y;
+ image_data_enhp = p->image_data_enh + linesize * y;
+
+ cmsDoTransform(hTransform, image_data_rawp, image_data_enhp, p->image_width);
+
+ if (p->gamma_functions_interruptable)
+ {
+ while (gtk_events_pending())
+ {
+ DBG(DBG_info, "preview_do_color_correction: calling gtk_main_iteration\n");
+ gtk_main_iteration();
+ }
+ }
+ }
+
+ if (p->image_data_enh)
+ {
+ preview_display_partial_image(p);
+ }
+
+ return 0;
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
void preview_calculate_raw_histogram(Preview *p, SANE_Int *count_raw, SANE_Int *count_raw_red, SANE_Int *count_raw_green, SANE_Int *count_raw_blue)
{
int x, y;
@@ -6625,7 +6807,7 @@ void preview_gamma_correction(Preview *p, int gamma_input_bits,
preview_gamma_input_bits = gamma_input_bits;
- preview_do_gamma_correction(p);
+ preview_display_with_correction(p);
preview_draw_selection(p);
}
@@ -7363,7 +7545,7 @@ void preview_display_valid(Preview *p)
gtk_widget_hide(p->valid_pixmap);
gtk_widget_hide(p->invalid_pixmap);
}
- else if ((xsane.medium_changed) || (xsane.xsane_colors != p->preview_colors) || (p->invalid) ) /* preview is not valid */
+ else if ((xsane.medium_changed) || (xsane.xsane_channels != p->preview_channels) || (p->invalid) ) /* preview is not valid */
{
DBG(DBG_info, "preview not vaild\n");
diff --git a/src/xsane-preview.h b/src/xsane-preview.h
index d57870e..a488ce2 100644
--- a/src/xsane-preview.h
+++ b/src/xsane-preview.h
@@ -3,7 +3,7 @@
xsane-preview.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -122,7 +122,7 @@ typedef struct
char last_offset_16_byte;
int scan_incomplete;
int invalid;
- int preview_colors;
+ int preview_channels;
time_t image_last_time_updated;
gint input_tag;
SANE_Parameters params;
@@ -153,6 +153,13 @@ typedef struct
int show_selection;
+#ifdef HAVE_LIBLCMS
+ int cms_enable;
+ int cms_proofing;
+ int cms_proofing_intent;
+ int cms_gamut_check;
+#endif
+
#if 0
Batch_selection *batch_selection;
#endif
diff --git a/src/xsane-rc-io.c b/src/xsane-rc-io.c
index 4a0af86..39a29ef 100644
--- a/src/xsane-rc-io.c
+++ b/src/xsane-rc-io.c
@@ -3,7 +3,7 @@
xsane-rc-io.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -119,7 +119,7 @@ void xsane_rc_io_w_void(Wire *w)
/* ---------------------------------------------------------------------------------------------------------------- */
-void xsane_rc_io_w_array(Wire *w, SANE_Word *len_ptr, void **v, WireCodecFunc w_element, size_t element_size)
+void xsane_rc_io_w_array(Wire *w, SANE_Word *len_ptr, char **v, WireCodecFunc w_element, size_t element_size)
{
SANE_Word len;
char *val;
@@ -180,7 +180,7 @@ void xsane_rc_io_w_array(Wire *w, SANE_Word *len_ptr, void **v, WireCodecFunc w_
/* ---------------------------------------------------------------------------------------------------------------- */
-void xsane_rc_io_w_ptr(Wire *w, void **v, WireCodecFunc w_value, size_t value_size)
+void xsane_rc_io_w_ptr(Wire *w, char **v, WireCodecFunc w_value, size_t value_size)
{
SANE_Word is_null;
@@ -352,7 +352,7 @@ void xsane_rc_io_w_device_ptr(Wire *w, SANE_Device **v)
{
DBG(DBG_wire, "xsane_rc_io_w_device_ptr\n");
- xsane_rc_io_w_ptr(w, (void **) v, (WireCodecFunc) xsane_rc_io_w_device, sizeof (**v));
+ xsane_rc_io_w_ptr(w, (char **) v, (WireCodecFunc) xsane_rc_io_w_device, sizeof (**v));
}
/* ---------------------------------------------------------------------------------------------------------------- */
@@ -360,6 +360,7 @@ void xsane_rc_io_w_device_ptr(Wire *w, SANE_Device **v)
void xsane_rc_io_w_option_descriptor(Wire *w, SANE_Option_Descriptor *v)
{
SANE_Word len;
+ char *data_ptr = NULL;
DBG(DBG_wire, "xsane_rc_io_w_option_descriptor\n");
@@ -378,7 +379,8 @@ void xsane_rc_io_w_option_descriptor(Wire *w, SANE_Option_Descriptor *v)
break;
case SANE_CONSTRAINT_RANGE:
- xsane_rc_io_w_ptr(w, (void **) &v->constraint.range, (WireCodecFunc) xsane_rc_io_w_range, sizeof (SANE_Range));
+ data_ptr = (char *) v->constraint.range;
+ xsane_rc_io_w_ptr(w, &data_ptr, (WireCodecFunc) xsane_rc_io_w_range, sizeof (SANE_Range));
break;
case SANE_CONSTRAINT_WORD_LIST:
@@ -386,16 +388,18 @@ void xsane_rc_io_w_option_descriptor(Wire *w, SANE_Option_Descriptor *v)
{
len = v->constraint.word_list[0] + 1;
}
- xsane_rc_io_w_array(w, &len, (void **) &v->constraint.word_list, w->codec.w_word, sizeof(SANE_Word));
+ data_ptr = (char *) v->constraint.word_list;
+ xsane_rc_io_w_array(w, &len, &data_ptr, w->codec.w_word, sizeof(SANE_Word));
break;
case SANE_CONSTRAINT_STRING_LIST:
if (w->direction != WIRE_DECODE)
- {
- for (len = 0; v->constraint.string_list[len]; ++len);
- ++len; /* send NULL string, too */
- }
- xsane_rc_io_w_array(w, &len, (void **) &v->constraint.string_list, w->codec.w_string, sizeof(SANE_String));
+ {
+ for (len = 0; v->constraint.string_list[len]; ++len);
+ ++len; /* send NULL string, too */
+ }
+ data_ptr = (char *) v->constraint.string_list;
+ xsane_rc_io_w_array(w, &len, &data_ptr, w->codec.w_string, sizeof(SANE_String));
break;
}
}
@@ -406,7 +410,7 @@ void xsane_rc_io_w_option_descriptor_ptr(Wire *w, SANE_Option_Descriptor **v)
{
DBG(DBG_wire, "xsane_rc_io_w_option_descriptor_ptr\n");
- xsane_rc_io_w_ptr(w, (void **) v, (WireCodecFunc) xsane_rc_io_w_option_descriptor, sizeof (**v));
+ xsane_rc_io_w_ptr(w, (char **) v, (WireCodecFunc) xsane_rc_io_w_option_descriptor, sizeof (**v));
}
/* ---------------------------------------------------------------------------------------------------------------- */
diff --git a/src/xsane-rc-io.h b/src/xsane-rc-io.h
index dab2555..bfd7a3c 100644
--- a/src/xsane-rc-io.h
+++ b/src/xsane-rc-io.h
@@ -3,7 +3,7 @@
xsane-rc-io.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -108,7 +108,7 @@ extern void xsane_rc_io_w_device_ptr(Wire *w, SANE_Device **v);
extern void xsane_rc_io_w_option_descriptor(Wire *w, SANE_Option_Descriptor *v);
extern void xsane_rc_io_w_option_descriptor_ptr(Wire *w, SANE_Option_Descriptor **v);
extern void xsane_rc_io_w_parameters(Wire *w, SANE_Parameters *v);
-extern void xsane_rc_io_w_array(Wire *w, SANE_Word *len, void **v, WireCodecFunc w_element, size_t element_size);
+extern void xsane_rc_io_w_array(Wire *w, SANE_Word *len, char **v, WireCodecFunc w_element, size_t element_size);
extern void xsane_rc_io_w_flush(Wire *w);
extern void xsane_rc_io_w_set_dir(Wire *w, WireDirection dir);
extern void xsane_rc_io_w_call(Wire *w, SANE_Word proc_num, WireCodecFunc w_arg, void *arg, WireCodecFunc w_reply, void *reply);
diff --git a/src/xsane-save.c b/src/xsane-save.c
index a56e2ce..cc5f934 100644
--- a/src/xsane-save.c
+++ b/src/xsane-save.c
@@ -3,7 +3,7 @@
xsane-save.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -430,6 +430,7 @@ void xsane_read_pnm_header(FILE *file, Image_info *image_info)
image_info->resolution_x = 72.0;
image_info->resolution_y = 72.0;
image_info->reduce_to_lineart = FALSE;
+ image_info->enable_color_management = FALSE;
while (strcmp(buf, "# XSANE data follows\n"))
{
@@ -483,6 +484,26 @@ void xsane_read_pnm_header(FILE *file, Image_info *image_info)
&image_info->contrast_green,
&image_info->contrast_blue);
}
+ else if (!strncmp(buf, "# color-management=", 20))
+ {
+ sscanf(buf+20, "%d", &image_info->enable_color_management);
+ }
+ else if (!strncmp(buf, "# cms-function =", 20))
+ {
+ sscanf(buf+20, "%d", &image_info->cms_function);
+ }
+ else if (!strncmp(buf, "# cms-intent =", 20))
+ {
+ sscanf(buf+20, "%d", &image_info->cms_intent);
+ }
+ else if (!strncmp(buf, "# cms-bpc =", 20))
+ {
+ sscanf(buf+20, "%d", &image_info->cms_bpc);
+ }
+ else if (!strncmp(buf, "# icm-profile =", 20))
+ {
+ sscanf(buf+20, "%s", image_info->icm_profile);
+ }
else if (!strncmp(buf, "# reduce to lineart", 20))
{
image_info->reduce_to_lineart = TRUE;
@@ -510,11 +531,11 @@ void xsane_read_pnm_header(FILE *file, Image_info *image_info)
fgetc(file); /* read exactly one newline character */
- image_info->colors = 1;
+ image_info->channels = 1;
if (filetype_nr == 6) /* ppm RGB */
{
- image_info->colors = 3;
+ image_info->channels = 3;
}
}
#ifdef SUPPORT_RGBA
@@ -534,12 +555,12 @@ void xsane_read_pnm_header(FILE *file, Image_info *image_info)
image_info->depth = 16;
}
- image_info->colors = 4;
+ image_info->channels = 4;
}
#endif
DBG(DBG_info, "xsane_read_pnm_header: width=%d, height=%d, depth=%d, colors=%d, resolution_x=%f, resolution_y=%f\n",
- image_info->image_width, image_info->image_height, image_info->depth, image_info->colors,
+ image_info->image_width, image_info->image_height, image_info->depth, image_info->channels,
image_info->resolution_x, image_info->resolution_y);
}
@@ -573,7 +594,7 @@ void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_a
}
- if (image_info->colors == 1)
+ if (image_info->channels == 1)
{
if (image_info->depth == 1)
{
@@ -618,6 +639,11 @@ void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_a
"# gamma = %3.2f\n"
"# brightness = %4.1f\n"
"# contrast = %4.1f\n"
+ "# color-management= %d\n"
+ "# cms-function = %d\n"
+ "# cms-intent = %d\n"
+ "# cms-bpc = %d\n"
+ "# icm-profile = %s\n"
"# XSANE data follows\n"
"%05d %05d\n"
"%d\n",
@@ -627,11 +653,16 @@ void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_a
image_info->gamma,
image_info->brightness,
image_info->contrast,
+ image_info->enable_color_management,
+ image_info->cms_function,
+ image_info->cms_intent,
+ image_info->cms_bpc,
+ image_info->icm_profile,
image_info->image_width, image_info->image_height,
maxval);
}
}
- else if (image_info->colors == 3)
+ else if (image_info->channels == 3)
{
fprintf(file, "P%d\n"
"# XSane settings:\n"
@@ -640,6 +671,11 @@ void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_a
"# gamma IRGB = %3.2f %3.2f %3.2f %3.2f\n"
"# brightness IRGB = %4.1f %4.1f %4.1f %4.1f\n"
"# contrast IRGB = %4.1f %4.1f %4.1f %4.1f\n"
+ "# color-management= %d\n"
+ "# cms-function = %d\n"
+ "# cms-intent = %d\n"
+ "# cms-bpc = %d\n"
+ "# icm-profile = %s\n"
"# XSANE data follows\n"
"%05d %05d\n" \
"%d\n",
@@ -649,11 +685,16 @@ void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_a
image_info->gamma, image_info->gamma_red, image_info->gamma_green, image_info->gamma_blue,
image_info->brightness, image_info->brightness_red, image_info->brightness_green, image_info->brightness_blue,
image_info->contrast, image_info->contrast_red, image_info->contrast_green, image_info->contrast_blue,
+ image_info->enable_color_management,
+ image_info->cms_function,
+ image_info->cms_intent,
+ image_info->cms_bpc,
+ image_info->icm_profile,
image_info->image_width, image_info->image_height,
maxval);
}
#ifdef SUPPORT_RGBA
- else if (image_info->colors == 4)
+ else if (image_info->channels == 4)
{
fprintf(file, "SANE_RGBA\n" \
"%d %d\n" \
@@ -793,6 +834,121 @@ int xsane_copy_file_by_name(char *output_filename, char *input_filename, GtkProg
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+cmsHTRANSFORM xsane_create_cms_transform(Image_info *image_info, int cms_function, int cms_intent, int cms_bpc)
+{
+ cmsHPROFILE hInProfile = NULL;
+ cmsHPROFILE hOutProfile = NULL;
+ cmsHTRANSFORM hTransform = NULL;
+ DWORD cms_input_format;
+ DWORD cms_output_format;
+ DWORD cms_flags = 0;
+
+ if (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE)
+ {
+ return NULL;
+ }
+
+ DBG(DBG_info, "Prepare CMS transform\n");
+
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ if (cms_bpc)
+ {
+ cms_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+ }
+
+ if (image_info->channels == 1) /* == 1 (grayscale) */
+ {
+ if (image_info->depth == 8)
+ {
+ cms_input_format = TYPE_GRAY_8;
+ cms_output_format = TYPE_GRAY_8;
+ }
+ else
+ {
+ cms_input_format = TYPE_GRAY_16;
+ cms_output_format = TYPE_GRAY_16;
+ }
+ }
+ else /* color */
+ {
+ if (image_info->depth == 8)
+ {
+ cms_input_format = TYPE_RGB_8;
+ cms_output_format = TYPE_RGB_8;
+ }
+ else
+ {
+ cms_input_format = TYPE_RGB_16;
+ cms_output_format = TYPE_RGB_16;
+ }
+ }
+
+ hInProfile = cmsOpenProfileFromFile(image_info->icm_profile, "r");
+ if (!hInProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_SCANNER_ICM, image_info->icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ }
+#if 0
+{
+ LPGAMMATABLE Gamma = cmsBuildGamma(256, 3.0);
+ hOutProfile = cmsCreateGrayProfile(cmsD50_xyY(), Gamma);
+ cmsFreeGamma(Gamma);
+}
+#endif
+ if (cms_function == XSANE_CMS_FUNCTION_CONVERT_TO_SRGB)
+ {
+ hOutProfile = cmsCreate_sRGBProfile();
+ }
+ else
+ {
+ hOutProfile = cmsOpenProfileFromFile(preferences.working_color_space_icm_profile, "r");
+ if (!hOutProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_DISPLAY_ICM, preferences.display_icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ }
+ }
+
+ if (!hOutProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+
+ snprintf(buf, sizeof(buf), "%s\n", ERR_CMS_CONVERSION);
+ xsane_back_gtk_error(buf, TRUE);
+ }
+
+ hTransform = cmsCreateTransform(hInProfile, cms_input_format,
+ hOutProfile, cms_output_format,
+ cms_intent, cms_flags);
+
+ cmsCloseProfile(hInProfile);
+ cmsCloseProfile(hOutProfile);
+
+ if (!hTransform)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s\n%s\n", ERR_CMS_CONVERSION, ERR_CMS_CREATE_TRANSFORM);
+ xsane_back_gtk_error(buf, TRUE);
+ }
+
+ return hTransform;
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
int xsane_save_grayscale_image_as_lineart(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
{
int x, y, bit;
@@ -901,14 +1057,14 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
image_info->resolution_x *= x_scale;
image_info->resolution_y *= y_scale;
- original_line = malloc(original_image_width * image_info->colors * bytespp);
+ original_line = malloc(original_image_width * image_info->channels * bytespp);
if (!original_line)
{
DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
return -1;
}
- new_line = malloc(new_image_width * image_info->colors * bytespp);
+ new_line = malloc(new_image_width * image_info->channels * bytespp);
if (!new_line)
{
free(original_line);
@@ -916,7 +1072,7 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
return -1;
}
- pixel_val = malloc(new_image_width * image_info->colors * sizeof(float));
+ pixel_val = malloc(new_image_width * image_info->channels * sizeof(float));
if (!pixel_val)
{
free(original_line);
@@ -925,7 +1081,7 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
return -1;
}
- pixel_norm = malloc(new_image_width * image_info->colors * sizeof(float));
+ pixel_norm = malloc(new_image_width * image_info->channels * sizeof(float));
if (!pixel_norm)
{
free(original_line);
@@ -939,8 +1095,8 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
read_line = TRUE;
- memset(pixel_val, 0, new_image_width * image_info->colors * sizeof(float));
- memset(pixel_norm, 0, new_image_width * image_info->colors * sizeof(float));
+ memset(pixel_val, 0, new_image_width * image_info->channels * sizeof(float));
+ memset(pixel_norm, 0, new_image_width * image_info->channels * sizeof(float));
y_new = 0;
y_go = 1.0 / y_scale;
@@ -960,7 +1116,7 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
if (read_line)
{
DBG(DBG_info, "xsane_save_scaled_image: reading original line %d\n", (int) y);
- fread(original_line, original_image_width, image_info->colors * bytespp, imagefile); /* read one line */
+ fread(original_line, original_image_width, image_info->channels * bytespp, imagefile); /* read one line */
original_line16 = (guint16 *) original_line;
}
@@ -970,23 +1126,22 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
x_factor = 1.0;
while ( (x < original_image_width) && (x_new < new_image_width) ) /* add this line to anti aliasing buffer */
-
{
factor = x_factor * y_factor;
- for (c = 0; c < image_info->colors; c++)
+ for (c = 0; c < image_info->channels; c++)
{
if (bytespp == 1)
{
- color = original_line[((int) x) * image_info->colors + c];
+ color = original_line[((int) x) * image_info->channels + c];
}
else /* bytespp == 2 */
{
- color = original_line16[((int) x) * image_info->colors + c];
+ color = original_line16[((int) x) * image_info->channels + c];
}
- pixel_val [x_new * image_info->colors + c] += factor * color;
- pixel_norm[x_new * image_info->colors + c] += factor;
+ pixel_val [x_new * image_info->channels + c] += factor * color;
+ pixel_norm[x_new * image_info->channels + c] += factor;
}
x_go -= x_factor;
@@ -1023,7 +1178,7 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
if (bytespp == 1)
{
- for (x_new = 0; x_new < new_image_width * image_info->colors; x_new++)
+ for (x_new = 0; x_new < new_image_width * image_info->channels; x_new++)
{
new_line[x_new] = (int) (pixel_val[x_new] / pixel_norm[x_new]);
}
@@ -1032,13 +1187,13 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
{
guint16 *new_line16 = (guint16 *) new_line;
- for (x_new = 0; x_new < new_image_width * image_info->colors; x_new++)
+ for (x_new = 0; x_new < new_image_width * image_info->channels; x_new++)
{
new_line16[x_new] = (int) (pixel_val[x_new] / pixel_norm[x_new]);
}
}
- fwrite(new_line, new_image_width, image_info->colors * bytespp, outfile); /* write one line */
+ fwrite(new_line, new_image_width, image_info->channels * bytespp, outfile); /* write one line */
if (ferror(outfile))
{
@@ -1052,8 +1207,8 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
}
/* reset values and norm factors */
- memset(pixel_val, 0, new_image_width * image_info->colors * sizeof(float));
- memset(pixel_norm, 0, new_image_width * image_info->colors * sizeof(float));
+ memset(pixel_val, 0, new_image_width * image_info->channels * sizeof(float));
+ memset(pixel_norm, 0, new_image_width * image_info->channels * sizeof(float));
y_new++;
y_go = 1.0 / y_scale;
@@ -1079,6 +1234,11 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
read_line = (oldy != (int) y);
}
+ if (read_line) /* we have to write one more line */
+ {
+ fwrite(new_line, new_image_width, image_info->channels * bytespp, outfile); /* write one line */
+ }
+
free(original_line);
free(new_line);
free(pixel_val);
@@ -1113,14 +1273,14 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
image_info->resolution_x *= x_scale;
image_info->resolution_y *= y_scale;
- original_line = malloc(original_image_width * image_info->colors * bytespp);
+ original_line = malloc(original_image_width * image_info->channels * bytespp);
if (!original_line)
{
DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
return -1;
}
- new_line = malloc(new_image_width * image_info->colors * bytespp);
+ new_line = malloc(new_image_width * image_info->channels * bytespp);
if (!new_line)
{
free(original_line);
@@ -1143,18 +1303,18 @@ int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_in
for (; ((int) original_y) - old_original_y; old_original_y += 1)
{
- fread(original_line, original_image_width, image_info->colors * bytespp, imagefile); /* read one line */
+ fread(original_line, original_image_width, image_info->channels * bytespp, imagefile); /* read one line */
}
for (x = 0; x < new_image_width; x++)
{
- for (i = 0; i < image_info->colors * bytespp; i++)
+ for (i = 0; i < image_info->channels * bytespp; i++)
{
- new_line[x * image_info->colors * bytespp + i] = original_line[((int) (x / x_scale)) * image_info->colors * bytespp + i];
+ new_line[x * image_info->channels * bytespp + i] = original_line[((int) (x / x_scale)) * image_info->channels * bytespp + i];
}
}
- fwrite(new_line, new_image_width, image_info->colors * bytespp, outfile); /* write one line */
+ fwrite(new_line, new_image_width, image_info->channels * bytespp, outfile); /* write one line */
original_y += 1/y_scale;
@@ -1187,7 +1347,7 @@ int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image
guint16 *color_cache_ptr;
int bytespp = 1;
int color_radius;
- int color_width = image_info->image_width * image_info->colors;
+ int color_width = image_info->image_width * image_info->channels;
radius--; /* correct radius : 1 means nothing happens */
@@ -1196,7 +1356,7 @@ int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image
radius = 1;
}
- color_radius = radius * image_info->colors;
+ color_radius = radius * image_info->channels;
if (image_info->depth > 8)
{
@@ -1252,7 +1412,7 @@ int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image
if (xmin < 0)
{
- xmin = x % image_info->colors;
+ xmin = x % image_info->channels;
}
if (xmax > color_width)
@@ -1271,11 +1431,11 @@ int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image
{
line_cache_ptr = line_cache + (sy-ymin) * color_width + xmin;
- for (sx = xmin; sx <= xmax; sx+=image_info->colors) /* x part */
+ for (sx = xmin; sx <= xmax; sx+=image_info->channels) /* x part */
{
*color_cache_ptr = *line_cache_ptr;
color_cache_ptr++;
- line_cache_ptr += image_info->colors;
+ line_cache_ptr += image_info->channels;
}
}
@@ -1314,11 +1474,11 @@ int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image
{
line_cache16_ptr = line_cache16 + (sy-ymin) * color_width + xmin;
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
+ for (sx = xmin; sx <= xmax; sx+=image_info->channels)
{
*color_cache_ptr = *line_cache16_ptr;
color_cache_ptr++;
- line_cache16_ptr += image_info->colors;
+ line_cache16_ptr += image_info->channels;
}
}
@@ -1407,14 +1567,14 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
xsane_write_pnm_header(outfile, image_info, 0);
- line_cache = malloc(image_info->image_width * image_info->colors * bytespp * (2 * intradius + 1));
+ line_cache = malloc(image_info->image_width * image_info->channels * bytespp * (2 * intradius + 1));
if (!line_cache)
{
DBG(DBG_error, "xsane_blur_image: out of memory\n");
return -1;
}
- fread(line_cache, image_info->image_width * image_info->colors * bytespp, (2 * intradius + 1), imagefile);
+ fread(line_cache, image_info->image_width * image_info->channels * bytespp, (2 * intradius + 1), imagefile);
for (y = 0; y < image_info->image_height; y++)
{
@@ -1424,22 +1584,22 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
gtk_main_iteration();
}
- for (x = 0; x < image_info->image_width * image_info->colors; x++)
+ for (x = 0; x < image_info->image_width * image_info->channels; x++)
{
xmin_flag = xmax_flag = ymin_flag = ymax_flag = TRUE;
- xmin = x - intradius * image_info->colors;
- xmax = x + intradius * image_info->colors;
+ xmin = x - intradius * image_info->channels;
+ xmax = x + intradius * image_info->channels;
if (xmin < 0)
{
- xmin = x % image_info->colors;
+ xmin = x % image_info->channels;
xmin_flag = FALSE;
}
- if (xmax > image_info->image_width * image_info->colors)
+ if (xmax > image_info->image_width * image_info->channels)
{
- xmax = image_info->image_width * image_info->colors;
+ xmax = image_info->image_width * image_info->channels;
xmax_flag = FALSE;
}
@@ -1467,7 +1627,7 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
{
for (sy = ymin+1; sy <= ymax-1 ; sy++)
{
- val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->colors + xmin];
+ val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->channels + xmin];
norm += outer_factor;
}
}
@@ -1476,14 +1636,14 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
{
for (sy = ymin+1; sy <= ymax-1 ; sy++)
{
- val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->colors + xmax];
+ val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->channels + xmax];
norm += outer_factor;
}
}
if (ymin_flag) /* integrate over top margin */
{
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
+ for (sx = xmin+image_info->channels; sx <= xmax-image_info->channels ; sx += image_info->channels)
{
val += outer_factor * line_cache[sx];
norm += outer_factor;
@@ -1492,18 +1652,18 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
if (ymax_flag) /* integrate over bottom margin */
{
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
+ for (sx = xmin+image_info->channels; sx <= xmax-image_info->channels ; sx += image_info->channels)
{
- val += outer_factor * line_cache[(ymax-ymin) * image_info->image_width * image_info->colors + sx];
+ val += outer_factor * line_cache[(ymax-ymin) * image_info->image_width * image_info->channels + sx];
norm += outer_factor;
}
}
for (sy = ymin+1; sy <= ymax-1; sy++) /* integrate internal square */
{
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors; sx+=image_info->colors)
+ for (sx = xmin+image_info->channels; sx <= xmax-image_info->channels; sx+=image_info->channels)
{
- val += line_cache[(sy-ymin) * image_info->image_width * image_info->colors + sx];
+ val += line_cache[(sy-ymin) * image_info->image_width * image_info->channels + sx];
norm += 1.0;
}
}
@@ -1519,7 +1679,7 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
{
for (sy = ymin+1; sy <= ymax-1 ; sy++)
{
- val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + xmin];
+ val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->channels + xmin];
norm += outer_factor;
}
}
@@ -1528,14 +1688,14 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
{
for (sy = ymin+1; sy <= ymax-1 ; sy++)
{
- val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + xmax];
+ val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->channels + xmax];
norm += outer_factor;
}
}
if (ymin_flag) /* integrate over top margin */
{
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
+ for (sx = xmin+image_info->channels; sx <= xmax-image_info->channels ; sx += image_info->channels)
{
val += outer_factor * line_cache16[sx];
norm += outer_factor;
@@ -1544,18 +1704,18 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
if (ymax_flag) /* integrate over bottom margin */
{
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
+ for (sx = xmin+image_info->channels; sx <= xmax-image_info->channels ; sx += image_info->channels)
{
- val += outer_factor * line_cache16[(ymax-ymin) * image_info->image_width * image_info->colors + sx];
+ val += outer_factor * line_cache16[(ymax-ymin) * image_info->image_width * image_info->channels + sx];
norm += outer_factor;
}
}
for (sy = ymin; sy <= ymax; sy++) /* integrate internal square */
{
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
+ for (sx = xmin; sx <= xmax; sx+=image_info->channels)
{
- val += line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + sx];
+ val += line_cache16[(sy-ymin) * image_info->image_width * image_info->channels + sx];
norm += 1.0;
}
}
@@ -1581,10 +1741,10 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
if ((y > intradius) && (y < image_info->image_height - intradius))
{
- memcpy(line_cache, line_cache + image_info->image_width * image_info->colors * bytespp,
- image_info->image_width * image_info->colors * bytespp * 2 * intradius);
- fread(line_cache + image_info->image_width * image_info->colors * bytespp * 2 * intradius,
- image_info->image_width * image_info->colors * bytespp, 1, imagefile);
+ memcpy(line_cache, line_cache + image_info->image_width * image_info->channels * bytespp,
+ image_info->image_width * image_info->channels * bytespp * 2 * intradius);
+ fread(line_cache + image_info->image_width * image_info->channels * bytespp * 2 * intradius,
+ image_info->image_width * image_info->channels * bytespp, 1, imagefile);
}
}
@@ -1616,14 +1776,14 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
xsane_write_pnm_header(outfile, image_info, 0);
- line_cache = malloc(image_info->image_width * image_info->colors * bytespp * (2 * radius + 1));
+ line_cache = malloc(image_info->image_width * image_info->channels * bytespp * (2 * radius + 1));
if (!line_cache)
{
DBG(DBG_error, "xsane_blur_image: out of memory\n");
return -1;
}
- fread(line_cache, image_info->image_width * image_info->colors * bytespp, (2 * radius + 1), imagefile);
+ fread(line_cache, image_info->image_width * image_info->channels * bytespp, (2 * radius + 1), imagefile);
for (y = 0; y < image_info->image_height; y++)
{
@@ -1633,19 +1793,19 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
gtk_main_iteration();
}
- for (x = 0; x < image_info->image_width * image_info->colors; x++)
+ for (x = 0; x < image_info->image_width * image_info->channels; x++)
{
- xmin = x - radius * image_info->colors;
- xmax = x + radius * image_info->colors;
+ xmin = x - radius * image_info->channels;
+ xmax = x + radius * image_info->channels;
if (xmin < 0)
{
- xmin = x % image_info->colors;
+ xmin = x % image_info->channels;
}
- if (xmax > image_info->image_width * image_info->colors)
+ if (xmax > image_info->image_width * image_info->channels)
{
- xmax = image_info->image_width * image_info->colors;
+ xmax = image_info->image_width * image_info->channels;
}
ymin = y - radius;
@@ -1668,9 +1828,9 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
{
for (sy = ymin; sy <= ymax; sy++)
{
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
+ for (sx = xmin; sx <= xmax; sx+=image_info->channels)
{
- val += line_cache[(sy-ymin) * image_info->image_width * image_info->colors + sx];
+ val += line_cache[(sy-ymin) * image_info->image_width * image_info->channels + sx];
count++;
}
}
@@ -1684,9 +1844,9 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
for (sy = ymin; sy <= ymax; sy++)
{
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
+ for (sx = xmin; sx <= xmax; sx+=image_info->channels)
{
- val += line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + sx];
+ val += line_cache16[(sy-ymin) * image_info->image_width * image_info->channels + sx];
count++;
}
}
@@ -1699,10 +1859,10 @@ int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info
if ((y > radius) && (y < image_info->image_height - radius))
{
- memcpy(line_cache, line_cache + image_info->image_width * image_info->colors * bytespp,
- image_info->image_width * image_info->colors * bytespp * 2 * radius);
- fread(line_cache + image_info->image_width * image_info->colors * bytespp * 2 * radius,
- image_info->image_width * image_info->colors * bytespp, 1, imagefile);
+ memcpy(line_cache, line_cache + image_info->image_width * image_info->channels * bytespp,
+ image_info->image_width * image_info->channels * bytespp * 2 * radius);
+ fread(line_cache + image_info->image_width * image_info->channels * bytespp * 2 * radius,
+ image_info->image_width * image_info->channels * bytespp, 1, imagefile);
}
}
@@ -1734,7 +1894,7 @@ int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_in
pos0 = ftell(imagefile); /* mark position to skip header */
- bytespp = image_info->colors;
+ bytespp = image_info->channels;
if (image_info->depth > 8)
{
@@ -2227,7 +2387,7 @@ int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_in
/* ---------------------------------------------------------------------------------------------------------------------- */
-void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdecode)
+void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatedecode)
{
DBG(DBG_proc, "xsane_save_ps_create_document_header\n");
@@ -2236,7 +2396,7 @@ void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdeco
SANE_VERSION_MAJOR(xsane.sane_backend_versioncode),
SANE_VERSION_MINOR(xsane.sane_backend_versioncode));
fprintf(outfile, "%%%%DocumentData: Clean7Bit\n");
- if (flatdecode)
+ if (flatedecode)
{
fprintf(outfile, "%%%%LanguageLevel: 3\n");
}
@@ -2288,7 +2448,7 @@ static void xsane_save_ps_create_page_header(FILE *outfile, int page,
float width, float height,
int paper_left_margin, int paper_bottom_margin,
int paper_width, int paper_height,
- int paper_orientation, int flatdecode,
+ int paper_orientation, int flatedecode,
GtkProgressBar *progress_bar)
{
int degree, position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth;
@@ -2377,7 +2537,7 @@ static void xsane_save_ps_create_page_header(FILE *outfile, int page,
if (depth > 8)
{
- depth = 8;
+ depth = 12;
}
fprintf(outfile, "\n");
@@ -2394,23 +2554,22 @@ static void xsane_save_ps_create_page_header(FILE *outfile, int page,
fprintf(outfile, "%d rotate\n", degree);
fprintf(outfile, "%d %d translate\n", position_left, position_bottom);
fprintf(outfile, "%f %f scale\n", width, height);
- fprintf(outfile, "%d %d %d\n", image_info->image_width, image_info->image_height, depth);
- fprintf(outfile, "[%d %d %d %d %d %d]\n", image_info->image_width, 0, 0, -image_info->image_height, 0, image_info->image_height);
- fprintf(outfile, "currentfile\n");
- fprintf(outfile, "/ASCII85Decode filter\n");
+ fprintf(outfile, "<<\n");
+ fprintf(outfile, " /ImageType 1\n");
+ fprintf(outfile, " /Width %d\n", image_info->image_width);
+ fprintf(outfile, " /Height %d\n", image_info->image_height);
+ fprintf(outfile, " /BitsPerComponent %d\n", depth);
+ fprintf(outfile, " /Decode [0 1 0 1 0 1]\n");
+ fprintf(outfile, " /ImageMatrix [%d %d %d %d %d %d]\n", image_info->image_width, 0, 0, -image_info->image_height, 0, image_info->image_height);
+ fprintf(outfile, " /DataSource currentfile /ASCII85Decode filter");
#ifdef HAVE_LIBZ
- if (flatdecode)
+ if (flatedecode)
{
- fprintf(outfile, "/FlateDecode filter\n");
+ fprintf(outfile, " /FlateDecode filter");
}
#endif
-
- if (image_info->colors == 3) /* what about RGBA here ? */
- {
- fprintf(outfile, "false 3 colorimage\n");
- fprintf(outfile, "\n");
- }
- else
+ fprintf(outfile, "\n");
+ fprintf(outfile, ">>\n");
{
fprintf(outfile, "image\n");
fprintf(outfile, "\n");
@@ -2429,8 +2588,102 @@ static void xsane_save_ps_create_page_trailer(FILE *outfile)
/* ---------------------------------------------------------------------------------------------------------------------- */
#ifdef HAVE_LIBZ
+/* Utility function for the PDF output */
+static int xsane_write_flatedecode(FILE *outfile, unsigned char *line, int len, int finish)
+{
+ static unsigned char *cbuf = NULL;
+ static int cbuflen = 0;
+ static int linelen = 0;
+ int outlen;
+ static int init = 0;
+ static z_stream s;
+ int ret;
+ int flush;
+ static int count = 0;
+
+ DBG(DBG_proc, "xsane_write_flatedecode\n");
+
+ if (linelen != len)
+ {
+ linelen = len;
+ if (cbuf != NULL)
+ {
+ free(cbuf);
+ }
+ /* buffer length = length + 0.1 * length + 12 (mandatory) */
+ cbuflen = len + len / 10 + 12;
+ cbuf = malloc(cbuflen);
+ }
+
+ if (cbuf == NULL)
+ {
+ DBG(DBG_error, "cbuf allocation failed\n");
+ return 1;
+ }
+
+ if (!init)
+ {
+ s.zalloc = Z_NULL;
+ s.zfree = Z_NULL;
+ s.opaque = Z_NULL;
+
+ ret = deflateInit(&s, Z_DEFAULT_COMPRESSION);
+
+ if (ret != Z_OK)
+ {
+ DBG(DBG_error, "deflateInit failed\n");
+ free(cbuf);
+ return 1;
+ }
+
+ init = 1;
+ }
+
+ s.avail_in = len;
+ s.next_in = line;
+
+ do
+ {
+ s.avail_out = cbuflen;
+ s.next_out = cbuf;
+
+ flush = (finish) ? Z_FINISH : Z_NO_FLUSH;
+
+ ret = deflate(&s, flush);
+
+ if (ret == Z_STREAM_ERROR)
+ {
+ DBG(DBG_error, "deflate failed\n");
+ free(cbuf);
+ return 1;
+ }
+
+ outlen = cbuflen - s.avail_out;
+
+ fwrite(cbuf, outlen, 1, outfile);
+ } while (s.avail_out == 0);
+
+ if (finish)
+ {
+ DBG(DBG_info, "xsane_write_flatedecode finished\n");
+ deflateEnd(&s);
+ free(cbuf);
+ cbuf = NULL;
+ init = 0;
+ cbuflen = 0;
+ linelen = 0;
+ count = 0;
+ }
+
+ return 0;
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+#ifdef HAVE_LIBZ
/* Utility function for the PostScript output */
-static int xsane_write_compressed_a85_flatdecode(FILE *outfile, unsigned char *line, int len, int finish)
+static int xsane_write_compressed_a85_flatedecode(FILE *outfile, unsigned char *line, int len, int finish)
{
static unsigned char *cbuf = NULL;
static int cbuflen = 0;
@@ -2446,7 +2699,7 @@ static int xsane_write_compressed_a85_flatdecode(FILE *outfile, unsigned char *l
static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0};
static int count = 0;
- DBG(DBG_proc, "xsane_write_compressed_a85_flatdecode\n");
+ DBG(DBG_proc, "xsane_write_compressed_a85_flatedecode\n");
if (linelen != len)
{
@@ -2741,7 +2994,91 @@ static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int le
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save)
+#ifdef HAVE_LIBLCMS
+static int xsane_write_CSA(FILE *outfile, char *input_profile, int intent)
+{
+ cmsHPROFILE hProfile;
+ size_t n;
+ char* buffer;
+
+ hProfile = cmsOpenProfileFromFile(input_profile, "r");
+ if (!hProfile)
+ {
+ return -1;
+ }
+
+ n = cmsGetPostScriptCSA(hProfile, intent, NULL, 0);
+ if (n == 0)
+ {
+ return -2;
+ }
+
+ buffer = (char*) malloc(n + 1);
+ if (!buffer)
+ {
+ return -3;
+ }
+
+ cmsGetPostScriptCSA(hProfile, intent, buffer, n);
+ buffer[n] = 0;
+
+ fprintf(outfile, "%s", buffer);
+ fprintf(outfile, "setcolorspace\n");
+
+ free(buffer);
+ cmsCloseProfile(hProfile);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static int xsane_write_CRD(FILE *outfile, char *output_profile, int intent, int blackpointcompensation)
+{
+ cmsHPROFILE hProfile;
+ size_t n;
+ char* buffer;
+ DWORD flags = cmsFLAGS_NODEFAULTRESOURCEDEF;
+
+ hProfile = cmsOpenProfileFromFile(output_profile, "r");
+ if (!hProfile)
+ {
+ return -1;
+ }
+
+ if (blackpointcompensation)
+ {
+ flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+ }
+
+ n = cmsGetPostScriptCRDEx(hProfile, intent, flags, NULL, 0);
+ if (n == 0)
+ {
+ return -2;
+ }
+
+ buffer = (char*) malloc(n + 1);
+ if (!buffer)
+ {
+ return -3;
+ }
+
+ cmsGetPostScriptCRDEx(hProfile, intent, flags, buffer, n);
+ buffer[n] = 0;
+
+ fprintf(outfile, "%s", buffer);
+ fprintf(outfile, "setcolorrendering\n");
+
+ free(buffer);
+ cmsCloseProfile(hProfile);
+
+ return 0;
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, int ascii85decode, int flatedecode, GtkProgressBar *progress_bar, int *cancel_save)
{
int x, y;
int bytes_per_line = (image_info->image_width+7)/8;
@@ -2778,15 +3115,26 @@ static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *imag
line[x] = fgetc(imagefile) ^ 255;
}
+ if (ascii85decode)
+ {
#ifdef HAVE_LIBZ
- if (flatdecode)
+ if (flatedecode)
+ {
+ ret = xsane_write_compressed_a85_flatedecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
+ }
+ else
+#endif
+ {
+ ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
+ }
+ }
+ else if (flatedecode)
{
- ret = xsane_write_compressed_a85_flatdecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
+ ret = xsane_write_flatedecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
}
else
-#endif
{
- ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
+ fwrite(line, bytes_per_line, 1, outfile);
}
if ((ret != 0) || (ferror(outfile)))
@@ -2822,11 +3170,15 @@ static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *imag
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save)
+static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, int ascii85decode, int flatedecode, cmsHTRANSFORM hTransform, int embed_scanner_icm_profile, GtkProgressBar *progress_bar, int *cancel_save)
{
- int x, y;
- int ret;
- unsigned char *line;
+ int x, y;
+ int ret;
+ unsigned char *line;
+#ifdef HAVE_LIBLCMS
+ unsigned char *line_raw = NULL;
+#endif
+
DBG(DBG_proc, "xsane_save_ps_pdf_gray\n");
@@ -2865,15 +3217,26 @@ static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *im
}
}
+ if (ascii85decode)
+ {
#ifdef HAVE_LIBZ
- if (flatdecode)
+ if (flatedecode)
+ {
+ ret = xsane_write_compressed_a85_flatedecode(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
+ }
+ else
+#endif
+ {
+ ret = xsane_write_compressed_a85(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
+ }
+ }
+ else if (flatedecode)
{
- ret = xsane_write_compressed_a85_flatdecode(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
+ ret = xsane_write_flatedecode(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
}
else
-#endif
{
- ret = xsane_write_compressed_a85(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
+ fwrite(line, image_info->image_width, 1, outfile);
}
if ((ret != 0) || (ferror(outfile)))
@@ -2915,28 +3278,106 @@ static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *im
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save)
+static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, int ascii85decode, int flatedecode,
+ cmsHTRANSFORM hTransform, int do_transform,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
int x, y;
int ret;
- unsigned char *line, *linep;
+ unsigned char *line = NULL, *linep = NULL, *line16 = NULL;
+ int bytes_per_line;
+ int bytes_per_line16 = 0;
+#ifdef HAVE_LIBLCMS
+ unsigned char *line_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_ps_pdf_color\n");
*cancel_save = 0;
- line = (unsigned char *) malloc(image_info->image_width * 3);
+ if (image_info->depth > 8) /* reduce 16 bit images to 12 bit */
+ {
+ bytes_per_line16 = image_info->image_width * 3 * 2;
+
+ bytes_per_line = (image_info->image_width/2) * 3 * 3;
+ if (image_info->image_width & 1)
+ {
+ bytes_per_line += 5;
+ }
+
+ DBG(DBG_info, "bytes_per_line16 = %d\n", bytes_per_line16);
+ DBG(DBG_info, "bytes_per_line = %d\n", bytes_per_line);
+
+ line16 = (unsigned char *) malloc(bytes_per_line16);
+
+ if (line16 == NULL)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s malloc for line16 failed", ERR_DURING_SAVE);
+ DBG(DBG_error, "%s\n", buf);
+ xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
+ *cancel_save = 1;
+ return (*cancel_save);
+ }
+ DBG(DBG_info, "line16 allocated\n");
+ }
+ else
+ {
+ bytes_per_line = image_info->image_width * 3;
+ bytes_per_line16 = image_info->image_width * 3;
+ DBG(DBG_info, "bytes_per_line = %d\n", bytes_per_line);
+ }
+
+ line = (unsigned char *) malloc(bytes_per_line);
if (line == NULL)
{
char buf[TEXTBUFSIZE];
- snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE);
+ snprintf(buf, sizeof(buf), "%s malloc for line failed", ERR_DURING_SAVE);
DBG(DBG_error, "%s\n", buf);
xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
+
+ if (line16)
+ {
+ free(line16);
+ }
+
*cancel_save = 1;
return (*cancel_save);
}
+ DBG(DBG_info, "line allocated\n");
+
+#ifdef HAVE_LIBLCMS
+ if (do_transform && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ line_raw = (unsigned char *) malloc(bytes_per_line16);
+
+ if (line_raw == NULL)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s malloc for line_raw failed", ERR_DURING_SAVE);
+ DBG(DBG_error, "%s\n", buf);
+ xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
+
+ free(line);
+
+ if (line16)
+ {
+ free(line16);
+ }
+
+ *cancel_save = 1;
+ return (*cancel_save);
+ }
+
+ DBG(DBG_info, "line_raw allocated\n");
+ }
+#endif
for (y = 0; y < image_info->image_height; y++)
{
@@ -2948,39 +3389,101 @@ static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *i
linep = line;
- if (image_info->depth > 8) /* reduce 16 bit images */
+ if (image_info->depth > 8) /* reduce 16 bit images to 12 bit */
{
- guint16 val;
+#ifdef HAVE_LIBLCMS
+ if (do_transform && (hTransform != NULL))
+ {
+ fread(line_raw, 6, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, line_raw, line16, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(line16, 6, image_info->image_width, imagefile);
+ }
- for (x = 0; x < image_info->image_width; x++)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ for (x = 0; x < image_info->image_width; x=x+2)
{
- fread(&val, 2, 1, imagefile);
- *linep++ = val/256;
- fread(&val, 2, 1, imagefile);
- *linep++ = val/256;
- fread(&val, 2, 1, imagefile);
- *linep++ = val/256;
+ *linep++ = line16[6*x+1]; /* red high+middle */
+ *linep++ = (line16[6*x+0] & 240) | (line16[6*x+3] >> 4); /* red low | green high */
+ *linep++ = ((line16[6*x+3] & 15) << 4) | ((line16[6*x+2] & 240) >> 4); /* green middle | green low */
+
+ *linep++ = line16[6*x+5]; /* blue high+middle */
+
+ if (x == image_info->image_width-1)
+ {
+ *linep++ = (line16[6*x+4] & 240); /* blue low */
+ break;
+ }
+
+ *linep++ = (line16[6*x+4] & 240) | (line16[6*x+7] >> 4); /* blue low | red high */
+ *linep++ = ((line16[6*x+7] & 15) << 4) | ((line16[6*x+6] & 240) >> 4); /* red middle | red low */
+
+ *linep++ = line16[6*x+9]; /* green high+middle */
+ *linep++ = (line16[6*x+8] & 240) | (line16[6*x+11] >> 4); /* green low | blue high */
+ *linep++ = ((line16[6*x+11] & 15) << 4) | ((line16[6*x+10] & 240) >> 4); /* blue middle | blue low */
}
+#else
+ for (x = 0; x < image_info->image_width; x=x+2)
+ {
+ *linep++ = line16[6*x+0]; /* red high+middle */
+ *linep++ = (line16[6*x+1] & 240) | (line16[6*x+2] >> 4); /* red low | green high */
+ *linep++ = ((line16[6*x+2] & 15) << 4) | ((line16[6*x+3] & 240) >> 4); /* green middle | green low */
+
+ *linep++ = line16[6*x+4]; /* blue high+middle */
+
+ if (x == image_info->image_width-1)
+ {
+ *linep++ = (line16[6*x+5] & 240); /* blue low */
+ break;
+ }
+
+ *linep++ = (line16[6*x+5] & 240) | (line16[6*x+6] >> 4); /* blue low | red high */
+ *linep++ = ((line16[6*x+6] & 15) << 4) | ((line16[6*x+7] & 240) >> 4); /* red middle | red low */
+
+ *linep++ = line16[6*x+8]; /* green high+middle */
+ *linep++ = (line16[6*x+9] & 240) | (line16[6*x+10] >> 4); /* green low | blue high */
+ *linep++ = ((line16[6*x+10] & 15) << 4) | ((line16[6*x+11] & 240) >> 4); /* blue middle | blue low */
+ }
+#endif
}
else /* 8 bits/sample */
{
- for (x = 0; x < image_info->image_width; x++)
+#ifdef HAVE_LIBLCMS
+ if (do_transform && (hTransform != NULL))
{
- *linep++ = fgetc(imagefile);
- *linep++ = fgetc(imagefile);
- *linep++ = fgetc(imagefile);
+ fread(line_raw, 3, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, line_raw, line, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(line, 3, image_info->image_width, imagefile);
}
}
+ if (ascii85decode)
+ {
#ifdef HAVE_LIBZ
- if (flatdecode)
+ if (flatedecode)
+ {
+ ret = xsane_write_compressed_a85_flatedecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
+ }
+ else
+#endif
+ {
+ ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
+ }
+ }
+ else if (flatedecode)
{
- ret = xsane_write_compressed_a85_flatdecode(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1));
+ ret = xsane_write_flatedecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
}
else
-#endif
{
- ret = xsane_write_compressed_a85(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1));
+ fwrite(line, bytes_per_line, 1, outfile);
}
if ((ret != 0) || (ferror(outfile)))
@@ -3009,6 +3512,18 @@ static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *i
}
}
+#ifdef HAVE_LIBLCMS
+ if (line_raw)
+ {
+ free(line_raw);
+ }
+#endif
+
+ if (line16)
+ {
+ free(line16);
+ }
+
free(line);
return (*cancel_save);
@@ -3019,7 +3534,8 @@ static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *i
int xsane_save_ps_page(FILE *outfile, int page,
FILE *imagefile, Image_info *image_info, float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int do_transform,
GtkProgressBar *progress_bar, int *cancel_save)
{
DBG(DBG_proc, "xsane_save_ps_page\n");
@@ -3027,23 +3543,23 @@ int xsane_save_ps_page(FILE *outfile, int page,
xsane_save_ps_create_page_header(outfile, page,
image_info, width, height,
paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation,
- flatdecode,
+ flatedecode,
progress_bar);
- if (image_info->colors == 1) /* lineart, halftone, grayscale */
+ if (image_info->channels == 1) /* lineart, halftone, grayscale */
{
if (image_info->depth == 1) /* lineart, halftone */
{
- xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
+ xsane_save_ps_pdf_bw(outfile, imagefile, image_info, TRUE, flatedecode, progress_bar, cancel_save);
}
else /* grayscale */
{
- xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
+ xsane_save_ps_pdf_gray(outfile, imagefile, image_info, TRUE, flatedecode, hTransform, do_transform, progress_bar, cancel_save);
}
}
else /* color RGB */
{
- xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
+ xsane_save_ps_pdf_color(outfile, imagefile, image_info, TRUE, flatedecode, hTransform, do_transform, progress_bar, cancel_save);
}
xsane_save_ps_create_page_trailer(outfile);
@@ -3065,19 +3581,46 @@ int xsane_save_ps_page(FILE *outfile, int page,
int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int embed_CSA, char *CSA_profile,
+ int embed_CRD, char *CRD_profile, int blackpointcompensation, int intent,
GtkProgressBar *progress_bar, int *cancel_save)
{
DBG(DBG_proc, "xsane_save_ps\n");
*cancel_save = 0;
- xsane_save_ps_create_document_header(outfile, 1 /* pages */, flatdecode);
+ xsane_save_ps_create_document_header(outfile, 1 /* pages */, flatedecode);
+
+#ifdef HAVE_LIBLCMS
+ if ((apply_ICM_profile) && (embed_CRD))
+ {
+ xsane_write_CRD(outfile, CRD_profile, intent, blackpointcompensation); /* write printer profile to ps file */
+ }
+
+
+ if ((apply_ICM_profile) && (embed_CSA))
+ {
+ xsane_write_CSA(outfile, CSA_profile, intent); /* write scanner profile to ps file */
+ }
+ else
+#endif
+ {
+ if (image_info->channels == 1) /* lineart, halftone, grayscale */
+ {
+ fprintf(outfile, "/DeviceGray setcolorspace\n");
+ }
+ else
+ {
+ fprintf(outfile, "/DeviceRGB setcolorspace\n");
+ }
+ }
xsane_save_ps_page(outfile, 1 /* page */,
imagefile, image_info, width, height,
paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation,
- flatdecode,
+ flatedecode,
+ hTransform, (apply_ICM_profile && (!embed_CSA) && (!embed_CRD)) /* do_transform */,
progress_bar, cancel_save);
xsane_save_ps_create_document_trailer(outfile, 0 /* we defined pages at beginning */);
@@ -3097,7 +3640,93 @@ int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float
/* ---------------------------------------------------------------------------------------------------------------------- */
-void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref, int pages, int flatdecode)
+static int xsane_embed_pdf_icm_profile(FILE *outfile, struct pdf_xref *xref, char *icm_filename, int flatedecode, int icc_object)
+{
+ FILE *icm_profile;
+ size_t size, embed_len;
+ unsigned char *embed_buffer;
+ int ret;
+
+ DBG(DBG_proc, "xsane_embed_pdf_icm_profile(%s)\n", icm_filename);
+
+ icm_profile = fopen(icm_filename, "rb");
+ if (icm_profile == NULL)
+ {
+ DBG(DBG_error, "Could not open ICM profile \"%s\" for reading\n", icm_filename);
+ return -1;
+ }
+
+ fseek(icm_profile, 0, SEEK_END);
+ size = ftell(icm_profile);
+ fseek(icm_profile, 0, SEEK_SET);
+
+ embed_buffer = malloc(size + 1);
+ if (embed_buffer)
+ {
+ xref->obj[icc_object] = ftell(outfile);
+ fprintf(outfile, "%d 0 obj\n", icc_object);
+ fprintf(outfile, " << /N 3\n"); /* 3 channels */
+ fprintf(outfile, " /Alternate /DeviceRGB\n");
+#ifdef HAVE_LIBZ
+ if (flatedecode)
+ {
+ fprintf(outfile, " /Filter /FlateDecode\n");
+ }
+#endif
+
+ fprintf(outfile, " /Length >>\n");
+
+ /* Position of the stream length, to be written later on */
+ xref->slenp = ftell(outfile) - 15;
+
+ fprintf(outfile, "stream\n");
+
+ /* Start of the stream data */
+ xref->slen = ftell(outfile);
+
+ embed_len = fread(embed_buffer, 1, size, icm_profile);
+ embed_buffer[embed_len] = 0;
+ fclose(icm_profile);
+
+#ifdef HAVE_LIBZ
+ if (flatedecode)
+ {
+ ret = xsane_write_flatedecode(outfile, embed_buffer, size, TRUE);
+ }
+ else
+#endif
+ {
+ fwrite(embed_buffer, size, 1, outfile);
+ ret = 0;
+ }
+
+ /* Go back and write the length of the stream */
+ xref->slen = ftell(outfile) - xref->slen;
+ fseek(outfile, xref->slenp, SEEK_SET);
+ fprintf(outfile, "%lu", xref->slen);
+ fseek(outfile, 0L, SEEK_END);
+
+ fprintf(outfile, "endstream\n");
+ fprintf(outfile, "endobj\n");
+ fprintf(outfile, "\n");
+
+ free(embed_buffer);
+ }
+ else
+ {
+ DBG(DBG_info, "Embedding ICM profile \"%s\" to PDF: no mem\n", icm_filename);
+ fclose(icm_profile);
+ return -2;
+ }
+
+
+ DBG(DBG_info, "Embedding ICM profile \"%s\" to PDF file retuned with status %d\n", icm_filename, ret);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref, int pages, int flatedecode)
{
int i;
@@ -3126,7 +3755,7 @@ void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref,
fprintf(outfile, " /Kids [\n");
for (i=0; i < pages; i++)
{
- fprintf(outfile, " %d 0 R\n", i * 2 + 4);
+ fprintf(outfile, " %d 0 R\n", i * 2 + 6);
}
fprintf(outfile, " ]\n");
fprintf(outfile, " /Count %d\n", pages);
@@ -3143,7 +3772,8 @@ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xr
float width, float height,
int paper_left_margin, int paper_bottom_margin,
int paper_width, int paper_height,
- int paper_orientation, int flatdecode,
+ int paper_orientation,
+ int flatedecode, int icc_object,
GtkProgressBar *progress_bar)
{
int position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth;
@@ -3231,26 +3861,26 @@ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xr
depth = image_info->depth;
- if (depth > 8)
+ if (depth > 8) /* PDF does not support 16bits/sample in a standard image */
{
depth = 8;
}
- xref->obj[page * 2 + 2] = ftell(outfile);
- fprintf(outfile, "%d 0 obj\n", page * 2 + 2);
+ xref->obj[page * 2 + 4] = ftell(outfile);
+ fprintf(outfile, "%d 0 obj\n", page * 2 + 4);
fprintf(outfile, " << /Type /Page\n");
fprintf(outfile, " /Parent 3 0 R\n");
fprintf(outfile, " /MediaBox [%d %d %d %d]\n", box_left, box_bottom, box_right, box_top);
- fprintf(outfile, " /Contents %d 0 R\n", page * 2 + 3);
- fprintf(outfile, " /Resources << /ProcSet %d 0 R >>\n", page * 2 + 4);
+ fprintf(outfile, " /Contents %d 0 R\n", page * 2 + 5);
+ fprintf(outfile, " /Resources << /ProcSet %d 0 R >>\n", page * 2 + 6);
fprintf(outfile, " >>\n");
fprintf(outfile, "endobj\n");
fprintf(outfile, "\n");
/* Offset of object 5, for xref */
- xref->obj[page * 2 + 3] = ftell(outfile);
+ xref->obj[page * 2 + 5] = ftell(outfile);
- fprintf(outfile, "%d 0 obj\n", page * 2 + 3);
+ fprintf(outfile, "%d 0 obj\n", page * 2 + 5);
fprintf(outfile, " << /Length >>\n");
/* Position of the stream length, to be written later on */
@@ -3269,9 +3899,17 @@ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xr
fprintf(outfile, " /W %d\n", image_info->image_width);
fprintf(outfile, " /H %d\n", image_info->image_height);
- if (image_info->colors == 3) /* what about RGBA here ? */
+ if ((icc_object) && (image_info->depth != 1))
+ {
+ fprintf(outfile, " /ColorSpace [/ICCBased %d 0 R]\n", icc_object);
+ }
+
+ if (image_info->channels == 3) /* what about RGBA here ? */
{
- fprintf(outfile, " /CS /RGB\n");
+ if (icc_object == 0)
+ {
+ fprintf(outfile, " /CS /RGB\n");
+ }
fprintf(outfile, " /BPC %d\n", depth);
}
else if (image_info->depth == 1) /* BW */
@@ -3281,22 +3919,20 @@ static void xsane_save_pdf_create_page_header(FILE *outfile, struct pdf_xref *xr
}
else /* gray */
{
- fprintf(outfile, " /CS /G\n");
- fprintf(outfile, " /BPC 8\n");
+ if (icc_object == 0)
+ {
+ fprintf(outfile, " /CS /G\n");
+ }
+ fprintf(outfile, " /BPC %d\n", depth);
}
#ifdef HAVE_LIBZ
- if (flatdecode)
- {
- fprintf(outfile, " /F [/A85 /FlateDecode]\n");
- }
- else
+ if (flatedecode)
{
- fprintf(outfile, " /F /A85\n");
+ fprintf(outfile, " /F /FlateDecode\n");
}
-#else
- fprintf(outfile, " /F /A85\n");
#endif
+
fprintf(outfile, "ID\n");
}
@@ -3311,17 +3947,17 @@ void xsane_save_pdf_create_document_trailer(FILE *outfile, struct pdf_xref *xref
/* PDF document trailer */
/* Offset of object 6, for xref */
- xref->obj[pages * 2 + 4] = ftell(outfile);
+ xref->obj[pages * 2 + 6] = ftell(outfile);
- fprintf(outfile, "%d 0 obj\n", pages * 2 + 4);
+ fprintf(outfile, "%d 0 obj\n", pages * 2 + 6);
fprintf(outfile, " [/PDF]\n");
fprintf(outfile, "endobj\n");
fprintf(outfile, "\n");
/* Offset of object 7, for xref */
- xref->obj[pages * 2 + 5] = ftell(outfile);
+ xref->obj[pages * 2 + 7] = ftell(outfile);
- fprintf(outfile, "%d 0 obj\n", pages * 2 + 5);
+ fprintf(outfile, "%d 0 obj\n", pages * 2 + 7);
fprintf(outfile, " << /Title (XSane scanned image)\n");
fprintf(outfile, " /Creator (XSane version %s (sane %d.%d) - by Oliver Rauch)\n",
VERSION,
@@ -3342,19 +3978,19 @@ void xsane_save_pdf_create_document_trailer(FILE *outfile, struct pdf_xref *xref
xref->xref = ftell(outfile);
fprintf(outfile, "xref\n");
- fprintf(outfile, "0 %d\n", pages * 2 + 6);
+ fprintf(outfile, "0 %d\n", pages * 2 + 8);
fprintf(outfile, "0000000000 65535 f \n");
- for (i=1; i <= pages * 2 + 5; i++)
+ for (i=1; i <= pages * 2 + 7; i++)
{
fprintf(outfile, "%010lu 00000 n \n", xref->obj[i]);
}
fprintf(outfile, "\n");
fprintf(outfile, "trailer\n");
- fprintf(outfile, " << /Size %d\n", pages * 2 + 6);
+ fprintf(outfile, " << /Size %d\n", pages * 2 + 8);
fprintf(outfile, " /Root 1 0 R\n");
- fprintf(outfile, " /Info %d 0 R\n", pages * 2 + 5);
+ fprintf(outfile, " /Info %d 0 R\n", pages * 2 + 7);
fprintf(outfile, " >>\n");
fprintf(outfile, "startxref\n");
fprintf(outfile, "%lu\n", xref->xref);
@@ -3370,7 +4006,7 @@ static void xsane_save_pdf_create_page_trailer(FILE *outfile, struct pdf_xref *x
fprintf(outfile, "Q\n");
/* Go back and write the length of the stream */
- xref->slen = ftell(outfile) - xref->slen - 1;
+ xref->slen = ftell(outfile) - xref->slen; /* we had a "-1" at the end but I do not understand the reason for -1, without looks better */
fseek(outfile, xref->slenp, SEEK_SET);
fprintf(outfile, "%lu", xref->slen);
fseek(outfile, 0L, SEEK_END);
@@ -3385,7 +4021,8 @@ static void xsane_save_pdf_create_page_trailer(FILE *outfile, struct pdf_xref *x
int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page,
FILE *imagefile, Image_info *image_info, float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int do_transform, int icc_object,
GtkProgressBar *progress_bar, int *cancel_save)
{
@@ -3394,23 +4031,23 @@ int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page,
xsane_save_pdf_create_page_header(outfile, xref, page,
image_info, width, height,
paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation,
- flatdecode,
+ flatedecode, icc_object,
progress_bar);
- if (image_info->colors == 1) /* lineart, halftone, grayscale */
+ if (image_info->channels == 1) /* lineart, halftone, grayscale */
{
if (image_info->depth == 1) /* lineart, halftone */
{
- xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
+ xsane_save_ps_pdf_bw(outfile, imagefile, image_info, FALSE, flatedecode, progress_bar, cancel_save);
}
else /* grayscale */
{
- xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
+ xsane_save_ps_pdf_gray(outfile, imagefile, image_info, FALSE, flatedecode, hTransform, do_transform, progress_bar, cancel_save);
}
}
else /* color RGB */
{
- xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
+ xsane_save_ps_pdf_color(outfile, imagefile, image_info, FALSE, flatedecode, hTransform, do_transform, progress_bar, cancel_save);
}
xsane_save_pdf_create_page_trailer(outfile, xref);
@@ -3432,21 +4069,33 @@ int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page,
int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
GtkProgressBar *progress_bar, int *cancel_save)
{
- struct pdf_xref xref;
+ struct pdf_xref xref;
+ int icc_object = 0;
DBG(DBG_proc, "xsane_save_pdf\n");
*cancel_save = 0;
- xsane_save_pdf_create_document_header(outfile, &xref, 1, flatdecode);
+ xsane_save_pdf_create_document_header(outfile, &xref, 1, flatedecode);
+
+ xref.obj[4] = ftell(outfile);
+ xref.obj[5] = ftell(outfile);
+
+ if (apply_ICM_profile && (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE))
+ {
+ icc_object = 4;
+ xsane_embed_pdf_icm_profile(outfile, &xref, image_info->icm_profile, flatedecode, icc_object);
+ }
xsane_save_pdf_page(outfile, &xref, 1,
imagefile, image_info, width, height,
paper_left_margin, paper_bottom_margin, paperwidth, paperheight, paper_orientation,
- flatdecode,
+ flatedecode,
+ hTransform, apply_ICM_profile && ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE)) /* do_transform */, icc_object,
progress_bar, cancel_save);
xsane_save_pdf_create_document_trailer(outfile, &xref, 1);
@@ -3465,8 +4114,8 @@ int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float
}
/* ---------------------------------------------------------------------------------------------------------------------- */
-#ifdef HAVE_LIBJPEG
+#ifdef HAVE_LIBJPEG
typedef struct
{
struct jpeg_error_mgr pub;/* "public" fields */
@@ -3494,7 +4143,110 @@ static void xsane_jpeg_error_exit(j_common_ptr cinfo)
*xsane_jpeg_error_mgr_data->cancel_save = 1;
}
-int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save)
+/* ---------------------------------------------------------- */
+
+#ifdef HAVE_LIBLCMS
+static void xsane_jpeg_write_icm_profile(j_compress_ptr cinfo_ptr, const JOCTET *icm_data_ptr, unsigned int icm_data_len)
+{
+#define ICM_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICM */
+#define ICM_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */
+#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */
+#define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICM_OVERHEAD_LEN)
+
+ unsigned int num_markers; /* total number of markers we'll write */
+ int cur_marker = 1; /* per spec, counting starts at 1 */
+ unsigned int length; /* number of bytes to write in this marker */
+
+ /* Calculate the number of markers we'll need, rounding up of course */
+ num_markers = icm_data_len / MAX_DATA_BYTES_IN_MARKER;
+ if (num_markers * MAX_DATA_BYTES_IN_MARKER != icm_data_len)
+ {
+ num_markers++;
+ }
+
+ while (icm_data_len > 0)
+ {
+ length = icm_data_len; /* length of profile to put in this marker */
+ if (length > MAX_DATA_BYTES_IN_MARKER)
+ {
+ length = MAX_DATA_BYTES_IN_MARKER;
+ }
+ icm_data_len -= length;
+
+ /* Write the JPEG marker header (APP2 code and marker length) */
+ jpeg_write_m_header(cinfo_ptr, ICM_MARKER, (unsigned int) (length + ICM_OVERHEAD_LEN));
+
+ /* Write the marker identifying string "ICC_PROFILE" (null-terminated).
+ * We code it in this less-than-transparent way so that the code works
+ * even if the local character set is not ASCII.
+ */
+ jpeg_write_m_byte(cinfo_ptr, 0x49);
+ jpeg_write_m_byte(cinfo_ptr, 0x43);
+ jpeg_write_m_byte(cinfo_ptr, 0x43);
+ jpeg_write_m_byte(cinfo_ptr, 0x5F);
+ jpeg_write_m_byte(cinfo_ptr, 0x50);
+ jpeg_write_m_byte(cinfo_ptr, 0x52);
+ jpeg_write_m_byte(cinfo_ptr, 0x4F);
+ jpeg_write_m_byte(cinfo_ptr, 0x46);
+ jpeg_write_m_byte(cinfo_ptr, 0x49);
+ jpeg_write_m_byte(cinfo_ptr, 0x4C);
+ jpeg_write_m_byte(cinfo_ptr, 0x45);
+ jpeg_write_m_byte(cinfo_ptr, 0x0);
+
+ /* Add the sequencing info */
+ jpeg_write_m_byte(cinfo_ptr, cur_marker);
+ jpeg_write_m_byte(cinfo_ptr, (int) num_markers);
+
+ /* Add the profile data */
+ while (length--)
+ {
+ jpeg_write_m_byte(cinfo_ptr, *icm_data_ptr);
+ icm_data_ptr++;
+ }
+ cur_marker++;
+ }
+}
+
+/* ---------------------------------------------------------- */
+
+static void xsane_jpeg_embed_scanner_icm_profile(j_compress_ptr cinfo_ptr, const char *icm_filename)
+{
+ FILE *icm_profile;
+ size_t size, embed_len;
+ LPBYTE embed_buffer;
+
+ DBG(DBG_proc, "xsane_jpeg_embed_scanner_icm_profile(%s)\n", icm_filename);
+
+ icm_profile = fopen(icm_filename, "rb");
+ if (icm_profile == NULL)
+ {
+ return;
+ }
+
+ fseek(icm_profile, 0, SEEK_END);
+ size = ftell(icm_profile);
+ fseek(icm_profile, 0, SEEK_SET);
+
+ embed_buffer = (LPBYTE) malloc(size + 1);
+ if (embed_buffer)
+ {
+ embed_len = fread(embed_buffer, 1, size, icm_profile);
+ fclose(icm_profile);
+ embed_buffer[embed_len] = 0;
+
+ xsane_jpeg_write_icm_profile(cinfo_ptr, embed_buffer, embed_len);
+ free(embed_buffer);
+
+ DBG(DBG_info, "ICM profile %s has been embedded to jpeg file\n", icm_filename);
+ }
+}
+#endif
+
+/* ---------------------------------------------------------- */
+
+int xsane_save_jpeg(FILE *outfile, int quality, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
unsigned char *data;
char buf[TEXTBUFSIZE];
@@ -3504,12 +4256,15 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
struct jpeg_compress_struct cinfo;
xsane_jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
+#ifdef HAVE_LIBLCMS
+ unsigned char *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_jpeg\n");
*cancel_save = 0;
- if (image_info->colors == 3)
+ if (image_info->channels == 3)
{
components = 3;
}
@@ -3528,6 +4283,24 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
return -1; /* error */
}
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile && (cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * components * bytespp);
+
+ if (!data_raw)
+ {
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = xsane_jpeg_error_exit;
jerr.cancel_save = cancel_save;
@@ -3537,7 +4310,7 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
cinfo.image_width = image_info->image_width;
cinfo.image_height = image_info->image_height;
cinfo.input_components = components;
- if (image_info->colors == 3)
+ if (image_info->channels == 3)
{
cinfo.in_color_space = JCS_RGB;
}
@@ -3560,6 +4333,20 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
jpeg_start_compress(&cinfo, TRUE);
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile)
+ {
+ if (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE)
+ {
+ xsane_jpeg_embed_scanner_icm_profile(&cinfo, image_info->icm_profile);
+ }
+ else if (cms_function == XSANE_CMS_FUNCTION_CONVERT_TO_WORKING_CS)
+ {
+ xsane_jpeg_embed_scanner_icm_profile(&cinfo, preferences.working_color_space_icm_profile);
+ }
+ }
+#endif
+
for (y = 0; y < image_info->image_height; y++)
{
gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
@@ -3596,7 +4383,18 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
else if (image_info->depth > 8) /* jpeg does not support 16 bits/sample, so we reduce it at first */
{
guint16 *data16 = (guint16 *) data;
- fread(data, components * 2, image_info->image_width, imagefile);
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile && (cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ fread(data_raw, components * 2, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, components * 2, image_info->image_width, imagefile);
+ }
+
for (x = 0; x < image_info->image_width * components; x++)
{
data[x] = data16[x] / 256;
@@ -3605,7 +4403,17 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
}
else /* 8 bits/sample */
{
- fread(data, components, image_info->image_width, imagefile);
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile && (cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ fread(data_raw, components, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, components, image_info->image_width, imagefile);
+ }
}
row_pointer[0] = data;
@@ -3619,6 +4427,13 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
}
jpeg_finish_compress(&cinfo);
+
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
free(data);
return (*cancel_save);
@@ -3628,9 +4443,58 @@ int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int
/* ---------------------------------------------------------------------------------------------------------------------- */
#ifdef HAVE_LIBTIFF
+#ifdef HAVE_LIBLCMS
+static void xsane_tiff_embed_scanner_icm_profile(TIFF *tiffile, const char *icm_filename)
+{
+ FILE *icm_profile;
+ size_t size;
+ char *icm_profile_buffer;
+
+ DBG(DBG_proc, "xsane_tiff_embed_scanner_icm_profile(%s)\n", icm_filename);
+ if((icm_profile = fopen(icm_filename, "rb")))
+ {
+ fseek(icm_profile, 0, SEEK_END);
+ size = ftell(icm_profile);
+ fseek(icm_profile, 0, SEEK_SET);
+
+ icm_profile_buffer = (char *) malloc(size + 1);
+
+ if (icm_profile_buffer)
+ {
+ if (fread(icm_profile_buffer, 1, size, icm_profile) == size)
+ {
+ icm_profile_buffer[size] = 0;
+
+ TIFFSetField(tiffile, TIFFTAG_ICCPROFILE, size, icm_profile_buffer);
+ }
+ else
+ {
+ DBG(DBG_error, "Can not read ICM profile data\n");
+ }
+
+ free(icm_profile_buffer);
+ }
+ else
+ {
+ DBG(DBG_error, "Can not get enogh memory for ICM profile\n");
+ }
+
+
+ fclose(icm_profile);
+ }
+ else
+ {
+ DBG(DBG_error, "Can not embed ICM profile\n");
+ }
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
/* pages = 0 => single page tiff, page = 0 */
/* pages > 0 => page = [1 .. pages] */
-int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Image_info *image_info, int quality,
+int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, int quality, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
GtkProgressBar *progress_bar, int *cancel_save)
{
char *data;
@@ -3641,6 +4505,9 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
int bytes;
struct tm *ptm;
time_t now;
+#ifdef HAVE_LIBLCMS
+ char *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_tiff_page(%d/%d\n", page, pages);
@@ -3660,7 +4527,7 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
}
- if (image_info->colors == 3)
+ if (image_info->channels == 3)
{
components = 3;
}
@@ -3686,6 +4553,25 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
xsane_back_gtk_error(buf, TRUE);
return -1; /* error */
}
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = (char *) malloc(image_info->image_width * components * bytes);
+
+ if (!data_raw)
+ {
+ _TIFFfree(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
TIFFSetField(tiffile, TIFFTAG_IMAGEWIDTH, image_info->image_width);
TIFFSetField(tiffile, TIFFTAG_IMAGELENGTH, image_info->image_height);
@@ -3717,7 +4603,7 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
TIFFSetField(tiffile, TIFFTAG_JPEGQUALITY, quality);
}
- if (image_info->colors == 3)
+ if (image_info->channels == 3)
{
if (compression == COMPRESSION_JPEG)
{
@@ -3728,6 +4614,20 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
{
TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
}
+
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile)
+ {
+ if (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE)
+ {
+ xsane_tiff_embed_scanner_icm_profile(tiffile, image_info->icm_profile);
+ }
+ else if (cms_function == XSANE_CMS_FUNCTION_CONVERT_TO_WORKING_CS)
+ {
+ xsane_tiff_embed_scanner_icm_profile(tiffile, preferences.working_color_space_icm_profile);
+ }
+ }
+#endif
}
else
{
@@ -3760,7 +4660,17 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
gtk_main_iteration();
}
- fread(data, 1, w, imagefile);
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ fread(data_raw, 1, w, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 1, w, imagefile);
+ }
if (TIFFWriteScanline(tiffile, data, y, 0) != 1)
{
@@ -3784,6 +4694,13 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
TIFFWriteDirectory(tiffile);
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+
_TIFFfree(data);
return (*cancel_save);
}
@@ -3791,9 +4708,60 @@ int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Im
/* ---------------------------------------------------------------------------------------------------------------------- */
+#if defined(PNG_iCCP_SUPPORTED)
+#ifdef HAVE_LIBLCMS
+static void xsane_png_embed_scanner_icm_profile(png_structp png_ptr, png_infop png_info_ptr, const char *icm_filename)
+{
+ FILE *icm_profile;
+ gchar *profile_buffer;
+ size_t size;
+
+ DBG(DBG_proc, "xsane_png_embed_scanner_icm_profile(%s)\n", icm_filename);
+ icm_profile = fopen(icm_filename, "rb");
+
+ if (icm_profile)
+ {
+ fseek(icm_profile, 0, SEEK_END);
+ size = ftell(icm_profile);
+ fseek(icm_profile, 0, SEEK_SET);
+
+ profile_buffer = malloc(size);
+
+ if (profile_buffer)
+ {
+ if (fread(profile_buffer, 1, size, icm_profile) == size)
+ {
+ png_set_iCCP(png_ptr, png_info_ptr, "ICC profile", 0, profile_buffer, size);
+ }
+ else
+ {
+ DBG(DBG_error, "can not read ICC profile data\n");
+ }
+
+ free(profile_buffer);
+ }
+ else
+ {
+ DBG(DBG_error, "can not allocate profile_buffer\n");
+ }
+
+ fclose(icm_profile);
+ }
+ else
+ {
+ DBG(DBG_error, "can not open ICM-profile\n");
+ }
+}
+#endif
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
#ifdef HAVE_LIBPNG
#ifdef HAVE_LIBZ
-int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save)
+int xsane_save_png(FILE *outfile, int compression, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
png_structp png_ptr;
png_infop png_info_ptr;
@@ -3803,6 +4771,9 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
char buf[TEXTBUFSIZE];
int colortype, components, byte_width;
int y;
+#ifdef HAVE_LIBLCMS
+ unsigned char *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_png\n");
@@ -3834,12 +4805,12 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
byte_width = image_info->image_width;
- if (image_info->colors == 4) /* RGBA */
+ if (image_info->channels == 4) /* RGBA */
{
components = 4;
colortype = PNG_COLOR_TYPE_RGB_ALPHA;
}
- else if (image_info->colors == 3) /* RGB */
+ else if (image_info->channels == 3) /* RGB */
{
components = 3;
colortype = PNG_COLOR_TYPE_RGB;
@@ -3855,13 +4826,13 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
png_set_IHDR(png_ptr, png_info_ptr, image_info->image_width, image_info->image_height, image_info->depth,
colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- if (image_info->colors >=3)
+ if (image_info->channels >=3)
{
sig_bit.red = image_info->depth;
sig_bit.green = image_info->depth;
sig_bit.blue = image_info->depth;
- if (image_info->colors == 4)
+ if (image_info->channels == 4)
{
sig_bit.alpha = image_info->depth;
}
@@ -3884,6 +4855,23 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
image_info->resolution_x * 100.0 / 2.54,
image_info->resolution_y * 100.0 / 2.54, PNG_RESOLUTION_METER);
#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile)
+ {
+ if (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE)
+ {
+ xsane_png_embed_scanner_icm_profile(png_ptr, png_info_ptr, image_info->icm_profile);
+ }
+ else if (cms_function == XSANE_CMS_FUNCTION_CONVERT_TO_WORKING_CS)
+ {
+ xsane_png_embed_scanner_icm_profile(png_ptr, png_info_ptr, preferences.working_color_space_icm_profile);
+ }
+ }
+#endif
+#endif
+
png_write_info(png_ptr, png_info_ptr);
png_set_shift(png_ptr, &sig_bit);
@@ -3897,6 +4885,25 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
return -1; /* error */
}
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * components);
+
+ if (!data_raw)
+ {
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ png_destroy_write_struct(&png_ptr, (png_infopp) 0);
+ return -1; /* error */
+ }
+ }
+#endif
+
for (y = 0; y < image_info->image_height; y++)
{
gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
@@ -3905,7 +4912,17 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
gtk_main_iteration();
}
- fread(data, components, byte_width, imagefile);
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ fread(data_raw, components, byte_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, components, byte_width, imagefile);
+ }
row_ptr = data;
png_write_rows(png_ptr, &row_ptr, 1); /* errors are caught by test sor setjmp(...) */
@@ -3916,6 +4933,12 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
}
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
free(data);
png_write_end(png_ptr, png_info_ptr);
png_destroy_write_struct(&png_ptr, (png_infopp) 0);
@@ -3929,7 +4952,9 @@ int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int c
#ifdef HAVE_LIBPNG
#ifdef HAVE_LIBZ
-int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save)
+int xsane_save_png_16(FILE *outfile, int compression, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
png_structp png_ptr;
png_infop png_info_ptr;
@@ -3938,8 +4963,10 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
unsigned char *data;
char buf[TEXTBUFSIZE];
int colortype, components;
- int x,y;
- guint16 val;
+ int y;
+#ifdef HAVE_LIBLCMS
+ unsigned char *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_png16\n");
@@ -3969,12 +4996,12 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
return -1; /* error */
}
- if (image_info->colors == 4) /* RGBA */
+ if (image_info->channels == 4) /* RGBA */
{
components = 4;
colortype = PNG_COLOR_TYPE_RGB_ALPHA;
}
- else if (image_info->colors == 3) /* RGB */
+ else if (image_info->channels == 3) /* RGB */
{
components = 3;
colortype = PNG_COLOR_TYPE_RGB;
@@ -3997,6 +5024,29 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
sig_bit.gray = image_info->depth;
png_set_sBIT(png_ptr, png_info_ptr, &sig_bit);
+
+#if defined(PNG_pHYs_SUPPORTED)
+ png_set_pHYs(png_ptr, png_info_ptr,
+ image_info->resolution_x * 100.0 / 2.54,
+ image_info->resolution_y * 100.0 / 2.54, PNG_RESOLUTION_METER);
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile)
+ {
+ if (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE)
+ {
+ xsane_png_embed_scanner_icm_profile(png_ptr, png_info_ptr, image_info->icm_profile);
+ }
+ else if (cms_function == XSANE_CMS_FUNCTION_CONVERT_TO_WORKING_CS)
+ {
+ xsane_png_embed_scanner_icm_profile(png_ptr, png_info_ptr, preferences.working_color_space_icm_profile);
+ }
+ }
+#endif
+#endif
+
png_write_info(png_ptr, png_info_ptr);
png_set_shift(png_ptr, &sig_bit);
png_set_packing(png_ptr);
@@ -4011,6 +5061,25 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
return -1; /* error */
}
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * components * 2);
+
+ if (!data_raw)
+ {
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ png_destroy_write_struct(&png_ptr, (png_infopp) 0);
+ return -1; /* error */
+ }
+ }
+#endif
+
for (y = 0; y < image_info->image_height; y++)
{
gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
@@ -4019,13 +5088,34 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
gtk_main_iteration();
}
- for (x = 0; x < image_info->image_width * components; x++) /* this must be changed in dependance of endianess */
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && (hTransform != NULL))
+ {
+ fread(data_raw, components * 2, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
{
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- data[x*2+0] = val / 256; /* write data in network order (MSB first) */
- data[x*2+1] = val & 255;
+ fread(data, components * 2, image_info->image_width, imagefile);
}
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ /* we have to write data in network order (MSB first), so when we run on a low endian machine then we have to swap bytes */
+ {
+ int x;
+
+ for (x = 0; x < image_info->image_width * components; x++)
+ {
+ unsigned char help;
+
+ help = data[x*2+1];
+ data[x*2+0] = data[x*2+1];
+ data[x*2+1] = help;
+ }
+ }
+#endif /* LITTLE_ENDIAN */
+
row_ptr = data;
png_write_rows(png_ptr, &row_ptr, 1);
if (*cancel_save)
@@ -4034,6 +5124,12 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
}
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
free(data);
png_write_end(png_ptr, png_info_ptr);
png_destroy_write_struct(&png_ptr, (png_infopp) 0);
@@ -4045,22 +5141,69 @@ int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, in
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
+static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
int x,y;
- guint16 val;
+ guint16 *data;
int count = 0;
+#ifdef HAVE_LIBLCMS
+ guint16 *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_pnm_16_ascii_gray\n");
*cancel_save = 0;
+ data = malloc(image_info->image_width * 2);
+
+ if (!data)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((apply_ICM_profile) && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * 2);
+
+ if (!data_raw)
+ {
+ char buf[TEXTBUFSIZE];
+
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
for (y = 0; y < image_info->image_height; y++)
{
+#ifdef HAVE_LIBLCMS
+ if ((apply_ICM_profile) && (hTransform != NULL))
+ {
+ fread(data_raw, 2, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 2, image_info->image_width, imagefile);
+ }
+
for (x = 0; x < image_info->image_width; x++)
{
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fprintf(outfile, "%d ", val);
+ fprintf(outfile, "%d ", data[x]);
if (++count >= 10)
{
@@ -4068,6 +5211,7 @@ static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_in
count = 0;
}
}
+
fprintf(outfile, "\n");
if (ferror(outfile))
@@ -4094,33 +5238,85 @@ static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_in
}
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
return (*cancel_save);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
+static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
int x,y;
- guint16 val;
+ guint16 *data;
int count = 0;
+#ifdef HAVE_LIBLCMS
+ guint16 *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_pnm_16_ascii_color\n");
*cancel_save = 0;
- for (y = 0; y < image_info->image_height; y++)
+
+ data = malloc(image_info->image_width * 6);
+
+ if (!data)
{
- for (x = 0; x < image_info->image_width; x++)
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((apply_ICM_profile) && (hTransform != NULL))
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * 6);
+
+ if (!data_raw)
{
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fprintf(outfile, "%d ", val);
+ char buf[TEXTBUFSIZE];
+
+ free(data);
- fread(&val, 2, 1, imagefile);
- fprintf(outfile, "%d ", val);
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
- fread(&val, 2, 1, imagefile);
- fprintf(outfile, "%d ", val);
+ for (y = 0; y < image_info->image_height; y++)
+ {
+#ifdef HAVE_LIBLCMS
+ if ((apply_ICM_profile) && (hTransform != NULL))
+ {
+ fread(data_raw, 6, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 6, image_info->image_width, imagefile);
+ }
+
+ for (x = 0; x < image_info->image_width; x++)
+ {
+ fprintf(outfile, "%d ", data[3*x+0]);
+ fprintf(outfile, "%d ", data[3*x+1]);
+ fprintf(outfile, "%d ", data[3*x+2]);
if (++count >= 3)
{
@@ -4155,27 +5351,82 @@ static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, Image_i
}
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
return (*cancel_save);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
+static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
int x,y;
- guint16 val;
+ guint16 *data;
+#ifdef HAVE_LIBLCMS
+ guint16 *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_pnm_16_binary_gray\n");
*cancel_save = 0;
+ data = malloc(image_info->image_width * 2);
+
+ if (!data)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * 2);
+
+ if (!data_raw)
+ {
+ char buf[TEXTBUFSIZE];
+
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
for (y = 0; y < image_info->image_height; y++)
{
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ fread(data_raw, 2, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 2, image_info->image_width, imagefile);
+ }
+
for (x = 0; x < image_info->image_width; x++)
{
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
+ fputc(data[3*x+0] / 256, outfile);
+ fputc(data[3*x+0] & 255, outfile);
}
gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
@@ -4201,38 +5452,289 @@ static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, Image_i
}
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
return (*cancel_save);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
-static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
+static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
int x,y;
- guint16 val;
+ guint16 *data;
+#ifdef HAVE_LIBLCMS
+ guint16 *data_raw = NULL;
+#endif
DBG(DBG_proc, "xsane_save_pnm_16_binary_color\n");
*cancel_save = 0;
+ data = malloc(image_info->image_width * 6);
+
+ if (!data)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * 6);
+
+ if (!data_raw)
+ {
+ char buf[TEXTBUFSIZE];
+
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
for (y = 0; y < image_info->image_height; y++)
{
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ fread(data_raw, 6, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 6, image_info->image_width, imagefile);
+ }
+
for (x = 0; x < image_info->image_width; x++)
{
- /* red */
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
+ fputc(data[3*x+0] / 256, outfile);
+ fputc(data[3*x+0] & 255, outfile);
+ fputc(data[3*x+1] / 256, outfile);
+ fputc(data[3*x+1] & 255, outfile);
+ fputc(data[3*x+2] / 256, outfile);
+ fputc(data[3*x+2] & 255, outfile);
+ }
+
+ gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
+ while (gtk_events_pending())
+ {
+ gtk_main_iteration();
+ }
+
+
+ if (ferror(outfile))
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
+ DBG(DBG_error, "%s\n", buf);
+ xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
+ *cancel_save = 1;
+ break;
+ }
+
+ if (*cancel_save)
+ {
+ break;
+ }
+ }
+
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
+ return (*cancel_save);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static int xsane_save_pnm_8_gray(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
+{
+ int x,y;
+ guint8 *data;
+#ifdef HAVE_LIBLCMS
+ guint8 *data_raw = NULL;
+#endif
+
+ DBG(DBG_proc, "xsane_save_pnm_8_gray\n");
+
+ *cancel_save = 0;
+
+ data = malloc(image_info->image_width);
+
+ if (!data)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width);
+
+ if (!data_raw)
+ {
+ char buf[TEXTBUFSIZE];
- /* green */
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
+ free(data);
- /* blue */
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
+ for (y = 0; y < image_info->image_height; y++)
+ {
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ fread(data_raw, 1, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 1, image_info->image_width, imagefile);
+ }
+
+ for (x = 0; x < image_info->image_width; x++)
+ {
+ fputc(data[x], outfile);
+ }
+
+ gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
+ while (gtk_events_pending())
+ {
+ gtk_main_iteration();
+ }
+
+
+ if (ferror(outfile))
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
+ DBG(DBG_error, "%s\n", buf);
+ xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
+ *cancel_save = 1;
+ break;
+ }
+
+ if (*cancel_save)
+ {
+ break;
+ }
+ }
+
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
+ return (*cancel_save);
+}
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static int xsane_save_pnm_8_color(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
+{
+ int x,y;
+ guint8 *data;
+#ifdef HAVE_LIBLCMS
+ guint8 *data_raw = NULL;
+#endif
+
+ DBG(DBG_proc, "xsane_save_pnm_8_color\n");
+
+ *cancel_save = 0;
+
+ data = malloc(image_info->image_width * 3);
+
+ if (!data)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info->image_width * 3);
+
+ if (!data_raw)
+ {
+ char buf[TEXTBUFSIZE];
+
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
+ for (y = 0; y < image_info->image_height; y++)
+ {
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ fread(data_raw, 3, image_info->image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info->image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 3, image_info->image_width, imagefile);
+ }
+
+ for (x = 0; x < image_info->image_width; x++)
+ {
+ fputc(data[3*x+0], outfile);
+ fputc(data[3*x+1], outfile);
+ fputc(data[3*x+2], outfile);
}
gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
@@ -4259,12 +5761,46 @@ static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, Image_
}
}
+#ifdef HAVE_LIBLCMS
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
+ return (*cancel_save);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static int xsane_save_pnm_8(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
+{
+ DBG(DBG_proc, "xsane_save_pnm_8\n");
+
+ *cancel_save = 0;
+
+ xsane_write_pnm_header(outfile, image_info, preferences.save_pnm16_as_ascii);
+
+ if (image_info->channels > 1)
+ {
+ xsane_save_pnm_8_color(outfile, imagefile, image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
+ }
+ else
+ {
+ xsane_save_pnm_8_gray(outfile, imagefile, image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
+ }
+
return (*cancel_save);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
-int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
+int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
DBG(DBG_proc, "xsane_save_pnm_16\n");
@@ -4272,26 +5808,26 @@ int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, Gt
xsane_write_pnm_header(outfile, image_info, preferences.save_pnm16_as_ascii);
- if (image_info->colors > 1)
+ if (image_info->channels > 1)
{
if (preferences.save_pnm16_as_ascii)
{
- xsane_save_pnm_16_ascii_color(outfile, imagefile, image_info, progress_bar, cancel_save);
+ xsane_save_pnm_16_ascii_color(outfile, imagefile, image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
}
else
{
- xsane_save_pnm_16_binary_color(outfile, imagefile, image_info, progress_bar, cancel_save);
+ xsane_save_pnm_16_binary_color(outfile, imagefile, image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
}
}
else
{
if (preferences.save_pnm16_as_ascii)
{
- xsane_save_pnm_16_ascii_gray(outfile, imagefile, image_info, progress_bar, cancel_save);
+ xsane_save_pnm_16_ascii_gray(outfile, imagefile, image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
}
else
{
- xsane_save_pnm_16_binary_gray(outfile, imagefile, image_info, progress_bar, cancel_save);
+ xsane_save_pnm_16_binary_gray(outfile, imagefile, image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
}
}
@@ -4299,7 +5835,6 @@ int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, Gt
}
/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
/* 0=ok, <0=error, 1=canceled */
int xsane_save_image_as_lineart(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save)
@@ -4524,14 +6059,17 @@ int xsane_save_image_as_text(char *output_filename, char *input_filename, GtkPro
/* ---------------------------------------------------------------------------------------------------------------------- */
/* save image in destination file format. lineart images that are stored as grayscale image are reduced to lineart! */
-int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, GtkProgressBar *progress_bar, int *cancel_save)
+int xsane_save_image_as(char *output_filename, char *input_filename, int output_format,
+ int apply_ICM_profile, int cms_function, int cms_intent, int cms_bpc,
+ GtkProgressBar *progress_bar, int *cancel_save)
{
FILE *outfile;
FILE *infile;
char buf[TEXTBUFSIZE];
Image_info image_info;
- char lineart_filename[PATH_MAX];
+ char temporary_filename[PATH_MAX];
int remove_input_file = FALSE;
+ cmsHTRANSFORM hTransform = NULL;
DBG(DBG_proc, "xsane_save_image_as(output_file=%s, input_file=%s, type=%d)\n", output_filename, input_filename, output_format);
@@ -4553,7 +6091,7 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
{
DBG(DBG_info, "original image is a lineart => reduce to lineart\n");
fclose(infile);
- xsane_back_gtk_make_path(sizeof(lineart_filename), lineart_filename, 0, 0, "xsane-conversion-", xsane.dev_name, ".pbm", XSANE_PATH_TMP);
+ xsane_back_gtk_make_path(sizeof(temporary_filename), temporary_filename, 0, 0, "xsane-conversion-", xsane.dev_name, ".pbm", XSANE_PATH_TMP);
snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_PACKING_DATA, output_filename);
@@ -4565,9 +6103,9 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
gtk_main_iteration();
}
- xsane_save_image_as_lineart(lineart_filename, input_filename, progress_bar, cancel_save);
+ xsane_save_image_as_lineart(temporary_filename, input_filename, progress_bar, cancel_save);
- input_filename = lineart_filename;
+ input_filename = temporary_filename;
remove_input_file = TRUE;
infile = fopen(input_filename, "rb"); /* read binary (b for win32) */
@@ -4583,8 +6121,23 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
xsane_read_pnm_header(infile, &image_info);
}
- snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_SAVING_DATA, output_filename);
+#ifdef HAVE_LIBLCMS
+ if (apply_ICM_profile && ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) || ((output_format == XSANE_PNM) || (output_format == XSANE_PNM16))))
+ {
+ hTransform = xsane_create_cms_transform(&image_info, cms_function, cms_intent, cms_bpc);
+ }
+#endif
+
+ if (1)
+ {
+ snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_SAVING_DATA, output_filename);
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "%s", PROGRESS_SAVING_DATA);
+ }
+ gtk_progress_bar_set_ellipsize(GTK_PROGRESS_BAR(progress_bar), PANGO_ELLIPSIZE_START); /* this is new API, can be removed for old GTK versions */
gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf);
gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
@@ -4614,7 +6167,7 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
return -1; /* error */
}
- xsane_save_tiff_page(tiffile, 0, 0, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save);
+ xsane_save_tiff_page(tiffile, 0, 0, preferences.jpeg_quality, infile, &image_info, hTransform, apply_ICM_profile, cms_function, progress_bar, cancel_save);
TIFFClose(tiffile);
}
@@ -4641,13 +6194,13 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
}
else
{
- xsane_copy_file(outfile, infile, progress_bar, cancel_save);
+ xsane_save_pnm_8(outfile, infile, &image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
}
break;
#ifdef HAVE_LIBJPEG
case XSANE_JPEG:
- xsane_save_jpeg(outfile, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save);
+ xsane_save_jpeg(outfile, preferences.jpeg_quality, infile, &image_info, hTransform, apply_ICM_profile, cms_function, progress_bar, cancel_save);
break; /* switch format == XSANE_JPEG */
#endif
@@ -4656,18 +6209,18 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
case XSANE_PNG:
if (image_info.depth <= 8)
{
- xsane_save_png(outfile, infile, &image_info, preferences.png_compression, progress_bar, cancel_save);
+ xsane_save_png(outfile, preferences.png_compression, infile, &image_info, hTransform, apply_ICM_profile, cms_function, progress_bar, cancel_save);
}
else
{
- xsane_save_png_16(outfile, infile, &image_info, preferences.png_compression, progress_bar, cancel_save);
+ xsane_save_png_16(outfile, preferences.png_compression, infile, &image_info, hTransform, apply_ICM_profile, cms_function, progress_bar, cancel_save);
}
break; /* switch format == XSANE_PNG */
#endif
#endif
case XSANE_PNM16:
- xsane_save_pnm_16(outfile, infile, &image_info, progress_bar, cancel_save);
+ xsane_save_pnm_16(outfile, infile, &image_info, hTransform, apply_ICM_profile, progress_bar, cancel_save);
break; /* switch fomat == XSANE_PNM16 */
case XSANE_PS: /* save postscript, use original size */
@@ -4685,7 +6238,11 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
(int) imagewidth, /* paper_width */
(int) imageheight, /* paper_height */
0 /* portrait top left */,
- preferences.save_ps_flatdecoded,
+ preferences.save_ps_flatedecoded,
+ hTransform, apply_ICM_profile,
+ (cms_function == XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE), image_info.icm_profile,
+ 0, NULL, 0, /* no CRD */
+ 0 /* intent */,
progress_bar,
cancel_save);
}
@@ -4706,7 +6263,8 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
(int) imagewidth, /* paper_width */
(int) imageheight, /* paper_height */
0 /* portrait top left */,
- preferences.save_pdf_flatdecoded,
+ preferences.save_pdf_flatedecoded,
+ hTransform, apply_ICM_profile, cms_function,
progress_bar,
cancel_save);
}
@@ -4771,6 +6329,13 @@ int xsane_save_image_as(char *output_filename, char *input_filename, int output_
fclose (infile);
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ cmsDeleteTransform(hTransform);
+ }
+#endif
+
if (remove_input_file)
{
remove(input_filename); /* remove lineart pbm file */
@@ -5098,8 +6663,9 @@ void null_print_func(gchar *msg)
}
/* ---------------------------------------------------------------------------------------------------------------------- */
+/* ---------------------------------------------------------------------------------------------------------------------- */
-int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, int *cancel_save)
+int xsane_transfer_to_gimp(char *input_filename, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save)
{
int remaining;
size_t tile_size;
@@ -5114,6 +6680,13 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
int i, x, y;
Image_info image_info;
FILE *imagefile;
+ int bytes;
+ unsigned char *data = NULL;
+ guint16 *data16 = NULL;
+#ifdef HAVE_LIBLCMS
+ unsigned char *data_raw = NULL;
+ cmsHTRANSFORM hTransform = NULL;
+#endif
DBG(DBG_info, "xsane_transer_to_gimp\n");
@@ -5131,18 +6704,64 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
xsane_read_pnm_header(imagefile, &image_info);
+ if (image_info.depth == 16)
+ {
+ bytes = 2;
+ }
+ else
+ {
+ bytes = 1;
+ }
+
+ data = malloc(image_info.image_width * 3 * bytes);
+ data16 = (guint16 *) data;
+
+ if (!data)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (image_info.depth != 1))
+ {
+ hTransform = xsane_create_cms_transform(&image_info, cms_function, preferences.cms_intent, preferences.cms_bpc);
+ }
+
+ if (hTransform != NULL)
+ {
+ DBG(DBG_info, "Doing CMS color conversion\n");
+
+ data_raw = malloc(image_info.image_width * 3 * bytes);
+
+ if (!data_raw)
+ {
+ char buf[TEXTBUFSIZE];
+
+ free(data);
+
+ snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1; /* error */
+ }
+ }
+#endif
+
x = 0;
y = 0;
tile_offset = 0;
tile_size = image_info.image_width * gimp_tile_height();
- if (image_info.colors == 3) /* RGB */
+ if (image_info.channels == 3) /* RGB */
{
tile_size *= 3; /* 24 bits/pixel RGB */
image_type = GIMP_RGB;
drawable_type = GIMP_RGB_IMAGE;
}
- else if (image_info.colors == 4) /* RGBA */
+ else if (image_info.channels == 4) /* RGBA */
{
tile_size *= 4; /* 32 bits/pixel RGBA */
image_type = GIMP_RGB;
@@ -5151,6 +6770,55 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
/* colors == 0/1 is predefined */
image_ID = gimp_image_new(image_info.image_width, image_info.image_height, image_type);
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_CONVERT_TO_SRGB) && apply_ICM_profile) /* embed profile */
+ {
+ GimpParasite *parasite;
+ FILE *icm_profile;
+ guchar *profile_buffer;
+ gint32 size;
+
+ DBG(DBG_error, "Opening ICM profile %s\n", image_info.icm_profile);
+ icm_profile = fopen(image_info.icm_profile, "rb");
+
+ if (icm_profile)
+ {
+ fseek(icm_profile, 0, SEEK_END);
+ size = ftell(icm_profile);
+ fseek(icm_profile, 0, SEEK_SET);
+
+ profile_buffer = malloc(size);
+
+ if (profile_buffer)
+ {
+ if (fread(profile_buffer, 1, size, icm_profile) == size)
+ {
+ parasite = gimp_parasite_new("icc-profile", 0, size, profile_buffer);
+ gimp_image_parasite_attach(image_ID, parasite);
+ gimp_parasite_free(parasite);
+ }
+ else
+ {
+ DBG(DBG_error, "can not read profile data\n");
+ }
+
+ free(profile_buffer);
+ }
+ else
+ {
+ DBG(DBG_error, "can not allocate profile_buffer\n");
+ }
+
+ fclose(icm_profile);
+ }
+ else
+ {
+ DBG(DBG_error, "can not open ICM-profile\n");
+ }
+ }
+#endif
+
/* the following is supported since gimp-1.1.? */
#ifdef GIMP_HAVE_RESOLUTION_INFO
@@ -5168,7 +6836,7 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
tile = g_new(guchar, tile_size);
- if (image_info.colors == 1) /* gray */
+ if (image_info.channels == 1) /* gray */
{
switch (image_info.depth)
{
@@ -5217,30 +6885,79 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
break; /* leave switch depth 1 */
case 8: /* 8 bit gray */
- case 16: /* 16 bit gray already has been reduced to 8 bit */
- for (i = 0; i < image_info.image_width * image_info.image_height; ++i)
+ for (y = 1; y <= image_info.image_height; y++)
{
- tile[tile_offset++] = fgetc(imagefile);
- x++;
+ int tile_height = gimp_tile_height();
- if (x >= image_info.image_width)
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL))
{
- int tile_height = gimp_tile_height();
+ fread(data_raw, 1, image_info.image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info.image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 1, image_info.image_width, imagefile);
+ }
- x = 0;
- y++;
+ for (x = 0; x < image_info.image_width; x++)
+ {
+ tile[tile_offset++] = data[x];
+ }
- if (y % tile_height == 0)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
- tile_offset = 0;
- }
+ if (y % tile_height == 0)
+ {
+ gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
+ tile_offset = 0;
+ }
- gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
+ gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
+ while (gtk_events_pending())
+ {
+ gtk_main_iteration();
+ }
+
+ if (*cancel_save)
+ {
+ break;
+ }
+ }
+ break; /* case 8 */
+
+
+ case 16: /* 16 bit gray has to be reduced to 8 bit */
+ for (y = 1; y <= image_info.image_height; y++)
+ {
+ int tile_height = gimp_tile_height();
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL))
+ {
+ fread(data_raw, 2, image_info.image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info.image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 2, image_info.image_width, imagefile);
+ }
+
+ for (x = 0; x < image_info.image_width; x++)
+ {
+ tile[tile_offset++] = data16[x]/256;
+ }
+
+ if (y % tile_height == 0)
+ {
+ gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
+ tile_offset = 0;
+ }
+
+ gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
+ while (gtk_events_pending())
+ {
+ gtk_main_iteration();
}
if (*cancel_save)
@@ -5248,44 +6965,51 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
break;
}
}
- break; /* leave switch depth */
+ break; /* case 16 */
default: /* bad depth */
break; /* default */
}
}
- else if (image_info.colors == 3) /* RGB */
+ else if (image_info.channels == 3) /* RGB */
{
switch (image_info.depth)
{
case 8: /* 8 bit RGB */
- case 16: /* 16 bit RGB already has been reduced to 8 bit */
- for (i = 0; i < image_info.image_width * image_info.image_height*3; ++i)
+
+ for (y = 1; y <= image_info.image_height; y++)
{
- tile[tile_offset++] = fgetc(imagefile);
- if (tile_offset % 3 == 0)
- {
- x++;
+ int tile_height = gimp_tile_height();
- if (x >= image_info.image_width)
- {
- int tile_height = gimp_tile_height();
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL))
+ {
+ fread(data_raw, 3, image_info.image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info.image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 3, image_info.image_width, imagefile);
+ }
- x = 0;
- y++;
+ for (x = 0; x < image_info.image_width; x++)
+ {
+ tile[tile_offset++] = data[3*x+0];
+ tile[tile_offset++] = data[3*x+1];
+ tile[tile_offset++] = data[3*x+2];
+ }
- if (y % tile_height == 0)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
- tile_offset = 0;
- }
+ if (y % tile_height == 0)
+ {
+ gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
+ tile_offset = 0;
+ }
- gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
+ gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
+ while (gtk_events_pending())
+ {
+ gtk_main_iteration();
}
if (*cancel_save)
@@ -5295,12 +7019,57 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
}
break; /* case 8 */
+
+ case 16: /* 16 bit RGB has to be reduced to 8 bit */
+
+ for (y = 1; y <= image_info.image_height; y++)
+ {
+ int tile_height = gimp_tile_height();
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_function != XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE) && apply_ICM_profile && (hTransform != NULL))
+ {
+ fread(data_raw, 6, image_info.image_width, imagefile);
+ cmsDoTransform(hTransform, data_raw, data, image_info.image_width);
+ }
+ else
+#endif
+ {
+ fread(data, 6, image_info.image_width, imagefile);
+ }
+
+ for (x = 0; x < image_info.image_width; x++)
+ {
+ tile[tile_offset++] = data16[3*x+0]/256;
+ tile[tile_offset++] = data16[3*x+1]/256;
+ tile[tile_offset++] = data16[3*x+2]/256;
+ }
+
+ if (y % tile_height == 0)
+ {
+ gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
+ tile_offset = 0;
+ }
+
+ gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
+ while (gtk_events_pending())
+ {
+ gtk_main_iteration();
+ }
+
+ if (*cancel_save)
+ {
+ break;
+ }
+ }
+ break; /* case 16 */
+
default: /* bad depth */
break; /* default */
}
}
#ifdef SUPPORT_RGBA
- else if (image_info.colors == 4) /* RGBA */
+ else if (image_info.channels == 4) /* RGBA */
{
int i;
@@ -5370,6 +7139,19 @@ int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, i
fclose(imagefile);
+#ifdef HAVE_LIBLCMS
+ if (hTransform != NULL)
+ {
+ cmsDeleteTransform(hTransform);
+ }
+
+ if (data_raw)
+ {
+ free(data_raw);
+ }
+#endif
+ free(data);
+
return 0;
}
#endif /* HAVE_ANY_GIMP */
@@ -5414,7 +7196,7 @@ static void write_3chars_as_base64(unsigned char c1, unsigned char c2, unsigned
/* ---------------------------------------------------------------------------------------------------------------------- */
-void write_string_base64(int fd_socket, unsigned char *string, int len)
+void write_string_base64(int fd_socket, char *string, int len)
{
int i;
int pad;
@@ -5422,9 +7204,9 @@ void write_string_base64(int fd_socket, unsigned char *string, int len)
for (i = 0; i < len; i+=3)
{
- c1 = string[i];
- c2 = string[i+1];
- c3 = string[i+2];
+ c1 = (unsigned char) string[i];
+ c2 = (unsigned char) string[i+1];
+ c3 = (unsigned char) string[i+2];
pad = i - len + 3;
@@ -5477,7 +7259,7 @@ void write_base64(int fd_socket, FILE *infile)
pos += 4;
if (pos > 71)
{
- write(fd_socket, "\n", 1);
+ write(fd_socket, "\r\n", 2);
pos = 0;
}
@@ -5492,7 +7274,7 @@ void write_base64(int fd_socket, FILE *infile)
if (pos)
{
- write(fd_socket, "\n", 1);
+ write(fd_socket, "\r\n", 2);
}
xsane.email_progress_val = 1.0;
@@ -5505,33 +7287,33 @@ void write_email_header(int fd_socket, char *from, char *reply_to, char *to, cha
{
char buf[1024];
- snprintf(buf, sizeof(buf), "From: %s\n", from);
+ snprintf(buf, sizeof(buf), "From: %s\r\n", from);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Reply-To: %s\n", reply_to);
+ snprintf(buf, sizeof(buf), "Reply-To: %s\r\n", reply_to);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "To: %s\n", to);
+ snprintf(buf, sizeof(buf), "To: %s\r\n", to);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Subject: %s\n", subject);
+ snprintf(buf, sizeof(buf), "Subject: %s\r\n", subject);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "MIME-Version: 1.0\n");
+ snprintf(buf, sizeof(buf), "MIME-Version: 1.0\r\n");
write(fd_socket, buf, strlen(buf));
if (related) /* related means that we need a special link in the html part to display the image */
{
- snprintf(buf, sizeof(buf), "Content-Type: multipart/related;\n");
+ snprintf(buf, sizeof(buf), "Content-Type: multipart/related;\r\n");
write(fd_socket, buf, strlen(buf));
}
else
{
- snprintf(buf, sizeof(buf), "Content-Type: multipart/mixed;\n");
+ snprintf(buf, sizeof(buf), "Content-Type: multipart/mixed;\r\n");
write(fd_socket, buf, strlen(buf));
}
- snprintf(buf, sizeof(buf), " boundary=\"%s\"\n\n", boundary);
+ snprintf(buf, sizeof(buf), " boundary=\"%s\"\r\n\r\n", boundary);
write(fd_socket, buf, strlen(buf));
}
@@ -5541,7 +7323,7 @@ void write_email_footer(int fd_socket, char *boundary)
{
char buf[1024];
- snprintf(buf, sizeof(buf), "--%s--\n", boundary);
+ snprintf(buf, sizeof(buf), "--%s--\r\n", boundary);
write(fd_socket, buf, strlen(buf));
}
@@ -5551,16 +7333,16 @@ void write_email_mime_ascii(int fd_socket, char *boundary)
{
char buf[1024];
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
+ snprintf(buf, sizeof(buf), "--%s\r\n", boundary);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Type: text/plain;\n");
+ snprintf(buf, sizeof(buf), "Content-Type: text/plain;\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), " charset=\"iso-8859-1\"\n");
+ snprintf(buf, sizeof(buf), " charset=\"iso-8859-1\"\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 8bit\n\n");
+ snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 8bit\r\n\r\n");
write(fd_socket, buf, strlen(buf));
}
@@ -5570,22 +7352,22 @@ void write_email_mime_html(int fd_socket, char *boundary)
{
char buf[1024];
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
+ snprintf(buf, sizeof(buf), "--%s\r\n", boundary);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Type: text/html;\n");
+ snprintf(buf, sizeof(buf), "Content-Type: text/html;\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), " charset=\"us-ascii\"\n");
+ snprintf(buf, sizeof(buf), " charset=\"us-ascii\"\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 7bit\n\n");
+ snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 7bit\r\n\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">\n");
+ snprintf(buf, sizeof(buf), "<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "<html>\n");
+ snprintf(buf, sizeof(buf), "<html>\r\n");
write(fd_socket, buf, strlen(buf));
}
@@ -5595,28 +7377,28 @@ void write_email_attach_image(int fd_socket, char *boundary, char *content_id, c
{
char buf[1024];
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
+ snprintf(buf, sizeof(buf), "--%s\r\n", boundary);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Type: %s\n", content_type);
+ snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", content_type);
write(fd_socket, buf, strlen(buf));
if (content_id)
{
- snprintf(buf, sizeof(buf), "Content-ID: <%s>\n", content_id);
+ snprintf(buf, sizeof(buf), "Content-ID: <%s>\r\n", content_id);
write(fd_socket, buf, strlen(buf));
}
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\n");
+ snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Disposition: inline;\n");
+ snprintf(buf, sizeof(buf), "Content-Disposition: inline;\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), " filename=\"%s\"\n", filename);
+ snprintf(buf, sizeof(buf), " filename=\"%s\"\r\n", filename);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "\n");
+ snprintf(buf, sizeof(buf), "\r\n");
write(fd_socket, buf, strlen(buf));
write_base64(fd_socket, infile);
@@ -5628,25 +7410,25 @@ void write_email_attach_file(int fd_socket, char *boundary, FILE *infile, char *
{
char buf[1024];
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
+ snprintf(buf, sizeof(buf), "--%s\r\n", boundary);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Type: application/octet-stream\n");
+ snprintf(buf, sizeof(buf), "Content-Type: application/octet-stream\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), " name=\"%s\"\n", filename);
+ snprintf(buf, sizeof(buf), " name=\"%s\"\r\n", filename);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\n");
+ snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "Content-Disposition: attachment;\n");
+ snprintf(buf, sizeof(buf), "Content-Disposition: attachment;\r\n");
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), " filename=\"%s\"\n", filename);
+ snprintf(buf, sizeof(buf), " filename=\"%s\"\r\n", filename);
write(fd_socket, buf, strlen(buf));
- snprintf(buf, sizeof(buf), "\n");
+ snprintf(buf, sizeof(buf), "\r\n");
write(fd_socket, buf, strlen(buf));
write_base64(fd_socket, infile);
diff --git a/src/xsane-save.c.orig b/src/xsane-save.c.orig
deleted file mode 100644
index a495e1c..0000000
--- a/src/xsane-save.c.orig
+++ /dev/null
@@ -1,5801 +0,0 @@
-/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend
-
- xsane-save.c
-
- Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
- This file is part of the XSANE package.
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#include "xsane.h"
-#include "xsane-back-gtk.h"
-#include "xsane-front-gtk.h"
-#include <time.h>
-#include <sys/wait.h>
-
-/* the following test is always false */
-#ifdef _native_WIN32
-# include <winsock.h>
-#else
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <netdb.h>
-#endif
-
-#ifdef HAVE_LIBJPEG
-#include <jpeglib.h>
-#endif
-
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-#ifdef HAVE_LIBPNG
-#include <png.h>
-#endif
-
-#ifdef HAVE_LIBTIFF
-#include <tiffio.h>
-#endif
-
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-
-#ifdef HAVE_OS2_H
-#include <process.h>
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_ANY_GIMP
-
-#include <libgimp/gimp.h>
-
-static void xsane_gimp_query(void);
-#ifdef HAVE_GIMP_2
-static void xsane_gimp_run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals);
-#else
-static void xsane_gimp_run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals);
-#endif
-
-GimpPlugInInfo PLUG_IN_INFO =
-{
- NULL, /* init_proc */
- NULL, /* quit_proc */
- xsane_gimp_query, /* query_proc */
- xsane_gimp_run, /* run_proc */
-};
-
-
-static int xsane_decode_devname(const char *encoded_devname, int n,
-char *buf);
-static int xsane_encode_devname(const char *devname, int n, char *buf);
-void null_print_func(gchar *msg);
-
-#endif /* HAVE_ANY_GIMP */
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* why this routine ?
- Problem: link attack
- Bad user wants to overwrite a file (mywork.txt) of good user.
- File permissions of mywork.txt is 700 so that bad user can not
- change or overwrite the file. Directory permissions allow bad user
- to write into directory. Bad user sets symlink from a file that good
- user will write soon (image.pnm) to mywork.txt.
- ==> Good user overwrites his own file, he is allowed to do so.
-
- Solution: remove file.
- Create outputfile and make sure that it does not exist while creation.
-
- The file is created with the requested image-file permissions.
-
- Note: This case is a bit curious because it is only a small part of a larger problem:
- When other users have write access to the directory they simply can move
- mywork.txt to image.pnm. If they do it in the right moment the file is
- overwritten without any notice of good user. If they do it long before xsane
- wants to write image.pnm then xsane will possibly ask if image.pnm shall be
- overwritten. So the real solution is to make the direcoty permissions safe!!!
- But some users asked for this and so I added this.
-
-
- This routine shall not be called for temporary files because temp files shall not
- be removed after they have been created safe. (Although a temporary file should
- not be a symlink so there should be no problem with this)
-*/
-
-int xsane_create_secure_file(const char *filename)
-/* returns 0 on success, -1 on error */
-{
- int fd;
-
- DBG(DBG_proc, "xsane_create_secure_file\n");
-
- remove(filename); /* we need to remove the file because open(..., O_EXCL) will fail otherwise */
- umask((mode_t) preferences.image_umask); /* define image file permissions */
- fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
- umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
-
- if (fd > 0)
- {
- DBG(DBG_info, "file %s is created and secure\n", filename);
- close(fd);
- fd = 0;
- }
- else
- {
- DBG(DBG_info, "could not create secure file %s\n", filename);
- }
-
- return fd; /* -1 means file is not safe !!! otherwise 0 */
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_cancel_save(int *cancel_save)
-{
- DBG(DBG_proc, "xsane_cancel_save\n");
- *cancel_save = 1;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_convert_text_to_filename(char **text)
-{
- DBG(DBG_proc, "xsane_convert_text_to_filename\n");
-
- if (text)
- {
- char *filename = *text;
- char buf[256];
- int buflen=0;
- int txtlen=0;
-
- while((filename[txtlen] != 0) && (buflen<253))
- {
- switch (filename[txtlen])
- {
- case ' ':
- buf[buflen++] = ':';
- buf[buflen++] = '_';
- txtlen++;
- break;
-
- case '/':
- buf[buflen++] = ':';
- buf[buflen++] = '%';
- txtlen++;
- break;
-
- case '*':
- buf[buflen++] = ':';
- buf[buflen++] = '#';
- txtlen++;
- break;
-
- case '?':
- buf[buflen++] = ':';
- buf[buflen++] = 'q';
- txtlen++;
- break;
-
- case '\\':
- buf[buflen++] = ':';
- buf[buflen++] = '=';
- txtlen++;
- break;
-
- case ';':
- buf[buflen++] = ':';
- buf[buflen++] = '!';
- txtlen++;
- break;
-
- case '&':
- buf[buflen++] = ':';
- buf[buflen++] = '+';
- txtlen++;
- break;
-
- case '<':
- buf[buflen++] = ':';
- buf[buflen++] = 's';
- txtlen++;
- break;
-
- case '>':
- buf[buflen++] = ':';
- buf[buflen++] = 'g';
- txtlen++;
- break;
-
- case '|':
- buf[buflen++] = ':';
- buf[buflen++] = 'p';
- txtlen++;
- break;
-
- case ':':
- buf[buflen++] = ':';
- buf[buflen++] = ':';
- txtlen++;
- break;
-
- default:
- buf[buflen++] = filename[txtlen++];
- break;
- }
- }
- buf[buflen] = 0;
- free(filename);
- *text = strdup(buf);
- DBG(DBG_info, "filename = \"%s\"\n", *text);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_get_filesize(char *filename)
-{
- FILE *infile;
- int pos;
- int size;
-
- infile = fopen(filename, "rb"); /* read binary (b for win32) */
- if (infile == NULL)
- {
- return 0;
- }
-
- pos = ftell(infile);
- fseek(infile, 0, SEEK_END); /* get size */
- size = ftell(infile);
- fseek(infile, pos, SEEK_SET); /* go to previous position */
-
- fclose(infile);
-
- return size;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_ensure_counter_in_filename(char **filename, int counter_len)
-{
- char *position_point = NULL;
- char *position;
- int counter = 1;
-
- DBG(DBG_proc, "xsane_ensure_counter_in_filename\n");
-
- if (!counter_len)
- {
- counter_len = 1;
- }
-
- position_point = strrchr(*filename, '.');
-
- if (!position_point) /* nothing usable ? */
- {
- position_point = *filename + strlen(*filename); /* position_point - 1 is last character */
- }
-
- if (position_point)
- {
- position = position_point-1;
- if ( (position < *filename) || (*position < '0') || (*position >'9') ) /* we have no counter */
- {
- char buf[PATH_MAX];
- int len;
-
- len = position_point - (*filename); /* length until "." or end of string */
- strncpy(buf, *filename, len);
- snprintf(buf+len, sizeof(buf)-len, "-%0*d%s", counter_len, counter, position_point);
- *filename = strdup(buf);
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_update_counter_in_filename(char **filename, int skip, int step, int min_counter_len)
-{
- FILE *testfile;
- char *position_point = NULL;
- char *position_counter;
- char buf[PATH_MAX];
- int counter;
- int counter_len;
- int set_counter_len = min_counter_len;
-
- DBG(DBG_proc, "xsane_update_counter_in_filename\n");
-
- if ( (!step) && (!min_counter_len) )
- {
- return; /* do not touch counter */
- }
-
- while (1) /* loop because we may have to skip existing files */
- {
- position_point = strrchr(*filename, '.');
-
- if (!position_point) /* nothing usable ? */
- {
- position_point = *filename + strlen(*filename); /* here is no point, but position - 1 is last character */
- }
-
- if (position_point)
- {
- position_counter = position_point-1; /* go to last number of counter (if counter exists) */
-
- /* search non numeric char */
- while ( (position_counter >= *filename) && (*position_counter >= '0') && (*position_counter <='9') )
- {
- position_counter--; /* search fisrt numeric character */
- }
-
- position_counter++; /* go to first numeric charcter */
-
- counter_len = position_point - position_counter;
-
- if (counter_len) /* we have a counter */
- {
- sscanf(position_counter, "%d", &counter);
- counter = counter + step; /* update counter */
-
- if (counter < 0)
- {
- counter = 0;
- xsane_back_gtk_warning(WARN_COUNTER_UNDERRUN, TRUE);
- break; /* last available number ("..999") */
- }
-
- *position_counter = 0; /* set end of string mark to counter start */
-
- if (set_counter_len == 0)
- {
- set_counter_len = counter_len;
- }
-
- snprintf(buf, sizeof(buf), "%s%0*d%s", *filename, set_counter_len, counter, position_point);
-
- DBG(DBG_info, "filename = \"%s\"\n", buf);
-
- free(*filename);
- *filename = strdup(buf);
-
- if (skip) /* test if filename already used */
- {
- if (preferences.filetype) /* add filetype to filename */
- {
- snprintf(buf, sizeof(buf), "%s%s", *filename, preferences.filetype);
- testfile = fopen(buf, "rb"); /* read binary (b for win32) */
- }
- else /* filetype in filename */
- {
- testfile = fopen(*filename, "rb"); /* read binary (b for win32) */
- }
-
- if (testfile) /* filename used: skip */
- {
- fclose(testfile);
- }
- else
- {
- break; /* filename not used, ok */
- }
- }
- else /* do not test if filename already used */
- {
- break; /* filename ok */
- }
- }
- else /* no counter */
- {
- break; /* no counter */
- }
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_read_pnm_header(FILE *file, Image_info *image_info)
-{
- int max_val, filetype_nr;
- char buf[256];
-
- fgets(buf, sizeof(buf)-1, file);
- DBG(DBG_info, "filetype header :%s", buf);
-
- if (buf[0] == 'P')
- {
- filetype_nr = atoi(buf+1); /* get filetype number */
-
- image_info->resolution_x = 72.0;
- image_info->resolution_y = 72.0;
- image_info->reduce_to_lineart = FALSE;
-
- while (strcmp(buf, "# XSANE data follows\n"))
- {
- fgets(buf, sizeof(buf)-1, file);
-
- if (!strncmp(buf, "# resolution_x =", 20))
- {
- sscanf(buf+20, "%lf", &image_info->resolution_x);
- }
- else if (!strncmp(buf, "# resolution_y =", 20))
- {
- sscanf(buf+20, "%lf", &image_info->resolution_y);
- }
- else if (!strncmp(buf, "# threshold =", 20))
- {
- sscanf(buf+20, "%lf", &image_info->threshold);
- }
- else if (!strncmp(buf, "# gamma =", 20))
- {
- sscanf(buf+20, "%lf", &image_info->gamma);
- }
- else if (!strncmp(buf, "# gamma IRGB =", 20))
- {
- sscanf(buf+20, "%lf %lf %lf %lf",
- &image_info->gamma,
- &image_info->gamma_red,
- &image_info->gamma_green,
- &image_info->gamma_blue);
- }
- else if (!strncmp(buf, "# brightness =", 20))
- {
- sscanf(buf+20, "%lf", &image_info->brightness);
- }
- else if (!strncmp(buf, "# brightness IRGB =", 20))
- {
- sscanf(buf+20, "%lf %lf %lf %lf",
- &image_info->brightness,
- &image_info->brightness_red,
- &image_info->brightness_green,
- &image_info->brightness_blue);
- }
- else if (!strncmp(buf, "# contrast =", 20))
- {
- sscanf(buf+20, "%lf", &image_info->contrast);
- }
- else if (!strncmp(buf, "# contrast IRGB =", 20))
- {
- sscanf(buf+20, "%lf %lf %lf %lf",
- &image_info->contrast,
- &image_info->contrast_red,
- &image_info->contrast_green,
- &image_info->contrast_blue);
- }
- else if (!strncmp(buf, "# reduce to lineart", 20))
- {
- image_info->reduce_to_lineart = TRUE;
- }
- }
-
- fscanf(file, "%d %d", &image_info->image_width, &image_info->image_height);
-
- image_info->depth = 1;
-
- if (filetype_nr != 4) /* P4 = lineart */
- {
- fscanf(file, "%d", &max_val);
-
- if (max_val == 255)
- {
- image_info->depth = 8;
- }
- else if (max_val == 65535)
- {
- image_info->depth = 16;
- }
- }
-
- fgetc(file); /* read exactly one newline character */
-
-
- image_info->colors = 1;
-
- if (filetype_nr == 6) /* ppm RGB */
- {
- image_info->colors = 3;
- }
- }
-#ifdef SUPPORT_RGBA
- else if (buf[0] == 'S') /* RGBA format */
- {
- fscanf(file, "%d %d\n%d", &image_info->image_width, &image_info->image_height, &max_val);
- fgetc(file); /* read exactly one newline character */
-
- image_info->depth = 1;
-
- if (max_val == 255)
- {
- image_info->depth = 8;
- }
- else if (max_val == 65535)
- {
- image_info->depth = 16;
- }
-
- image_info->colors = 4;
- }
-#endif
-
- DBG(DBG_info, "xsane_read_pnm_header: width=%d, height=%d, depth=%d, colors=%d, resolution_x=%f, resolution_y=%f\n",
- image_info->image_width, image_info->image_height, image_info->depth, image_info->colors,
- image_info->resolution_x, image_info->resolution_y);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_as_ascii)
-{
- int maxval;
- int magic;
-
- fflush(file);
- rewind(file);
-
- if (image_info->depth > 8)
- {
- maxval = 65535;
-
- if (save_pnm16_as_ascii)
- {
- magic = 2; /* thats the magic number for grayscale ascii, 3 = color ascii */
- }
- else /* save pnm as binary */
- {
- magic = 5; /* that is the magic number for grayscake binary, 6 = color binary */
- }
- }
- else
- {
- maxval = 255;
- magic = 5; /* 8 bit images are always saved in binary mode */
- }
-
-
- if (image_info->colors == 1)
- {
- if (image_info->depth == 1)
- {
- /* do not touch the texts and length here, the reading routine needs to know the exact texts */
- fprintf(file, "P4\n"
- "# XSane settings:\n"
- "# resolution_x = %6.1f\n"
- "# resolution_y = %6.1f\n"
- "# threshold = %4.1f\n"
- "# XSANE data follows\n"
- "%05d %05d\n",
- image_info->resolution_x,
- image_info->resolution_y,
- image_info->threshold,
- image_info->image_width, image_info->image_height);
- }
- else if (image_info->reduce_to_lineart)
- {
- /* do not touch the texts and length here, the reading routine needs to know the exact texts */
- fprintf(file, "P%d\n"
- "# XSane settings:\n"
- "# resolution_x = %6.1f\n"
- "# resolution_y = %6.1f\n"
- "# threshold = %4.1f\n"
- "# reduce to lineart\n"
- "# XSANE data follows\n"
- "%05d %05d\n"
- "%d\n",
- magic, /* P5 for binary, P2 for ascii */
- image_info->resolution_x,
- image_info->resolution_y,
- image_info->threshold,
- image_info->image_width, image_info->image_height,
- maxval);
- }
- else
- {
- fprintf(file, "P%d\n"
- "# XSane settings:\n"
- "# resolution_x = %6.1f\n"
- "# resolution_y = %6.1f\n"
- "# gamma = %3.2f\n"
- "# brightness = %4.1f\n"
- "# contrast = %4.1f\n"
- "# XSANE data follows\n"
- "%05d %05d\n"
- "%d\n",
- magic, /* P5 for binary, P2 for ascii */
- image_info->resolution_x,
- image_info->resolution_y,
- image_info->gamma,
- image_info->brightness,
- image_info->contrast,
- image_info->image_width, image_info->image_height,
- maxval);
- }
- }
- else if (image_info->colors == 3)
- {
- fprintf(file, "P%d\n"
- "# XSane settings:\n"
- "# resolution_x = %6.1f\n"
- "# resolution_y = %6.1f\n"
- "# gamma IRGB = %3.2f %3.2f %3.2f %3.2f\n"
- "# brightness IRGB = %4.1f %4.1f %4.1f %4.1f\n"
- "# contrast IRGB = %4.1f %4.1f %4.1f %4.1f\n"
- "# XSANE data follows\n"
- "%05d %05d\n" \
- "%d\n",
- magic+1, /* P6 for binary, P3 for ascii */
- image_info->resolution_x,
- image_info->resolution_y,
- image_info->gamma, image_info->gamma_red, image_info->gamma_green, image_info->gamma_blue,
- image_info->brightness, image_info->brightness_red, image_info->brightness_green, image_info->brightness_blue,
- image_info->contrast, image_info->contrast_red, image_info->contrast_green, image_info->contrast_blue,
- image_info->image_width, image_info->image_height,
- maxval);
- }
-#ifdef SUPPORT_RGBA
- else if (image_info->colors == 4)
- {
- fprintf(file, "SANE_RGBA\n" \
- "%d %d\n" \
- "%d\n",
- image_info->image_width, image_info->image_height, maxval);
- }
-#endif
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_copy_file(FILE *outfile, FILE *infile, GtkProgressBar *progress_bar, int *cancel_save)
-{
- long size;
- long bytes_sum = 0;
- size_t bytes;
- unsigned char buf[65536];
-
- DBG(DBG_proc, "copying file\n");
-
- fseek(infile, 0, SEEK_END);
- size = ftell(infile);
- fseek(infile, 0, SEEK_SET);
-
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- while (!feof(infile))
- {
- bytes = fread(buf, 1, sizeof(buf), infile);
- if (bytes > 0)
- {
- fwrite(buf, 1, bytes, outfile);
- bytes_sum += bytes;
- }
-
- gtk_progress_bar_update(progress_bar, (float) bytes_sum / size); /* update progress bar */
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- if (ferror(infile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_READ, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- fflush(outfile);
-
- if (size != bytes_sum)
- {
- DBG(DBG_info, "copy errro, not complete, %ld bytes of %ld bytes copied\n", bytes_sum, size);
- *cancel_save = 1;
- return (*cancel_save);
- }
-
- DBG(DBG_info, "copy complete, %ld bytes copied\n", bytes_sum);
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_copy_file_by_name(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save)
-{
- FILE *infile;
- FILE *outfile;
-
- DBG(DBG_proc, "copying file %s to %s\n", input_filename, output_filename);
-
- outfile = fopen(output_filename, "wb"); /* b = binary mode for win32 */
-
- if (outfile == 0)
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, output_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
- return -2;
- }
-
- infile = fopen(input_filename, "rb"); /* read binary (b for win32) */
- if (infile == 0)
- {
- char buf[256];
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- fclose(outfile);
- remove(output_filename); /* remove already created output file */
- return -1;
- }
-
- xsane_copy_file(outfile, infile, progress_bar, cancel_save);
-
- fclose(infile);
- fclose(outfile);
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), "");
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_grayscale_image_as_lineart(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x, y, bit;
- u_char bitval, packed;
-
- *cancel_save = 0;
-
- image_info->depth = 1;
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (y = 0; y < image_info->image_height; y++)
- {
- bit = 128;
- packed = 0;
-
- for (x = 0; x < image_info->image_width; x++)
- {
- bitval = fgetc(imagefile);
-
- if (!bitval) /* white gets 0 bit, black gets 1 bit */
- {
- packed |= bit;
- }
-
- if (bit == 1)
- {
- fputc(packed, outfile);
- bit = 128;
- packed = 0;
- }
- else
- {
- bit >>= 1;
- }
- }
-
- if (bit != 128)
- {
- fputc(packed, outfile);
- bit = 128;
- packed = 0;
- }
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height); /* update progress bar */
- while (gtk_events_pending()) /* give gtk the chance to display the changes */
- {
- gtk_main_iteration();
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int original_image_width = image_info->image_width;
- int original_image_height = image_info->image_height;
- int new_image_width = image_info->image_width * x_scale + 0.5;
- int new_image_height = image_info->image_height * y_scale + 0.5;
- unsigned char *original_line;
- guint16 *original_line16 = NULL;
- unsigned char *new_line;
- float *pixel_val;
- float *pixel_norm;
- int bytespp = 1;
- float x, y;
- int c;
- int oldy;
- int x_new, y_new;
- float x_go, y_go;
- float factor, x_factor, y_factor;
- guint16 color;
- int read_line;
-
- DBG(DBG_proc, "xsane_save_scaled_image\n");
-
- *cancel_save = 0;
-
- if (image_info->depth > 8)
- {
- bytespp = 2;
- }
-
- image_info->image_width = new_image_width;
- image_info->image_height = new_image_height;
- image_info->resolution_x *= x_scale;
- image_info->resolution_y *= y_scale;
-
- original_line = malloc(original_image_width * image_info->colors * bytespp);
- if (!original_line)
- {
- DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
- return -1;
- }
-
- new_line = malloc(new_image_width * image_info->colors * bytespp);
- if (!new_line)
- {
- free(original_line);
- DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
- return -1;
- }
-
- pixel_val = malloc(new_image_width * image_info->colors * sizeof(float));
- if (!pixel_val)
- {
- free(original_line);
- free(new_line);
- DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
- return -1;
- }
-
- pixel_norm = malloc(new_image_width * image_info->colors * sizeof(float));
- if (!pixel_norm)
- {
- free(original_line);
- free(new_line);
- free(pixel_val);
- DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
- return -1;
- }
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- read_line = TRUE;
-
- memset(pixel_val, 0, new_image_width * image_info->colors * sizeof(float));
- memset(pixel_norm, 0, new_image_width * image_info->colors * sizeof(float));
-
- y_new = 0;
- y_go = 1.0 / y_scale;
- y_factor = 1.0;
- y = 0.0;
-
- while (y < original_image_height)
- {
- DBG(DBG_info2, "xsane_save_scaled_image: original line %d, new line %d\n", (int) y, y_new);
-
- gtk_progress_bar_update(progress_bar, (float) y / original_image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- if (read_line)
- {
- DBG(DBG_info, "xsane_save_scaled_image: reading original line %d\n", (int) y);
- fread(original_line, original_image_width, image_info->colors * bytespp, imagefile); /* read one line */
- original_line16 = (guint16 *) original_line;
- }
-
- x_new = 0;
- x_go = 1.0 / x_scale;
- x = 0.0;
- x_factor = 1.0;
-
- while ( (x < original_image_width) && (x_new < new_image_width) ) /* add this line to anti aliasing buffer */
-
- {
- factor = x_factor * y_factor;
-
- for (c = 0; c < image_info->colors; c++)
- {
- if (bytespp == 1)
- {
- color = original_line[((int) x) * image_info->colors + c];
- }
- else /* bytespp == 2 */
- {
- color = original_line16[((int) x) * image_info->colors + c];
- }
-
- pixel_val [x_new * image_info->colors + c] += factor * color;
- pixel_norm[x_new * image_info->colors + c] += factor;
- }
-
- x_go -= x_factor;
-
- if (x_go <= 0.0) /* change of pixel in new image */
- {
- x_new++;
- x_go = 1.0 / x_scale;
-
- x_factor = x - (int) x; /* use pixel rest */
- if (x_factor > x_go)
- {
- x_factor = x_go;
- }
- }
- else
- {
- x_factor = x_go;
- }
-
- if (x_factor > 1.0)
- {
- x_factor = 1.0;
- }
-
- x += x_factor;
- }
-
- y_go -= y_factor;
-
- if (y_go <= 0.0) /* normalize one line and write to destination image file */
- {
- DBG(DBG_info2, "xsane_save_scaled_image: writing new line %d\n", y_new);
-
- if (bytespp == 1)
- {
- for (x_new = 0; x_new < new_image_width * image_info->colors; x_new++)
- {
- new_line[x_new] = (int) (pixel_val[x_new] / pixel_norm[x_new]);
- }
- }
- else /* bytespp == 2 */
- {
- guint16 *new_line16 = (guint16 *) new_line;
-
- for (x_new = 0; x_new < new_image_width * image_info->colors; x_new++)
- {
- new_line16[x_new] = (int) (pixel_val[x_new] / pixel_norm[x_new]);
- }
- }
-
- fwrite(new_line, new_image_width, image_info->colors * bytespp, outfile); /* write one line */
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- /* reset values and norm factors */
- memset(pixel_val, 0, new_image_width * image_info->colors * sizeof(float));
- memset(pixel_norm, 0, new_image_width * image_info->colors * sizeof(float));
-
- y_new++;
- y_go = 1.0 / y_scale;
-
- y_factor = y - (int) y;
- if (y_factor > y_go)
- {
- y_factor = y_go;
- }
- }
- else
- {
- y_factor = y_go;
- }
-
- if (y_factor > 1.0)
- {
- y_factor = 1.0;
- }
-
- oldy = (int) y;
- y += y_factor;
- read_line = (oldy != (int) y);
- }
-
- free(original_line);
- free(new_line);
- free(pixel_val);
- free(pixel_norm);
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-#if 0
-int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save)
-{
- float original_y;
- int old_original_y;
- int x, y, i;
- int original_image_width = image_info->image_width;
- int new_image_width = image_info->image_width * x_scale;
- int new_image_height = image_info->image_height * y_scale;
- unsigned char *original_line;
- unsigned char *new_line;
- int bytespp = 1;
-
- DBG(DBG_proc, "xsane_save_scaled_image\n");
-
- if (image_info->depth > 8)
- {
- bytespp = 2;
- }
-
- image_info->image_width = new_image_width;
- image_info->image_height = new_image_height;
- image_info->resolution_x *= x_scale;
- image_info->resolution_y *= y_scale;
-
- original_line = malloc(original_image_width * image_info->colors * bytespp);
- if (!original_line)
- {
- DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
- return -1;
- }
-
- new_line = malloc(new_image_width * image_info->colors * bytespp);
- if (!new_line)
- {
- free(original_line);
- DBG(DBG_error, "xsane_save_scaled_image: out of memory\n");
- return -1;
- }
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- original_y = 0.0;
- old_original_y = -1;
-
- for (y = 0; y < new_image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (; ((int) original_y) - old_original_y; old_original_y += 1)
- {
- fread(original_line, original_image_width, image_info->colors * bytespp, imagefile); /* read one line */
- }
-
- for (x = 0; x < new_image_width; x++)
- {
- for (i = 0; i < image_info->colors * bytespp; i++)
- {
- new_line[x * image_info->colors * bytespp + i] = original_line[((int) (x / x_scale)) * image_info->colors * bytespp + i];
- }
- }
-
- fwrite(new_line, new_image_width, image_info->colors * bytespp, outfile); /* write one line */
-
- original_y += 1/y_scale;
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- free(original_line);
- free(new_line);
-
- fflush(outfile);
-
- return (*cancel_save);
-}
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x, y, sx, sy, i;
- int xmin, xmax;
- int ymin, ymax;
- int count;
- unsigned char *line_cache;
- unsigned char *line_cache_ptr;
- guint16 *color_cache;
- guint16 *color_cache_ptr;
- int bytespp = 1;
- int color_radius;
- int color_width = image_info->image_width * image_info->colors;
-
- radius--; /* correct radius : 1 means nothing happens */
-
- if (radius < 1)
- {
- radius = 1;
- }
-
- color_radius = radius * image_info->colors;
-
- if (image_info->depth > 8)
- {
- bytespp = 2;
- }
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- line_cache = malloc(color_width * bytespp * (2 * radius + 1));
- if (!line_cache)
- {
- DBG(DBG_error, "xsane_despeckle_image: out of memory\n");
- return -1;
- }
-
- fread(line_cache, color_width * bytespp, (2 * radius + 1), imagefile);
-
- color_cache = malloc((size_t) sizeof(guint16) * (2*radius+1)*(2*radius+1));
-
- if (!color_cache)
- {
- free(line_cache);
- DBG(DBG_error, "xsane_despeckle_image: out of memory\n");
- return -1;
- }
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- ymin = y - radius;
- ymax = y + radius;
-
- if (ymin < 0)
- {
- ymin = 0;
- }
-
- if (ymax > image_info->image_height)
- {
- ymax = image_info->image_height;
- }
-
- for (x = 0; x < color_width; x++)
- {
- xmin = x - color_radius;
- xmax = x + color_radius;
-
- if (xmin < 0)
- {
- xmin = x % image_info->colors;
- }
-
- if (xmax > color_width)
- {
- xmax = color_width;
- }
-
- count = 0;
-
- color_cache_ptr = color_cache;
-
-
- if (bytespp == 1)
- {
- for (sy = ymin; sy <= ymax; sy++) /* search area defined by radius - y part */
- {
- line_cache_ptr = line_cache + (sy-ymin) * color_width + xmin;
-
- for (sx = xmin; sx <= xmax; sx+=image_info->colors) /* x part */
- {
- *color_cache_ptr = *line_cache_ptr;
- color_cache_ptr++;
- line_cache_ptr += image_info->colors;
- }
- }
-
- /* sort color_cache */
-
- count = color_cache_ptr - color_cache;
-
- if (count > 1)
- {
- int d, j, val;
-
- for (d = count / 2; d > 0; d = d / 2)
- {
- for (i = d; i < count; i++)
- {
- for (j = i - d, color_cache_ptr = color_cache + j; j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; j -= d, color_cache_ptr -= d)
- {
- val = color_cache_ptr[0];
- color_cache_ptr[0] = color_cache_ptr[d];
- color_cache_ptr[d] = val;
- };
- }
- }
- }
-
- fputc((char) (color_cache[count/2]), outfile);
- }
- else /* 16 bit/color */
- {
- guint16 val16;
- guint16 *line_cache16 = (guint16 *) line_cache;
- guint16 *line_cache16_ptr;
- char *bytes16 = (char *) &val16;
-
- for (sy = ymin; sy <= ymax; sy++)
- {
- line_cache16_ptr = line_cache16 + (sy-ymin) * color_width + xmin;
-
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
- {
- *color_cache_ptr = *line_cache16_ptr;
- color_cache_ptr++;
- line_cache16_ptr += image_info->colors;
- }
- }
-
- /* sort color_cache */
-
- count = color_cache_ptr - color_cache;
-
- if (count > 1)
- {
- int d,j, val;
-
- for (d = count / 2; d > 0; d = d / 2)
- {
- for (i = d; i < count; i++)
- {
- for (j = i - d, color_cache_ptr = color_cache + j; j >= 0 && color_cache_ptr[0] > color_cache_ptr[d]; j -= d, color_cache_ptr -= d)
- {
- val = color_cache_ptr[0];
- color_cache_ptr[0] = color_cache_ptr[d];
- color_cache_ptr[d] = val;
- };
- }
- }
- }
-
- val16 = color_cache[count/2];
- fputc(bytes16[0], outfile); /* write bytes in machine byte order */
- fputc(bytes16[1], outfile);
- }
- }
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if ((y > radius) && (y < image_info->image_height - radius))
- {
- memcpy(line_cache, line_cache + color_width * bytespp,
- color_width * bytespp * 2 * radius);
- fread(line_cache + color_width * bytespp * 2 * radius,
- color_width * bytespp, 1, imagefile);
- }
- }
-
- fflush(outfile);
-
- free(line_cache);
- free(color_cache);
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float radius, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x, y, sx, sy;
- int xmin, xmax;
- int ymin, ymax;
- double val, norm, outer_factor;
- unsigned char *line_cache;
- int bytespp = 1;
- int intradius;
- int xmin_flag;
- int xmax_flag;
- int ymin_flag;
- int ymax_flag;
-
- *cancel_save = 0;
-
- intradius = (int) radius;
-
- outer_factor = radius - (int) radius;
-
- if (image_info->depth > 8)
- {
- bytespp = 2;
- }
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- line_cache = malloc(image_info->image_width * image_info->colors * bytespp * (2 * intradius + 1));
- if (!line_cache)
- {
- DBG(DBG_error, "xsane_blur_image: out of memory\n");
- return -1;
- }
-
- fread(line_cache, image_info->image_width * image_info->colors * bytespp, (2 * intradius + 1), imagefile);
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = 0; x < image_info->image_width * image_info->colors; x++)
- {
- xmin_flag = xmax_flag = ymin_flag = ymax_flag = TRUE;
-
- xmin = x - intradius * image_info->colors;
- xmax = x + intradius * image_info->colors;
-
- if (xmin < 0)
- {
- xmin = x % image_info->colors;
- xmin_flag = FALSE;
- }
-
- if (xmax > image_info->image_width * image_info->colors)
- {
- xmax = image_info->image_width * image_info->colors;
- xmax_flag = FALSE;
- }
-
- ymin = y - intradius;
- ymax = y + intradius;
-
- if (ymin < 0)
- {
- ymin = 0;
- ymin_flag = FALSE;
- }
-
- if (ymax > image_info->image_height)
- {
- ymax = image_info->image_height;
- ymax_flag = FALSE;
- }
-
- val = 0.0;
- norm = 0.0;
-
- if (bytespp == 1)
- {
- if (xmin_flag) /* integrate over left margin */
- {
- for (sy = ymin+1; sy <= ymax-1 ; sy++)
- {
- val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->colors + xmin];
- norm += outer_factor;
- }
- }
-
- if (xmax_flag) /* integrate over right margin */
- {
- for (sy = ymin+1; sy <= ymax-1 ; sy++)
- {
- val += outer_factor * line_cache[(sy-ymin) * image_info->image_width * image_info->colors + xmax];
- norm += outer_factor;
- }
- }
-
- if (ymin_flag) /* integrate over top margin */
- {
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
- {
- val += outer_factor * line_cache[sx];
- norm += outer_factor;
- }
- }
-
- if (ymax_flag) /* integrate over bottom margin */
- {
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
- {
- val += outer_factor * line_cache[(ymax-ymin) * image_info->image_width * image_info->colors + sx];
- norm += outer_factor;
- }
- }
-
- for (sy = ymin+1; sy <= ymax-1; sy++) /* integrate internal square */
- {
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors; sx+=image_info->colors)
- {
- val += line_cache[(sy-ymin) * image_info->image_width * image_info->colors + sx];
- norm += 1.0;
- }
- }
- fputc((char) ((int) (val/norm)), outfile);
- }
- else /* bytespp == 2 */
- {
- guint16 *line_cache16 = (guint16 *) line_cache;
- guint16 val16;
- char *bytes16 = (char *) &val16;
-
- if (xmin_flag) /* integrate over left margin */
- {
- for (sy = ymin+1; sy <= ymax-1 ; sy++)
- {
- val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + xmin];
- norm += outer_factor;
- }
- }
-
- if (xmax_flag) /* integrate over right margin */
- {
- for (sy = ymin+1; sy <= ymax-1 ; sy++)
- {
- val += outer_factor * line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + xmax];
- norm += outer_factor;
- }
- }
-
- if (ymin_flag) /* integrate over top margin */
- {
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
- {
- val += outer_factor * line_cache16[sx];
- norm += outer_factor;
- }
- }
-
- if (ymax_flag) /* integrate over bottom margin */
- {
- for (sx = xmin+image_info->colors; sx <= xmax-image_info->colors ; sx += image_info->colors)
- {
- val += outer_factor * line_cache16[(ymax-ymin) * image_info->image_width * image_info->colors + sx];
- norm += outer_factor;
- }
- }
-
- for (sy = ymin; sy <= ymax; sy++) /* integrate internal square */
- {
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
- {
- val += line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + sx];
- norm += 1.0;
- }
- }
-
- val16 = val / norm;
- fputc(bytes16[0], outfile); /* write bytes in machine byte order */
- fputc(bytes16[1], outfile);
- }
- }
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- /* reset values and norm factors */
-
- if ((y > intradius) && (y < image_info->image_height - intradius))
- {
- memcpy(line_cache, line_cache + image_info->image_width * image_info->colors * bytespp,
- image_info->image_width * image_info->colors * bytespp * 2 * intradius);
- fread(line_cache + image_info->image_width * image_info->colors * bytespp * 2 * intradius,
- image_info->image_width * image_info->colors * bytespp, 1, imagefile);
- }
- }
-
- fflush(outfile);
- free(line_cache);
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#if 0
-int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar)
-{
- int x, y, sx, sy;
- int xmin, xmax;
- int ymin, ymax;
- int pos0;
- int val, count;
- unsigned char *line_cache;
- int bytespp = 1;
-
- if (image_info->depth > 8)
- {
- bytespp = 2;
- }
-
- pos0 = ftell(imagefile); /* mark position to skip header */
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- line_cache = malloc(image_info->image_width * image_info->colors * bytespp * (2 * radius + 1));
- if (!line_cache)
- {
- DBG(DBG_error, "xsane_blur_image: out of memory\n");
- return -1;
- }
-
- fread(line_cache, image_info->image_width * image_info->colors * bytespp, (2 * radius + 1), imagefile);
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = 0; x < image_info->image_width * image_info->colors; x++)
- {
- xmin = x - radius * image_info->colors;
- xmax = x + radius * image_info->colors;
-
- if (xmin < 0)
- {
- xmin = x % image_info->colors;
- }
-
- if (xmax > image_info->image_width * image_info->colors)
- {
- xmax = image_info->image_width * image_info->colors;
- }
-
- ymin = y - radius;
- ymax = y + radius;
-
- if (ymin < 0)
- {
- ymin = 0;
- }
-
- if (ymax > image_info->image_height)
- {
- ymax = image_info->image_height;
- }
-
- val = 0;
- count = 0;
-
- if (bytespp == 1)
- {
- for (sy = ymin; sy <= ymax; sy++)
- {
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
- {
- val += line_cache[(sy-ymin) * image_info->image_width * image_info->colors + sx];
- count++;
- }
- }
- fputc((char) (val/count), outfile);
- }
- else
- {
- guint16 *line_cache16 = (guint16 *) line_cache;
- guint16 val16;
- char *bytes16 = (char *) &val16;
-
- for (sy = ymin; sy <= ymax; sy++)
- {
- for (sx = xmin; sx <= xmax; sx+=image_info->colors)
- {
- val += line_cache16[(sy-ymin) * image_info->image_width * image_info->colors + sx];
- count++;
- }
- }
-
- val16 = val / count;
- fputc(bytes16[0], outfile); /* write bytes in machine byte order */
- fputc(bytes16[1], outfile);
- }
- }
-
- if ((y > radius) && (y < image_info->image_height - radius))
- {
- memcpy(line_cache, line_cache + image_info->image_width * image_info->colors * bytespp,
- image_info->image_width * image_info->colors * bytespp * 2 * radius);
- fread(line_cache + image_info->image_width * image_info->colors * bytespp * 2 * radius,
- image_info->image_width * image_info->colors * bytespp, 1, imagefile);
- }
- }
-
- fflush(outfile);
- free(line_cache);
-
- return 0;
-}
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int rotation, GtkProgressBar *progress_bar, int *cancel_save)
-/* returns true if operation was cancelled */
-{
- int x, y, pos0, bytespp, i;
- int pixel_width = image_info->image_width;
- int pixel_height = image_info->image_height;
- float resolution_x = image_info->resolution_x;
- float resolution_y = image_info->resolution_y;
-
-#ifdef HAVE_MMAP
- char *mmaped_imagefile = NULL;
-#endif
-
- DBG(DBG_proc, "xsane_save_rotate_image\n");
-
- *cancel_save = 0;
-
- pos0 = ftell(imagefile); /* mark position to skip header */
-
- bytespp = image_info->colors;
-
- if (image_info->depth > 8)
- {
- bytespp *= 2;
- }
-
- if (image_info->depth < 8) /* lineart images are expanded to grayscale until transformation is done */
- {
- image_info->depth = 8; /* so we have at least 8 bits/pixel here */
- }
-
-#ifdef HAVE_MMAP
- mmaped_imagefile = mmap(NULL, pixel_width * pixel_height * bytespp + pos0, PROT_READ, MAP_PRIVATE, fileno(imagefile), 0);
- if (mmaped_imagefile == (char *) -1) /* mmap failed */
- {
- DBG(DBG_info, "xsane_save_rotate_image: unable to memory map image file, using standard file access\n");
- mmaped_imagefile = NULL;
- }
- else
- {
- DBG(DBG_info, "xsane_save_rotate_image: using memory mapped image file\n");
- }
-#endif
-
- switch (rotation)
- {
- default:
- break;
-
- case 0: /* 0 degree */
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (y = 0; y < pixel_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / pixel_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = 0; x < pixel_width; x++)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i=0; i<bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
-
- case 1: /* 90 degree */
- image_info->image_width = pixel_height;
- image_info->image_height = pixel_width;
-
- image_info->resolution_x = resolution_y;
- image_info->resolution_y = resolution_x;
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (x=0; x<pixel_width; x++)
- {
- gtk_progress_bar_update(progress_bar, (float) x / pixel_width);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (y=pixel_height-1; y>=0; y--)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i=0; i<bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i=0; i<bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- break;
-
- case 2: /* 180 degree */
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (y = pixel_height-1; y >= 0; y--)
- {
- gtk_progress_bar_update(progress_bar, (float) (pixel_height - y) / pixel_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = pixel_width-1; x >= 0; x--)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i = 0; i < bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
-
- case 3: /* 270 degree */
- image_info->image_width = pixel_height;
- image_info->image_height = pixel_width;
-
- image_info->resolution_x = resolution_y;
- image_info->resolution_y = resolution_x;
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (x = pixel_width-1; x >= 0; x--)
- {
- gtk_progress_bar_update(progress_bar, (float) (pixel_width - x) / pixel_width);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (y = 0; y < pixel_height; y++)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i = 0; i < bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
-
- case 4: /* 0 degree, x mirror */
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (y = 0; y < pixel_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / pixel_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = pixel_width-1; x >= 0; x--)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i = 0; i < bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
-
- case 5: /* 90 degree, x mirror */
- image_info->image_width = pixel_height;
- image_info->image_height = pixel_width;
-
- image_info->resolution_x = resolution_y;
- image_info->resolution_y = resolution_x;
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (x = 0; x < pixel_width; x++)
- {
- gtk_progress_bar_update(progress_bar, (float) x / pixel_width);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (y = 0; y < pixel_height; y++)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i=0; i<bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- break;
-
- case 6: /* 180 degree, x mirror */
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (y = pixel_height-1; y >= 0; y--)
- {
- gtk_progress_bar_update(progress_bar, (float) (pixel_height - y) / pixel_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = 0; x < pixel_width; x++)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i = 0; i < bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
-
- case 7: /* 270 degree, x mirror */
- image_info->image_width = pixel_height;
- image_info->image_height = pixel_width;
-
- image_info->resolution_x = resolution_y;
- image_info->resolution_y = resolution_x;
-
- xsane_write_pnm_header(outfile, image_info, 0);
-
- for (x = pixel_width-1; x >= 0; x--)
- {
- gtk_progress_bar_update(progress_bar, (float) (pixel_width - x) / pixel_width);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (y = pixel_height-1; y >= 0; y--)
- {
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- char *p = mmaped_imagefile + pos0 + bytespp * (x + y * pixel_width); /* calculate correct position */
-
- for (i = 0; i < bytespp; i++)
- {
- fputc(*p++, outfile);
- }
- }
- else
-#endif
- {
- fseek(imagefile, pos0 + bytespp * (x + y * pixel_width), SEEK_SET); /* go to the correct position */
- for (i = 0; i < bytespp; i++)
- {
- fputc(fgetc(imagefile), outfile);
- }
- }
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
- }
-
-#ifdef HAVE_MMAP
- if (mmaped_imagefile)
- {
- munmap(mmaped_imagefile, pos0 + pixel_width * pixel_height * bytespp);
- }
-#endif
-
- fflush(outfile);
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdecode)
-{
- DBG(DBG_proc, "xsane_save_ps_create_document_header\n");
-
- fprintf(outfile, "%%!PS-Adobe-3.0\n");
- fprintf(outfile, "%%%%Creator: XSane version %s (sane %d.%d) - by Oliver Rauch\n", VERSION,
- SANE_VERSION_MAJOR(xsane.sane_backend_versioncode),
- SANE_VERSION_MINOR(xsane.sane_backend_versioncode));
- fprintf(outfile, "%%%%DocumentData: Clean7Bit\n");
- if (flatdecode)
- {
- fprintf(outfile, "%%%%LanguageLevel: 3\n");
- }
- else
- {
- fprintf(outfile, "%%%%LanguageLevel: 2\n");
- }
-
- if (pages)
- {
- fprintf(outfile, "%%%%Pages: %d\n", pages);
- }
- else
- {
- fprintf(outfile, "%%%%Pages: (atend)\n");
- }
-
- fprintf(outfile, "%%%%EndComments\n");
- fprintf(outfile, "\n");
- fprintf(outfile, "/origstate save def\n");
- fprintf(outfile, "20 dict begin\n");
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void xsane_save_ps_create_document_trailer(FILE *outfile, int pages)
-{
- DBG(DBG_proc, "xsane_save_ps_create_document_trailer\n");
-
- fprintf(outfile, "end\n");
- fprintf(outfile, "origstate restore\n");
-
- if (pages)
- {
- fprintf(outfile, "%%%%Trailer\n");
- fprintf(outfile, "%%%%Pages: %d\n", pages);
- }
-
- fprintf(outfile, "%%%%EOF\n");
- fprintf(outfile, "\n");
-
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* page = [1 .. pages] */
-static void xsane_save_ps_create_page_header(FILE *outfile, int page,
- Image_info *image_info,
- float width, float height,
- int paper_left_margin, int paper_bottom_margin,
- int paper_width, int paper_height,
- int paper_orientation, int flatdecode,
- GtkProgressBar *progress_bar)
-{
- int degree, position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth;
- int left, bottom;
-
- DBG(DBG_proc, "xsane_save_ps_create_page_header\n");
-
- switch (paper_orientation)
- {
- default:
- case 0: /* top left portrait */
- left = 0.0;
- bottom = paper_height - height;
- break;
-
- case 1: /* top right portrait */
- left = paper_width - width;
- bottom = paper_height - height;
- break;
-
- case 2: /* bottom right portrait */
- left = paper_width - width;
- bottom = 0.0;
- break;
-
- case 3: /* bottom left portrait */
- left = 0.0;
- bottom = 0.0;
- break;
-
- case 4: /* center portrait */
- left = paper_width / 2.0 - width / 2.0;
- bottom = paper_height / 2.0 - height / 2.0;
- break;
-
-
- case 8: /* top left landscape */
- left = 0.0;
- bottom = paper_width - height;
- break;
-
- case 9: /* top right landscape */
- left = paper_height - width;
- bottom = paper_width - height;
- break;
-
- case 10: /* bottom right landscape */
- left = paper_height - width;
- bottom = 0.0;
- break;
-
- case 11: /* bottom left landscape */
- left = 0.0;
- bottom = 0.0;
- break;
-
- case 12: /* center landscape */
- left = paper_height / 2.0 - width / 2.0;
- bottom = paper_width / 2.0 - height / 2.0;
- break;
- }
-
-
- if (paper_orientation >= 8) /* rotate with 90 degrees - landscape mode */
- {
- degree = 90;
- position_left = left + paper_bottom_margin;
- position_bottom = bottom - paper_width - paper_left_margin;
- box_left = paper_width - paper_left_margin - bottom - height;
- box_bottom = left + paper_bottom_margin;
- box_right = box_left + ceil(height);
- box_top = box_bottom + ceil(width);
- }
- else /* do not rotate, portrait mode */
- {
- degree = 0;
- position_left = left + paper_left_margin;
- position_bottom = bottom + paper_bottom_margin;
- box_left = left + paper_left_margin;
- box_bottom = bottom + paper_bottom_margin;
- box_right = box_left + ceil(width);
- box_top = box_bottom + ceil(height);
- }
-
- depth = image_info->depth;
-
- if (depth > 8)
- {
- depth = 8;
- }
-
- fprintf(outfile, "\n");
- fprintf(outfile, "%%%%Page: %d %d\n", page, page);
- fprintf(outfile, "%%%%PageBoundingBox: %d %d %d %d\n", box_left, box_bottom, box_right, box_top);
-
- if (depth == 1)
- {
- fprintf(outfile, "/grays %d string def\n", image_info->image_width);
- fprintf(outfile, "/npixels 0 def\n");
- fprintf(outfile, "/rgbindx 0 def\n");
- }
-
- fprintf(outfile, "%d rotate\n", degree);
- fprintf(outfile, "%d %d translate\n", position_left, position_bottom);
- fprintf(outfile, "%f %f scale\n", width, height);
- fprintf(outfile, "%d %d %d\n", image_info->image_width, image_info->image_height, depth);
- fprintf(outfile, "[%d %d %d %d %d %d]\n", image_info->image_width, 0, 0, -image_info->image_height, 0, image_info->image_height);
- fprintf(outfile, "currentfile\n");
- fprintf(outfile, "/ASCII85Decode filter\n");
-#ifdef HAVE_LIBZ
- if (flatdecode)
- {
- fprintf(outfile, "/FlateDecode filter\n");
- }
-#endif
-
- if (image_info->colors == 3) /* what about RGBA here ? */
- {
- fprintf(outfile, "false 3 colorimage\n");
- fprintf(outfile, "\n");
- }
- else
- {
- fprintf(outfile, "image\n");
- fprintf(outfile, "\n");
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void xsane_save_ps_create_page_trailer(FILE *outfile)
-{
- fprintf(outfile, "\n");
- fprintf(outfile, "showpage\n");
- fprintf(outfile, "%%%%PageTrailer\n");
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_LIBZ
-/* Utility function for the PostScript output */
-static int xsane_write_compressed_a85_flatdecode(FILE *outfile, unsigned char *line, int len, int finish)
-{
- static unsigned char *cbuf = NULL;
- static int cbuflen = 0;
- static int linelen = 0;
- int i, j;
- int outlen;
- static int init = 0;
- static z_stream s;
- int ret;
- int flush;
- static int a85count = 0;
- static guint32 a85tuple = 0;
- static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0};
- static int count = 0;
-
- DBG(DBG_proc, "xsane_write_compressed_a85_flatdecode\n");
-
- if (linelen != len)
- {
- linelen = len;
- if (cbuf != NULL)
- {
- free(cbuf);
- }
- /* buffer length = length + 0.1 * length + 12 (mandatory) */
- cbuflen = len + len / 10 + 12;
- cbuf = malloc(cbuflen);
- }
-
- if (cbuf == NULL)
- {
- DBG(DBG_error, "cbuf allocation failed\n");
- return 1;
- }
-
- if (!init)
- {
- s.zalloc = Z_NULL;
- s.zfree = Z_NULL;
- s.opaque = Z_NULL;
-
- ret = deflateInit(&s, Z_DEFAULT_COMPRESSION);
-
- if (ret != Z_OK)
- {
- DBG(DBG_error, "deflateInit failed\n");
- free(cbuf);
- return 1;
- }
-
- init = 1;
- }
-
- s.avail_in = len;
- s.next_in = line;
-
- do
- {
- s.avail_out = cbuflen;
- s.next_out = cbuf;
-
- flush = (finish) ? Z_FINISH : Z_NO_FLUSH;
-
- ret = deflate(&s, flush);
-
- if (ret == Z_STREAM_ERROR)
- {
- DBG(DBG_error, "deflate failed\n");
- free(cbuf);
- return 1;
- }
-
- outlen = cbuflen - s.avail_out;
-
- /* ASCII85 (base 85) encoding */
- for (i = 0; i < outlen; i++)
- {
- switch (a85count)
- {
- case 0:
- a85tuple |= (cbuf[i] << 24);
- a85count++;
- break;
-
- case 1:
- a85tuple |= (cbuf[i] << 16);
- a85count++;
- break;
-
- case 2:
- a85tuple |= (cbuf[i] << 8);
- a85count++;
- break;
-
- case 3:
- a85tuple |= (cbuf[i] << 0);
-
- if (count == 40)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
-
- if (a85tuple == 0)
- {
- fprintf(outfile, "z");
- count++;
- }
- else
- {
- /* The ASCII chars must be written in reverse order, hence -> a85block[4-j] */
- for (j = 0; j < 5; j++)
- {
- a85block[4-j] = a85tuple % 85 + '!';
- a85tuple /= 85;
- }
-
- for (j = 0; j < 5; j++)
- {
- fprintf(outfile, "%c", a85block[j]);
- count++;
- if (count == 40)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
- }
- }
-
- a85count = 0;
- a85tuple = 0;
- break;
-
- default:
- break;
- }
- }
- } while (s.avail_out == 0);
-
- if (finish)
- {
- DBG(DBG_info, "finish\n");
- if (a85count > 0)
- {
- a85count++;
- for (j = 0; j <= a85count; j++)
- {
- a85block[j] = a85tuple % 85 + '!';
- a85tuple /= 85;
- }
- /* Reverse order */
- for (j--; j > 0; j--)
- {
- if (count == 40)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
- fprintf(outfile, "%c", a85block[j]);
- count++;
- }
- }
-
- /* ASCII85 EOD marker + newline*/
- if (count + 2 > 40)
- {
- fprintf(outfile, "\n");
- }
- fprintf(outfile, "~>\n");
- deflateEnd(&s);
- free(cbuf);
- cbuf = NULL;
- init = 0;
- a85tuple = 0;
- a85count = 0;
- cbuflen = 0;
- linelen = 0;
- count = 0;
- }
-
- return 0;
-}
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* Utility function for the PostScript output */
-static int xsane_write_compressed_a85(FILE *outfile, unsigned char *line, int len, int finish)
-{
- static unsigned char *cbuf = NULL;
- static int cbuflen = 0;
- static int linelen = 0;
- int i, j;
- int outlen;
- static int a85count = 0;
- static guint32 a85tuple = 0;
- static unsigned char a85block[6] = {0, 0, 0, 0, 0, 0};
- static int count = 0;
-
- DBG(DBG_proc, "xsane_write_compressed_a85\n");
-
- cbuf = line;
- outlen = len;
-
- /* ASCII85 (base 85) encoding */
- for (i = 0; i < outlen; i++)
- {
- switch (a85count)
- {
- case 0:
- a85tuple |= (cbuf[i] << 24);
- a85count++;
- break;
-
- case 1:
- a85tuple |= (cbuf[i] << 16);
- a85count++;
- break;
-
- case 2:
- a85tuple |= (cbuf[i] << 8);
- a85count++;
- break;
-
- case 3:
- a85tuple |= (cbuf[i] << 0);
-
- if (count == 40)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
-
- if (a85tuple == 0)
- {
- fprintf(outfile, "z");
- count++;
- }
- else
- {
- /* The ASCII chars must be written in reverse order, hence -> a85block[4-j] */
- for (j = 0; j < 5; j++)
- {
- a85block[4-j] = a85tuple % 85 + '!';
- a85tuple /= 85;
- }
-
- for (j = 0; j < 5; j++)
- {
- fprintf(outfile, "%c", a85block[j]);
- count++;
- if (count == 40)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
- }
- }
-
- a85count = 0;
- a85tuple = 0;
- break;
-
- default:
- break;
- }
- }
-
- if (finish)
- {
- DBG(DBG_info, "finish\n");
- if (a85count > 0)
- {
- a85count++;
- for (j = 0; j <= a85count; j++)
- {
- a85block[j] = a85tuple % 85 + '!';
- a85tuple /= 85;
- }
- /* Reverse order */
- for (j--; j > 0; j--)
- {
- if (count == 40)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
- fprintf(outfile, "%c", a85block[j]);
- count++;
- }
- }
-
- /* ASCII85 EOD marker + newline*/
- if (count + 2 > 40)
- {
- fprintf(outfile, "\n");
- }
- fprintf(outfile, "~>\n");
- a85tuple = 0;
- a85count = 0;
- cbuflen = 0;
- linelen = 0;
- count = 0;
- }
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_ps_pdf_bw(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x, y;
- int bytes_per_line = (image_info->image_width+7)/8;
- int ret;
- unsigned char *line;
-
- DBG(DBG_proc, "xsane_save_ps_pdf_bw\n");
-
- *cancel_save = 0;
-
- line = (unsigned char *) malloc(bytes_per_line);
-
- if (line == NULL)
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE);
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- return (*cancel_save);
- }
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = 0; x < bytes_per_line; x++)
- {
- line[x] = fgetc(imagefile) ^ 255;
- }
-
-#ifdef HAVE_LIBZ
- if (flatdecode)
- {
- ret = xsane_write_compressed_a85_flatdecode(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
- }
- else
-#endif
- {
- ret = xsane_write_compressed_a85(outfile, line, bytes_per_line, (y == image_info->image_height - 1));
- }
-
- if ((ret != 0) || (ferror(outfile)))
- {
- char buf[255];
-
- if (ret == 0)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- }
- else
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_ZLIB);
- }
-
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
-
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- free(line);
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_ps_pdf_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x, y;
- int ret;
- unsigned char *line;
-
- DBG(DBG_proc, "xsane_save_ps_pdf_gray\n");
-
- *cancel_save = 0;
-
- line = (unsigned char *) malloc(image_info->image_width);
-
- if (line == NULL)
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE);
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- return (*cancel_save);
- }
-
- for (y = 0; y < image_info->image_height; y++)
- {
- if (image_info->depth > 8) /* reduce 16 bit images */
- {
- guint16 val;
-
- for (x = 0; x < image_info->image_width; x++)
- {
- fread(&val, 2, 1, imagefile);
- line[x] = val/256;
- }
- }
- else /* 8 bits/sample */
- {
- for (x = 0; x < image_info->image_width; x++)
- {
- line[x] = fgetc(imagefile);
- }
- }
-
-#ifdef HAVE_LIBZ
- if (flatdecode)
- {
- ret = xsane_write_compressed_a85_flatdecode(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
- }
- else
-#endif
- {
- ret = xsane_write_compressed_a85(outfile, line, image_info->image_width, (y == image_info->image_height - 1));
- }
-
- if ((ret != 0) || (ferror(outfile)))
- {
- char buf[255];
-
- if (ret == 0)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- }
- else
- {
- snprintf(buf, sizeof(buf), "%s zlib error or memory allocation problem", ERR_DURING_SAVE);
- }
-
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
-
- break;
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- free(line);
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_ps_pdf_color(FILE *outfile, FILE *imagefile, Image_info *image_info, int flatdecode, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x, y;
- int ret;
- unsigned char *line, *linep;
-
- DBG(DBG_proc, "xsane_save_ps_pdf_color\n");
-
- *cancel_save = 0;
-
- line = (unsigned char *) malloc(image_info->image_width * 3);
-
- if (line == NULL)
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s malloc failed", ERR_DURING_SAVE);
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- return (*cancel_save);
- }
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- linep = line;
-
- if (image_info->depth > 8) /* reduce 16 bit images */
- {
- guint16 val;
-
- for (x = 0; x < image_info->image_width; x++)
- {
- fread(&val, 2, 1, imagefile);
- *linep++ = val/256;
- fread(&val, 2, 1, imagefile);
- *linep++ = val/256;
- fread(&val, 2, 1, imagefile);
- *linep++ = val/256;
- }
- }
- else /* 8 bits/sample */
- {
- for (x = 0; x < image_info->image_width; x++)
- {
- *linep++ = fgetc(imagefile);
- *linep++ = fgetc(imagefile);
- *linep++ = fgetc(imagefile);
- }
- }
-
-#ifdef HAVE_LIBZ
- if (flatdecode)
- {
- ret = xsane_write_compressed_a85_flatdecode(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1));
- }
- else
-#endif
- {
- ret = xsane_write_compressed_a85(outfile, line, (image_info->image_width * 3), (y == image_info->image_height - 1));
- }
-
- if ((ret != 0) || (ferror(outfile)))
- {
- char buf[255];
-
- if (ret == 0)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- }
- else
- {
- snprintf(buf, sizeof(buf), "%s zlib error or memory allocation problem", ERR_DURING_SAVE);
- }
-
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
-
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- free(line);
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_ps_page(FILE *outfile, int page,
- FILE *imagefile, Image_info *image_info, float width, float height,
- int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation,
- int flatdecode,
- GtkProgressBar *progress_bar, int *cancel_save)
-{
- DBG(DBG_proc, "xsane_save_ps_page\n");
-
- xsane_save_ps_create_page_header(outfile, page,
- image_info, width, height,
- paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation,
- flatdecode,
- progress_bar);
-
- if (image_info->colors == 1) /* lineart, halftone, grayscale */
- {
- if (image_info->depth == 1) /* lineart, halftone */
- {
- xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
- }
- else /* grayscale */
- {
- xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
- }
- }
- else /* color RGB */
- {
- xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
- }
-
- xsane_save_ps_create_page_trailer(outfile);
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height,
- int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation,
- int flatdecode,
- GtkProgressBar *progress_bar, int *cancel_save)
-{
- DBG(DBG_proc, "xsane_save_ps\n");
-
- *cancel_save = 0;
-
- xsane_save_ps_create_document_header(outfile, 1 /* pages */, flatdecode);
-
- xsane_save_ps_page(outfile, 1 /* page */,
- imagefile, image_info, width, height,
- paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation,
- flatdecode,
- progress_bar, cancel_save);
-
- xsane_save_ps_create_document_trailer(outfile, 0 /* we defined pages at beginning */);
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* The pdf_xref struct holds byte offsets from the beginning of the PDF
- * file to each object of the PDF file -- used to build the xref table
- */
-struct pdf_xref
-{
- unsigned long obj5; /* obj 5 0 */
- unsigned long obj6; /* obj 6 0 */
- unsigned long obj7; /* obj 7 0 */
- unsigned long xref; /* xref table */
- unsigned long slen; /* length of image stream */
- unsigned long slenp; /* position of image stream length */
-};
-
-static void xsane_save_pdf_create_header(FILE *outfile, Image_info *image_info,
- float width, float height,
- int paper_left_margin, int paper_bottom_margin,
- int paper_width, int paper_height,
- int paper_orientation, int flatdecode,
- GtkProgressBar *progress_bar, struct pdf_xref *xref)
-{
- int position_left, position_bottom, box_left, box_bottom, box_right, box_top, depth;
- int left, bottom;
- float rad;
-
- DBG(DBG_proc, "xsane_save_pdf_create_header\n");
-
- switch (paper_orientation)
- {
- default:
- case 0: /* top left portrait */
- left = 0.0;
- bottom = paper_height - height;
- break;
-
- case 1: /* top right portrait */
- left = paper_width - width;
- bottom = paper_height - height;
- break;
-
- case 2: /* bottom right portrait */
- left = paper_width - width;
- bottom = 0.0;
- break;
-
- case 3: /* bottom left portrait */
- left = 0.0;
- bottom = 0.0;
- break;
-
- case 4: /* center portrait */
- left = paper_width / 2.0 - width / 2.0;
- bottom = paper_height / 2.0 - height / 2.0;
- break;
-
-
- case 8: /* top left landscape */
- left = 0.0;
- bottom = paper_width - height;
- break;
-
- case 9: /* top right landscape */
- left = paper_height - width;
- bottom = paper_width - height;
- break;
-
- case 10: /* bottom right landscape */
- left = paper_height - width;
- bottom = 0.0;
- break;
-
- case 11: /* bottom left landscape */
- left = 0.0;
- bottom = 0.0;
- break;
-
- case 12: /* center landscape */
- left = paper_height / 2.0 - width / 2.0;
- bottom = paper_width / 2.0 - height / 2.0;
- break;
- }
-
-
- if (paper_orientation >= 8) /* rotate with 90 degrees - landscape mode */
- {
- rad = -M_PI_2; /* pi / 2 */
- position_left = left + paper_bottom_margin;
- position_bottom = bottom - paper_width - paper_left_margin;
- box_left = paper_width - paper_left_margin - bottom - height;
- box_bottom = left + paper_bottom_margin;
- box_right = box_left + ceil(height);
- box_top = box_bottom + ceil(width);
- }
- else /* do not rotate, portrait mode */
- {
- rad = 0;
- position_left = left + paper_left_margin;
- position_bottom = bottom + paper_bottom_margin;
- box_left = left + paper_left_margin;
- box_bottom = bottom + paper_bottom_margin;
- box_right = box_left + ceil(width);
- box_top = box_bottom + ceil(height);
- }
-
- depth = image_info->depth;
-
- if (depth > 8)
- {
- depth = 8;
- }
-
- fprintf(outfile, "%%PDF-1.4\n");
- fprintf(outfile, "\n");
- fprintf(outfile, "1 0 obj\n");
- fprintf(outfile, " << /Type /Catalog\n");
- fprintf(outfile, " /Outlines 2 0 R\n");
- fprintf(outfile, " /Pages 3 0 R\n");
- fprintf(outfile, " >>\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
- fprintf(outfile, "2 0 obj\n");
- fprintf(outfile, " << /Type /Outlines\n");
- fprintf(outfile, " /Count 0\n");
- fprintf(outfile, " >>\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
- fprintf(outfile, "3 0 obj\n");
- fprintf(outfile, " << /Type /Pages\n");
- fprintf(outfile, " /Kids [4 0 R]\n");
- fprintf(outfile, " /Count 1\n");
- fprintf(outfile, " >>\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
- fprintf(outfile, "4 0 obj\n");
- fprintf(outfile, " << /Type /Page\n");
- fprintf(outfile, " /Parent 3 0 R\n");
- fprintf(outfile, " /MediaBox [%d %d %d %d]\n", box_left, box_bottom, box_right, box_top);
- fprintf(outfile, " /Contents 5 0 R\n");
- fprintf(outfile, " /Resources << /ProcSet 6 0 R >>\n");
- fprintf(outfile, " >>\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
-
- /* Offset of object 5, for xref */
- xref->obj5 = ftell(outfile);
-
- fprintf(outfile, "5 0 obj\n");
- fprintf(outfile, " << /Length >>\n");
-
- /* Position of the stream length, to be written later on */
- xref->slenp = ftell(outfile) - 15;
-
- fprintf(outfile, "stream\n");
-
- /* Start of the stream data */
- xref->slen = ftell(outfile);
-
- fprintf(outfile, "q\n");
- fprintf(outfile, "1 0 0 1 %d %d cm\n", position_left, position_bottom); /* translate */
- fprintf(outfile, "%f %f -%f %f 0 0 cm\n", cos(rad), sin(rad), sin(rad), cos(rad)); /* rotate */
- fprintf(outfile, "%f 0 0 %f 0 0 cm\n", width, height); /* scale */
- fprintf(outfile, "BI\n");
- fprintf(outfile, " /W %d\n", image_info->image_width);
- fprintf(outfile, " /H %d\n", image_info->image_height);
-
- if (image_info->colors == 3) /* what about RGBA here ? */
- {
- fprintf(outfile, " /CS /RGB\n");
- fprintf(outfile, " /BPC %d\n", depth);
- }
- else if (image_info->depth == 1) /* BW */
- {
- fprintf(outfile, " /CS /G\n");
- fprintf(outfile, " /BPC 1\n");
- }
- else /* gray */
- {
- fprintf(outfile, " /CS /G\n");
- fprintf(outfile, " /BPC 8\n");
- }
-
-#ifdef HAVE_LIBZ
- if (flatdecode)
- {
- fprintf(outfile, " /F [/A85 /FlateDecode]\n");
- }
- else
- {
- fprintf(outfile, " /F /A85\n");
- }
-#else
- fprintf(outfile, " /F /A85\n");
-#endif
- fprintf(outfile, "ID\n");
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info, float width, float height,
- int paper_left_margin, int paper_bottom_margin, int paperheight, int paperwidth, int paper_orientation,
- int flatdecode,
- GtkProgressBar *progress_bar, int *cancel_save)
-{
- struct tm *t;
- time_t tt;
- struct pdf_xref xref;
-
- DBG(DBG_proc, "xsane_save_pdf\n");
-
- *cancel_save = 0;
-
- xsane_save_pdf_create_header(outfile, image_info, width, height,
- paper_left_margin, paper_bottom_margin, paperheight, paperwidth, paper_orientation,
- flatdecode,
- progress_bar, &xref);
-
- if (image_info->colors == 1) /* lineart, halftone, grayscale */
- {
- if (image_info->depth == 1) /* lineart, halftone */
- {
- xsane_save_ps_pdf_bw(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
- }
- else /* grayscale */
- {
- xsane_save_ps_pdf_gray(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
- }
- }
- else /* color RGB */
- {
- xsane_save_ps_pdf_color(outfile, imagefile, image_info, flatdecode, progress_bar, cancel_save);
- }
-
- /* PDF trailer */
- fprintf(outfile, "EI\n");
- fprintf(outfile, "Q\n");
-
- /* Go back and write the length of the stream */
- xref.slen = ftell(outfile) - xref.slen - 1;
- fseek(outfile, xref.slenp, SEEK_SET);
- fprintf(outfile, "%lu", xref.slen);
- fseek(outfile, 0L, SEEK_END);
-
- fprintf(outfile, "endstream\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
-
- /* Offset of object 6, for xref */
- xref.obj6 = ftell(outfile);
-
- fprintf(outfile, "6 0 obj\n");
- fprintf(outfile, " [/PDF]\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
-
- /* Offset of object 7, for xref */
- xref.obj7 = ftell(outfile);
-
- fprintf(outfile, "7 0 obj\n");
- fprintf(outfile, " << /Title (XSane scanned image)\n");
- fprintf(outfile, " /Creator (XSane version %s (sane %d.%d) - by Oliver Rauch)\n",
- VERSION,
- SANE_VERSION_MAJOR(xsane.sane_backend_versioncode),
- SANE_VERSION_MINOR(xsane.sane_backend_versioncode));
- fprintf(outfile, " /Producer (XSane %s)\n", VERSION);
-
- tt = time(NULL);
- t = gmtime(&tt);
-
- fprintf(outfile, " /CreationDate (D:%04d%02d%02d%02d%02d%02d+00'00')\n",
- 1900 + t->tm_year, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
- fprintf(outfile, " >>\n");
- fprintf(outfile, "endobj\n");
- fprintf(outfile, "\n");
-
- /* Offset of xref, for startxref below */
- xref.xref = ftell(outfile);
-
- fprintf(outfile, "xref\n");
- fprintf(outfile, "0 8\n");
- fprintf(outfile, "0000000000 65535 f \n");
- fprintf(outfile, "0000000010 00000 n \n");
- fprintf(outfile, "0000000094 00000 n \n");
- fprintf(outfile, "0000000153 00000 n \n");
- fprintf(outfile, "0000000229 00000 n \n");
- fprintf(outfile, "%010lu 00000 n \n", xref.obj5);
- fprintf(outfile, "%010lu 00000 n \n", xref.obj6);
- fprintf(outfile, "%010lu 00000 n \n", xref.obj7);
- fprintf(outfile, "\n");
- fprintf(outfile, "trailer\n");
- fprintf(outfile, " << /Size 8\n");
- fprintf(outfile, " /Root 1 0 R\n");
- fprintf(outfile, " /Info 7 0 R\n");
- fprintf(outfile, " >>\n");
- fprintf(outfile, "startxref\n");
- fprintf(outfile, "%lu\n", xref.xref);
- fprintf(outfile, "%%%%EOF\n");
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-#ifdef HAVE_LIBJPEG
-
-typedef struct
-{
- struct jpeg_error_mgr pub;/* "public" fields */
- int *cancel_save;
-} xsane_jpeg_error_mgr;
-
-typedef xsane_jpeg_error_mgr *xsane_jpeg_error_mgr_ptr;
-
-static void xsane_jpeg_error_exit(j_common_ptr cinfo)
-{
- char buf[256];
-
- /* cinfo->err points to a xsane_jpeg_error_mgr struct */
- xsane_jpeg_error_mgr_ptr xsane_jpeg_error_mgr_data = (xsane_jpeg_error_mgr_ptr) cinfo->err;
-
-
- if (!*xsane_jpeg_error_mgr_data->cancel_save)
- {
- /* output original error message */
- (*cinfo->err->output_message) (cinfo);
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBJPEG);
- xsane_back_gtk_error(buf, TRUE);
- }
-
- *xsane_jpeg_error_mgr_data->cancel_save = 1;
-}
-
-int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save)
-{
- unsigned char *data;
- char buf[256];
- int components = 1;
- int x,y;
- int bytespp = 1;
- struct jpeg_compress_struct cinfo;
- xsane_jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1];
-
- DBG(DBG_proc, "xsane_save_jpeg\n");
-
- *cancel_save = 0;
-
- if (image_info->colors == 3)
- {
- components = 3;
- }
-
- if (image_info->depth > 8)
- {
- bytespp = 2;
- }
-
- data = malloc(image_info->image_width * components * bytespp);
-
- if (!data)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- cinfo.err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = xsane_jpeg_error_exit;
- jerr.cancel_save = cancel_save;
-
- jpeg_create_compress(&cinfo);
- jpeg_stdio_dest(&cinfo, outfile);
- cinfo.image_width = image_info->image_width;
- cinfo.image_height = image_info->image_height;
- cinfo.input_components = components;
- if (image_info->colors == 3)
- {
- cinfo.in_color_space = JCS_RGB;
- }
- else
- {
- cinfo.in_color_space = JCS_GRAYSCALE;
- }
- jpeg_set_defaults(&cinfo);
-
- jpeg_set_quality(&cinfo, quality, TRUE);
-
- cinfo.density_unit = 1; /* dpi */
- cinfo.X_density = image_info->resolution_x;
- cinfo.Y_density = image_info->resolution_y;
-
- jpeg_start_compress(&cinfo, TRUE);
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- if (image_info->depth == 1)
- {
- int byte = 0;
- int mask = 128;
-
- for (x = 0; x < image_info->image_width; x++)
- {
-
- if ( (x % 8) == 0)
- {
- byte = fgetc(imagefile);
- mask = 128;
- }
-
- if (byte & mask)
- {
- data[x] = 0;
- }
- else
- {
- data[x] = 255;
- }
- mask >>= 1;
- }
- }
- else if (image_info->depth > 8) /* jpeg does not support 16 bits/sample, so we reduce it at first */
- {
- guint16 *data16 = (guint16 *) data;
- fread(data, components * 2, image_info->image_width, imagefile);
- for (x = 0; x < image_info->image_width * components; x++)
- {
- data[x] = data16[x] / 256;
- }
-
- }
- else /* 8 bits/sample */
- {
- fread(data, components, image_info->image_width, imagefile);
- }
-
- row_pointer[0] = data;
- jpeg_write_scanlines(&cinfo, row_pointer, 1);
-
- if (*cancel_save)
- {
- cinfo.image_height = y; /* correct image height */
- break;
- }
- }
-
- jpeg_finish_compress(&cinfo);
- free(data);
-
- return (*cancel_save);
-}
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_LIBTIFF
-/* pages = 0 => single page tiff, page = 0 */
-/* pages > 0 => page = [1 .. pages] */
-int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Image_info *image_info, int quality,
- GtkProgressBar *progress_bar, int *cancel_save)
-{
- char *data;
- char buf[256];
- int y, w;
- int components;
- int compression;
- int bytes;
- struct tm *ptm;
- time_t now;
-
- DBG(DBG_proc, "xsane_save_tiff_page(%d/%d\n", page, pages);
-
- *cancel_save = 0;
-
- if (image_info->depth == 1)
- {
- compression = preferences.tiff_compression1_nr;
- }
- else if (image_info->depth == 8)
- {
- compression = preferences.tiff_compression8_nr;
- }
- else
- {
- compression = preferences.tiff_compression16_nr;
- }
-
-
- if (image_info->colors == 3)
- {
- components = 3;
- }
- else
- {
- components = 1;
- }
-
- if (image_info->depth <= 8)
- {
- bytes = 1;
- }
- else
- {
- bytes = 2;
- }
-
- data = (char *)_TIFFmalloc(image_info->image_width * components * bytes);
-
- if (!data)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- TIFFSetField(tiffile, TIFFTAG_IMAGEWIDTH, image_info->image_width);
- TIFFSetField(tiffile, TIFFTAG_IMAGELENGTH, image_info->image_height);
- TIFFSetField(tiffile, TIFFTAG_BITSPERSAMPLE, image_info->depth);
- TIFFSetField(tiffile, TIFFTAG_SAMPLESPERPIXEL, components);
- TIFFSetField(tiffile, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
- TIFFSetField(tiffile, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
- TIFFSetField(tiffile, TIFFTAG_COMPRESSION, compression);
- TIFFSetField(tiffile, TIFFTAG_SOFTWARE, "xsane");
-
- time(&now);
- ptm = localtime(&now);
- sprintf(buf, "%04d:%02d:%02d %02d:%02d:%02d", 1900+ptm->tm_year, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
- TIFFSetField(tiffile, TIFFTAG_DATETIME, buf);
-
- if (image_info->resolution_x > 0.0)
- {
- TIFFSetField(tiffile, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
- TIFFSetField(tiffile, TIFFTAG_XRESOLUTION, image_info->resolution_x);
- TIFFSetField(tiffile, TIFFTAG_YRESOLUTION, image_info->resolution_y);
- }
-
- if (compression == COMPRESSION_JPEG)
- {
- TIFFSetField(tiffile, TIFFTAG_JPEGQUALITY, quality);
- TIFFSetField(tiffile, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); /* should be default, but to be sure */
- }
-
- if (image_info->colors == 3)
- {
- TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
- }
- else
- {
- if (image_info->depth == 1) /* lineart */
- {
- TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
- }
- else /* grayscale */
- {
- TIFFSetField(tiffile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
- }
- }
-
- TIFFSetField(tiffile, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tiffile, -1));
-
- if (pages)
- {
- TIFFSetField(tiffile, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
- TIFFSetField(tiffile, TIFFTAG_PAGENUMBER, page, pages);
- }
-
- w = TIFFScanlineSize(tiffile);
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- fread(data, 1, w, imagefile);
-
- if (TIFFWriteScanline(tiffile, data, y, 0) != 1)
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s", ERR_DURING_SAVE);
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- if (pages)
- {
- TIFFWriteDirectory(tiffile);
- }
-
- _TIFFfree(data);
- return (*cancel_save);
-}
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_LIBPNG
-#ifdef HAVE_LIBZ
-int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save)
-{
- png_structp png_ptr;
- png_infop png_info_ptr;
- png_bytep row_ptr;
- png_color_8 sig_bit;
- unsigned char *data;
- char buf[256];
- int colortype, components, byte_width;
- int y;
-
- DBG(DBG_proc, "xsane_save_png\n");
-
- *cancel_save = 0;
-
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- if (!png_ptr)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- png_info_ptr = png_create_info_struct(png_ptr);
- if (!png_info_ptr)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBTIFF);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- if (setjmp(png_ptr->jmpbuf))
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
- xsane_back_gtk_error(buf, TRUE);
- png_destroy_write_struct(&png_ptr, (png_infopp) 0);
- return -1; /* error */
- }
-
- byte_width = image_info->image_width;
-
- if (image_info->colors == 4) /* RGBA */
- {
- components = 4;
- colortype = PNG_COLOR_TYPE_RGB_ALPHA;
- }
- else if (image_info->colors == 3) /* RGB */
- {
- components = 3;
- colortype = PNG_COLOR_TYPE_RGB;
- }
- else /* gray or black/white */
- {
- components = 1;
- colortype = PNG_COLOR_TYPE_GRAY;
- }
-
- png_init_io(png_ptr, outfile);
- png_set_compression_level(png_ptr, compression);
- png_set_IHDR(png_ptr, png_info_ptr, image_info->image_width, image_info->image_height, image_info->depth,
- colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- if (image_info->colors >=3)
- {
- sig_bit.red = image_info->depth;
- sig_bit.green = image_info->depth;
- sig_bit.blue = image_info->depth;
-
- if (image_info->colors == 4)
- {
- sig_bit.alpha = image_info->depth;
- }
-
- }
- else
- {
- sig_bit.gray = image_info->depth;
-
- if (image_info->depth == 1)
- {
- byte_width = (image_info->image_width+7)/8;
- png_set_invert_mono(png_ptr);
- }
- }
-
- png_set_sBIT(png_ptr, png_info_ptr, &sig_bit);
-#if defined(PNG_pHYs_SUPPORTED)
- png_set_pHYs(png_ptr, png_info_ptr,
- image_info->resolution_x * 100.0 / 2.54,
- image_info->resolution_y * 100.0 / 2.54, PNG_RESOLUTION_METER);
-#endif
- png_write_info(png_ptr, png_info_ptr);
- png_set_shift(png_ptr, &sig_bit);
-
- data = malloc(image_info->image_width * components);
-
- if (!data)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
- xsane_back_gtk_error(buf, TRUE);
- png_destroy_write_struct(&png_ptr, (png_infopp) 0);
- return -1; /* error */
- }
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- fread(data, components, byte_width, imagefile);
-
- row_ptr = data;
- png_write_rows(png_ptr, &row_ptr, 1); /* errors are caught by test sor setjmp(...) */
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- free(data);
- png_write_end(png_ptr, png_info_ptr);
- png_destroy_write_struct(&png_ptr, (png_infopp) 0);
-
- return (*cancel_save);
-}
-#endif
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_LIBPNG
-#ifdef HAVE_LIBZ
-int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save)
-{
- png_structp png_ptr;
- png_infop png_info_ptr;
- png_bytep row_ptr;
- png_color_8 sig_bit; /* should be 16, but then I get a warning about wrong type */
- unsigned char *data;
- char buf[256];
- int colortype, components;
- int x,y;
- guint16 val;
-
- DBG(DBG_proc, "xsane_save_png16\n");
-
- *cancel_save = 0;
-
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- if (!png_ptr)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- png_info_ptr = png_create_info_struct(png_ptr);
- if (!png_info_ptr)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- if (setjmp(png_ptr->jmpbuf))
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_LIBPNG);
- xsane_back_gtk_error(buf, TRUE);
- png_destroy_write_struct(&png_ptr, (png_infopp) 0);
- return -1; /* error */
- }
-
- if (image_info->colors == 4) /* RGBA */
- {
- components = 4;
- colortype = PNG_COLOR_TYPE_RGB_ALPHA;
- }
- else if (image_info->colors == 3) /* RGB */
- {
- components = 3;
- colortype = PNG_COLOR_TYPE_RGB;
- }
- else /* gray or black/white */
- {
- components = 1;
- colortype = PNG_COLOR_TYPE_GRAY;
- }
-
- png_init_io(png_ptr, outfile);
- png_set_compression_level(png_ptr, compression);
- png_set_IHDR(png_ptr, png_info_ptr, image_info->image_width, image_info->image_height, 16,
- colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- sig_bit.red = image_info->depth;
- sig_bit.green = image_info->depth;
- sig_bit.blue = image_info->depth;
- sig_bit.alpha = image_info->depth;
- sig_bit.gray = image_info->depth;
-
- png_set_sBIT(png_ptr, png_info_ptr, &sig_bit);
- png_write_info(png_ptr, png_info_ptr);
- png_set_shift(png_ptr, &sig_bit);
- png_set_packing(png_ptr);
-
- data = malloc(image_info->image_width * components * 2);
-
- if (!data)
- {
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, ERR_NO_MEM);
- xsane_back_gtk_error(buf, TRUE);
- png_destroy_write_struct(&png_ptr, (png_infopp) 0);
- return -1; /* error */
- }
-
- for (y = 0; y < image_info->image_height; y++)
- {
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- for (x = 0; x < image_info->image_width * components; x++) /* this must be changed in dependance of endianess */
- {
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- data[x*2+0] = val / 256; /* write data in network order (MSB first) */
- data[x*2+1] = val & 255;
- }
-
- row_ptr = data;
- png_write_rows(png_ptr, &row_ptr, 1);
- if (*cancel_save)
- {
- break;
- }
- }
-
- free(data);
- png_write_end(png_ptr, png_info_ptr);
- png_destroy_write_struct(&png_ptr, (png_infopp) 0);
-
- return (*cancel_save);
-}
-#endif
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_pnm_16_ascii_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x,y;
- guint16 val;
- int count = 0;
-
- DBG(DBG_proc, "xsane_save_pnm_16_ascii_gray\n");
-
- *cancel_save = 0;
-
- for (y = 0; y < image_info->image_height; y++)
- {
- for (x = 0; x < image_info->image_width; x++)
- {
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fprintf(outfile, "%d ", val);
-
- if (++count >= 10)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
- }
- fprintf(outfile, "\n");
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- count = 0;
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- if (*cancel_save)
- {
- break;
- }
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_pnm_16_ascii_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x,y;
- guint16 val;
- int count = 0;
-
- DBG(DBG_proc, "xsane_save_pnm_16_ascii_color\n");
-
- *cancel_save = 0;
-
- for (y = 0; y < image_info->image_height; y++)
- {
- for (x = 0; x < image_info->image_width; x++)
- {
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fprintf(outfile, "%d ", val);
-
- fread(&val, 2, 1, imagefile);
- fprintf(outfile, "%d ", val);
-
- fread(&val, 2, 1, imagefile);
- fprintf(outfile, "%d ", val);
-
- if (++count >= 3)
- {
- fprintf(outfile, "\n");
- count = 0;
- }
- }
- fprintf(outfile, "\n");
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- count = 0;
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_pnm_16_binary_gray(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x,y;
- guint16 val;
-
- DBG(DBG_proc, "xsane_save_pnm_16_binary_gray\n");
-
- *cancel_save = 0;
-
- for (y = 0; y < image_info->image_height; y++)
- {
- for (x = 0; x < image_info->image_width; x++)
- {
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_save_pnm_16_binary_color(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int x,y;
- guint16 val;
-
- DBG(DBG_proc, "xsane_save_pnm_16_binary_color\n");
-
- *cancel_save = 0;
-
- for (y = 0; y < image_info->image_height; y++)
- {
- for (x = 0; x < image_info->image_width; x++)
- {
- /* red */
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
-
- /* green */
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
-
- /* blue */
- fread(&val, 2, 1, imagefile); /* get data in machine order */
- fputc(val / 256, outfile); /* MSB fist */
- fputc(val & 255, outfile); /* LSB */
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info->image_height);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
-
- if (ferror(outfile))
- {
- char buf[255];
-
- snprintf(buf, sizeof(buf), "%s %s", ERR_DURING_SAVE, strerror(errno));
- DBG(DBG_error, "%s\n", buf);
- xsane_back_gtk_decision(ERR_HEADER_ERROR, (gchar **) error_xpm, buf, BUTTON_OK, NULL, TRUE /* wait */);
- *cancel_save = 1;
- break;
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save)
-{
- DBG(DBG_proc, "xsane_save_pnm_16\n");
-
- *cancel_save = 0;
-
- xsane_write_pnm_header(outfile, image_info, preferences.save_pnm16_as_ascii);
-
- if (image_info->colors > 1)
- {
- if (preferences.save_pnm16_as_ascii)
- {
- xsane_save_pnm_16_ascii_color(outfile, imagefile, image_info, progress_bar, cancel_save);
- }
- else
- {
- xsane_save_pnm_16_binary_color(outfile, imagefile, image_info, progress_bar, cancel_save);
- }
- }
- else
- {
- if (preferences.save_pnm16_as_ascii)
- {
- xsane_save_pnm_16_ascii_gray(outfile, imagefile, image_info, progress_bar, cancel_save);
- }
- else
- {
- xsane_save_pnm_16_binary_gray(outfile, imagefile, image_info, progress_bar, cancel_save);
- }
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* 0=ok, <0=error, 1=canceled */
-int xsane_save_image_as_lineart(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save)
-{
- FILE *outfile;
- FILE *infile;
- char buf[256];
- Image_info image_info;
-
- *cancel_save = 0;
-
- outfile = fopen(output_filename, "wb"); /* b = binary mode for win32 */
-
- if (outfile == 0)
- {
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, output_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
- return -2;
- }
-
- infile = fopen(input_filename, "rb"); /* read binary (b for win32) */
- if (infile == 0)
- {
- char buf[256];
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- fclose(outfile);
- remove(output_filename); /* remove already created output file */
- return -1;
- }
-
- xsane_read_pnm_header(infile, &image_info);
-
- xsane_save_grayscale_image_as_lineart(outfile, infile, &image_info, progress_bar, cancel_save);
-
- fclose(infile);
- fclose(outfile);
-
- if (*cancel_save) /* remove output file if saving has been canceled */
- {
- remove(output_filename);
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_save_image_as_text(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save)
-{
- char *arg[1000];
- char buf[256];
- int argnr;
- pid_t pid;
- int i;
- int pipefd[2]; /* for progress communication with gocr */
- FILE *ocr_progress = NULL;
-
- DBG(DBG_proc, "xsane_save_image_as_text\n");
-
- argnr = xsane_parse_options(preferences.ocr_command, arg);
-
- arg[argnr++] = strdup(preferences.ocr_inputfile_option);
- arg[argnr++] = strdup(input_filename);
-
- arg[argnr++] = strdup(preferences.ocr_outputfile_option);
- arg[argnr++] = strdup(output_filename);
-
- if (preferences.ocr_use_gui_pipe)
- {
- if (!pipe(pipefd)) /* success */
- {
- DBG(DBG_info, "xsane_save_image_as_text: created pipe for progress communication\n");
-
- arg[argnr++] = strdup(preferences.ocr_gui_outfd_option);
-
- snprintf(buf, sizeof(buf),"%d", pipefd[1]);
- arg[argnr++] = strdup(buf);
- }
- else
- {
- DBG(DBG_info, "xsane_save_image_as_text: could not create pipe for progress communication\n");
- pipefd[0] = 0;
- pipefd[1] = 0;
- }
- }
- else
- {
- DBG(DBG_info, "xsane_save_image_as_text: no pipe for progress communication requested\n");
- pipefd[0] = 0;
- pipefd[1] = 0;
- }
-
- arg[argnr] = 0;
-
-#ifndef HAVE_OS2_H
- pid = fork();
-
- if (pid == 0) /* new process */
- {
- FILE *ipc_file = NULL;
-
- if (xsane.ipc_pipefd[0]) /* did we create the progress pipe? */
- {
- close(xsane.ipc_pipefd[0]); /* close reading end of pipe */
- ipc_file = fdopen(xsane.ipc_pipefd[1], "w");
- }
-
- if (pipefd[0]) /* did we create the progress pipe? */
- {
- close(pipefd[0]); /* close reading end of pipe */
- }
-
- DBG(DBG_info, "trying to change user id for new subprocess:\n");
- DBG(DBG_info, "old effective uid = %d\n", (int) geteuid());
- setuid(getuid());
- DBG(DBG_info, "new effective uid = %d\n", (int) geteuid());
-
-
- execvp(arg[0], arg); /* does not return if successfully */
- DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command);
-
- /* send error message via IPC pipe to parent process */
- if (ipc_file)
- {
- fprintf(ipc_file, "%s %s:\n%s", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command, strerror(errno));
- fflush(ipc_file); /* make sure message is displayed */
- fclose(ipc_file);
- }
-
- _exit(0); /* do not use exit() here! otherwise gtk gets in trouble */
- }
-
-#else
- pid = spawnvp(P_NOWAIT, arg[0], arg);
- if (pid == -1)
- {
- DBG(DBG_error, "%s %s\n", ERR_FAILED_EXEC_OCR_CMD, preferences.ocr_command);
- }
-#endif
-
- if (pipefd[1])
- {
- close(pipefd[1]); /* close writing end of pipe */
- ocr_progress = fdopen(pipefd[0], "r"); /* open reading end of pipe as file */
- }
-
- for (i=0; i<argnr; i++)
- {
- free(arg[i]);
- }
-
- if (ocr_progress) /* pipe available */
- {
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (!feof(ocr_progress))
- {
- int progress, subprogress;
- float fprogress;
-
- fgets(buf, sizeof(buf), ocr_progress);
-
- if (!strncmp(preferences.ocr_progress_keyword, buf, strlen(preferences.ocr_progress_keyword)))
- {
- sscanf(buf + strlen(preferences.ocr_progress_keyword), "%d %d", &progress, &subprogress);
-
- snprintf(buf, sizeof(buf), "%s (%d:%d)", PROGRESS_OCR, progress, subprogress);
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf);
-
- fprogress = progress / 100.0;
-
- if (fprogress < 0.0)
- {
- fprogress = 0.0;
- }
-
- if (fprogress > 11.0)
- {
- fprogress = 1.0;
- }
-
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), fprogress);
- }
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), "");
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
- }
- else /* no pipe available */
- {
- while (pid)
- {
- int status = 0;
- pid_t pid_status = waitpid(pid, &status, WNOHANG);
-
- if (pid == pid_status)
- {
- pid = 0; /* ok, child process has terminated */
- }
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
- }
-
- if (pipefd[0])
- {
- fclose(ocr_progress); /* close reading end of pipe */
- }
-
- return (*cancel_save);
-}
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* save image in destination file format. lineart images that are stored as grayscale image are reduced to lineart! */
-int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, GtkProgressBar *progress_bar, int *cancel_save)
-{
- FILE *outfile;
- FILE *infile;
- char buf[256];
- Image_info image_info;
- char lineart_filename[PATH_MAX];
- int remove_input_file = FALSE;
-
- DBG(DBG_proc, "xsane_save_image_as(output_file=%s, input_file=%s, type=%d)\n", output_filename, input_filename, output_format);
-
- *cancel_save = 0;
-
- infile = fopen(input_filename, "rb"); /* read binary (b for win32) */
- if (infile == 0)
- {
- char buf[256];
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- return -1;
- }
-
- xsane_read_pnm_header(infile, &image_info);
-
- if ((image_info.reduce_to_lineart) && (output_format != XSANE_PNM))
- {
- DBG(DBG_info, "original image is a lineart => reduce to lineart\n");
- fclose(infile);
- xsane_back_gtk_make_path(sizeof(lineart_filename), lineart_filename, 0, 0, "xsane-conversion-", xsane.dev_name, ".pbm", XSANE_PATH_TMP);
-
- snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_PACKING_DATA, output_filename);
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf);
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- xsane_save_image_as_lineart(lineart_filename, input_filename, progress_bar, cancel_save);
-
- input_filename = lineart_filename;
- remove_input_file = TRUE;
-
- infile = fopen(input_filename, "rb"); /* read binary (b for win32) */
- if (infile == 0)
- {
- char buf[256];
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- return -1;
- }
-
- xsane_read_pnm_header(infile, &image_info);
- }
-
- snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_SAVING_DATA, output_filename);
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), buf);
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
-
-#ifdef HAVE_LIBTIFF
- if (output_format == XSANE_TIFF) /* routines that want to have filename for saving */
- {
- TIFF *tiffile;
-
- if (xsane_create_secure_file(output_filename)) /* remove possibly existing symbolic links for security */
- {
- snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, output_filename);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- tiffile = TIFFOpen(output_filename, "w");
- if (!tiffile)
- {
- snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_OPEN_FAILED, output_filename);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- xsane_save_tiff_page(tiffile, 0, 0, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save);
-
- TIFFClose(tiffile);
- }
- else /* routines that want to have filedescriptor for saving */
-#endif /* HAVE_LIBTIFF */
- {
- if (xsane_create_secure_file(output_filename)) /* remove possibly existing symbolic links for security */
- {
- snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, output_filename);
- xsane_back_gtk_error(buf, TRUE);
- return -1; /* error */
- }
-
- outfile = fopen(output_filename, "wb"); /* b = binary mode for win32 */
-
- if (outfile != 0)
- {
- switch(output_format)
- {
- case XSANE_PNM:
- if (image_info.reduce_to_lineart)
- {
- xsane_save_grayscale_image_as_lineart(outfile, infile, &image_info, progress_bar, cancel_save);
- }
- else
- {
- xsane_copy_file(outfile, infile, progress_bar, cancel_save);
- }
- break;
-
-#ifdef HAVE_LIBJPEG
- case XSANE_JPEG:
- xsane_save_jpeg(outfile, infile, &image_info, preferences.jpeg_quality, progress_bar, cancel_save);
- break; /* switch format == XSANE_JPEG */
-#endif
-
-#ifdef HAVE_LIBPNG
-#ifdef HAVE_LIBZ
- case XSANE_PNG:
- if (image_info.depth <= 8)
- {
- xsane_save_png(outfile, infile, &image_info, preferences.png_compression, progress_bar, cancel_save);
- }
- else
- {
- xsane_save_png_16(outfile, infile, &image_info, preferences.png_compression, progress_bar, cancel_save);
- }
- break; /* switch format == XSANE_PNG */
-#endif
-#endif
-
- case XSANE_PNM16:
- xsane_save_pnm_16(outfile, infile, &image_info, progress_bar, cancel_save);
- break; /* switch fomat == XSANE_PNM16 */
-
- case XSANE_PS: /* save postscript, use original size */
- {
- float imagewidth, imageheight;
-
- imagewidth = 72.0 * image_info.image_width/image_info.resolution_x; /* width in 1/72 inch */
- imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */
-
- xsane_save_ps(outfile, infile,
- &image_info,
- imagewidth, imageheight,
- 0, /* paper_left_margin */
- 0, /* paper_bottom_margin */
- (int) imagewidth, /* paper_width */
- (int) imageheight, /* paper_height */
- 0 /* portrait top left */,
- preferences.save_ps_flatdecoded,
- progress_bar,
- cancel_save);
- }
- break; /* switch format == XSANE_PS */
-
- case XSANE_PDF: /* save PDF, use original size */
- {
- float imagewidth, imageheight;
-
- imagewidth = 72.0 * image_info.image_width/image_info.resolution_x; /* width in 1/72 inch */
- imageheight = 72.0 * image_info.image_height/image_info.resolution_y; /* height in 1/72 inch */
-
- xsane_save_pdf(outfile, infile,
- &image_info,
- imagewidth, imageheight,
- 0, /* paper_left_margin */
- 0, /* paper_bottom_margin */
- (int) imagewidth, /* paper_width */
- (int) imageheight, /* paper_height */
- 0 /* portrait top left */,
- preferences.save_pdf_flatdecoded,
- progress_bar,
- cancel_save);
- }
- break; /* switch format == XSANE_PDF */
-
- case XSANE_TEXT: /* save as text using ocr program like gocr/jocr */
- {
- xsane_save_image_as_text(output_filename, input_filename, progress_bar, cancel_save);
- }
- break; /* switch format == XSANE_TEXT */
-
- default:
- snprintf(buf, sizeof(buf),"%s", ERR_UNKNOWN_SAVING_FORMAT);
- xsane_back_gtk_error(buf, TRUE);
-
- fclose(outfile);
- fclose(infile);
-
- remove(output_filename); /* no usable output: remove output file */
-
- if (remove_input_file)
- {
- remove(input_filename); /* remove lineart pbm file */
- }
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), "");
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- return -2;
- break; /* switch format == default */
- }
- fclose(outfile);
- }
- else
- {
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, output_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- fclose(infile);
-
- if (remove_input_file)
- {
- remove(input_filename); /* remove lineart pbm file */
- }
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), "");
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- return -2;
- }
- }
-
- fclose (infile);
-
- if (remove_input_file)
- {
- remove(input_filename); /* remove lineart pbm file */
- }
-
- if (*cancel_save) /* remove output file if saving has been canceled */
- {
- remove(output_filename);
- }
-
- gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), "");
- gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), 0.0);
-
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- return (*cancel_save);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_ANY_GIMP
-static int xsane_decode_devname(const char *encoded_devname, int n, char *buf)
-{
- char *dst, *limit;
- const char *src;
- char ch, val;
-
- DBG(DBG_proc, "xsane_decode_devname\n");
-
- limit = buf + n;
- for (src = encoded_devname, dst = buf; *src; ++dst)
- {
- if (dst >= limit)
- {
- return -1;
- }
-
- ch = *src++;
- /* don't use the ctype.h macros here since we don't want to allow anything non-ASCII here... */
- if (ch != '-')
- {
- *dst = ch;
- }
- else /* decode */
- {
- ch = *src++;
- if (ch == '-')
- {
- *dst = ch;
- }
- else
- {
- if (ch >= 'a' && ch <= 'f')
- {
- val = (ch - 'a') + 10;
- }
- else
- {
- val = (ch - '0');
- }
- val <<= 4;
-
- ch = *src++;
- if (ch >= 'a' && ch <= 'f')
- {
- val |= (ch - 'a') + 10;
- }
- else
- {
- val |= (ch - '0');
- }
-
- *dst = val;
-
- ++src; /* simply skip terminating '-' for now... */
- }
- }
- }
-
- if (dst >= limit)
- {
- return -1;
- }
-
- *dst = '\0';
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int xsane_encode_devname(const char *devname, int n, char *buf)
-{
- static const char hexdigit[] = "0123456789abcdef";
- char *dst, *limit;
- const char *src;
- char ch;
-
- DBG(DBG_proc, "xsane_encode_devname\n");
-
- limit = buf + n;
- for (src = devname, dst = buf; *src; ++src)
- {
- if (dst >= limit)
- {
- return -1;
- }
-
- ch = *src;
- /* don't use the ctype.h macros here since we don't want to allow anything non-ASCII here... */
- if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
- {
- *dst++ = ch;
- }
- else /* encode */
- {
- if (dst + 4 >= limit)
- {
- return -1;
- }
-
- *dst++ = '-';
- if (ch == '-')
- {
- *dst++ = '-';
- }
- else
- {
- *dst++ = hexdigit[(ch >> 4) & 0x0f];
- *dst++ = hexdigit[(ch >> 0) & 0x0f];
- *dst++ = '-';
- }
- }
- }
-
- if (dst >= limit)
- {
- return -1;
- }
-
- *dst = '\0';
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void xsane_gimp_query(void)
-{
- static GimpParamDef args[] =
- {
- {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
- };
- static GimpParamDef *return_vals = NULL;
- static int nargs = sizeof(args) / sizeof(args[0]);
- static int nreturn_vals = 0;
- char mpath[1024];
- char name[1024];
- size_t len;
- int i, j;
-
- DBG(DBG_proc, "xsane_gimp_query\n");
-
- snprintf(name, sizeof(name), "%s", xsane.prog_name);
-#ifdef GIMP_CHECK_VERSION
-# if GIMP_CHECK_VERSION(1,1,9)
- snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG);
-# else
- snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG_OLD);
-# endif
-#else
- snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_DIALOG_OLD);
-#endif
- gimp_install_procedure(name,
- XSANE_GIMP_INSTALL_BLURB,
- XSANE_GIMP_INSTALL_HELP,
- XSANE_AUTHOR,
- XSANE_COPYRIGHT,
- XSANE_DATE,
- mpath,
- 0, /* "RGB, GRAY", */
- GIMP_EXTENSION,
- nargs, nreturn_vals,
- args, return_vals);
-
- sane_init(&xsane.sane_backend_versioncode, (void *) xsane_authorization_callback);
- if (SANE_VERSION_MAJOR(xsane.sane_backend_versioncode) != SANE_V_MAJOR)
- {
- DBG(DBG_error0, "\n\n"
- "%s %s:\n"
- " %s\n"
- " %s %d\n"
- " %s %d\n"
- "%s\n\n",
- xsane.prog_name, ERR_ERROR,
- ERR_MAJOR_VERSION_NR_CONFLICT,
- ERR_XSANE_MAJOR_VERSION, SANE_V_MAJOR,
- ERR_BACKEND_MAJOR_VERSION, SANE_VERSION_MAJOR(xsane.sane_backend_versioncode),
- ERR_PROGRAM_ABORTED);
- return;
- }
-
- sane_get_devices(&xsane.devlist, SANE_FALSE);
-
- for (i = 0; xsane.devlist[i]; ++i)
- {
- snprintf(name, sizeof(name), "%s-", xsane.prog_name);
- if (xsane_encode_devname(xsane.devlist[i]->name, sizeof(name) - 6, name + 6) < 0)
- {
- continue; /* name too long... */
- }
-
-#ifdef GIMP_CHECK_VERSION
-# if GIMP_CHECK_VERSION(1,1,9)
- snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU);
-# else
- snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_OLD);
-# endif
-#else
- snprintf(mpath, sizeof(mpath), "%s", XSANE_GIMP_MENU_OLD);
-#endif
- len = strlen(mpath);
- for (j = 0; xsane.devlist[i]->name[j]; ++j)
- {
- if (xsane.devlist[i]->name[j] == '/')
- {
- mpath[len++] = '\'';
- }
- else
- {
- mpath[len++] = xsane.devlist[i]->name[j];
- }
- }
- mpath[len++] = '\0';
-
- gimp_install_procedure(name,
- XSANE_GIMP_INSTALL_BLURB,
- XSANE_GIMP_INSTALL_HELP,
- XSANE_AUTHOR,
- XSANE_COPYRIGHT,
- XSANE_DATE,
- mpath,
- 0, /* "RGB, GRAY", */
- GIMP_EXTENSION,
- nargs, nreturn_vals,
- args, return_vals);
- }
-
- sane_exit();
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef HAVE_GIMP_2
-static void xsane_gimp_run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals)
-{
- GimpRunMode run_mode;
-#else /* GIMP-1.x */
-static void xsane_gimp_run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals)
-{
- GimpRunModeType run_mode;
-#endif
-
- static GimpParam values[2];
- char devname[1024];
- char *args[2];
- int nargs;
-
- DBG(DBG_proc, "xsane_gimp_run\n");
-
- run_mode = param[0].data.d_int32;
- xsane.mode = XSANE_GIMP_EXTENSION;
- xsane.xsane_mode = XSANE_SAVE;
-
- *nreturn_vals = 1;
- *return_vals = values;
-
- values[0].type = GIMP_PDB_STATUS;
- values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
-
- nargs = 0;
- args[nargs++] = "xsane";
-
- xsane.selected_dev = -1;
- if (strncmp(name, "xsane-", 6) == 0)
- {
- if (xsane_decode_devname(name + 6, sizeof(devname), devname) < 0)
- {
- return; /* name too long */
- }
- args[nargs++] = devname;
- }
-
- switch (run_mode)
- {
- case GIMP_RUN_INTERACTIVE:
-#ifdef HAVE_GIMP_2
- gimp_extension_ack();
-#endif
- xsane_interface(nargs, args);
- values[0].data.d_status = GIMP_PDB_SUCCESS;
- break;
-
- case GIMP_RUN_NONINTERACTIVE:
- /* Make sure all the arguments are there! */
- break;
-
- case GIMP_RUN_WITH_LAST_VALS:
- /* Possibly retrieve data */
- break;
-
- default:
- break;
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void null_print_func(gchar *msg)
-{
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, int *cancel_save)
-{
- int remaining;
- size_t tile_size;
- GimpImageType image_type = GIMP_GRAY;
- GimpImageType drawable_type = GIMP_GRAY_IMAGE;
- gint32 layer_ID;
- gint32 image_ID;
- GimpDrawable *drawable;
- guchar *tile;
- GimpPixelRgn region;
- unsigned tile_offset;
- int i, x, y;
- Image_info image_info;
- FILE *imagefile;
-
- DBG(DBG_info, "xsane_transer_to_gimp\n");
-
- *cancel_save = 0;
-
- imagefile = fopen(input_filename, "rb"); /* read binary (b for win32) */
- if (imagefile == 0)
- {
- char buf[256];
- snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, input_filename, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- return -1;
- }
-
- xsane_read_pnm_header(imagefile, &image_info);
-
- x = 0;
- y = 0;
- tile_offset = 0;
- tile_size = image_info.image_width * gimp_tile_height();
-
- if (image_info.colors == 3) /* RGB */
- {
- tile_size *= 3; /* 24 bits/pixel RGB */
- image_type = GIMP_RGB;
- drawable_type = GIMP_RGB_IMAGE;
- }
- else if (image_info.colors == 4) /* RGBA */
- {
- tile_size *= 4; /* 32 bits/pixel RGBA */
- image_type = GIMP_RGB;
- drawable_type = GIMP_RGBA_IMAGE; /* interpret infrared as alpha */
- }
- /* colors == 0/1 is predefined */
-
- image_ID = gimp_image_new(image_info.image_width, image_info.image_height, image_type);
-
-/* the following is supported since gimp-1.1.? */
-#ifdef GIMP_HAVE_RESOLUTION_INFO
- if (image_info.resolution_x > 0)
- {
- gimp_image_set_resolution(image_ID, image_info.resolution_x, image_info.resolution_y);
- }
-/* gimp_image_set_unit(image_ID, unit?); */
-#endif
-
- layer_ID = gimp_layer_new(image_ID, "Background", image_info.image_width, image_info.image_height, drawable_type, 100.0, GIMP_NORMAL_MODE);
- gimp_image_add_layer(image_ID, layer_ID, 0);
- drawable = gimp_drawable_get(layer_ID);
- gimp_pixel_rgn_init(&region, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE);
- tile = g_new(guchar, tile_size);
-
-
- if (image_info.colors == 1) /* gray */
- {
- switch (image_info.depth)
- {
- case 1: /* 1 bit gray => conversion to 8 bit gray */
- for (i = 0; i < ( (image_info.image_width + 7) / 8) * image_info.image_height; ++i)
- {
- u_char mask;
- int j;
-
- mask = fgetc(imagefile);
- for (j = 7; j >= 0; --j)
- {
- u_char gl = (mask & (1 << j)) ? 0x00 : 0xff;
- tile[tile_offset++] = gl;
-
- x++;
-
- if (x >= image_info.image_width)
- {
- int tile_height = gimp_tile_height();
-
- x = 0;
- y++;
-
- if (y % tile_height == 0)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
- tile_offset = 0;
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
-
- break; /* leave for j loop */
- }
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break; /* leave switch depth 1 */
-
- case 8: /* 8 bit gray */
- case 16: /* 16 bit gray already has been reduced to 8 bit */
- for (i = 0; i < image_info.image_width * image_info.image_height; ++i)
- {
- tile[tile_offset++] = fgetc(imagefile);
- x++;
-
- if (x >= image_info.image_width)
- {
- int tile_height = gimp_tile_height();
-
- x = 0;
- y++;
-
- if (y % tile_height == 0)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
- tile_offset = 0;
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break; /* leave switch depth */
-
- default: /* bad depth */
- break; /* default */
- }
- }
- else if (image_info.colors == 3) /* RGB */
- {
- switch (image_info.depth)
- {
- case 8: /* 8 bit RGB */
- case 16: /* 16 bit RGB already has been reduced to 8 bit */
- for (i = 0; i < image_info.image_width * image_info.image_height*3; ++i)
- {
- tile[tile_offset++] = fgetc(imagefile);
- if (tile_offset % 3 == 0)
- {
- x++;
-
- if (x >= image_info.image_width)
- {
- int tile_height = gimp_tile_height();
-
- x = 0;
- y++;
-
- if (y % tile_height == 0)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
- tile_offset = 0;
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break; /* case 8 */
-
- default: /* bad depth */
- break; /* default */
- }
- }
-#ifdef SUPPORT_RGBA
- else if (image_info.colors == 4) /* RGBA */
- {
- int i;
-
- switch (image_info.depth)
- {
- case 8: /* 8 bit RGBA */
- case 16: /* 16 bit RGBA already has been reduced to 8 bit */
- for (i = 0; i < image_info.image_width * image_info.image_height * 4; ++i)
- {
- tile[tile_offset++] = fgetc(imagefile);
- if (tile_offset % 4 == 0)
- {
- x++;
-
- if (x >= image_info.image_width)
- {
- int tile_height = gimp_tile_height();
-
- x = 0;
- y++;
-
- if (y % tile_height == 0)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - tile_height, image_info.image_width, tile_height);
- tile_offset = 0;
- }
-
- gtk_progress_bar_update(progress_bar, (float) y / image_info.image_height); /* update progress bar */
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
- }
-
- if (*cancel_save)
- {
- break;
- }
- }
- break;
-
- default: /* bad depth */
- break;
- }
- }
-#endif
-
-/* scan_done part */
- if (y > image_info.image_height)
- {
- y = image_info.image_height;
- }
-
- remaining = y % gimp_tile_height();
-
- if (remaining)
- {
- gimp_pixel_rgn_set_rect(&region, tile, 0, y - remaining, image_info.image_width, remaining);
- }
-
- gimp_drawable_flush(drawable);
- gimp_display_new(image_ID);
- gimp_drawable_detach(drawable);
- g_free(tile);
- tile = 0;
-
- fclose(imagefile);
-
- return 0;
-}
-#endif /* HAVE_ANY_GIMP */
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#ifdef XSANE_ACTIVATE_MAIL
-
-/* character base of base64 coding */
-static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void write_3chars_as_base64(unsigned char c1, unsigned char c2, unsigned char c3, int pads, int fd_socket)
-{
- char buf[4];
-
- buf[0] = base64[c1>>2]; /* wirte bits 7-2 of first char */
- buf[1] = base64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; /* write bits 1,0 of first and bits 7-4 of second char */
-
- if (pads == 2) /* only one byte used */
- {
- buf[2] = '='; /* char not used */
- buf[3] = '='; /* char not used */
- }
- else if (pads) /* only two bytes used */
- {
- buf[2] = base64[((c2 & 0xF) << 2)]; /* write bits 3-0 of second char */
- buf[3] = '='; /* char not used */
- }
- else
- {
- buf[2] = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; /* write bits 3-0 of second and bits 7,6 of third char */
- buf[3] = base64[c3 & 0x3F]; /* write bits 5-0 of third char as lsb */
- }
-
- write(fd_socket, buf, 4);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_base64(int fd_socket, FILE *infile)
-{
- int c1, c2, c3;
- int pos = 0;
-
- while ((c1 = getc(infile)) != EOF)
- {
- c2 = getc(infile);
- if (c2 == EOF)
- {
- write_3chars_as_base64(c1, 0, 0, 2, fd_socket);
- }
- else
- {
- c3 = getc(infile);
- if (c3 == EOF)
- {
- write_3chars_as_base64(c1, c2, 0, 1, fd_socket);
- }
- else
- {
- write_3chars_as_base64(c1, c2, c3, 0, fd_socket);
- }
- }
-
- pos += 4;
- if (pos > 71)
- {
- write(fd_socket, "\n", 1);
-
- pos = 0;
- }
-
- xsane.mail_progress_bytes += 3;
- if ((int) ((xsane.mail_progress_bytes * 100) / xsane.mail_progress_size) != (int) (xsane.mail_progress_val * 100))
- {
- xsane.mail_progress_val = (float) xsane.mail_progress_bytes / xsane.mail_progress_size;
- xsane_front_gtk_mail_project_update_lockfile_status();
- }
- }
-
- if (pos)
- {
- write(fd_socket, "\n", 1);
- }
-
- xsane.mail_progress_val = 1.0;
- xsane_front_gtk_mail_project_update_lockfile_status();
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_mail_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "From: %s\n", from);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Reply-To: %s\n", reply_to);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "To: %s\n", to);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Subject: %s\n", subject);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "MIME-Version: 1.0\n");
- write(fd_socket, buf, strlen(buf));
-
- if (related) /* related means that we need a special link in the html part to display the image */
- {
- snprintf(buf, sizeof(buf), "Content-Type: multipart/related;\n");
- write(fd_socket, buf, strlen(buf));
- }
- else
- {
- snprintf(buf, sizeof(buf), "Content-Type: multipart/mixed;\n");
- write(fd_socket, buf, strlen(buf));
- }
-
- snprintf(buf, sizeof(buf), " boundary=\"%s\"\n\n", boundary);
- write(fd_socket, buf, strlen(buf));
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_mail_footer(int fd_socket, char *boundary)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "--%s--\n", boundary);
- write(fd_socket, buf, strlen(buf));
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_mail_mime_ascii(int fd_socket, char *boundary)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Type: text/plain;\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), " charset=\"iso-8859-1\"\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 8bit\n\n");
- write(fd_socket, buf, strlen(buf));
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_mail_mime_html(int fd_socket, char *boundary)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Type: text/html;\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), " charset=\"us-ascii\"\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: 7bit\n\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "<html>\n");
- write(fd_socket, buf, strlen(buf));
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_mail_attach_image(int fd_socket, char *boundary, char *content_id, char *content_type, FILE *infile, char *filename)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Type: %s\n", content_type);
- write(fd_socket, buf, strlen(buf));
-
- if (content_id)
- {
- snprintf(buf, sizeof(buf), "Content-ID: <%s>\n", content_id);
- write(fd_socket, buf, strlen(buf));
- }
-
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Disposition: inline;\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), " filename=\"%s\"\n", filename);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "\n");
- write(fd_socket, buf, strlen(buf));
-
- write_base64(fd_socket, infile);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void write_mail_attach_file(int fd_socket, char *boundary, FILE *infile, char *filename)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "--%s\n", boundary);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Type: application/octet-stream\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), " name=\"%s\"\n", filename);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Transfer-Encoding: base64\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "Content-Disposition: attachment;\n");
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), " filename=\"%s\"\n", filename);
- write(fd_socket, buf, strlen(buf));
-
- snprintf(buf, sizeof(buf), "\n");
- write(fd_socket, buf, strlen(buf));
-
- write_base64(fd_socket, infile);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* returns fd_socket if sucessfull, < 0 when error occured */
-int open_socket(char *server, int port)
-{
- int fd_socket;
- struct sockaddr_in sin;
- struct hostent *he;
-
- he = gethostbyname(server);
- if (!he)
- {
- DBG(DBG_error, "open_socket: Could not get hostname of \"%s\"\n", server);
- return -1;
- }
- else
- {
- DBG(DBG_info, "open_socket: connecting to \"%s\" = %d.%d.%d.%d\n",
- he->h_name,
- (unsigned char) he->h_addr_list[0][0],
- (unsigned char) he->h_addr_list[0][1],
- (unsigned char) he->h_addr_list[0][2],
- (unsigned char) he->h_addr_list[0][3]);
- }
-
- if (he->h_addrtype != AF_INET)
- {
- DBG(DBG_error, "open_socket: Unknown address family: %d\n", he->h_addrtype);
- return -1;
- }
-
- fd_socket = socket(AF_INET, SOCK_STREAM, 0);
-
- if (fd_socket < 0)
- {
- DBG(DBG_error, "open_socket: Could not create socket: %s\n", strerror(errno));
- return -1;
- }
-
-/* setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on)); */
-
- sin.sin_port = htons(port);
- sin.sin_family = AF_INET;
- memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length);
-
- if (connect(fd_socket, &sin, sizeof(sin)))
- {
- DBG(DBG_error, "open_socket: Could not connect with port %d of socket: %s\n", ntohs(sin.sin_port), strerror(errno));
- return -1;
- }
-
- DBG(DBG_info, "open_socket: Connected with port %d\n", ntohs(sin.sin_port));
-
- return fd_socket;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* returns 0 if success */
-/* not only a write routine, also reads data */
-int pop3_login(int fd_socket, char *user, char *passwd)
-{
- char buf[1024];
- int len;
-
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- snprintf(buf, sizeof(buf), "USER %s\r\n", user);
- DBG(DBG_info2, "> USER xxx\n");
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
- if (buf[0] != '+')
- {
- return -1;
- }
-
- snprintf(buf, sizeof(buf), "PASS %s\r\n", passwd);
- DBG(DBG_info2, "> PASS xxx\n");
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
- if (buf[0] != '+')
- {
- return -1;
- }
-
- snprintf(buf, sizeof(buf), "QUIT\r\n");
- DBG(DBG_info2, "> QUIT\n");
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* not only a write routine, also reads data */
-/* returns -1 on error, 0 when ok */
-int write_smtp_header(int fd_socket, char *from, char *to)
-{
- char buf[1024];
- int len;
-
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- snprintf(buf, sizeof(buf), "helo localhost\r\n");
- DBG(DBG_info2, "> %s", buf);
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- if (buf[0] != '2')
- {
- DBG(DBG_info, "=> error\n");
-
- if (xsane.mail_status)
- {
- free(xsane.mail_status);
- }
- xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_CONNECTION_FAILED);
- xsane_front_gtk_mail_project_update_lockfile_status();
- return -1;
- }
-
- snprintf(buf, sizeof(buf), "MAIL FROM: %s\r\n", from);
- DBG(DBG_info2, "> %s", buf);
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- if (buf[0] != '2')
- {
- DBG(DBG_info, "=> error\n");
-
- if (xsane.mail_status)
- {
- free(xsane.mail_status);
- }
- xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_FROM);
- xsane_front_gtk_mail_project_update_lockfile_status();
- return -1;
- }
-
-
- snprintf(buf, sizeof(buf), "RCPT TO: %s\r\n", to);
- DBG(DBG_info2, "> %s", buf);
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- if (buf[0] != '2')
- {
- DBG(DBG_info, "=> error\n");
-
- if (xsane.mail_status)
- {
- free(xsane.mail_status);
- }
- xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_RCPT);
- xsane_front_gtk_mail_project_update_lockfile_status();
- return -1;
- }
-
- snprintf(buf, sizeof(buf), "DATA\r\n");
- DBG(DBG_info2, "> %s", buf);
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- if ((buf[0] != '2') && (buf[0] != '3'))
- {
- DBG(DBG_info, "=> error\n");
-
- if (xsane.mail_status)
- {
- free(xsane.mail_status);
- }
- xsane.mail_status = strdup(TEXT_MAIL_STATUS_SMTP_ERR_DATA);
- xsane_front_gtk_mail_project_update_lockfile_status();
- return -1;
- }
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* not only a write routine, also reads data */
-int write_smtp_footer(int fd_socket)
-{
- char buf[1024];
- int len;
-
- snprintf(buf, sizeof(buf), "\r\n.\r\n");
- DBG(DBG_info2, "> %s", buf);
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- snprintf(buf, sizeof(buf), "QUIT\r\n");
- DBG(DBG_info2, "> %s", buf);
- write(fd_socket, buf, strlen(buf));
- len = read(fd_socket, buf, sizeof(buf));
- if (len >= 0)
- {
- buf[len] = 0;
- }
- DBG(DBG_info2, "< %s\n", buf);
-
- return 0;
-}
-
-#endif
-/* ---------------------------------------------------------------------------------------------------------------------- */
diff --git a/src/xsane-save.h b/src/xsane-save.h
index 553fbd5..f94fe7c 100644
--- a/src/xsane-save.h
+++ b/src/xsane-save.h
@@ -3,7 +3,7 @@
xsane-save.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -40,7 +40,7 @@
#define PDF_PAGES_MAX 1000
struct pdf_xref
{
- unsigned long obj[PDF_PAGES_MAX * 2 + 6];
+ unsigned long obj[PDF_PAGES_MAX * 2 + 8];
unsigned long xref; /* xref table */
unsigned long slen; /* length of image stream */
unsigned long slenp; /* position of image stream length */
@@ -60,50 +60,58 @@ extern void xsane_read_pnm_header(FILE *file, Image_info *image_info);
extern void xsane_write_pnm_header(FILE *file, Image_info *image_info, int save_pnm16_as_ascii);
extern int xsane_copy_file(FILE *outfile, FILE *infile, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_copy_file_by_name(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save);
+#ifdef HAVE_LIBLCMS
+extern cmsHTRANSFORM xsane_create_cms_transform(Image_info *image_info, int cms_function, int cms_intent, int cms_bpc);
+#endif
extern int xsane_save_grayscale_image_as_lineart(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float radius, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int rotation, GtkProgressBar *progress_bar, int *cancel_save);
-extern void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatdecode);
+extern void xsane_save_ps_create_document_header(FILE *outfile, int pages, int flatedecode);
extern void xsane_save_ps_create_document_trailer(FILE *outfile, int pages);
extern int xsane_save_ps_page(FILE *outfile, int page,
FILE *imagefile, Image_info *image_info, float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int embed_scanner_icm_profile,
GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_ps(FILE *outfile, FILE *imagefile, Image_info *image_info,
float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int embed_CSA, char *CSA_profile,
+ int embed_CRD, char *CRD_profile, int blackpointcompensation, int intent,
GtkProgressBar *progress_bar, int *cancel_save);
-extern void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref, int pages, int flatdecode);
+extern void xsane_save_pdf_create_document_header(FILE *outfile, struct pdf_xref *xref, int pages, int flatedecode);
extern void xsane_save_pdf_create_document_trailer(FILE *outfile, struct pdf_xref *xref, int pages);
extern int xsane_save_pdf_page(FILE *outfile, struct pdf_xref *xref, int page,
FILE *imagefile, Image_info *image_info, float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int embed__scanner_icm_profile, int icc_object,
GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_pdf(FILE *outfile, FILE *imagefile, Image_info *image_info,
float width, float height,
int paper_left_margin, int paper_bottom_margin, int paperwidth, int paperheight, int paper_orientation,
- int flatdecode,
+ int flatedecode,
+ cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
GtkProgressBar *progress_bar, int *cancel_save);
#ifdef HAVE_LIBJPEG
-extern int xsane_save_jpeg(FILE *outfile, FILE *imagefile, Image_info *image_info, int quality, GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_save_jpeg(FILE *outfile, int quality, FILE *imagefile, Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save);
#endif
#ifdef HAVE_LIBTIFF
-extern int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, FILE *imagefile, Image_info *image_info, int quality,
- GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_save_tiff_page(TIFF *tiffile, int page, int pages, int quality, FILE *imagefile, Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function,
+ GtkProgressBar *progress_bar, int *cancel_save);
#endif
-extern int xsane_save_png(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save);
-extern int xsane_save_png_16(FILE *outfile, FILE *imagefile, Image_info *image_info, int compression, GtkProgressBar *progress_bar, int *cancel_save);
-extern int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_save_png(FILE *outfile, int compression, FILE *imagefile, Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_save_png_16(FILE *outfile, int compression, FILE *imagefile, Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_save_pnm_16(FILE *outfile, FILE *imagefile, Image_info *image_info, cmsHTRANSFORM hTransform, int apply_ICM_profile, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_image_as_lineart(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save);
extern int xsane_save_image_as_text(char *output_filename, char *input_filename, GtkProgressBar *progress_bar, int *cancel_save);
-extern int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_save_image_as(char *output_filename, char *input_filename, int output_format, int apply_ICM_profile, int cms_function, int cms_intent, int cms_bpc, GtkProgressBar *progress_bar, int *cancel_save);
extern void null_print_func(gchar *msg);
-extern int xsane_transfer_to_gimp(char *input_filename, GtkProgressBar *progress_bar, int *cancel_save);
+extern int xsane_transfer_to_gimp(char *input_filename, int apply_ICM_profile, int cms_function, GtkProgressBar *progress_bar, int *cancel_save);
extern void write_base64(int fd_socket, FILE *infile);
extern void write_email_header(int fd_socket, char *from, char *reply_to, char *to, char *subject, char *boundary, int related);
extern void write_email_footer(int fd_socket, char *boundary);
diff --git a/src/xsane-scan.c b/src/xsane-scan.c
index 578cc57..9cc9ffb 100644
--- a/src/xsane-scan.c
+++ b/src/xsane-scan.c
@@ -3,7 +3,7 @@
xsane-scan.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -1061,7 +1061,7 @@ void xsane_scan_done(SANE_Status status)
image_info.image_width = xsane.param.pixels_per_line;
image_info.image_height = pixel_height;
image_info.depth = xsane.depth;
- image_info.colors = xsane.xsane_colors;
+ image_info.channels = xsane.xsane_channels;
image_info.resolution_x = xsane.resolution_x;
image_info.resolution_y = xsane.resolution_y;
@@ -1085,6 +1085,13 @@ void xsane_scan_done(SANE_Status status)
image_info.reduce_to_lineart = xsane.expand_lineart_to_grayscale;
+ image_info.enable_color_management = xsane.enable_color_management;
+ image_info.cms_function = preferences.cms_function;
+ image_info.cms_intent = preferences.cms_intent;
+ image_info.cms_bpc = preferences.cms_bpc;
+
+ strncpy(image_info.icm_profile, xsane.scanner_default_color_icm_profile, sizeof(image_info.icm_profile));
+
xsane_write_pnm_header(xsane.out, &image_info, 0);
}
@@ -1233,12 +1240,12 @@ void xsane_scan_done(SANE_Status status)
#ifdef HAVE_ANY_GIMP
if (xsane.mode == XSANE_GIMP_EXTENSION) /* xsane runs as gimp plugin */
{
- xsane_transfer_to_gimp(xsane.dummy_filename, xsane.progress_bar, &xsane.cancel_save);
+ xsane_transfer_to_gimp(xsane.dummy_filename, xsane.enable_color_management, preferences.cms_function, xsane.progress_bar, &xsane.cancel_save);
}
else
#endif /* HAVE_ANY_GIMP */
{
- xsane_save_image_as(xsane.output_filename, xsane.dummy_filename, xsane.xsane_output_format, xsane.progress_bar, &xsane.cancel_save);
+ xsane_save_image_as(xsane.output_filename, xsane.dummy_filename, xsane.xsane_output_format, xsane.enable_color_management, preferences.cms_function, preferences.cms_intent, preferences.cms_bpc, xsane.progress_bar, &xsane.cancel_save);
}
xsane_progress_clear();
@@ -1345,7 +1352,11 @@ void xsane_scan_done(SANE_Status status)
preferences.printer[preferences.printernr]->width * 72.0/MM_PER_INCH, /* usable paperwidth */
preferences.printer[preferences.printernr]->height * 72.0/MM_PER_INCH, /* usable paperheight */
preferences.paper_orientation,
- preferences.printer[preferences.printernr]->ps_flatdecoded, /* ps level 3 */
+ preferences.printer[preferences.printernr]->ps_flatedecoded, /* ps level 3 */
+ NULL /* hTransform */, xsane.enable_color_management,
+ preferences.printer[preferences.printernr]->embed_csa, xsane.scanner_default_color_icm_profile,
+ preferences.printer[preferences.printernr]->embed_crd, preferences.printer[preferences.printernr]->icm_profile, preferences.printer[preferences.printernr]->blackpointcompensation,
+ 0 /* intent */,
xsane.progress_bar,
&xsane.cancel_save);
}
@@ -1729,7 +1740,7 @@ static void xsane_start_scan(void)
image_info.image_width = xsane.param.pixels_per_line;
image_info.image_height = xsane.param.lines;
image_info.depth = xsane.depth;
- image_info.colors = xsane.xsane_colors;
+ image_info.channels = xsane.xsane_channels;
image_info.resolution_x = xsane.resolution_x;
image_info.resolution_y = xsane.resolution_y;
@@ -1753,6 +1764,13 @@ static void xsane_start_scan(void)
image_info.reduce_to_lineart = xsane.expand_lineart_to_grayscale;
+ image_info.enable_color_management = xsane.enable_color_management;
+ image_info.cms_function = preferences.cms_function;
+ image_info.cms_intent = preferences.cms_intent;
+ image_info.cms_bpc = preferences.cms_bpc;
+
+ strncpy(image_info.icm_profile, xsane.scanner_default_color_icm_profile, sizeof(image_info.icm_profile));
+
xsane_write_pnm_header(xsane.out, &image_info, 0);
fflush(xsane.out);
@@ -1946,34 +1964,6 @@ gint xsane_scan_dialog(gpointer *data)
free(extension);
}
}
-#ifdef HAVE_ANY_GIMP
- else /* We are running in gimp mode */
- {
- if ((xsane.param.depth != 1) && (xsane.param.depth != 8)) /* not support bit depth ? */
- {
- if (!xsane.reduce_16bit_to_8bit) /* ask if reduce 16 to 8 bit */
- {
- if (xsane.param.depth == 16)
- {
- snprintf(buf, sizeof(buf), TEXT_GIMP_REDUCE_16BIT_TO_8BIT);
- if (xsane_back_gtk_decision(ERR_HEADER_INFO, (gchar **) info_xpm, buf, BUTTON_REDUCE, BUTTON_CANCEL, TRUE /* wait */) == FALSE)
- {
- xsane_set_sensitivity(TRUE);
- return FALSE;
- }
- xsane.reduce_16bit_to_8bit = TRUE;
- }
- else /* unsupported bit depth */
- {
- snprintf(buf, sizeof(buf), ERR_GIMP_BAD_DEPTH, xsane.param.depth);
- xsane_back_gtk_error(buf, TRUE);
- xsane_set_sensitivity(TRUE);
- return FALSE;
- }
- }
- }
- }
-#endif
if (xsane.dummy_filename) /* no dummy filename defined - necessary if an error occurs */
{
@@ -1982,7 +1972,7 @@ gint xsane_scan_dialog(gpointer *data)
}
/* create scanner gamma tables, xsane internal gamma tables are created after sane_start */
- if ( (xsane.xsane_colors > 1) && /* color scan */
+ if ( (xsane.xsane_channels > 1) && /* color scan */
xsane.scanner_gamma_color ) /* gamma table for red, green and blue available */
{
double gamma_red, gamma_green, gamma_blue;
@@ -2097,7 +2087,7 @@ gint xsane_scan_dialog(gpointer *data)
xsane.gamma_data = malloc(gamma_gray_size * sizeof(SANE_Int));
- if (xsane.xsane_colors > 1) /* color scan */
+ if (xsane.xsane_channels > 1) /* color scan */
{
xsane_create_gamma_curve(xsane.gamma_data, xsane.negative,
gamma, xsane.brightness, xsane.contrast,
@@ -2145,7 +2135,7 @@ static void xsane_create_internal_gamma_tables(void)
size = (int) pow(2, xsane.param.depth);
maxval = size-1;
- if (xsane.xsane_colors > 1) /* color scan */
+ if (xsane.xsane_channels > 1) /* color scan */
{
if ( (!xsane.scanner_gamma_color) && (xsane.scanner_gamma_gray) )
{
diff --git a/src/xsane-scan.h b/src/xsane-scan.h
index b46d5e0..681e89f 100644
--- a/src/xsane-scan.h
+++ b/src/xsane-scan.h
@@ -3,7 +3,7 @@
xsane-scan.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-setup.c b/src/xsane-setup.c
index c0c9000..677c375 100644
--- a/src/xsane-setup.c
+++ b/src/xsane-setup.c
@@ -3,7 +3,7 @@
xsane-setup.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -92,6 +92,9 @@ static void xsane_setup_authentication_type_callback(GtkWidget *widget, gpointer
static void xsane_setup_show_range_mode_callback(GtkWidget *widget, gpointer data);
static void xsane_setup_lineart_mode_callback(GtkWidget *widget, gpointer data);
static void xsane_enhance_notebook(GtkWidget *notebook);
+#ifdef HAVE_LIBLCMS
+static void xsane_color_management_notebook(GtkWidget *notebook);
+#endif
void xsane_setup_dialog(GtkWidget *widget, gpointer data);
@@ -135,7 +138,10 @@ void xsane_new_printer(void)
preferences.printer[preferences.printernr]->gamma_red = 1.0;
preferences.printer[preferences.printernr]->gamma_green = 1.0;
preferences.printer[preferences.printernr]->gamma_blue = 1.0;
- preferences.printer[preferences.printernr]->ps_flatdecoded = 1;
+ preferences.printer[preferences.printernr]->icm_profile = NULL;
+ preferences.printer[preferences.printernr]->embed_csa = 1;
+ preferences.printer[preferences.printernr]->embed_crd = 0;
+ preferences.printer[preferences.printernr]->ps_flatedecoded = 1;
}
else
{
@@ -275,8 +281,23 @@ static void xsane_setup_printer_update()
gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_gamma_green_entry), buf);
snprintf(buf, sizeof(buf), "%1.2f", preferences.printer[preferences.printernr]->gamma_blue);
gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_gamma_blue_entry), buf);
+
+#ifdef HAVE_LIBLCMS
+ if (preferences.printer[preferences.printernr]->icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_icm_profile_entry), (char *) preferences.printer[preferences.printernr]->icm_profile);
+ }
+ else
+ {
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_icm_profile_entry), "");
+ }
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane_setup.printer_embed_csa_button), preferences.printer[preferences.printernr]->embed_csa);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane_setup.printer_embed_crd_button), preferences.printer[preferences.printernr]->embed_crd);
+#endif
+
#ifdef HAVE_LIBZ
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane_setup.printer_ps_flatdecoded_button), preferences.printer[preferences.printernr]->ps_flatdecoded);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane_setup.printer_ps_flatedecoded_button), preferences.printer[preferences.printernr]->ps_flatedecoded);
#endif
}
@@ -354,8 +375,18 @@ static void xsane_setup_printer_apply_changes(GtkWidget *widget, gpointer data)
xsane_update_double(xsane_setup.printer_gamma_green_entry, &preferences.printer[preferences.printernr]->gamma_green);
xsane_update_double(xsane_setup.printer_gamma_blue_entry, &preferences.printer[preferences.printernr]->gamma_blue);
+#ifdef HAVE_LIBLCMS
+ if (preferences.printer[preferences.printernr]->icm_profile)
+ {
+ free(preferences.printer[preferences.printernr]->icm_profile);
+ }
+ preferences.printer[preferences.printernr]->icm_profile = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.printer_icm_profile_entry)));
+ xsane_update_bool(xsane_setup.printer_embed_csa_button, &preferences.printer[preferences.printernr]->embed_csa);
+ xsane_update_bool(xsane_setup.printer_embed_crd_button, &preferences.printer[preferences.printernr]->embed_crd);
+#endif
+
#ifdef HAVE_LIBZ
- xsane_update_bool(xsane_setup.printer_ps_flatdecoded_button, &preferences.printer[preferences.printernr]->ps_flatdecoded);
+ xsane_update_bool(xsane_setup.printer_ps_flatedecoded_button, &preferences.printer[preferences.printernr]->ps_flatedecoded);
#endif
if (option_menu)
@@ -530,6 +561,50 @@ static void xsane_setup_enhance_apply_changes(GtkWidget *widget, gpointer data)
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+static void xsane_setup_color_management_apply_changes(GtkWidget *widget, gpointer data)
+{
+ DBG(DBG_proc, "xsane_setup_colormagaement_apply_changes\n");
+
+// preferences.cms_intent = gtk_option_menu_get_history(GTK_OPTION_MENU(xsane_setup.cms_intent_option_menu));
+// preferences.cms_intent = gtk_option_menu_get_history(GTK_OPTION_MENU(xsane_setup.cms_intent_option_menu));
+ preferences.cms_intent = (int) gtk_object_get_data(GTK_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(xsane_setup.cms_intent_option_menu))))), "Selection");
+ xsane_update_bool(xsane_setup.cms_bpc_button, &preferences.cms_bpc);
+
+ if (xsane.scanner_default_color_icm_profile)
+ {
+ free(xsane.scanner_default_color_icm_profile);
+ }
+ xsane.scanner_default_color_icm_profile = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.scanner_default_color_icm_profile_entry)));
+
+ if (xsane.scanner_default_gray_icm_profile)
+ {
+ free(xsane.scanner_default_gray_icm_profile);
+ }
+ xsane.scanner_default_gray_icm_profile = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.scanner_default_gray_icm_profile_entry)));
+
+ if (preferences.display_icm_profile)
+ {
+ free(preferences.display_icm_profile);
+ }
+ preferences.display_icm_profile = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.display_icm_profile_entry)));
+
+ if (preferences.custom_proofing_icm_profile)
+ {
+ free(preferences.custom_proofing_icm_profile);
+ }
+ preferences.custom_proofing_icm_profile = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.custom_proofing_icm_profile_entry)));
+
+ if (preferences.working_color_space_icm_profile)
+ {
+ free(preferences.working_color_space_icm_profile);
+ }
+ preferences.working_color_space_icm_profile = strdup(gtk_entry_get_text(GTK_ENTRY(xsane_setup.working_color_space_icm_profile_entry)));
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
static void xsane_setup_saving_apply_changes(GtkWidget *widget, gpointer data)
{
int level;
@@ -597,8 +672,8 @@ static void xsane_setup_image_apply_changes(GtkWidget *widget, gpointer data)
xsane_update_bool(xsane_setup.save_pnm16_as_ascii_button, &preferences.save_pnm16_as_ascii);
#ifdef HAVE_LIBZ
- xsane_update_bool(xsane_setup.save_ps_flatdecoded_button, &preferences.save_ps_flatdecoded);
- xsane_update_bool(xsane_setup.save_pdf_flatdecoded_button, &preferences.save_pdf_flatdecoded);
+ xsane_update_bool(xsane_setup.save_ps_flatedecoded_button, &preferences.save_ps_flatedecoded);
+ xsane_update_bool(xsane_setup.save_pdf_flatedecoded_button, &preferences.save_pdf_flatedecoded);
#endif
xsane_define_maximum_output_size();
@@ -627,7 +702,7 @@ static void xsane_setup_fax_apply_changes(GtkWidget *widget, gpointer data)
xsane_update_geometry_double(xsane_setup.fax_height_entry, &preferences.fax_height, preferences.length_unit);
#ifdef HAVE_LIBZ
- xsane_update_bool(xsane_setup.fax_ps_flatdecoded_button, &preferences.fax_ps_flatdecoded);
+ xsane_update_bool(xsane_setup.fax_ps_flatedecoded_button, &preferences.fax_ps_flatedecoded);
#endif
xsane_define_maximum_output_size();
@@ -719,6 +794,9 @@ static void xsane_setup_options_ok_callback(GtkWidget *widget, gpointer data)
xsane_setup_email_apply_changes(0, 0);
#endif
xsane_setup_ocr_apply_changes(0, 0);
+#ifdef HAVE_LIBLCMS
+ xsane_setup_color_management_apply_changes(0, 0);
+#endif
if (xsane_setup.grayscale_scanmode)
{
@@ -851,7 +929,7 @@ static void xsane_permission_box(GtkWidget *parent, gchar *name, gchar *descript
button = gtk_toggle_button_new_with_label("x");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *permission & 64 );
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PERMISSION_EXECUTE);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PERMISSION_SEARCH);
gtk_widget_set_size_request(button, 21, -1);
gtk_widget_set_name(button, name);
g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_permission_toggled, (void *) 64);
@@ -887,7 +965,7 @@ static void xsane_permission_box(GtkWidget *parent, gchar *name, gchar *descript
button = gtk_toggle_button_new_with_label("x");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *permission & 8 );
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PERMISSION_EXECUTE);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PERMISSION_SEARCH);
gtk_widget_set_size_request(button, 21, -1);
gtk_widget_set_name(button, name);
g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_permission_toggled, (void *) 8);
@@ -923,7 +1001,7 @@ static void xsane_permission_box(GtkWidget *parent, gchar *name, gchar *descript
button = gtk_toggle_button_new_with_label("x");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *permission & 1 );
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PERMISSION_EXECUTE);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PERMISSION_SEARCH);
gtk_widget_set_size_request(button, 21, -1);
gtk_widget_set_name(button, name);
g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_permission_toggled, (void *) 1);
@@ -948,6 +1026,47 @@ static void xsane_permission_box(GtkWidget *parent, gchar *name, gchar *descript
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMSx
+static void xsane_setup_display_icm_profile_info_callback(GtkWidget *widget, gpointer data)
+{
+ DBG(DBG_proc, "xsane_setup_display_icm_profile_info_callback\n");
+
+ const char* cmsTakeProductName(cmsHPROFILE hProfile);
+ const char* cmsTakeProductDesc(cmsHPROFILE hProfile);
+
+ int cmsTakeRenderingIntent(cmsHPROFILE hProfile);
+
+ #define LCMS_USED_AS_INPUT 0
+ #define LCMS_USED_AS_OUTPUT 1
+ #define LCMS_USED_AS_PROOF 2
+ BOOL cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);
+
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+#ifdef HAVE_LIBLCMS
+static void xsane_setup_browse_printer_icm_profile_callback(GtkWidget *widget, gpointer data)
+{
+ const gchar *old_printer_icm_profile;
+ char printer_icm_profile[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_setup_browse_printer_icm_profile_callback\n");
+
+ old_printer_icm_profile = gtk_entry_get_text(GTK_ENTRY(xsane_setup.printer_icm_profile_entry));
+ strncpy(printer_icm_profile, old_printer_icm_profile, sizeof(printer_icm_profile));
+
+ snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_PRINTER_ICM_PROFILE);
+ xsane_back_gtk_get_filename(windowname, printer_icm_profile, sizeof(printer_icm_profile), printer_icm_profile, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_ICM, XSANE_FILE_FILTER_ICM);
+
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.printer_icm_profile_entry), printer_icm_profile);
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
static void xsane_printer_notebook(GtkWidget *notebook)
{
GtkWidget *setup_vbox, *vbox, *hbox, *button, *label, *text, *frame;
@@ -1273,23 +1392,82 @@ static void xsane_printer_notebook(GtkWidget *notebook)
gtk_widget_show(hbox);
xsane_setup.printer_gamma_blue_entry = text;
+#ifdef HAVE_LIBLCMS
+ xsane_separator_new(vbox, 2);
+
+ /* printer ICM profile: */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_PRINTER_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 70, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_PRINTER_ICM_PROFILE);
+
+ if (preferences.printer[preferences.printernr]->icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.printer[preferences.printernr]->icm_profile);
+ }
+ else
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), "");
+ }
+
+ gtk_box_pack_start(GTK_BOX(hbox), text, TRUE, TRUE, 4);
+ gtk_widget_show(text);
+ xsane_setup.printer_icm_profile_entry = text;
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_printer_icm_profile_callback, NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_PRINTER_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ gtk_widget_show(hbox);
+
+
+ /* embed csa */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+ button = gtk_check_button_new_with_label(TEXT_SETUP_PRINTER_EMBED_CSA);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PRINTER_EMBED_CSA);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.printer[preferences.printernr]->embed_csa);
+ gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
+ gtk_widget_show(button);
+ gtk_widget_show(hbox);
+ xsane_setup.printer_embed_csa_button = button;
+
+ /* embed crd */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+ button = gtk_check_button_new_with_label(TEXT_SETUP_PRINTER_EMBED_CRD);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PRINTER_EMBED_CRD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.printer[preferences.printernr]->embed_crd);
+ gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
+ gtk_widget_show(button);
+ gtk_widget_show(hbox);
+ xsane_setup.printer_embed_crd_button = button;
+#endif
#ifdef HAVE_LIBZ
xsane_separator_new(vbox, 2);
- /* flatdecoded = ps level 3 */
+ /* flatedecoded = ps level 3 */
hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
- button = gtk_check_button_new_with_label(TEXT_SETUP_PRINTER_PS_FLATDECODED);
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PRINTER_PS_FLATDECODED);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.printer[preferences.printernr]->ps_flatdecoded);
+ button = gtk_check_button_new_with_label(TEXT_SETUP_PRINTER_PS_FLATEDECODED);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_PRINTER_PS_FLATEDECODED);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.printer[preferences.printernr]->ps_flatedecoded);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
gtk_widget_show(button);
gtk_widget_show(hbox);
- xsane_setup.printer_ps_flatdecoded_button = button;
+ xsane_setup.printer_ps_flatedecoded_button = button;
#endif
@@ -1336,13 +1514,110 @@ static void xsane_setup_browse_tmp_path_callback(GtkWidget *widget, gpointer dat
strncpy(tmp_path, old_tmp_path, sizeof(tmp_path));
snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_TMP_PATH);
- xsane_back_gtk_get_filename(windowname, tmp_path, sizeof(tmp_path), tmp_path, NULL, TRUE, FALSE, TRUE, FALSE);
+ xsane_back_gtk_get_filename(windowname, tmp_path, sizeof(tmp_path), tmp_path, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_FOLDER, XSANE_GET_FILENAME_SHOW_NOTHING, 0, 0);
gtk_entry_set_text(GTK_ENTRY(xsane_setup.tmp_path_entry), tmp_path);
}
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+static void xsane_setup_browse_scanner_default_color_icm_profile_callback(GtkWidget *widget, gpointer data)
+{
+ const gchar *old_scanner_default_color_icm_profile;
+ char scanner_default_color_icm_profile[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_setup_browse_scanner_default_color_icm_profile_callback\n");
+
+ old_scanner_default_color_icm_profile = gtk_entry_get_text(GTK_ENTRY(xsane_setup.scanner_default_color_icm_profile_entry));
+ strncpy(scanner_default_color_icm_profile, old_scanner_default_color_icm_profile, sizeof(scanner_default_color_icm_profile));
+
+ snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_SCANNER_DEFAULT_COLOR_ICM_PROFILE);
+ xsane_back_gtk_get_filename(windowname, scanner_default_color_icm_profile, sizeof(scanner_default_color_icm_profile), scanner_default_color_icm_profile, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_ICM, XSANE_FILE_FILTER_ICM);
+
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.scanner_default_color_icm_profile_entry), scanner_default_color_icm_profile);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_setup_browse_scanner_default_gray_icm_profile_callback(GtkWidget *widget, gpointer data)
+{
+ const gchar *old_scanner_default_gray_icm_profile;
+ char scanner_default_gray_icm_profile[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_setup_browse_scanner_default_gray_icm_profile_callback\n");
+
+ old_scanner_default_gray_icm_profile = gtk_entry_get_text(GTK_ENTRY(xsane_setup.scanner_default_gray_icm_profile_entry));
+ strncpy(scanner_default_gray_icm_profile, old_scanner_default_gray_icm_profile, sizeof(scanner_default_gray_icm_profile));
+
+ snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_SCANNER_DEFAULT_GRAY_ICM_PROFILE);
+ xsane_back_gtk_get_filename(windowname, scanner_default_gray_icm_profile, sizeof(scanner_default_gray_icm_profile), scanner_default_gray_icm_profile, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_ICM, XSANE_FILE_FILTER_ICM);
+
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.scanner_default_gray_icm_profile_entry), scanner_default_gray_icm_profile);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_setup_browse_display_icm_profile_callback(GtkWidget *widget, gpointer data)
+{
+ const gchar *old_display_icm_profile;
+ char display_icm_profile[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_setup_browse_display_icm_profile_callback\n");
+
+ old_display_icm_profile = gtk_entry_get_text(GTK_ENTRY(xsane_setup.display_icm_profile_entry));
+ strncpy(display_icm_profile, old_display_icm_profile, sizeof(display_icm_profile));
+
+ snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_DISPLAY_ICM_PROFILE);
+ xsane_back_gtk_get_filename(windowname, display_icm_profile, sizeof(display_icm_profile), display_icm_profile, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_ICM, XSANE_FILE_FILTER_ICM);
+
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.display_icm_profile_entry), display_icm_profile);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_setup_browse_custom_proofing_icm_profile_callback(GtkWidget *widget, gpointer data)
+{
+ const gchar *old_custom_proofing_icm_profile;
+ char custom_proofing_icm_profile[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_setup_browse_custom_proofing_icm_profile_callback\n");
+
+ old_custom_proofing_icm_profile = gtk_entry_get_text(GTK_ENTRY(xsane_setup.custom_proofing_icm_profile_entry));
+ strncpy(custom_proofing_icm_profile, old_custom_proofing_icm_profile, sizeof(custom_proofing_icm_profile));
+
+ snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_CUSTOM_PROOFING_ICM_PROFILE);
+ xsane_back_gtk_get_filename(windowname, custom_proofing_icm_profile, sizeof(custom_proofing_icm_profile), custom_proofing_icm_profile, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_ICM, XSANE_FILE_FILTER_ICM);
+
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.custom_proofing_icm_profile_entry), custom_proofing_icm_profile);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_setup_browse_working_color_space_icm_profile_callback(GtkWidget *widget, gpointer data)
+{
+ const gchar *old_working_color_space_icm_profile;
+ char working_color_space_icm_profile[PATH_MAX];
+ char windowname[TEXTBUFSIZE];
+
+ DBG(DBG_proc, "xsane_setup_browse_working_color_space_icm_profile_callback\n");
+
+ old_working_color_space_icm_profile = gtk_entry_get_text(GTK_ENTRY(xsane_setup.working_color_space_icm_profile_entry));
+ strncpy(working_color_space_icm_profile, old_working_color_space_icm_profile, sizeof(working_color_space_icm_profile));
+
+ snprintf(windowname, sizeof(windowname), "%s %s", xsane.prog_name, WINDOW_WORKING_COLOR_SPACE_ICM_PROFILE);
+ xsane_back_gtk_get_filename(windowname, working_color_space_icm_profile, sizeof(working_color_space_icm_profile), working_color_space_icm_profile, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SELECT_OPEN, XSANE_GET_FILENAME_SHOW_NOTHING, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_ICM, XSANE_FILE_FILTER_ICM);
+
+ gtk_entry_set_text(GTK_ENTRY(xsane_setup.working_color_space_icm_profile_entry), working_color_space_icm_profile);
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
static void xsane_saving_notebook(GtkWidget *notebook)
{
GtkWidget *setup_vbox, *vbox, *hbox, *button, *label, *text, *frame;
@@ -1379,7 +1654,7 @@ static void xsane_saving_notebook(GtkWidget *notebook)
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
gtk_widget_show(label);
- text = gtk_entry_new_with_max_length(255);
+ text = gtk_entry_new_with_max_length(PATH_MAX);
gtk_widget_set_size_request(text, 70, -1); /* set minimum size */
xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_TMP_PATH);
gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.tmp_path);
@@ -1615,28 +1890,28 @@ static void xsane_filetype_notebook(GtkWidget *notebook)
#ifdef HAVE_LIBZ
- /* save ps with zlib compression / flatdecode = ps level 3 */
+ /* save ps with zlib compression / flatedecode = ps level 3 */
hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
- button = gtk_check_button_new_with_label(RADIO_BUTTON_SAVE_PS_FLATDECODED);
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_SAVE_PS_FLATDECODED);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.save_ps_flatdecoded);
+ button = gtk_check_button_new_with_label(RADIO_BUTTON_SAVE_PS_FLATEDECODED);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_SAVE_PS_FLATEDECODED);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.save_ps_flatedecoded);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
gtk_widget_show(button);
gtk_widget_show(hbox);
- xsane_setup.save_ps_flatdecoded_button = button;
+ xsane_setup.save_ps_flatedecoded_button = button;
- /* save pdf with zlib compression / flatdecode */
+ /* save pdf with zlib compression / flatedecode */
hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
- button = gtk_check_button_new_with_label(RADIO_BUTTON_SAVE_PDF_FLATDECODED);
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_SAVE_PDF_FLATDECODED);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.save_pdf_flatdecoded);
+ button = gtk_check_button_new_with_label(RADIO_BUTTON_SAVE_PDF_FLATEDECODED);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_SAVE_PDF_FLATEDECODED);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.save_pdf_flatedecoded);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
gtk_widget_show(button);
gtk_widget_show(hbox);
- xsane_setup.save_pdf_flatdecoded_button = button;
+ xsane_setup.save_pdf_flatedecoded_button = button;
#endif
@@ -1656,24 +1931,24 @@ static void xsane_filetype_notebook(GtkWidget *notebook)
#ifdef HAVE_LIBJPEG
xsane_range_new(GTK_BOX(vbox), TEXT_SETUP_JPEG_QUALITY, DESC_JPEG_QUALITY, 0.0, 100.0, 1.0, 10.0, 0,
- &preferences.jpeg_quality, (GtkObject **) &xsane_setup.jpeg_image_quality_scale, 0, TRUE);
+ &preferences.jpeg_quality, &xsane_setup.jpeg_image_quality_scale, 0, TRUE);
#else
#ifdef HAVE_LIBTIFF
xsane_range_new(GTK_BOX(vbox), TEXT_SETUP_JPEG_QUALITY, DESC_JPEG_QUALITY, 0.0, 100.0, 1.0, 10.0, 0,
- &preferences.jpeg_quality, (GtkObject **) &xsane_setup.jpeg_image_quality_scale, 0, TRUE);
+ &preferences.jpeg_quality, &xsane_setup.jpeg_image_quality_scale, 0, TRUE);
#endif
#endif
#ifdef HAVE_LIBPNG
#ifdef HAVE_LIBZ
xsane_range_new(GTK_BOX(vbox), TEXT_SETUP_PNG_COMPRESSION, DESC_PNG_COMPRESSION, 0.0, Z_BEST_COMPRESSION, 1.0, 10.0, 0,
- &preferences.png_compression, (GtkObject **) &xsane_setup.png_image_compression_scale, 0, TRUE);
+ &preferences.png_compression, &xsane_setup.png_image_compression_scale, 0, TRUE);
#endif
#endif
#ifdef HAVE_LIBTIFF
xsane_range_new(GTK_BOX(vbox), TEXT_SETUP_TIFF_ZIP_COMPRESSION, DESC_TIFF_ZIP_COMPRESSION, 1.0, 9.0, 1.0, 6.0, 0,
- &preferences.tiff_zip_compression, (GtkObject **) &xsane_setup.tiff_image_zip_compression_scale, 0, TRUE);
+ &preferences.tiff_zip_compression, &xsane_setup.tiff_image_zip_compression_scale, 0, TRUE);
/* TIFF 16 BIT IMAGES COMPRESSION */
@@ -2083,16 +2358,16 @@ static void xsane_fax_notebook(GtkWidget *notebook)
xsane_separator_new(vbox, 4);
- /* flatdecoded = ps level 3 */
+ /* flatedecoded = ps level 3 */
hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
- button = gtk_check_button_new_with_label(TEXT_SETUP_FAX_PS_FLATDECODED);
- xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_FAX_PS_FLATDECODED);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.fax_ps_flatdecoded);
+ button = gtk_check_button_new_with_label(TEXT_SETUP_FAX_PS_FLATEDECODED);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_FAX_PS_FLATEDECODED);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.fax_ps_flatedecoded);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
gtk_widget_show(button);
gtk_widget_show(hbox);
- xsane_setup.fax_ps_flatdecoded_button = button;
+ xsane_setup.fax_ps_flatedecoded_button = button;
#endif
@@ -3224,6 +3499,355 @@ static void xsane_enhance_notebook(GtkWidget *notebook)
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+static void xsane_color_management_notebook(GtkWidget *notebook)
+{
+ GtkWidget *setup_vbox, *vbox, *hbox, *button, *label, *text, *frame, *option_menu, *menu, *menu_item;
+ int selection = 0;
+
+ DBG(DBG_proc, "xsane_color_management_notebook\n");
+
+ /* color management options notebook page */
+
+ setup_vbox = gtk_vbox_new(FALSE, 5);
+
+ label = gtk_label_new(NOTEBOOK_COLOR_MANAGEMENT_OPTIONS);
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), setup_vbox, label);
+ gtk_widget_show(setup_vbox);
+
+ frame = gtk_frame_new(0);
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 7);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start(GTK_BOX(setup_vbox), frame, TRUE, TRUE, 0); /* sizeable framehight */
+ gtk_widget_show(frame);
+
+ vbox = gtk_vbox_new(FALSE, 1);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ gtk_widget_show(vbox);
+
+
+
+ /* black point compensation */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+ button = gtk_check_button_new_with_label(RADIO_BUTTON_CMS_BPC);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_CMS_BPC);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), preferences.cms_bpc);
+ gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 2);
+ gtk_widget_show(button);
+ gtk_widget_show(hbox);
+ xsane_setup.cms_bpc_button = button;
+
+
+
+ /* Intent menu */
+ hbox = gtk_hbox_new(FALSE, 2);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new(MENU_ITEM_CMS_RENDERING_INTENT);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ option_menu = gtk_option_menu_new();
+ xsane_back_gtk_set_tooltip(xsane.tooltips, option_menu, DESC_RENDERING_INTENT);
+ gtk_box_pack_end(GTK_BOX(hbox), option_menu, FALSE, FALSE, 2);
+ gtk_widget_show(option_menu);
+ gtk_widget_show(hbox);
+
+ menu = gtk_menu_new();
+
+ menu_item = gtk_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_PERCEPTUAL);
+ gtk_object_set_data(GTK_OBJECT(menu_item), "Selection", (void *) INTENT_PERCEPTUAL);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ gtk_widget_show(menu_item);
+
+ menu_item = gtk_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_RELATIVE_COLORIMETRIC);
+ gtk_object_set_data(GTK_OBJECT(menu_item), "Selection", (void *) INTENT_RELATIVE_COLORIMETRIC);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ gtk_widget_show(menu_item);
+
+ menu_item = gtk_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_ABSOLUTE_COLORIMETRIC);
+ gtk_object_set_data(GTK_OBJECT(menu_item), "Selection", (void *) INTENT_ABSOLUTE_COLORIMETRIC);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ gtk_widget_show(menu_item);
+
+ menu_item = gtk_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_SATURATION);
+ gtk_object_set_data(GTK_OBJECT(menu_item), "Selection", (void *) INTENT_SATURATION);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ gtk_widget_show(menu_item);
+
+ if (preferences.cms_intent == INTENT_PERCEPTUAL)
+ {
+ selection = 0;
+ }
+ else if (preferences.cms_intent == INTENT_RELATIVE_COLORIMETRIC)
+ {
+ selection = 1;
+ }
+ else if (preferences.cms_intent == INTENT_ABSOLUTE_COLORIMETRIC)
+ {
+ selection = 2;
+ }
+ else
+ {
+ selection = 3;
+ }
+
+
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), selection);
+ xsane_setup.cms_intent_option_menu = option_menu;
+
+
+ xsane_separator_new(vbox, 4);
+
+
+ /* scanner_default_color_icm_profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_SCANNER_DEFAULT_COLOR_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_scanner_default_color_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_SCANNER_DEFAULT_COLOR_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_SCANNER_DEFAULT_COLOR_ICM_PROFILE);
+
+ if (xsane.scanner_default_color_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) xsane.scanner_default_color_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.scanner_default_color_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+
+
+ /* scanner_default_gray_icm_profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_SCANNER_DEFAULT_GRAY_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_scanner_default_gray_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_SCANNER_DEFAULT_GRAY_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_SCANNER_DEFAULT_GRAY_ICM_PROFILE);
+
+ if (xsane.scanner_default_gray_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) xsane.scanner_default_gray_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.scanner_default_gray_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+
+#if 0
+ xsane_separator_new(vbox, 4);
+
+
+ /* scanner_tran icm-profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_SCANNER_TRAN_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_scanner_tran_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_SCANNER_TRAN_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_SCANNER_TRAN_ICM_PROFILE);
+
+ if (xsane.scanner_tran_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) xsane.scanner_tran_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.scanner_tran_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+
+
+ /* scanner_tran_gray icm-profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_SCANNER_TRAN_GRAY_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_scanner_tran_gray_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_SCANNER_TRAN_GRAY_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_SCANNER_TRAN_GRAY_ICM_PROFILE);
+
+ if (xsane.scanner_tran_gray_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) xsane.scanner_tran_gray_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.scanner_tran_gray_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+#endif
+
+ xsane_separator_new(vbox, 4);
+
+
+ /* display icm-profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_DISPLAY_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_display_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_DISPLAY_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_DISPLAY_ICM_PROFILE);
+
+ if (preferences.display_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.display_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.display_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+
+
+
+ /* custom output icm-profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_CUSTOM_PROOFING_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_custom_proofing_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_CUSTOM_PROOFING_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_CUSTOM_PROOFING_ICM_PROFILE);
+
+ if (preferences.custom_proofing_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.custom_proofing_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.custom_proofing_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+
+
+ xsane_separator_new(vbox, 4);
+
+
+ /* working color space icm-profile filename : */
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+ label = gtk_label_new(TEXT_SETUP_WORKING_COLOR_SPACE_ICM_PROFILE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = gtk_button_new_with_label(BUTTON_BROWSE);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_browse_working_color_space_icm_profile_callback, NULL);
+ gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
+ xsane_back_gtk_set_tooltip(xsane.tooltips, button, DESC_BUTTON_WORKING_COLOR_SPACE_ICM_PROFILE_BROWSE);
+ gtk_widget_show(button);
+
+ text = gtk_entry_new_with_max_length(PATH_MAX);
+ gtk_widget_set_size_request(text, 250, -1); /* set minimum size */
+ xsane_back_gtk_set_tooltip(xsane.tooltips, text, DESC_WORKING_COLOR_SPACE_ICM_PROFILE);
+
+ if (preferences.working_color_space_icm_profile)
+ {
+ gtk_entry_set_text(GTK_ENTRY(text), (char *) preferences.working_color_space_icm_profile);
+ }
+
+ gtk_box_pack_end(GTK_BOX(hbox), text, FALSE, FALSE, 4);
+ gtk_widget_show(text);
+ xsane_setup.working_color_space_icm_profile_entry = text;
+
+ gtk_widget_show(hbox);
+
+
+
+ xsane_separator_new(vbox, 4);
+
+
+
+ /* apply button */
+
+ hbox = gtk_hbox_new(/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+
+#ifdef HAVE_GTK2
+ button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+#else
+ button = gtk_button_new_with_label(BUTTON_APPLY);
+#endif
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_color_management_apply_changes, NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
+ gtk_widget_show(button);
+
+ gtk_widget_show(hbox);
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
void xsane_setup_dialog(GtkWidget *widget, gpointer data)
{
GtkWidget *setup_dialog, *setup_vbox, *hbox, *button, *notebook;
@@ -3267,6 +3891,9 @@ void xsane_setup_dialog(GtkWidget *widget, gpointer data)
xsane_ocr_notebook(notebook);
xsane_display_notebook(notebook);
xsane_enhance_notebook(notebook);
+#ifdef HAVE_LIBLCMS
+ xsane_color_management_notebook(notebook);
+#endif
/* set the main hbox */
@@ -3277,23 +3904,23 @@ void xsane_setup_dialog(GtkWidget *widget, gpointer data)
gtk_widget_show(hbox);
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
- button = gtk_button_new_with_label(BUTTON_OK);
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
- GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_options_ok_callback, setup_dialog);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_close_setup_dialog_callback, setup_dialog);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
- gtk_widget_grab_default(button);
gtk_widget_show(button);
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
+ button = gtk_button_new_with_label(BUTTON_OK);
#endif
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_close_setup_dialog_callback, setup_dialog);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_setup_options_ok_callback, setup_dialog);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
+ gtk_widget_grab_default(button);
gtk_widget_show(button);
gtk_widget_show(setup_dialog);
diff --git a/src/xsane-setup.h b/src/xsane-setup.h
index 8055dfb..155790f 100644
--- a/src/xsane-setup.h
+++ b/src/xsane-setup.h
@@ -3,7 +3,7 @@
xsane-setup.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
diff --git a/src/xsane-text.h b/src/xsane-text.h
index 7614bfc..c271956 100644
--- a/src/xsane-text.h
+++ b/src/xsane-text.h
@@ -3,7 +3,7 @@
xsane-text.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -26,182 +26,193 @@
#define XSANE_TEXT_H
/* Please translate this to the correct directory name (eg. german=>de) */
-#define XSANE_LANGUAGE_DIR _("language_dir")
-
-#define XSANE_STRSTATUS(status) _(sane_strstatus(status))
-#define _BGT(text) dgettext(xsane.backend_translation, text)
-
-#define XSANE_COPYRIGHT_SIGN _("(c)") /* can be translated with \251 */
-
-#define FILENAME_PREFIX_CLONE_OF _("clone-of-")
-
-#define WINDOW_ABOUT_XSANE _("About")
-#define WINDOW_ABOUT_TRANSLATION _("About translation")
-#define WINDOW_AUTHORIZE _("authorization")
-#define WINDOW_GPL _("GPL - the license")
-#define WINDOW_EULA _("End User License Agreement")
-#define WINDOW_INFO _("info")
-#define WINDOW_LOAD_BATCH_LIST _("load batch list")
-#define WINDOW_SAVE_BATCH_LIST _("save batch list")
-#define WINDOW_BATCH_SCAN _("batch scan")
-#define WINDOW_BATCH_RENAME _("rename batch area")
-#define WINDOW_FAX_PROJECT _("fax project")
-#define WINDOW_FAX_RENAME _("rename fax page")
-#define WINDOW_FAX_INSERT _("insert ps-file into fax")
-#define WINDOW_EMAIL_PROJECT _("E-mail project")
-#define WINDOW_EMAIL_RENAME _("rename e-mail image")
-#define WINDOW_EMAIL_INSERT _("insert file into e-mail")
-#define WINDOW_MULTIPAGE_PROJECT _("multipage project")
-#define WINDOW_PRESET_AREA_RENAME _("rename preset area")
-#define WINDOW_PRESET_AREA_ADD _("add preset area")
-#define WINDOW_MEDIUM_RENAME _("rename medium")
-#define WINDOW_MEDIUM_ADD _("add new medium")
-#define WINDOW_SETUP _("setup")
-#define WINDOW_HISTOGRAM _("Histogram")
-#define WINDOW_GAMMA _("Gamma curve")
-#define WINDOW_STANDARD_OPTIONS _("Standard options")
-#define WINDOW_ADVANCED_OPTIONS _("Advanced options")
-#define WINDOW_DEVICE_SELECTION _("device selection")
-#define WINDOW_PREVIEW _("Preview")
-#define WINDOW_VIEWER _("Viewer")
-#define WINDOW_VIEWER_OUTPUT_FILENAME _("Viewer: select output filename")
-#define WINDOW_OCR_OUTPUT_FILENAME _("Select output filename for OCR text file")
-#define WINDOW_OUTPUT_FILENAME _("select output filename")
-#define WINDOW_SAVE_SETTINGS _("save device settings")
-#define WINDOW_LOAD_SETTINGS _("load device settings")
-#define WINDOW_CHANGE_WORKING_DIR _("change working directory")
-#define WINDOW_TMP_PATH _("select temporary directory")
-#define WINDOW_SCALE _("Scale image")
-#define WINDOW_DESPECKLE _("Despeckle image")
-#define WINDOW_BLUR _("Blur image")
-#define WINDOW_STORE_MEDIUM _("Store medium definition")
-#define WINDOW_NO_DEVICES _("No devices available")
-
-#define MENU_FILE _("File")
-#define MENU_PREFERENCES _("Preferences")
-#define MENU_VIEW _("View")
-#define MENU_WINDOW _("Window")
-#define MENU_HELP _("Help")
-#define MENU_EDIT _("Edit")
-#define MENU_FILTERS _("Filters")
-#define MENU_GEOMETRY _("Geometry")
-
-#define MENU_ITEM_ABOUT_XSANE _("About XSane")
-#define MENU_ITEM_ABOUT_TRANSLATION _("About translation")
-#define MENU_ITEM_INFO _("Info")
-#define MENU_ITEM_QUIT _("Quit")
-
-#define MENU_ITEM_SAVE_IMAGE _("Save image")
-#define MENU_ITEM_OCR _("OCR - save as text")
-#define MENU_ITEM_CLONE _("Clone")
-#define MENU_ITEM_SCALE _("Scale")
-#define MENU_ITEM_CLOSE _("Close")
-
-#define MENU_ITEM_UNDO _("Undo")
-
-#define MENU_ITEM_DESPECKLE _("Despeckle")
-#define MENU_ITEM_BLUR _("Blur")
-
-#define MENU_ITEM_ROTATE90 _("Rotate 90")
-#define MENU_ITEM_ROTATE180 _("Rotate 180")
-#define MENU_ITEM_ROTATE270 _("Rotate 270")
-#define MENU_ITEM_MIRROR_X _("Mirror |")
-#define MENU_ITEM_MIRROR_Y _("Mirror -")
-
-#define FRAME_RAW_IMAGE _("Raw image")
-#define FRAME_ENHANCED_IMAGE _("Enhanced image")
-
-#define BUTTON_SCAN _("Scan")
-#define BUTTON_OK _("Ok")
-#define BUTTON_ACCEPT _("Accept")
-#define BUTTON_NOT_ACCEPT _("Not accept")
-#define BUTTON_APPLY _("Apply")
-#define BUTTON_CANCEL _("Cancel")
-#define BUTTON_REDUCE _("Reduce")
-#define BUTTON_CONT_AT_OWN_RISK _("Continue at your own risk")
-#define BUTTON_BROWSE _("Browse")
-#define BUTTON_CLOSE _("Close")
-#define BUTTON_HELP _("Help")
-#define BUTTON_OVERWRITE _("Overwrite")
-#define BUTTON_BATCH_LIST_SCAN _("Scan batch list")
-#define BUTTON_BATCH_AREA_SCAN _("Scan selected area")
-#define BUTTON_PAGE_DELETE _("Delete page")
-#define BUTTON_PAGE_SHOW _("Show page")
-#define BUTTON_PAGE_RENAME _("Rename page")
-#define BUTTON_IMAGE_DELETE _("Delete image")
-#define BUTTON_IMAGE_SHOW _("Show image")
-#define BUTTON_IMAGE_EDIT _("Edit image")
-#define BUTTON_IMAGE_RENAME _("Rename image")
-#define BUTTON_FILE_INSERT _("Insert file")
-#define BUTTON_CREATE_PROJECT _("Create project")
-#define BUTTON_SEND_PROJECT _("Send project")
-#define BUTTON_SAVE_MULTIPAGE _("Save multipage file")
-#define BUTTON_DELETE_PROJECT _("Delete project")
-#define BUTTON_ADD_PRINTER _("Add printer")
-#define BUTTON_DELETE_PRINTER _("Delete printer")
-#define BUTTON_PREVIEW_ACQUIRE _("Acquire preview")
-#define BUTTON_PREVIEW_CANCEL _("Cancel preview")
-#define BUTTON_DISCARD_IMAGE _("Discard image")
-#define BUTTON_DISCARD_ALL_IMAGES _("Discard all images")
-#define BUTTON_DO_NOT_CLOSE _("Do not close")
-#define BUTTON_SCALE_BIND _("Bind scale")
-
-#define RADIO_BUTTON_FINE_MODE _("Fine mode")
-#define RADIO_BUTTON_HTML_EMAIL _("HTML e-mail")
-#define RADIO_BUTTON_SAVE_DEVPREFS_AT_EXIT _("Save device preferences at exit")
-#define RADIO_BUTTON_OVERWRITE_WARNING _("Overwrite warning")
-#define RADIO_BUTTON_SKIP_EXISTING_NRS _("Skip existing filenames")
-#define RADIO_BUTTON_SAVE_PS_FLATDECODED _("Save postscript zlib compressed (ps level 3)")
-#define RADIO_BUTTON_SAVE_PDF_FLATDECODED _("Save PDF zlib compressed")
-#define RADIO_BUTTON_SAVE_PNM16_AS_ASCII _("Save 16bit pnm in ascii format")
-#define RADIO_BUTTON_REDUCE_16BIT_TO_8BIT _("Reduce 16 bit image to 8 bit")
-#define RADIO_BUTTON_WINDOW_FIXED _("Main window size fixed")
-#define RADIO_BUTTON_DISABLE_GIMP_PREVIEW_GAMMA _("Disable gimp preview gamma")
-#define RADIO_BUTTON_PRIVATE_COLORMAP _("Use private colormap")
-#define RADIO_BUTTON_AUTOENHANCE_GAMMA _("Autoenhance gamma")
-#define RADIO_BUTTON_PRESELECT_SCANAREA _("Preselect scanarea")
-#define RADIO_BUTTON_AUTOCORRECT_COLORS _("Autocorrect colors")
-#define RADIO_BUTTON_OCR_USE_GUI_PIPE _("Use GUI progress pipe")
-
-#define TEXT_SCANNING_DEVICES _("scanning for devices")
-#define TEXT_AVAILABLE_DEVICES _("Available devices:")
-#define TEXT_XSANE_OPTIONS _("XSane options")
-#define TEXT_FILETYPE _("Type")
-#define TEXT_SCANNER_BACKEND _("Scanner and backend:")
-#define TEXT_VENDOR _("Vendor:")
-#define TEXT_MODEL _("Model:")
-#define TEXT_TYPE _("Type:")
-#define TEXT_DEVICE _("Device:")
-#define TEXT_LOADED_BACKEND _("Loaded backend:")
-#define TEXT_SANE_VERSION _("Sane version:")
-#define TEXT_RECENT_VALUES _("Recent values:")
-#define TEXT_GAMMA_CORR_BY _("Gamma correction by:")
-#define TEXT_SCANNER _("scanner")
-#define TEXT_SOFTWARE_XSANE _("software (XSane)")
-#define TEXT_NONE _("none")
-#define TEXT_GAMMA_INPUT_DEPTH _("Gamma input depth:")
-#define TEXT_GAMMA_OUTPUT_DEPTH _("Gamma output depth:")
-#define TEXT_SCANNER_OUTPUT_DEPTH _("Scanner output depth:")
-#define TEXT_OUTPUT_FORMATS _("XSane output formats:")
-#define TEXT_8BIT_FORMATS _("8 bit output formats:")
-#define TEXT_16BIT_FORMATS _("16 bit output formats:")
-#define TEXT_GIMP_REDUCE_16BIT_TO_8BIT _("Gimp does not support depth 16 bits/color.\n" \
- "Do you want to reduce the depth to 8 bits/color?")
-#define TEXT_REDUCE_16BIT_TO_8BIT _("Bit depth 16 bits/color is not supported for this output format.\n" \
- "Do you want to reduce the depth to 8 bits/color?")
-#define TEXT_AUTHORIZATION_REQ _("Authorization required for")
-#define TEXT_AUTHORIZATION_SECURE _("Password transmission is secure")
-#define TEXT_AUTHORIZATION_INSECURE _("Backend requests plain-text password")
-#define TEXT_USERNAME _("Username :")
-#define TEXT_PASSWORD _("Password :")
-#define TEXT_INVALID_PARAMS _("Invalid parameters.")
-#define TEXT_VERSION _("version:")
-#define TEXT_PACKAGE _("package")
-#define TEXT_WITH_GIMP_SUPPORT _("with GIMP support")
-#define TEXT_WITHOUT_GIMP_SUPPORT _("without GIMP support")
-#define TEXT_GTK_VERSION _("compiled with GTK-")
-#define TEXT_GIMP_VERSION _("compiled with GIMP-")
-#define TEXT_UNKNOWN _("unknown")
+#define XSANE_LANGUAGE_DIR _("language_dir")
+
+#define XSANE_STRSTATUS(status) _(sane_strstatus(status))
+#define _BGT(text) dgettext(xsane.backend_translation, text)
+
+#define XSANE_COPYRIGHT_SIGN _("(c)") /* can be translated with \251 */
+
+#define FILENAME_PREFIX_CLONE_OF _("clone-of-")
+
+#define WINDOW_ABOUT_XSANE _("About")
+#define WINDOW_ABOUT_TRANSLATION _("About translation")
+#define WINDOW_AUTHORIZE _("authorization")
+#define WINDOW_GPL _("GPL - the license")
+#define WINDOW_EULA _("End User License Agreement")
+#define WINDOW_INFO _("info")
+#define WINDOW_LOAD_BATCH_LIST _("load batch list")
+#define WINDOW_SAVE_BATCH_LIST _("save batch list")
+#define WINDOW_BATCH_SCAN _("batch scan")
+#define WINDOW_BATCH_RENAME _("rename batch area")
+#define WINDOW_FAX_PROJECT _("fax project")
+#define WINDOW_FAX_PROJECT_BROWSE _("browse for fax project")
+#define WINDOW_FAX_RENAME _("rename fax page")
+#define WINDOW_FAX_INSERT _("insert ps-file into fax")
+#define WINDOW_EMAIL_PROJECT _("E-mail project")
+#define WINDOW_EMAIL_PROJECT_BROWSE _("browse for email project")
+#define WINDOW_EMAIL_RENAME _("rename e-mail image")
+#define WINDOW_EMAIL_INSERT _("insert file into e-mail")
+#define WINDOW_MULTIPAGE_PROJECT _("multipage project")
+#define WINDOW_MULTIPAGE_PROJECT_BROWSE _("browse for multipage project")
+#define WINDOW_PRESET_AREA_RENAME _("rename preset area")
+#define WINDOW_PRESET_AREA_ADD _("add preset area")
+#define WINDOW_MEDIUM_RENAME _("rename medium")
+#define WINDOW_MEDIUM_ADD _("add new medium")
+#define WINDOW_SETUP _("setup")
+#define WINDOW_HISTOGRAM _("Histogram")
+#define WINDOW_GAMMA _("Gamma curve")
+#define WINDOW_STANDARD_OPTIONS _("Standard options")
+#define WINDOW_ADVANCED_OPTIONS _("Advanced options")
+#define WINDOW_DEVICE_SELECTION _("device selection")
+#define WINDOW_PREVIEW _("Preview")
+#define WINDOW_VIEWER _("Viewer")
+#define WINDOW_VIEWER_OUTPUT_FILENAME _("Viewer: select output filename")
+#define WINDOW_OCR_OUTPUT_FILENAME _("Select output filename for OCR text file")
+#define WINDOW_OUTPUT_FILENAME _("select output filename")
+#define WINDOW_SAVE_SETTINGS _("save device settings")
+#define WINDOW_LOAD_SETTINGS _("load device settings")
+#define WINDOW_CHANGE_WORKING_DIR _("change working directory")
+#define WINDOW_TMP_PATH _("select temporary directory")
+#define WINDOW_SCALE _("Scale image")
+#define WINDOW_DESPECKLE _("Despeckle image")
+#define WINDOW_BLUR _("Blur image")
+#define WINDOW_STORE_MEDIUM _("Store medium definition")
+#define WINDOW_NO_DEVICES _("No devices available")
+#define WINDOW_SCANNER_DEFAULT_COLOR_ICM_PROFILE _("select scanner default color ICM-profile")
+#define WINDOW_SCANNER_DEFAULT_GRAY_ICM_PROFILE _("select scanner default gray ICM-profile")
+#define WINDOW_DISPLAY_ICM_PROFILE _("select display ICM-profile")
+#define WINDOW_CUSTOM_PROOFING_ICM_PROFILE _("select custom proofing ICM-profile")
+#define WINDOW_WORKING_COLOR_SPACE_ICM_PROFILE _("select working color space ICM-profile")
+#define WINDOW_PRINTER_ICM_PROFILE _("select printer ICM-profile")
+
+#define MENU_FILE _("File")
+#define MENU_PREFERENCES _("Preferences")
+#define MENU_VIEW _("View")
+#define MENU_WINDOW _("Window")
+#define MENU_HELP _("Help")
+#define MENU_EDIT _("Edit")
+#define MENU_FILTERS _("Filters")
+#define MENU_GEOMETRY _("Geometry")
+#define MENU_COLOR_MANAGEMENT _("Color management")
+
+#define MENU_ITEM_ABOUT_XSANE _("About XSane")
+#define MENU_ITEM_ABOUT_TRANSLATION _("About translation")
+#define MENU_ITEM_INFO _("Info")
+#define MENU_ITEM_QUIT _("Quit")
+
+#define MENU_ITEM_SAVE_IMAGE _("Save image")
+#define MENU_ITEM_OCR _("OCR - save as text")
+#define MENU_ITEM_CLONE _("Clone")
+#define MENU_ITEM_SCALE _("Scale")
+#define MENU_ITEM_CLOSE _("Close")
+
+#define MENU_ITEM_UNDO _("Undo")
+
+#define MENU_ITEM_DESPECKLE _("Despeckle")
+#define MENU_ITEM_BLUR _("Blur")
+
+#define MENU_ITEM_ROTATE90 _("Rotate 90")
+#define MENU_ITEM_ROTATE180 _("Rotate 180")
+#define MENU_ITEM_ROTATE270 _("Rotate 270")
+#define MENU_ITEM_MIRROR_X _("Mirror |")
+#define MENU_ITEM_MIRROR_Y _("Mirror -")
+
+#define FRAME_RAW_IMAGE _("Raw image")
+#define FRAME_ENHANCED_IMAGE _("Enhanced image")
+
+#define BUTTON_SCAN _("Scan")
+#define BUTTON_OK _("Ok")
+#define BUTTON_ACCEPT _("Accept")
+#define BUTTON_NOT_ACCEPT _("Not accept")
+#define BUTTON_APPLY _("Apply")
+#define BUTTON_CANCEL _("Cancel")
+#define BUTTON_REDUCE _("Reduce")
+#define BUTTON_CONT_AT_OWN_RISK _("Continue at your own risk")
+#define BUTTON_BROWSE _("Browse")
+#define BUTTON_CLOSE _("Close")
+#define BUTTON_HELP _("Help")
+#define BUTTON_OVERWRITE _("Overwrite")
+#define BUTTON_BATCH_LIST_SCAN _("Scan batch list")
+#define BUTTON_BATCH_AREA_SCAN _("Scan selected area")
+#define BUTTON_PAGE_DELETE _("Delete page")
+#define BUTTON_PAGE_SHOW _("Show page")
+#define BUTTON_PAGE_RENAME _("Rename page")
+#define BUTTON_IMAGE_DELETE _("Delete image")
+#define BUTTON_IMAGE_SHOW _("Show image")
+#define BUTTON_IMAGE_EDIT _("Edit image")
+#define BUTTON_IMAGE_RENAME _("Rename image")
+#define BUTTON_FILE_INSERT _("Insert file")
+#define BUTTON_CREATE_PROJECT _("Create project")
+#define BUTTON_SEND_PROJECT _("Send project")
+#define BUTTON_SAVE_MULTIPAGE _("Save multipage file")
+#define BUTTON_DELETE_PROJECT _("Delete project")
+#define BUTTON_ADD_PRINTER _("Add printer")
+#define BUTTON_DELETE_PRINTER _("Delete printer")
+#define BUTTON_PREVIEW_ACQUIRE _("Acquire preview")
+#define BUTTON_PREVIEW_CANCEL _("Cancel preview")
+#define BUTTON_DISCARD_IMAGE _("Discard image")
+#define BUTTON_DISCARD_ALL_IMAGES _("Discard all images")
+#define BUTTON_DO_NOT_CLOSE _("Do not close")
+#define BUTTON_SCALE_BIND _("Bind scale")
+
+#define RADIO_BUTTON_FINE_MODE _("Fine mode")
+#define RADIO_BUTTON_HTML_EMAIL _("HTML e-mail")
+#define RADIO_BUTTON_SAVE_DEVPREFS_AT_EXIT _("Save device preferences at exit")
+#define RADIO_BUTTON_OVERWRITE_WARNING _("Overwrite warning")
+#define RADIO_BUTTON_SKIP_EXISTING_NRS _("Skip existing filenames")
+#define RADIO_BUTTON_SAVE_PS_FLATEDECODED _("Save postscript zlib compressed (ps level 3)")
+#define RADIO_BUTTON_SAVE_PDF_FLATEDECODED _("Save PDF zlib compressed")
+#define RADIO_BUTTON_SAVE_PNM16_AS_ASCII _("Save 16bit pnm in ascii format")
+#define RADIO_BUTTON_REDUCE_16BIT_TO_8BIT _("Reduce 16 bit image to 8 bit")
+#define RADIO_BUTTON_WINDOW_FIXED _("Main window size fixed")
+#define RADIO_BUTTON_DISABLE_GIMP_PREVIEW_GAMMA _("Disable GIMP preview gamma")
+#define RADIO_BUTTON_PRIVATE_COLORMAP _("Use private colormap")
+#define RADIO_BUTTON_AUTOENHANCE_GAMMA _("Autoenhance gamma")
+#define RADIO_BUTTON_PRESELECT_SCANAREA _("Preselect scanarea")
+#define RADIO_BUTTON_AUTOCORRECT_COLORS _("Autocorrect colors")
+#define RADIO_BUTTON_OCR_USE_GUI_PIPE _("Use GUI progress pipe")
+#define RADIO_BUTTON_CMS_BPC _("Black point compensation")
+
+#define TEXT_SCANNING_DEVICES _("scanning for devices")
+#define TEXT_AVAILABLE_DEVICES _("Available devices:")
+#define TEXT_XSANE_OPTIONS _("XSane options")
+#define TEXT_FILETYPE _("Type")
+#define TEXT_CMS_FUNCTION _("Color management function")
+#define TEXT_SCANNER_BACKEND _("Scanner and backend:")
+#define TEXT_VENDOR _("Vendor:")
+#define TEXT_MODEL _("Model:")
+#define TEXT_TYPE _("Type:")
+#define TEXT_DEVICE _("Device:")
+#define TEXT_LOADED_BACKEND _("Loaded backend:")
+#define TEXT_SANE_VERSION _("Sane version:")
+#define TEXT_RECENT_VALUES _("Recent values:")
+#define TEXT_GAMMA_CORR_BY _("Gamma correction by:")
+#define TEXT_SCANNER _("scanner")
+#define TEXT_SOFTWARE_XSANE _("software (XSane)")
+#define TEXT_NONE _("none")
+#define TEXT_GAMMA_INPUT_DEPTH _("Gamma input depth:")
+#define TEXT_GAMMA_OUTPUT_DEPTH _("Gamma output depth:")
+#define TEXT_SCANNER_OUTPUT_DEPTH _("Scanner output depth:")
+#define TEXT_OUTPUT_FORMATS _("XSane output formats:")
+#define TEXT_8BIT_FORMATS _("8 bit output formats:")
+#define TEXT_16BIT_FORMATS _("16 bit output formats:")
+#define TEXT_REDUCE_16BIT_TO_8BIT _("Bit depth 16 bits/channel is not supported for this output format.\n" \
+ "Do you want to reduce the depth to 8 bits/channel?")
+#define TEXT_AUTHORIZATION_REQ _("Authorization required for")
+#define TEXT_AUTHORIZATION_SECURE _("Password transmission is secure")
+#define TEXT_AUTHORIZATION_INSECURE _("Backend requests plain-text password")
+#define TEXT_USERNAME _("Username :")
+#define TEXT_PASSWORD _("Password :")
+#define TEXT_INVALID_PARAMS _("Invalid parameters.")
+#define TEXT_VERSION _("version:")
+#define TEXT_PACKAGE _("package")
+#define TEXT_WITH_CMS_FUNCTION _("with color management function")
+#define TEXT_WITH_GIMP_SUPPORT _("with GIMP support")
+#define TEXT_WITHOUT_GIMP_SUPPORT _("without GIMP support")
+#define TEXT_GTK_VERSION _("compiled with GTK-")
+#define TEXT_GIMP_VERSION _("compiled with GIMP-")
+#define TEXT_UNKNOWN _("unknown")
#define TEXT_EULA _( "XSane is distributed under the terms of the GNU General Public License\n" \
"as published by the Free Software Foundation; either version 2 of the\n" \
"License, or (at your option) any later version.\n" \
@@ -220,164 +231,196 @@
"This program is distributed in the hope that it will be useful, but\n" \
"WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")
-#define TEXT_EMAIL_ADR _("E-mail:")
-#define TEXT_HOMEPAGE _("Homepage:")
-#define TEXT_FILE _("File:")
-#define TEXT_TRANSLATION _("Translation:")
+#define TEXT_EMAIL_ADR _("E-mail:")
+#define TEXT_HOMEPAGE _("Homepage:")
+#define TEXT_FILE _("File:")
+#define TEXT_TRANSLATION _("Translation:")
/* Please translate this to something like */
/* translation to YOUR LANGUAGE\n */
/* by YOUR NAME\n */
/* E-mail: your.name@yourdomain.com\n */
-#define TEXT_TRANSLATION_INFO _("untranslated original english text\n" \
- "by Oliver Rauch\n" \
- "E-mail: Oliver.Rauch@rauch-domain.de\n")
-
-#define TEXT_INFO_BOX _("0x0: 0KB")
-
-#define TEXT_ADF_PAGES_SCANNED _("Scanned pages: ")
-
-#define TEXT_EMAIL_TEXT _("E-mail text:")
-#define TEXT_ATTACHMENTS _("Attachments:")
-#define TEXT_EMAIL_STATUS _("Project status:")
-#define TEXT_EMAIL_FILETYPE _("E-mail image filetype:")
-
-#define TEXT_PAGES _("Pages:")
-#define TEXT_MULTIPAGE_FILETYPE _("Multipage document filetype:")
-
-#define TEXT_MEDIUM_DEFINITION_NAME _("Medium Name:")
-
-#define TEXT_VIEWER_IMAGE_INFO _("Size %d x %d pixel, %d bit/color, %d colors, %1.0f dpi x %1.0f dpi, %1.1f %s")
-#define TEXT_DESPECKLE_RADIUS _("Despeckle radius:")
-#define TEXT_BLUR_RADIUS _("Blur radius:")
-#define TEXT_BATCH_AREA_DEFAULT_NAME _("(no name)")
-#define TEXT_BATCH_LIST_AREANAME _("Area name:")
-#define TEXT_BATCH_LIST_SCANMODE _("Scanmode:")
-#define TEXT_BATCH_LIST_GEOMETRY_TL _("Top left:")
-#define TEXT_BATCH_LIST_GEOMETRY_SIZE _("Size:")
-#define TEXT_BATCH_LIST_RESOLUTION _("Resolution:")
-#define TEXT_BATCH_LIST_BIT_DEPTH _("Bit depth:")
-#define TEXT_BATCH_LIST_BY_GUI _("as selected")
-
-#define TEXT_SETUP_PRINTER_SEL _("Printer selection:")
-#define TEXT_SETUP_PRINTER_NAME _("Name:")
-#define TEXT_SETUP_PRINTER_CMD _("Command:")
-#define TEXT_SETUP_COPY_NR_OPT _("Copy number option:")
-#define TEXT_SETUP_PRINTER_LINEART_RES _("Lineart resolution (dpi):")
-#define TEXT_SETUP_PRINTER_GRAYSCALE_RES _("Grayscale resolution (dpi):")
-#define TEXT_SETUP_PRINTER_COLOR_RES _("Color resolution (dpi):")
-#define TEXT_SETUP_PRINTER_WIDTH _("Width")
-#define TEXT_SETUP_PRINTER_HEIGHT _("Height")
-#define TEXT_SETUP_PRINTER_LEFT _("Left offset")
-#define TEXT_SETUP_PRINTER_BOTTOM _("Bottom offset")
-#define TEXT_SETUP_PRINTER_GAMMA _("Printer gamma value:")
-#define TEXT_SETUP_PRINTER_GAMMA_RED _("Printer gamma red:")
-#define TEXT_SETUP_PRINTER_GAMMA_GREEN _("Printer gamma green:")
-#define TEXT_SETUP_PRINTER_GAMMA_BLUE _("Printer gamma blue:")
-#define TEXT_SETUP_PRINTER_PS_FLATDECODED _("Create zlib compressed postscript image (ps level 3) for printing")
-#define TEXT_SETUP_TMP_PATH _("Temporary directory")
-#define TEXT_SETUP_IMAGE_PERMISSION _("Image-file permissions")
-#define TEXT_SETUP_DIR_PERMISSION _("Directory permissions")
-#define TEXT_SETUP_JPEG_QUALITY _("JPEG image quality")
-#define TEXT_SETUP_PNG_COMPRESSION _("PNG image compression")
-#define TEXT_SETUP_FILENAME_COUNTER_LEN _("Filename counter length")
-#define TEXT_SETUP_TIFF_ZIP_COMPRESSION _("TIFF zip compression rate")
-#define TEXT_SETUP_TIFF_COMPRESSION_16 _("TIFF 16 bit image compression")
-#define TEXT_SETUP_TIFF_COMPRESSION_8 _("TIFF 8 bit image compression")
-#define TEXT_SETUP_TIFF_COMPRESSION_1 _("TIFF lineart image compression")
-#define TEXT_SETUP_SHOW_RANGE_MODE _("Show range as:")
-#define TEXT_SETUP_PREVIEW_OVERSAMPLING _("Preview oversampling:")
-#define TEXT_SETUP_PREVIEW_GAMMA _("Preview gamma:")
-#define TEXT_SETUP_PREVIEW_GAMMA_RED _("Preview gamma red:")
-#define TEXT_SETUP_PREVIEW_GAMMA_GREEN _("Preview gamma green:")
-#define TEXT_SETUP_PREVIEW_GAMMA_BLUE _("Preview gamma blue:")
-#define TEXT_SETUP_LINEART_MODE _("Threshold option:")
-#define TEXT_SETUP_PREVIEW_PIPETTE_RANGE _("Preview pipette range")
-#define TEXT_SETUP_THRESHOLD_MIN _("Threshold minimum:")
-#define TEXT_SETUP_THRESHOLD_MAX _("Threshold maximum:")
-#define TEXT_SETUP_THRESHOLD_MUL _("Threshold multiplier:")
-#define TEXT_SETUP_THRESHOLD_OFF _("Threshold offset:")
-#define TEXT_SETUP_GRAYSCALE_SCANMODE _("Name of grayscale scanmode:")
-#define TEXT_SETUP_HELPFILE_VIEWER _("Helpfile viewer (HTML):")
-#define TEXT_SETUP_FAX_COMMAND _("Command:")
-#define TEXT_SETUP_FAX_RECEIVER_OPTION _("Receiver option:")
-#define TEXT_SETUP_FAX_POSTSCRIPT_OPT _("Postscriptfile option:")
-#define TEXT_SETUP_FAX_NORMAL_MODE_OPT _("Normal mode option:")
-#define TEXT_SETUP_FAX_FINE_MODE_OPT _("Fine mode option:")
-#define TEXT_SETUP_FAX_PROGRAM_DEFAULTS _("Set program defaults for:")
-#define TEXT_SETUP_FAX_VIEWER _("Viewer (Postscript):")
-#define TEXT_SETUP_FAX_WIDTH _("Width")
-#define TEXT_SETUP_FAX_HEIGHT _("Height")
-#define TEXT_SETUP_FAX_LEFT _("Left offset")
-#define TEXT_SETUP_FAX_BOTTOM _("Bottom offset")
-#define TEXT_SETUP_FAX_PS_FLATDECODED _("Create zlib compressed postscript image (ps level 3) for fax")
-#define TEXT_SETUP_SMTP_SERVER _("SMTP server:")
-#define TEXT_SETUP_SMTP_PORT _("SMTP port:")
-#define TEXT_SETUP_EMAIL_FROM _("From:")
-#define TEXT_SETUP_EMAIL_REPLY_TO _("Reply to:")
-#define TEXT_SETUP_EMAIL_AUTHENTICATION _("E-mail authentication")
-#define TEXT_SETUP_EMAIL_AUTH_USER _("User:")
-#define TEXT_SETUP_EMAIL_AUTH_PASS _("Password:")
-#define TEXT_SETUP_POP3_SERVER _("POP3 server:")
-#define TEXT_SETUP_POP3_PORT _("POP3 port:")
-#define TEXT_SETUP_OCR_COMMAND _("OCR Command:")
-#define TEXT_SETUP_OCR_INPUTFILE_OPT _("Inputfile option:")
-#define TEXT_SETUP_OCR_OUTPUTFILE_OPT _("Outputfile option:")
-#define TEXT_SETUP_OCR_USE_GUI_PIPE_OPT _("Use GUI progress pipe:")
-#define TEXT_SETUP_OCR_OUTFD_OPT _("GUI output-fd option:")
-#define TEXT_SETUP_OCR_PROGRESS_KEYWORD _("Progress keyword:")
-#define TEXT_SETUP_PERMISSION_USER _("user")
-#define TEXT_SETUP_PERMISSION_GROUP _("group")
-#define TEXT_SETUP_PERMISSION_ALL _("all")
-#define TEXT_NEW_MEDIA_NAME _("new media")
-
-#define NOTEBOOK_SAVING_OPTIONS _("Save")
-#define NOTEBOOK_FILETYPE_OPTIONS _("Filetype")
-#define NOTEBOOK_COPY_OPTIONS _("Copy")
-#define NOTEBOOK_FAX_OPTIONS _("Fax")
-#define NOTEBOOK_EMAIL_OPTIONS _("E-mail")
-#define NOTEBOOK_OCR_OPTIONS _("OCR")
-#define NOTEBOOK_DISPLAY_OPTIONS _("Display")
-#define NOTEBOOK_ENHANCE_OPTIONS _("Enhancement")
-
-#define MENU_ITEM_SAVE _("Save")
-#define MENU_ITEM_VIEWER _("Viewer")
-#define MENU_ITEM_COPY _("Copy")
-#define MENU_ITEM_MULTIPAGE _("Multipage")
-#define MENU_ITEM_FAX _("Fax")
-#define MENU_ITEM_EMAIL _("E-mail")
-
-#define MENU_ITEM_SHOW_TOOLTIPS _("Show tooltips")
-#define MENU_ITEM_SHOW_PREVIEW _("Show preview")
-#define MENU_ITEM_SHOW_HISTOGRAM _("Show histogram")
-#define MENU_ITEM_SHOW_GAMMA _("Show gamma curve")
-#define MENU_ITEM_SHOW_BATCH_SCAN _("Show batch scan")
-#define MENU_ITEM_SHOW_STANDARDOPTIONS _("Show standard options")
-#define MENU_ITEM_SHOW_ADVANCEDOPTIONS _("Show advanced options")
-
-#define MENU_ITEM_SETUP _("Setup")
-#define MENU_ITEM_LENGTH_UNIT _("Length unit")
-#define SUBMENU_ITEM_LENGTH_MILLIMETERS _("millimeters")
-#define SUBMENU_ITEM_LENGTH_CENTIMETERS _("centimeters")
-#define SUBMENU_ITEM_LENGTH_INCHES _("inches")
-#define MENU_ITEM_UPDATE_POLICY _("Update policy")
-#define SUBMENU_ITEM_POLICY_CONTINUOUS _("continuous")
-#define SUBMENU_ITEM_POLICY_DISCONTINU _("discontinuous")
-#define SUBMENU_ITEM_POLICY_DELAYED _("delayed")
-#define MENU_ITEM_SHOW_RESOLUTIONLIST _("Show resolution list")
-#define MENU_ITEM_PAGE_ROTATE _("Rotate postscript")
-#define MENU_ITEM_EDIT_MEDIUM_DEF _("Edit medium definition")
-#define MENU_ITEM_SAVE_DEVICE_SETTINGS _("Save device settings")
-#define MENU_ITEM_LOAD_DEVICE_SETTINGS _("Load device settings")
-#define MENU_ITEM_CHANGE_WORKING_DIR _("Change directory")
-
-#define MENU_ITEM_XSANE_EULA _("Show EULA")
-#define MENU_ITEM_XSANE_GPL _("Show license (GPL)")
-#define MENU_ITEM_XSANE_DOC _("XSane doc")
-#define MENU_ITEM_BACKEND_DOC _("Backend doc")
-#define MENU_ITEM_AVAILABLE_BACKENDS _("Available backends")
-#define MENU_ITEM_SCANTIPS _("Scantips")
-#define MENU_ITEM_PROBLEMS _("Problems?")
+#define TEXT_TRANSLATION_INFO _("untranslated original english text\n" \
+ "by Oliver Rauch\n" \
+ "E-mail: Oliver.Rauch@rauch-domain.de\n")
+
+#define TEXT_INFO_BOX _("0x0: 0KB")
+
+#define TEXT_ADF_PAGES_SCANNED _("Scanned pages: ")
+
+#define TEXT_EMAIL_TEXT _("E-mail text:")
+#define TEXT_ATTACHMENTS _("Attachments:")
+#define TEXT_EMAIL_STATUS _("Project status:")
+#define TEXT_EMAIL_FILETYPE _("E-mail image filetype:")
+
+#define TEXT_PAGES _("Pages:")
+#define TEXT_MULTIPAGE_FILETYPE _("Multipage document filetype:")
+
+#define TEXT_MEDIUM_DEFINITION_NAME _("Medium Name:")
+
+#define TEXT_VIEWER_IMAGE_INFO _("Size %d x %d pixel, %d bits/channel, %d channels, %1.0f dpi x %1.0f dpi, %1.1f %s")
+#define TEXT_DESPECKLE_RADIUS _("Despeckle radius:")
+#define TEXT_BLUR_RADIUS _("Blur radius:")
+#define TEXT_BATCH_AREA_DEFAULT_NAME _("(no name)")
+#define TEXT_BATCH_LIST_AREANAME _("Area name:")
+#define TEXT_BATCH_LIST_SCANMODE _("Scanmode:")
+#define TEXT_BATCH_LIST_GEOMETRY_TL _("Top left:")
+#define TEXT_BATCH_LIST_GEOMETRY_SIZE _("Size:")
+#define TEXT_BATCH_LIST_RESOLUTION _("Resolution:")
+#define TEXT_BATCH_LIST_BIT_DEPTH _("Bit depth:")
+#define TEXT_BATCH_LIST_BY_GUI _("as selected")
+
+#define TEXT_SETUP_PRINTER_SEL _("Printer selection:")
+#define TEXT_SETUP_PRINTER_NAME _("Name:")
+#define TEXT_SETUP_PRINTER_CMD _("Command:")
+#define TEXT_SETUP_COPY_NR_OPT _("Copy number option:")
+#define TEXT_SETUP_PRINTER_LINEART_RES _("Lineart resolution (dpi):")
+#define TEXT_SETUP_PRINTER_GRAYSCALE_RES _("Grayscale resolution (dpi):")
+#define TEXT_SETUP_PRINTER_COLOR_RES _("Color resolution (dpi):")
+#define TEXT_SETUP_PRINTER_WIDTH _("Width")
+#define TEXT_SETUP_PRINTER_HEIGHT _("Height")
+#define TEXT_SETUP_PRINTER_LEFT _("Left offset")
+#define TEXT_SETUP_PRINTER_BOTTOM _("Bottom offset")
+#define TEXT_SETUP_PRINTER_GAMMA _("Printer gamma value:")
+#define TEXT_SETUP_PRINTER_GAMMA_RED _("Printer gamma red:")
+#define TEXT_SETUP_PRINTER_GAMMA_GREEN _("Printer gamma green:")
+#define TEXT_SETUP_PRINTER_GAMMA_BLUE _("Printer gamma blue:")
+#define TEXT_SETUP_PRINTER_EMBED_CSA _("Embed scanner ICM profile as CSA")
+#define TEXT_SETUP_PRINTER_EMBED_CRD _("Embed printer ICM profile as CRD")
+#define TEXT_SETUP_PRINTER_PS_FLATEDECODED _("Create zlib compressed postscript image (ps level 3) for printing")
+#define TEXT_SETUP_TMP_PATH _("Temporary directory")
+#define TEXT_SETUP_IMAGE_PERMISSION _("Image-file permissions")
+#define TEXT_SETUP_DIR_PERMISSION _("Directory permissions")
+#define TEXT_SETUP_JPEG_QUALITY _("JPEG image quality")
+#define TEXT_SETUP_PNG_COMPRESSION _("PNG image compression")
+#define TEXT_SETUP_FILENAME_COUNTER_LEN _("Filename counter length")
+#define TEXT_SETUP_TIFF_ZIP_COMPRESSION _("TIFF zip compression rate")
+#define TEXT_SETUP_TIFF_COMPRESSION_16 _("TIFF 16 bit image compression")
+#define TEXT_SETUP_TIFF_COMPRESSION_8 _("TIFF 8 bit image compression")
+#define TEXT_SETUP_TIFF_COMPRESSION_1 _("TIFF lineart image compression")
+#define TEXT_SETUP_SHOW_RANGE_MODE _("Show range as:")
+#define TEXT_SETUP_PREVIEW_OVERSAMPLING _("Preview oversampling:")
+#define TEXT_SETUP_PREVIEW_GAMMA _("Preview gamma:")
+#define TEXT_SETUP_PREVIEW_GAMMA_RED _("Preview gamma red:")
+#define TEXT_SETUP_PREVIEW_GAMMA_GREEN _("Preview gamma green:")
+#define TEXT_SETUP_PREVIEW_GAMMA_BLUE _("Preview gamma blue:")
+#define TEXT_SETUP_LINEART_MODE _("Threshold option:")
+#define TEXT_SETUP_PREVIEW_PIPETTE_RANGE _("Preview pipette range")
+#define TEXT_SETUP_THRESHOLD_MIN _("Threshold minimum:")
+#define TEXT_SETUP_THRESHOLD_MAX _("Threshold maximum:")
+#define TEXT_SETUP_THRESHOLD_MUL _("Threshold multiplier:")
+#define TEXT_SETUP_THRESHOLD_OFF _("Threshold offset:")
+#define TEXT_SETUP_GRAYSCALE_SCANMODE _("Name of grayscale scanmode:")
+#define TEXT_SETUP_HELPFILE_VIEWER _("Helpfile viewer (HTML):")
+#define TEXT_SETUP_FAX_COMMAND _("Command:")
+#define TEXT_SETUP_FAX_RECEIVER_OPTION _("Receiver option:")
+#define TEXT_SETUP_FAX_POSTSCRIPT_OPT _("Postscriptfile option:")
+#define TEXT_SETUP_FAX_NORMAL_MODE_OPT _("Normal mode option:")
+#define TEXT_SETUP_FAX_FINE_MODE_OPT _("Fine mode option:")
+#define TEXT_SETUP_FAX_PROGRAM_DEFAULTS _("Set program defaults for:")
+#define TEXT_SETUP_FAX_VIEWER _("Viewer (Postscript):")
+#define TEXT_SETUP_FAX_WIDTH _("Width")
+#define TEXT_SETUP_FAX_HEIGHT _("Height")
+#define TEXT_SETUP_FAX_LEFT _("Left offset")
+#define TEXT_SETUP_FAX_BOTTOM _("Bottom offset")
+#define TEXT_SETUP_FAX_PS_FLATEDECODED _("Create zlib compressed postscript image (ps level 3) for fax")
+#define TEXT_SETUP_SMTP_SERVER _("SMTP server:")
+#define TEXT_SETUP_SMTP_PORT _("SMTP port:")
+#define TEXT_SETUP_EMAIL_FROM _("From:")
+#define TEXT_SETUP_EMAIL_REPLY_TO _("Reply to:")
+#define TEXT_SETUP_EMAIL_AUTHENTICATION _("E-mail authentication")
+#define TEXT_SETUP_EMAIL_AUTH_USER _("User:")
+#define TEXT_SETUP_EMAIL_AUTH_PASS _("Password:")
+#define TEXT_SETUP_POP3_SERVER _("POP3 server:")
+#define TEXT_SETUP_POP3_PORT _("POP3 port:")
+#define TEXT_SETUP_OCR_COMMAND _("OCR Command:")
+#define TEXT_SETUP_OCR_INPUTFILE_OPT _("Inputfile option:")
+#define TEXT_SETUP_OCR_OUTPUTFILE_OPT _("Outputfile option:")
+#define TEXT_SETUP_OCR_USE_GUI_PIPE_OPT _("Use GUI progress pipe:")
+#define TEXT_SETUP_OCR_OUTFD_OPT _("GUI output-fd option:")
+#define TEXT_SETUP_OCR_PROGRESS_KEYWORD _("Progress keyword:")
+#define TEXT_SETUP_PERMISSION_USER _("user")
+#define TEXT_SETUP_PERMISSION_GROUP _("group")
+#define TEXT_SETUP_PERMISSION_ALL _("all")
+#define TEXT_SETUP_SCANNER_DEFAULT_COLOR_ICM_PROFILE _("Scanner default color ICM-profile")
+#define TEXT_SETUP_SCANNER_DEFAULT_GRAY_ICM_PROFILE _("Scanner default gray ICM-profile")
+#define TEXT_SETUP_DISPLAY_ICM_PROFILE _("Display ICM-profile")
+#define TEXT_SETUP_CUSTOM_PROOFING_ICM_PROFILE _("Custom proofing ICM-profile")
+#define TEXT_SETUP_WORKING_COLOR_SPACE_ICM_PROFILE _("Working color space ICM-profile")
+#define TEXT_SETUP_PRINTER_ICM_PROFILE _("Printer ICM-profile")
+#define TEXT_NEW_MEDIA_NAME _("new media")
+
+#define NOTEBOOK_SAVING_OPTIONS _("Save")
+#define NOTEBOOK_FILETYPE_OPTIONS _("Filetype")
+#define NOTEBOOK_COPY_OPTIONS _("Copy")
+#define NOTEBOOK_FAX_OPTIONS _("Fax")
+#define NOTEBOOK_EMAIL_OPTIONS _("E-mail")
+#define NOTEBOOK_OCR_OPTIONS _("OCR")
+#define NOTEBOOK_DISPLAY_OPTIONS _("Display")
+#define NOTEBOOK_ENHANCE_OPTIONS _("Enhancement")
+#define NOTEBOOK_COLOR_MANAGEMENT_OPTIONS _("Color management")
+
+#define MENU_ITEM_SAVE _("Save")
+#define MENU_ITEM_VIEWER _("Viewer")
+#define MENU_ITEM_COPY _("Copy")
+#define MENU_ITEM_MULTIPAGE _("Multipage")
+#define MENU_ITEM_FAX _("Fax")
+#define MENU_ITEM_EMAIL _("E-mail")
+
+#define MENU_ITEM_SHOW_TOOLTIPS _("Show tooltips")
+#define MENU_ITEM_SHOW_PREVIEW _("Show preview")
+#define MENU_ITEM_SHOW_HISTOGRAM _("Show histogram")
+#define MENU_ITEM_SHOW_GAMMA _("Show gamma curve")
+#define MENU_ITEM_SHOW_BATCH_SCAN _("Show batch scan")
+#define MENU_ITEM_SHOW_STANDARDOPTIONS _("Show standard options")
+#define MENU_ITEM_SHOW_ADVANCEDOPTIONS _("Show advanced options")
+
+#define MENU_ITEM_SETUP _("Setup")
+#define MENU_ITEM_LENGTH_UNIT _("Length unit")
+#define SUBMENU_ITEM_LENGTH_MILLIMETERS _("millimeters")
+#define SUBMENU_ITEM_LENGTH_CENTIMETERS _("centimeters")
+#define SUBMENU_ITEM_LENGTH_INCHES _("inches")
+#define MENU_ITEM_UPDATE_POLICY _("Update policy")
+#define SUBMENU_ITEM_POLICY_CONTINUOUS _("continuous")
+#define SUBMENU_ITEM_POLICY_DISCONTINU _("discontinuous")
+#define SUBMENU_ITEM_POLICY_DELAYED _("delayed")
+#define MENU_ITEM_SHOW_RESOLUTIONLIST _("Show resolution list")
+#define MENU_ITEM_PAGE_ROTATE _("Rotate postscript")
+#define MENU_ITEM_ENABLE_COLOR_MANAGEMENT _("Enable color management")
+#define MENU_ITEM_EDIT_MEDIUM_DEF _("Edit medium definition")
+#define MENU_ITEM_SAVE_DEVICE_SETTINGS _("Save device settings")
+#define MENU_ITEM_LOAD_DEVICE_SETTINGS _("Load device settings")
+#define MENU_ITEM_CHANGE_WORKING_DIR _("Change directory")
+
+#define MENU_ITEM_XSANE_EULA _("Show EULA")
+#define MENU_ITEM_XSANE_GPL _("Show license (GPL)")
+#define MENU_ITEM_XSANE_DOC _("XSane doc")
+#define MENU_ITEM_BACKEND_DOC _("Backend doc")
+#define MENU_ITEM_AVAILABLE_BACKENDS _("Available backends")
+#define MENU_ITEM_SCANTIPS _("Scantips")
+#define MENU_ITEM_PROBLEMS _("Problems?")
+
+
+#define MENU_ITEM_CMS_ENABLE_COLOR_MANAGEMENT _("Enable color management")
+#define MENU_ITEM_CMS_BLACK_POINT_COMPENSATION _("Black point compensation")
+#define MENU_ITEM_CMS_PROOFING _("Proofing")
+#define SUBMENU_ITEM_CMS_PROOF_OFF _("no proofing (Display)")
+#define SUBMENU_ITEM_CMS_PROOF_PRINTER _("Proof printer")
+#define SUBMENU_ITEM_CMS_PROOF_CUSTOM _("Proof custom device")
+#define MENU_ITEM_CMS_RENDERING_INTENT _("Rendering intent")
+#define MENU_ITEM_CMS_PROOFING_INTENT _("Proofing rendering intent")
+#define SUBMENU_ITEM_CMS_INTENT_PERCEPTUAL _("Perceptual")
+#define SUBMENU_ITEM_CMS_INTENT_RELATIVE_COLORIMETRIC _("Relative colorimetric")
+#define SUBMENU_ITEM_CMS_INTENT_ABSOLUTE_COLORIMETRIC _("Absolute colorimentric")
+#define SUBMENU_ITEM_CMS_INTENT_SATURATION _("Saturation")
+#define MENU_ITEM_CMS_GAMUT_CHECK _("Gamut check")
+#define MENU_ITEM_CMS_GAMUT_ALARM_COLOR _("Gamut alarm color")
+#define SUBMENU_ITEM_CMS_COLOR_BLACK _("Black")
+#define SUBMENU_ITEM_CMS_COLOR_GRAY _("Gray")
+#define SUBMENU_ITEM_CMS_COLOR_WHITE _("White")
+#define SUBMENU_ITEM_CMS_COLOR_RED _("Red")
+#define SUBMENU_ITEM_CMS_COLOR_GREEN _("Green")
+#define SUBMENU_ITEM_CMS_COLOR_BLUE _("Blue")
#define MENU_ITEM_COUNTER_LEN_INACTIVE _("inactive")
#define MENU_ITEM_TIFF_COMP_NONE _("no compression")
@@ -415,6 +458,10 @@
#define MENU_ITEM_AUTH_ASMTP_LOGIN _("ASMTP Login")
#define MENU_ITEM_AUTH_ASMTP_CRAM_MD5 _("ASMTP CRAM-MD5")
+#define MENU_ITEM_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE _("Embed scanner ICM profile")
+#define MENU_ITEM_CMS_FUNCTION_CONVERT_TO_SRGB _("Convert to sRGB")
+#define MENU_ITEM_FUNCTION_CONVERT_TO_WORKING_CS _("Convert to working color space")
+
#define PROGRESS_SCANNING _("Scanning")
#define PROGRESS_RECEIVING_FRAME_DATA _("Receiving %s data")
#define PROGRESS_PAGE _("page")
@@ -430,6 +477,7 @@
#define PROGRESS_DESPECKLING_DATA _("Despeckling image")
#define PROGRESS_BLURING_DATA _("Bluring image")
#define PROGRESS_OCR _("OCR in progress")
+#define PROGRESS_ICM_CONVERSION _("converting colors")
#define DESC_SCAN_START _("Start scan <Ctrl-Enter>")
#define DESC_SCAN_CANCEL _("Cancel scan <ESC>")
@@ -445,15 +493,18 @@
#define DESC_BROWSE_FILENAME _("Browse for image filename")
#define DESC_FILENAME _("Filename for scanned image")
#define DESC_FILETYPE _("Type of image format, the suitable filename extension is automatically added to the filename")
-#define DESC_FAXPROJECT _("Enter name of fax project")
+#define DESC_FAXPROJECT _("Enter fax project directory name")
#define DESC_FAXPAGENAME _("Enter new name for faxpage")
#define DESC_FAXRECEIVER _("Enter receiver phone number or address")
-#define DESC_EMAIL_PROJECT _("Enter name of e-mail project")
+#define DESC_FAX_PROJECT_BROWSE _("Browse for fax project directory")
+#define DESC_EMAIL_PROJECT _("Enter e-mail project directory name")
#define DESC_EMAIL_IMAGENAME _("Enter new name for e-mail image")
#define DESC_EMAIL_RECEIVER _("Enter e-mail address")
+#define DESC_EMAIL_PROJECT_BROWSE _("Browse for email project directory")
#define DESC_EMAIL_SUBJECT _("Enter subject of e-mail")
#define DESC_EMAIL_FILETYPE _("Select filetype for image attachments")
-#define DESC_MULTIPAGE_PROJECT _("Enter name of multipage project")
+#define DESC_MULTIPAGE_PROJECT _("Enter multipage project directory name")
+#define DESC_MULTIPAGE_PROJECT_BROWSE _("Browse for multipage project directory")
#define DESC_MULTIPAGE_FILETYPE _("Select filetype for multipage file")
#define DESC_PRESET_AREA_RENAME _("Enter new name for preset area")
#define DESC_PRESET_AREA_ADD _("Enter name for new preset area")
@@ -495,7 +546,7 @@
" brightness = 0\n" \
" contrast = 0")
-#define DESC_ENH_AUTO _("Autoadjust gamma, brightness and contrast <Ctrl-e>")
+#define DESC_ENH_AUTO _("Autoadjust gamma, brightness and contrast <Ctrl-a>")
#define DESC_ENH_DEFAULT _("Set default enhancement values <Ctrl-0>:\n" \
"gamma = 1.0\n" \
"brightness = 0\n" \
@@ -525,7 +576,9 @@
#define DESC_PRINTER_GAMMA_RED _("Additional gamma value for red component for photocopy")
#define DESC_PRINTER_GAMMA_GREEN _("Additional gamma value for green component for photocopy")
#define DESC_PRINTER_GAMMA_BLUE _("Additional gamma value for blue component for photocopy")
-#define DESC_PRINTER_PS_FLATDECODED _("Create zlib compressed postscript image for printer (flatdecode).\n" \
+#define DESC_PRINTER_EMBED_CSA _("Creates a postsciptfile that contains the ICM profile of the scanner")
+#define DESC_PRINTER_EMBED_CRD _("Creates a postsciptfile that contains the ICM profile of the printer")
+#define DESC_PRINTER_PS_FLATEDECODED _("Create zlib compressed postscript image for printer (flatedecode).\n" \
"The printer has to understand postscript level 3!")
#define DESC_TMP_PATH _("Path to temp directory")
#define DESC_BUTTON_TMP_PATH_BROWSE _("Browse for temporary directory")
@@ -539,20 +592,20 @@
#define DESC_SAVE_DEVPREFS_AT_EXIT _("Save device dependant preferences in default file at exit of xsane")
#define DESC_OVERWRITE_WARNING _("Warn before overwriting an existing file")
#define DESC_SKIP_EXISTING _("If filename counter is automatically increased, used numbers are skipped")
-#define DESC_SAVE_PS_FLATDECODED _("compress postscript image with zlib algorithm (flatdecode). " \
+#define DESC_SAVE_PS_FLATEDECODED _("compress postscript image with zlib algorithm (flatedecode). " \
"When you want to print such a file your printer has to understand postscript level 3")
-#define DESC_SAVE_PDF_FLATDECODED _("compress PDF image with zlib algorithm (flatdecode).")
+#define DESC_SAVE_PDF_FLATEDECODED _("compress PDF image with zlib algorithm (flatedecode).")
#define DESC_SAVE_PNM16_AS_ASCII _("When a 16 bit image shall be saved in pnm format then use ascii format " \
"instead of binary format. The binary format is a new format that is not " \
"supported by all programs. The ascii format is supported by more programs " \
"but it produces really huge files!!!")
-#define DESC_REDUCE_16BIT_TO_8BIT _("If scanner sends image with 16 bits/color save image with 8 bits/color")
+#define DESC_REDUCE_16BIT_TO_8BIT _("If scanner sends image with 16 bits/channel save image with 8 bits/channel")
#define DESC_PSFILE_WIDTH _("Width of paper for postscript files")
#define DESC_PSFILE_HEIGHT _("Height of paper for postscript files")
#define DESC_PSFILE_LEFTOFFSET _("Left offset from the edge of the paper to the usable area for postscript files")
#define DESC_PSFILE_BOTTOMOFFSET _("Bottom offset from the edge of the paper to the usable area for postscript files")
#define DESC_MAIN_WINDOW_FIXED _("Use fixed main window size or scrolled, resizable main window")
-#define DESC_DISABLE_GIMP_PREVIEW_GAMMA _("Disable preview gamma when XSane runs as gimp plugin")
+#define DESC_DISABLE_GIMP_PREVIEW_GAMMA _("Disable preview gamma when XSane runs as GIMP plugin")
#define DESC_PREVIEW_COLORMAP _("Use an own colormap for preview if display depth is 8 bpp")
#define DESC_SHOW_RANGE_MODE _("Select how a range is displayed")
#define DESC_PREVIEW_OVERSAMPLING _("Value with that the calculated preview resolution is multiplied")
@@ -575,6 +628,9 @@
#define DESC_PRESELECT_SCANAREA _("Select scanarea after preview scan has finished")
#define DESC_AUTOCORRECT_COLORS _("Do color correction after preview scan has finished")
+#define DESC_RENDERING_INTENT _("Select rendering intent for preview and saving")
+#define DESC_CMS_BPC _("Apply black point compensation when color transformation is done")
+
#define DESC_FAX_COMMAND _("Enter command to be executed in fax mode")
#define DESC_FAX_RECEIVER_OPT _("Enter option to specify receiver")
#define DESC_FAX_POSTSCRIPT_OPT _("Enter option to specify postscript files following")
@@ -586,7 +642,7 @@
#define DESC_FAX_HEIGHT _("Height of printable area")
#define DESC_FAX_LEFTOFFSET _("Left offset from the edge of the paper to the printable area")
#define DESC_FAX_BOTTOMOFFSET _("Bottom offset from the edge of the paper to the printable area")
-#define DESC_FAX_PS_FLATDECODED _("Create zlib compressed postscript image for fax (flatdecode)")
+#define DESC_FAX_PS_FLATEDECODED _("Create zlib compressed postscript image for fax (flatedecode)")
#define DESC_SMTP_SERVER _("IP Address or Domain name of SMTP server")
#define DESC_SMTP_PORT _("port to connect to SMTP server")
#define DESC_EMAIL_FROM _("enter your e-mail address")
@@ -606,7 +662,7 @@
#define DESC_PERMISSION_READ _("read")
#define DESC_PERMISSION_WRITE _("write")
-#define DESC_PERMISSION_EXECUTE _("execute")
+#define DESC_PERMISSION_SEARCH _("search")
#define DESC_ADD_BATCH _("Add selection for batch scan")
#define DESC_PIPETTE_WHITE _("Pick white point")
@@ -658,6 +714,21 @@
#define DESC_BATCH_DEL _("Delete selected area from batch list")
#define DESC_AUTOMATIC _("Turns on automatic mode")
+#define DESC_SCANNER_DEFAULT_COLOR_ICM_PROFILE _("Scanner default color ICM-profile")
+#define DESC_BUTTON_SCANNER_DEFAULT_COLOR_ICM_PROFILE_BROWSE _("Browse for scanner default color ICM-profile")
+#define DESC_SCANNER_DEFAULT_GRAY_ICM_PROFILE _("Scanner default gray ICM-profile")
+#define DESC_BUTTON_SCANNER_DEFAULT_GRAY_ICM_PROFILE_BROWSE _("Browse for scanner default gray ICM-profile")
+#define DESC_DISPLAY_ICM_PROFILE _("Display ICM-profile")
+#define DESC_BUTTON_DISPLAY_ICM_PROFILE_BROWSE _("Browse for display ICM-profile")
+#define DESC_PRINTER_ICM_PROFILE _("Printer ICM-profile")
+#define DESC_BUTTON_PRINTER_ICM_PROFILE_BROWSE _("Browse for printer ICM-profile")
+#define DESC_CUSTOM_PROOFING_ICM_PROFILE _("Custom proofing ICM-profile")
+#define DESC_BUTTON_CUSTOM_PROOFING_ICM_PROFILE_BROWSE _("Browse for custom proofing ICM-profile")
+#define DESC_WORKING_COLOR_SPACE_ICM_PROFILE _("Working color space ICM-profile")
+#define DESC_BUTTON_WORKING_COLOR_SPACE_ICM_PROFILE_BROWSE _("Browse for working color space ICM-profile")
+
+#define DESC_CMS_FUNCTION _("Color management function")
+
#define ERR_HOME_DIR _("Failed to determine home directory:")
#define ERR_CHANGE_WORKING_DIR _("Failed to change working directory to")
#define ERR_FILENAME_TOO_LONG _("Filename too long")
@@ -673,7 +744,6 @@ write permissions." )
#define ERR_DURING_READ _("Error during read:")
#define ERR_DURING_SAVE _("Error during save:")
#define ERR_BAD_DEPTH _("Can't handle depth")
-#define ERR_GIMP_BAD_DEPTH _("GIMP can't handle depth %d bits/color")
#define ERR_UNKNOWN_SAVING_FORMAT _("Unknown file format for saving")
#define ERR_OPEN_FAILED _("Failed to open")
#define ERR_CREATE_SECURE_FILE _("Could not create secure file (may be a link does exist):")
@@ -741,8 +811,22 @@ YOU ARE ALONE!\
#define ERR_FILE_NOT_POSTSCRIPT _("File %s is not a postscript file")
#define ERR_UNSUPPORTED_OUTPUT_FORMAT _("Unsupported %d-bit output format: %s")
+#define ERR_CMS_CONVERSION _("Error during CMS conversion:")
+#define ERR_CMS_OPEN_ICM_FILE _("Could not open")
+#define CMS_SCANNER_ICM _("scanner ICM profile")
+#define CMS_DISPLAY_ICM _("display ICM profile")
+#define CMS_PROOF_ICM _("proofing ICM profile")
+#define ERR_CMS_CREATE_TRANSFORM _("Could not create transform")
+
#define WARN_VIEWER_IMAGE_NOT_SAVED _("viewer image is not saved")
+#define FILE_FILTER_ALL_FILES _("All files")
+#define FILE_FILTER_IMAGES _("Images")
+#define FILE_FILTER_XBL _("XSane batch list")
+#define FILE_FILTER_ICM _("ICC/ICM Profiles")
+#define FILE_FILTER_DRC _("XSane device preferences")
+#define FILE_FILTER_RC _("XSane preferences")
+
#define TEXT_USAGE _("Usage:")
#define TEXT_USAGE_OPTIONS _("[OPTION]... [DEVICE]")
#define TEXT_HELP _(\
@@ -849,4 +933,5 @@ The format of [DEVICE] is backendname:devicefile (e.g. umax:/dev/scanner).\n\
#define TEXT_FAX_STATUS_QUEUEING_FAX N_("Queueing Fax")
#define TEXT_FAX_STATUS_FAX_QUEUED N_("Fax is queued")
+
#endif
diff --git a/src/xsane-viewer.c b/src/xsane-viewer.c
index d1d8e5e..ef47529 100644
--- a/src/xsane-viewer.c
+++ b/src/xsane-viewer.c
@@ -3,7 +3,7 @@
xsane-viewer.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -32,8 +32,7 @@
#include "xsane-save.h"
#include <gdk/gdkkeysyms.h>
#include <sys/wait.h>
-
-
+
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
@@ -81,35 +80,37 @@ static void xsane_viewer_set_sensitivity(Viewer *v, int sensitivity)
switch (v->allow_modification)
{
case VIEWER_NO_MODIFICATION:
- gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
-
- gtk_widget_set_sensitive(GTK_WIDGET(v->save), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(v->save), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), FALSE);
break;
case VIEWER_NO_NAME_AND_SIZE_MODIFICATION:
- gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
-
- gtk_widget_set_sensitive(GTK_WIDGET(v->save), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(v->save), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), FALSE);
break;
case VIEWER_NO_NAME_MODIFICATION:
@@ -121,26 +122,28 @@ static void xsane_viewer_set_sensitivity(Viewer *v, int sensitivity)
case VIEWER_FULL_MODIFICATION:
default:
- gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), TRUE);
-
- gtk_widget_set_sensitive(GTK_WIDGET(v->save), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(v->save), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), TRUE);
break;
}
}
else
{
v->block_actions = TRUE;
- gtk_widget_set_sensitive(GTK_WIDGET(v->file_menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(v->button_box), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->file_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu),FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(v->button_box), FALSE);
}
}
@@ -255,6 +258,7 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data)
char windowname[TEXTBUFSIZE];
int output_format;
int abort = 0;
+ int show_extra_widgets;
char buf[TEXTBUFSIZE];
if (v->block_actions) /* actions blocked: return */
@@ -280,9 +284,15 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data)
if (v->allow_modification == VIEWER_FULL_MODIFICATION) /* it is allowed to rename the image */
{
snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_VIEWER_OUTPUT_FILENAME, xsane.device_text);
+
+ show_extra_widgets = XSANE_GET_FILENAME_SHOW_FILETYPE;
+ if (v->cms_enable)
+ {
+ show_extra_widgets |= XSANE_GET_FILENAME_SHOW_CMS_FUNCTION;
+ }
umask((mode_t) preferences.directory_umask); /* define new file permissions */
- abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, &v->selection_filetype, TRUE, TRUE, FALSE, TRUE);
+ abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, &v->selection_filetype, &v->cms_function, XSANE_FILE_CHOOSER_ACTION_SAVE, show_extra_widgets, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES);
umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
if (abort)
@@ -348,7 +358,7 @@ static void xsane_viewer_save_callback(GtkWidget *window, gpointer data)
}
else
{
- xsane_save_image_as(v->output_filename, inputfilename, output_format, v->progress_bar, &v->cancel_save);
+ xsane_save_image_as(v->output_filename, inputfilename, output_format, v->cms_enable, v->cms_function, v->cms_intent, v->cms_bpc, v->progress_bar, &v->cancel_save);
}
free(inputfilename);
@@ -411,7 +421,7 @@ static void xsane_viewer_ocr_callback(GtkWidget *window, gpointer data)
snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_OCR_OUTPUT_FILENAME, xsane.device_text);
umask((mode_t) preferences.directory_umask); /* define new file permissions */
- abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, NULL, TRUE, TRUE, FALSE, FALSE);
+ abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SAVE, XSANE_GET_FILENAME_SHOW_FILETYPE, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES);
umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
if (abort)
@@ -458,11 +468,11 @@ static void xsane_viewer_clone_callback(GtkWidget *window, gpointer data)
{
char buf[TEXTBUFSIZE];
snprintf(buf, sizeof(buf), "%s%s", FILENAME_PREFIX_CLONE_OF, v->last_saved_filename);
- xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, buf, v->allow_modification, IMAGE_NOT_SAVED);
+ xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, buf, v->allow_modification, v->image_saved);
}
else
{
- xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, NULL, v->allow_modification, IMAGE_NOT_SAVED);
+ xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, NULL, v->allow_modification, v->image_saved);
}
}
@@ -569,7 +579,7 @@ static void xsane_viewer_scale_callback(GtkWidget *window, gpointer data)
GtkWidget *frame;
GtkWidget *hbox, *vbox;
GtkWidget *button;
- GtkObject *scale_widget, *scalex_widget, *scaley_widget;
+ GtkWidget *scale_widget, *scalex_widget, *scaley_widget;
GtkAdjustment *adjustment_size_x;
GtkAdjustment *adjustment_size_y;
GtkWidget *spinbutton;
@@ -1071,7 +1081,7 @@ static void xsane_viewer_scale_image(GtkWidget *window, gpointer data)
xsane_read_pnm_header(infile, &image_info);
- DBG(DBG_info, "scaling image %s with geometry: %d x %d x %d, %d colors\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.colors);
+ DBG(DBG_info, "scaling image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
@@ -1153,7 +1163,7 @@ static void xsane_viewer_despeckle_image(GtkWidget *window, gpointer data)
xsane_read_pnm_header(infile, &image_info);
- DBG(DBG_info, "despeckling image %s with geometry: %d x %d x %d, %d colors\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.colors);
+ DBG(DBG_info, "despeckling image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
@@ -1230,7 +1240,7 @@ static void xsane_viewer_blur_image(GtkWidget *window, gpointer data)
xsane_read_pnm_header(infile, &image_info);
- DBG(DBG_info, "bluring image %s with geometry: %d x %d x %d, %d colors\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.colors);
+ DBG(DBG_info, "bluring image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
@@ -1312,7 +1322,7 @@ static void xsane_viewer_rotate(Viewer *v, int rotation)
xsane_read_pnm_header(infile, &image_info);
- DBG(DBG_info, "rotating image %s with geometry: %d x %d x %d, %d colors\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.colors);
+ DBG(DBG_info, "rotating image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
@@ -1654,6 +1664,915 @@ static GtkWidget *xsane_viewer_geometry_build_menu(Viewer *v)
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+#define INTENT_PERCEPTUAL 0
+#define INTENT_RELATIVE_COLORIMETRIC 1
+#define INTENT_SATURATION 2
+#define INTENT_ABSOLUTE_COLORIMETRIC 3
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_enable_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+
+ v->cms_enable = (GTK_CHECK_MENU_ITEM(widget)->active != 0);
+ DBG(DBG_proc, "xsane_viewer_set_cms_enable_callback (%d)\n", v->cms_enable);
+
+ xsane_viewer_read_image(v);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_black_point_compensation_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+
+ v->cms_bpc = (GTK_CHECK_MENU_ITEM(widget)->active != 0);
+ DBG(DBG_proc, "xsane_viewer_set_cms_black_point_compensation_callback (%d)\n", v->cms_bpc);
+
+ xsane_viewer_read_image(v);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_gamut_check_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+
+ v->cms_gamut_check = (GTK_CHECK_MENU_ITEM(widget)->active != 0);
+ DBG(DBG_proc, "xsane_viewer_set_cms_gamut_check_callback (%d)\n", v->cms_gamut_check);
+
+ xsane_viewer_read_image(v);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_proofing_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+ int val;
+
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+
+ val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
+
+ DBG(DBG_proc, "xsane_viewer_set_cms_proofing_callback (%d)\n", val);
+
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_widget[v->cms_proofing]), FALSE);
+ v->cms_proofing = val;
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_widget[v->cms_proofing]), TRUE);
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+
+ xsane_viewer_read_image(v);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_intent_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+ int val;
+
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+
+ val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
+
+ DBG(DBG_proc, "xsane_viewer_set_cms_intent_callback (%d)\n", val);
+
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_intent_widget[v->cms_intent]), FALSE);
+ v->cms_intent = val;
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_intent_widget[v->cms_intent]), TRUE);
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+
+ xsane_viewer_read_image(v);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_proofing_intent_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+ int val;
+
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
+
+ val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
+
+ DBG(DBG_proc, "xsane_viewer_set_cms_proofing_intent_callback (%d)\n", val);
+
+ /* we have cms_proofing_intent = 1 and 3 and widget[0] and widget[1] => widget[(cms_proofing_intent-1)/2] */
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_intent_widget[(v->cms_proofing_intent-1)/2]), FALSE);
+ v->cms_proofing_intent = val;
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_intent_widget[(v->cms_proofing_intent-1)/2]), TRUE);
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
+
+ xsane_viewer_read_image(v);
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_viewer_set_cms_gamut_alarm_color_callback(GtkWidget *widget, gpointer data)
+{
+ Viewer *v = (Viewer *) data;
+ int val;
+
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[4]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[5]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+
+ val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
+
+ DBG(DBG_proc, "xsane_viewer_set_cms_gamut_alarm_color_callback (%d)\n", val);
+
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_gamut_alarm_color_widget[v->cms_gamut_alarm_color]), FALSE);
+ v->cms_gamut_alarm_color = val;
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_gamut_alarm_color_widget[v->cms_gamut_alarm_color]), TRUE);
+
+ switch(v->cms_gamut_alarm_color)
+ {
+ default:
+ case 0: /* black */
+ cmsSetAlarmCodes(0, 0, 0);
+ break;
+
+ case 1: /* gray */
+ cmsSetAlarmCodes(128, 128, 128);
+ break;
+
+ case 2: /* white */
+ cmsSetAlarmCodes(255, 255, 255);
+ break;
+
+ case 3: /* red */
+ cmsSetAlarmCodes(255, 0, 0);
+ break;
+
+ case 4: /* green */
+ cmsSetAlarmCodes(0, 255, 0);
+ break;
+
+ case 5: /* blue */
+ cmsSetAlarmCodes(0, 0, 255);
+ break;
+ }
+
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[4]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[5]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+
+ if (v->cms_gamut_check)
+ {
+ xsane_viewer_read_image(v);
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+static GtkWidget *xsane_viewer_color_management_build_menu(Viewer *v)
+{
+ GtkWidget *menu, *item, *submenu, *subitem;
+
+ DBG(DBG_proc, "xsane_viewer_color_management_build_menu\n");
+
+ menu = gtk_menu_new();
+ gtk_menu_set_accel_group(GTK_MENU(menu), xsane.accelerator_group);
+
+ /* cms enable */
+ item = gtk_check_menu_item_new_with_label(MENU_ITEM_CMS_ENABLE_COLOR_MANAGEMENT);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), v->cms_enable);
+ g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_enable_callback, v);
+ gtk_widget_show(item);
+
+ /* black point compensation */
+ item = gtk_check_menu_item_new_with_label(MENU_ITEM_CMS_BLACK_POINT_COMPENSATION);
+ gtk_menu_append(GTK_MENU(menu), item);
+ if (v->cms_bpc)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_black_point_compensation_callback, v);
+ gtk_widget_show(item);
+
+
+ /* Output Device submenu */
+ item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_PROOFING);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ submenu = gtk_menu_new();
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_PROOF_OFF);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_proofing == 0)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 0);
+ gtk_widget_show(subitem);
+ v->cms_proofing_widget[0] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_PROOF_PRINTER);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_proofing == 1)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 1);
+ gtk_widget_show(subitem);
+ v->cms_proofing_widget[1] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_PROOF_CUSTOM);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_proofing == 2)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 2);
+ gtk_widget_show(subitem);
+ v->cms_proofing_widget[2] = subitem;
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+
+
+ /* Intent submenu */
+ item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_RENDERING_INTENT);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ submenu = gtk_menu_new();
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_PERCEPTUAL);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_intent == INTENT_PERCEPTUAL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_PERCEPTUAL);
+ gtk_widget_show(subitem);
+ v->cms_intent_widget[INTENT_PERCEPTUAL] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_RELATIVE_COLORIMETRIC);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_intent == INTENT_RELATIVE_COLORIMETRIC)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_RELATIVE_COLORIMETRIC);
+ gtk_widget_show(subitem);
+ v->cms_intent_widget[INTENT_RELATIVE_COLORIMETRIC] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_ABSOLUTE_COLORIMETRIC);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_intent == INTENT_ABSOLUTE_COLORIMETRIC)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_ABSOLUTE_COLORIMETRIC);
+ gtk_widget_show(subitem);
+ v->cms_intent_widget[INTENT_ABSOLUTE_COLORIMETRIC] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_SATURATION);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_intent == INTENT_SATURATION)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_SATURATION);
+ gtk_widget_show(subitem);
+ v->cms_intent_widget[INTENT_SATURATION] = subitem;
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+
+
+ /* proofing_intent submenu */
+ item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_PROOFING_INTENT);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ submenu = gtk_menu_new();
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_RELATIVE_COLORIMETRIC);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_proofing_intent == INTENT_RELATIVE_COLORIMETRIC)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_RELATIVE_COLORIMETRIC);
+ gtk_widget_show(subitem);
+ v->cms_proofing_intent_widget[0] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_ABSOLUTE_COLORIMETRIC);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_proofing_intent == INTENT_ABSOLUTE_COLORIMETRIC)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_ABSOLUTE_COLORIMETRIC);
+ gtk_widget_show(subitem);
+ v->cms_proofing_intent_widget[1] = subitem;
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+
+
+ /* cms gamut check */
+ item = gtk_check_menu_item_new_with_label(MENU_ITEM_CMS_GAMUT_CHECK);
+ gtk_menu_append(GTK_MENU(menu), item);
+ g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_check_callback, v);
+ gtk_widget_show(item);
+
+
+ /* gamut alarm color */
+ item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_GAMUT_ALARM_COLOR);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ submenu = gtk_menu_new();
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_BLACK);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_gamut_alarm_color == 0)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 0);
+ gtk_widget_show(subitem);
+ v->cms_gamut_alarm_color_widget[0] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_GRAY);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_gamut_alarm_color == 1)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 1);
+ gtk_widget_show(subitem);
+ v->cms_gamut_alarm_color_widget[1] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_WHITE);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_gamut_alarm_color == 2)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 2);
+ gtk_widget_show(subitem);
+ v->cms_gamut_alarm_color_widget[2] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_RED);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_gamut_alarm_color == 3)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 3);
+ gtk_widget_show(subitem);
+ v->cms_gamut_alarm_color_widget[3] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_GREEN);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_gamut_alarm_color == 4)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 4);
+ gtk_widget_show(subitem);
+ v->cms_gamut_alarm_color_widget[4] = subitem;
+
+ subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_BLUE);
+ gtk_menu_append(GTK_MENU(submenu), subitem);
+ if (v->cms_gamut_alarm_color == 5)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
+ }
+ g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
+ gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 5);
+ gtk_widget_show(subitem);
+ v->cms_gamut_alarm_color_widget[5] = subitem;
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+
+ return menu;
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+
+static int xsane_viewer_read_image_header(Viewer *v)
+{
+ int pos0;
+ FILE *infile;
+ Image_info image_info;
+
+ /* open imagefile */
+
+ infile = fopen(v->filename, "rb");
+ if (!infile)
+ {
+ DBG(DBG_error, "could not load file %s\n", v->filename);
+ return -1;
+ }
+
+ xsane_read_pnm_header(infile, &image_info);
+
+ pos0 = ftell(infile);
+
+ if (!image_info.channels) /* == 0 (grayscale) ? */
+ {
+ image_info.channels = 1; /* we have one color component */
+ }
+
+ DBG(DBG_info, "reading image header %s with geometry: %d x %d x %d, %d channels\n", v->filename,
+ image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
+
+ /* init color management */
+ v->enable_color_management = image_info.enable_color_management;
+ if (!image_info.enable_color_management)
+ {
+ v->cms_enable = FALSE;
+ }
+
+ v->cms_function = image_info.cms_function;
+ v->cms_intent = image_info.cms_intent;
+ v->cms_bpc = image_info.cms_bpc;
+
+ if ((v->enable_color_management) && (image_info.reduce_to_lineart))
+ {
+ v->enable_color_management = FALSE;
+ v->cms_enable = FALSE;
+ }
+
+ fclose(infile);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------------------------------------------------------- */
+
+
+static int xsane_viewer_read_image(Viewer *v)
+{
+ unsigned char *cms_row, *row, *src_row;
+ int x, y;
+ int last_y;
+ int nread;
+ int pos0;
+ FILE *infile;
+ Image_info image_info;
+ char buf[TEXTBUFSIZE];
+ float size;
+ char *size_unit;
+ int width, height;
+
+#ifdef HAVE_LIBLCMS
+ cmsHPROFILE hInProfile = NULL;
+ cmsHPROFILE hOutProfile = NULL;
+ cmsHPROFILE hProofProfile = NULL;
+ cmsHTRANSFORM hTransform = NULL;
+ int proof = 0;
+ char *cms_proof_icm_profile = NULL;
+ DWORD cms_input_format;
+ DWORD cms_output_format;
+ DWORD cms_flags = 0;
+#endif
+
+ /* open imagefile */
+
+ infile = fopen(v->filename, "rb");
+ if (!infile)
+ {
+ DBG(DBG_error, "could not load file %s\n", v->filename);
+ return -1;
+ }
+
+ xsane_read_pnm_header(infile, &image_info);
+
+ pos0 = ftell(infile);
+
+ if (!image_info.channels) /* == 0 (grayscale) ? */
+ {
+ image_info.channels = 1; /* we have one color component */
+ }
+
+ DBG(DBG_info, "reading image %s with geometry: %d x %d x %d, %d channels\n", v->filename,
+ image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
+
+#ifdef HAVE_LIBLCMS
+ /* init color management */
+
+ if ((v->enable_color_management) && (v->cms_enable))
+ {
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ if (v->cms_bpc)
+ {
+ cms_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+ }
+
+ if (image_info.channels == 1) /* == 1 (grayscale) */
+ {
+ if (image_info.depth == 8)
+ {
+ cms_input_format = TYPE_GRAY_8;
+ cms_output_format = TYPE_GRAY_8;
+ }
+ else
+ {
+ cms_input_format = TYPE_GRAY_16;
+ cms_output_format = TYPE_GRAY_8;
+ }
+ }
+ else /* color */
+ {
+ if (image_info.depth == 8)
+ {
+ cms_input_format = TYPE_RGB_8;
+ cms_output_format = TYPE_RGB_8;
+ }
+ else
+ {
+ cms_input_format = TYPE_RGB_16;
+ cms_output_format = TYPE_RGB_8;
+ }
+ }
+
+ switch (v->cms_proofing)
+ {
+ default:
+ case 0: /* display */
+ proof = 0;
+ break;
+
+ case 1: /* proof printer */
+ cms_proof_icm_profile = preferences.printer[preferences.printernr]->icm_profile;
+ proof = 1;
+ break;
+
+ case 2: /* proof custom proofing */
+ cms_proof_icm_profile = preferences.custom_proofing_icm_profile;
+ proof = 1;
+ break;
+ }
+
+ hInProfile = cmsOpenProfileFromFile(image_info.icm_profile, "r");
+ if (!hInProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_SCANNER_ICM, image_info.icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+ hOutProfile = cmsOpenProfileFromFile(preferences.display_icm_profile, "r");
+ if (!hOutProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_DISPLAY_ICM, preferences.display_icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+
+ if (proof == 0)
+ {
+ hTransform = cmsCreateTransform(hInProfile, cms_input_format,
+ hOutProfile, cms_output_format,
+ v->cms_intent, cms_flags);
+ }
+ else /* proof */
+ {
+ cms_flags |= cmsFLAGS_SOFTPROOFING;
+
+ if (v->cms_gamut_check)
+ {
+ cms_flags |= cmsFLAGS_GAMUTCHECK;
+ }
+
+ hProofProfile = cmsOpenProfileFromFile(cms_proof_icm_profile, "r");
+ if (!hProofProfile)
+ {
+ char buf[TEXTBUFSIZE];
+
+ cmsCloseProfile(hInProfile);
+ cmsCloseProfile(hOutProfile);
+
+ snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_PROOF_ICM, cms_proof_icm_profile);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+
+ hTransform = cmsCreateProofingTransform(hInProfile, cms_input_format,
+ hOutProfile, cms_output_format,
+ hProofProfile,
+ v->cms_intent, v->cms_proofing_intent, cms_flags);
+ }
+
+ cmsCloseProfile(hInProfile);
+ cmsCloseProfile(hOutProfile);
+ if (proof)
+ {
+ cmsCloseProfile(hProofProfile);
+ }
+
+ if (!hTransform)
+ {
+ char buf[TEXTBUFSIZE];
+
+ snprintf(buf, sizeof(buf), "%s\n%s\n", ERR_CMS_CONVERSION, ERR_CMS_CREATE_TRANSFORM);
+ xsane_back_gtk_error(buf, TRUE);
+ return -1;
+ }
+ }
+#endif
+
+ /* open infile */
+
+ if (v->window) /* we already have an existing viewer preview window? */
+ {
+ gtk_widget_destroy(v->window);
+ }
+
+ /* the preview area */
+ if (image_info.channels == 3) /* RGB */
+ {
+ v->window = gtk_preview_new(GTK_PREVIEW_COLOR);
+ }
+ else /* grayscale */
+ {
+ v->window = gtk_preview_new(GTK_PREVIEW_GRAYSCALE);
+ }
+
+ gtk_preview_size(GTK_PREVIEW(v->window), image_info.image_width * v->zoom, image_info.image_height * v->zoom);
+ gtk_container_add(GTK_CONTAINER(v->viewport), v->window);
+ gtk_widget_show(v->window);
+
+
+
+ /* get memory for one row of the image */
+ src_row = malloc(image_info.image_width * image_info.channels * image_info.depth / 8);
+
+ if ((v->enable_color_management) && (v->cms_enable))
+ {
+ row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels * image_info.depth / 8);
+ }
+ else
+ {
+ row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels);
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((v->enable_color_management) && (v->cms_enable))
+ {
+ cms_row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels);
+ }
+ else
+#endif
+ {
+ cms_row = row;
+ }
+
+ if (!row || !src_row || !cms_row)
+ {
+ if (src_row)
+ {
+ free(src_row);
+ }
+
+ if (row)
+ {
+ free(row);
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((cms_row) && (v->enable_color_management) && (v->cms_enable))
+ {
+ free(cms_row);
+ }
+#endif
+
+ fclose(infile);
+ DBG(DBG_error, "could not allocate memory\n");
+ return -1;
+ }
+
+
+ last_y = -99999;
+
+ /* read the image from file */
+ for (y = 0; y < (int) (image_info.image_height * v->zoom); y++)
+ {
+ if ((int) (last_y / v->zoom) != (int) (y / v->zoom))
+ {
+ last_y = y;
+
+ if (image_info.depth == 8) /* 8 bits/pixel */
+ {
+ fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels, SEEK_SET);
+ nread = fread(src_row, image_info.channels, image_info.image_width, infile);
+
+ if (image_info.channels > 1)
+ {
+ for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
+ {
+ int xoff = ((int) (x / v->zoom)) * image_info.channels;
+
+ row[3*x+0] = src_row[xoff + 0];
+ row[3*x+1] = src_row[xoff + 1];
+ row[3*x+2] = src_row[xoff + 2];
+ }
+ }
+ else
+ {
+ for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
+ {
+ row[x] = src_row[((int) (x / v->zoom))];
+ }
+ }
+ }
+ else if ((!v->enable_color_management) || (!v->cms_enable)) /* 16 bits/pixel => reduce to 8 bits/pixel */
+ {
+ guint16 *src_row16 = (guint16 *) src_row;
+
+ fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels * 2, SEEK_SET);
+ nread = fread(src_row, 2 * image_info.channels, image_info.image_width, infile);
+
+ if (image_info.channels > 1)
+ {
+ for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
+ {
+ int xoff = ((int) (x / v->zoom)) * image_info.channels;
+
+ row[3*x+0] = (unsigned char) (src_row16[xoff + 0] / 256);
+ row[3*x+1] = (unsigned char) (src_row16[xoff + 1] / 256);
+ row[3*x+2] = (unsigned char) (src_row16[xoff + 2] / 256);
+ }
+ }
+ else
+ {
+ for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
+ {
+ row[x] = (unsigned char) (src_row16[(int) (x / v->zoom)] / 256);
+ }
+ }
+ }
+ else /* 16 bits/pixel with color management enabled, cms does 16->8 conversion */
+ {
+ guint16 *src_row16 = (guint16 *) src_row;
+ guint16 *dst_row16 = (guint16 *) row;
+
+ fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels * 2, SEEK_SET);
+ nread = fread(src_row, 2 * image_info.channels, image_info.image_width, infile);
+
+ if (image_info.channels > 1)
+ {
+ for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
+ {
+ int xoff = ((int) (x / v->zoom)) * image_info.channels;
+
+ dst_row16[3*x+0] = src_row16[xoff + 0];
+ dst_row16[3*x+1] = src_row16[xoff + 1];
+ dst_row16[3*x+2] = src_row16[xoff + 2];
+ }
+ }
+ else
+ {
+ for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
+ {
+ dst_row16[x] = src_row16[(int) (x / v->zoom)];
+ }
+ }
+ }
+ }
+
+#ifdef HAVE_LIBLCMS
+ if ((v->enable_color_management) && (v->cms_enable))
+ {
+ cmsDoTransform(hTransform, row, cms_row, image_info.image_width * v->zoom);
+ }
+#endif
+ gtk_preview_draw_row(GTK_PREVIEW(v->window), cms_row, 0, y, image_info.image_width * v->zoom);
+ }
+
+ gtk_preview_put(GTK_PREVIEW(v->window), v->window->window, v->window->style->black_gc, 0, 0, 0, 0,
+ image_info.image_width * v->zoom, image_info.image_height * v->zoom);
+
+ size = (float) image_info.image_width * image_info.image_height * image_info.channels;
+ if (image_info.depth == 16)
+ {
+ size *= 2.0;
+ }
+
+ if (image_info.reduce_to_lineart)
+ {
+ size /= 8.0;
+ }
+
+ size_unit = "B";
+
+ if (size >= 1024 * 1024)
+ {
+ size /= (1024.0 * 1024.0);
+ size_unit = "MB";
+ }
+ else if (size >= 1024)
+ {
+ size /= 1024.0;
+ size_unit = "KB";
+ }
+
+ if (image_info.reduce_to_lineart)
+ {
+ snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, 1, image_info.channels,
+ image_info.resolution_x, image_info.resolution_y, size, size_unit);
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels,
+ image_info.resolution_x, image_info.resolution_y, size, size_unit);
+ }
+ gtk_label_set(GTK_LABEL(v->image_info_label), buf);
+
+ width = image_info.image_width * v->zoom + 26;
+ height = image_info.image_height * v->zoom + 136;
+
+ if (width > gdk_screen_width())
+ {
+ width = gdk_screen_width();
+ }
+
+ if (height > gdk_screen_height())
+ {
+ height = gdk_screen_height();
+ }
+
+#ifdef HAVE_GTK2
+ if (GTK_WIDGET_REALIZED(v->top))
+ {
+ gtk_window_resize(GTK_WINDOW(v->top), width, height);
+ }
+ else
+#endif
+ {
+ gtk_window_set_default_size(GTK_WINDOW(v->top), width, height);
+ }
+
+ free(row);
+ free(src_row);
+ fclose(infile);
+
+#ifdef HAVE_LIBLCMS
+ if ((v->enable_color_management) && (v->cms_enable))
+ {
+ cmsDeleteTransform(hTransform);
+ }
+#endif
+
+ return 0;
+}
+
+#if 0 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
static int xsane_viewer_read_image(Viewer *v)
{
unsigned char *row, *src_row;
@@ -1679,13 +2598,13 @@ static int xsane_viewer_read_image(Viewer *v)
pos0 = ftell(infile);
- if (!image_info.colors) /* == 0 (grayscale) ? */
+ if (!image_info.channels) /* == 0 (grayscale) ? */
{
- image_info.colors = 1; /* we have one color component */
+ image_info.channels = 1; /* we have one color component */
}
- DBG(DBG_info, "reading image %s with geometry: %d x %d x %d, %d colors\n", v->filename,
- image_info.image_width, image_info.image_height, image_info.depth, image_info.colors);
+ DBG(DBG_info, "reading image %s with geometry: %d x %d x %d, %d channels\n", v->filename,
+ image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
/* open infile */
if (v->window) /* we already have an existing viewer preview window? */
@@ -1694,7 +2613,7 @@ static int xsane_viewer_read_image(Viewer *v)
}
/* the preview area */
- if (image_info.colors == 3) /* RGB */
+ if (image_info.channels == 3) /* RGB */
{
v->window = gtk_preview_new(GTK_PREVIEW_COLOR);
}
@@ -1710,8 +2629,8 @@ static int xsane_viewer_read_image(Viewer *v)
/* get memory for one row of the image */
- src_row = malloc(image_info.image_width * image_info.colors * image_info.depth / 8);
- row = malloc(((int) image_info.image_width * v->zoom) * image_info.colors);
+ src_row = malloc(image_info.image_width * image_info.channels * image_info.depth / 8);
+ row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels);
if (!row || !src_row)
{
@@ -1742,14 +2661,14 @@ static int xsane_viewer_read_image(Viewer *v)
if (image_info.depth == 8) /* 8 bits/pixel */
{
- fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.colors, SEEK_SET);
- nread = fread(src_row, image_info.colors, image_info.image_width, infile);
+ fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels, SEEK_SET);
+ nread = fread(src_row, image_info.channels, image_info.image_width, infile);
- if (image_info.colors > 1)
+ if (image_info.channels > 1)
{
for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
{
- int xoff = ((int) (x / v->zoom)) * image_info.colors;
+ int xoff = ((int) (x / v->zoom)) * image_info.channels;
row[3*x+0] = src_row[xoff + 0];
row[3*x+1] = src_row[xoff + 1];
@@ -1768,14 +2687,14 @@ static int xsane_viewer_read_image(Viewer *v)
{
guint16 *src_row16 = (guint16 *) src_row;
- fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.colors * 2, SEEK_SET);
- nread = fread(src_row, 2 * image_info.colors, image_info.image_width, infile);
+ fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels * 2, SEEK_SET);
+ nread = fread(src_row, 2 * image_info.channels, image_info.image_width, infile);
- if (image_info.colors > 1)
+ if (image_info.channels > 1)
{
for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
{
- int xoff = ((int) (x / v->zoom)) * image_info.colors;
+ int xoff = ((int) (x / v->zoom)) * image_info.channels;
row[3*x+0] = (unsigned char) (src_row16[xoff + 0] / 256);
row[3*x+1] = (unsigned char) (src_row16[xoff + 1] / 256);
@@ -1798,7 +2717,7 @@ static int xsane_viewer_read_image(Viewer *v)
gtk_preview_put(GTK_PREVIEW(v->window), v->window->window, v->window->style->black_gc, 0, 0, 0, 0,
image_info.image_width * v->zoom, image_info.image_height * v->zoom);
- size = (float) image_info.image_width * image_info.image_height * image_info.colors;
+ size = (float) image_info.image_width * image_info.image_height * image_info.channels;
if (image_info.depth == 16)
{
size *= 2.0;
@@ -1824,18 +2743,18 @@ static int xsane_viewer_read_image(Viewer *v)
if (image_info.reduce_to_lineart)
{
- snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, 1, image_info.colors,
+ snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, 1, image_info.channels,
image_info.resolution_x, image_info.resolution_y, size, size_unit);
}
else
{
- snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, image_info.depth, image_info.colors,
+ snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels,
image_info.resolution_x, image_info.resolution_y, size, size_unit);
}
gtk_label_set(GTK_LABEL(v->image_info_label), buf);
- width = image_info.image_width + 26;
- height = image_info.image_height + 136;
+ width = image_info.image_width * v->zoom + 26;
+ height = image_info.image_height * v->zoom + 136;
if (width > gdk_screen_width())
{
@@ -1864,6 +2783,7 @@ static int xsane_viewer_read_image(Viewer *v)
return 0;
}
+#endif
/* ---------------------------------------------------------------------------------------------------------------------- */
@@ -1897,6 +2817,17 @@ Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_red
v->keep_viewer_pnm_format = FALSE;
v->allow_modification = allow_modification;
v->next_viewer = xsane.viewer_list;
+#ifdef HAVE_LIBLCMS
+ v->enable_color_management = FALSE;
+ v->cms_enable = TRUE;
+ v->cms_function = XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE;
+ v->cms_intent = INTENT_PERCEPTUAL;
+ v->cms_proofing = 0; /* display */
+ v->cms_proofing_intent = INTENT_ABSOLUTE_COLORIMETRIC;
+ v->cms_gamut_check = 0;
+ v->cms_gamut_alarm_color = 3; /* red */
+ cmsSetAlarmCodes(255, 0, 0);
+#endif
if (selection_filetype)
{
v->selection_filetype = strdup(selection_filetype);
@@ -1933,6 +2864,8 @@ Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_red
snprintf(buf, sizeof(buf), "%s %s", WINDOW_VIEWER, xsane.device_text);
}
+ xsane_viewer_read_image_header(v); // xxx oli
+
v->top = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(v->top), buf);
xsane_set_window_icon(v->top, 0);
@@ -1983,6 +2916,17 @@ Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_red
gtk_widget_show(menubar_item);
v->geometry_menu = menubar_item;
+#ifdef HAVE_LIBLCMS
+ /* "Color management" submenu: */
+ menubar_item = gtk_menu_item_new_with_label(MENU_COLOR_MANAGEMENT);
+ gtk_container_add(GTK_CONTAINER(menubar), menubar_item);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_viewer_color_management_build_menu(v));
+/* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
+ gtk_widget_show(menubar_item);
+ v->color_management_menu = menubar_item;
+ gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
+#endif
+
gtk_widget_show(menubar);
diff --git a/src/xsane-viewer.h b/src/xsane-viewer.h
index 373fd31..b729151 100644
--- a/src/xsane-viewer.h
+++ b/src/xsane-viewer.h
@@ -3,7 +3,7 @@
xsane-viewer.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 2001-2005 Oliver Rauch
+ Copyright (C) 2001-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -47,6 +47,8 @@ typedef struct Viewer
char *undo_filename;
char *selection_filetype;
+ int cms_function;
+
int allow_reduction_to_lineart;
int keep_viewer_pnm_format;
float zoom;
@@ -57,6 +59,15 @@ typedef struct Viewer
int despeckle_radius;
float blur_radius;
+ int enable_color_management;
+ int cms_enable;
+ int cms_bpc;
+ int cms_proofing;
+ int cms_intent;
+ int cms_proofing_intent;
+ int cms_gamut_check;
+ int cms_gamut_alarm_color;
+
int bind_scale;
double x_scale_factor;
double y_scale_factor;
@@ -73,6 +84,7 @@ typedef struct Viewer
GtkWidget *edit_menu;
GtkWidget *filters_menu;
GtkWidget *geometry_menu;
+ GtkWidget *color_management_menu;
GtkWidget *viewport;
GtkWidget *window;
@@ -94,6 +106,11 @@ typedef struct Viewer
GtkWidget *despeckle;
GtkWidget *blur;
+ GtkWidget *cms_proofing_widget[3];
+ GtkWidget *cms_intent_widget[4];
+ GtkWidget *cms_proofing_intent_widget[2];
+ GtkWidget *cms_gamut_alarm_color_widget[6];
+
GtkWidget *image_info_label;
GtkProgressBar *progress_bar;
diff --git a/src/xsane.c b/src/xsane.c
index 9254ea7..38ee7d1 100644
--- a/src/xsane.c
+++ b/src/xsane.c
@@ -3,7 +3,7 @@
xsane.c
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -56,6 +56,7 @@ struct option long_options[] =
{"version", no_argument, 0, 'v'},
{"license", no_argument, 0, 'l'},
{"device-settings", required_argument, 0, 'd'},
+ {"xsane-rc", required_argument, 0, 'r'},
{"save", no_argument, 0, 's'},
{"viewer", no_argument, 0, 'V'},
{"copy", no_argument, 0, 'c'},
@@ -752,7 +753,7 @@ static void xsane_resolution_list_callback(GtkWidget *widget, gpointer data)
static int xsane_resolution_widget_new(GtkWidget *parent, int well_known_option, double *resolution, const char *image_xpm[],
const gchar *desc, const gchar *widget_name)
{
- GtkObject *resolution_widget;
+ GtkWidget *resolution_widget;
const SANE_Option_Descriptor *opt;
DBG(DBG_proc, "xsane_resolution_widget_new\n");
@@ -1153,6 +1154,14 @@ static void xsane_scanmode_menu_callback(GtkWidget *widget, gpointer data)
}
}
+/* ----------------------------------------------------------------------------------------------------------------- */
+
+static void xsane_cms_function_menu_callback(GtkWidget *widget, gpointer data)
+{
+ preferences.cms_function = (int) data;
+ DBG(DBG_proc, "xsane_cms_function_menu_callback(%d)\n", preferences.cms_function);
+}
+
/* ---------------------------------------------------------------------------------------------------------------------- */
static void xsane_adf_pages_max_callback(GtkWidget *widget, gpointer data)
@@ -1444,6 +1453,31 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
gtk_widget_show(xsane_spinbutton);
}
+#ifdef HAVE_LIBLCMS
+ if ((xsane.enable_color_management) &&
+ ( (xsane.xsane_mode == XSANE_VIEWER) ||
+ (xsane.xsane_mode == XSANE_SAVE) ||
+ (xsane.xsane_mode == XSANE_EMAIL) ||
+ (xsane.xsane_mode == XSANE_MULTIPAGE)
+ )
+ )
+ {
+ hbox = gtk_hbox_new(FALSE, 2);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
+ gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 1);
+ gtk_widget_show(hbox);
+
+ pixmap = gdk_pixmap_create_from_xpm_d(xsane.histogram_dialog->window, &mask, xsane.bg_trans, (gchar **) cms_xpm);
+ pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
+ gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
+ gdk_drawable_unref(pixmap);
+ gtk_widget_show(pixmapwidget);
+
+ xsane.cms_function_option_menu = xsane_back_gtk_cms_function_menu_new(preferences.cms_function, (GtkSignalFunc) xsane_cms_function_menu_callback);
+ gtk_box_pack_end(GTK_BOX(hbox), xsane.cms_function_option_menu, FALSE, FALSE, 2);
+ gtk_widget_show(xsane.cms_function_option_menu);
+ }
+#endif
/* input selection */
opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.scansource);
@@ -1526,7 +1560,8 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
}
- if (xsane.param.depth != 1) /* show medium selection of not lineart mode */
+ /* show medium selection when not lineart mode and no color management */
+ if ((xsane.param.depth != 1) && (!xsane.enable_color_management))
{
/* medium selection */
hbox = gtk_hbox_new(FALSE, 2);
@@ -1658,33 +1693,31 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
}
#endif
- /* test if scanner gamma table is selected */
+ /* test if scanner gamma table is selected */
- xsane.scanner_gamma_gray = FALSE;
- if (xsane.well_known.gamma_vector >0)
- {
- const SANE_Option_Descriptor *opt;
-
- opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.gamma_vector);
- if (SANE_OPTION_IS_ACTIVE(opt->cap))
- {
- xsane.scanner_gamma_gray = TRUE;
- }
- }
-
- xsane.scanner_gamma_color = FALSE;
- if (xsane.well_known.gamma_vector_r >0)
- {
- const SANE_Option_Descriptor *opt;
+ xsane.scanner_gamma_gray = FALSE;
+ if (xsane.well_known.gamma_vector >0)
+ {
+ const SANE_Option_Descriptor *opt;
- opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.gamma_vector_r);
- if (SANE_OPTION_IS_ACTIVE(opt->cap))
- {
- xsane.scanner_gamma_color = TRUE;
- }
- }
+ opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.gamma_vector);
+ if (SANE_OPTION_IS_ACTIVE(opt->cap))
+ {
+ xsane.scanner_gamma_gray = TRUE;
+ }
+ }
+ xsane.scanner_gamma_color = FALSE;
+ if (xsane.well_known.gamma_vector_r >0)
+ {
+ const SANE_Option_Descriptor *opt;
+ opt = xsane_get_option_descriptor(xsane.dev, xsane.well_known.gamma_vector_r);
+ if (SANE_OPTION_IS_ACTIVE(opt->cap))
+ {
+ xsane.scanner_gamma_color = TRUE;
+ }
+ }
/* XSane Frame Enhancement */
@@ -1717,7 +1750,41 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
xsane.slider_gray.active = XSANE_SLIDER_ACTIVE; /* mark slider active */
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) )
+
+ if (xsane.enable_color_management) /* do not show gamma widgets when color management is active */
+ {
+ xsane.gamma = 1.0;
+ xsane.gamma_red = 1.0;
+ xsane.gamma_green = 1.0;
+ xsane.gamma_blue = 1.0;
+ xsane.brightness = 0.0;
+ xsane.brightness_red = 0.0;
+ xsane.brightness_green = 0.0;
+ xsane.brightness_blue = 0.0;
+ xsane.contrast = 0.0;
+ xsane.contrast_red = 0.0;
+ xsane.contrast_green = 0.0;
+ xsane.contrast_blue = 0.0;
+ xsane.threshold = 50.0;
+
+ xsane.slider_gray.value[2] = 100.0;
+ xsane.slider_gray.value[1] = 50.0;
+ xsane.slider_gray.value[0] = 0.0;
+ xsane.slider_red.value[2] = 100.0;
+ xsane.slider_red.value[1] = 50.0;
+ xsane.slider_red.value[0] = 0.0;
+ xsane.slider_green.value[2] = 100.0;
+ xsane.slider_green.value[1] = 50.0;
+ xsane.slider_green.value[0] = 0.0;
+ xsane.slider_blue.value[2] = 100.0;
+ xsane.slider_blue.value[1] = 50.0;
+ xsane.slider_blue.value[0] = 0.0;
+
+ return(xsane_hbox);
+ }
+
+
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) )
{
xsane_separator_new(xsane_vbox_xsane_modus, 2);
}
@@ -1725,7 +1792,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(xsane_vbox_xsane_modus), Gamma_xpm, DESC_GAMMA,
XSANE_GAMMA_MIN, XSANE_GAMMA_MAX, 0.01, 0.1, 2,
&xsane.gamma, &xsane.gamma_widget, 0, xsane_gamma_changed, TRUE);
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) )
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) )
{
xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(xsane_vbox_xsane_modus), Gamma_red_xpm, DESC_GAMMA_R,
XSANE_GAMMA_MIN, XSANE_GAMMA_MAX, 0.01, 0.1, 2,
@@ -1743,7 +1810,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(xsane_vbox_xsane_modus), brightness_xpm, DESC_BRIGHTNESS,
xsane.brightness_min, xsane.brightness_max, 0.1, 1.0, 1,
&xsane.brightness, &xsane.brightness_widget, 0, xsane_gamma_changed, TRUE);
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) )
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) )
{
xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(xsane_vbox_xsane_modus), brightness_red_xpm, DESC_BRIGHTNESS_R,
xsane.brightness_min, xsane.brightness_max, 0.1, 1.0, 1,
@@ -1761,7 +1828,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(xsane_vbox_xsane_modus), contrast_xpm, DESC_CONTRAST,
xsane.contrast_gray_min, xsane.contrast_max, 0.1, 1.0, 1,
&xsane.contrast, &xsane.contrast_widget, 0, xsane_gamma_changed, TRUE);
- if ( (xsane.xsane_colors > 1) && (!xsane.enhancement_rgb_default) )
+ if ( (xsane.xsane_channels > 1) && (!xsane.enhancement_rgb_default) )
{
xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(xsane_vbox_xsane_modus), contrast_red_xpm, DESC_CONTRAST_R,
xsane.contrast_min, xsane.contrast_max, 0.1, 1.0, 1,
@@ -1782,7 +1849,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), xsane_hbox_xsane_enhancement, FALSE, FALSE, 0);
gtk_widget_show(xsane_hbox_xsane_enhancement);
- if (xsane.xsane_colors > 1)
+ if (xsane.xsane_channels > 1)
{
button = xsane_toggle_button_new_with_pixmap(xsane.xsane_window->window, xsane_hbox_xsane_enhancement, rgb_default_xpm, DESC_RGB_DEFAULT,
&xsane.enhancement_rgb_default, xsane_enhancement_rgb_default_callback);
@@ -1795,7 +1862,7 @@ GtkWidget *xsane_update_xsane_callback() /* creates the XSane option window */
button = xsane_button_new_with_pixmap(xsane.xsane_window->window, xsane_hbox_xsane_enhancement, enhance_xpm, DESC_ENH_AUTO,
xsane_auto_enhancement_callback, NULL);
- gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_E, GDK_CONTROL_MASK, DEF_GTK_ACCEL_LOCKED);
+ gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_A, GDK_CONTROL_MASK, DEF_GTK_ACCEL_LOCKED);
button = xsane_button_new_with_pixmap(xsane.xsane_window->window, xsane_hbox_xsane_enhancement, default_enhancement_xpm, DESC_ENH_DEFAULT,
xsane_enhancement_restore_default, NULL);
@@ -1831,7 +1898,8 @@ void xsane_pref_save(void)
DBG(DBG_proc, "xsane_pref_save\n");
/* first save xsane-specific preferences: */
- xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, "xsane", NULL, ".rc", XSANE_PATH_LOCAL_SANE);
+ xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, NULL, xsane.xsane_rc_set_filename, ".rc", XSANE_PATH_LOCAL_SANE);
+// xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, "xsane", NULL, ".rc", XSANE_PATH_LOCAL_SANE);
DBG(DBG_info2, "saving preferences to \"%s\"\n", filename);
@@ -1862,7 +1930,8 @@ static int xsane_pref_restore(void)
DBG(DBG_proc, "xsane_pref_restore\n");
- xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, "xsane", NULL, ".rc", XSANE_PATH_LOCAL_SANE);
+ xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, NULL, xsane.xsane_rc_set_filename, ".rc", XSANE_PATH_LOCAL_SANE);
+// xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", NULL, "xsane", NULL, ".rc", XSANE_PATH_LOCAL_SANE);
fd = open(filename, O_RDONLY);
if (fd >= 0)
@@ -1947,7 +2016,23 @@ static int xsane_pref_restore(void)
if (!preferences.filename)
{
- preferences.filename = strdup(OUT_FILENAME);
+ char filename[PATH_MAX];
+ char buf[PATH_MAX];
+
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), SLASH, OUT_FILENAME);
+ preferences.filename = strdup(buf);
+ }
+ else if (getcwd(filename, sizeof(filename)))
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", filename, SLASH, OUT_FILENAME);
+ preferences.filename = strdup(buf);
+ }
+ else
+ {
+ preferences.filename = strdup("");
+ }
}
if (!preferences.filetype)
@@ -1962,7 +2047,23 @@ static int xsane_pref_restore(void)
if (!preferences.fax_project)
{
- preferences.fax_project = strdup(FAXPROJECT);
+ char filename[PATH_MAX];
+ char buf[PATH_MAX];
+
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), SLASH, FAXPROJECT);
+ preferences.fax_project = strdup(buf);
+ }
+ else if (getcwd(filename, sizeof(filename)))
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", filename, SLASH, FAXPROJECT);
+ preferences.fax_project = strdup(buf);
+ }
+ else
+ {
+ preferences.fax_project = strdup("");
+ }
}
if (!preferences.fax_command)
@@ -2028,7 +2129,23 @@ static int xsane_pref_restore(void)
if (!preferences.email_project)
{
- preferences.email_project = strdup(EMAILPROJECT);
+ char filename[PATH_MAX];
+ char buf[PATH_MAX];
+
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), SLASH, EMAILPROJECT);
+ preferences.email_project = strdup(buf);
+ }
+ else if (getcwd(filename, sizeof(filename)))
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", filename, SLASH, EMAILPROJECT);
+ preferences.email_project = strdup(buf);
+ }
+ else
+ {
+ preferences.email_project = strdup("");
+ }
}
if (!preferences.email_filetype)
@@ -2039,7 +2156,23 @@ static int xsane_pref_restore(void)
if (!preferences.multipage_project)
{
- preferences.multipage_project = strdup(MULTIPAGEPROJECT);
+ char filename[PATH_MAX];
+ char buf[PATH_MAX];
+
+ if (getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)) != NULL)
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", getenv(STRINGIFY(ENVIRONMENT_HOME_DIR_NAME)), SLASH, MULTIPAGEPROJECT);
+ preferences.multipage_project = strdup(buf);
+ }
+ else if (getcwd(filename, sizeof(filename)))
+ {
+ snprintf(buf, sizeof(buf)-2, "%s%c%s", filename, SLASH, MULTIPAGEPROJECT);
+ preferences.multipage_project = strdup(buf);
+ }
+ else
+ {
+ preferences.multipage_project = strdup("");
+ }
}
if (!preferences.multipage_filetype)
@@ -2076,7 +2209,7 @@ static int xsane_pref_restore(void)
{
if (getenv(STRINGIFY(ENVIRONMENT_BROWSER_NAME)))
{
- preferences.browser = getenv(STRINGIFY(ENVIRONMENT_BROWSER_NAME));
+ preferences.browser = strdup(getenv(STRINGIFY(ENVIRONMENT_BROWSER_NAME)));
}
else
{
@@ -2871,6 +3004,55 @@ static void xsane_set_pref_unit_callback(GtkWidget *widget, gpointer data)
}
/* ---------------------------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_LIBLCMS
+static void xsane_enable_color_management_callback(GtkWidget *widget, gpointer data)
+{
+ DBG(DBG_proc, "xsane_enable_color_management_callback\n");
+
+ xsane.enable_color_management = (GTK_CHECK_MENU_ITEM(widget)->active);
+
+ gtk_widget_set_sensitive(xsane.edit_medium_definition_widget, (xsane.enable_color_management) == 0);
+
+ if (xsane.enable_color_management)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(xsane.edit_medium_definition_widget), FALSE);
+ xsane.medium_calibration = FALSE;
+ }
+
+ xsane.gamma = 1.0;
+ xsane.gamma_red = 1.0;
+ xsane.gamma_green = 1.0;
+ xsane.gamma_blue = 1.0;
+ xsane.brightness = 0.0;
+ xsane.brightness_red = 0.0;
+ xsane.brightness_green = 0.0;
+ xsane.brightness_blue = 0.0;
+ xsane.contrast = 0.0;
+ xsane.contrast_red = 0.0;
+ xsane.contrast_green = 0.0;
+ xsane.contrast_blue = 0.0;
+ xsane.threshold = 50.0;
+
+ xsane.slider_gray.value[2] = 100.0;
+ xsane.slider_gray.value[1] = 50.0;
+ xsane.slider_gray.value[0] = 0.0;
+ xsane.slider_red.value[2] = 100.0;
+ xsane.slider_red.value[1] = 50.0;
+ xsane.slider_red.value[0] = 0.0;
+ xsane.slider_green.value[2] = 100.0;
+ xsane.slider_green.value[1] = 50.0;
+ xsane.slider_green.value[0] = 0.0;
+ xsane.slider_blue.value[2] = 100.0;
+ xsane.slider_blue.value[1] = 50.0;
+ xsane.slider_blue.value[0] = 0.0;
+
+ xsane_update_sliders();
+ xsane_update_gamma_curve(FALSE);
+ xsane_batch_scan_update_icon_list();
+ xsane_refresh_dialog();
+}
+#endif
+/* ---------------------------------------------------------------------------------------------------------------------- */
static void xsane_edit_medium_definition_callback(GtkWidget *widget, gpointer data)
{
@@ -3087,7 +3269,7 @@ static void xsane_info_dialog(GtkWidget *widget, gpointer data)
gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 5);
gtk_widget_show(table);
- if ((xsane.xsane_colors > 1) && (xsane.scanner_gamma_color)) /* color gamma correction by scanner */
+ if ((xsane.xsane_channels > 1) && (xsane.scanner_gamma_color)) /* color gamma correction by scanner */
{
const SANE_Option_Descriptor *opt;
@@ -3108,7 +3290,7 @@ static void xsane_info_dialog(GtkWidget *widget, gpointer data)
snprintf(buf, sizeof(buf), "%d bit", (int) (0.5 + log(opt->constraint.range->max+1.0) / log(2.0)));
label = xsane_info_table_text_new(table, buf, 1, 2);
}
- else if ((!xsane.xsane_colors > 1) && (xsane.scanner_gamma_gray)) /* gray gamma correction by scanner */
+ else if ((!xsane.xsane_channels > 1) && (xsane.scanner_gamma_gray)) /* gray gamma correction by scanner */
{
const SANE_Option_Descriptor *opt;
@@ -3996,7 +4178,7 @@ static GtkWidget *xsane_preferences_build_menu(void)
gtk_widget_show(item);
-
+#if 0
/* change working directory */
item = gtk_menu_item_new_with_label(MENU_ITEM_CHANGE_WORKING_DIR);
@@ -4010,6 +4192,18 @@ static GtkWidget *xsane_preferences_build_menu(void)
item = gtk_menu_item_new();
gtk_menu_append(GTK_MENU(menu), item);
gtk_widget_show(item);
+#endif
+
+#ifdef HAVE_LIBLCMS
+ /* enable color management */
+
+ item = gtk_check_menu_item_new_with_label(MENU_ITEM_ENABLE_COLOR_MANAGEMENT);
+ g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_enable_color_management_callback, NULL);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+ xsane.enable_color_management_widget = item;
+#endif
+
/* edit medium definitions */
@@ -4017,6 +4211,7 @@ static GtkWidget *xsane_preferences_build_menu(void)
g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_edit_medium_definition_callback, NULL);
gtk_menu_append(GTK_MENU(menu), item);
gtk_widget_show(item);
+ xsane.edit_medium_definition_widget = item;
/* insert separator: */
@@ -4705,12 +4900,16 @@ static void xsane_device_dialog(void)
GtkWidget *xsane_vbox_advanced;
GdkColormap *colormap;
SANE_Status status;
+ SANE_Handle sane_handle;
DBG(DBG_proc, "xsane_device_dialog\n");
devname = xsane.devlist[xsane.selected_dev]->name;
- status = sane_open(devname, (SANE_Handle *) &xsane.dev);
+/* status = sane_open(devname, (SANE_Handle *) &xsane.dev); // old version */
+ status = sane_open(devname, &sane_handle);
+ xsane.dev = sane_handle;
+
if (status != SANE_STATUS_GOOD)
{
snprintf(buf, sizeof(buf), "%s `%s':\n %s.", ERR_DEVICE_OPEN_FAILED, devname, XSANE_STRSTATUS(status));
@@ -4802,7 +5001,6 @@ static void xsane_device_dialog(void)
xsane.device_text = strdup(devicetext);
-
/* if no preferences filename is given on commandline create one from devicenaname */
if (!xsane.device_set_filename)
@@ -5383,27 +5581,27 @@ static void xsane_choose_device(void)
gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
gtk_widget_show(hbox);
- /* The OK button */
+ /* The Cancel button */
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
- button = gtk_button_new_with_label(BUTTON_OK);
+ button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
- GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_choose_dialog_ok_callback, NULL);
+ gtk_widget_add_accelerator(button, "clicked", device_selection_accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_exit, NULL);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
- gtk_widget_grab_default(button);
gtk_widget_show(button);
- /* The Cancel button */
+ /* The OK button */
#ifdef HAVE_GTK2
- button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ button = gtk_button_new_from_stock(GTK_STOCK_OK);
#else
- button = gtk_button_new_with_label(BUTTON_CANCEL);
+ button = gtk_button_new_with_label(BUTTON_OK);
#endif
- gtk_widget_add_accelerator(button, "clicked", device_selection_accelerator_group, GDK_Escape, 0, DEF_GTK_ACCEL_LOCKED);
- g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_exit, NULL);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_choose_dialog_ok_callback, NULL);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
+ gtk_widget_grab_default(button);
gtk_widget_show(button);
gtk_widget_show(xsane.choose_device_dialog);
@@ -5478,7 +5676,7 @@ static int xsane_init(int argc, char **argv)
{
int ch;
- while((ch = getopt_long(argc, argv, "cd:efghlmnpsvFN:RV", long_options, 0)) != EOF)
+ while((ch = getopt_long(argc, argv, "cd:efghlmnpr:svFN:RV", long_options, 0)) != EOF)
{
switch(ch)
{
@@ -5497,7 +5695,9 @@ static int xsane_init(int argc, char **argv)
g_print(" %s %s\n", TEXT_EMAIL_ADR, XSANE_EMAIL_ADR);
g_print(" %s %s\n", TEXT_PACKAGE, XSANE_PACKAGE_VERSION);
g_print(" %s%d.%d.%d\n", TEXT_GTK_VERSION, GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
-
+#ifdef HAVE_LIBLCMS
+ g_print(" %s\n", TEXT_WITH_CMS_FUNCTION);
+#endif
#ifdef HAVE_ANY_GIMP
g_print(" %s, %s%s\n", TEXT_WITH_GIMP_SUPPORT, TEXT_GIMP_VERSION, GIMP_VERSION);
#else
@@ -5553,6 +5753,10 @@ static int xsane_init(int argc, char **argv)
xsane.device_set_filename = strdup(optarg);
break;
+ case 'r': /* --xsane-rc */
+ xsane.xsane_rc_set_filename = strdup(optarg);
+ break;
+
case 'V': /* --viewer, default */
xsane.xsane_mode = XSANE_VIEWER;
break;
@@ -5606,6 +5810,14 @@ static int xsane_init(int argc, char **argv)
}
}
+ /* if no xsane_rc filename is given on commandline then use "xsane.rc" */
+
+ if (!xsane.xsane_rc_set_filename)
+ {
+ xsane.xsane_rc_set_filename = strdup("xsane"); /* ".rc" is appended later */
+ }
+
+
if (xsane_pref_restore()) /* restore preferences, returns TRUE if license is not accpted yet */
{
if (xsane_display_eula(1)) /* show license and ask for accept/not accept */
@@ -5649,6 +5861,9 @@ static int xsane_init(int argc, char **argv)
device_scanning_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(device_scanning_dialog), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(device_scanning_dialog), FALSE);
+/*
+ gtk_window_set_deletable(GTK_WINDOW(device_scanning_dialog), FALSE);
+*/
snprintf(buf, sizeof(buf), "%s %s", xsane.prog_name, XSANE_VERSION);
gtk_window_set_title(GTK_WINDOW(device_scanning_dialog), buf);
g_signal_connect(GTK_OBJECT(device_scanning_dialog), "delete_event", GTK_SIGNAL_FUNC(xsane_quit), NULL);
@@ -5914,11 +6129,13 @@ int main(int argc, char **argv)
xsane.histogram_int = 1;
xsane.histogram_log = 1;
- xsane.xsane_colors = -1; /* unused value to make sure that change of this vlaue is detected */
+ xsane.xsane_channels = -1; /* unused value to make sure that change of this vlaue is detected */
xsane.scanner_gamma_color = FALSE;
xsane.scanner_gamma_gray = FALSE;
xsane.enhancement_rgb_default = TRUE;
+ xsane.enable_color_management = FALSE;
+
xsane.adf_page_counter = 0;
xsane.print_filenames = FALSE;
xsane.force_filename = FALSE;
diff --git a/src/xsane.h b/src/xsane.h
index 154bb52..4e4ddd8 100644
--- a/src/xsane.h
+++ b/src/xsane.h
@@ -3,7 +3,7 @@
xsane.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify
@@ -69,6 +69,12 @@
#include <gdk/gdk.h>
#include <gtk/gtk.h>
+#ifdef HAVE_LIBLCMS
+# include "lcms.h"
+#else
+# define cmsHTRANSFORM void *
+#endif
+
/* ---------------------------------------------------------------------------------------------------------------------- */
#if 0
@@ -85,10 +91,10 @@
/* ---------------------------------------------------------------------------------------------------------------------- */
-#define XSANE_VERSION "0.991"
+#define XSANE_VERSION "0.993"
#define XSANE_AUTHOR "Oliver Rauch"
#define XSANE_COPYRIGHT "Oliver Rauch"
-#define XSANE_DATE "1998-2006"
+#define XSANE_DATE "1998-2007"
#define XSANE_EMAIL_ADR "Oliver.Rauch@xsane.org"
#define XSANE_HOMEPAGE "http://www.xsane.org"
#define XSANE_COPYRIGHT_TXT XSANE_DATE " " XSANE_COPYRIGHT
@@ -381,7 +387,7 @@ typedef struct Image_info
int image_height;
int depth;
- int colors;
+ int channels;
double resolution_x;
double resolution_y;
@@ -404,6 +410,13 @@ typedef struct Image_info
double threshold;
int reduce_to_lineart;
+
+ int enable_color_management;
+ int cms_function;
+ int cms_intent;
+ int cms_bpc;
+
+ char icm_profile[PATH_MAX];
}
Image_info;
@@ -469,7 +482,14 @@ enum
EMAIL_AUTH_ASMTP_LOGIN,
EMAIL_AUTH_ASMTP_CRAM_MD5
};
-
+
+enum
+{
+ XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE = 0,
+ XSANE_CMS_FUNCTION_CONVERT_TO_SRGB,
+ XSANE_CMS_FUNCTION_CONVERT_TO_WORKING_CS
+};
+
/* ---------------------------------------------------------------------------------------------------------------------- */
extern void xsane_pref_save(void);
@@ -617,6 +637,7 @@ typedef struct Xsane
char *backend;
char *backend_translation;
char *device_set_filename;
+ char *xsane_rc_set_filename;
char *output_filename;
char *dummy_filename;
@@ -739,6 +760,9 @@ typedef struct Xsane
GtkWidget *filename_entry;
GtkWidget *filetype_option_menu;
+ /* for all modes */
+ GtkWidget *cms_function_option_menu;
+
/* saving and transformation values: */
FILE *out;
int xsane_mode;
@@ -816,22 +840,24 @@ typedef struct Xsane
GtkWidget *show_standard_options_widget;
GtkWidget *show_advanced_options_widget;
GtkWidget *show_resolution_list_widget;
- GtkObject *zoom_widget;
- GtkObject *gamma_widget;
- GtkObject *gamma_red_widget;
- GtkObject *gamma_green_widget;
- GtkObject *gamma_blue_widget;
- GtkObject *brightness_widget;
- GtkObject *brightness_red_widget;
- GtkObject *brightness_green_widget;
- GtkObject *brightness_blue_widget;
- GtkObject *contrast_widget;
- GtkObject *contrast_red_widget;
- GtkObject *contrast_green_widget;
- GtkObject *contrast_blue_widget;
- GtkObject *threshold_widget;
-
- SANE_Int xsane_colors;
+ GtkWidget *enable_color_management_widget;
+ GtkWidget *edit_medium_definition_widget;
+ GtkWidget *zoom_widget;
+ GtkWidget *gamma_widget;
+ GtkWidget *gamma_red_widget;
+ GtkWidget *gamma_green_widget;
+ GtkWidget *gamma_blue_widget;
+ GtkWidget *brightness_widget;
+ GtkWidget *brightness_red_widget;
+ GtkWidget *brightness_green_widget;
+ GtkWidget *brightness_blue_widget;
+ GtkWidget *contrast_widget;
+ GtkWidget *contrast_red_widget;
+ GtkWidget *contrast_green_widget;
+ GtkWidget *contrast_blue_widget;
+ GtkWidget *threshold_widget;
+
+ SANE_Int xsane_channels;
SANE_Bool scanner_gamma_color;
SANE_Bool scanner_gamma_gray;
@@ -945,10 +971,17 @@ typedef struct Xsane
int enhancement_rgb_default;
int negative;
int show_preview;
+
+ int enable_color_management;
+ char *scanner_active_icm_profile;
+ char *scanner_default_color_icm_profile;
+ char *scanner_default_gray_icm_profile;
+
int print_filenames;
int force_filename;
char *external_filename;
+
/* -------------------------------------------------- */
int ipc_pipefd[2]; /* for inter process communication error messages */
@@ -974,9 +1007,12 @@ typedef struct XsaneSetup
GtkWidget *printer_gamma_red_entry;
GtkWidget *printer_gamma_green_entry;
GtkWidget *printer_gamma_blue_entry;
+ GtkWidget *printer_icm_profile_entry;
+ GtkWidget *printer_embed_csa_button;
+ GtkWidget *printer_embed_crd_button;
GtkWidget *printer_width_entry;
GtkWidget *printer_height_entry;
- GtkWidget *printer_ps_flatdecoded_button;
+ GtkWidget *printer_ps_flatedecoded_button;
GtkWidget *jpeg_image_quality_scale;
GtkWidget *png_image_compression_scale;
@@ -985,8 +1021,8 @@ typedef struct XsaneSetup
GtkWidget *overwrite_warning_button;
GtkWidget *increase_filename_counter_button;
GtkWidget *skip_existing_numbers_button;
- GtkWidget *save_ps_flatdecoded_button;
- GtkWidget *save_pdf_flatdecoded_button;
+ GtkWidget *save_ps_flatedecoded_button;
+ GtkWidget *save_pdf_flatedecoded_button;
GtkWidget *save_pnm16_as_ascii_button;
GtkWidget *reduce_16bit_to_8bit_button;
@@ -1020,7 +1056,7 @@ typedef struct XsaneSetup
GtkWidget *fax_leftoffset_entry;
GtkWidget *fax_bottomoffset_entry;
GtkWidget *fax_height_entry;
- GtkWidget *fax_ps_flatdecoded_button;
+ GtkWidget *fax_ps_flatedecoded_button;
GtkWidget *tmp_path_entry;
@@ -1041,6 +1077,15 @@ typedef struct XsaneSetup
GtkWidget *ocr_gui_outfd_option_entry;
GtkWidget *ocr_progress_keyword_entry;
+ GtkWidget *cms_intent_option_menu;
+ GtkWidget *cms_bpc_button;
+ GtkWidget *embed_scanner_icm_profile_for_gimp_button;
+ GtkWidget *scanner_default_color_icm_profile_entry;
+ GtkWidget *scanner_default_gray_icm_profile_entry;
+ GtkWidget *display_icm_profile_entry;
+ GtkWidget *custom_proofing_icm_profile_entry;
+ GtkWidget *working_color_space_icm_profile_entry;
+
int filename_counter_len;
int tiff_compression16_nr;
diff --git a/src/xsaneopts.h b/src/xsaneopts.h
index 8dbd655..5e03f54 100644
--- a/src/xsaneopts.h
+++ b/src/xsaneopts.h
@@ -3,7 +3,7 @@
xsaneopts.h
Oliver Rauch <Oliver.Rauch@rauch-domain.de>
- Copyright (C) 1998-2005 Oliver Rauch
+ Copyright (C) 1998-2007 Oliver Rauch
This file is part of the XSANE package.
This program is free software; you can redistribute it and/or modify