Index: xsane/src/xsane-preview.h diff -u xsane/src/xsane-preview.h:1.1.1.1 xsane/src/xsane-preview.h:1.1.1.1.6.1 --- xsane/src/xsane-preview.h:1.1.1.1 Mon Apr 22 18:38:41 2002 +++ xsane/src/xsane-preview.h Wed Jul 3 10:17:39 2002 @@ -125,7 +125,18 @@ int image_y; int image_width; /* width of preview image in pixels */ int image_height; /* height of preview image in pixel lines */ - int rotation; /* rotation: 0=0, 1=90, 2=180, 3=270 degree, 4-7= rotation + mirror in x direction */ + +#define ROTATE_0_DEGREE 0 +#define ROTATE_90_DEGREE 1 +#define ROTATE_180_DEGREE 2 +#define ROTATE_270_DEGREE 3 +#define ROTATE_0_DEGREE_X_MIRROR 4 +#define ROTATE_90_DEGREE_X_MIRROR 5 +#define ROTOATE_180_DEGREE_X_MIRROR 6 +#define ROTATE_270_DEGREE_X_MIRROR 7 + + int rotation; + int gamma_functions_interruptable; /* bit that defines if gamma function can be interrupted */ guint16 *image_data_raw; /* 3 * image_width * image_height bytes * 2 */ u_char *image_data_enh; /* 3 * image_width * image_height bytes */ Index: xsane/src/xsane-save.c diff -u xsane/src/xsane-save.c:1.1.1.1 xsane/src/xsane-save.c:1.1.1.1.6.1 --- xsane/src/xsane-save.c:1.1.1.1 Mon Apr 22 18:38:42 2002 +++ xsane/src/xsane-save.c Wed Jul 3 10:17:39 2002 @@ -1483,7 +1483,7 @@ default: break; - case 0: /* 0 degree */ + case ROTATE_0_DEGREE: xsane_write_pnm_header(outfile, image_info); for (y = 0; y < pixel_height; y++) @@ -1523,7 +1523,7 @@ } break; - case 1: /* 90 degree */ + case ROTATE_90_DEGREE: image_info->image_width = pixel_height; image_info->image_height = pixel_width; @@ -1571,7 +1571,7 @@ break; - case 2: /* 180 degree */ + case ROTATE_180_DEGREE: xsane_write_pnm_header(outfile, image_info); for (y = pixel_height-1; y >= 0; y--) @@ -1612,7 +1612,7 @@ } break; - case 3: /* 270 degree */ + case ROTATE_270_DEGREE: image_info->image_width = pixel_height; image_info->image_height = pixel_width; @@ -1659,7 +1659,7 @@ } break; - case 4: /* 0 degree, x mirror */ + case ROTATE_0_DEGREE_X_MIRROR: xsane_write_pnm_header(outfile, image_info); for (y = 0; y < pixel_height; y++) @@ -1700,7 +1700,7 @@ } break; - case 5: /* 90 degree, x mirror */ + case ROTATE_90_DEGREE_X_MIRROR: image_info->image_width = pixel_height; image_info->image_height = pixel_width; @@ -1748,7 +1748,7 @@ break; - case 6: /* 180 degree, x mirror */ + case ROTOATE_180_DEGREE_X_MIRROR: xsane_write_pnm_header(outfile, image_info); for (y = pixel_height-1; y >= 0; y--) @@ -1789,7 +1789,7 @@ } break; - case 7: /* 270 degree, x mirror */ + case ROTATE_270_DEGREE_X_MIRROR: image_info->image_width = pixel_height; image_info->image_height = pixel_width; Index: xsane/src/xsane-scan.c diff -u xsane/src/xsane-scan.c:1.1.1.1 xsane/src/xsane-scan.c:1.1.1.1.10.3 --- xsane/src/xsane-scan.c:1.1.1.1 Mon Apr 22 18:38:41 2002 +++ xsane/src/xsane-scan.c Sat Jul 6 17:50:27 2002 @@ -39,6 +39,9 @@ #endif #endif +#include +#include + /* ---------------------------------------------------------------------------------------------------------------------- */ /* forward declarations: */ @@ -71,7 +74,7 @@ free(xsane.dummy_filename); } - if ( (conversion_level == 0) && (xsane.preview->rotation) ) /* scan level with rotation */ + if ( (conversion_level == 0) && (xsane.preview->rotation != ROTATE_0_DEGREE) ) /* scan level with rotation */ { tempfile = TRUE; } @@ -110,704 +113,477 @@ /* ---------------------------------------------------------------------------------------------------------------------- */ +static void buf_to_mmap(unsigned char *scan_buf_8, SANE_Int len, int colors, int bpp) { + size_t old_pos; + size_t old_row; + size_t old_nrows; + size_t old_col; + size_t old_ncols; + size_t new_pos; + size_t new_row; + size_t new_nrows; + size_t new_col; + size_t new_ncols; + size_t color; + size_t i; + + old_nrows = xsane.param.lines; + old_ncols = xsane.param.pixels_per_line; + + for (i = 0; i < len; i++) { + old_pos = xsane.mmap_pos - xsane.header_size; + color = (old_pos % (colors * bpp)) / bpp; + old_row = old_pos / (old_ncols * colors * bpp); + old_col = (old_pos % (old_ncols * colors * bpp)) / (colors * bpp); + + switch(xsane.preview->rotation) { + case ROTATE_0_DEGREE: + new_nrows = old_nrows; + new_ncols = old_ncols; + new_row = old_row; + new_col = old_col; + break; + case ROTATE_90_DEGREE: + new_nrows = old_ncols; + new_ncols = old_nrows; + new_row = old_col; + new_col = new_ncols - old_row - 1; + break; + case ROTATE_180_DEGREE: + new_nrows = old_nrows; + new_ncols = old_ncols; + new_row = new_nrows - old_row - 1; + new_col = new_ncols - old_col - 1; + break; + case ROTATE_270_DEGREE: + new_nrows = old_ncols; + new_ncols = old_nrows; + new_row = new_nrows - old_col - 1; + new_col = old_row; + break; + case ROTATE_0_DEGREE_X_MIRROR: + new_nrows = old_nrows; + new_ncols = old_ncols; + new_row = old_row; + new_col = new_ncols - old_col - 1; + break; + case ROTATE_90_DEGREE_X_MIRROR: + new_nrows = old_ncols; + new_ncols = old_nrows; + new_row = old_col; + new_col = old_row; + break; + case ROTOATE_180_DEGREE_X_MIRROR: + new_nrows = old_nrows; + new_ncols = old_ncols; + new_row = new_nrows - old_row - 1; + new_col = old_col; + break; + case ROTATE_270_DEGREE_X_MIRROR: + new_nrows = old_ncols; + new_ncols = old_nrows; + new_row = new_nrows - old_col - 1; + new_col = new_ncols - old_row - 1; + break; + default: + /* XXXX Error */ + return; + } + new_pos = (new_row * new_ncols * colors * bpp) + (new_col * colors * bpp) + (color * bpp); + new_pos += xsane.header_size; + xsane.out_mmap[new_pos] = scan_buf_8[i]; + xsane.mmap_pos++; + if (bpp > 1) { + xsane.out_mmap[new_pos+1] = scan_buf_8[i+1]; + xsane.mmap_pos++; + i++; + } + } +} + +#define SCAN_BUF_8_LEN 65536 +#define SCAN_BUF_16_LEN 32768 + static void xsane_read_image_data(gpointer data, gint source, GdkInputCondition cond) { - SANE_Handle dev = xsane.dev; - SANE_Status status; - SANE_Int len; - int i, j, x; - char buf[255]; - + SANE_Handle dev = xsane.dev; + SANE_Status status; + SANE_Int len; + int i, j; + char buf[255]; + unsigned char scan_buf_8[SCAN_BUF_8_LEN]; + unsigned char *scan_buf_8_ex; + guint16 *scan_buf_16 = (guint16 *)scan_buf_8; + DBG(DBG_proc, "xsane_read_image_data\n"); - + xsane.reading_data = TRUE; - - x = xsane.param.pixels_per_line; - - if ( (xsane.param.depth == 1) || (xsane.param.depth == 8) ) - { - unsigned char buf8[2*32768]; - unsigned char *buf8ptr; - - DBG(DBG_info, "depth = 1 or 8 bit\n"); - while (1) - { - if (xsane.cancel_scan) - { - break; /* leave while loop */ - } + if ((xsane.param.format == SANE_FRAME_GRAY) && + (xsane.param.depth == 1) && + (xsane.expand_lineart_to_grayscale)) { + if ((scan_buf_8_ex = malloc(SCAN_BUF_8_LEN * 8)) == NULL) { - status = sane_read(dev, (SANE_Byte *) buf8, sizeof(buf8), &len); - - DBG(DBG_info, "sane_read returned with status %s\n", XSANE_STRSTATUS(status)); - DBG(DBG_info, "sane_read: len = %d\n", len); + xsane_scan_done(-1); /* -1 = error */ + snprintf(buf, sizeof(buf), "%s", ERR_NO_MEM); + xsane_back_gtk_error(buf, TRUE); + return; + } + } else { + scan_buf_8_ex = NULL; + } + + while (1) { + if (xsane.cancel_scan) { + break; /* leave while loop */ + } + + status = sane_read(dev, (SANE_Byte *) scan_buf_8 + xsane.read_offset_16, SCAN_BUF_8_LEN - xsane.read_offset_16, &len); - if (status == SANE_STATUS_EOF) - { - if (!xsane.param.last_frame) - { - DBG(DBG_info, "not last frame\n"); + if (xsane.read_offset_16 && len > 0) { + scan_buf_8[0] = xsane.last_offset_16_byte; + len++; + } + + DBG(DBG_info, "sane_read returned with status %s\n", XSANE_STRSTATUS(status)); + DBG(DBG_info, "sane_read: len = %d\n", len); - if (xsane.input_tag >= 0) - { - gdk_input_remove(xsane.input_tag); - xsane.input_tag = -1; - } - xsane_start_scan(); - break; /* leave while loop */ - } + if ((xsane.param.depth == 16) && (len % 2)) { + /* odd number of bytes */ + len--; + xsane.last_offset_16_byte = scan_buf_8[len]; + xsane.read_offset_16 = 1; + } else { + /* even number of bytes */ + xsane.read_offset_16 = 0; + } - xsane_scan_done(SANE_STATUS_EOF); /* image complete, stop scanning */ - return; + if (status == SANE_STATUS_EOF) { + if (!xsane.param.last_frame) { + DBG(DBG_info, "not last frame\n"); + if (xsane.input_tag >= 0) { + gdk_input_remove(xsane.input_tag); + xsane.input_tag = -1; + } + xsane_start_scan(); + break; /* leave while loop */ } + xsane_scan_done(SANE_STATUS_EOF); /* image complete, stop scanning */ + return; + } - if (status == SANE_STATUS_CANCELLED) - { + if (status == SANE_STATUS_CANCELLED) { xsane_scan_done(status); /* status = return of sane_read */ snprintf(buf, sizeof(buf), "%s.", XSANE_STRSTATUS(status)); xsane_back_gtk_warning(buf, TRUE); return; } - if (status != SANE_STATUS_GOOD) - { + if (status != SANE_STATUS_GOOD) { xsane_scan_done(status); /* status = return of sane_read */ snprintf(buf, sizeof(buf), "%s %s.", ERR_DURING_READ, XSANE_STRSTATUS(status)); xsane_back_gtk_error(buf, TRUE); return; } - if (!len) /* nothing read */ - { + if (len == 0) { break; /* out of data for now, leave while loop */ } xsane.bytes_read += len; xsane_progress_update(xsane.bytes_read / (gfloat) xsane.num_bytes); - /* it is not allowed to call gtk_main_iteration when we have gdk_input active */ - /* because xsane_read_image_data will be called several times */ - if (xsane.input_tag < 0) - { - while (gtk_events_pending()) - { + if (xsane.input_tag < 0) { + while (gtk_events_pending()) { DBG(DBG_info, "calling gtk_main_iteration\n"); gtk_main_iteration(); } } - - switch (xsane.param.format) - { - case SANE_FRAME_GRAY: - { - int i; - u_char val; - - DBG(DBG_info, "grayscale\n"); - - if ((!xsane.scanner_gamma_gray) && (xsane.param.depth > 1)) - { - buf8ptr = buf8; - - for (i=0; i < len; ++i) /* do gamma correction by xsane */ - { - *buf8ptr = xsane.gamma_data[(int) (*buf8ptr)]; - buf8ptr++; - } - fwrite(buf8, 1, len, xsane.out); /* write gamma corrected data */ - } - else if ((xsane.param.depth == 1) && (xsane.expand_lineart_to_grayscale)) - { - unsigned char *expanded_buf8; - unsigned char *expanded_buf8ptr; - - /* if we want to do any postprocessing (e.g. rotation) */ - /* we save lineart images in grayscale mode */ - /* to speed up transformation and saving the transformed expanded (1bit->1byte) */ - /* is written in a buffer and saved as full buffer */ - - expanded_buf8 = malloc(len * 8); /* one byte for each pixel (bit) */ - if (!expanded_buf8) - { - xsane_scan_done(-1); /* -1 = error */ - snprintf(buf, sizeof(buf), "%s", ERR_NO_MEM); - xsane_back_gtk_error(buf, TRUE); - return; - } - - expanded_buf8ptr = expanded_buf8; - buf8ptr = buf8; - - for (i = 0; i < len; ++i) - { - val = *buf8ptr; - for (j = 7; j >= 0; --j) - { - *expanded_buf8ptr = (val & (1 << j)) ? 0x00 : 0xff; - expanded_buf8ptr++; - x--; - if (x <= 0) - { - x = xsane.param.pixels_per_line; - break; - } - } - buf8ptr++; - } - fwrite(expanded_buf8, 1, len*8, xsane.out); - free(expanded_buf8); - } - else /* save direct to the file */ - { - fwrite(buf8, 1, len, xsane.out); - } - } - break; /* SANE_FRAME_GRAY */ - - case SANE_FRAME_RGB: - { - int i; - - DBG(DBG_info, "1 pass color\n"); - - if (!xsane.scanner_gamma_color) /* do gamma correction by xsane */ - { - buf8ptr = buf8; - for (i=0; i < len; ++i) - { - if (xsane.pixelcolor == 0) - { - *buf8ptr = xsane.gamma_data_red[(int) (*buf8ptr)]; - buf8ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 1) - { - *buf8ptr = xsane.gamma_data_green[(int) (*buf8ptr)]; - buf8ptr++; - xsane.pixelcolor++; - } - else - { - *buf8ptr = xsane.gamma_data_blue[(int) (*buf8ptr)]; - buf8ptr++; - xsane.pixelcolor = 0; - } - } - fwrite(buf8, 1, len, xsane.out); /* write buffer */ - } - else /* gamma correction has been done by scanner */ - { - fwrite(buf8, 1, len, xsane.out); /* write buffer */ - } - } - break; - - case SANE_FRAME_RED: - case SANE_FRAME_GREEN: - case SANE_FRAME_BLUE: - { - DBG(DBG_info, "3 pass color\n"); - - if (!xsane.scanner_gamma_color) /* gamma correction by xsane */ - { - char val; - SANE_Int *gamma; - - if (xsane.param.format == SANE_FRAME_RED) - { - gamma = xsane.gamma_data_red; - } - else if (xsane.param.format == SANE_FRAME_GREEN) - { - gamma = xsane.gamma_data_green; - } - else - { - gamma = xsane.gamma_data_blue; - } - - for (i = 0; i < len; ++i) - { - val = gamma[(int) buf8[i]]; - fputc(val, xsane.out); - fseek(xsane.out, 2, SEEK_CUR); - } - } - else /* gamma correction by scanner */ - { - for (i = 0; i < len; ++i) - { - fputc(buf8[i], xsane.out); - fseek(xsane.out, 2, SEEK_CUR); - } - } - } - break; - + switch (xsane.param.format) { + case SANE_FRAME_GRAY: + DBG(DBG_info, "grayscale\n"); + switch (xsane.param.depth) { + case 1: + if ( xsane.expand_lineart_to_grayscale ) { + for (i = 0; i < len; i++) { + for ( j = 0; j < 8; j++) { + scan_buf_8_ex[i*8+j] = (scan_buf_8[i] & (1<<(8-j-1))) ? 0x00 : 0xff; + /* XXXXX if(x <= 0){x=xsane.param.pixels_per_line;break;} */ + } + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8_ex, 1, len*8, xsane.out); +#else + buf_to_mmap(scan_buf_8_ex, len * 8, 1, 1); +#endif + } else { +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len, xsane.out); +#else + for (i = 0; i < len * 8; i++) { + xsane.out_mmap[xsane.mmap_pos++] = scan_buf_8[i]; + } +#endif + } + break; + case 8: + if (!xsane.scanner_gamma_gray) { + for (i = 0; i < len; i++) { + scan_buf_8[i] = xsane.gamma_data[scan_buf_8[i]]; + } + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len, xsane.out); +#else + buf_to_mmap(scan_buf_8, len, 1, 1); +#endif + break; + case 16: + if (xsane.reduce_16bit_to_8bit) { + for (i = 0; i < len/2; i++) { + if (xsane.scanner_gamma_gray) { + scan_buf_8[i] = scan_buf_16[i] >> 8; + } else { + scan_buf_8[i] = xsane.gamma_data[scan_buf_16[i]] >> 8; + } + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len/2, xsane.out); +#else + buf_to_mmap(scan_buf_8, len/2, 1, 1); +#endif + } else { + if (!xsane.scanner_gamma_gray) { + for (i = 0; i < len/2; ++i) { + scan_buf_16[i] = xsane.gamma_data[scan_buf_16[i]]; + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len, xsane.out); +#else + buf_to_mmap(scan_buf_8, len, 1, 2); +#endif + } + } + break; + default: + + } + break; + case SANE_FRAME_RGB: #ifdef SUPPORT_RGBA - case SANE_FRAME_RGBA: /* Scanning including Infrared channel */ - { - int i; - char val; - - DBG(DBG_info, "1 pass color+alpha (RGBA)\n"); - - if (!xsane.scanner_gamma_color) /* gamma correction by xsane */ - { - buf8ptr = buf8; - - for (i=0; i < len; ++i) - { - if (xsane.pixelcolor == 0) - { - *buf8ptr = xsane.gamma_data_red[(int) (*buf8ptr)]; - buf8ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 1) - { - *buf8ptr = xsane.gamma_data_green[(int) (*buf8ptr)]; - buf8ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 2) - { - *buf8ptr = xsane.gamma_data_blue[(int) (*buf8ptr)]; - buf8ptr++; - xsane.pixelcolor++; - } - else - { - /* no gamma table for infrared channel */ - buf8ptr++; - xsane.pixelcolor = 0; - } - } - - fwrite(buf8, 1, len, xsane.out); - } - else /* gamma correction has been done by scanner */ - { - fwrite(buf8, 1, len, xsane.out); - } - } - break; + case SANE_FRAME_RGBA: #endif - - default: - xsane_scan_done(-1); /* -1 = error */ - DBG(DBG_error, "xsane_read_image_data: %s %d\n", ERR_BAD_FRAME_FORMAT, xsane.param.format); - return; - break; - } - } - } - else if ( xsane.param.depth == 16 ) - { - guint16 buf16[32768]; - guint16 *buf16ptr; - unsigned char *buf8 = (unsigned char *) buf16; - unsigned char *buf8ptr; - char buf[255]; - - DBG(DBG_info, "depth = 16 bit\n"); - - while (1) - { - if (xsane.cancel_scan) - { - break; /* leave while loop */ - } - - if (xsane.read_offset_16) /* if we have had an odd number of bytes */ - { - buf8[0] = xsane.last_offset_16_byte; - status = sane_read(dev, ((SANE_Byte *) buf16) + 1, sizeof(buf16) - 1, &len); - if (len) - { - len++; - } - } - else /* last read we had an even number of bytes */ - { - status = sane_read(dev, (SANE_Byte *) buf16, sizeof(buf16), &len); - } - - - if (!xsane.scanning) /* scan may have been canceled while sane_read was executed */ - { - return; /* ok, the scan has been canceled */ - } - - - if (len % 2) /* odd number of bytes */ - { - len--; - xsane.last_offset_16_byte = buf16[len]; - xsane.read_offset_16 = 1; - } - else /* even number of bytes */ - { - xsane.read_offset_16 = 0; - } - - if (status == SANE_STATUS_EOF) - { - if (!xsane.param.last_frame) - { - DBG(DBG_info, "not last frame\n"); - if (xsane.input_tag >= 0) - { - gdk_input_remove(xsane.input_tag); - xsane.input_tag = -1; - } - xsane_start_scan(); - break; /* leave while loop */ - } - - xsane_scan_done(SANE_STATUS_EOF); /* image complete, stop scanning */ - return; - } - - if (status == SANE_STATUS_CANCELLED) - { - xsane_scan_done(status); /* status = return of sane_read */ - snprintf(buf, sizeof(buf), "%s.", XSANE_STRSTATUS(status)); - xsane_back_gtk_warning(buf, TRUE); - return; - } - - if (status != SANE_STATUS_GOOD) - { - xsane_scan_done(status); /* status = return of sane_read */ - snprintf(buf, sizeof(buf), "%s %s.", ERR_DURING_READ, XSANE_STRSTATUS(status)); - xsane_back_gtk_error(buf, TRUE); - return; - } - - if (!len) /* nothing read */ - { - break; /* out of data for now, leave while loop */ - } - - xsane.bytes_read += len; - xsane_progress_update(xsane.bytes_read / (gfloat) xsane.num_bytes); - - if (xsane.input_tag < 0) - { - while (gtk_events_pending()) - { - gtk_main_iteration(); - } - } - - switch (xsane.param.format) - { - case SANE_FRAME_GRAY: - { - int i; - - if (xsane.reduce_16bit_to_8bit) /* reduce 16 bit image to 8 bit */ - { - DBG(DBG_info, "reducing 16 bit image to 8 bit\n"); - - if (!xsane.scanner_gamma_gray) /* gamma correction by xsane */ - { - buf8ptr = buf8; - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - *buf8ptr = (xsane.gamma_data[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - } - - fwrite(buf8, 1, len/2, xsane.out); - } - else /* gamma correction by scanner */ - { - buf8ptr = buf8; - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - *buf8ptr = (*buf16ptr) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - } - - fwrite(buf8, 1, len/2, xsane.out); - } - } - else /* save as 16 bit image */ - { - if (!xsane.scanner_gamma_gray) /* gamma correction by xsane */ - { - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - *buf16ptr = xsane.gamma_data[(*buf16ptr)]; - buf16ptr++; - } - fwrite(buf16, 2, len/2, xsane.out); - } - else /* gamma correction by scanner */ - { - fwrite(buf16, 2, len/2, xsane.out); - } - } - } - break; - - case SANE_FRAME_RGB: - { - int i; - - if (xsane.reduce_16bit_to_8bit) /* reduce 16 bit image to 8 bit */ - { - DBG(DBG_info, "reducing 16 bit image to 8 bit\n"); - - if (!xsane.scanner_gamma_color) /* gamma correction by xsane */ - { - buf8ptr = buf8; - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - if (xsane.pixelcolor == 0) - { - *buf8ptr = (xsane.gamma_data_red[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 1) - { - *buf8ptr = (xsane.gamma_data_green[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor++; - } - else - { - *buf8ptr = (xsane.gamma_data_blue[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor = 0; - } - } - fwrite(buf8, 1, len/2, xsane.out); - } - else /* gamma correction by scanner */ - { - buf8ptr = buf8; - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - *buf8ptr = (*buf16ptr) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor++; - } - fwrite(buf8, 1, len/2, xsane.out); - } - } - else /* save as 16 bit image */ - { - if (!xsane.scanner_gamma_color) /* gamma correction by xsane */ - { - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - if (xsane.pixelcolor == 0) - { - *buf16ptr = xsane.gamma_data_red[(*buf16ptr)]; - buf16ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 1) - { - *buf16ptr = xsane.gamma_data_green[(*buf16ptr)]; - buf16ptr++; - xsane.pixelcolor++; - } - else - { - *buf16ptr = xsane.gamma_data_blue[(*buf16ptr)]; - buf16ptr++; - xsane.pixelcolor = 0; - } - } - fwrite(buf16, 2, len/2, xsane.out); - } - else /* gamma correction by scanner */ - { - fwrite(buf16, 2, len/2, xsane.out); - } - } - } - break; - - case SANE_FRAME_RED: - case SANE_FRAME_GREEN: - case SANE_FRAME_BLUE: - /* this is incomplete: - - missing: gamma correction by xsane - - missing: reduction to 8 bit - but I do not think there are 3 pass scanners with more - than 24 bits/pixel */ - { - for (i = 0; i < len/2; ++i) - { - fwrite(buf16 + i*2, 2, 1, xsane.out); - fseek(xsane.out, 4, SEEK_CUR); - } - } - break; - + switch (xsane.param.depth) { + case 8: + if (!xsane.scanner_gamma_color) { + for (i = 0; i < len; i++) { + switch(xsane.pixelcolor) { + case 0: + scan_buf_8[i] = xsane.gamma_data_red[scan_buf_8[i]]; + xsane.pixelcolor++; + break; + case 1: + scan_buf_8[i] = xsane.gamma_data_green[scan_buf_8[i]]; + xsane.pixelcolor++; + break; + case 2: + scan_buf_8[i] = xsane.gamma_data_blue[scan_buf_8[i]]; #ifdef SUPPORT_RGBA - case SANE_FRAME_RGBA: - { - int i; - guint16 val; - - if (xsane.reduce_16bit_to_8bit) /* reduce 16 bit image to 8 bit */ - { - DBG(DBG_info, "reducing 16 bit image to 8 bit\n"); - - if (!xsane.scanner_gamma_color) - { - buf8ptr = buf8; - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - if (xsane.pixelcolor == 0) - { - *buf8ptr = (xsane.gamma_data_red[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 1) - { - *buf8ptr = (xsane.gamma_data_green[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 2) - { - *buf8ptr = (xsane.gamma_data_blue[(*buf16ptr)]) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor++; - } - else - { - /* no gamma table for infrared channel */ - *buf8ptr = (*buf16ptr) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - xsane.pixelcolor = 0; - } - } - - fwrite(buf8, 1, len, xsane.out); - } - else /* gamma correction done by scanner */ - { - buf8ptr = buf8; - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - *buf8ptr = (*buf16ptr) >> 8; /* reduce to 8 bit */ - buf8ptr++; - buf16ptr++; - } - - fwrite(buf8, 1, len, xsane.out); - } - } - else /* save as 16 bit image */ - { - if (!xsane.scanner_gamma_color) - { - buf16ptr = buf16; - - for (i=0; i < len/2; ++i) - { - if (xsane.pixelcolor == 0) - { - *buf16ptr = xsane.gamma_data_red[(*buf16ptr)]; - buf16ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 1) - { - *buf16ptr = xsane.gamma_data_green[(*buf16ptr)]; - buf16ptr++; - xsane.pixelcolor++; - } - else if (xsane.pixelcolor == 2) - { - *buf16ptr = xsane.gamma_data_blue[(*buf16ptr)]; - buf16ptr++; - xsane.pixelcolor++; - } - else - { - /* no gamma table for infrared channel */ - buf16ptr++; - xsane.pixelcolor = 0; - } - } - - fwrite(buf16, 2, len/2, xsane.out); - } - else /* gamma correction done by scanner */ - { - fwrite(buf16, 2, len/2, xsane.out); - } - } - } - break; + if (xsane.param.format == SANE_FRAME_RGBA) { + xsane.pixelcolor++; + } else { #endif - - default: - xsane_scan_done(-1); /* -1 = error */ - DBG(DBG_error, "xsane_read_image_data: %s %d\n", ERR_BAD_FRAME_FORMAT, xsane.param.format); - return; - break; - } - } - } - else - { - xsane_scan_done(-1); /* -1 = error */ - snprintf(buf, sizeof(buf), "%s %d.", ERR_BAD_DEPTH, xsane.param.depth); - xsane_back_gtk_error(buf, TRUE); - return; + xsane.pixelcolor = 0; +#ifdef SUPPORT_RGBA + } + break; + case 3: + /* no gamma table for infrared channel */ + scan_buf_8[i] = scan_buf_8[i]; + xsane.pixelcolor = 0; + break; +#endif + default: + } + } + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len, xsane.out); +#else +#ifdef SUPPORT_RGBA + if (xsane.param.format == SANE_FRAME_RGBA) { + buf_to_mmap(scan_buf_8, len, 4, 1); + } else { +#endif + buf_to_mmap(scan_buf_8, len, 3, 1); +#ifdef SUPPORT_RGBA + } +#endif +#endif + break; + case 16: + if (xsane.reduce_16bit_to_8bit) { + if (!xsane.scanner_gamma_color) { + for (i = 0; i < len/2; i++) { + switch(xsane.pixelcolor) { + case 0: + scan_buf_8[i] = xsane.gamma_data_red[scan_buf_16[i]] >> 8; + xsane.pixelcolor++; + break; + case 1: + scan_buf_8[i] = xsane.gamma_data_green[scan_buf_16[i]] >> 8; + xsane.pixelcolor++; + break; + case 2: + scan_buf_8[i] = xsane.gamma_data_blue[scan_buf_16[i]] >> 8; +#ifdef SUPPORT_RGBA + if (xsane.param.format == SANE_FRAME_RGBA) { + xsane.pixelcolor++; + } else { +#endif + xsane.pixelcolor = 0; +#ifdef SUPPORT_RGBA + } + break; + case 3: + /* no gamma table for infrared channel */ + scan_buf_8[i] = scan_buf_16[i] >> 8; + xsane.pixelcolor = 0; + break; +#endif + default: + } + } + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len/2, xsane.out); +#else +#ifdef SUPPORT_RGBA + if (xsane.param.format == SANE_FRAME_RGBA) { + buf_to_mmap(scan_buf_8, len/2, 4, 1); + } else { +#endif + buf_to_mmap(scan_buf_8, len/2, 3, 1); +#ifdef SUPPORT_RGBA + } +#endif +#endif + } else { + if (!xsane.scanner_gamma_color) { + for (i = 0; i < len/2; i++) { + switch(xsane.pixelcolor) { + case 0: + scan_buf_16[i] = xsane.gamma_data_red[scan_buf_16[i]]; + xsane.pixelcolor++; + break; + case 1: + scan_buf_16[i] = xsane.gamma_data_green[scan_buf_16[i]]; + xsane.pixelcolor++; + break; + case 2: + scan_buf_16[i] = xsane.gamma_data_blue[scan_buf_16[i]]; +#ifdef SUPPORT_RGBA + if (xsane.param.format == SANE_FRAME_RGBA) { + xsane.pixelcolor++; + } else { +#endif + xsane.pixelcolor = 0; +#ifdef SUPPORT_RGBA + } + break; + case 3: + /* no gamma table for infrared channel */ + scan_buf_16[i] = scan_buf_16[i]; + xsane.pixelcolor = 0; + break; +#endif + default: + } + } + } +#ifndef HAVE_MMAP + fwrite(scan_buf_8, 1, len, xsane.out); +#else +#ifdef SUPPORT_RGBA + if (xsane.param.format == SANE_FRAME_RGBA) { + buf_to_mmap(scan_buf_8, len, 4, 2); + } else { +#endif + buf_to_mmap(scan_buf_8, len, 3, 2); +#ifdef SUPPORT_RGBA + } +#endif +#endif + } + break; + default: + + } + break; + case SANE_FRAME_RED: + case SANE_FRAME_GREEN: + case SANE_FRAME_BLUE: + switch (xsane.param.depth) { + case 8: + for (i = 0; i < len; ++i) { + if (!xsane.scanner_gamma_color) { + switch (xsane.param.format) { + case SANE_FRAME_RED: + scan_buf_8[i] = xsane.gamma_data_red[scan_buf_8[i]]; + break; + case SANE_FRAME_GREEN: + scan_buf_8[i] = xsane.gamma_data_green[scan_buf_8[i]]; + break; + case SANE_FRAME_BLUE: + scan_buf_8[i] = xsane.gamma_data_red[scan_buf_8[i]]; + break; + default: + } + } +#ifndef HAVE_MMAP + fputc(scan_buf_8[i], xsane.out); + fseek(xsane.out, 2, SEEK_CUR); +#else + buf_to_mmap(scan_buf_8, 1, 3, 1); + xsane.mmap_pos += 2; +#endif + } + break; + case 16: + for (i = 0; i < len/2; ++i) { +#ifndef HAVE_MMAP + fwrite(&scan_buf_16[i], 2, 1, xsane.out); + fseek(xsane.out, 4, SEEK_CUR); +#else + buf_to_mmap(scan_buf_8, 1, 3, 2); + xsane.mmap_pos += 4; +#endif + } + break; + default: + } + break; + default: + xsane_scan_done(-1); /* -1 = error */ + DBG(DBG_error, "xsane_read_image_data: %s %d\n", ERR_BAD_FRAME_FORMAT, xsane.param.format); + return; + } } - - if (xsane.cancel_scan) - { + + if (xsane.cancel_scan) { xsane.cancel_scan = FALSE; /* make sure we do not get an infinite loop */ xsane_read_image_data(0, -1, GDK_INPUT_READ); } - + + if (scan_buf_8_ex != NULL) { + free(scan_buf_8_ex); + } + xsane.reading_data = FALSE; - - return; + + return; } /* ---------------------------------------------------------------------------------------------------------------------- */ @@ -986,14 +762,37 @@ { DBG(DBG_info, "correcting image height to %d lines\n", pixel_height); xsane.param.lines = pixel_height; - +#ifndef HAVE_MMAP image_info.image_width = xsane.param.pixels_per_line; - image_info.image_height = pixel_height; - image_info.depth = xsane.depth; - image_info.colors = xsane.xsane_colors; - + image_info.image_height = xsane.param.lines; image_info.resolution_x = xsane.resolution_x; image_info.resolution_y = xsane.resolution_y; +#else + switch(xsane.preview->rotation) { + case ROTATE_0_DEGREE: + case ROTATE_180_DEGREE: + case ROTATE_0_DEGREE_X_MIRROR: + case ROTOATE_180_DEGREE_X_MIRROR: + image_info.image_width = xsane.param.pixels_per_line; + image_info.image_height = xsane.param.lines; + image_info.resolution_x = xsane.resolution_x; + image_info.resolution_y = xsane.resolution_y; + break; + case ROTATE_90_DEGREE: + case ROTATE_270_DEGREE: + case ROTATE_90_DEGREE_X_MIRROR: + case ROTATE_270_DEGREE_X_MIRROR: + image_info.image_width = xsane.param.lines; + image_info.image_height = xsane.param.pixels_per_line; + image_info.resolution_x = xsane.resolution_y; + image_info.resolution_y = xsane.resolution_x; + break; + default: + } +#endif + + image_info.depth = xsane.depth; + image_info.colors = xsane.xsane_colors; image_info.gamma = xsane.gamma; image_info.gamma_red = xsane.gamma_red; @@ -1018,15 +817,22 @@ DBG(DBG_info, "closing output file\n"); + fflush(xsane.out); fclose(xsane.out); +#ifdef HAVE_MMAP + if ( xsane.out_mmap != MAP_FAILED ) { + munmap(xsane.out_mmap, xsane.out_mmap_length); + } +#endif xsane.out = 0; } if ( (status == SANE_STATUS_GOOD) || (status == SANE_STATUS_EOF) ) /* no error, do conversion etc. */ { +#ifndef HAVE_MMAP /* do we have to rotate the image ? */ - if (xsane.preview->rotation) + if (xsane.preview->rotation != ROTATE_0_DEGREE) { char *old_dummy_filename; int abort = 0; @@ -1112,6 +918,7 @@ return; } } +#endif if (xsane.xsane_mode == XSANE_VIEWER) { @@ -1579,7 +1386,8 @@ char buf[256]; int fd; Image_info image_info; - + size_t data_size; + DBG(DBG_proc, "xsane_start_scan\n"); while (gtk_events_pending()) @@ -1665,7 +1473,7 @@ } } - xsane.out = fopen(xsane.dummy_filename, "wb"); /* b = binary mode for win32 */ + xsane.out = fopen(xsane.dummy_filename, "w+b"); /* b = binary mode for win32 */ if (!xsane.out) /* error while opening the dummy_file for writing */ { @@ -1680,14 +1488,37 @@ { xsane.depth = 8; } - +#ifndef HAVE_MMAP image_info.image_width = xsane.param.pixels_per_line; image_info.image_height = xsane.param.lines; - image_info.depth = xsane.depth; - image_info.colors = xsane.xsane_colors; - image_info.resolution_x = xsane.resolution_x; image_info.resolution_y = xsane.resolution_y; +#else + switch(xsane.preview->rotation) { + case ROTATE_0_DEGREE: + case ROTATE_180_DEGREE: + case ROTATE_0_DEGREE_X_MIRROR: + case ROTOATE_180_DEGREE_X_MIRROR: + image_info.image_width = xsane.param.pixels_per_line; + image_info.image_height = xsane.param.lines; + image_info.resolution_x = xsane.resolution_x; + image_info.resolution_y = xsane.resolution_y; + break; + case ROTATE_90_DEGREE: + case ROTATE_270_DEGREE: + case ROTATE_90_DEGREE_X_MIRROR: + case ROTATE_270_DEGREE_X_MIRROR: + image_info.image_width = xsane.param.lines; + image_info.image_height = xsane.param.pixels_per_line; + image_info.resolution_x = xsane.resolution_y; + image_info.resolution_y = xsane.resolution_x; + break; + default: + } +#endif + + image_info.depth = xsane.depth; + image_info.colors = xsane.xsane_colors; image_info.gamma = xsane.gamma; image_info.gamma_red = xsane.gamma_red; @@ -1710,12 +1541,34 @@ fflush(xsane.out); xsane.header_size = ftell(xsane.out); /* store header size for 3 pass scan */ +#ifdef HAVE_MMAP + /* additional mmap the output file */ + data_size = image_info.image_width * image_info.image_height * image_info.depth * image_info.colors / 8; + xsane.out_mmap_length = xsane.header_size + data_size; + fseek(xsane.out, xsane.header_size + data_size -1, SEEK_SET); + fwrite("", 1, 1, xsane.out); + fflush(xsane.out); + fseek(xsane.out, xsane.header_size, SEEK_SET); + if ((xsane.out_mmap = mmap(NULL, xsane.header_size + data_size, PROT_WRITE, MAP_SHARED, fileno(xsane.out), 0)) == MAP_FAILED) { + fprintf(stderr, "mmap failed (%s)\n", strerror(errno)); + xsane_scan_done(-1); /* -1 = error */ + DBG(DBG_info, "mmap of file `%s'failed : %s\n", xsane.dummy_filename, strerror(errno)); + snprintf(buf, sizeof(buf), "%s `%s': %s", ERR_OPEN_FAILED, xsane.dummy_filename, strerror(errno)); + xsane_back_gtk_error(buf, TRUE); + return; + } + xsane.mmap_pos = xsane.header_size; +#endif } if (xsane.param.format >= SANE_FRAME_RED && xsane.param.format <= SANE_FRAME_BLUE) { -/* correct this using read_pnm_header */ +#ifndef HAVE_MMAP + /* correct this using read_pnm_header */ fseek(xsane.out, xsane.header_size + xsane.param.format - SANE_FRAME_RED, SEEK_SET); +#else + xsane.mmap_pos = xsane.header_size + xsane.param.format - SANE_FRAME_RED; +#endif } xsane.pixelcolor = 0; Index: xsane/src/xsane.h diff -u xsane/src/xsane.h:1.1.1.1 xsane/src/xsane.h:1.1.1.1.6.1 --- xsane/src/xsane.h:1.1.1.1 Mon Apr 22 18:38:41 2002 +++ xsane/src/xsane.h Wed Jul 3 10:17:39 2002 @@ -551,9 +551,12 @@ /* saving and transformation values: */ FILE *out; + unsigned char *out_mmap; + size_t out_mmap_length; int xsane_mode; int xsane_output_format; long header_size; + long mmap_pos; int expand_lineart_to_grayscale; int reduce_16bit_to_8bit;