gnome-scan r721 - in trunk: . modules/gsane
- From: bersace svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-scan r721 - in trunk: . modules/gsane
- Date: Sat, 20 Dec 2008 19:02:44 +0000 (UTC)
Author: bersace
Date: Sat Dec 20 19:02:43 2008
New Revision: 721
URL: http://svn.gnome.org/viewvc/gnome-scan?rev=721&view=rev
Log:
Support hand scanner.
Modified:
trunk/ChangeLog
trunk/modules/gsane/gsane-processor.c
trunk/modules/gsane/gsane-scanner.c
Modified: trunk/modules/gsane/gsane-processor.c
==============================================================================
--- trunk/modules/gsane/gsane-processor.c (original)
+++ trunk/modules/gsane/gsane-processor.c Sat Dec 20 19:02:43 2008
@@ -165,14 +165,19 @@
GeglRectangle extent = {
.x = 0, .y = 0,
.width = params->pixels_per_line,
- .height = params->lines,
+ /* we set an arbirary huge height for unknown height,
+ GSaneScanner takes care of resizing at end of frame
+ acquisition */
+ .height = (params->lines == -1 ? 65535 : params->lines),
};
self->priv->params = params;
self->priv->frame_count = frame_count;
self->priv->bytes_per_pixel = (gdouble)params->bytes_per_line/(gdouble)params->pixels_per_line;
+
self->priv->process = gsane_processor_get_func(self);
g_return_val_if_fail(self->priv->process, NULL);
+
self->priv->format = gsane_processor_get_babl_format(self);
g_return_val_if_fail(self->priv->format, NULL);
@@ -186,26 +191,6 @@
self->priv->params = params;
self->priv->bytes_processed = 0;
self->priv->sample_offset = gsane_processor_get_sample_offset(self);
- switch(params->format) {
- case SANE_FRAME_GRAY:
- g_debug("Processing GRAY frame format");
- break;
- case SANE_FRAME_RGB:
- g_debug("Processing RGB frame format");
- break;
- case SANE_FRAME_RED:
- g_debug("Processing RED frame format");
- break;
- case SANE_FRAME_GREEN:
- g_debug("Processing GREEN frame format");
- break;
- case SANE_FRAME_BLUE:
- g_debug("Processing BLUE frame format");
- break;
- default:
- g_debug("Unknown frame format");
- break;
- }
}
void
@@ -247,12 +232,6 @@
}
}
- /* extend buffer to fit if needed */
- GeglRectangle *extent = g_boxed_copy(GEGL_TYPE_RECTANGLE, gegl_buffer_get_extent(self->priv->buffer));
- extent->height = MAX(extent->height, self->priv->rect.y+self->priv->rect.height);
- gegl_buffer_set_extent(self->priv->buffer, extent);
- g_boxed_free(GEGL_TYPE_RECTANGLE, extent);
-
/* process */
g_debug("Processing %dx%d+%d+%d", self->priv->rect.width, self->priv->rect.height, self->priv->rect.x, self->priv->rect.y);
self->priv->process(self, buf, buf_len);
Modified: trunk/modules/gsane/gsane-scanner.c
==============================================================================
--- trunk/modules/gsane/gsane-scanner.c (original)
+++ trunk/modules/gsane/gsane-scanner.c Sat Dec 20 19:02:43 2008
@@ -49,13 +49,13 @@
guint image_count;
/* SANE frame paramters */
SANE_Parameters params;
+ guint chunk_len;
guint bytes_per_pixel;
+ guint frame_count;
/* total bytes read*/
volatile guint bytes_read;
/* total bytes to acquire to get the entire image (all frames) */
guint total_bytes_count;
- /* status */
- gboolean guessing_parameters;
/* Threads */
GThread* opt_thread;
@@ -86,7 +86,8 @@
}
-/* Returns whether the status is good */
+/* Returns whether the status is good. Update node status if
+ failing. */
static gboolean
gsane_scanner_check_sane_status(GSaneScanner *self, const gchar* operation, SANE_Status status)
{
@@ -98,6 +99,9 @@
return status == SANE_STATUS_GOOD;
}
+/* Reload parameters. This is useful if we want to predetermine image
+ size and such. However, it is not supposed to be accurate before
+ sane_start() (see SANE standard). */
static void
gsane_scanner_reload_parameters_thread(GSaneScanner* self)
{
@@ -111,9 +115,7 @@
g_debug("%s parameters reloaded", self->priv->sane_id);
- sane_cancel(self->priv->handle);
self->priv->params_thread = NULL;
- self->priv->guessing_parameters = FALSE;
}
void
@@ -125,6 +127,8 @@
self->priv->params_thread = g_thread_create((GThreadFunc)gsane_scanner_reload_parameters_thread, self, FALSE, NULL);
}
+/* Take care of one option, instanciating the right handler and
+ passing option to it. */
static void
gsane_scanner_handle_sane_option(GSaneScanner*self, SANE_Int n, const SANE_Option_Descriptor* desc, const gchar* group)
{
@@ -144,9 +148,8 @@
key = g_type_name(handler_type);
handler = g_hash_table_lookup(self->priv->option_handlers, key);
}
- else {
+ else
key = desc->name;
- }
if (handler == NULL) {
handler = gsane_option_handler_new(handler_type, GNOME_SCAN_SCANNER(self), self->priv->handle);
@@ -159,8 +162,9 @@
g_type_class_unref(handler_class);
}
-/* GThreadFunc */
-static void*
+/* Loops all SANE option and extract groups, sensors, buttons and
+ regular option. Let OptionHandler manager *all* options. */
+static void
gsane_scanner_probe_options(GSaneScanner *self)
{
SANE_Status status;
@@ -201,14 +205,18 @@
}
}
+ /* initialisation is done */
gnome_scan_node_update_status(GNOME_SCAN_NODE(self), GNOME_SCAN_STATUS_UNCONFIGURED, NULL);
+ /* this is where we know if we're actually ready. (well
+ actually not until sane_start()â) */
gsane_scanner_reload_parameters(self);
end:
self->priv->opt_thread = NULL;
- return NULL;
}
+/* Start counting images acquired during an atomic scan for mass
+ acquisition. */
static void
gsane_scanner_start_scan(GnomeScanNode *node)
{
@@ -216,12 +224,14 @@
self->priv->image_count = 0;
}
-static gboolean gsane_scanner_start_frame(GSaneScanner *self)
+/* Ask SANE to start a frame, update parameters according. We may need
+ to call sane_cancel() before each sane_start() in order to avoid
+ nasty SANE_STATUS_BUSY. */
+static gboolean
+gsane_scanner_start_frame(GSaneScanner *self)
{
SANE_Status status;
- sane_cancel(self->priv->handle);
-
status = sane_start(self->priv->handle);
if (!gsane_scanner_check_sane_status(self, "sane_start", status))
return FALSE;
@@ -230,13 +240,18 @@
if (!gsane_scanner_check_sane_status(self, "sane_get_parameters", status))
return FALSE;
+ /* Scan line by line. We may compute larger chunk considering
+ height. */
+ self->priv->chunk_len = self->priv->params.bytes_per_line;
gsane_processor_prepare_frame(&self->priv->processor, &self->priv->params);
- g_debug("New frame started");
-
return TRUE;
}
+/* returns the amount of frame to acquire to get all the image
+ data. Actually SANE tells use whether a frame is the last or
+ not. However we need frame count to handle proper sample handling,
+ progress monitoring, etc. */
static guint
gsane_scanner_get_frame_count(GSaneScanner *self)
{
@@ -253,59 +268,98 @@
}
}
+/* Starts the acquisition of one image of a scan. */
static gboolean
gsane_scanner_start_image(GnomeScanNode *node)
{
GSaneScanner *self = GSANE_SCANNER(node);
GeglBuffer *buffer;
- guint frame_count;
+ /* No mass acquisition from flatbed. We might use timeout scan, at this level? */
if (self->priv->image_count > 0 && !self->priv->is_adf_selected)
return FALSE;
+ /* start the frame */
if (!gsane_scanner_start_frame(self))
return FALSE;
- frame_count = gsane_scanner_get_frame_count(self);
+ self->priv->frame_count = gsane_scanner_get_frame_count(self);
self->priv->bytes_read = 0;
self->priv->bytes_per_pixel = self->priv->params.bytes_per_line/self->priv->params.pixels_per_line;
- self->priv->total_bytes_count = self->priv->params.pixels_per_line * self->priv->params.lines * frame_count;
+ self->priv->total_bytes_count = self->priv->params.pixels_per_line * self->priv->params.lines * self->priv->frame_count;
- buffer = gsane_processor_prepare_image(&self->priv->processor, &self->priv->params, frame_count);
+ /* get the image buffer from the processor and let processor
+ initialize data processing */
+ buffer = gsane_processor_prepare_image(&self->priv->processor, &self->priv->params, self->priv->frame_count);
gnome_scan_scanner_set_buffer((GnomeScanScanner*)self, buffer);
return TRUE;
}
+/* Called once SANE stop sending data */
+static gboolean
+gsane_scanner_end_frame(GSaneScanner *self, SANE_Status status)
+{
+ g_debug("%s", sane_strstatus(status));
+ /* The frame is acquired */
+ if (status == SANE_STATUS_EOF) {
+ if (!self->priv->params.last_frame)
+ /* start next frame */
+ return gsane_scanner_start_frame(self);
+ else {
+ /* terminate hand scanner acquisition */
+ if (self->priv->params.lines == -1)
+ gsane_scanner_resize_buffer(self);
+ return FALSE; /* job done :). */
+ }
+ }
+ else
+ return FALSE; /* an error occur, just stop the work */
+}
+
+/* Resize buffer to actual size. This is needed for hand scanner where
+ we put an arbitrary huge height and then shrink back to the actual
+ height. */
+static void
+gsane_scanner_resize_buffer(GSaneScanner *self)
+{
+ GeglBuffer *buffer;
+ const GeglRectangle *extent;
+ GeglRectangle *actual_extent;
+ guint actual_height;
+
+ buffer = gnome_scan_scanner_get_buffer(GNOME_SCAN_SCANNER(self));
+ extent = gegl_buffer_get_extent(buffer);
+ actual_height = (self->priv->bytes_read/self->priv->frame_count) / self->priv->params.bytes_per_line;
+ actual_extent = g_boxed_copy(GEGL_TYPE_RECTANGLE, extent);
+ actual_extent->height = actual_height;
+ gegl_buffer_set_extent(buffer, actual_extent);
+ g_boxed_free(GEGL_TYPE_RECTANGLE, actual_extent);
+}
+
+/* Actually ask SANE data and work on it. */
static gboolean
gsane_scanner_work(GnomeScanScanner*scanner, gdouble *progress)
{
- GSaneScanner *self = GSANE_SCANNER(scanner);
+ GSaneScanner *self = (GSaneScanner*) scanner;
SANE_Status status;
SANE_Byte *buf;
SANE_Int read_len;
- guint chunk_len = self->priv->params.bytes_per_line;
- buf = g_new0(SANE_Byte, chunk_len);
- status = sane_read (self->priv->handle, buf, chunk_len, &read_len);
- if (status != SANE_STATUS_GOOD) {
- g_debug("%s", sane_strstatus(status));
- if (status == SANE_STATUS_EOF) {
- if (!self->priv->params.last_frame)
- /* start next frame */
- return gsane_scanner_start_frame(self);
- else
- return FALSE;
- }
- else
- return FALSE;
- }
+ buf = g_new0(SANE_Byte, self->priv->chunk_len);
+ status = sane_read (self->priv->handle, buf, self->priv->chunk_len, &read_len);
+
+ if (status != SANE_STATUS_GOOD)
+ /* close current frame and start next if this is not
+ the last frame of the image */
+ return gsane_scanner_end_frame(self, status);
self->priv->bytes_read += read_len;
- g_debug("Asked %d bytes, got %d", chunk_len, read_len);
+ /* process the bytes received */
gsane_processor_process(&self->priv->processor, buf, read_len);
g_free(buf);
+ /* compute progress */
*progress = (gdouble)self->priv->bytes_read/(gdouble)self->priv->total_bytes_count;
return TRUE;
}
@@ -314,6 +368,8 @@
gsane_scanner_end_image(GnomeScanNode*scanner)
{
GSaneScanner *self = GSANE_SCANNER(scanner);
+ /* Some backends needs to explicitely stop scan even after
+ EOF. do we need this for each frame ? */
sane_cancel(self->priv->handle);
self->priv->image_count++;
}
@@ -361,12 +417,6 @@
}
static void
-gsane_scanner_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
-{
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
-}
-
-static void
gsane_scanner_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
GSaneScanner *self;
@@ -393,7 +443,7 @@
o_class->constructor = gsane_scanner_constructor;
o_class->finalize = gsane_scanner_finalize;
- o_class->get_property = gsane_scanner_get_property;
+ /* there is no readable properties */
o_class->set_property = gsane_scanner_set_property;
g_object_class_install_property(o_class, GSANE_SCANNER_SANE_ID, g_param_spec_string("sane-id", "SANE ID", "SANE device id", NULL,G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(o_class, GSANE_SCANNER_SANE_TYPE, g_param_spec_string("sane-type", "SANE Type", "SANE device type", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]