summaryrefslogtreecommitdiff
path: root/src/xsane-preview.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xsane-preview.c')
-rw-r--r--src/xsane-preview.c266
1 files changed, 224 insertions, 42 deletions
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");