mitsu70x: Major steps towards supoprting 8bpp spool data.

* Support old 16bpp YMC data and 8bpp BGR data.
 * Tweak spool format to flag the difference
 * Load up LUT and transform contents if enabled
 * Load up Matte lamination data and use it if enabled
 * Use the data tables to perform 8bppBGR->16bppYMC mapping.

Confirmed to work, and quality is much improved over old status quo

 (Note this requires code not yet committed to gutenprint)
This commit is contained in:
Solomon Peachy 2016-09-10 15:34:39 -04:00
parent 3af7523f0e
commit d980999c9e
2 changed files with 153 additions and 48 deletions

View File

@ -6,6 +6,7 @@ EXEC_NAME ?= dyesub_backend
PREFIX ?=
CUPS_BACKEND_DIR ?= $(PREFIX)`cups-config --serverbin`/backend
CUPS_DATA_DIR ?= $(PREFIX)`cups-config --datadir`
BACKEND_DATA_DIR ?= $(PREFIX)/usr/share/gutenprint/backend_data
# Tools
CC ?= $(CROSS_COMPILE)gcc
@ -37,6 +38,10 @@ LDFLAGS += -ldl
#CPPFLAGS += -DUSE_LTDL
#LDFLAGS += -lltdl
# For the mitsu70x backend
CPPFLAGS += -DENABLE_CORRTABLES
CPPFLAGS += -DCORRTABLE_PATH=\"$(BACKEND_DATA_DIR)\"
# Build stuff
DEPS += backend_common.h
SOURCES = backend_common.c $(addsuffix .c,$(addprefix backend_,$(BACKENDS)))
@ -63,6 +68,11 @@ install:
$(INSTALL) -o root -m 700 $(EXEC_NAME) $(CUPS_BACKEND_DIR)/$(BACKEND_NAME)
$(MKDIR) -p $(CUPS_DATA_DIR)/usb
$(INSTALL) -o root -m 644 blacklist $(CUPS_DATA_DIR)/usb/net.sf.gimp-print.usb-quirks
ifneq ($(BACKEND_DATA_DIR),)
$(MKDIR) -p $(BACKEND_DATA_DIR)
$(INSTALL) -o root -m 644 D70/*raw $(BACKEND_DATA_DIR)
$(INSTALL) -o root -m 644 D70/*lut $(BACKEND_DATA_DIR)
endif
clean:
$(RM) -f $(EXEC_NAME) $(BACKENDS) $(SOURCES:.c=.o)

View File

@ -50,6 +50,14 @@
//#define ENABLE_CORRTABLES
#ifndef CORRTABLE_PATH
#define CORRTABLE_PATH "D70"
#endif
#ifdef ENABLE_CORRTABLES
#include "D70/Mitsu_D70.c"
#endif
/* Private data stucture */
struct mitsu70x_ctx {
struct libusb_device_handle *dev;
@ -76,6 +84,8 @@ struct mitsu70x_ctx {
char *laminatefname;
char *lutfname;
struct CColorConv3D lut;
int raw_format;
#endif
};
@ -260,7 +270,9 @@ struct mitsu70x_hdr {
uint8_t zero3[6];
uint8_t multicut;
uint8_t zero4[15];
uint8_t zero4[13];
uint8_t mode; /* 0 for cooked YMC planar, 1 for packed BGR */
uint8_t use_lut; /* in BGR mode, 0 disables, 1 enables */
uint8_t pad[448];
} __attribute__((packed));
@ -616,6 +628,7 @@ static void mitsu70x_teardown(void *vctx) {
if (ctx->databuf)
free(ctx->databuf);
free(ctx);
}
@ -623,6 +636,7 @@ static int mitsu70x_read_parse(void *vctx, int data_fd) {
struct mitsu70x_ctx *ctx = vctx;
int i, remain;
struct mitsu70x_hdr mhdr;
uint32_t planelen;
if (!ctx)
return CUPS_BACKEND_FAILED;
@ -663,13 +677,12 @@ repeat:
}
#ifdef ENABLE_CORRTABLES
ctx->raw_format = 1; // XXX until we define a new spool format for
// the data. Maybe reuse D90 header?
ctx->raw_format = !mhdr.mode;
/* Figure out the correction data table to use */
if (ctx->type == P_MITSU_D70X) {
ctx->laminatefname = "D70MAT01.raw";
ctx->lutfname = "CPD70L01.lut";
ctx->laminatefname = CORRTABLE_PATH "/D70MAT01.raw";
ctx->lutfname = CORRTABLE_PATH "/CPD70L01.lut";
if (mhdr.speed == 3) {
ctx->corrdata = &CPD70S01_data;
@ -682,8 +695,8 @@ repeat:
ctx->corrdatalens = &CPD70N01_lengths;
}
} else if (ctx->type == P_MITSU_D80) {
ctx->laminatefname = "D80MAT01.raw";
ctx->lutfname = "CPD80L01.lut";
ctx->laminatefname = CORRTABLE_PATH "/D80MAT01.raw";
ctx->lutfname = CORRTABLE_PATH "/CPD80L01.lut";
if (mhdr.speed == 3) {
ctx->corrdata = &CPD80S01_data;
@ -697,8 +710,8 @@ repeat:
}
// XXX what about CPD80**E**01?
} else if (ctx->type == P_MITSU_K60) {
ctx->laminatefname = "S60MAT02.raw";
ctx->lutfname = "CPS60L01.lut";
ctx->laminatefname = CORRTABLE_PATH "/S60MAT02.raw";
ctx->lutfname = CORRTABLE_PATH "/CPS60L01.lut";
if (mhdr.speed == 3 || mhdr.speed == 4) {
ctx->corrdata = &CPS60T03_data;
@ -709,8 +722,8 @@ repeat:
}
} else if (ctx->type == P_KODAK_305) {
ctx->laminatefname = "EK305MAT.raw"; // Same as K60
ctx->lutfname = "EK305L01.lut";
ctx->laminatefname = CORRTABLE_PATH "/EK305MAT.raw"; // Same as K60
ctx->lutfname = CORRTABLE_PATH "/EK305L01.lut";
if (mhdr.speed == 3 || mhdr.speed == 4) {
ctx->corrdata = &EK305T03_data;
@ -720,8 +733,8 @@ repeat:
ctx->corrdatalens = &EK305T01_lengths;
}
} else if (ctx->type == P_FUJI_ASK300) {
ctx->laminatefname = "ASK300M2.raw"; // Same as D70
ctx->lutfname = "CPD70L01.lut"; // XXX guess!
ctx->laminatefname = CORRTABLE_PATH "/ASK300M2.raw"; // Same as D70
ctx->lutfname = CORRTABLE_PATH "/CPD70L01.lut"; // XXX guess, driver did not come with external LUT.
if (mhdr.speed == 3 || mhdr.speed == 4) {
ctx->corrdata = &ASK300T3_data;
@ -731,15 +744,20 @@ repeat:
ctx->corrdatalens = &ASK300T1_lengths;
}
}
if (!mhdr.use_lut)
ctx->lutfname = NULL;
/* Clean up header back to pristine. */
mhdr.use_lut = 0;
mhdr.mode = 0;
#endif
/* Work out printjob size */
/* Work out total printjob size */
ctx->cols = be16_to_cpu(mhdr.cols);
ctx->rows = be16_to_cpu(mhdr.rows);
remain = ctx->rows * ctx->cols * 2;
remain = (remain + 511) / 512 * 512; /* Round to nearest 512 bytes. */
remain *= 3; /* One for each plane */
planelen = ctx->rows * ctx->cols * 2;
planelen = (planelen + 511) / 512 * 512; /* Round to nearest 512 bytes. */
if (!mhdr.laminate && mhdr.laminate_mode) {
i = be16_to_cpu(mhdr.lamcols) * be16_to_cpu(mhdr.lamrows) * 2;
@ -747,43 +765,26 @@ repeat:
ctx->matte = i;
}
ctx->databuf = malloc(sizeof(mhdr) + remain + ctx->matte);
remain = 3 * planelen + ctx->matte;
ctx->datalen = 0;
ctx->databuf = malloc(sizeof(mhdr) + remain);
if (!ctx->databuf) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_FAILED;
}
memcpy(ctx->databuf, &mhdr, sizeof(mhdr));
memcpy(ctx->databuf + ctx->datalen, &mhdr, sizeof(mhdr));
ctx->datalen += sizeof(mhdr);
#ifndef ENABLE_CORRTABLES
/* Read matte from spool... */
remain += ctx->matte;
#endif
/* Read in the spool data */
while(remain) {
i = read(data_fd, ctx->databuf + ctx->datalen, remain);
if (i == 0)
return CUPS_BACKEND_CANCEL;
if (i < 0)
return CUPS_BACKEND_CANCEL;
ctx->datalen += i;
remain -= i;
}
#ifdef ENABLE_CORRTABLES
/* Read matte from matte file */
if (!ctx->raw_format && ctx->matte) {
int fd;
fd = open(ctx->laminatefname, O_RDONLY);
if (fd < 0) {
ERROR("Unable to open matte lamination data file '%s'\n", ctx->laminatefname);
return CUPS_BACKEND_CANCEL;
}
remain = ctx->matte;
while (remain) {
i = read(fd, ctx->databuf + ctx->datalen, remain);
if (ctx->raw_format) { /* RAW MODE */
#endif
DEBUG("Reading in %d bytes of 16bpp YMCL data\n", remain);
/* Read in the spool data */
while(remain) {
i = read(data_fd, ctx->databuf + ctx->datalen, remain);
if (i == 0)
return CUPS_BACKEND_CANCEL;
if (i < 0)
@ -791,9 +792,103 @@ repeat:
ctx->datalen += i;
remain -= i;
}
#ifdef ENABLE_CORRTABLES
} else { /* RAW MODE OFF */
int spoolbuflen = 0;
uint8_t *spoolbuf;
remain = ctx->rows * ctx->cols * 3;
DEBUG("Reading in %d bytes of 8bpp BGR data\n", remain);
spoolbuflen = 0; spoolbuf = malloc(remain);
if (!spoolbuf) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_FAILED;
}
/* Read in the BGR data */
while (remain) {
i = read(data_fd, spoolbuf + spoolbuflen, remain);
if (i == 0)
return CUPS_BACKEND_CANCEL;
if (i < 0)
return CUPS_BACKEND_CANCEL;
spoolbuflen += i;
remain -= i;
}
/* Run through basic LUT, if present and enabled */
if (ctx->lutfname) {
DEBUG("Running print data through LUT\n");
uint8_t *buf = malloc(LUT_LEN);
if (!buf) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_FAILED;
}
if (CColorConv3D_Get3DColorTable(buf, ctx->lutfname)) {
ERROR("Unable to open LUT file '%s'\n", ctx->lutfname);
return CUPS_BACKEND_CANCEL;
}
CColorConv3D_Load3DColorTable(&ctx->lut, buf);
free(buf);
CColorConv3D_DoColorConv(&ctx->lut, spoolbuf, ctx->cols, ctx->rows, ctx->cols * 3, 1);
// XXX proprietary lib also does gamma+contrast+brightness
}
/* Convert to YMC using corrtables */
// XXX INSERT ALGORITHM HERE...
{
uint32_t r, c;
uint32_t in = 0, out = 0;
uint16_t *offset_y = (uint16_t*)(ctx->databuf + ctx->datalen);
uint16_t *offset_m = offset_y + planelen/2;
uint16_t *offset_c = offset_m + planelen/2;
// uint16_t *offset_l = offset_c + planelen/2;
DEBUG("Running print data through BGR->YMC table (crude)\n");
for(r = 0 ; r < ctx->rows; r++) {
for (c = 0 ; c < ctx->cols ; c++) {
offset_y[out] = cpu_to_be16(ctx->corrdata->gnmby[spoolbuf[in]]);
offset_m[out] = cpu_to_be16(ctx->corrdata->gnmgm[spoolbuf[in + 1]]);
offset_c[out] = cpu_to_be16(ctx->corrdata->gnmrc[spoolbuf[in + 2]]);
in += 3;
out++;
}
}
}
/* Move up the pointer */
ctx->datalen += 3*planelen;
/* Clean up */
free(spoolbuf);
/* Now that we've filled everything in, read latte from file */
if (ctx->matte) {
int fd;
DEBUG("Reading %d bytes of matte data from disk\n", ctx->matte);
fd = open(ctx->laminatefname, O_RDONLY);
if (fd < 0) {
ERROR("Unable to open matte lamination data file '%s'\n", ctx->laminatefname);
return CUPS_BACKEND_CANCEL;
}
remain = ctx->matte;
while (remain) {
i = read(fd, ctx->databuf + ctx->datalen, remain);
if (i == 0) {
/* We hit EOF, restart from beginning */
lseek(fd, 0, SEEK_SET);
continue;
}
if (i < 0)
return CUPS_BACKEND_CANCEL;
ctx->datalen += i;
remain -= i;
}
}
}
#endif
return CUPS_BACKEND_OK;
}
@ -1400,7 +1495,7 @@ static int mitsu70x_cmdline_arg(void *vctx, int argc, char **argv)
/* Exported */
struct dyesub_backend mitsu70x_backend = {
.name = "Mitsubishi CP-D70/D707/K60/D80",
.version = "0.41WIP",
.version = "0.42WIP",
.uri_prefix = "mitsu70x",
.cmdline_usage = mitsu70x_cmdline,
.cmdline_arg = mitsu70x_cmdline_arg,