kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			Merge branch 'genesys-remove-image-enhancement' into 'master'
genesys: Remove image enhancement functionality See merge request sane-project/backends!460merge-requests/463/merge
						commit
						3cd0914f67
					
				|  | @ -578,7 +578,10 @@ libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys | |||
| nodist_libsane_genesys_la_SOURCES = genesys-s.cpp | ||||
| libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys | ||||
| libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) | ||||
| libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la  ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) | ||||
| libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la \
 | ||||
|     ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
 | ||||
|     ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo \
 | ||||
|     $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) | ||||
| EXTRA_DIST += genesys.conf.in | ||||
| 
 | ||||
| libgphoto2_i_la_SOURCES = gphoto2.c gphoto2.h | ||||
|  |  | |||
|  | @ -45,7 +45,6 @@ | |||
| #define DEBUG_DECLARE_ONLY | ||||
| 
 | ||||
| #include "conv.h" | ||||
| #include "sane/sanei_magic.h" | ||||
| 
 | ||||
| namespace genesys { | ||||
| 
 | ||||
|  | @ -155,82 +154,4 @@ void genesys_gray_lineart(Genesys_Device* dev, | |||
|     } | ||||
| } | ||||
| 
 | ||||
| /** Look in image for likely left/right/bottom paper edges, then crop image.
 | ||||
|  */ | ||||
| void genesys_crop(Genesys_Scanner* s) | ||||
| { | ||||
|     DBG_HELPER(dbg); | ||||
|   Genesys_Device *dev = s->dev; | ||||
|   int top = 0; | ||||
|   int bottom = 0; | ||||
|   int left = 0; | ||||
|   int right = 0; | ||||
| 
 | ||||
|     // first find edges if any
 | ||||
|     TIE(sanei_magic_findEdges(&s->params, dev->img_buffer.data(), | ||||
|                               dev->settings.xres, dev->settings.yres, | ||||
|                               &top, &bottom, &left, &right)); | ||||
| 
 | ||||
|   DBG (DBG_io, "%s: t:%d b:%d l:%d r:%d\n", __func__, top, bottom, left, | ||||
|        right); | ||||
| 
 | ||||
|     // now crop the image
 | ||||
|     TIE(sanei_magic_crop (&(s->params), dev->img_buffer.data(), top, bottom, left, right)); | ||||
| 
 | ||||
|   /* update counters to new image size */ | ||||
|   dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines; | ||||
| } | ||||
| 
 | ||||
| /** Look in image for likely upper and left paper edges, then rotate
 | ||||
|  * image so that upper left corner of paper is upper left of image. | ||||
|  */ | ||||
| void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor) | ||||
| { | ||||
|     DBG_HELPER(dbg); | ||||
|   Genesys_Device *dev = s->dev; | ||||
| 
 | ||||
|   int x = 0, y = 0, bg; | ||||
|   double slope = 0; | ||||
| 
 | ||||
|   bg=0; | ||||
|   if(s->params.format==SANE_FRAME_GRAY && s->params.depth == 1) | ||||
|     { | ||||
|       bg=0xff; | ||||
|     } | ||||
|     TIE(sanei_magic_findSkew(&s->params, dev->img_buffer.data(), | ||||
|                              sensor.full_resolution, sensor.full_resolution, | ||||
|                              &x, &y, &slope)); | ||||
| 
 | ||||
|     DBG(DBG_info, "%s: slope=%f => %f\n", __func__, slope, slope * 180 / M_PI); | ||||
| 
 | ||||
|     // rotate image slope is in [-PI/2,PI/2]. Positive values rotate trigonometric direction wise
 | ||||
|     TIE(sanei_magic_rotate(&s->params, dev->img_buffer.data(), | ||||
|                            x, y, slope, bg)); | ||||
| } | ||||
| 
 | ||||
| /** remove lone dots
 | ||||
|  */ | ||||
| void genesys_despeck(Genesys_Scanner* s) | ||||
| { | ||||
|     DBG_HELPER(dbg); | ||||
|     TIE(sanei_magic_despeck(&s->params, s->dev->img_buffer.data(), s->despeck)); | ||||
| } | ||||
| 
 | ||||
