diff options
Diffstat (limited to 'backend/pixma/pixma_common.c')
-rw-r--r-- | backend/pixma/pixma_common.c | 175 |
1 files changed, 162 insertions, 13 deletions
diff --git a/backend/pixma/pixma_common.c b/backend/pixma/pixma_common.c index 7b7ecec..436311a 100644 --- a/backend/pixma/pixma_common.c +++ b/backend/pixma/pixma_common.c @@ -1,6 +1,6 @@ /* SANE - Scanner Access Now Easy. - Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de> + Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de> Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org> Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de> @@ -48,11 +48,18 @@ #include <stdlib.h> #include <string.h> #include <stdarg.h> +#include <ctype.h> #include <math.h> /* pow(C90) */ #include <sys/time.h> /* gettimeofday(4.3BSD) */ #include <unistd.h> /* usleep */ +#if defined(HAVE_LIBXML2) +# include <libxml/parser.h> +#else +# error "The pixma backend requires libxml2" +#endif + #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" @@ -143,6 +150,24 @@ pixma_hexdump (int level, const void *d_, unsigned len) p++; } } + for (c = 0; c < 4; c++) + { + p[0] = ' '; + p++; + } + for (c = 0; c != 16 && (ofs + c) < plen; c++) + { + if (isprint(d[ofs + c])) + p[0] = d[ofs + c]; + else + p[0] = '.'; + p++; + if (c == 7) + { + p[0] = ' '; + p++; + } + } p[0] = '\0'; pixma_dbg (level, "%s\n", line); ofs += c; @@ -335,7 +360,7 @@ pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c) /* convert 24/48 bit RGB to 8/16 bit grayscale * - * Formular: g = (R + G + B) / 3 + * Formular: Y' = 0,2126 R' + 0,7152 G' + 0,0722 B' * * sptr: source color scale buffer * gptr: destination gray scale buffer @@ -345,19 +370,28 @@ pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c) uint8_t * pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c) { - unsigned i, j, g; + unsigned i, g; /* PDBG (pixma_dbg (4, "*pixma_rgb_to_gray*****\n")); */ for (i = 0; i < w; i++) { - for (j = 0, g = 0; j < 3; j++) - { - g += *sptr++; - if (c == 6) g += (*sptr++ << 8); /* 48 bit RGB: high byte */ + if (c == 6) + { /* 48 bit RGB */ + unsigned r = sptr[0] + (sptr[1] << 8); + unsigned y = sptr[2] + (sptr[3] << 8); + unsigned b = sptr[4] + (sptr[5] << 8); + + g = (r * 2126) + (y * 7152) + (b * 722); + sptr += 6; } + else + { /* 24 bit RGB */ + g = (sptr[0] * 2126) + (sptr[1] * 7152) + (sptr[2] * 722); + sptr += 3; + } + g /= 10000; /* 8 and 16 bit gray */ - g /= 3; /* 8 or 16 bit gray */ *gptr++ = g; if (c == 6) *gptr++ = (g >> 8); /* 16 bit gray: high byte */ } @@ -846,7 +880,7 @@ pixma_scan (pixma_t * s, pixma_scan_param_t * sp) sp->line_size, sp->image_size, sp->channels, sp->depth); pixma_dbg (3, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n", sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h); - pixma_dbg (3, " gamma_table=%p source=%d\n", sp->gamma_table, sp->source); + pixma_dbg (3, " gamma=%f gamma_table=%p source=%d\n", sp->gamma, sp->gamma_table, sp->source); pixma_dbg (3, " threshold=%d threshold_curve=%d\n", sp->threshold, sp->threshold_curve); pixma_dbg (3, " adf-wait=%d\n", sp->adf_wait); pixma_dbg (3, " ADF page count: %d\n", sp->adf_pageid); @@ -1152,14 +1186,35 @@ pixma_get_config (pixma_t * s) void pixma_fill_gamma_table (double gamma, uint8_t * table, unsigned n) { - int i; + unsigned i; double r_gamma = 1.0 / gamma; - double out_scale = 255.0; double in_scale = 1.0 / (n - 1); - for (i = 0; (unsigned) i != n; i++) + /* 8-bits gamma table + * for generation 1 scanners + */ + if (n == 4096) + { + double out_scale = 255.0; + + for (i = 0; (unsigned) i != n; i++) + { + table[i] = (int) (out_scale * pow (i * in_scale, r_gamma) + 0.5); + } + } + + /* 16-bits gamma table */ + else { - table[i] = (int) (out_scale * pow (i * in_scale, r_gamma) + 0.5); + double out_scale = 65535.0; + uint16_t value; + + for (i = 0; i < n; i++) + { + value = (uint16_t) (out_scale * pow (i * in_scale, r_gamma) + 0.5); + table[2 * i] = (uint8_t) (value & 0xff); + table[2 * i + 1] = (uint8_t) (value >> 8); + } } } @@ -1185,3 +1240,97 @@ pixma_get_device_status (pixma_t * s, pixma_device_status_t * status) memset (status, 0, sizeof (*status)); return s->ops->get_status (s, status); } + +static const char * +format_xml_response(const char *resp_details) +{ + if (strcmp(resp_details, "DeviceBusy") == 0) + /* https://cromwell-intl.com/open-source/canon-pixma-printer-scanner.html */ + return "DeviceBusy - Device not initialized (yet). " \ + "Please check the USB power, try a different port or install the Ink Cartridges if the device supports them."; + else if (strcmp(resp_details, "ScannerCarriageLockError") == 0) + return "ScannerCarriageLockError - Please consult the manual to unlock the Carriage Lock."; + else if (strcmp(resp_details, "PCScanning") == 0) + return "PCScanning - Previous scan attempt was not completed. Try disconnecting and reconnecting the scanner. " \ + "If the problem persists, consider reporting it as a bug at http://www.sane-project.org/bugs.html."; + else if (strcmp(resp_details, "DeviceCheckError") == 0) + return "DeviceCheckError - Device detected a fault. Contact the repair center."; + else + return resp_details; +} + +int +pixma_parse_xml_response(const char *xml_message) +{ + int status = PIXMA_EPROTO; + xmlDoc *doc = NULL; + xmlNode *node = NULL; + xmlChar *content = NULL; + + doc = xmlReadMemory(xml_message, strlen(xml_message), "mem:device-resp.xml", NULL, 0); + if (doc == NULL) { + PDBG(pixma_dbg(10, "unable to parse xml response\n")); + status = PIXMA_EINVAL; + goto clean; + } + + node = xmlDocGetRootElement(doc); + if (node == NULL) { + status = PIXMA_EPROTO; + goto clean; + } + + /* /cmd */ + for (; node; node = node->next) { + if (strcmp((const char*)node->name, "cmd") == 0) + break; + } + if (!node) { + status = PIXMA_EPROTO; + goto clean; + } + + /* /cmd/contents */ + for (node = node->children; node; node = node->next) { + if (strcmp((const char*)node->name, "contents") == 0) + break; + } + if (!node) { + status = PIXMA_EPROTO; + goto clean; + } + + /* /cmd/contents/param_set */ + for (node = node->children; node; node = node->next) { + if (strcmp((const char*)node->name, "param_set") == 0) + break; + } + if (!node) { + status = PIXMA_EPROTO; + goto clean; + } + + /* /cmd/contents/param_set/response... */ + for (node = node->children; node; node = node->next) + { + if (strcmp((const char*)node->name, "response") == 0) { + content = xmlNodeGetContent(node); + if (strcmp((const char*)content, "OK") == 0) + status = PIXMA_STATUS_OK; + else + status = PIXMA_EINVAL; + xmlFree(content); + } else if (strcmp((const char*)node->name, "response_detail") == 0) { + content = xmlNodeGetContent(node); + if (strlen((const char*)content) > 0) { + PDBG(pixma_dbg(0, "device response: %s\n", + format_xml_response((const char*)content))); + } + xmlFree(content); + } + } + +clean: + xmlFreeDoc(doc); + return status; +} |