gnome-scan r727 - in trunk: . modules/gsane



Author: bersace
Date: Sun Dec 21 16:36:06 2008
New Revision: 727
URL: http://svn.gnome.org/viewvc/gnome-scan?rev=727&view=rev

Log:
Added three-pass nbit data support.

Modified:
   trunk/ChangeLog
   trunk/modules/gsane/gsane-processor.c

Modified: trunk/modules/gsane/gsane-processor.c
==============================================================================
--- trunk/modules/gsane/gsane-processor.c	(original)
+++ trunk/modules/gsane/gsane-processor.c	Sun Dec 21 16:36:06 2008
@@ -41,6 +41,7 @@
 	volatile guint bytes_processed;
 	/* total number of frame to acquire to get the entire image */
 	guint frame_count;
+	/* number of sample in frame */
 	guint sample_count;
 	/* offset of a sample in bytes for three-pass acquisition */
 	guint sample_offset;
@@ -161,14 +162,15 @@
 		src_pos = i * self->priv->bytes_per_pixel / self->priv->sample_count;
 		/* retrieve bytes containing sample value */
 		memcpy(&value, buf+src_pos, self->priv->sample_stride);
-		/* compute the offset of the samples bits inside the sample stride */
-		offset = (8 * self->priv->sample_stride) - ((i * self->priv->params->depth) - (src_pos * 8)) - 1;
+		/* At which bit from right of value start the sample. */
+		offset = (i * self->priv->params->depth) - (src_pos * 8);
 		/* align sample bits to the right */
 		value = value >> offset;
 		/* apply sample patter to get sample value */
 		value = value & self->priv->sample_pattern;
 		/* compute target value */
-		value = self->priv->max_target_sample_value * (value / self->priv->max_sample_value);
+		value = (gdouble)self->priv->max_target_sample_value * ((gdouble)value / (gdouble)self->priv->max_sample_value);
+
 		/* get the address of the first byte set. */
 		src = (guchar*)(&value);
 #if G_BYTE_ORDER == G_BIG_ENDIAN
@@ -183,7 +185,6 @@
 	gegl_buffer_set(self->priv->buffer, &roi, self->priv->format, buf8, GEGL_AUTO_ROWSTRIDE);
 	g_free(buf8);
 }
-
 static void
 gsane_processor_process_three_pass_1bit(GSaneProcessor *self, guchar *buf, guint buf_len)
 {
@@ -225,6 +226,43 @@
 	g_free(buf3);
 }
 
+
+static void
+gsane_processor_process_three_pass_nbit(GSaneProcessor *self, guchar *buf, guint buf_len)
+{
+	GeglRectangle roi = self->priv->rect;
+	guint32 value = 0;
+	guchar *src, *dest, *buf8 = g_new0(guchar, self->priv->pixels_in_buf * self->priv->sample_stride * self->priv->frame_count);
+	guint i, offset, src_pos;
+	gegl_buffer_get(self->priv->buffer, 1.0, &roi, self->priv->format, buf8, GEGL_AUTO_ROWSTRIDE);
+	for (i = 0; i < self->priv->pixels_in_buf; i++) {
+		/* compute the address of the first byte container sample value */
+		src_pos = i* self->priv->bytes_per_pixel;
+		/* retrieve bytes containing sample value */
+		memcpy(&value, buf + src_pos, self->priv->sample_stride);
+		/* compute the offset of the samples bits inside the sample stride */
+		offset = (8 * self->priv->sample_stride) - ((i * self->priv->params->depth) - (src_pos * 8)) - 1;
+		/* align sample bits to the right */
+		value = value >> offset;
+		/* apply sample patter to get sample value */
+		value = value & self->priv->sample_pattern;
+		/* compute target value */
+		value = self->priv->max_target_sample_value * (value / self->priv->max_sample_value);
+		/* get the address of the first byte set. */
+		src = (guchar*)(&value);
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+		src = src + (sizeof(value) - self->priv->sample_stride);
+#endif
+		/* compute the first byte target address */
+		dest = buf8 + i * self->priv->frame_count * self->priv->sample_stride  + self->priv->sample_offset;
+		/* save */
+		memcpy(dest, src, self->priv->sample_stride);
+	}
+	/* send */
+	gegl_buffer_set(self->priv->buffer, &roi, self->priv->format, buf8, GEGL_AUTO_ROWSTRIDE);
+	g_free(buf8);
+}
+
 static GSaneProcessorFunc
 gsane_processor_get_func(GSaneProcessor *self)
 {
@@ -247,7 +285,7 @@
 		else if (self->priv->params->depth == 1)
 			func = gsane_processor_process_three_pass_1bit;
 		else
-			g_warning("Unsupported %dbit three-pass frame format", self->priv->params->depth);
+			func = gsane_processor_process_three_pass_nbit;
 		break;
 	default:
 		g_warning("Unsupported SANE frame format.");
@@ -308,14 +346,34 @@
 	case SANE_FRAME_RED:
 		return 0;
 	case SANE_FRAME_GREEN:
-		return self->priv->pixel_stride;
+		return self->priv->sample_stride;
 	case SANE_FRAME_BLUE:
-		return 2 * self->priv->pixel_stride;
+		return 2 * self->priv->sample_stride;
 	default:
 		return 0;
 	}
 }
 