| /** Look if image needs rotation and apply it
 | ||||
|  * */ | ||||
| void genesys_derotate(Genesys_Scanner* s) | ||||
| { | ||||
|     DBG_HELPER(dbg); | ||||
|   int angle = 0; | ||||
| 
 | ||||
|     TIE(sanei_magic_findTurn(&s->params, s->dev->img_buffer.data(), | ||||
|                              s->resolution, s->resolution, &angle)); | ||||
| 
 | ||||
|     // apply rotation angle found
 | ||||
|     TIE(sanei_magic_turn(&s->params, s->dev->img_buffer.data(), angle)); | ||||
| 
 | ||||
|     // update counters to new image size
 | ||||
|     s->dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines; | ||||
| } | ||||
| 
 | ||||
| } // namespace genesys
 | ||||
|  |  | |||
|  | @ -56,14 +56,6 @@ void genesys_gray_lineart(Genesys_Device* dev, | |||
|                           std::uint8_t* src_data, std::uint8_t* dst_data, | ||||
|                           std::size_t pixels, size_t lines, std::uint8_t threshold); | ||||
| 
 | ||||
| void genesys_crop(Genesys_Scanner* s); | ||||
| 
 | ||||
| void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor); | ||||
| 
 | ||||
| void genesys_despeck(Genesys_Scanner* s); | ||||
| 
 | ||||
| void genesys_derotate(Genesys_Scanner* s); | ||||
| 
 | ||||
| } // namespace genesys
 | ||||
| 
 | ||||
| #endif // BACKEND_GENESYS_CONV_H
 | ||||
|  |  | |||
|  | @ -270,7 +270,6 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev) | |||
|         << "    line_count: " << dev.line_count << '\n' | ||||
|         << "    segment_order: " | ||||
|         << format_indent_braced_list(4, format_vector_unsigned(4, dev.segment_order)) << '\n' | ||||
|         << "    buffer_image: " << dev.buffer_image << '\n' | ||||
|         << "    img_buffer.size(): " << dev.img_buffer.size() << '\n' | ||||
|         << '}'; | ||||
|     return out; | ||||
|  |  | |||
|  | @ -353,9 +353,6 @@ struct Genesys_Device | |||
|     // an buffer that allows reading from `pipeline` in chunks of any size
 | ||||
|     ImageBuffer pipeline_buffer; | ||||
| 
 | ||||
|     // when true the scanned picture is first buffered to allow software image enhancements
 | ||||
|     bool buffer_image = false; | ||||
| 
 | ||||
|     // image buffer where the scanned picture is stored
 | ||||
|     std::vector<std::uint8_t> img_buffer; | ||||
| 
 | ||||
|  |  | |||
|  | @ -74,7 +74,6 @@ | |||
| #include "test_scanner_interface.h" | ||||
| #include "test_settings.h" | ||||
| #include "../include/sane/sanei_config.h" | ||||
| #include "../include/sane/sanei_magic.h" | ||||
| 
 | ||||
| #include <array> | ||||
| #include <cmath> | ||||
|  | @ -132,12 +131,6 @@ static SANE_String_Const cis_color_filter_list[] = { | |||
|     nullptr | ||||
| }; | ||||
| 
 | ||||
| static SANE_Range swdespeck_range = { | ||||
|   1, | ||||
|   9, | ||||
|   1 | ||||
| }; | ||||
| 
 | ||||
