kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			Add new blank page and rotation detection algos
							rodzic
							
								
									b49271c798
								
							
						
					
					
						commit
						28ccc11d91
					
				| 
						 | 
				
			
			@ -1,10 +1,11 @@
 | 
			
		|||
 | 
			
		||||
2011-06-06 m. allan noah <kitno455 at gmail dot com>
 | 
			
		||||
	* docs/*kvs40xx*, backend/kvs40xx*: New Panasonic KV-S40xx/70xx
 | 
			
		||||
	backend, originally by Panasonic Russia.
 | 
			
		||||
	* acinclude.m4, */Makefile.am, configure*: build new kvs40xx backend
 | 
			
		||||
	* po/POTFILES: add new kvs40xx backend
 | 
			
		||||
	* po/.gitignore: ignore sane-backends.pot
 | 
			
		||||
	* include/sane/sanei_magic.h, sanei/sanei_magic.c:
 | 
			
		||||
	add new blank detection and rotation detection routines
 | 
			
		||||
 | 
			
		||||
2011-06-02 Julien Blache <jb@jblache.org>
 | 
			
		||||
	* tools/sane-desc.c: add udev+acl output mode, udev rules using ACLs
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,8 @@
 | 
			
		|||
 * - Deskew (correct rotated scans, by detecting media edges)
 | 
			
		||||
 * - Autocrop (reduce image size to minimum rectangle containing media)
 | 
			
		||||
 * - Despeckle (replace dots of significantly different color with background)
 | 
			
		||||
 * - Blank detection (check if density is over a threshold)
 | 
			
		||||
 * - Rotate (detect and correct 90 degree increment rotations)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that these functions are simplistic, and are expected to change.
 | 
			
		||||
 * Patches and suggestions are welcome.
 | 
			
		||||
| 
						 | 
				
			
			@ -151,4 +153,52 @@ extern SANE_Status
 | 
			
		|||
sanei_magic_crop(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  int top, int bot, int left, int right);
 | 
			
		||||
 | 
			
		||||
/** Determine if image is blank
 | 
			
		||||
 *
 | 
			
		||||
 * @param params describes image
 | 
			
		||||
 * @param buffer contains image data
 | 
			
		||||
 * @param thresh maximum % density for blankness (0-100)
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 * - SANE_STATUS_GOOD - page is not blank
 | 
			
		||||
 * - SANE_STATUS_NO_DOCS - page is blank
 | 
			
		||||
 * - SANE_STATUS_NO_MEM - not enough memory
 | 
			
		||||
 * - SANE_STATUS_INVAL - invalid image parameters
 | 
			
		||||
 */
 | 
			
		||||
extern SANE_Status
 | 
			
		||||
sanei_magic_isBlank(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  double thresh);
 | 
			
		||||
 | 
			
		||||
/** Determine coarse image rotation (90 degree increments)
 | 
			
		||||
 *
 | 
			
		||||
 * @param params describes image
 | 
			
		||||
 * @param buffer contains image data
 | 
			
		||||
 * @param dpiX horizontal resolution
 | 
			
		||||
 * @param dpiY vertical resolution
 | 
			
		||||
 * @param[out] angle amount of rotation recommended
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 * - SANE_STATUS_GOOD - success
 | 
			
		||||
 * - SANE_STATUS_NO_MEM - not enough memory
 | 
			
		||||
 * - SANE_STATUS_INVAL - invalid image parameters
 | 
			
		||||
 */
 | 
			
		||||
extern SANE_Status
 | 
			
		||||
sanei_magic_findTurn(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  int dpiX, int dpiY, int * angle);
 | 
			
		||||
 | 
			
		||||