+static guint
+gsane_processor_get_sample_count(GSaneProcessor *self)
+{
+	switch(self->priv->params->format) {
+	case SANE_FRAME_RGB:
+		return 3;
+	case SANE_FRAME_GRAY:
+	case SANE_FRAME_RED:
+	case SANE_FRAME_GREEN:
+	case SANE_FRAME_BLUE:
+		return 1;
+		break;
+	default:
+		g_warning("Unsupported SANE frame format.");
+		break;
+	}
+
+	return 0;
+}
+
 /* Initialize acquisition of one image. Returns the buffer initialized
    with right format and extent. */
 GeglBuffer*
@@ -331,11 +389,12 @@
 	};
 
 	self->priv->params = params;
+	/* computes values used by various processor func */
 	self->priv->frame_count		= frame_count;
-	self->priv->bytes_per_pixel	= (gdouble)params->bytes_per_line / (gdouble)params->pixels_per_line;
+	self->priv->sample_count	= gsane_processor_get_sample_count(self);
+	self->priv->bits_per_pixel	= params->depth * self->priv->sample_count;
+	self->priv->bytes_per_pixel	= (gdouble) self->priv->bits_per_pixel / 8.;
 	self->priv->pixel_stride	= floor(self->priv->bytes_per_pixel) + (self->priv->bytes_per_pixel > (gdouble)((guint) self->priv->bytes_per_pixel) ? 1 : 0);
-	self->priv->bits_per_pixel	= 8 * self->priv->bytes_per_pixel;
-	self->priv->sample_count	= self->priv->bits_per_pixel / self->priv->params->depth;
 	self->priv->max_sample_value	= (0xFFFFFFFF) >> (32 - self->priv->params->depth);
 	self->priv->pixel_pattern	= (0xFFFFFFFF) >> (32 - self->priv->bits_per_pixel);
 	self->priv->sample_pattern	= (0xFFFFFFFF) >> (32 - self->priv->params->depth);
@@ -346,8 +405,8 @@
 	self->priv->format = gsane_processor_get_babl_format(self);
 	g_return_val_if_fail(self->priv->format, NULL);
 
-	self->priv->sample_stride	= self->priv->format->format.bytes_per_pixel / self->priv->sample_count;
-	self->priv->max_target_sample_value= (0xFFFFFFFF) >> (32 - self->priv->format->format.bytes_per_pixel / self->priv->sample_count * 8);
+	self->priv->sample_stride	= self->priv->format->format.bytes_per_pixel / MAX(self->priv->sample_count, self->priv->frame_count);
+	self->priv->max_target_sample_value= (0xFFFFFFFF) >> (32 - self->priv->sample_stride * 8);
 
 	self->priv->buffer = gegl_buffer_new(&extent, self->priv->format);
 	return self->priv->buffer;
@@ -373,7 +432,7 @@
 	self->priv->rect.y = self->priv->bytes_processed / self->priv->params->bytes_per_line;
 	self->priv->rect.x = self->priv->bytes_processed % self->priv->params->bytes_per_line;
 	guint pixel_to_end_of_line = self->priv->params->pixels_per_line - self->priv->rect.x;
-	self->priv->pixels_in_buf = (gdouble)buf_len / self->priv->bytes_per_pixel;
+	self->priv->pixels_in_buf = (gdouble)buf_len / self->priv->params->bytes_per_line * self->priv->params->pixels_per_line;
 	self->priv->rect.width = MIN (self->priv->pixels_in_buf - self->priv->rect.x, pixel_to_end_of_line);
 
 	/* compute the height of the rect and determine whether buf is



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]