From eba9c9e2391d59459e5fa3f362d8dc08d14c7b9c Mon Sep 17 00:00:00 2001 From: Rolf Bensch Date: Fri, 4 Mar 2016 13:36:08 +0100 Subject: [PATCH] pixma_imageclass: software lineart for all imageCLASS, imageRUNNER, i-SENSYS and laserBase scanners, supported by this sub-backend imageCLASS scanners: D420, D480, D530, MF810/820, MF3240, MF4010, MF4150, MF4270, MF4320, MF4360, MF4410, MF4570dw, MF4690, MF5630, MF6500, MF8030, MF8170c i-SENSYS scanners: MF210, MF220, MF3010, MF4500, MF4700, MF4800, MF5880dn, MF5900, MF6100, MF6680dn, MF8200C, MF8300, MF8500C imageRUNNER scanners: iR1133 laserBase scanners: MF5650 --- backend/pixma_imageclass.c | 74 +++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/backend/pixma_imageclass.c b/backend/pixma_imageclass.c index 023330c41..d26a51e5b 100644 --- a/backend/pixma_imageclass.c +++ b/backend/pixma_imageclass.c @@ -264,7 +264,7 @@ send_scan_param (pixma_t * s) pixma_set_be32 (mf->raw_width, data + 0x10); pixma_set_be32 (s->param->h, data + 0x14); data[0x18] = (s->param->channels == 1) ? 0x04 : 0x08; - data[0x19] = s->param->channels * s->param->depth; /* bits per pixel */ + data[0x19] = s->param->channels * ((s->param->depth == 1) ? 8 : s->param->depth); /* bits per pixel */ data[0x1f] = 0x7f; data[0x20] = 0xff; data[0x23] = 0x81; @@ -529,8 +529,34 @@ iclass_check_param (pixma_t * s, pixma_scan_param_t * sp) { UNUSED (s); + /* PDBG (pixma_dbg (4, "*iclass_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, line_size=%" PRIu64 " , h=%u*****\n", + sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->line_size, sp->h)); */ + sp->depth = 8; - sp->line_size = ALIGN_SUP (sp->w, 32) * sp->channels; + sp->software_lineart = 0; + if (sp->mode == PIXMA_SCAN_MODE_LINEART) + { + sp->software_lineart = 1; + sp->channels = 1; + sp->depth = 1; + } + + if (sp->software_lineart == 1) + { + unsigned w_max; + + /* for software lineart line_size and w must be a multiple of 8 */ + sp->line_size = ALIGN_SUP (sp->w, 8) * sp->channels; + sp->w = ALIGN_SUP (sp->w, 8); + + /* do not exceed the scanner capability */ + w_max = s->cfg->width * s->cfg->xdpi / 75; + w_max -= w_max % 32; + if (sp->w > w_max) + sp->w = w_max; + } + else + sp->line_size = ALIGN_SUP (sp->w, 32) * sp->channels; /* Some exceptions here for particular devices */ /* Those devices can scan up to Legal 14" with ADF, but A4 11.7" in flatbed */ @@ -538,6 +564,9 @@ iclass_check_param (pixma_t * s, pixma_scan_param_t * sp) if ((s->cfg->cap & PIXMA_CAP_ADF) && sp->source == PIXMA_SOURCE_FLATBED) sp->h = MIN (sp->h, 877 * sp->xdpi / 75); + /* PDBG (pixma_dbg (4, "*iclass_check_param***** Finally: channels=%u, depth=%u, x=%u, y=%u, w=%u, line_size=%" PRIu64 " , h=%u*****\n", + sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->line_size, sp->h)); */ + return 0; } @@ -608,7 +637,7 @@ iclass_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error, n; iclass_t *mf = (iclass_t *) s->subdriver; - unsigned block_size, lines_size, first_block_size; + unsigned block_size, lines_size, lineart_lines_size, first_block_size; uint8_t info; /* @@ -668,10 +697,33 @@ iclass_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) /* add current block to remainder of previous */ mf->blk_len += block_size; /* n = number of full lines (rows) we have in the buffer. */ - n = mf->blk_len / s->param->line_size; + n = mf->blk_len / ((s->param->mode == PIXMA_SCAN_MODE_LINEART) ? mf->raw_width : s->param->line_size); if (n != 0) { - if (s->param->channels != 1 && + /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** Processing with n=%d, w=%i, line_size=%" PRIu64 ", raw_width=%u ***** \n", + n, s->param->w, s->param->line_size, mf->raw_width)); */ + /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** scan_mode=%d, lineptr=%" PRIu64 ", blkptr=%" PRIu64 " \n", + s->param->mode, (uint64_t)mf->lineptr, (uint64_t)mf->blkptr)); */ + + /* gray to lineart convert + * mf->lineptr : image line + * mf->blkptr : scanned image block as grayscale + * s->param->w : image width + * s->param->line_size : scanned image width */ + if (s->param->mode == PIXMA_SCAN_MODE_LINEART) + { + int i; + uint8_t *sptr, *dptr; + + /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** Processing lineart *****\n")); */ + + /* process ALL lines */ + sptr = mf->blkptr; + dptr = mf->lineptr; + for (i = 0; i < n; i++, sptr += mf->raw_width) + dptr = pixma_binarize_line (s->param, dptr, sptr, s->param->line_size, 1); + } + else if (s->param->channels != 1 && mf->generation == 1 && s->cfg->pid != MF4600_PID && s->cfg->pid != MF6500_PID && @@ -685,17 +737,22 @@ iclass_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) /* grayscale */ memcpy (mf->lineptr, mf->blkptr, n * s->param->line_size); } - lines_size = n * s->param->line_size; /* cull remainder and shift left */ + lineart_lines_size = n * s->param->line_size / 8; + lines_size = n * ((s->param->mode == PIXMA_SCAN_MODE_LINEART) ? mf->raw_width : s->param->line_size); mf->blk_len -= lines_size; memcpy (mf->blkptr, mf->blkptr + lines_size, mf->blk_len); } } while (n == 0); - /* output full lines, keep partial lines for next block */ + /* output full lines, keep partial lines for next block + * ib->rptr : start of image buffer + * ib->rend : end of image buffer */ ib->rptr = mf->lineptr; - ib->rend = mf->lineptr + lines_size; + ib->rend = mf->lineptr + (s->param->mode == PIXMA_SCAN_MODE_LINEART ? lineart_lines_size : lines_size); + /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** rptr=%" PRIu64 ", rend=%" PRIu64 ", diff=%ld \n", + (uint64_t)ib->rptr, (uint64_t)ib->rend, ib->rend - ib->rptr)); */ return ib->rend - ib->rptr; } @@ -800,6 +857,7 @@ static const pixma_scan_ops_t pixma_iclass_ops = { adftpu_max_dpi, /* adftpu_max_dpi */ \ 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ w, h, /* width, height */ \ + PIXMA_CAP_LINEART| /* all scanners have software lineart */ \ PIXMA_CAP_GRAY|PIXMA_CAP_EVENTS|cap \ } const pixma_config_t pixma_iclass_devices[] = {