diff options
author | Mattia Rizzolo <mattia@mapreri.org> | 2014-10-03 14:05:01 +0000 |
---|---|---|
committer | Mattia Rizzolo <mattia@mapreri.org> | 2014-10-03 14:05:01 +0000 |
commit | e7e90b72fd3161c5d55fed49e100781dfa3e9408 (patch) | |
tree | 67cfcfae6b9a9e15701a332dfacbe0ca6440f16c /frontend/xsane-preview.c | |
parent | 2d113e8792747151bf5d830f1a1485f2f951f940 (diff) |
Imported Upstream version 0.84upstream/0.84
Diffstat (limited to 'frontend/xsane-preview.c')
-rw-r--r-- | frontend/xsane-preview.c | 3257 |
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); -} - -/* ---------------------------------------------------------------------------------------------------------------------- */ |