| static SANE_Range time_range = { | ||||
|   0,				/* minimum */ | ||||
|   60,				/* maximum */ | ||||
|  | @ -4449,20 +4442,6 @@ static void calc_parameters(Genesys_Scanner* s) | |||
|     // threshold curve for dynamic rasterization
 | ||||
|     s->dev->settings.threshold_curve = s->threshold_curve; | ||||
| 
 | ||||
|   /* some digital processing requires the whole picture to be buffered */ | ||||
|   /* no digital processing takes place when doing preview, or when bit depth is
 | ||||
|    * higher than 8 bits */ | ||||
|     if ((s->swdespeck || s->swcrop || s->swdeskew || s->swderotate ||(fixed_to_float(s->swskip)>0)) | ||||
|         && (!s->preview) | ||||
|         && (s->bit_depth <= 8)) | ||||
|     { | ||||
|         s->dev->buffer_image = true; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|         s->dev->buffer_image = false; | ||||
|     } | ||||
| 
 | ||||
|   /* brigthness and contrast only for for 8 bit scans */ | ||||
|   if(s->bit_depth <= 8) | ||||
|     { | ||||
|  | @ -4853,61 +4832,6 @@ static void init_options(Genesys_Scanner* s) | |||
|    * memory than used by the full scanned image and may fail at high | ||||
|    * resolution | ||||
|    */ | ||||
|   /* software deskew */ | ||||
|   s->opt[OPT_SWDESKEW].name = "swdeskew"; | ||||
|   s->opt[OPT_SWDESKEW].title = "Software deskew"; | ||||
|   s->opt[OPT_SWDESKEW].desc = "Request backend to rotate skewed pages digitally"; | ||||
|   s->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL; | ||||
|   s->opt[OPT_SWDESKEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; | ||||
|   s->swdeskew = false; | ||||
| 
 | ||||
|   /* software deskew */ | ||||
|   s->opt[OPT_SWDESPECK].name = "swdespeck"; | ||||
|   s->opt[OPT_SWDESPECK].title = "Software despeck"; | ||||
|   s->opt[OPT_SWDESPECK].desc = "Request backend to remove lone dots digitally"; | ||||
|   s->opt[OPT_SWDESPECK].type = SANE_TYPE_BOOL; | ||||
|   s->opt[OPT_SWDESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; | ||||
|   s->swdespeck = false; | ||||
| 
 | ||||
|   /* software despeckle radius */ | ||||
|   s->opt[OPT_DESPECK].name = "despeck"; | ||||
|   s->opt[OPT_DESPECK].title = "Software despeckle diameter"; | ||||
|   s->opt[OPT_DESPECK].desc = "Maximum diameter of lone dots to remove from scan"; | ||||
|   s->opt[OPT_DESPECK].type = SANE_TYPE_INT; | ||||
|   s->opt[OPT_DESPECK].unit = SANE_UNIT_NONE; | ||||
|   s->opt[OPT_DESPECK].constraint_type = SANE_CONSTRAINT_RANGE; | ||||
|   s->opt[OPT_DESPECK].constraint.range = &swdespeck_range; | ||||
|   s->opt[OPT_DESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_INACTIVE; | ||||
|   s->despeck = 1; | ||||
| 
 | ||||
|   /* crop by software */ | ||||
|   s->opt[OPT_SWCROP].name = "swcrop"; | ||||
|   s->opt[OPT_SWCROP].title = SANE_I18N ("Software crop"); | ||||
|   s->opt[OPT_SWCROP].desc = SANE_I18N ("Request backend to remove border from pages digitally"); | ||||
|   s->opt[OPT_SWCROP].type = SANE_TYPE_BOOL; | ||||
|   s->opt[OPT_SWCROP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; | ||||
|   s->opt[OPT_SWCROP].unit = SANE_UNIT_NONE; | ||||
|   s->swcrop = false; | ||||
| 
 | ||||
|   /* Software blank page skip */ | ||||
|   s->opt[OPT_SWSKIP].name = "swskip"; | ||||
|   s->opt[OPT_SWSKIP].title = SANE_I18N ("Software blank skip percentage"); | ||||
|   s->opt[OPT_SWSKIP].desc = SANE_I18N("Request driver to discard pages with low numbers of dark pixels"); | ||||
|   s->opt[OPT_SWSKIP].type = SANE_TYPE_FIXED; | ||||
|   s->opt[OPT_SWSKIP].unit = SANE_UNIT_PERCENT; | ||||
|   s->opt[OPT_SWSKIP].constraint_type = SANE_CONSTRAINT_RANGE; | ||||
|   s->opt[OPT_SWSKIP].constraint.range = &(percentage_range); | ||||
|   s->opt[OPT_SWSKIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; | ||||
|   s->swskip = 0;    // disable by default
 | ||||
| 
 | ||||
|   /* Software Derotate */ | ||||
|   s->opt[OPT_SWDEROTATE].name = "swderotate"; | ||||
|   s->opt[OPT_SWDEROTATE].title = SANE_I18N ("Software derotate"); | ||||
|   s->opt[OPT_SWDEROTATE].desc = SANE_I18N("Request driver to detect and correct 90 degree image rotation"); | ||||
|   s->opt[OPT_SWDEROTATE].type = SANE_TYPE_BOOL; | ||||
|   s->opt[OPT_SWDEROTATE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; | ||||
|   s->opt[OPT_SWDEROTATE].unit = SANE_UNIT_NONE; | ||||
|   s->swderotate = false; | ||||
| 
 | ||||
|   /* Software brightness */ | ||||
|   s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; | ||||
|  | @ -5446,114 +5370,6 @@ static void write_calibration(Genesys_Device::Calibration& calibration, const st | |||
|     write_calibration(str, calibration); | ||||
| } | ||||
| 
 | ||||
| /** @brief buffer scanned picture
 | ||||
|  * In order to allow digital processing, we must be able to put all the | ||||
|  * scanned picture in a buffer. | ||||
|  */ | ||||
| static void genesys_buffer_image(Genesys_Scanner *s) | ||||
| { | ||||
|     DBG_HELPER(dbg); | ||||
|   size_t maximum;     /**> maximum bytes size of the scan */ | ||||
|   size_t len;	      /**> length of scanned data read */ | ||||
|   size_t total;	      /**> total of butes read */ | ||||
|   size_t size;	      /**> size of image buffer */ | ||||
|   size_t read_size;   /**> size of reads */ | ||||
|   int lines;	      /** number of lines of the scan */ | ||||
|   Genesys_Device *dev = s->dev; | ||||
| 
 | ||||
|   /* compute maximum number of lines for the scan */ | ||||
|   if (s->params.lines > 0) | ||||
|     { | ||||
|       lines = s->params.lines; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|         lines = static_cast<int>((dev->model->y_size * dev->settings.yres) / MM_PER_INCH); | ||||
|     } | ||||
|   DBG(DBG_info, "%s: buffering %d lines of %d bytes\n", __func__, lines, | ||||
|       s->params.bytes_per_line); | ||||
| 
 | ||||
|   /* maximum bytes to read */ | ||||
|   maximum = s->params.bytes_per_line * lines; | ||||
|     if (s->dev->settings.scan_mode == ScanColorMode::LINEART) { | ||||
|       maximum *= 8; | ||||
|     } | ||||
| 
 | ||||
|   /* initial size of the read buffer */ | ||||
|   size = | ||||
|     ((2048 * 2048) / s->params.bytes_per_line) * s->params.bytes_per_line; | ||||
| 
 | ||||
|   /* read size */ | ||||
|   read_size = size / 2; | ||||
| 
 | ||||
|   dev->img_buffer.resize(size); | ||||
| 
 | ||||
|   /* loop reading data until we reach maximum or EOF */ | ||||
|     total = 0; | ||||
|     while (total < maximum) { | ||||
|       len = size - maximum; | ||||
|       if (len > read_size) | ||||
| 	{ | ||||
| 	  len = read_size; | ||||
| 	} | ||||
| 
 | ||||
|         try { | ||||
|             genesys_read_ordered_data(dev, dev->img_buffer.data() + total, &len); | ||||
|         } catch (const SaneException& e) { | ||||
|             if (e.status() == SANE_STATUS_EOF) { | ||||
|                 // ideally we shouldn't end up here, but because computations are duplicated and
 | ||||
|                 // slightly different everywhere in the genesys backend, we have no other choice
 | ||||
|                 break; | ||||
|             } | ||||
|             throw; | ||||
|         } | ||||
|       total += len; | ||||
| 
 | ||||
|         // do we need to enlarge read buffer ?
 | ||||
|         if (total + read_size > size) { | ||||
|             size += read_size; | ||||
|             dev->img_buffer.resize(size); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   /* since digital processing is going to take place,
 | ||||
|    * issue head parking command so that the head move while | ||||
|    * computing so we can save time | ||||
|    */ | ||||
|     if (!dev->model->is_sheetfed && !dev->parking) { | ||||
|         dev->cmd_set->move_back_home(dev, has_flag(dev->model->flags, ModelFlag::MUST_WAIT)); | ||||
|         dev->parking = !has_flag(s->dev->model->flags, ModelFlag::MUST_WAIT); | ||||
|     } | ||||
| 
 | ||||
|   /* in case of dynamic lineart, we have buffered gray data which
 | ||||
|    * must be converted to lineart first */ | ||||
|     if (s->dev->settings.scan_mode == ScanColorMode::LINEART) { | ||||
|       total/=8; | ||||
|       std::vector<uint8_t> lineart(total); | ||||
| 
 | ||||
|       genesys_gray_lineart (dev, | ||||
|                             dev->img_buffer.data(), | ||||
|                             lineart.data(), | ||||
|                             dev->settings.pixels, | ||||
|                             (total*8)/dev->settings.pixels, | ||||
|                             dev->settings.threshold); | ||||
|       dev->img_buffer = lineart; | ||||
|     } | ||||
| 
 | ||||
|   /* update counters */ | ||||
|   dev->total_bytes_to_read = total; | ||||
|   dev->total_bytes_read = 0; | ||||
| 
 | ||||
|   /* update params */ | ||||
|     s->params.lines = total / s->params.bytes_per_line; | ||||
| 
 | ||||
|     if (dbg_log_image_data()) { | ||||
|       sanei_genesys_write_pnm_file("gl_unprocessed.pnm", dev->img_buffer.data(), s->params.depth, | ||||
|                                    s->params.format==SANE_FRAME_RGB ? 3 : 1, | ||||
|                                    s->params.pixels_per_line, s->params.lines); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* -------------------------- SANE API functions ------------------------- */ | ||||
| 
 | ||||
| void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize) | ||||
|  | @ -5579,9 +5395,6 @@ void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize) | |||
|         sanei_usb_init(); | ||||
|     } | ||||
| 
 | ||||
|   /* init sanei_magic */ | ||||
|   sanei_magic_init(); | ||||
| 
 | ||||
|   s_scanners.init(); | ||||
|   s_devices.init(); | ||||
|   s_sane_devices.init(); | ||||
|  | @ -5991,24 +5804,6 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val) | |||
|     case OPT_LAMP_OFF_TIME: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->lamp_off_time; | ||||
|         break; | ||||
|     case OPT_SWDESKEW: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->swdeskew; | ||||
|         break; | ||||
|     case OPT_SWCROP: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->swcrop; | ||||
|         break; | ||||
|     case OPT_SWDESPECK: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->swdespeck; | ||||
|         break; | ||||
|     case OPT_SWDEROTATE: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->swderotate; | ||||
|         break; | ||||
|     case OPT_SWSKIP: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->swskip; | ||||
|         break; | ||||
|     case OPT_DESPECK: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->despeck; | ||||
|         break; | ||||
|     case OPT_CONTRAST: | ||||
|         *reinterpret_cast<SANE_Word*>(val) = s->contrast; | ||||
|         break; | ||||
|  | @ -6212,31 +6007,6 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int | |||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_SWCROP: | ||||
|         s->swcrop = *reinterpret_cast<SANE_Word*>(val); | ||||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_SWDESKEW: | ||||
|         s->swdeskew = *reinterpret_cast<SANE_Word*>(val); | ||||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_DESPECK: | ||||
|         s->despeck = *reinterpret_cast<SANE_Word*>(val); | ||||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_SWDEROTATE: | ||||
|         s->swderotate = *reinterpret_cast<SANE_Word*>(val); | ||||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_SWSKIP: | ||||
|         s->swskip = *reinterpret_cast<SANE_Word*>(val); | ||||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_DISABLE_INTERPOLATION: | ||||
|         s->disable_interpolation = *reinterpret_cast<SANE_Word*>(val); | ||||
|         calc_parameters(s); | ||||
|  | @ -6262,38 +6032,14 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int | |||
|         calc_parameters(s); | ||||
|         *myinfo |= SANE_INFO_RELOAD_PARAMS; | ||||
|         break; | ||||
|     case OPT_SWDESPECK: | ||||
|         s->swdespeck = *reinterpret_cast<SANE_Word*>(val); | ||||
|         if (s->swdespeck) { | ||||
|             ENABLE(OPT_DESPECK); | ||||
|         } else { | ||||
|             DISABLE(OPT_DESPECK); | ||||
|         } | ||||
|         calc_parameters(s); | ||||
|       *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; | ||||
|       break; | ||||
|     /* software enhancement functions only apply to 8 or 1 bits data */ | ||||
|     case OPT_BIT_DEPTH: | ||||
|         s->bit_depth = *reinterpret_cast<SANE_Word*>(val); | ||||
|         if(s->bit_depth>8) | ||||
|         { | ||||
|           DISABLE(OPT_SWDESKEW); | ||||
|           DISABLE(OPT_SWDESPECK); | ||||
|           DISABLE(OPT_SWCROP); | ||||
|           DISABLE(OPT_DESPECK); | ||||
|           DISABLE(OPT_SWDEROTATE); | ||||
|           DISABLE(OPT_SWSKIP); | ||||
|           DISABLE(OPT_CONTRAST); | ||||
|           DISABLE(OPT_BRIGHTNESS); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           ENABLE(OPT_SWDESKEW); | ||||
|           ENABLE(OPT_SWDESPECK); | ||||
|           ENABLE(OPT_SWCROP); | ||||
|           ENABLE(OPT_DESPECK); | ||||
|           ENABLE(OPT_SWDEROTATE); | ||||
|           ENABLE(OPT_SWSKIP); | ||||
|             } else { | ||||
|           ENABLE(OPT_CONTRAST); | ||||
|           ENABLE(OPT_BRIGHTNESS); | ||||
|         } | ||||
|  | @ -6586,7 +6332,7 @@ void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params) | |||
|        * don't know the real document height. | ||||
|        * We don't do that doing buffering image for digital processing | ||||
|        */ | ||||
|         if (s->dev->model->is_sheetfed && !s->dev->buffer_image && | ||||
|         if (s->dev->model->is_sheetfed && | ||||
|             s->pos_bottom_right_y == s->opt[OPT_BR_Y].constraint.range->max) | ||||
|         { | ||||
| 	  params->lines = -1; | ||||
|  | @ -6645,52 +6391,6 @@ void sane_start_impl(SANE_Handle handle) | |||
|         s->dev->local_buffer.clear(); | ||||
|         s->dev->local_buffer.alloc(s->dev->binarize_buffer.size() * 8); | ||||
|     } | ||||
| 
 | ||||
|   /* if one of the software enhancement option is selected,
 | ||||
|    * we do the scan internally, process picture then put it an internal | ||||
|    * buffer. Since cropping may change scan parameters, we recompute them | ||||
|    * at the end */ | ||||
|   if (s->dev->buffer_image) | ||||
|     { | ||||
|         genesys_buffer_image(s); | ||||
| 
 | ||||
|       /* check if we need to skip this page, sheetfed scanners
 | ||||
|        * can go to next doc while flatbed ones can't */ | ||||
|         if (s->swskip > 0 && IS_ACTIVE(OPT_SWSKIP)) { | ||||
|             auto status = sanei_magic_isBlank(&s->params, | ||||
|                                               s->dev->img_buffer.data(), | ||||
|                                               fixed_to_float(s->swskip)); | ||||
| 
 | ||||
|             if (status == SANE_STATUS_NO_DOCS && s->dev->model->is_sheetfed) { | ||||
|                 DBG(DBG_info, "%s: blank page, recurse\n", __func__); | ||||
|                 sane_start(handle); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (status != SANE_STATUS_GOOD) { | ||||
|                 throw SaneException(status); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (s->swdeskew) { | ||||
|             const auto& sensor = sanei_genesys_find_sensor(s->dev, s->dev->settings.xres, | ||||
|                                                            s->dev->settings.get_channels(), | ||||
|                                                            s->dev->settings.scan_method); | ||||
|             catch_all_exceptions(__func__, [&](){ genesys_deskew(s, sensor); }); | ||||
|         } | ||||
| 
 | ||||
|         if (s->swdespeck) { | ||||
|             catch_all_exceptions(__func__, [&](){ genesys_despeck(s); }); | ||||
|         } | ||||
| 
 | ||||
|         if(s->swcrop) { | ||||
|             catch_all_exceptions(__func__, [&](){ genesys_crop(s); }); | ||||
|         } | ||||
| 
 | ||||
|         if(s->swderotate) { | ||||
|             catch_all_exceptions(__func__, [&](){ genesys_derotate(s); }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SANE_GENESYS_API_LINKAGE | ||||
|  | @ -6754,65 +6454,46 @@ void sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_ | |||
| 
 | ||||
|   local_len = max_len; | ||||
| 
 | ||||
|   /* in case of image processing, all data has been stored in
 | ||||
|    * buffer_image. So read data from it if it exists, else from scanner */ | ||||
|   if(!dev->buffer_image) | ||||
|     { | ||||
|       /* dynamic lineart is another kind of digital processing that needs
 | ||||
|        * another layer of buffering on top of genesys_read_ordered_data */ | ||||
|         if (dev->settings.scan_mode == ScanColorMode::LINEART) { | ||||
|           /* if buffer is empty, fill it with genesys_read_ordered_data */ | ||||
|           if(dev->binarize_buffer.avail() == 0) | ||||
|             { | ||||
|               /* store gray data */ | ||||
|               local_len=dev->local_buffer.size(); | ||||
|               dev->local_buffer.reset(); | ||||
|                 genesys_read_ordered_data(dev, dev->local_buffer.get_write_pos(local_len), | ||||
|                                           &local_len); | ||||
|               dev->local_buffer.produce(local_len); | ||||
|     // dynamic lineart is another kind of digital processing that needs
 | ||||
|     // another layer of buffering on top of genesys_read_ordered_data
 | ||||
|     if (dev->settings.scan_mode == ScanColorMode::LINEART) { | ||||
|         // if buffer is empty, fill it with genesys_read_ordered_data
 | ||||
|         if (dev->binarize_buffer.avail() == 0) { | ||||
|             // store gray data
 | ||||
|             local_len=dev->local_buffer.size(); | ||||
|             dev->local_buffer.reset(); | ||||
|             genesys_read_ordered_data(dev, dev->local_buffer.get_write_pos(local_len), | ||||
|                                         &local_len); | ||||
|             dev->local_buffer.produce(local_len); | ||||
| 
 | ||||
|                 dev->binarize_buffer.reset(); | ||||
|                 if (!is_testing_mode()) { | ||||
|                     genesys_gray_lineart(dev, dev->local_buffer.get_read_pos(), | ||||
|                                          dev->binarize_buffer.get_write_pos(local_len / 8), | ||||
|                                          dev->settings.pixels, | ||||
|                                          local_len / dev->settings.pixels, | ||||
|                                          dev->settings.threshold); | ||||
|                 } | ||||
|                 dev->binarize_buffer.produce(local_len / 8); | ||||
|             dev->binarize_buffer.reset(); | ||||
|             if (!is_testing_mode()) { | ||||
|                 genesys_gray_lineart(dev, dev->local_buffer.get_read_pos(), | ||||
|                                      dev->binarize_buffer.get_write_pos(local_len / 8), | ||||
|                                      dev->settings.pixels, | ||||
|                                      local_len / dev->settings.pixels, | ||||
|                                      dev->settings.threshold); | ||||
|             } | ||||
|             dev->binarize_buffer.produce(local_len / 8); | ||||
|         } | ||||
| 
 | ||||
|           /* return data from lineart buffer if any, up to the available amount */ | ||||
|           local_len = max_len; | ||||
|           if (static_cast<std::size_t>(max_len) > dev->binarize_buffer.avail()) | ||||
|             { | ||||
|               local_len=dev->binarize_buffer.avail(); | ||||
|             } | ||||
|           if(local_len) | ||||
|             { | ||||
|               memcpy(buf, dev->binarize_buffer.get_read_pos(), local_len); | ||||
|               dev->binarize_buffer.consume(local_len); | ||||
|             } | ||||
|         // return data from lineart buffer if any, up to the available amount
 | ||||
|         local_len = max_len; | ||||
|         if (static_cast<std::size_t>(max_len) > dev->binarize_buffer.avail()) { | ||||
|             local_len=dev->binarize_buffer.avail(); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|             // most usual case, direct read of data from scanner */
 | ||||
|             genesys_read_ordered_data(dev, buf, &local_len); | ||||
|         if (local_len) { | ||||
|             std::memcpy(buf, dev->binarize_buffer.get_read_pos(), local_len); | ||||
|             dev->binarize_buffer.consume(local_len); | ||||
|         } | ||||
|     } | ||||
|   else /* read data from buffer */ | ||||
|     { | ||||
|       if(dev->total_bytes_read+local_len>dev->total_bytes_to_read) | ||||
|         { | ||||
|           local_len=dev->total_bytes_to_read-dev->total_bytes_read; | ||||
|         } | ||||
|       memcpy(buf, dev->img_buffer.data() + dev->total_bytes_read, local_len); | ||||
|       dev->total_bytes_read+=local_len; | ||||
|     } else { | ||||
|         // most usual case, direct read of data from scanner */
 | ||||
|         genesys_read_ordered_data(dev, buf, &local_len); | ||||
|     } | ||||
| 
 | ||||
|   *len = local_len; | ||||
|     if (local_len > static_cast<std::size_t>(max_len)) { | ||||
|       fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n"); | ||||
|         dbg.log(DBG_error, "error: returning incorrect length"); | ||||
|     } | ||||
|   DBG(DBG_proc, "%s: %d bytes returned\n", __func__, *len); | ||||
| } | ||||
|  |  | |||
|  | @ -107,12 +107,6 @@ enum Genesys_Option | |||
|   OPT_GAMMA_VECTOR_R, | ||||
|   OPT_GAMMA_VECTOR_G, | ||||
|   OPT_GAMMA_VECTOR_B, | ||||
|   OPT_SWDESKEW, | ||||
|   OPT_SWCROP, | ||||
|   OPT_SWDESPECK, | ||||
|   OPT_DESPECK, | ||||
|   OPT_SWSKIP, | ||||
|   OPT_SWDEROTATE, | ||||
|   OPT_BRIGHTNESS, | ||||
|   OPT_CONTRAST, | ||||
| 
 | ||||
|  | @ -213,18 +207,12 @@ struct Genesys_Scanner | |||
|     // Option values
 | ||||
|     SANE_Word bit_depth = 0; | ||||
|     SANE_Word resolution = 0; | ||||
|     bool preview = false; | ||||
|     bool preview = false; // TODO: currently not used
 | ||||
|     SANE_Word threshold = 0; | ||||
|     SANE_Word threshold_curve = 0; | ||||
|     bool disable_interpolation = false; | ||||
|     bool lamp_off = false; | ||||
|     SANE_Word lamp_off_time = 0; | ||||
|     bool swdeskew = false; | ||||
|     bool swcrop = false; | ||||
|     bool swdespeck = false; | ||||
|     bool swderotate = false; | ||||
|     SANE_Word swskip = 0; | ||||
|     SANE_Word despeck = 0; | ||||
|     SANE_Word contrast = 0; | ||||
|     SANE_Word brightness = 0; | ||||
|     SANE_Word expiration_time = 0; | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Povilas Kanapickas
						Povilas Kanapickas