/** Coarse image rotation (90 degree increments)
 | 
			
		||||
 *
 | 
			
		||||
 * @param params describes image
 | 
			
		||||
 * @param buffer contains image data
 | 
			
		||||
 * @param angle amount of rotation requested (multiple of 90)
 | 
			
		||||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 * - SANE_STATUS_GOOD - success
 | 
			
		||||
 * - SANE_STATUS_NO_MEM - not enough memory
 | 
			
		||||
 * - SANE_STATUS_INVAL - invalid image or angle parameters
 | 
			
		||||
 */
 | 
			
		||||
extern SANE_Status
 | 
			
		||||
sanei_magic_turn(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  int angle);
 | 
			
		||||
 | 
			
		||||
#endif /* SANEI_MAGIC_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -529,6 +529,8 @@ sanei_magic_findSkew(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		|||
 | 
			
		||||
  DBG (10, "sanei_magic_findSkew: start\n");
 | 
			
		||||
 | 
			
		||||
  dpiX=dpiX;
 | 
			
		||||
 | 
			
		||||
  /* get buffers for edge detection */
 | 
			
		||||
  topBuf = sanei_magic_getTransY(params,dpiY,buffer,1);
 | 
			
		||||
  if(!topBuf){
 | 
			
		||||
| 
						 | 
				
			
			@ -711,6 +713,448 @@ sanei_magic_rotate (SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		|||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SANE_Status
 | 
			
		||||
sanei_magic_isBlank (SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  double thresh)
 | 
			
		||||
{
 | 
			
		||||
  SANE_Status ret = SANE_STATUS_GOOD;
 | 
			
		||||
  double imagesum = 0;
 | 
			
		||||
  int i, j;
 | 
			
		||||
 | 
			
		||||
  DBG(10,"sanei_magic_isBlank: start: %f\n",thresh);
 | 
			
		||||
 | 
			
		||||
  /*convert thresh from percent (0-100) to 0-1 range*/
 | 
			
		||||
  thresh /= 100;
 | 
			
		||||
 | 
			
		||||
  if(params->format == SANE_FRAME_RGB || 
 | 
			
		||||
    (params->format == SANE_FRAME_GRAY && params->depth == 8)
 | 
			
		||||
  ){
 | 
			
		||||
 | 
			
		||||
    /* loop over all rows, find density of each */
 | 
			
		||||
    for(i=0; i<params->lines; i++){
 | 
			
		||||
      int rowsum = 0;
 | 
			
		||||
      SANE_Byte * ptr = buffer + params->bytes_per_line*i;
 | 
			
		||||
 | 
			
		||||
      /* loop over all columns, sum the 'darkness' of the pixels */
 | 
			
		||||
      for(j=0; j<params->bytes_per_line; j++){
 | 
			
		||||
        rowsum += 255 - ptr[j];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      imagesum += (double)rowsum/params->bytes_per_line/255;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  else if(params->format == SANE_FRAME_GRAY && params->depth == 1){
 | 
			
		||||
 | 
			
		||||
    /* loop over all rows, find density of each */
 | 
			
		||||
    for(i=0; i<params->lines; i++){
 | 
			
		||||
      int rowsum = 0;
 | 
			
		||||
      SANE_Byte * ptr = buffer + params->bytes_per_line*i;
 | 
			
		||||
 | 
			
		||||
      /* loop over all columns, sum the pixels */
 | 
			
		||||
      for(j=0; j<params->pixels_per_line; j++){
 | 
			
		||||
        rowsum += ptr[j/8] >> (7-(j%8)) & 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      imagesum += (double)rowsum/params->pixels_per_line;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  else{
 | 
			
		||||
    DBG (5, "sanei_magic_isBlank: unsupported format/depth\n");
 | 
			
		||||
    ret = SANE_STATUS_INVAL;
 | 
			
		||||
    goto cleanup;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DBG (5, "sanei_magic_isBlank: sum:%f lines:%d thresh:%f density:%f\n",
 | 
			
		||||
    imagesum,params->lines,thresh,imagesum/params->lines);
 | 
			
		||||
 | 
			
		||||
  if(imagesum/params->lines <= thresh){
 | 
			
		||||
    DBG (5, "sanei_magic_isBlank: blank!\n");
 | 
			
		||||
    ret = SANE_STATUS_NO_DOCS;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cleanup:
 | 
			
		||||
 | 
			
		||||
  DBG(10,"sanei_magic_isBlank: finish\n");
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SANE_Status
 | 
			
		||||
sanei_magic_findTurn(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  int dpiX, int dpiY, int * angle)
 | 
			
		||||
{
 | 
			
		||||
  SANE_Status ret = SANE_STATUS_GOOD;
 | 
			
		||||
  int i, j, k;
 | 
			
		||||
  int depth = 1;
 | 
			
		||||
  int htrans=0, vtrans=0;
 | 
			
		||||
  int htot=0, vtot=0;
 | 
			
		||||
 | 
			
		||||
  DBG(10,"sanei_magic_findTurn: start\n");
 | 
			
		||||
 | 
			
		||||
  if(params->format == SANE_FRAME_RGB || 
 | 
			
		||||
    (params->format == SANE_FRAME_GRAY && params->depth == 8)
 | 
			
		||||
  ){
 | 
			
		||||
 | 
			
		||||
    if(params->format == SANE_FRAME_RGB)
 | 
			
		||||
      depth = 3;
 | 
			
		||||
 | 
			
		||||
    /* loop over some rows, count segment lengths */
 | 
			
		||||
    for(i=0; i<params->lines; i+=dpiY/20){
 | 
			
		||||
      SANE_Byte * ptr = buffer + params->bytes_per_line*i;
 | 
			
		||||
      int color = 0;
 | 
			
		||||
      int len   = 0;
 | 
			
		||||
      int sum   = 0;
 | 
			
		||||
 | 
			
		||||
      /* loop over all columns */
 | 
			
		||||
      for(j=0; j<params->pixels_per_line; j++){
 | 
			
		||||
        int curr = 0;
 | 
			
		||||
 | 
			
		||||
        /*convert color to gray*/
 | 
			
		||||
        for (k=0; k<depth; k++) {
 | 
			
		||||
          curr += ptr[j*depth+k];
 | 
			
		||||
        }
 | 
			
		||||
        curr /= depth;
 | 
			
		||||
 | 
			
		||||
        /*convert gray to binary (with hysteresis) */
 | 
			
		||||
        curr = (curr < 100)?1:
 | 
			
		||||
               (curr > 156)?0:color;
 | 
			
		||||
 | 
			
		||||
        /*count segment length*/
 | 
			
		||||
        if(curr != color || j==params->pixels_per_line-1){
 | 
			
		||||
          sum += len * len/5;
 | 
			
		||||
          len = 0;
 | 
			
		||||
          color = curr;
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
          len++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      htot++;
 | 
			
		||||
      htrans += (double)sum/params->pixels_per_line;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* loop over some cols, count dark vs light transitions */
 | 
			
		||||
    for(i=0; i<params->pixels_per_line; i+=dpiX/20){
 | 
			
		||||
      SANE_Byte * ptr = buffer + i*depth;
 | 
			
		||||
      int color = 0;
 | 
			
		||||
      int len   = 0;
 | 
			
		||||
      int sum   = 0;
 | 
			
		||||
 | 
			
		||||
      /* loop over all rows */
 | 
			
		||||
      for(j=0; j<params->lines; j++){
 | 
			
		||||
        int curr = 0;
 | 
			
		||||
 | 
			
		||||
        /*convert color to gray*/
 | 
			
		||||
        for (k=0; k<depth; k++) {
 | 
			
		||||
          curr += ptr[j*params->bytes_per_line+k];
 | 
			
		||||
        }
 | 
			
		||||
        curr /= depth;
 | 
			
		||||
 | 
			
		||||
        /*convert gray to binary (with hysteresis) */
 | 
			
		||||
        curr = (curr < 100)?1:
 | 
			
		||||
               (curr > 156)?0:color;
 | 
			
		||||
 | 
			
		||||
        /*count segment length*/
 | 
			
		||||
        if(curr != color || j==params->lines-1){
 | 
			
		||||
          sum += len * len/5;
 | 
			
		||||
          len = 0;
 | 
			
		||||
          color = curr;
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
          len++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      vtot++;
 | 
			
		||||
      vtrans += (double)sum/params->lines;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  else if(params->format == SANE_FRAME_GRAY && params->depth == 1){
 | 
			
		||||
 | 
			
		||||
    /* loop over some rows, count segment lengths */
 | 
			
		||||
    for(i=0; i<params->lines; i+=dpiY/30){
 | 
			
		||||
      SANE_Byte * ptr = buffer + params->bytes_per_line*i;
 | 
			
		||||
      int color = 0;
 | 
			
		||||
      int len   = 0;
 | 
			
		||||
      int sum   = 0;
 | 
			
		||||
 | 
			
		||||
      /* loop over all columns */
 | 
			
		||||
      for(j=0; j<params->pixels_per_line; j++){
 | 
			
		||||
        int curr = ptr[j/8] >> (7-(j%8)) & 1;
 | 
			
		||||
 | 
			
		||||
        /*count segment length*/
 | 
			
		||||
        if(curr != color || j==params->pixels_per_line-1){
 | 
			
		||||
          sum += len * len/5;
 | 
			
		||||
          len = 0;
 | 
			
		||||
          color = curr;
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
          len++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      htot++;
 | 
			
		||||
      htrans += (double)sum/params->pixels_per_line;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* loop over some cols, count dark vs light transitions */
 | 
			
		||||
    for(i=0; i<params->pixels_per_line; i+=dpiX/30){
 | 
			
		||||
      SANE_Byte * ptr = buffer;
 | 
			
		||||
      int color = 0;
 | 
			
		||||
      int len   = 0;
 | 
			
		||||
      int sum   = 0;
 | 
			
		||||
 | 
			
		||||
      /* loop over all rows */
 | 
			
		||||
      for(j=0; j<params->lines; j++){
 | 
			
		||||
        int curr = ptr[j*params->bytes_per_line + i/8] >> (7-(i%8)) & 1;
 | 
			
		||||
 | 
			
		||||
        /*count segment length*/
 | 
			
		||||
        if(curr != color || j==params->lines-1){
 | 
			
		||||
          sum += len * len/5;
 | 
			
		||||
          len = 0;
 | 
			
		||||
          color = curr;
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
          len++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      vtot++;
 | 
			
		||||
      vtrans += (double)sum/params->lines;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  else{
 | 
			
		||||
    DBG (5, "sanei_magic_findTurn: unsupported format/depth\n");
 | 
			
		||||
    ret = SANE_STATUS_INVAL;
 | 
			
		||||
    goto cleanup;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DBG (10, "sanei_magic_findTurn: vtrans=%d vtot=%d vfrac=%f htrans=%d htot=%d hfrac=%f\n",
 | 
			
		||||
    vtrans, vtot, (double)vtrans/vtot, htrans, htot, (double)htrans/htot
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  if((double)vtrans/vtot > (double)htrans/htot){
 | 
			
		||||
    DBG (10, "sanei_magic_findTurn: suggest turning 90\n");
 | 
			
		||||
    *angle = 90;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cleanup:
 | 
			
		||||
 | 
			
		||||
  DBG(10,"sanei_magic_findTurn: finish\n");
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME: Do in-place rotation to save memory */
 | 
			
		||||
SANE_Status
 | 
			
		||||
sanei_magic_turn(SANE_Parameters * params, SANE_Byte * buffer,
 | 
			
		||||
  int angle)
 | 
			
		||||
{
 | 
			
		||||
  SANE_Status ret = SANE_STATUS_GOOD;
 | 
			
		||||
  int opwidth, ipwidth = params->pixels_per_line;
 | 
			
		||||
  int obwidth, ibwidth = params->bytes_per_line;
 | 
			
		||||
  int oheight, iheight = params->lines;
 | 
			
		||||
  int depth = 1;
 | 
			
		||||
 | 
			
		||||
  unsigned char * outbuf = NULL;
 | 
			
		||||
  int i, j, k;
 | 
			
		||||
 | 
			
		||||
  DBG(10,"sanei_magic_turn: start %d\n",angle);
 | 
			
		||||
 | 
			
		||||
  if(params->format == SANE_FRAME_RGB)
 | 
			
		||||
    depth = 3;
 | 
			
		||||
 | 
			
		||||
  /*clean angle and convert to 0-3*/
 | 
			
		||||
  angle = (angle % 360) / 90;
 | 
			
		||||
 | 
			
		||||
  /*figure size of output image*/
 | 
			
		||||
  switch(angle){
 | 
			
		||||
    case 1:
 | 
			
		||||
    case 3:
 | 
			
		||||
      opwidth = iheight;
 | 
			
		||||
      oheight = ipwidth;
 | 
			
		||||
 | 
			
		||||
      /*gray and color, 1 or 3 bytes per pixel*/
 | 
			
		||||
      if ( params->format == SANE_FRAME_RGB
 | 
			
		||||
        || (params->format == SANE_FRAME_GRAY && params->depth == 8)
 | 
			
		||||
      ){
 | 
			
		||||
        obwidth = opwidth*depth;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*clamp binary to byte width. must be <= input image*/
 | 
			
		||||
      else if(params->format == SANE_FRAME_GRAY && params->depth == 1){
 | 
			
		||||
        obwidth = opwidth/8;
 | 
			
		||||
        opwidth = obwidth*8;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      else{
 | 
			
		||||
        DBG(10,"sanei_magic_turn: bad params\n");
 | 
			
		||||
        ret = SANE_STATUS_INVAL;
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
      opwidth = ipwidth;
 | 
			
		||||
      obwidth = ibwidth;
 | 
			
		||||
      oheight = iheight;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      DBG(10,"sanei_magic_turn: no turn\n");
 | 
			
		||||
      goto cleanup;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*get output image buffer*/
 | 
			
		||||
  outbuf = malloc(obwidth*oheight);
 | 
			
		||||
  if(!outbuf){
 | 
			
		||||
    DBG(15,"sanei_magic_turn: no outbuf\n");
 | 
			
		||||
    ret = SANE_STATUS_NO_MEM;
 | 
			
		||||
    goto cleanup;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*turn color & gray image*/
 | 
			
		||||
  if(params->format == SANE_FRAME_RGB || 
 | 
			
		||||
    (params->format == SANE_FRAME_GRAY && params->depth == 8)
 | 
			
		||||
  ){
 | 
			
		||||
 | 
			
		||||
    switch (angle) {
 | 
			
		||||
 | 
			
		||||
      /*rotate 90 clockwise*/
 | 
			
		||||
      case 1:
 | 
			
		||||
        for (i=0; i<oheight; i++) {
 | 
			
		||||
          for (j=0; j<opwidth; j++) {
 | 
			
		||||
            for (k=0; k<depth; k++) {
 | 
			
		||||
              outbuf[i*obwidth + j*depth + k]
 | 
			
		||||
                = buffer[(iheight-j-1)*ibwidth + i*depth + k];
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      /*rotate 180 clockwise*/
 | 
			
		||||
      case 2:
 | 
			
		||||
        for (i=0; i<oheight; i++) {
 | 
			
		||||
          for (j=0; j<opwidth; j++) {
 | 
			
		||||
            for (k=0; k<depth; k++) {
 | 
			
		||||
              outbuf[i*obwidth + j*depth + k]
 | 
			
		||||
                = buffer[(iheight-i-1)*ibwidth + (ipwidth-j-1)*depth + k];
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      /*rotate 270 clockwise*/
 | 
			
		||||
      case 3:
 | 
			
		||||
        for (i=0; i<oheight; i++) {
 | 
			
		||||
          for (j=0; j<opwidth; j++) {
 | 
			
		||||
            for (k=0; k<depth; k++) {
 | 
			
		||||
              outbuf[i*obwidth + j*depth + k]
 | 
			
		||||
                = buffer[j*ibwidth + (ipwidth-i-1)*depth + k];
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    } /*end switch*/
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*turn binary image*/
 | 
			
		||||
  else if(params->format == SANE_FRAME_GRAY && params->depth == 1){
 | 
			
		||||
 | 
			
		||||
    switch (angle) {
 | 
			
		||||
 | 
			
		||||
      /*rotate 90 clockwise*/
 | 
			
		||||
      case 1:
 | 
			
		||||
        for (i=0; i<oheight; i++) {
 | 
			
		||||
          for (j=0; j<opwidth; j++) {
 | 
			
		||||
            unsigned char curr
 | 
			
		||||
              = buffer[(iheight-j-1)*ibwidth + i/8] >> (7-(i%8)) & 1;
 | 
			
		||||
 | 
			
		||||
            unsigned char mask = 1 << (7-(j%8));
 | 
			
		||||
 | 
			
		||||
            if(curr){
 | 
			
		||||
              outbuf[i*obwidth + j/8] |= mask;
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
              outbuf[i*obwidth + j/8] &= (~mask);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      /*rotate 180 clockwise*/
 | 
			
		||||
      case 2:
 | 
			
		||||
        for (i=0; i<oheight; i++) {
 | 
			
		||||
          for (j=0; j<opwidth; j++) {
 | 
			
		||||
            unsigned char curr
 | 
			
		||||
              = buffer[(iheight-i-1)*ibwidth + (ipwidth-j-1)/8] >> (j%8) & 1;
 | 
			
		||||
 | 
			
		||||
            unsigned char mask = 1 << (7-(j%8));
 | 
			
		||||
 | 
			
		||||
            if(curr){
 | 
			
		||||
              outbuf[i*obwidth + j/8] |= mask;
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
              outbuf[i*obwidth + j/8] &= (~mask);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      /*rotate 270 clockwise*/
 | 
			
		||||
      case 3:
 | 
			
		||||
        for (i=0; i<oheight; i++) {
 | 
			
		||||
          for (j=0; j<opwidth; j++) {
 | 
			
		||||
            unsigned char curr
 | 
			
		||||
              = buffer[j*ibwidth + (ipwidth-i-1)/8] >> (i%8) & 1;
 | 
			
		||||
 | 
			
		||||
            unsigned char mask = 1 << (7-(j%8));
 | 
			
		||||
 | 
			
		||||
            if(curr){
 | 
			
		||||
              outbuf[i*obwidth + j/8] |= mask;
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
              outbuf[i*obwidth + j/8] &= (~mask);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    } /*end switch*/
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  else{
 | 
			
		||||
    DBG (5, "sanei_magic_turn: unsupported format/depth\n");
 | 
			
		||||
    ret = SANE_STATUS_INVAL;
 | 
			
		||||
    goto cleanup;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*copy output back into input buffer*/
 | 
			
		||||
  memcpy(buffer,outbuf,obwidth*oheight);
 | 
			
		||||
 | 
			
		||||
  /*update input params*/
 | 
			
		||||
  params->pixels_per_line = opwidth;
 | 
			
		||||
  params->bytes_per_line = obwidth;
 | 
			
		||||
  params->lines = oheight;
 | 
			
		||||
 | 
			
		||||
  cleanup:
 | 
			
		||||
 | 
			
		||||
  if(outbuf)
 | 
			
		||||
    free(outbuf);
 | 
			
		||||
 | 
			
		||||
  DBG(10,"sanei_magic_turn: finish\n");
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Utility functions, not used outside this file */
 | 
			
		||||
 | 
			
		||||
/* Repeatedly call getLine to find the best range of slope and offset.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue