kopia lustrzana https://gitlab.com/sane-project/frontends
Merge branch 'preview_fixes' into 'master'
Draft: preview: use GPixBuf and and lib function to do resize See merge request sane-project/frontends!31merge-requests/31/merge
commit
1c164ad2f4
|
@ -42,7 +42,9 @@ Preferences preferences =
|
|||
10.0, /* length unit */
|
||||
1, /* preserve_preview */
|
||||
0, /* preview_own_cmap */
|
||||
1.0 /* preview_gamma */
|
||||
1.0, /* preview_gamma */
|
||||
0, /* preview width, will be set by software */
|
||||
0 /* preview height, will be set by software. */
|
||||
};
|
||||
|
||||
static void w_string (Wire *w, Preferences *p, long offset);
|
||||
|
@ -66,6 +68,8 @@ desc[] =
|
|||
{"preserve-preview", w_int, POFFSET(preserve_preview)},
|
||||
{"preview-own-cmap", w_int, POFFSET(preview_own_cmap)},
|
||||
{"preview-gamma", w_double, POFFSET(preview_gamma)},
|
||||
{"preview-width", w_int, POFFSET(preview_width)},
|
||||
{"preview-height", w_int, POFFSET(preview_height)},
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -16,6 +16,8 @@ typedef struct
|
|||
int preserve_preview; /* save/restore preview image(s)? */
|
||||
int preview_own_cmap; /* install colormap for preview */
|
||||
double preview_gamma; /* gamma value for previews */
|
||||
int preview_width; /* width of the preview window. */
|
||||
int preview_height; /* height of the preview window. */
|
||||
}
|
||||
Preferences;
|
||||
|
||||
|
|
442
src/preview.c
442
src/preview.c
|
@ -156,14 +156,24 @@ screen_size_get_dimensions (gint *width, gint *height)
|
|||
}
|
||||
|
||||
static void
|
||||
draw_rect(cairo_t *cr, double coord[4])
|
||||
draw_selection (Preview *p, cairo_t *cr)
|
||||
{
|
||||
if (!p->selection.active)
|
||||
return;
|
||||
|
||||
double *coord = p->selection.coord;
|
||||
double x, y, w, h;
|
||||
|
||||
/*
|
||||
* Make sure that we account for a selection dragged in reverse
|
||||
* from what we expect, e.g leftwards or upwards or both.
|
||||
*
|
||||
*/
|
||||
x = coord[0];
|
||||
y = coord[1];
|
||||
w = coord[2] - x;
|
||||
h = coord[3] - y;
|
||||
|
||||
if (w < 0)
|
||||
{
|
||||
x = coord[2];
|
||||
|
@ -174,32 +184,30 @@ draw_rect(cairo_t *cr, double coord[4])
|
|||
y = coord[3];
|
||||
h = -h;
|
||||
}
|
||||
cairo_set_line_width(cr, 1.5);
|
||||
const double dashes1[2] = {4.0, 4.0};
|
||||
|
||||
/*
|
||||
* Draw selection rectangle. One black dash, then another, filling in the
|
||||
* black dash gaps with white. This means that regardless of the picture, the
|
||||
* dash pattern is visible.
|
||||
*
|
||||
*/
|
||||
const double dashes1[2] = { 4.0, 4.0 };
|
||||
const double dashes2[4] = { 0.0, 4.0, 4.0, 0.0 };
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_line_width (cr, 1.5);
|
||||
|
||||
// Black dashes.
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_set_dash(cr, dashes1, sizeof(dashes1)/sizeof(dashes1[0]), 0);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
|
||||
cairo_rectangle(cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke(cr);
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
const double dashes2[4] = {0.0, 4.0, 4.0, 0.0};
|
||||
cairo_set_dash(cr, dashes2, sizeof(dashes2)/sizeof(dashes2[0]), 0);
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
cairo_rectangle(cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
cairo_set_dash (cr, dashes1, sizeof(dashes1) / sizeof(dashes1[0]), 0);
|
||||
cairo_rectangle (cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
static void
|
||||
draw_selection (Preview * p, cairo_t *cr)
|
||||
{
|
||||
if (p->previous_selection.active)
|
||||
draw_rect (cr, p->previous_selection.coord);
|
||||
|
||||
if (p->selection.active)
|
||||
draw_rect (cr, p->selection.coord);
|
||||
|
||||
p->previous_selection = p->selection;
|
||||
// White dashes.
|
||||
cairo_set_dash (cr, dashes2, sizeof(dashes2) / sizeof(dashes2[0]), 0);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
||||
cairo_rectangle (cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -211,8 +219,6 @@ update_selection (Preview * p)
|
|||
SANE_Word val;
|
||||
int i, optnum;
|
||||
|
||||
p->previous_selection = p->selection;
|
||||
|
||||
memcpy (dev_selection, p->surface, sizeof (dev_selection));
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
|
@ -237,7 +243,7 @@ update_selection (Preview * p)
|
|||
min = 0.0;
|
||||
max = p->surface[i + 2];
|
||||
if (max >= INF)
|
||||
max = p->preview_width;
|
||||
max = (i == 0) ? p->preview_width : p->preview_height;
|
||||
|
||||
normal = ((i == 0) ? p->preview_width : p->preview_height) - 1;
|
||||
normal /= (max - min);
|
||||
|
@ -288,62 +294,62 @@ get_image_scale (Preview * p, float *xscalep, float *yscalep)
|
|||
static void
|
||||
paint_image (Preview * p)
|
||||
{
|
||||
float xscale, yscale, src_x, src_y;
|
||||
int dst_x, dst_y, height, x, y, src_offset;
|
||||
gint gwidth, gheight;
|
||||
|
||||
gwidth = p->preview_width;
|
||||
gheight = p->preview_height;
|
||||
|
||||
get_image_scale (p, &xscale, &yscale);
|
||||
|
||||
if (p->preview_row == NULL)
|
||||
p->preview_row = malloc (3 * gwidth);
|
||||
else
|
||||
p->preview_row = realloc (p->preview_row, 3 * gwidth);
|
||||
memset (p->preview_row, 0xff, 3 * gwidth);
|
||||
if (p->preview_data == NULL)
|
||||
p->preview_data = malloc (3 * gwidth * gheight);
|
||||
else
|
||||
p->preview_data = realloc (p->preview_data, 3 * gwidth * gheight);
|
||||
memset (p->preview_data, 0xff, 3 * gwidth * gheight);
|
||||
gtk_widget_queue_draw (p->window);
|
||||
|
||||
/* 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;
|
||||
for (dst_y = 0; dst_y < gheight; ++dst_y)
|
||||
{
|
||||
y = (int) (src_y + 0.5);
|
||||
if (y >= height)
|
||||
break;
|
||||
src_offset = y * 3 * p->image_width;
|
||||
|
||||
if (p->image_data)
|
||||
for (dst_x = 0; dst_x < gwidth; ++dst_x)
|
||||
{
|
||||
x = (int) (src_x + 0.5);
|
||||
if (x >= p->image_width)
|
||||
break;
|
||||
|
||||
p->preview_row[3 * dst_x + 0] =
|
||||
p->image_data[src_offset + 3 * x + 0];
|
||||
p->preview_row[3 * dst_x + 1] =
|
||||
p->image_data[src_offset + 3 * x + 1];
|
||||
p->preview_row[3 * dst_x + 2] =
|
||||
p->image_data[src_offset + 3 * x + 2];
|
||||
src_x += xscale;
|
||||
}
|
||||
memcpy(p->preview_data + (size_t) dst_y * (size_t) gwidth * 3, p->preview_row, (size_t) gwidth * 3);
|
||||
src_x = 0.0;
|
||||
src_y += yscale;
|
||||
}
|
||||
gtk_widget_queue_draw (p->window);
|
||||
// float xscale, yscale, src_x, src_y;
|
||||
// int dst_x, dst_y, height, x, y, src_offset;
|
||||
// gint gwidth, gheight;
|
||||
//
|
||||
// gwidth = p->preview_width;
|
||||
// gheight = p->preview_height;
|
||||
//
|
||||
// get_image_scale (p, &xscale, &yscale);
|
||||
//
|
||||
// if (p->preview_row == NULL)
|
||||
// p->preview_row = malloc (3 * gwidth);
|
||||
// else
|
||||
// p->preview_row = realloc (p->preview_row, 3 * gwidth);
|
||||
// memset (p->preview_row, 0xff, 3 * gwidth);
|
||||
//// if (p->preview_data == NULL)
|
||||
//// p->preview_data = malloc (3 * gwidth * gheight);
|
||||
//// else
|
||||
//// p->preview_data = realloc (p->preview_data, 3 * gwidth * gheight);
|
||||
//// memset (p->preview_data, 0xff, 3 * gwidth * gheight);
|
||||
// gtk_widget_queue_draw (p->window);
|
||||
//
|
||||
// /* 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;
|
||||
// for (dst_y = 0; dst_y < gheight; ++dst_y)
|
||||
// {
|
||||
// y = (int) (src_y + 0.5);
|
||||
// if (y >= height)
|
||||
// break;
|
||||
// src_offset = y * 3 * p->image_width;
|
||||
//
|
||||
// if (p->image_data)
|
||||
// for (dst_x = 0; dst_x < gwidth; ++dst_x)
|
||||
// {
|
||||
// x = (int) (src_x + 0.5);
|
||||
// if (x >= p->image_width)
|
||||
// break;
|
||||
//
|
||||
// p->preview_row[3 * dst_x + 0] =
|
||||
// p->image_data[src_offset + 3 * x + 0];
|
||||
// p->preview_row[3 * dst_x + 1] =
|
||||
// p->image_data[src_offset + 3 * x + 1];
|
||||
// p->preview_row[3 * dst_x + 2] =
|
||||
// p->image_data[src_offset + 3 * x + 2];
|
||||
// src_x += xscale;
|
||||
// }
|
||||
// memcpy(p->preview_data + (size_t) dst_y * (size_t) gwidth * 3, p->preview_row, (size_t) gwidth * 3);
|
||||
// src_x = 0.0;
|
||||
// src_y += yscale;
|
||||
// }
|
||||
// gtk_widget_queue_draw (p->window);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -376,8 +382,8 @@ display_image (Preview * p)
|
|||
p->image_data = realloc (p->image_data,
|
||||
3 * p->image_width * p->image_height);
|
||||
assert (p->image_data);
|
||||
p->preview_data = realloc (p->preview_data,
|
||||
3 * p->image_width * p->image_height);
|
||||
// p->preview_data = realloc (p->preview_data,
|
||||
// 3 * p->image_width * p->image_height);
|
||||
}
|
||||
display_partial_image (p);
|
||||
scan_done (p);
|
||||
|
@ -608,7 +614,7 @@ increment_image_y (Preview * p)
|
|||
extra_size = 3 * 32 * p->image_width;
|
||||
p->image_height += 32;
|
||||
p->image_data = realloc (p->image_data, offset + extra_size);
|
||||
p->preview_data = realloc (p->preview_data, offset + extra_size);
|
||||
// p->preview_data = realloc (p->preview_data, offset + extra_size);
|
||||
if (!p->image_data)
|
||||
{
|
||||
snprintf (buf, sizeof (buf),
|
||||
|
@ -619,7 +625,10 @@ increment_image_y (Preview * p)
|
|||
return -1;
|
||||
}
|
||||
memset (p->image_data + offset, 0xff, extra_size);
|
||||
memset (p->preview_data + offset, 0xff, extra_size);
|
||||
// memset (p->preview_data + offset, 0xff, extra_size);
|
||||
|
||||
g_object_unref(p->image_pixbuf);
|
||||
p->image_pixbuf = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -949,12 +958,16 @@ scan_start (Preview * p)
|
|||
gsg_set_sensitivity (p->dialog, FALSE);
|
||||
// gtk_widget_set_sensitive (p->dialog->window->parent->parent->parent, FALSE);
|
||||
|
||||
if (p->preview_data == NULL)
|
||||
p->preview_data = malloc (p->image_width * p->image_height * 3);
|
||||
else
|
||||
p->preview_data = realloc (p->preview_data, 3 * p->image_width * p->image_height);
|
||||
// if (p->preview_data == NULL)
|
||||
// p->preview_data = malloc (p->image_width * p->image_height * 3);
|
||||
// else
|
||||
// p->preview_data = realloc (p->preview_data, 3 * p->image_width * p->image_height);
|
||||
/* clear old preview: */
|
||||
memset (p->preview_data, 0xff, 3 * p->image_width * p->image_height);
|
||||
// memset (p->preview_data, 0xff, 3 * p->image_width * p->image_height);
|
||||
|
||||
g_object_unref(p->image_pixbuf);
|
||||
p->image_pixbuf = NULL;
|
||||
|
||||
gtk_widget_queue_draw (p->window);
|
||||
|
||||
if (p->input_tag >= 0)
|
||||
|
@ -1040,6 +1053,12 @@ scan_start (Preview * p)
|
|||
if (!p->image_data || p->params.pixels_per_line != p->image_width
|
||||
|| (p->params.lines >= 0 && p->params.lines != p->image_height))
|
||||
{
|
||||
if (p->image_pixbuf)
|
||||
{
|
||||
g_object_unref(p->image_pixbuf);
|
||||
p->image_pixbuf = NULL;
|
||||
}
|
||||
|
||||
/* image size changed */
|
||||
if (p->image_data)
|
||||
free (p->image_data);
|
||||
|
@ -1050,7 +1069,7 @@ scan_start (Preview * p)
|
|||
p->image_height = 32; /* may have to adjust as we go... */
|
||||
|
||||
p->image_data = malloc (p->image_width * p->image_height * 3);
|
||||
p->preview_data = malloc (p->preview_width * p->image_height * 3);
|
||||
// p->preview_data = malloc (p->preview_width * p->image_height * 3);
|
||||
if (!p->image_data)
|
||||
{
|
||||
snprintf (buf, sizeof (buf),
|
||||
|
@ -1064,7 +1083,7 @@ scan_start (Preview * p)
|
|||
|
||||
if (p->selection.active)
|
||||
{
|
||||
p->previous_selection = p->selection;
|
||||
// p->previous_selection = p->selection;
|
||||
p->selection.active = FALSE;
|
||||
gtk_widget_queue_draw (p->window);
|
||||
}
|
||||
|
@ -1129,23 +1148,22 @@ restore_preview_image (Preview * p)
|
|||
int width, height;
|
||||
float psurface[4];
|
||||
size_t nread;
|
||||
FILE *in;
|
||||
FILE *in = NULL;
|
||||
|
||||
/* See whether there is a saved preview and load it if present: */
|
||||
|
||||
if (make_preview_image_path (p, sizeof (filename), filename) < 0)
|
||||
return;
|
||||
goto finish;
|
||||
|
||||
in = fopen (filename, "r");
|
||||
if (!in)
|
||||
return;
|
||||
goto finish;
|
||||
|
||||
/* Be careful about consuming too many bytes after the final newline
|
||||
(e.g., consider an image whose first image byte is 13 (`\r'). */
|
||||
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, &width, &height) != 8)
|
||||
return;
|
||||
goto finish;
|
||||
|
||||
if (GROSSLY_DIFFERENT (psurface[0], p->surface[0])
|
||||
|| GROSSLY_DIFFERENT (psurface[1], p->surface[1])
|
||||
|
@ -1153,12 +1171,12 @@ restore_preview_image (Preview * p)
|
|||
|| GROSSLY_DIFFERENT (psurface[3], p->surface[3])
|
||||
|| psurface_type != p->surface_type || psurface_unit != p->surface_unit)
|
||||
/* ignore preview image that was acquired for/with a different surface */
|
||||
return;
|
||||
goto finish;
|
||||
|
||||
p->image_width = width;
|
||||
p->image_height = height;
|
||||
if ((width == 0) || (height == 0))
|
||||
return;
|
||||
goto finish;
|
||||
|
||||
int data_size = 3 * width * height;
|
||||
|
||||
|
@ -1166,25 +1184,21 @@ restore_preview_image (Preview * p)
|
|||
if ((data_size / width) / height != 3)
|
||||
{
|
||||
// overflow occurred. Ignore the image. The dimensions are probably corrupted.
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
p->image_data = malloc (data_size);
|
||||
if (!p->image_data)
|
||||
return;
|
||||
|
||||
p->preview_data = malloc (data_size);
|
||||
if (!p->preview_data)
|
||||
{
|
||||
free(p->image_data);
|
||||
p->image_data = NULL;
|
||||
return;
|
||||
}
|
||||
goto finish;
|
||||
|
||||
nread = fread (p->image_data, 3, width * height, in);
|
||||
|
||||
p->image_y = nread / width;
|
||||
p->image_x = nread % width;
|
||||
|
||||
finish:
|
||||
if (in)
|
||||
fclose(in);
|
||||
}
|
||||
|
||||
/* This is executed _after_ the gtkpreview's expose routine. */
|
||||
|
@ -1193,13 +1207,54 @@ expose_handler (GtkWidget * window, cairo_t *cr, gpointer data)
|
|||
{
|
||||
Preview *p = data;
|
||||
|
||||
if (p->preview_data == NULL) return FALSE;
|
||||
if (p->image_data == NULL)
|
||||
return FALSE;
|
||||
|
||||
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(p->preview_data, GDK_COLORSPACE_RGB, FALSE, 8, p->preview_width,
|
||||
p->preview_height, p->preview_width * 3, NULL/*preview_pixbuf_data_destroy*/, NULL);
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
||||
if (p->image_pixbuf == NULL)
|
||||
{
|
||||
p->image_pixbuf = gdk_pixbuf_new_from_data (p->image_data,
|
||||
GDK_COLORSPACE_RGB, FALSE, 8,
|
||||
p->image_width,
|
||||
p->image_height,
|
||||
p->image_width * 3, NULL,
|
||||
NULL);
|
||||
if (!p->image_pixbuf)
|
||||
{
|
||||
// Scaled image could not be generated.
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gint width = gtk_widget_get_allocated_width (window);
|
||||
gint height = gtk_widget_get_allocated_height (window);
|
||||
|
||||
gint img_width = gdk_pixbuf_get_width (p->image_pixbuf);
|
||||
gint img_height = gdk_pixbuf_get_height (p->image_pixbuf);
|
||||
double scale = MIN((double )width / img_width, (double )height / img_height);
|
||||
gint scaled_width = img_width * scale;
|
||||
gint scaled_height = img_height * scale;
|
||||
|
||||
p->preview_width = scaled_width;
|
||||
p->preview_height = scaled_height;
|
||||
|
||||
/*
|
||||
* Save out the preview window size to the prefs structure.
|
||||
*
|
||||
*/
|
||||
gtk_window_get_size (GTK_WINDOW(p->top), &preferences.preview_width,
|
||||
&preferences.preview_height);
|
||||
|
||||
/*
|
||||
* TODO: we could store this scaled pixbuf in the Preview and only regenerate it
|
||||
* when the scaled image dimensions or content changes. [RL]
|
||||
*/
|
||||
GdkPixbuf *scaled = gdk_pixbuf_scale_simple (p->image_pixbuf, scaled_width,
|
||||
scaled_height,
|
||||
GDK_INTERP_BILINEAR);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, scaled, 0, 0);
|
||||
cairo_paint(cr);
|
||||
g_object_unref(pixbuf);
|
||||
g_object_unref(scaled);
|
||||
|
||||
if (p->selection_drag == FALSE)
|
||||
update_selection (p);
|
||||
|
@ -1317,10 +1372,10 @@ preview_new (GSGDialog * dialog)
|
|||
p->surface_unit = SANE_UNIT_MM;
|
||||
p->input_tag = -1;
|
||||
p->image_data = NULL;
|
||||
p->preview_data = NULL;
|
||||
p->preview_row = NULL;
|
||||
p->top = NULL;
|
||||
p->scanning = FALSE;
|
||||
p->image_pixbuf = NULL;
|
||||
|
||||
if (first_time)
|
||||
{
|
||||
|
@ -1335,6 +1390,17 @@ preview_new (GSGDialog * dialog)
|
|||
gtk_window_set_title (GTK_WINDOW (p->top), "xscanimage preview");
|
||||
vbox = GTK_BOX (gtk_dialog_get_content_area(GTK_DIALOG (p->top)));
|
||||
|
||||
// Set the default size of the preview window.
|
||||
if ((preferences.preview_width == 0) || (preferences.preview_height == 0))
|
||||
{
|
||||
int screen_width, screen_height;
|
||||
screen_size_get_dimensions (&screen_width, &screen_height);
|
||||
preferences.preview_width = 0.5 * (double)screen_width;
|
||||
preferences.preview_height = 0.7 * (double)screen_height;
|
||||
}
|
||||
gtk_window_set_default_size (GTK_WINDOW(p->top), preferences.preview_width,
|
||||
preferences.preview_height);
|
||||
|
||||
// construct the preview area (table with sliders & preview window)
|
||||
table = gtk_grid_new ();
|
||||
gtk_grid_set_column_spacing (GTK_GRID (table), 1);
|
||||
|
@ -1421,6 +1487,13 @@ preview_new (GSGDialog * dialog)
|
|||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* The purpose of this function is to take account of external changes
|
||||
* and reflect them in the preview.
|
||||
*
|
||||
* - If the image geometry or other parameters change, then reset the preview window.
|
||||
* -
|
||||
*/
|
||||
void
|
||||
preview_update (Preview * p)
|
||||
{
|
||||
|
@ -1431,6 +1504,20 @@ preview_update (Preview * p)
|
|||
SANE_Unit unit;
|
||||
float min, max;
|
||||
|
||||
/*
|
||||
* Read preview image geometry from the options. This determines the area that
|
||||
* we are scanning for the preview image itself. This will typically be the maximum
|
||||
* extents of the width and height that the backend will support. So, maximum scan.
|
||||
*
|
||||
* For each, we also read type (data type) and unit (mm/pixel).
|
||||
*
|
||||
* Note: that we are making the bald assumption that all geometry items
|
||||
* are the same type and unit. I don't believe that there is anything in the
|
||||
* standard that says it has to be. It probably usually is, but there is no
|
||||
* reason that we should do so.
|
||||
* We will assume that the type and unit of the final option is the one to use. [RL]
|
||||
*
|
||||
*/
|
||||
surface_changed = 0;
|
||||
unit = SANE_UNIT_PIXEL;
|
||||
type = SANE_TYPE_INT;
|
||||
|
@ -1467,91 +1554,27 @@ preview_update (Preview * p)
|
|||
surface_changed = 1;
|
||||
p->surface_type = type;
|
||||
}
|
||||
|
||||
/*
|
||||
* If any of the image preview geometry changes then remove the image and
|
||||
* flush out anything that depends on it.
|
||||
* This effectively puts us in the initial case with no preview.
|
||||
*
|
||||
*/
|
||||
if (surface_changed && p->image_data)
|
||||
{
|
||||
free (p->image_data);
|
||||
free (p->preview_data);
|
||||
|
||||
g_object_unref(p->image_pixbuf);
|
||||
p->image_pixbuf = NULL;
|
||||
|
||||
p->image_data = 0;
|
||||
p->preview_data = 0;
|
||||
p->image_width = 0;
|
||||
p->image_height = 0;
|
||||
}
|
||||
|
||||
/* guess the initial preview window size: */
|
||||
|
||||
width = p->surface[GSG_BR_X] - p->surface[GSG_TL_X];
|
||||
height = p->surface[GSG_BR_Y] - p->surface[GSG_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;
|
||||
|
||||
if (surface_changed)
|
||||
{
|
||||
int width, height;
|
||||
screen_size_get_dimensions (&width, &height);
|
||||
max_width = 0.5 * (double)width;
|
||||
max_height = 0.5 * (double)height;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocated_size (p->window, &alloc, NULL);
|
||||
max_width = alloc.width;
|
||||
max_height = alloc.height;
|
||||
}
|
||||
|
||||
if (p->surface_unit != SANE_UNIT_PIXEL)
|
||||
{
|
||||
width = max_width;
|
||||
height = width / p->aspect;
|
||||
|
||||
if (height > max_height)
|
||||
{
|
||||
height = max_height;
|
||||
width = height * p->aspect;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (width > max_width)
|
||||
width = max_width;
|
||||
|
||||
if (height > max_height)
|
||||
height = max_height;
|
||||
}
|
||||
|
||||
/* re-adjust so we maintain aspect without exceeding max size: */
|
||||
if (width / height != p->aspect)
|
||||
{
|
||||
if (p->aspect > 1.0)
|
||||
height = width / p->aspect;
|
||||
else
|
||||
width = height * p->aspect;
|
||||
}
|
||||
|
||||
p->preview_width = width + 0.5;
|
||||
p->preview_height = height + 0.5;
|
||||
if (surface_changed)
|
||||
{
|
||||
gtk_widget_set_size_request (GTK_WIDGET (p->window),
|
||||
p->preview_width, p->preview_height);
|
||||
if (gtk_widget_is_drawable(GTK_WIDGET(p->window)))
|
||||
preview_area_resize (p->window, NULL, p);
|
||||
|
||||
if (preferences.preserve_preview)
|
||||
restore_preview_image (p);
|
||||
}
|
||||
|
@ -1630,6 +1653,11 @@ preview_destroy (Preview * p)
|
|||
char filename[PATH_MAX];
|
||||
FILE *out;
|
||||
|
||||
if (!p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->scanning)
|
||||
scan_done (p); /* don't save partial window */
|
||||
else if (preferences.preserve_preview && p->image_data
|
||||
|
@ -1648,15 +1676,29 @@ preview_destroy (Preview * p)
|
|||
fclose (out);
|
||||
}
|
||||
}
|
||||
|
||||
if (p->image_data)
|
||||
free (p->image_data);
|
||||
p->image_data = NULL;
|
||||
if (p->preview_data)
|
||||
free (p->preview_data);
|
||||
p->preview_data = NULL;
|
||||
{
|
||||
free (p->image_data);
|
||||
p->image_data = NULL;
|
||||
}
|
||||
|
||||
// if (p->preview_data)
|
||||
// free (p->preview_data);
|
||||
// p->preview_data = NULL;
|
||||
|
||||
if (p->image_pixbuf)
|
||||
{
|
||||
g_object_unref(p->image_pixbuf);
|
||||
p->image_pixbuf = NULL;
|
||||
}
|
||||
|
||||
if (p->preview_row)
|
||||
free (p->preview_row);
|
||||
p->preview_row = NULL;
|
||||
{
|
||||
free (p->preview_row);
|
||||
p->preview_row = NULL;
|
||||
}
|
||||
|
||||
if (p->top)
|
||||
gtk_widget_destroy (p->top);
|
||||
free (p);
|
||||
|
|
|
@ -62,7 +62,6 @@ typedef struct
|
|||
int image_width;
|
||||
int image_height;
|
||||
u_char *image_data; /* 3 * image_width * image_height bytes */
|
||||
u_char *preview_data; /* 3 * image_width * image_height bytes */
|
||||
|
||||
int selection_drag;
|
||||
struct
|
||||
|
@ -70,7 +69,7 @@ typedef struct
|
|||
int active;
|
||||
double coord[4];
|
||||
}
|
||||
selection, previous_selection;
|
||||
selection; // coords of selection box in the preview window
|
||||
|
||||
GtkWidget *top; /* top-level widget */
|
||||
GtkWidget *hruler;
|
||||
|
@ -80,8 +79,7 @@ typedef struct
|
|||
GtkWidget *cancel; /* the cancel button */
|
||||
GtkWidget *preview; /* the preview button */
|
||||
|
||||
cairo_surface_t *surface_cairo;
|
||||
gboolean drawable;
|
||||
GdkPixbuf *image_pixbuf;
|
||||
}
|
||||
Preview;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue