summaryrefslogtreecommitdiff
path: root/frontend/xsane-preview.c
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/xsane-preview.c')
-rw-r--r--frontend/xsane-preview.c3257
1 files changed, 0 insertions, 3257 deletions
diff --git a/frontend/xsane-preview.c b/frontend/xsane-preview.c
deleted file mode 100644
index a75b12a..0000000
--- a/frontend/xsane-preview.c
+++ /dev/null
@@ -1,3257 +0,0 @@
-/* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend
-
- xsane-preview.c
-
- Oliver Rauch <Oliver.Rauch@Wolfsburg.DE>
- Copyright (C) 1998-2000 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. */
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/*
-
- The preview strategy is as follows:
- -----------------------------------
-
- 1) The preview is done on the full scan area or a part of it.
-
- 2) The preview is zoomable so the user can precisely pick
- the selection area even for small scans on a large scan
- surface.
-
- 3) The preview window is resizeable.
-
- 4) The preview scan resolution depends on preview window size
- and the selected preview surface (zoom area).
-
- 5) We let the user/backend pick whether a preview is in color,
- grayscale, lineart or what not. The only options that the
- preview may (temporarily) modify are:
-
- - resolution (set so the preview fills the window)
- - scan area options (top-left corner, bottom-right corner)
- - preview option (to let the backend know we're doing a preview)
- - gamma table is set to default (gamma=1.0)
-
- 5) The initial size of the scan surface is determined based on the constraints
- of the four corner coordinates. Missing constraints are replaced
- by 0/+INF as appropriate (0 for top-left, +INF for bottom-right coords).
-
- 6) Given the preview window size and the scan surface size, we
- select the resolution so the acquired preview image just fits
- in the preview window. The resulting resolution may be out
- of range in which case we pick the minum/maximum if there is
- a range or word-list constraint or a default value if there is
- no such constraint.
-
- 7) Once a preview image has been acquired, we know the size of the
- preview image (in pixels). An initial scale factor is chosen
- so the image fits into the preview window.
-
-*/
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#include "xsane.h"
-/* #include <sys/param.h> */
-#include "xsane-back-gtk.h"
-#include "xsane-front-gtk.h"
-#include "xsane-preview.h"
-#include "xsane-preferences.h"
-#include "xsane-gamma.h"
-
-
-#ifndef PATH_MAX
-# define PATH_MAX 1024
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-extern const char *prog_name;
-extern const char *device_text;
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* Cut fp conversion routines some slack: */
-#define GROSSLY_DIFFERENT(f1,f2) (fabs ((f1) - (f2)) > 1e-3)
-#define GROSSLY_EQUAL(f1,f2) (fabs ((f1) - (f2)) < 1e-3)
-
-#ifdef __alpha__
- /* This seems to be necessary for at least some XFree86 3.1.2
- servers. It's known to be necessary for the XF86_TGA server for
- Linux/Alpha. Fortunately, it's no great loss so we turn this on
- by default for now. */
-# define XSERVER_WITH_BUGGY_VISUALS
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#define PRESET_AREA_ITEMS 11
-typedef struct
-{
- char *name;
- float width;
- float height;
-} Preset_area;
-
-static const Preset_area preset_area[] =
-{
- { "full size", INF, INF },
- { "DIN A3", 296.98, 420.0 },
- { "DIN A4", 210.0, 296.98 },
- { "DIN A4H", 296.98, 210.0 },
- { "DIN A5", 148.5, 210.0 },
- { "DIN A5H", 210.0, 148.5 },
- { "9x13 cm", 90.0, 130.0 },
- { "13x9 cm", 130.0, 90.0 },
- { "legal", 215.9, 355.6 },
- { "letter", 215.9, 279.4 },
- { "custom", INF, INF }
-};
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static SANE_Int *preview_gamma_data_red = 0;
-static SANE_Int *preview_gamma_data_green = 0;
-static SANE_Int *preview_gamma_data_blue = 0;
-
-static SANE_Int *histogram_gamma_data_red = 0;
-static SANE_Int *histogram_gamma_data_green = 0;
-static SANE_Int *histogram_gamma_data_blue = 0;
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* forward declarations */
-static void preview_order_selection(Preview *p);
-static void preview_bound_selection(Preview *p);
-static void preview_draw_rect(Preview *p, GdkWindow *win, GdkGC *gc, float coord[4]);
-static void preview_draw_selection(Preview *p);
-static void preview_update_selection(Preview *p);
-static void preview_establish_selection(Preview *p);
-/* static void preview_update_batch_selection(Preview *p); */
-static void preview_get_scale_device_to_image(Preview *p, float *xscalep, float *yscalep);
-static void preview_get_scale_device_to_preview(Preview *p, float *xscalep, float *yscalep);
-static void preview_get_scale_preview_to_image(Preview *p, float *xscalep, float *yscalep);
-static void preview_paint_image(Preview *p);
-static void preview_display_partial_image(Preview *p);
-static void preview_display_maybe(Preview *p);
-static void preview_display_image(Preview *p);
-static void preview_save_option(Preview *p, int option, SANE_Word *save_loc, int *valid);
-static void preview_restore_option(Preview *p, int option, SANE_Word saved_value, int valid);
-static void preview_set_option_float(Preview *p, int option, float value);
-static void preview_set_option_bool(Preview *p, int option, SANE_Bool value);
-static void preview_set_option_int(Preview *p, int option, SANE_Int value);
-static int preview_increment_image_y(Preview *p);
-static void preview_read_image_data(gpointer data, gint source, GdkInputCondition cond);
-static void preview_scan_done(Preview *p);
-static void preview_scan_start(Preview *p);
-static int preview_make_image_path(Preview *p, size_t filename_size, char *filename, int level);
-static void preview_restore_image(Preview *p);
-static gint preview_expose_handler(GtkWidget *window, GdkEvent *event, gpointer data);
-static gint preview_event_handler(GtkWidget *window, GdkEvent *event, gpointer data);
-static void preview_start_button_clicked(GtkWidget *widget, gpointer data);
-static void preview_cancel_button_clicked(GtkWidget *widget, gpointer data);
-static void preview_area_correct(Preview *p);
-static void preview_save_image(Preview *p);
-static void preview_zoom_not(GtkWidget *window, gpointer data);
-static void preview_zoom_out(GtkWidget *window, gpointer data);
-static void preview_zoom_in(GtkWidget *window, gpointer data);
-static void preview_zoom_undo(GtkWidget *window, gpointer data);
-static void preview_get_color(Preview *p, int x, int y, int *red, int *green, int *blue);
-static void preview_pipette_white(GtkWidget *window, gpointer data);
-static void preview_pipette_gray(GtkWidget *window, gpointer data);
-static void preview_pipette_black(GtkWidget *window, gpointer data);
-static void preview_full_preview_area(GtkWidget *widget, gpointer call_data);
-static void preview_preset_area_callback(GtkWidget *widget, gpointer call_data);
-
-void preview_do_gamma_correction(Preview *p);
-void preview_calculate_histogram(Preview *p,
- SANE_Int *count_raw, SANE_Int *count_raw_red, SANE_Int *count_raw_green, SANE_Int *count_raw_blue,
- SANE_Int *count, SANE_Int *count_red, SANE_Int *count_green, SANE_Int *count_blue);
-void preview_gamma_correction(Preview *p,
- SANE_Int *gamma_red, SANE_Int *gamma_green, SANE_Int *gamma_blue,
- SANE_Int *gamma_red_hist, SANE_Int *gamma_green_hist, SANE_Int *gamma_blue_hist);
-void preview_area_resize(GtkWidget *widget);
-void preview_update_maximum_output_size(Preview *p);
-void preview_set_maximum_output_size(Preview *p, float width, float height);
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_order_selection(Preview *p)
-{
- float tmp_coordinate;
-
- p->selection.active = ( (p->selection.coordinate[0] != p->selection.coordinate[2]) &&
- (p->selection.coordinate[1] != p->selection.coordinate[3]) );
-
-
- if (p->selection.active)
- {
- if (p->selection.coordinate[0] > p->selection.coordinate[2])
- {
- tmp_coordinate = p->selection.coordinate[0];
- p->selection.coordinate[0] = p->selection.coordinate[2];
- p->selection.coordinate[2] = tmp_coordinate;
-
- p->selection_xedge = (p->selection_xedge + 2) & 3;
- }
-
- if (p->selection.coordinate[1] > p->selection.coordinate[3])
- {
- tmp_coordinate = p->selection.coordinate[1];
- p->selection.coordinate[1] = p->selection.coordinate[3];
- p->selection.coordinate[3] = tmp_coordinate;
-
- p->selection_yedge = (p->selection_yedge + 2) & 3;
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_bound_selection(Preview *p)
-{
-
- p->selection.active = ( (p->selection.coordinate[0] != p->selection.coordinate[2]) &&
- (p->selection.coordinate[1] != p->selection.coordinate[3]) );
-
-
- if (p->selection.active)
- {
- if (p->selection.coordinate[0] < p->scanner_surface[0])
- {
- p->selection.coordinate[0] = p->scanner_surface[0];
- }
-
- if (p->selection.coordinate[1] < p->scanner_surface[1])
- {
- p->selection.coordinate[1] = p->scanner_surface[1];
- }
-
- if (p->selection.coordinate[2] > p->scanner_surface[2])
- {
- p->selection.coordinate[2] = p->scanner_surface[2];
- }
-
- if (p->selection.coordinate[3] > p->scanner_surface[3])
- {
- p->selection.coordinate[3] = p->scanner_surface[3];
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_draw_rect(Preview *p, GdkWindow *win, GdkGC *gc, float coordinate[4])
-{
- float xscale, yscale;
- float x, y, w, h;
- gint xi, yi, wi, hi;
-
- x = coordinate[0];
- y = coordinate[1];
- w = coordinate[2] - x;
- h = coordinate[3] - y;
-
- if (w < 0)
- {
- x = coordinate[2];
- w = -w;
- }
-
- if (h < 0)
- {
- y = coordinate[3];
- h = -h;
- }
-
- preview_get_scale_device_to_preview(p, &xscale, &yscale);
-
- x = x - p->surface[0];
- y = y - p->surface[1];
-
- xi = (gint) (x * xscale + 0.5);
- yi = (gint) (y * yscale + 0.5);
- wi = (gint) (w * xscale + 0.5);
- hi = (gint) (h * yscale + 0.5);
-
- gdk_draw_rectangle(win, gc, FALSE, xi, yi, wi + 1, hi + 1);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_draw_selection(Preview *p)
-{
- if (!p->gc_selection) /* window isn't mapped yet */
- {
- return;
- }
-
- while (gtk_events_pending()) /* make sure all drawing actions are finished */
- {
- gtk_main_iteration();
- }
-
- if (p->previous_selection.active)
- {
- preview_draw_rect(p, p->window->window, p->gc_selection, p->previous_selection.coordinate);
- }
-
- if (p->selection.active)
- {
- preview_draw_rect(p, p->window->window, p->gc_selection, p->selection.coordinate);
- }
-
- p->previous_selection = p->selection;
-
-
- if (!p->gc_selection_maximum) /* window isn't mapped yet */
- {
- return;
- }
-
- if (p->previous_selection_maximum.active)
- {
- preview_draw_rect(p, p->window->window, p->gc_selection_maximum, p->previous_selection_maximum.coordinate);
- }
-
- if (p->selection_maximum.active)
- {
- preview_draw_rect(p, p->window->window, p->gc_selection_maximum, p->selection_maximum.coordinate);
- }
-
- p->previous_selection_maximum = p->selection_maximum;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_update_selection(Preview *p)
-/* draw selection box as defined in backend */
-{
- const SANE_Option_Descriptor *opt;
- SANE_Status status;
- SANE_Word val;
- int i, optnum;
-
- p->previous_selection = p->selection;
-
- for (i = 0; i < 4; ++i)
- {
- optnum = p->dialog->well_known.coord[i];
- if (optnum > 0)
- {
- opt = sane_get_option_descriptor(p->dialog->dev, optnum);
- status = sane_control_option(p->dialog->dev, optnum, SANE_ACTION_GET_VALUE, &val, 0);
- if (status != SANE_STATUS_GOOD)
- {
- continue;
- }
- if (opt->type == SANE_TYPE_FIXED)
- {
- p->selection.coordinate[i] = SANE_UNFIX(val);
- }
- else
- {
- p->selection.coordinate[i] = val;
- }
- }
- else /* backend does not use scanarea options */
- {
- switch (i)
- {
- case 0:
- case 1:
- p->selection.coordinate[i] = 0;
- break;
-
- case 2:
- p->selection.coordinate[i] = p->preview_width;
- break;
-
- case 3:
- p->selection.coordinate[i] = p->preview_height;
- break;
- }
- }
- }
-
- for (i = 0; i < 2; ++i)
- {
- if (p->selection.coordinate[i + 2] < p->selection.coordinate[i])
- {
- p->selection.coordinate[i + 2] = p->selection.coordinate[i];
- }
- }
-
- p->selection.active = ( (p->selection.coordinate[0] != p->selection.coordinate[2]) &&
- (p->selection.coordinate[1] != p->selection.coordinate[3]) );
-
- preview_draw_selection(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_establish_selection(Preview *p)
-{
- /* This routine only shall be called if the preview area really is changed. */
-
- int i;
-
- preview_order_selection(p);
-
- xsane.block_update_param = TRUE; /* do not change parameters each time */
-
- for (i = 0; i < 4; ++i)
- {
- preview_set_option_float(p, p->dialog->well_known.coord[i], p->selection.coordinate[i]);
- }
-
- xsane_back_gtk_update_scan_window(p->dialog);
-
- xsane.block_update_param = FALSE;
-
- if (p->dialog->param_change_callback)
- {
- (*p->dialog->param_change_callback) (p->dialog, p->dialog->param_change_arg);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-#if 0
-static void preview_update_batch_selection(Preview *p)
-{
- Batch_selection *batch_selection;
-
- if (!p->gc_selection) /* window isn't mapped yet */
- {
- return;
- }
-
- batch_selection = p->batch_selection;
-
- while (batch_selection)
- {
- preview_draw_rect(p, p->window->window, p->gc_selection, batch_selection->coordinate);
-
- batch_selection = batch_selection->next;
- }
-}
-#endif
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_get_scale_device_to_image(Preview *p, float *xscalep, float *yscalep)
-{
- float device_width, device_height;
- float xscale = 1.0;
- float yscale = 1.0;
-
- device_width = fabs(p->image_surface[2] - p->image_surface[0]);
- device_height = fabs(p->image_surface[3] - p->image_surface[1]);
-
- if ( (device_width >0) && (device_width < INF) )
- {
- xscale = p->image_width / device_width;
- }
-
- if ( (device_height >0) && (device_height < INF) )
- {
- yscale = p->image_height / device_height;
- }
-
- if (p->surface_unit == SANE_UNIT_PIXEL)
- {
- if (xscale > yscale)
- {
- yscale = xscale;
- }
- else
- {
- xscale = yscale;
- }
- }
-
- *xscalep = xscale;
- *yscalep = yscale;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_get_scale_device_to_preview(Preview *p, float *xscalep, float *yscalep)
-{
- float device_width, device_height;
- float xscale = 1.0;
- float yscale = 1.0;
-
- device_width = fabs(p->image_surface[2] - p->image_surface[0]);
- device_height = fabs(p->image_surface[3] - p->image_surface[1]);
-
- if ( (device_width >0) && (device_width < INF) )
- {
- xscale = p->preview_width / device_width;
- }
-
- if ( (device_height >0) && (device_height < INF) )
- {
- yscale = p->preview_height / device_height;
- }
-
- if (p->surface_unit == SANE_UNIT_PIXEL)
- {
- if (xscale > yscale)
- {
- yscale = xscale;
- }
- else
- {
- xscale = yscale;
- }
- }
-
- *xscalep = xscale;
- *yscalep = yscale;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_get_scale_preview_to_image(Preview *p, float *xscalep, float *yscalep)
-{
- float xscale = 1.0;
- float yscale = 1.0;
-
- if (p->image_width > 0)
- {
- xscale = p->image_width / (float) p->preview_width;
- }
-
- if (p->image_height > 0)
- {
- yscale = p->image_height / (float) p->preview_height;
- }
-
- if (p->surface_unit == SANE_UNIT_PIXEL)
- {
- if (xscale > yscale)
- {
- yscale = xscale;
- }
- else
- {
- xscale = yscale;
- }
- }
-
- *xscalep = xscale;
- *yscalep = yscale;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_paint_image(Preview *p)
-{
- float xscale, yscale, src_x, src_y;
- int dst_x, dst_y, height, x, y, old_y, src_offset;
-
- preview_get_scale_preview_to_image(p, &xscale, &yscale);
-
- memset(p->preview_row, 0x80, 3*p->preview_window_width);
-
- /* don't draw last line unless it's complete: */
- height = p->image_y;
-
- if (p->image_x == 0 && height < p->image_height)
- {
- ++height;
- }
-
- /* for now, use simple nearest-neighbor interpolation: */
- src_offset = 0;
- src_x = src_y = 0.0;
- old_y = -1;
-
- for (dst_y = 0; dst_y < p->preview_height; ++dst_y)
- {
- y = (int) (src_y + 0.5);
- if (y >= height)
- {
- break;
- }
- src_offset = y * 3 * p->image_width;
-
- if ((p->image_data_enh) && (old_y != y))
- {
- old_y = y;
- for (dst_x = 0; dst_x < p->preview_width; ++dst_x)
- {
- x = (int) (src_x + 0.5);
- if (x >= p->image_width)
- {
- break;
- }
-
- p->preview_row[3*dst_x + 0] = p->image_data_enh[src_offset + 3*x + 0];
- p->preview_row[3*dst_x + 1] = p->image_data_enh[src_offset + 3*x + 1];
- p->preview_row[3*dst_x + 2] = p->image_data_enh[src_offset + 3*x + 2];
- src_x += xscale;
- }
- }
- gtk_preview_draw_row(GTK_PREVIEW(p->window), p->preview_row, 0, dst_y, p->preview_window_width);
- src_x = 0.0;
- src_y += yscale;
- }
-
- if (dst_y >= p->preview_height-5)
- {
- memset(p->preview_row, 0x80, 3*p->preview_window_width);
- for (dst_y = p->preview_height-1; dst_y < p->preview_window_height; ++dst_y)
- {
- gtk_preview_draw_row(GTK_PREVIEW(p->window), p->preview_row, 0, dst_y, p->preview_window_width);
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_display_partial_image(Preview *p)
-{
- preview_paint_image(p);
-
- if (GTK_WIDGET_DRAWABLE(p->window))
- {
- GtkPreview *preview = GTK_PREVIEW(p->window);
- int src_x, src_y;
-
- src_x = (p->window->allocation.width - preview->buffer_width)/2;
- src_y = (p->window->allocation.height - preview->buffer_height)/2;
- gtk_preview_put(preview, p->window->window, p->window->style->black_gc, src_x, src_y,
- 0, 0, p->preview_width, p->preview_height);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_display_maybe(Preview *p)
-{
- time_t now;
-
- time(&now);
-
- if (now > p->image_last_time_updated) /* wait at least one secone */
- {
- p->image_last_time_updated = now;
- preview_display_partial_image(p);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_display_image(Preview *p)
-{
- /* if image height was unknown and got larger than expected get missing memory */
- if (p->params.lines <= 0 && p->image_y < p->image_height)
- {
- p->image_height = p->image_y;
- p->image_data_raw = realloc(p->image_data_raw, 3 * p->image_width * p->image_height);
- p->image_data_enh = realloc(p->image_data_enh, 3 * p->image_width * p->image_height);
- assert(p->image_data_raw);
- assert(p->image_data_enh);
- }
-
- memcpy(p->image_data_raw, p->image_data_enh, 3 * p->image_width * p->image_height);
-
- preview_do_gamma_correction(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_save_option(Preview *p, int option, SANE_Word *save_loc, int *valid)
-{
- SANE_Status status;
-
- if (option <= 0)
- {
- *valid = 0;
- return;
- }
-
- status = sane_control_option(p->dialog->dev, option, SANE_ACTION_GET_VALUE, save_loc, 0);
- *valid = (status == SANE_STATUS_GOOD);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_restore_option(Preview *p, int option, SANE_Word saved_value, int valid)
-{
- const SANE_Option_Descriptor *opt;
- SANE_Status status;
- SANE_Handle dev;
-
- if (!valid)
- {
- return;
- }
-
- dev = p->dialog->dev;
- status = sane_control_option(dev, option, SANE_ACTION_SET_VALUE, &saved_value, 0);
-
- if (status != SANE_STATUS_GOOD)
- {
- char buf[256];
- opt = sane_get_option_descriptor(dev, option);
- snprintf(buf, sizeof(buf), "%s %s: %s.", ERR_SET_OPTION, opt->name, XSANE_STRSTATUS(status));
- xsane_back_gtk_error(buf, TRUE);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_set_option_float(Preview *p, int option, float value)
-{
- const SANE_Option_Descriptor *opt;
- SANE_Handle dev;
- SANE_Word word;
-
- if (option <= 0 || value <= -INF || value >= INF)
- {
- return;
- }
-
- dev = p->dialog->dev;
- opt = sane_get_option_descriptor(dev, option);
- if (opt->type == SANE_TYPE_FIXED)
- {
- word = SANE_FIX(value) + 0.5;
- }
- else
- {
- word = value + 0.5;
- }
-
- sane_control_option(dev, option, SANE_ACTION_SET_VALUE, &word, 0);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_set_option_bool(Preview *p, int option, SANE_Bool value)
-{
- SANE_Handle dev;
-
- if (option <= 0)
- return;
-
- dev = p->dialog->dev;
- sane_control_option(dev, option, SANE_ACTION_SET_VALUE, &value, 0);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_set_option_int(Preview *p, int option, SANE_Int value)
-{
- SANE_Handle dev;
-
- if (option <= 0)
- return;
-
- dev = p->dialog->dev;
- sane_control_option(dev, option, SANE_ACTION_SET_VALUE, &value, 0);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int preview_increment_image_y(Preview *p)
-{
- size_t extra_size, offset;
- char buf[256];
-
- p->image_x = 0;
- ++p->image_y;
- if (p->params.lines <= 0 && p->image_y >= p->image_height)
- {
- offset = 3 * p->image_width*p->image_height;
- extra_size = 3 * 32 * p->image_width;
- p->image_height += 32;
- p->image_data_raw = realloc(p->image_data_raw, offset + extra_size);
- p->image_data_enh = realloc(p->image_data_enh, offset + extra_size);
- if ( (!p->image_data_enh) || (!p->image_data_raw) )
- {
- snprintf(buf, sizeof(buf), "%s %s.", ERR_FAILED_ALLOCATE_IMAGE, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
- preview_scan_done(p);
- return -1;
- }
- memset(p->image_data_enh + offset, 0xff, extra_size);
- }
- return 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_read_image_data(gpointer data, gint source, GdkInputCondition cond)
-{
- SANE_Status status;
- Preview *p = data;
- u_char buf[8192];
- SANE_Handle dev;
- SANE_Int len;
- int i, j;
-
- dev = p->dialog->dev;
- while (1)
- {
- status = sane_read(dev, buf, sizeof(buf), &len);
- if (status != SANE_STATUS_GOOD)
- {
- if (status == SANE_STATUS_EOF)
- {
- if (p->params.last_frame) /* got all preview image data */
- {
- preview_display_image(p); /* display preview image */
- preview_save_image(p); /* save preview image */
- preview_scan_done(p); /* scan is done */
- return; /* ok, all finished */
- }
- else
- {
- preview_scan_start(p);
- break;
- }
- }
- else
- {
- snprintf(buf, sizeof(buf), "%s %s.", ERR_DURING_READ, XSANE_STRSTATUS(status));
- xsane_back_gtk_error(buf, TRUE);
- }
- preview_scan_done(p);
- return;
- }
-
- if (!len)
- {
- break; /* out of data for now */
- }
-
- switch (p->params.format)
- {
- case SANE_FRAME_RGB:
- if (p->params.depth != 8)
- {
- goto bad_depth;
- }
-
- for (i = 0; i < len; ++i)
- {
- p->image_data_enh[p->image_offset++] = buf[i];
- if (p->image_offset%3 == 0)
- {
- if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
- {
- return;
- }
- }
- }
- break;
-
- case SANE_FRAME_GRAY:
- switch (p->params.depth)
- {
- case 1:
- for (i = 0; i < len; ++i)
- {
- u_char mask = buf[i];
-
- for (j = 7; j >= 0; --j)
- {
- u_char gl = (mask & (1 << j)) ? 0x00 : 0xff;
- p->image_data_enh[p->image_offset++] = gl;
- p->image_data_enh[p->image_offset++] = gl;
- p->image_data_enh[p->image_offset++] = gl;
- if (++p->image_x >= p->image_width)
- {
- if (preview_increment_image_y(p) < 0)
- {
- return;
- }
- break; /* skip padding bits */
- }
- }
- }
- break;
-
- case 8:
- for (i = 0; i < len; ++i)
- {
- u_char gl = buf[i];
- p->image_data_enh[p->image_offset++] = gl;
- p->image_data_enh[p->image_offset++] = gl;
- p->image_data_enh[p->image_offset++] = gl;
- if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
- {
- return;
- }
- }
- break;
-
- default:
- goto bad_depth;
- }
- break;
-
- case SANE_FRAME_RED:
- case SANE_FRAME_GREEN:
- case SANE_FRAME_BLUE:
- switch (p->params.depth)
- {
- case 1:
- for (i = 0; i < len; ++i)
- {
- u_char mask = buf[i];
-
- for (j = 0; j < 8; ++j)
- {
- u_char gl = (mask & 1) ? 0xff : 0x00;
- mask >>= 1;
- p->image_data_enh[p->image_offset++] = gl;
- p->image_offset += 3;
- if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
- {
- return;
- }
- }
- }
- break;
-
- case 8:
- for (i = 0; i < len; ++i)
- {
- p->image_data_enh[p->image_offset] = buf[i];
- p->image_offset += 3;
- if (++p->image_x >= p->image_width && preview_increment_image_y(p) < 0)
- {
- return;
- }
- }
- break;
-
- default:
- goto bad_depth;
- }
- break;
-
- default:
- fprintf(stderr, "preview_read_image_data: %s %d\n", ERR_BAD_FRAME_FORMAT, p->params.format);
- preview_scan_done(p);
- return;
- }
-
- if (p->input_tag < 0)
- {
- preview_display_maybe(p);
- while (gtk_events_pending())
- {
- gtk_main_iteration();
- }
- }
- }
- preview_display_maybe(p);
- return;
-
-bad_depth:
- snprintf(buf, sizeof(buf), "%s %d.", ERR_PREVIEW_BAD_DEPTH, p->params.depth);
- xsane_back_gtk_error(buf, TRUE);
- preview_scan_done(p);
- return;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_scan_done(Preview *p)
-{
- int i;
-
- p->scanning = FALSE;
-
- if (p->input_tag >= 0)
- {
- gdk_input_remove(p->input_tag);
- p->input_tag = -1;
- }
-
- sane_cancel(p->dialog->dev);
-
- xsane.block_update_param = TRUE; /* do not change parameters each time */
-
- preview_restore_option(p, p->dialog->well_known.dpi, p->saved_dpi, p->saved_dpi_valid);
- preview_restore_option(p, p->dialog->well_known.dpi_x, p->saved_dpi_x, p->saved_dpi_x_valid);
- preview_restore_option(p, p->dialog->well_known.dpi_y, p->saved_dpi_y, p->saved_dpi_y_valid);
-
- for (i = 0; i < 4; ++i)
- {
- preview_restore_option(p, p->dialog->well_known.coord[i], p->saved_coord[i], p->saved_coord_valid[i]);
- }
-
- preview_restore_option(p, p->dialog->well_known.bit_depth, p->saved_bit_depth, p->saved_bit_depth_valid);
-
- preview_set_option_bool(p, p->dialog->well_known.preview, SANE_FALSE);
-
- gtk_widget_set_sensitive(p->cancel, FALSE);
- xsane_set_sensitivity(TRUE);
-
- xsane.block_update_param = FALSE;
-
- preview_update_surface(p, 0); /* if surface was not defined it's necessary to redefine it now */
-
- preview_update_selection(p);
- xsane_update_histogram();
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int preview_get_memory(Preview *p)
-{
- char buf[256];
-
- if (p->image_data_enh)
- {
- free(p->image_data_enh);
- p->image_data_enh = 0;
- }
-
- if (p->image_data_raw)
- {
- free(p->image_data_raw);
- p->image_data_raw = 0;
- }
-
- if (p->preview_row)
- {
- free(p->preview_row);
- p->preview_row = 0;
- }
-
- p->image_data_enh = malloc(3 * p->image_width * (p->image_height));
- p->image_data_raw = malloc(3 * p->image_width * (p->image_height));
- p->preview_row = malloc(3 * p->preview_window_width);
-
- if ( (!p->image_data_raw) || (!p->image_data_enh) || (!p->preview_row) )
- {
- if (p->image_data_enh)
- {
- free(p->image_data_enh);
- p->image_data_enh = 0;
- }
-
- if (p->image_data_raw)
- {
- free(p->image_data_raw);
- p->image_data_raw = 0;
- }
-
- if (p->preview_row)
- {
- free(p->preview_row);
- p->preview_row = 0;
- }
-
- snprintf(buf, sizeof(buf), "%s %s.", ERR_FAILED_ALLOCATE_IMAGE, strerror(errno));
- xsane_back_gtk_error(buf, TRUE);
-
- return -1; /* error */
- }
-
- memset(p->image_data_enh, 0xff, 3*p->image_width*p->image_height); /* clean memory */
-
- return 0; /* ok */
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_scan_start(Preview *p)
-{
- SANE_Handle dev = p->dialog->dev;
- SANE_Status status;
- char buf[256];
- int fd, y, i;
- int gamma_gray_size = 256; /* set this values to image depth for more than 8bpp input support!!! */
- int gamma_red_size = 256;
- int gamma_green_size = 256;
- int gamma_blue_size = 256;
- int gamma_gray_max = 255; /* set this to to image depth for more than 8bpp output support */
- int gamma_red_max = 255;
- int gamma_green_max = 255;
- int gamma_blue_max = 255;
-
- for (i=0; i<4; i++)
- {
- p->image_surface[i] = p->surface[i];
- }
-
- xsane_clear_histogram(&xsane.histogram_raw);
- xsane_clear_histogram(&xsane.histogram_enh);
- gtk_widget_set_sensitive(p->cancel, TRUE);
- xsane_set_sensitivity(FALSE);
-
- /* clear old preview: */
- memset(p->preview_row, 0xff, 3*p->preview_width);
- for (y = 0; y < p->preview_height; ++y)
- {
- gtk_preview_draw_row(GTK_PREVIEW(p->window), p->preview_row, 0, y, p->preview_width);
- }
-
- if (p->input_tag >= 0)
- {
- gdk_input_remove(p->input_tag);
- p->input_tag = -1;
- }
-
- if (p->dialog->well_known.gamma_vector >0)
- {
- const SANE_Option_Descriptor *opt;
-
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.gamma_vector);
- if (SANE_OPTION_IS_ACTIVE(opt->cap))
- {
- SANE_Int *gamma_data;
-
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.gamma_vector);
- gamma_gray_size = opt->size / sizeof(opt->type);
- gamma_gray_max = opt->constraint.range->max;
-
- gamma_data = malloc(gamma_gray_size * sizeof(SANE_Int));
- xsane_create_gamma_curve(gamma_data, 0, 1.0, 0.0, 0.0, gamma_gray_size, gamma_gray_max);
- xsane_back_gtk_update_vector(p->dialog, p->dialog->well_known.gamma_vector, gamma_data);
- free(gamma_data);
- }
- }
-
- if (p->dialog->well_known.gamma_vector_r >0)
- {
- const SANE_Option_Descriptor *opt;
-
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.gamma_vector_r);
- if (SANE_OPTION_IS_ACTIVE(opt->cap))
- {
- SANE_Int *gamma_data_red, *gamma_data_green, *gamma_data_blue;
-
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.gamma_vector_r);
- gamma_red_size = opt->size / sizeof(opt->type);
- gamma_red_max = opt->constraint.range->max;
-
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.gamma_vector_g);
- gamma_green_size = opt->size / sizeof(opt->type);
- gamma_green_max = opt->constraint.range->max;
-
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.gamma_vector_b);
- gamma_blue_size = opt->size / sizeof(opt->type);
- gamma_blue_max = opt->constraint.range->max;
-
- gamma_data_red = malloc(gamma_red_size * sizeof(SANE_Int));
- gamma_data_green = malloc(gamma_green_size * sizeof(SANE_Int));
- gamma_data_blue = malloc(gamma_blue_size * sizeof(SANE_Int));
-
- xsane_create_gamma_curve(gamma_data_red, 0, 1.0, 0.0, 0.0, gamma_red_size, gamma_red_max);
- xsane_create_gamma_curve(gamma_data_green, 0, 1.0, 0.0, 0.0, gamma_green_size, gamma_green_max);
- xsane_create_gamma_curve(gamma_data_blue, 0, 1.0, 0.0, 0.0, gamma_blue_size, gamma_blue_max);
-
- xsane_back_gtk_update_vector(p->dialog, p->dialog->well_known.gamma_vector_r, gamma_data_red);
- xsane_back_gtk_update_vector(p->dialog, p->dialog->well_known.gamma_vector_g, gamma_data_green);
- xsane_back_gtk_update_vector(p->dialog, p->dialog->well_known.gamma_vector_b, gamma_data_blue);
-
- free(gamma_data_red);
- free(gamma_data_green);
- free(gamma_data_blue);
- }
- }
-
- status = sane_start(dev);
- if (status != SANE_STATUS_GOOD)
- {
- snprintf(buf, sizeof(buf), "%s %s.", ERR_FAILED_START_SCANNER, XSANE_STRSTATUS(status));
- xsane_back_gtk_error(buf, TRUE);
- preview_scan_done(p);
- return;
- }
-
- status = sane_get_parameters(dev, &p->params);
- if (status != SANE_STATUS_GOOD)
- {
- snprintf(buf, sizeof(buf), "%s %s.", ERR_FAILED_GET_PARAMS, XSANE_STRSTATUS(status));
- xsane_back_gtk_error(buf, TRUE);
- preview_scan_done(p);
- return;
- }
-
- p->image_offset = p->image_x = p->image_y = 0;
-
- if (p->params.format >= SANE_FRAME_RED && p->params.format <= SANE_FRAME_BLUE)
- {
- p->image_offset = p->params.format - SANE_FRAME_RED;
- }
-
- if ( (!p->image_data_enh) || (p->params.pixels_per_line != p->image_width)
- || ( (p->params.lines >= 0) && (p->params.lines != p->image_height) ) )
- {
- p->image_width = p->params.pixels_per_line;
- p->image_height = p->params.lines;
-
- if (p->image_height < 0)
- {
- p->image_height = 32; /* may have to adjust as we go... */
- }
-
- if (preview_get_memory(p))
- {
- preview_scan_done(p); /* error */
- return;
- }
- }
-
-/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-/* THIS IS A BIT STRANGE HERE */
- p->selection.active = FALSE;
- p->previous_selection_maximum.active = FALSE;
-/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-
- p->scanning = TRUE;
-
- if (sane_set_io_mode(dev, SANE_TRUE) == SANE_STATUS_GOOD && sane_get_select_fd(dev, &fd) == SANE_STATUS_GOOD)
- {
- p->input_tag = gdk_input_add(fd, GDK_INPUT_READ, preview_read_image_data, p);
- }
- else
- {
- preview_read_image_data(p, -1, GDK_INPUT_READ);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int preview_make_image_path(Preview *p, size_t filename_size, char *filename, int level)
-{
- char buf[256];
-
- snprintf(buf, sizeof(buf), "preview-level-%d-", level);
- return xsane_back_gtk_make_path(filename_size, filename, 0, 0, buf, p->dialog->dev_name, ".ppm", XSANE_PATH_TMP);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static int preview_restore_image_from_file(Preview *p, FILE *in, int min_quality)
-{
- u_int psurface_type, psurface_unit;
- int image_width, image_height;
- int xoffset, yoffset, width, height;
- int quality;
- int y;
- float psurface[4];
- size_t nread;
- char *imagep;
-
- if (!in)
- {
- return min_quality;
- }
-
- /* See whether there is a saved preview and load it if present: */
-
- if (fscanf(in, "P6\n# surface: %g %g %g %g %u %u\n%d %d\n255\n",
- psurface + 0, psurface + 1, psurface + 2, psurface + 3,
- &psurface_type, &psurface_unit,
- &image_width, &image_height) != 8)
- {
- return min_quality;
- }
-
- if ((psurface_type != p->surface_type) || (psurface_unit != p->surface_unit))
- {
- return min_quality;
- }
-
- xoffset = (p->surface[0] - psurface[0])/(psurface[2] - psurface[0]) * image_width;
- yoffset = (p->surface[1] - psurface[1])/(psurface[3] - psurface[1]) * image_height;
- width = (p->surface[2] - p->surface[0])/(psurface[2] - psurface[0]) * image_width;
- height = (p->surface[3] - p->surface[1])/(psurface[3] - psurface[1]) * image_height;
- quality = width;
-
- if ((xoffset < 0) || (yoffset < 0) ||
- (xoffset+width > image_width) || (yoffset+height > image_height) ||
- (width == 0) || (height == 0))
- {
- return min_quality;
- }
-
- if (quality < min_quality)
- {
- return min_quality;
- }
-
- p->params.depth = 8;
- p->image_width = width;
- p->image_height = height;
-
- if (preview_get_memory(p))
- {
- return min_quality; /* error allocating memory */
- }
-
- fseek(in, yoffset * 3 * image_width, SEEK_CUR); /* skip unused lines */
-
- imagep = p->image_data_enh;
-
- for (y = yoffset; y < yoffset + height; y++)
- {
- fseek(in, xoffset * 3, SEEK_CUR); /* skip unused pixel left of area */
-
- nread = fread(imagep, 3, width, in);
- imagep += width * 3;
-
- fseek(in, (image_width - width - xoffset) * 3, SEEK_CUR); /* skip unused pixel right of area */
- }
-
- p->image_y = height;
- p->image_x = width;
-
- p->image_surface[0] = p->surface[0];
- p->image_surface[1] = p->surface[1];
- p->image_surface[2] = p->surface[2];
- p->image_surface[3] = p->surface[3];
-
- return quality;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_restore_image(Preview *p)
-{
- char filename[PATH_MAX];
- FILE *in;
- int status;
- int quality = 0;
- int level;
-
- /* See whether there is a saved preview and load it if present: */
-
- for(level = 2; level >= 0; level--)
- {
- status = preview_make_image_path(p, sizeof(filename), filename, level);
- if (status >= 0)
- {
- in = fopen(filename, "r");
- if (in)
- {
- quality = preview_restore_image_from_file(p, in, quality);
- }
- }
- }
- memcpy(p->image_data_raw, p->image_data_enh, 3 * p->image_width * p->image_height);
-
-/* the following commands may be removed because they are done because a event is emmited */
- preview_do_gamma_correction(p);
- xsane_update_histogram();
- preview_draw_selection(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-/* This is executed _after_ the gtkpreview's expose routine. */
-static gint preview_expose_handler(GtkWidget *window, GdkEvent *event, gpointer data)
-{
- Preview *p = data;
-
- p->previous_selection.active = FALSE; /* ok, old selections are overpainted */
- p->previous_selection_maximum.active = FALSE;
- p->selection.active = TRUE; /* ok, old selections are overpainted */
- p->selection_maximum.active = TRUE;
- preview_draw_selection(p); /* draw selections again */
-
- return FALSE;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static gint preview_event_handler(GtkWidget *window, GdkEvent *event, gpointer data)
-{
- Preview *p = data;
- GdkCursor *cursor;
- GdkColor color;
- GdkColormap *colormap;
- float preview_selection[4];
- float xscale, yscale;
- static int event_count = 0;
- int cursornr;
-
- event_count++;
-
- preview_get_scale_device_to_preview(p, &xscale, &yscale);
-
- preview_selection[0] = xscale * (p->selection.coordinate[0] - p->surface[0]);
- preview_selection[1] = yscale * (p->selection.coordinate[1] - p->surface[1]);
- preview_selection[2] = xscale * (p->selection.coordinate[2] - p->surface[0]);
- preview_selection[3] = yscale * (p->selection.coordinate[3] - p->surface[1]);
-
- if (event->type == GDK_EXPOSE)
- {
- if (!p->gc_selection)
- {
- colormap = gdk_window_get_colormap(p->window->window);
-
- p->gc_selection = gdk_gc_new(p->window->window);
- gdk_gc_set_function(p->gc_selection, GDK_INVERT);
- gdk_gc_set_line_attributes(p->gc_selection, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
-
- p->gc_selection_maximum = gdk_gc_new(p->window->window);
- gdk_gc_set_function(p->gc_selection_maximum, GDK_XOR);
- gdk_gc_set_line_attributes(p->gc_selection_maximum, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
- color.red = 0;
- color.green = 65535;
- color.blue = 30000;
- gdk_color_alloc(colormap, &color);
- gdk_gc_set_foreground(p->gc_selection_maximum, &color);
-
- preview_paint_image(p);
- }
- else
- {
- while (gtk_events_pending()) /* make sure image is updated */
- {
- gtk_main_iteration();
- }
-
- p->previous_selection.active = FALSE; /* ok, old selections are overpainted */
- p->previous_selection_maximum.active = FALSE;
- preview_draw_selection(p); /* draw selections again */
- }
- }
- else if (!p->scanning)
- {
- switch (event->type)
- {
- case GDK_UNMAP:
- case GDK_MAP:
- break;
-
- case GDK_BUTTON_PRESS:
- switch (p->mode)
- {
- case MODE_PIPETTE_WHITE:
- {
- if ( ( (((GdkEventButton *)event)->button == 1) || (((GdkEventButton *)event)->button == 2) ) &&
- (p->image_data_raw) ) /* left or middle button */
- {
- int r,g,b;
-
- preview_get_color(p, event->button.x, event->button.y, &r, &g, &b);
-
- xsane.slider_gray.value[2] = sqrt( (r*r+g*g+b*b) / 3)/2.55;
-
- if ( (!xsane.enhancement_rgb_default) && (((GdkEventButton *)event)->button == 2) ) /* middle button */
- {
- xsane.slider_red.value[2] = r/2.55;
- xsane.slider_green.value[2] = g/2.55;
- xsane.slider_blue.value[2] = b/2.55;
- }
- else
- {
- xsane.slider_red.value[2] = xsane.slider_gray.value[2];
- xsane.slider_green.value[2] = xsane.slider_gray.value[2];
- xsane.slider_blue.value[2] = xsane.slider_gray.value[2];
- }
-
- if (xsane.slider_gray.value[2] < 2)
- {
- xsane.slider_gray.value[2] = 2;
- }
- if (xsane.slider_gray.value[1] >= xsane.slider_gray.value[2])
- {
- xsane.slider_gray.value[1] = xsane.slider_gray.value[2]-1;
- if (xsane.slider_gray.value[0] >= xsane.slider_gray.value[1])
- {
- xsane.slider_gray.value[0] = xsane.slider_gray.value[1]-1;
- }
- }
-
- if (xsane.slider_red.value[2] < 2)
- {
- xsane.slider_red.value[2] = 2;
- }
- if (xsane.slider_red.value[1] >= xsane.slider_red.value[2])
- {
- xsane.slider_red.value[1] = xsane.slider_red.value[2]-1;
- if (xsane.slider_red.value[0] >= xsane.slider_red.value[1])
- {
- xsane.slider_red.value[0] = xsane.slider_red.value[1]-1;
- }
- }
-
- if (xsane.slider_green.value[2] < 2)
- {
- xsane.slider_green.value[2] = 2;
- }
- if (xsane.slider_green.value[1] >= xsane.slider_green.value[2])
- {
- xsane.slider_green.value[1] = xsane.slider_green.value[2]-1;
- if (xsane.slider_green.value[0] >= xsane.slider_green.value[1])
- {
- xsane.slider_green.value[0] = xsane.slider_green.value[1]-1;
- }
- }
-
- if (xsane.slider_blue.value[2] < 2)
- {
- xsane.slider_blue.value[2] = 2;
- }
- if (xsane.slider_blue.value[1] >= xsane.slider_blue.value[2])
- {
- xsane.slider_blue.value[1] = xsane.slider_blue.value[2]-1;
- if (xsane.slider_blue.value[0] >= xsane.slider_blue.value[1])
- {
- xsane.slider_blue.value[0] = xsane.slider_blue.value[1]-1;
- }
- }
-
- xsane_enhancement_by_histogram();
- }
-
- p->mode = MODE_NORMAL;
-
- cursor = gdk_cursor_new(XSANE_CURSOR_PREVIEW);
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = XSANE_CURSOR_PREVIEW;
- }
- break;
-
- case MODE_PIPETTE_GRAY:
- {
- if ( ( (((GdkEventButton *)event)->button == 1) || (((GdkEventButton *)event)->button == 2) ) &&
- (p->image_data_raw) ) /* left or middle button */
- {
- int r,g,b;
-
- preview_get_color(p, event->button.x, event->button.y, &r, &g, &b);
-
- xsane.slider_gray.value[1] = sqrt( (r*r+g*g+b*b) / 3)/2.55;
-
- if ( (!xsane.enhancement_rgb_default) && (((GdkEventButton *)event)->button == 2) ) /* middle button */
- {
- xsane.slider_red.value[1] = r/2.55;
- xsane.slider_green.value[1] = g/2.55;
- xsane.slider_blue.value[1] = b/2.55;
- }
- else
- {
- xsane.slider_red.value[1] = xsane.slider_gray.value[1];
- xsane.slider_green.value[1] = xsane.slider_gray.value[1];
- xsane.slider_blue.value[1] = xsane.slider_gray.value[1];
- }
-
- if (xsane.slider_gray.value[1] == 0)
- {
- xsane.slider_gray.value[1] += 1;
- }
- if (xsane.slider_gray.value[1] == 100)
- {
- xsane.slider_gray.value[1] -= 1;
- }
- if (xsane.slider_gray.value[1] >= xsane.slider_gray.value[2])
- {
- xsane.slider_gray.value[2] = xsane.slider_gray.value[1]+1;
- }
- if (xsane.slider_gray.value[1] <= xsane.slider_gray.value[0])
- {
- xsane.slider_gray.value[0] = xsane.slider_gray.value[1]-1;
- }
-
- if (xsane.slider_red.value[1] == 0)
- {
- xsane.slider_red.value[1] += 1;
- }
- if (xsane.slider_red.value[1] == 100)
- {
- xsane.slider_red.value[1] -= 1;
- }
- if (xsane.slider_red.value[1] >= xsane.slider_red.value[2])
- {
- xsane.slider_red.value[2] = xsane.slider_red.value[1]+1;
- }
- if (xsane.slider_red.value[1] <= xsane.slider_red.value[0])
- {
- xsane.slider_red.value[0] = xsane.slider_red.value[1]-1;
- }
-
- if (xsane.slider_green.value[1] == 0)
- {
- xsane.slider_green.value[1] += 1;
- }
- if (xsane.slider_green.value[1] == 100)
- {
- xsane.slider_green.value[1] -= 1;
- }
- if (xsane.slider_green.value[1] >= xsane.slider_green.value[2])
- {
- xsane.slider_green.value[2] = xsane.slider_green.value[1]+1;
- }
- if (xsane.slider_green.value[1] <= xsane.slider_green.value[0])
- {
- xsane.slider_green.value[0] = xsane.slider_green.value[1]-1;
- }
-
- if (xsane.slider_blue.value[1] == 0)
- {
- xsane.slider_blue.value[1] += 1;
- }
- if (xsane.slider_blue.value[1] == 100)
- {
- xsane.slider_blue.value[1] -= 1;
- }
- if (xsane.slider_blue.value[1] >= xsane.slider_blue.value[2])
- {
- xsane.slider_blue.value[2] = xsane.slider_blue.value[1]+1;
- }
- if (xsane.slider_blue.value[1] <= xsane.slider_blue.value[0])
- {
- xsane.slider_blue.value[0] = xsane.slider_blue.value[1]-1;
- }
-
- xsane_enhancement_by_histogram();
- }
-
- p->mode = MODE_NORMAL;
-
- cursor = gdk_cursor_new(XSANE_CURSOR_PREVIEW);
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = XSANE_CURSOR_PREVIEW;
- }
- break;
-
- case MODE_PIPETTE_BLACK:
- {
- if ( ( (((GdkEventButton *)event)->button == 1) || (((GdkEventButton *)event)->button == 2) ) &&
- (p->image_data_raw) ) /* left or middle button */
- {
- int r,g,b;
-
- preview_get_color(p, event->button.x, event->button.y, &r, &g, &b);
-
- xsane.slider_gray.value[0] = sqrt( (r*r+g*g+b*b) / 3)/2.55;
-
- if ( (!xsane.enhancement_rgb_default) && (((GdkEventButton *)event)->button == 2) ) /* middle button */
- {
- xsane.slider_red.value[0] = r/2.55;
- xsane.slider_green.value[0] = g/2.55;
- xsane.slider_blue.value[0] = b/2.55;
- }
- else
- {
- xsane.slider_red.value[0] = xsane.slider_gray.value[0];
- xsane.slider_green.value[0] = xsane.slider_gray.value[0];
- xsane.slider_blue.value[0] = xsane.slider_gray.value[0];
- }
-
- if (xsane.slider_gray.value[0] > 98)
- {
- xsane.slider_gray.value[0] = 98;
- }
- if (xsane.slider_gray.value[1] <= xsane.slider_gray.value[0])
- {
- xsane.slider_gray.value[1] = xsane.slider_gray.value[0]+1;
- if (xsane.slider_gray.value[2] <= xsane.slider_gray.value[1])
- {
- xsane.slider_gray.value[2] = xsane.slider_gray.value[1]+1;
- }
- }
-
- if (xsane.slider_red.value[0] > 98)
- {
- xsane.slider_red.value[0] = 98;
- }
- if (xsane.slider_red.value[1] <= xsane.slider_red.value[0])
- {
- xsane.slider_red.value[1] = xsane.slider_red.value[0]+1;
- if (xsane.slider_red.value[2] <= xsane.slider_red.value[1])
- {
- xsane.slider_red.value[2] = xsane.slider_red.value[1]+1;
- }
- }
-
- if (xsane.slider_green.value[0] > 98)
- {
- xsane.slider_green.value[0] = 98;
- }
- if (xsane.slider_green.value[1] <= xsane.slider_green.value[0])
- {
- xsane.slider_green.value[1] = xsane.slider_green.value[0]+1;
- if (xsane.slider_green.value[2] <= xsane.slider_green.value[1])
- {
- xsane.slider_green.value[2] = xsane.slider_green.value[1]+1;
- }
- }
-
- if (xsane.slider_blue.value[0] > 98)
- {
- xsane.slider_blue.value[0] = 98;
- }
- if (xsane.slider_blue.value[1] <= xsane.slider_blue.value[0])
- {
- xsane.slider_blue.value[1] = xsane.slider_blue.value[0]+1;
- if (xsane.slider_blue.value[2] <= xsane.slider_blue.value[1])
- {
- xsane.slider_blue.value[2] = xsane.slider_blue.value[1]+1;
- }
- }
-
- xsane_enhancement_by_histogram();
- }
-
- p->mode = MODE_NORMAL;
-
- cursor = gdk_cursor_new(XSANE_CURSOR_PREVIEW);
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = XSANE_CURSOR_PREVIEW;
- }
- break;
-
- case MODE_NORMAL:
- {
- switch (((GdkEventButton *)event)->button)
- {
- case 1: /* left button */
- p->selection_xedge = -1;
- if ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) && (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) /* left */
- {
- p->selection_xedge = 0;
- }
- else if ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) && (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) /* right */
- {
- p->selection_xedge = 2;
- }
-
- p->selection_yedge = -1;
- if ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) && (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) /* top */
- {
- p->selection_yedge = 1;
- }
- else if ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) && (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) /* bottom */
- {
- p->selection_yedge = 3;
- }
-
- if ( (p->selection_xedge != -1) && (p->selection_yedge != -1) ) /* move edge */
- {
- p->selection_drag_edge = TRUE;
- p->selection.coordinate[p->selection_xedge] = p->surface[0] + event->button.x / xscale;
- p->selection.coordinate[p->selection_yedge] = p->surface[1] + event->button.y / yscale;
- preview_draw_selection(p);
- }
- else /* select new area */
- {
- p->selection_xedge = 2;
- p->selection_yedge = 3;
- p->selection.coordinate[0] = p->surface[0] + event->button.x / xscale;
- p->selection.coordinate[1] = p->surface[1] + event->button.y / yscale;
- p->selection_drag = TRUE;
-
- cursornr = GDK_CROSS;
- cursor = gdk_cursor_new(cursornr); /* set curosr */
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = cursornr;
- }
- break;
-
- case 2: /* middle button */
- case 3: /* right button */
- if ( (preview_selection[0]-SELECTION_RANGE_OUT < event->button.x) &&
- (preview_selection[2]+SELECTION_RANGE_OUT > event->button.x) &&
- (preview_selection[1]-SELECTION_RANGE_OUT < event->button.y) &&
- (preview_selection[3]+SELECTION_RANGE_OUT > event->button.y) )
- {
- p->selection_drag = TRUE;
- p->selection_xpos = event->button.x;
- p->selection_ypos = event->button.y;
-
- cursornr = GDK_HAND2;
- cursor = gdk_cursor_new(cursornr); /* set curosr */
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = cursornr;
- }
- break;
-
- default:
- break;
- }
- }
- }
- break;
-
- case GDK_BUTTON_RELEASE:
- switch (((GdkEventButton *)event)->button)
- {
- case 1: /* left button */
- case 2: /* middle button */
- case 3: /* right button */
- if (p->selection_drag)
- {
- cursornr = XSANE_CURSOR_PREVIEW;
- cursor = gdk_cursor_new(cursornr); /* set curosr */
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = cursornr;
- }
-
- if ( (p->selection_drag) || (p->selection_drag_edge) )
- {
-
- if (((GdkEventButton *)event)->button == 1) /* left button */
- {
- p->selection.coordinate[p->selection_xedge] = p->surface[0] + event->button.x / xscale;
- p->selection.coordinate[p->selection_yedge] = p->surface[1] + event->button.y / yscale;
- }
-
- p->selection_drag_edge = FALSE;
- p->selection_drag = FALSE;
-
- preview_order_selection(p);
- preview_bound_selection(p);
- preview_update_maximum_output_size(p);
- preview_draw_selection(p);
- preview_establish_selection(p);
- }
- default:
- break;
- }
- break;
-
- case GDK_MOTION_NOTIFY:
- switch (((GdkEventMotion *)event)->state)
- {
- case 256: /* left button */
- if (p->selection_drag_edge)
- {
- p->selection.active = TRUE;
- p->selection.coordinate[p->selection_xedge] = p->surface[0] + event->button.x / xscale;
- p->selection.coordinate[p->selection_yedge] = p->surface[1] + event->button.y / yscale;
-
- preview_order_selection(p);
- preview_bound_selection(p);
- preview_update_maximum_output_size(p);
- preview_draw_selection(p);
-
- if ((preferences.gtk_update_policy == GTK_UPDATE_CONTINUOUS) && (event_count == 1))
- {
- preview_establish_selection(p);
- }
- else if ((preferences.gtk_update_policy == GTK_UPDATE_DELAYED) && (event_count == 1))
- {
- preview_establish_selection(p);
- }
- }
-
- if (p->selection_drag)
- {
- p->selection.active = TRUE;
- p->selection.coordinate[p->selection_xedge] = p->surface[0] + event->motion.x / xscale;
- p->selection.coordinate[p->selection_yedge] = p->surface[1] + event->motion.y / yscale;
-
- preview_order_selection(p);
- preview_bound_selection(p);
- preview_update_maximum_output_size(p);
- preview_draw_selection(p);
-
- if ((preferences.gtk_update_policy == GTK_UPDATE_CONTINUOUS) && (event_count == 1))
- {
- preview_establish_selection(p);
- }
- else if ((preferences.gtk_update_policy == GTK_UPDATE_DELAYED) && (event_count == 1))
- {
- preview_establish_selection(p);
- }
- }
-
- cursornr = p->cursornr;
-
- if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) && (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left */
- ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) && (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
- {
- cursornr = GDK_TOP_LEFT_CORNER;
- }
- else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) && (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
- ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) && (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
- {
- cursornr = GDK_TOP_RIGHT_CORNER;
- }
- else if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) && (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left */
- ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) && (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
- {
- cursornr = GDK_BOTTOM_LEFT_CORNER;
- }
- else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) && (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
- ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) && (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
- {
- cursornr = GDK_BOTTOM_RIGHT_CORNER;
- }
-
- if (cursornr != p->cursornr)
- {
- cursor = gdk_cursor_new(cursornr); /* set curosr */
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = cursornr;
- }
- break;
-
- case 512: /* middle button */
- case 1024: /* right button */
- if (p->selection_drag)
- {
- int dx, dy;
-
- dx = p->selection_xpos - event->motion.x;
- dy = p->selection_ypos - event->motion.y;
-
- p->selection_xpos = event->motion.x;
- p->selection_ypos = event->motion.y;
-
- p->selection.active = TRUE;
- p->selection.coordinate[0] -= dx / xscale;
- p->selection.coordinate[1] -= dy / yscale;
- p->selection.coordinate[2] -= dx / xscale;
- p->selection.coordinate[3] -= dy / yscale;
-
- preview_bound_selection(p);
- preview_update_maximum_output_size(p);
- preview_draw_selection(p);
-
- if ((preferences.gtk_update_policy == GTK_UPDATE_CONTINUOUS) && (event_count == 1))
- {
- preview_establish_selection(p);
- }
- else if ((preferences.gtk_update_policy == GTK_UPDATE_DELAYED) && (event_count == 1))
- {
- preview_establish_selection(p);
- }
- }
- break;
-
- default:
- if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) && (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left */
- ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) && (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
- {
- cursornr = GDK_TOP_LEFT_CORNER;
- }
- else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) && (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
- ( (preview_selection[1] - SELECTION_RANGE_OUT < event->button.y) && (event->button.y < preview_selection[1] + SELECTION_RANGE_IN) ) ) /* top */
- {
- cursornr = GDK_TOP_RIGHT_CORNER;
- }
- else if ( ( (preview_selection[0] - SELECTION_RANGE_OUT < event->button.x) && (event->button.x < preview_selection[0] + SELECTION_RANGE_IN) ) && /* left */
- ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) && (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
- {
- cursornr = GDK_BOTTOM_LEFT_CORNER;
- }
- else if ( ( (preview_selection[2] - SELECTION_RANGE_IN < event->button.x) && (event->button.x < preview_selection[2] + SELECTION_RANGE_OUT) ) && /* right */
- ( (preview_selection[3] - SELECTION_RANGE_IN < event->button.y) && (event->button.y < preview_selection[3] + SELECTION_RANGE_OUT) ) ) /* bottom */
- {
- cursornr = GDK_BOTTOM_RIGHT_CORNER;
- }
- else
- {
- cursornr = XSANE_CURSOR_PREVIEW;
- }
-
- if ((cursornr != p->cursornr) && (p->cursornr != -1))
- {
- cursor = gdk_cursor_new(cursornr); /* set curosr */
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = cursornr;
- }
- break;
- }
- break;
-
- default:
-#if 0
- fprintf(stderr, "preview_event_handler: unhandled event type %d\n", event->type);
-#endif
- break;
- }
- }
-
- while (gtk_events_pending()) /* make sure all selection draw is done now */
- {
- gtk_main_iteration();
- }
-
- event_count--;
-
- return FALSE;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_start_button_clicked(GtkWidget *widget, gpointer data)
-{
- preview_scan(data);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_cancel_button_clicked(GtkWidget *widget, gpointer data)
-{
- preview_scan_done(data);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-Preview *preview_new(GSGDialog *dialog)
-{
- static int first_time = 1;
- GtkWidget *table, *frame;
- GtkSignalFunc signal_func;
- GtkWidgetClass *class;
- GtkBox *vbox, *hbox;
- GdkCursor *cursor;
- GtkWidget *preset_area_option_menu, *preset_area_menu, *preset_area_item;
- Preview *p;
- int i;
- char buf[256];
-
- p = malloc(sizeof(*p));
- if (!p)
- {
- return 0;
- }
- memset(p, 0, sizeof(*p));
-
- p->mode = MODE_NORMAL; /* no pipette functions etc */
- p->dialog = dialog;
- p->input_tag = -1;
-
- if (first_time)
- {
- first_time = 0;
- gtk_preview_set_gamma(1.0);
- gtk_preview_set_install_cmap(preferences.preview_own_cmap);
- }
-
- p->preset_width = INF; /* use full scanarea */
- p->preset_height = INF; /* use full scanarea */
-
- p->maximum_output_width = INF; /* full output with */
- p->maximum_output_height = INF; /* full output height */
-
-#ifndef XSERVER_WITH_BUGGY_VISUALS
- gtk_widget_push_visual(gtk_preview_get_visual());
-#endif
- gtk_widget_push_colormap(gtk_preview_get_cmap());
-
- snprintf(buf, sizeof(buf), "%s %s", WINDOW_PREVIEW, device_text);
- p->top = gtk_dialog_new();
- gtk_window_set_title(GTK_WINDOW(p->top), buf);
- vbox = GTK_BOX(GTK_DIALOG(p->top)->vbox);
- hbox = GTK_BOX(GTK_DIALOG(p->top)->action_area);
-
- xsane_set_window_icon(p->top, 0);
-
- /* top hbox for pipette buttons */
- p->button_box = gtk_hbox_new(FALSE, 5);
- gtk_container_set_border_width(GTK_CONTAINER(p->button_box), 4);
- gtk_box_pack_start(GTK_BOX(vbox), p->button_box, FALSE, FALSE, 0);
-
- /* White, gray and black pipette button */
- p->pipette_white = xsane_button_new_with_pixmap(p->button_box, pipette_white_xpm, DESC_PIPETTE_WHITE, (GtkSignalFunc) preview_pipette_white, p);
- p->pipette_gray = xsane_button_new_with_pixmap(p->button_box, pipette_gray_xpm, DESC_PIPETTE_GRAY, (GtkSignalFunc) preview_pipette_gray, p);
- p->pipette_black = xsane_button_new_with_pixmap(p->button_box, pipette_black_xpm, DESC_PIPETTE_BLACK, (GtkSignalFunc) preview_pipette_black, p);
-
- /* Zoom not, zoom out and zoom in button */
- p->zoom_not = xsane_button_new_with_pixmap(p->button_box, zoom_not_xpm, DESC_ZOOM_FULL, (GtkSignalFunc) preview_zoom_not, p);
- p->zoom_out = xsane_button_new_with_pixmap(p->button_box, zoom_out_xpm, DESC_ZOOM_OUT, (GtkSignalFunc) preview_zoom_out, p);
- p->zoom_in = xsane_button_new_with_pixmap(p->button_box, zoom_in_xpm, DESC_ZOOM_IN, (GtkSignalFunc) preview_zoom_in, p);
- p->zoom_undo = xsane_button_new_with_pixmap(p->button_box, zoom_undo_xpm, DESC_ZOOM_UNDO, (GtkSignalFunc) preview_zoom_undo, p);
-
- gtk_widget_set_sensitive(p->zoom_not, FALSE); /* no zoom at this point, so no zoom not */
- gtk_widget_set_sensitive(p->zoom_out, FALSE); /* no zoom at this point, so no zoom out */
- gtk_widget_set_sensitive(p->zoom_undo, FALSE); /* no zoom at this point, so no zoom undo */
-
-
-
- xsane_button_new_with_pixmap(p->button_box, full_preview_area_xpm, DESC_FULL_PREVIEW_AREA,
- (GtkSignalFunc) preview_full_preview_area, p);
-
- /* select maximum scanarea */
- preset_area_menu = gtk_menu_new();
-
- for (i = 0; i < PRESET_AREA_ITEMS; ++i)
- {
- preset_area_item = gtk_menu_item_new_with_label(preset_area[i].name);
- gtk_container_add(GTK_CONTAINER(preset_area_menu), preset_area_item);
- gtk_signal_connect(GTK_OBJECT(preset_area_item), "activate", (GtkSignalFunc) preview_preset_area_callback, p);
- gtk_object_set_data(GTK_OBJECT(preset_area_item), "Selection", (void *) i);
-
- gtk_widget_show(preset_area_item);
- }
-
- preset_area_option_menu = gtk_option_menu_new();
- gtk_box_pack_start(GTK_BOX(p->button_box), preset_area_option_menu, FALSE, FALSE, 2);
- gtk_option_menu_set_menu(GTK_OPTION_MENU(preset_area_option_menu), preset_area_menu);
- gtk_option_menu_set_history(GTK_OPTION_MENU(preset_area_option_menu), 0); /* full area */
-/* xsane_back_gtk_set_tooltip(tooltips, preset_area_option_menu, desc); */
-
- gtk_widget_show(preset_area_option_menu);
- p->preset_area_option_menu = preset_area_option_menu;
-
- gtk_widget_show(p->button_box);
-
-
-
- /* construct the preview area (table with sliders & preview window) */
- table = gtk_table_new(2, 2, /* homogeneous */ FALSE);
- gtk_table_set_col_spacing(GTK_TABLE(table), 0, 1);
- gtk_table_set_row_spacing(GTK_TABLE(table), 0, 1);
- gtk_container_set_border_width(GTK_CONTAINER(table), 2);
- gtk_box_pack_start(vbox, table, /* expand */ TRUE, /* fill */ TRUE, /* padding */ 0);
-
- /* the empty box in the top-left corner */
- frame = gtk_frame_new(/* label */ 0);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
- gtk_table_attach(GTK_TABLE(table), frame, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
-
- /* the horizontal ruler */
- p->hruler = gtk_hruler_new();
- gtk_table_attach(GTK_TABLE(table), p->hruler, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);
-
- /* the vertical ruler */
- p->vruler = gtk_vruler_new();
- gtk_table_attach(GTK_TABLE(table), p->vruler, 0, 1, 1, 2, 0, GTK_FILL, 0, 0);
-
- /* the preview area */
-
- p->window = gtk_preview_new(GTK_PREVIEW_COLOR);
- gtk_preview_set_expand(GTK_PREVIEW(p->window), TRUE);
- gtk_widget_set_events(p->window,
- GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- gtk_signal_connect(GTK_OBJECT(p->window), "event", (GtkSignalFunc) preview_event_handler, p);
- gtk_signal_connect_after(GTK_OBJECT(p->window), "expose_event", (GtkSignalFunc) preview_expose_handler, p);
- gtk_signal_connect_after(GTK_OBJECT(p->window), "size_allocate", (GtkSignalFunc) preview_area_resize, 0);
- gtk_object_set_data(GTK_OBJECT(p->window), "PreviewPointer", p);
-
- /* Connect the motion-notify events of the preview area with the rulers. Nifty stuff! */
-
- class = GTK_WIDGET_CLASS(GTK_OBJECT(p->hruler)->klass);
- signal_func = (GtkSignalFunc) class->motion_notify_event;
- gtk_signal_connect_object(GTK_OBJECT(p->window), "motion_notify_event", signal_func, GTK_OBJECT(p->hruler));
-
- class = GTK_WIDGET_CLASS(GTK_OBJECT(p->vruler)->klass);
- signal_func = (GtkSignalFunc) class->motion_notify_event;
- gtk_signal_connect_object(GTK_OBJECT(p->window), "motion_notify_event", signal_func, GTK_OBJECT(p->vruler));
-
- p->viewport = gtk_frame_new(/* label */ 0);
- gtk_frame_set_shadow_type(GTK_FRAME(p->viewport), GTK_SHADOW_IN);
- gtk_container_add(GTK_CONTAINER(p->viewport), p->window);
-
- gtk_table_attach(GTK_TABLE(table), p->viewport, 1, 2, 1, 2,
- GTK_FILL | GTK_EXPAND | GTK_SHRINK,
- GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
-
- preview_update_surface(p, 0);
-
- /* fill in action area: */
-
- /* Start button */
- p->start = gtk_button_new_with_label(BUTTON_PREVIEW_ACQUIRE);
- gtk_signal_connect(GTK_OBJECT(p->start), "clicked", (GtkSignalFunc) preview_start_button_clicked, p);
- gtk_box_pack_start(GTK_BOX(hbox), p->start, TRUE, TRUE, 0);
-
- /* Cancel button */
- p->cancel = gtk_button_new_with_label(BUTTON_PREVIEW_CANCEL);
- gtk_signal_connect(GTK_OBJECT(p->cancel), "clicked", (GtkSignalFunc) preview_cancel_button_clicked, p);
- gtk_box_pack_start(GTK_BOX(hbox), p->cancel, TRUE, TRUE, 0);
- gtk_widget_set_sensitive(p->cancel, FALSE);
-
- gtk_widget_show(p->cancel);
- gtk_widget_show(p->start);
- gtk_widget_show(p->viewport);
- gtk_widget_show(p->window);
- gtk_widget_show(p->hruler);
- gtk_widget_show(p->vruler);
- gtk_widget_show(frame);
- gtk_widget_show(table);
- gtk_widget_show(p->top);
-
- cursor = gdk_cursor_new(XSANE_CURSOR_PREVIEW); /* set default curosr */
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = XSANE_CURSOR_PREVIEW;
-
- gtk_widget_pop_colormap();
-#ifndef XSERVER_WITH_BUGGY_VISUALS
- gtk_widget_pop_visual();
-#endif
- return p;
-}
-
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_area_correct(Preview *p)
-{
- float width, height, max_width, max_height;
-
- width = p->preview_width;
- height = p->preview_height;
- max_width = p->preview_window_width;
- max_height = p->preview_window_height;
-
- width = max_width;
- height = width / p->aspect;
-
- if (height > max_height)
- {
- height = max_height;
- width = height * p->aspect;
- }
-
- p->preview_width = width + 0.5;
- p->preview_height = height + 0.5;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_update_surface(Preview *p, int surface_changed)
-{
- float val;
- float width, height;
- float max_width, max_height;
- float preset_width, preset_height;
- const SANE_Option_Descriptor *opt;
- int i;
- SANE_Value_Type type;
- SANE_Unit unit;
- double min, max;
-
- unit = SANE_UNIT_PIXEL;
- type = SANE_TYPE_INT;
-
- for (i = 0; i < 4; ++i) /* test if surface (max vals of scanarea) has changed */
- {
-/* val = (i & 2) ? INF : -INF; */
- val = (i & 2) ? INF : 0;
-
- if (p->dialog->well_known.coord[i] > 0)
- {
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.coord[i]);
- assert(opt->unit == SANE_UNIT_PIXEL || opt->unit == SANE_UNIT_MM);
- unit = opt->unit;
- type = opt->type;
-
- xsane_get_bounds(opt, &min, &max);
-
- if (i & 2)
- {
- val = max;
- }
- else
- {
- val = min;
- }
- }
-
- if (p->max_scanner_surface[i] != val)
- {
- surface_changed = 2;
- p->max_scanner_surface[i] = val;
- }
- }
-
- if (surface_changed == 2) /* redefine all surface subparts */
- {
- for (i = 0; i < 4; i++)
- {
- val = p->max_scanner_surface[i];
- p->scanner_surface[i] = val;
- p->surface[i] = val;
- p->image_surface[i] = val;
- }
- }
-
- max_width = p->max_scanner_surface[xsane_back_gtk_BR_X] - p->max_scanner_surface[xsane_back_gtk_TL_X];
- max_height = p->max_scanner_surface[xsane_back_gtk_BR_Y] - p->max_scanner_surface[xsane_back_gtk_TL_Y];
-
- width = p->scanner_surface[xsane_back_gtk_BR_X] - p->scanner_surface[xsane_back_gtk_TL_X];
- height = p->scanner_surface[xsane_back_gtk_BR_Y] - p->scanner_surface[xsane_back_gtk_TL_Y];
-
- preset_width = p->preset_width;
- preset_height = p->preset_height;
-
- if (preset_width > max_width)
- {
- preset_width = max_width;
- }
-
- if (preset_height > max_height)
- {
- preset_height = max_height;
- }
-
- if ( (width != preset_width) || (height != preset_height) )
- {
- p->scanner_surface[xsane_back_gtk_TL_X] = p->scanner_surface[xsane_back_gtk_TL_X];
- p->surface[xsane_back_gtk_TL_X] = p->scanner_surface[xsane_back_gtk_TL_X];
- p->image_surface[xsane_back_gtk_TL_X] = p->scanner_surface[xsane_back_gtk_TL_X];
-
- p->scanner_surface[xsane_back_gtk_BR_X] = p->scanner_surface[xsane_back_gtk_TL_X] + preset_width;
- p->surface[xsane_back_gtk_BR_X] = p->scanner_surface[xsane_back_gtk_TL_X] + preset_width;
- p->image_surface[xsane_back_gtk_BR_X] = p->scanner_surface[xsane_back_gtk_TL_X] + preset_width;
-
- p->scanner_surface[xsane_back_gtk_TL_Y] = p->scanner_surface[xsane_back_gtk_TL_Y];
- p->surface[xsane_back_gtk_TL_Y] = p->scanner_surface[xsane_back_gtk_TL_Y];
- p->image_surface[xsane_back_gtk_TL_Y] = p->scanner_surface[xsane_back_gtk_TL_Y];
-
- p->scanner_surface[xsane_back_gtk_BR_Y] = p->scanner_surface[xsane_back_gtk_TL_Y] + preset_height;
- p->surface[xsane_back_gtk_BR_Y] = p->scanner_surface[xsane_back_gtk_TL_Y] + preset_height;
- p->image_surface[xsane_back_gtk_BR_Y] = p->scanner_surface[xsane_back_gtk_TL_Y] + preset_height;
-
- surface_changed = 1;
- }
-
- if (p->surface_unit != unit)
- {
- surface_changed = 1;
- p->surface_unit = unit;
- }
-
- if (p->surface_unit == SANE_UNIT_MM)
- {
- gtk_widget_set_sensitive(p->preset_area_option_menu, TRUE); /* enable preset area */
- }
- else
- {
- gtk_widget_set_sensitive(p->preset_area_option_menu, FALSE); /* disable preset area */
- }
-
- if (p->surface_type != type)
- {
- surface_changed = 1;
- p->surface_type = type;
- }
-
- if (surface_changed)
- {
- /* guess the initial preview window size: */
-
- width = p->surface[xsane_back_gtk_BR_X] - p->surface[xsane_back_gtk_TL_X];
- height = p->surface[xsane_back_gtk_BR_Y] - p->surface[xsane_back_gtk_TL_Y];
-
- if (p->surface_type == SANE_TYPE_INT)
- {
- width += 1.0;
- height += 1.0;
- }
- else
- {
- width += SANE_UNFIX(1.0);
- height += SANE_UNFIX(1.0);
- }
-
- assert(width > 0.0 && height > 0.0);
-
- if (width >= INF || height >= INF)
- {
- p->aspect = 1.0;
- }
- else
- {
- p->aspect = width/height;
- }
- }
- else if ( (p->image_height) && (p->image_width) )
- {
- p->aspect = p->image_width/(float) p->image_height;
- }
-
- if ( (surface_changed) && (p->preview_window_width == 0) )
- {
- p->preview_window_width = 0.5 * gdk_screen_width();
- p->preview_window_height = 0.5 * gdk_screen_height();
- }
-
- preview_area_correct(p);
-
- if (surface_changed)
- {
- gtk_widget_set_usize(GTK_WIDGET(p->window), p->preview_width, p->preview_height);
- /* preview_area_resize is automatically called by signal handler */
-
- preview_bound_selection(p); /* make sure selection is not larger than surface */
- preview_restore_image(p); /* draw selected surface of the image */
- }
- else
- {
- preview_update_selection(p);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_scan(Preview *p)
-{
- double min, max, swidth, sheight, width, height, dpi = 0;
- const SANE_Option_Descriptor *opt;
- gint gwidth, gheight;
- int i;
-
- xsane.block_update_param = TRUE; /* do not change parameters each time */
-
- preview_save_option(p, p->dialog->well_known.dpi, &p->saved_dpi, &p->saved_dpi_valid);
- preview_save_option(p, p->dialog->well_known.dpi_x, &p->saved_dpi_x, &p->saved_dpi_x_valid);
- preview_save_option(p, p->dialog->well_known.dpi_y, &p->saved_dpi_y, &p->saved_dpi_y_valid);
-
- for (i = 0; i < 4; ++i)
- {
- preview_save_option(p, p->dialog->well_known.coord[i], &p->saved_coord[i], p->saved_coord_valid + i);
- }
- preview_save_option(p, p->dialog->well_known.bit_depth, &p->saved_bit_depth, &p->saved_bit_depth_valid);
-
- /* determine dpi, if necessary: */
-
- if (p->dialog->well_known.dpi > 0)
- {
- opt = sane_get_option_descriptor(p->dialog->dev, p->dialog->well_known.dpi);
-
- gwidth = p->preview_width;
- gheight = p->preview_height;
-
- height = gheight;
- width = height * p->aspect;
-
- if (width > gwidth)
- {
- width = gwidth;
- height = width / p->aspect;
- }
-
- swidth = (p->surface[xsane_back_gtk_BR_X] - p->surface[xsane_back_gtk_TL_X]);
-
- if (swidth < INF)
- {
- dpi = MM_PER_INCH * width/swidth;
- }
- else
- {
- sheight = (p->surface[xsane_back_gtk_BR_Y] - p->surface[xsane_back_gtk_TL_Y]);
- if (sheight < INF)
- {
- dpi = MM_PER_INCH * height/sheight;
- }
- else
- {
- dpi = 18.0;
- }
- }
-
- xsane_get_bounds(opt, &min, &max);
-
- if (dpi < min)
- {
- dpi = min;
- }
-
- if (dpi > max)
- {
- dpi = max;
- }
-
- xsane_set_resolution(p->dialog->well_known.dpi, dpi); /* set resolution to dpi or next higher value that is available */
- xsane_set_resolution(p->dialog->well_known.dpi_x, dpi); /* set resolution to dpi or next higher value that is available */
- xsane_set_resolution(p->dialog->well_known.dpi_y, dpi); /* set resolution to dpi or next higher value that is available */
- }
-
- /* set the scan window (necessary since backends may default to non-maximum size): */
-
- for (i = 0; i < 4; ++i)
- {
- preview_set_option_float(p, p->dialog->well_known.coord[i], p->surface[i]);
- }
-
- preview_set_option_bool(p, p->dialog->well_known.preview, SANE_TRUE);
-
- if ( (p->saved_bit_depth > 8) && (p->saved_bit_depth_valid) ) /* don't scan with more than 8bpp */
- {
- preview_set_option_int(p, p->dialog->well_known.bit_depth, 8);
- }
-
- xsane.block_update_param = FALSE;
-
- /* OK, all set to go */
- preview_scan_start(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_save_image_file(Preview *p, FILE *out)
-{
- if (out)
- {
- /* always save it as a PPM image: */
- fprintf(out, "P6\n# surface: %g %g %g %g %u %u\n%d %d\n255\n",
- p->surface[0], p->surface[1], p->surface[2], p->surface[3],
- p->surface_type, p->surface_unit, p->image_width, p->image_height);
-
- fwrite(p->image_data_raw, 3, p->image_width*p->image_height, out);
- fclose(out);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_save_image(Preview *p)
-{
- char filename[PATH_MAX];
- FILE *out;
- int status;
-
- if (!p->image_data_enh)
- {
- return;
- }
-
- if ( GROSSLY_EQUAL(p->max_scanner_surface[0], p->surface[0]) && /* full device surface */
- GROSSLY_EQUAL(p->max_scanner_surface[1], p->surface[1]) &&
- GROSSLY_EQUAL(p->max_scanner_surface[2], p->surface[2]) &&
- GROSSLY_EQUAL(p->max_scanner_surface[3], p->surface[3]) )
- {
- status = preview_make_image_path(p, sizeof(filename), filename, 0);
- }
- else if ( GROSSLY_EQUAL(p->scanner_surface[0], p->surface[0]) && /* user defined surface */
- GROSSLY_EQUAL(p->scanner_surface[1], p->surface[1]) &&
- GROSSLY_EQUAL(p->scanner_surface[2], p->surface[2]) &&
- GROSSLY_EQUAL(p->scanner_surface[3], p->surface[3]) )
- {
- status = preview_make_image_path(p, sizeof(filename), filename, 1);
- }
- else /* zoom area */
- {
- status = preview_make_image_path(p, sizeof(filename), filename, 2);
- }
-
- if (status >= 0)
- {
- /* save preview image */
- remove(filename); /* remove existing preview */
- umask(0177); /* creare temporary file with "-rw-------" permissions */
- out = fopen(filename, "w");
- umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
-
- preview_save_image_file(p, out);
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_destroy(Preview *p)
-{
- int level;
- int status;
- char filename[PATH_MAX];
-
- if (p->scanning)
- {
- preview_scan_done(p); /* don't save partial window */
- }
- else
- {
- preview_save_image(p);
- }
-
- if (!preferences.preserve_preview)
- {
- for(level = 0; level <= 2; level++)
- {
- status = preview_make_image_path(p, sizeof(filename), filename, level);
- if (status >= 0)
- {
- remove(filename); /* remove existing preview */
- }
- }
- }
-
- if (p->image_data_enh)
- {
- free(p->image_data_enh);
- p->image_data_enh = 0;
- }
-
- if (p->image_data_raw)
- {
- free(p->image_data_raw);
- p->image_data_raw = 0;
- }
-
- if (p->preview_row)
- {
- free(p->preview_row);
- p->preview_row = 0;
- }
-
- if (p->gc_selection)
- {
- gdk_gc_destroy(p->gc_selection);
- }
-
- if (p->gc_selection_maximum)
- {
- gdk_gc_destroy(p->gc_selection_maximum);
- }
-
- if (p->top)
- {
- gtk_widget_destroy(p->top);
- }
- free(p);
-
- p = 0;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_zoom_not(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- int i;
-
- for (i=0; i<4; i++)
- {
- p->surface[i] = p->scanner_surface[i];
- }
-
- preview_update_surface(p, 1);
- gtk_widget_set_sensitive(p->zoom_not, FALSE); /* forbid unzoom */
- gtk_widget_set_sensitive(p->zoom_out, FALSE); /* forbid zoom out */
- gtk_widget_set_sensitive(p->zoom_undo,TRUE); /* allow zoom undo */
-
- while (gtk_events_pending()) /* make sure all selection draw is done now */
- {
- gtk_main_iteration();
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_zoom_out(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- int i;
- float delta_width = (p->surface[2] - p->surface[0]) * 0.2;
- float delta_height = (p->surface[3] - p->surface[1]) * 0.2;
-
- for (i=0; i<4; i++)
- {
- p->old_surface[i] = p->surface[i];
- }
-
- p->surface[0] -= delta_width;
- p->surface[1] -= delta_height;
- p->surface[2] += delta_width;
- p->surface[3] += delta_height;
-
- if (p->surface[0] < p->scanner_surface[0])
- {
- p->surface[0] = p->scanner_surface[0];
- }
-
- if (p->surface[1] < p->scanner_surface[1])
- {
- p->surface[1] = p->scanner_surface[1];
- }
-
- if (p->surface[2] > p->scanner_surface[2])
- {
- p->surface[2] = p->scanner_surface[2];
- }
-
- if (p->surface[3] > p->scanner_surface[3])
- {
- p->surface[3] = p->scanner_surface[3];
- }
-
- preview_update_surface(p, 1);
- gtk_widget_set_sensitive(p->zoom_not, TRUE); /* allow unzoom */
- gtk_widget_set_sensitive(p->zoom_undo,TRUE); /* allow zoom undo */
-
- while (gtk_events_pending()) /* make sure all selection draw is done now */
- {
- gtk_main_iteration();
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_zoom_in(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- const SANE_Option_Descriptor *opt;
- SANE_Status status;
- SANE_Word val;
- int i, optnum;
-
- for (i=0; i<4; i++)
- {
- p->old_surface[i] = p->surface[i];
-
- optnum = p->dialog->well_known.coord[i];
- if (optnum > 0)
- {
- opt = sane_get_option_descriptor(p->dialog->dev, optnum);
- status = sane_control_option(p->dialog->dev, optnum, SANE_ACTION_GET_VALUE, &val, 0);
- if (status != SANE_STATUS_GOOD)
- {
- continue;
- }
-
- if (opt->type == SANE_TYPE_FIXED)
- {
- p->surface[i] = SANE_UNFIX(val);
- }
- else
- {
- p->surface[i] = val;
- }
- }
- }
-
- preview_update_surface(p, 1);
- gtk_widget_set_sensitive(p->zoom_not, TRUE); /* allow unzoom */
- gtk_widget_set_sensitive(p->zoom_out, TRUE); /* allow zoom out */
- gtk_widget_set_sensitive(p->zoom_undo,TRUE); /* allow zoom undo */
-
- while (gtk_events_pending()) /* make sure all selection draw is done now */
- {
- gtk_main_iteration();
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_zoom_undo(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- int i;
-
- for (i=0; i<4; i++)
- {
- p->surface[i] = p->old_surface[i];
- }
-
- preview_update_surface(p, 1);
- gtk_widget_set_sensitive(p->zoom_not, TRUE); /* allow unzoom */
- gtk_widget_set_sensitive(p->zoom_out, TRUE); /* allow zoom out */
- gtk_widget_set_sensitive(p->zoom_undo, FALSE); /* forbid zoom undo */
-
- while (gtk_events_pending()) /* make sure all selection draw is done now */
- {
- gtk_main_iteration();
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_get_color(Preview *p, int x, int y, int *red, int *green, int *blue)
-{
- int image_x, image_y;
- float xscale_p2i, yscale_p2i;
- int offset;
-
- if (p->image_data_raw)
- {
- preview_get_scale_preview_to_image(p, &xscale_p2i, &yscale_p2i);
-
- image_x = x * xscale_p2i;
- image_y = y * yscale_p2i;
-
- offset = 3 * (image_y * p->image_width + image_x);
-
- if (!xsane.negative) /* positive */
- {
- *red = p->image_data_raw[offset ];
- *green = p->image_data_raw[offset + 1];
- *blue = p->image_data_raw[offset + 2];
- }
- else /* negative */
- {
- *red = 255 - p->image_data_raw[offset ];
- *green = 255 - p->image_data_raw[offset + 1];
- *blue = 255 - p->image_data_raw[offset + 2];
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_pipette_white(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- GdkCursor *cursor;
- GdkColor fg;
- GdkColor bg;
- GdkPixmap *pixmap;
- GdkPixmap *mask;
-
- p->mode = MODE_PIPETTE_WHITE;
-
- pixmap = gdk_bitmap_create_from_data(p->top->window, cursor_pipette_white, CURSOR_PIPETTE_WIDTH, CURSOR_PIPETTE_HEIGHT);
- mask = gdk_bitmap_create_from_data(p->top->window, cursor_pipette_mask, CURSOR_PIPETTE_WIDTH, CURSOR_PIPETTE_HEIGHT);
-
- fg.red = 0;
- fg.green = 0;
- fg.blue = 0;
-
- bg.red = 65535;
- bg.green = 65535;
- bg.blue = 65535;
-
- cursor = gdk_cursor_new_from_pixmap(pixmap, mask, &fg, &bg, CURSOR_PIPETTE_HOT_X, CURSOR_PIPETTE_HOT_Y);
-
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = -1;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_pipette_gray(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- GdkCursor *cursor;
- GdkColor fg;
- GdkColor bg;
- GdkPixmap *pixmap;
- GdkPixmap *mask;
-
- p->mode = MODE_PIPETTE_GRAY;
-
- pixmap = gdk_bitmap_create_from_data(p->top->window, cursor_pipette_gray, CURSOR_PIPETTE_WIDTH, CURSOR_PIPETTE_HEIGHT);
- mask = gdk_bitmap_create_from_data(p->top->window, cursor_pipette_mask, CURSOR_PIPETTE_WIDTH, CURSOR_PIPETTE_HEIGHT);
-
- fg.red = 0;
- fg.green = 0;
- fg.blue = 0;
-
- bg.red = 65535;
- bg.green = 65535;
- bg.blue = 65535;
-
- cursor = gdk_cursor_new_from_pixmap(pixmap, mask, &fg, &bg, CURSOR_PIPETTE_HOT_X, CURSOR_PIPETTE_HOT_Y);
-
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = -1;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_pipette_black(GtkWidget *window, gpointer data)
-{
- Preview *p=data;
- GdkCursor *cursor;
- GdkColor fg;
- GdkColor bg;
- GdkPixmap *pixmap;
- GdkPixmap *mask;
-
- p->mode = MODE_PIPETTE_BLACK;
-
- pixmap = gdk_bitmap_create_from_data(p->top->window, cursor_pipette_black, CURSOR_PIPETTE_WIDTH, CURSOR_PIPETTE_HEIGHT);
- mask = gdk_bitmap_create_from_data(p->top->window, cursor_pipette_mask , CURSOR_PIPETTE_WIDTH, CURSOR_PIPETTE_HEIGHT);
-
- fg.red = 0;
- fg.green = 0;
- fg.blue = 0;
-
- bg.red = 65535;
- bg.green = 65535;
- bg.blue = 65535;
-
- cursor = gdk_cursor_new_from_pixmap(pixmap, mask, &fg, &bg, CURSOR_PIPETTE_HOT_X, CURSOR_PIPETTE_HOT_Y);
-
- gdk_window_set_cursor(p->window->window, cursor);
- gdk_cursor_destroy(cursor);
- p->cursornr = -1;
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_full_preview_area(GtkWidget *widget, gpointer call_data)
-{
- Preview *p = call_data;
- int i;
-
- p->selection.active = TRUE;
-
- for (i=0; i<4; i++)
- {
- p->selection.coordinate[i] = p->surface[i];
- }
-
- preview_update_maximum_output_size(p);
- preview_draw_selection(p);
- preview_establish_selection(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-static void preview_preset_area_callback(GtkWidget *widget, gpointer call_data)
-{
- Preview *p = call_data;
- int selection;
-
- selection = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
-
- p->preset_width = preset_area[selection].width;
- p->preset_height = preset_area[selection].height;
-
- preview_update_surface(p, 0);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_do_gamma_correction(Preview *p)
-{
- int x,y;
- int offset;
-
- if (p->image_data_raw)
- {
- if ((p->image_data_raw) && (p->params.depth > 1) && (preview_gamma_data_red))
- {
- for (y=0; y < p->image_height; y++)
- {
- for (x=0; x < p->image_width; x++)
- {
- offset = 3 * (y * p->image_width + x);
- p->image_data_enh[offset ] = preview_gamma_data_red [p->image_data_raw[offset ]];
- p->image_data_enh[offset + 1] = preview_gamma_data_green[p->image_data_raw[offset + 1]];
- p->image_data_enh[offset + 2] = preview_gamma_data_blue [p->image_data_raw[offset + 2]];
- }
- }
- }
-
- preview_display_partial_image(p);
-
- p->previous_selection.active = FALSE; /* previous selection is not drawn */
- p->previous_selection_maximum.active = FALSE;
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_calculate_histogram(Preview *p,
- SANE_Int *count_raw, SANE_Int *count_raw_red, SANE_Int *count_raw_green, SANE_Int *count_raw_blue,
- SANE_Int *count, SANE_Int *count_red, SANE_Int *count_green, SANE_Int *count_blue)
-{
- int x, y;
- int offset;
- SANE_Int red_raw, green_raw, blue_raw;
- SANE_Int red, green, blue;
- SANE_Int min_x, max_x, min_y, max_y;
- float xscale, yscale;
-
- preview_get_scale_device_to_image(p, &xscale, &yscale);
-
- min_x = (p->selection.coordinate[0] - p->surface[0]) * xscale;
- min_y = (p->selection.coordinate[1] - p->surface[1]) * yscale;
- max_x = (p->selection.coordinate[2] - p->surface[0]) * xscale;
- max_y = (p->selection.coordinate[3] - p->surface[1]) * yscale;
-
- if (min_x < 0)
- {
- min_x = 0;
- }
-
- if (max_x >= p->image_width)
- {
- max_x = p->image_width-1;
- }
-
- if (min_y < 0)
- {
- min_y = 0;
- }
-
- if (max_y >= p->image_height)
- {
- max_y = p->image_height-1;
- }
-
- if ((p->image_data_raw) && (p->params.depth > 1) && (preview_gamma_data_red))
- {
- for (y = min_y; y <= max_y; y++)
- {
- for (x = min_x; x <= max_x; x++)
- {
- offset = 3 * (y * p->image_width + x);
- red_raw = p->image_data_raw[offset ];
- green_raw = p->image_data_raw[offset + 1];
- blue_raw = p->image_data_raw[offset + 2];
-
- red = histogram_gamma_data_red [red_raw];
- green = histogram_gamma_data_green[green_raw];
- blue = histogram_gamma_data_blue [blue_raw];
-
-/* count_raw [(int) sqrt((red_raw*red_raw + green_raw*green_raw + blue_raw*blue_raw)/3.0)]++; */
- count_raw [(int) ((red_raw + green_raw + blue_raw)/3)]++;
- count_raw_red [red_raw]++;
- count_raw_green[green_raw]++;
- count_raw_blue [blue_raw]++;
-
-/* count [(int) sqrt((red*red + green*green + blue*blue)/3.0)]++; */
- count [(int) ((red + green + blue)/3)]++;
- count_red [red]++;
- count_green[green]++;
- count_blue [blue]++;
- }
- }
- }
- else /* no preview image => all colors = 1 */
- {
- int i;
-
- for (i = 1; i <= 254; i++)
- {
- count_raw [i] = 0;
- count_raw_red [i] = 0;
- count_raw_green[i] = 0;
- count_raw_blue [i] = 0;
-
- count [i] = 0;
- count_red [i] = 0;
- count_green[i] = 0;
- count_blue [i] = 0;
- }
-
- count_raw [0] = 10;
- count_raw_red [0] = 10;
- count_raw_green[0] = 10;
- count_raw_blue [0] = 10;
-
- count [0] = 10;
- count_red [0] = 10;
- count_green[0] = 10;
- count_blue [0] = 10;
-
- count_raw [255] = 10;
- count_raw_red [255] = 10;
- count_raw_green[255] = 10;
- count_raw_blue [255] = 10;
-
- count [255] = 10;
- count_red [255] = 10;
- count_green[255] = 10;
- count_blue [255] = 10;
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_gamma_correction(Preview *p,
- SANE_Int *gamma_red, SANE_Int *gamma_green, SANE_Int *gamma_blue,
- SANE_Int *gamma_red_hist, SANE_Int *gamma_green_hist, SANE_Int *gamma_blue_hist)
-{
- preview_gamma_data_red = gamma_red;
- preview_gamma_data_green = gamma_green;
- preview_gamma_data_blue = gamma_blue;
-
- histogram_gamma_data_red = gamma_red_hist;
- histogram_gamma_data_green = gamma_green_hist;
- histogram_gamma_data_blue = gamma_blue_hist;
-
- preview_do_gamma_correction(p);
- preview_draw_selection(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_area_resize(GtkWidget *widget)
-{
- float min_x, max_x, delta_x;
- float min_y, max_y, delta_y;
- float xscale, yscale, f;
- Preview *p;
-
- p = gtk_object_get_data(GTK_OBJECT(widget), "PreviewPointer");
-
- p->preview_window_width = widget->allocation.width;
- p->preview_window_height = widget->allocation.height;
-
- p->preview_width = widget->allocation.width;
- p->preview_height = widget->allocation.height;
-
- preview_area_correct(p); /* set preview dimensions (with right aspect) that they fit into the window */
-
- if (p->preview_row) /* make sure preview_row is large enough for one line of the new size */
- {
- p->preview_row = realloc(p->preview_row, 3 * p->preview_window_width);
- }
- else
- {
- p->preview_row = malloc(3 * p->preview_window_width);
- }
-
- /* set the ruler ranges: */
-
- min_x = p->surface[xsane_back_gtk_TL_X];
- if (min_x <= -INF)
- {
- min_x = 0.0;
- }
-
- max_x = p->surface[xsane_back_gtk_BR_X];
- if (max_x >= INF)
- {
- max_x = p->image_width - 1;
- }
-
- min_y = p->surface[xsane_back_gtk_TL_Y];
- if (min_y <= -INF)
- {
- min_y = 0.0;
- }
-
- max_y = p->surface[xsane_back_gtk_BR_Y];
- if (max_y >= INF)
- {
- max_y = p->image_height - 1;
- }
-
- /* convert mm to inches if that's what the user wants: */
-
- if (p->surface_unit == SANE_UNIT_MM)
- {
- double factor = 1.0/preferences.length_unit;
-
- min_x *= factor;
- max_x *= factor;
- min_y *= factor;
- max_y *= factor;
- }
-
- preview_get_scale_preview_to_image(p, &xscale, &yscale);
-
- if (p->image_width > 0)
- {
- f = xscale * p->preview_width / p->image_width;
- }
- else
- {
- f = 1.0;
- }
-
- min_x *= f;
- max_x *= f;
- delta_x = max_x - min_x;
-
- gtk_ruler_set_range(GTK_RULER(p->hruler), min_x, min_x + delta_x*p->preview_window_width/p->preview_width,
- min_x, /* max_size */ 20);
-
- if (p->image_height > 0)
- {
- f = yscale * p->preview_height / p->image_height;
- }
- else
- {
- f = 1.0;
- }
-
- min_y *= f;
- max_y *= f;
- delta_y = max_y - min_y;
-
- gtk_ruler_set_range(GTK_RULER(p->vruler), min_y, min_y + delta_y*p->preview_window_height/p->preview_height,
- min_y, /* max_size */ 20);
-
- preview_paint_image(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_update_maximum_output_size(Preview *p)
-{
- if ( (p->maximum_output_width >= INF) || (p->maximum_output_height >= INF) )
- {
- if (p->selection_maximum.active)
- {
- p->selection_maximum.active = FALSE;
- }
- }
- else
- {
- p->previous_selection_maximum = p->selection_maximum;
-
- p->selection_maximum.active = TRUE;
- p->selection_maximum.coordinate[0] = p->selection.coordinate[0];
- p->selection_maximum.coordinate[1] = p->selection.coordinate[1];
- p->selection_maximum.coordinate[2] = p->selection.coordinate[0] + p->maximum_output_width;
- p->selection_maximum.coordinate[3] = p->selection.coordinate[1] + p->maximum_output_height;
-
- if (p->selection_maximum.coordinate[2] > p->max_scanner_surface[2])
- {
- p->selection_maximum.coordinate[2] = p->max_scanner_surface[2];
- }
-
- if (p->selection_maximum.coordinate[3] > p->max_scanner_surface[3])
- {
- p->selection_maximum.coordinate[3] = p->max_scanner_surface[3];
- }
-
- if ( (p->selection.coordinate[0] < p->selection_maximum.coordinate[0]) ||
- (p->selection.coordinate[1] < p->selection_maximum.coordinate[1]) ||
- (p->selection.coordinate[2] > p->selection_maximum.coordinate[2]) ||
- (p->selection.coordinate[3] > p->selection_maximum.coordinate[3]) )
- {
- if (p->selection.coordinate[2] > p->selection_maximum.coordinate[2])
- {
- p->selection.coordinate[2] = p->selection_maximum.coordinate[2];
- }
-
- if (p->selection.coordinate[3] > p->selection_maximum.coordinate[3])
- {
- p->selection.coordinate[3] = p->selection_maximum.coordinate[3];
- }
- preview_draw_selection(p);
- preview_establish_selection(p);
- }
- }
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */
-
-void preview_set_maximum_output_size(Preview *p, float width, float height)
-{
- /* witdh and height in device units */
-
- p->maximum_output_width = width;
- p->maximum_output_height = height;
-
- preview_update_maximum_output_size(p);
- preview_draw_selection(p);
-}
-
-/* ---------------------------------------------------------------------------------------------------------------------- */