Compare commits

...

4 commits

Author SHA1 Message Date
Solomon Peachy 123a357a73 mitsud90: Use BACKEND_FLAG_DUMMYPRINT for testing M1 processing
...This way the full pipeline can be used.
2024-01-11 22:11:30 -05:00
Solomon Peachy 1aebde2715 mitsud90: Fix typo in a panorama check 2024-01-11 22:05:30 -05:00
Solomon Peachy 341f48dcaa Revert "mitsud90: Move all image processing to before pano splitting"
This reverts commit 69344f821a.
2024-01-11 22:04:25 -05:00
Solomon Peachy 981ba9acd4 Revert "mitsu70x: Move full image procesisng pipeline into read_parse"
This reverts commit 81193f9675.

It breaks job combining
2024-01-11 22:03:52 -05:00
2 changed files with 226 additions and 221 deletions

View file

@ -1,7 +1,7 @@
/*
* Mitsubishi CP-D70/D707 Photo Printer CUPS backend
*
* (c) 2013-2024 Solomon Peachy <pizza@shaftnet.org>
* (c) 2013-2023 Solomon Peachy <pizza@shaftnet.org>
*
* The latest version of this program can be found at:
*
@ -1108,53 +1108,55 @@ repeat:
job->datalen += i;
remain -= i;
}
} else { /* Non-RAW mode! */
remain = job->rows * job->cols * 3;
DEBUG("Reading in %d bytes of 8bpp BGR data\n", remain);
goto bypass_raw;
}
job->spoolbuflen = 0;
job->spoolbuf = malloc(remain);
if (!job->spoolbuf) {
ERROR("Memory allocation failure!\n");
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_RETRY_CURRENT;
}
/* Non-RAW mode! */
remain = job->rows * job->cols * 3;
DEBUG("Reading in %d bytes of 8bpp BGR data\n", remain);
/* Read in the BGR data */
while (remain) {
i = read(data_fd, job->spoolbuf + job->spoolbuflen, remain);
if (i == 0) {
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
if (i < 0) {
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
job->spoolbuflen += i;
remain -= i;
}
job->spoolbuflen = 0;
job->spoolbuf = malloc(remain);
if (!job->spoolbuf) {
ERROR("Memory allocation failure!\n");
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_RETRY_CURRENT;
}
if (!ctx->lib.dl_handle) {
ERROR("!!! Image Processing Library not found, aborting!\n");
/* Read in the BGR data */
while (remain) {
i = read(data_fd, job->spoolbuf + job->spoolbuflen, remain);
if (i == 0) {
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
if (i < 0) {
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
job->spoolbuflen += i;
remain -= i;
}
/* Run through basic LUT, if present and enabled */
if (job->lutfname) {
int ret = mitsu_apply3dlut_packed(&ctx->lib, job->lutfname,
job->spoolbuf, job->cols,
job->rows, job->cols * 3,
COLORCONV_BGR);
if (ret) {
mitsu70x_cleanup_job(job);
return ret;
}
if (!ctx->lib.dl_handle) {
ERROR("!!! Image Processing Library not found, aborting!\n");
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
/* Run through basic LUT, if present and enabled */
if (job->lutfname) {
int ret = mitsu_apply3dlut_packed(&ctx->lib, job->lutfname,
job->spoolbuf, job->cols,
job->rows, job->cols * 3,
COLORCONV_BGR);
if (ret) {
mitsu70x_cleanup_job(job);
return ret;
}
}
/* Validate size and deck placement */
bypass_raw:
for (i = 0 ; i < ctx->num_decks ; i++) {
switch (ctx->medias[i]) {
case 0x0: // 4x8 (DS480 only)
@ -1239,101 +1241,6 @@ repeat:
}
}
/* Process RGB data if needed */
if (!job->raw_format) {
struct BandImage input;
uint8_t rew[2] = { 1, 1 }; /* 1 for rewind ok (default!) */
/* Load in the CPC file, if needed */
if (job->cpcfname && job->cpcfname != ctx->last_cpcfname) {
char full[2048];
ctx->last_cpcfname = job->cpcfname;
if (ctx->lib.cpcdata)
ctx->lib.DestroyCPCData(ctx->lib.cpcdata);
snprintf(full, sizeof(full), "%s/%s", corrtable_path, job->cpcfname);
ctx->lib.cpcdata = ctx->lib.GetCPCData(full);
if (!ctx->lib.cpcdata) {
ERROR("Unable to load CPC file '%s'\n", full);
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
}
/* Load in the secondary CPC, if needed */
if (job->ecpcfname != ctx->last_ecpcfname) {
char full[2048];
ctx->last_ecpcfname = job->ecpcfname;
if (ctx->lib.ecpcdata)
ctx->lib.DestroyCPCData(ctx->lib.ecpcdata);
snprintf(full, sizeof(full), "%s/%s", corrtable_path, job->ecpcfname);
if (job->ecpcfname) {
ctx->lib.ecpcdata = ctx->lib.GetCPCData(full);
if (!ctx->lib.ecpcdata) {
ERROR("Unable to load CPC file '%s'\n", full);
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
} else {
ctx->lib.ecpcdata = NULL;
}
}
/* Convert using image processing library */
input.origin_rows = input.origin_cols = 0;
input.rows = job->rows;
input.cols = job->cols;
input.imgbuf = job->spoolbuf;
input.bytes_per_row = job->cols * 3;
ctx->output.origin_rows = ctx->output.origin_cols = 0;
ctx->output.rows = job->rows;
ctx->output.cols = job->cols;
ctx->output.imgbuf = job->databuf + job->datalen;
ctx->output.bytes_per_row = job->cols * 3 * 2;
DEBUG("Running print data through processing library\n");
if (ctx->lib.DoImageEffect(ctx->lib.cpcdata, ctx->lib.ecpcdata,
&input, &ctx->output, job->sharpen, job->reverse, rew)) {
ERROR("Image Processing failed, aborting!\n");
mitsu70x_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
/* Twiddle rewind stuff if needed */
if (ctx->conn->type != P_MITSU_D70X) {
mhdr.rewind[0] = !rew[0];
mhdr.rewind[1] = !rew[1];
DEBUG("Rewind Inhibit? %02x %02x\n", mhdr.rewind[0], mhdr.rewind[1]);
}
/* Move up the pointer to after the image data */
job->datalen += 3*job->planelen;
/* Clean up */
free(job->spoolbuf);
job->spoolbuf = NULL;
job->spoolbuflen = 0;
/* Now that we've filled everything in, read matte from file */
if (job->matte) {
int ret = mitsu_readlamdata(job->laminatefname, LAMINATE_STRIDE,
job->databuf, &job->datalen,
be16_to_cpu(mhdr.lamrows), be16_to_cpu(mhdr.lamcols), 2);
if (ret) {
mitsu70x_cleanup_job(job);
return ret;
}
/* Zero out the tail end of the buffer. */
ret = be16_to_cpu(mhdr.lamcols) * be16_to_cpu(mhdr.lamrows) * 2;
memset(job->databuf + job->datalen, 0, job->matte - ret);
}
}
/* Return what we found */
*vjob = job;
@ -1874,6 +1781,101 @@ static int mitsu70x_main_loop(void *vctx, const void *vjob, int wait_for_return)
/* Keep track of deck requested */
reqdeck = hdr->deck;
if (job->raw_format)
goto bypass;
struct BandImage input;
uint8_t rew[2] = { 1, 1 }; /* 1 for rewind ok (default!) */
/* Load in the CPC file, if needed */
if (job->cpcfname && job->cpcfname != ctx->last_cpcfname) {
char full[2048];
ctx->last_cpcfname = job->cpcfname;
if (ctx->lib.cpcdata)
ctx->lib.DestroyCPCData(ctx->lib.cpcdata);
snprintf(full, sizeof(full), "%s/%s", corrtable_path, job->cpcfname);
ctx->lib.cpcdata = ctx->lib.GetCPCData(full);
if (!ctx->lib.cpcdata) {
ERROR("Unable to load CPC file '%s'\n", full);
return CUPS_BACKEND_CANCEL;
}
}
/* Load in the secondary CPC, if needed */
if (job->ecpcfname != ctx->last_ecpcfname) {
char full[2048];
ctx->last_ecpcfname = job->ecpcfname;
if (ctx->lib.ecpcdata)
ctx->lib.DestroyCPCData(ctx->lib.ecpcdata);
snprintf(full, sizeof(full), "%s/%s", corrtable_path, job->ecpcfname);
if (job->ecpcfname) {
ctx->lib.ecpcdata = ctx->lib.GetCPCData(full);
if (!ctx->lib.ecpcdata) {
ERROR("Unable to load CPC file '%s'\n", full);
return CUPS_BACKEND_CANCEL;
}
} else {
ctx->lib.ecpcdata = NULL;
}
}
/* Convert using image processing library */
input.origin_rows = input.origin_cols = 0;
input.rows = job->rows;
input.cols = job->cols;
input.imgbuf = job->spoolbuf;
input.bytes_per_row = job->cols * 3;
ctx->output.origin_rows = ctx->output.origin_cols = 0;
ctx->output.rows = job->rows;
ctx->output.cols = job->cols;
ctx->output.imgbuf = job->databuf + job->datalen;
ctx->output.bytes_per_row = job->cols * 3 * 2;
DEBUG("Running print data through processing library\n");
if (ctx->lib.DoImageEffect(ctx->lib.cpcdata, ctx->lib.ecpcdata,
&input, &ctx->output, job->sharpen, job->reverse, rew)) {
ERROR("Image Processing failed, aborting!\n");
return CUPS_BACKEND_CANCEL;
}
/* Twiddle rewind stuff if needed */
if (ctx->conn->type != P_MITSU_D70X) {
hdr->rewind[0] = !rew[0];
hdr->rewind[1] = !rew[1];
DEBUG("Rewind Inhibit? %02x %02x\n", hdr->rewind[0], hdr->rewind[1]);
}
/* Move up the pointer to after the image data */
job->datalen += 3*job->planelen;
/* Clean up */
free(job->spoolbuf);
job->spoolbuf = NULL;
job->spoolbuflen = 0;
/* Now that we've filled everything in, read matte from file */
if (job->matte) {
ret = mitsu_readlamdata(job->laminatefname, LAMINATE_STRIDE,
job->databuf, &job->datalen,
be16_to_cpu(hdr->lamrows), be16_to_cpu(hdr->lamcols), 2);
if (ret)
return ret;
/* Zero out the tail end of the buffer. */
ret = be16_to_cpu(hdr->lamcols) * be16_to_cpu(hdr->lamrows) * 2;
memset(job->databuf + job->datalen, 0, job->matte - ret);
}
bypass:
/* Bypass */
if (test_mode >= TEST_MODE_NOPRINT)
return CUPS_BACKEND_OK;
INFO("Waiting for printer idle...\n");
/* Ensure printer is awake */
@ -2616,7 +2618,8 @@ static const char *mitsu70x_prefixes[] = {
/* Exported */
const struct dyesub_backend mitsu70x_backend = {
.name = "Mitsubishi CP-D70 family",
.version = "0.109" " (lib " LIBMITSU_VER ")",
.version = "0.108" " (lib " LIBMITSU_VER ")",
.flags = BACKEND_FLAG_DUMMYPRINT,
.uri_prefixes = mitsu70x_prefixes,
.cmdline_usage = mitsu70x_cmdline,
.cmdline_arg = mitsu70x_cmdline_arg,

View file

@ -1003,31 +1003,6 @@ static int mitsud90_panorama_splitjob(struct mitsud90_printjob *injob, struct mi
overlap_rows, pad_rows,
panel_rows, panels);
return CUPS_BACKEND_OK;
}
static int cpm1_fillmatte(struct mitsud90_printjob *job)
{
int ret;
int rows, cols;
struct mitsud90_plane_hdr *phdr = (struct mitsud90_plane_hdr *) job->databuf;
rows = be16_to_cpu(job->hdr.rows) + 12;
cols = be16_to_cpu(job->hdr.cols);
/* Fill in matte data */
ret = mitsu_readlamdata(CPM1_LAMINATE_FILE, CPM1_LAMINATE_STRIDE,
job->databuf, &job->datalen,
rows, cols, 1);
if (ret)
return ret;
/* Update plane header and overall length */
phdr->lamcols = cpu_to_be16(cols);
phdr->lamrows = cpu_to_be16(rows);
return CUPS_BACKEND_OK;
}
@ -1101,6 +1076,7 @@ static int mitsud90_read_parse(void *vctx, const void **vjob, int data_fd, int c
job->is_pano = 1;
job->hdr.pano.on = 0;
}
} else if (ctx->conn->type == P_MITSU_W5000) {
struct mitsuw5k_job_hdr *hdr = (struct mitsuw5k_job_hdr*) &job->hdr;
@ -1252,7 +1228,7 @@ read_data:
}
}
/* Apply 3D Lut if requested and the printer can't handle it */
/* CP-M1 has... other considerations */
if (((ctx->conn->type == P_MITSU_M1 ||
ctx->conn->type == P_FUJI_ASK500) && !job->is_raw) ||
(ctx->conn->type == P_MITSU_D90 && job->is_pano)) {
@ -1290,12 +1266,91 @@ read_data:
job->hdr.colorcorr = 1; // XXX not sure if right for ASK500?
}
if (job->is_pano) {
int rval;
// XXX do any print sharpening here! If possible..
rval = mitsud90_panorama_splitjob(job, (struct mitsud90_printjob**)vjob);
/* Clean up original parsed job regardless */
mitsud90_cleanup_job(job);
return rval;
} else {
*vjob = job;
}
return CUPS_BACKEND_OK;
}
static int cpm1_fillmatte(struct mitsud90_printjob *job)
{
int ret;
int rows, cols;
struct mitsud90_plane_hdr *phdr = (struct mitsud90_plane_hdr *) job->databuf;
rows = be16_to_cpu(job->hdr.rows) + 12;
cols = be16_to_cpu(job->hdr.cols);
/* Fill in matte data */
ret = mitsu_readlamdata(CPM1_LAMINATE_FILE, CPM1_LAMINATE_STRIDE,
job->databuf, &job->datalen,
rows, cols, 1);
if (ret)
return ret;
/* Update plane header and overall length */
phdr->lamcols = cpu_to_be16(cols);
phdr->lamrows = cpu_to_be16(rows);
return CUPS_BACKEND_OK;
}
static int mitsud90_main_loop(void *vctx, const void *vjob, int wait_for_return) {
struct mitsud90_ctx *ctx = vctx;
struct mitsud90_status_resp resp;
uint8_t last_status[2] = {0xff, 0xff};
int sent;
int ret;
int copies;
struct mitsud90_printjob *job = (struct mitsud90_printjob *)vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (!job)
return CUPS_BACKEND_FAILED;
copies = job->common.copies;
/* Handle panorama state */
if (ctx->conn->type == P_MITSU_D90) {
if (job->hdr.pano.on) {
ctx->pano_page++;
if (be16_to_cpu(job->hdr.pano.page) != ctx->pano_page) {
ERROR("Invalid panorama state (page %d of %d)\n",
ctx->pano_page, be16_to_cpu(job->hdr.pano.page));
return CUPS_BACKEND_FAILED;
}
if (copies > 1) {
WARNING("Cannot print non-collated copies of a panorama job\n");
copies = 1;
}
} else if (ctx->pano_page) {
/* Clean up panorama state */
WARNING("Dangling panorama state!\n");
ctx->pano_page = 0;
}
} else {
ctx->pano_page = 0;
}
if ((ctx->conn->type == P_MITSU_M1 ||
ctx->conn->type == P_FUJI_ASK500) && !job->is_raw) {
struct BandImage input;
struct BandImage output;
struct M1CPCData *cpc;
int ret;
input.origin_rows = input.origin_cols = 0;
input.rows = be16_to_cpu(job->hdr.rows);
@ -1307,7 +1362,6 @@ read_data:
uint8_t *convbuf = malloc(input.rows * input.cols * sizeof(uint16_t) * 3 + (job->hdr.overcoat? (input.rows + 12) * input.cols + CPM1_LAMINATE_STRIDE / 2 : 0) + sizeof(struct mitsud90_plane_hdr));
if (!convbuf) {
ERROR("Memory allocation Failure!\n");
mitsud90_cleanup_job(job);
return CUPS_BACKEND_RETRY_CURRENT;
}
@ -1360,7 +1414,6 @@ read_data:
if (!cpc) {
ERROR("Cannot read data tables\n");
free(convbuf);
mitsud90_cleanup_job(job);
return CUPS_BACKEND_FAILED;
}
@ -1379,7 +1432,6 @@ read_data:
ERROR("CLocalEnhancer failed (out of memory?)\n");
free(convbuf);
ctx->lib.M1_DestroyCPCData(cpc);
mitsud90_cleanup_job(job);
return CUPS_BACKEND_RETRY_CURRENT;
}
}
@ -1417,60 +1469,9 @@ read_data:
}
}
if (job->is_pano) {
int rval;
// XXX do any print sharpening here! If possible..
rval = mitsud90_panorama_splitjob(job, (struct mitsud90_printjob**)vjob);
/* Clean up original parsed job regardless */
mitsud90_cleanup_job(job);
return rval;
} else {
*vjob = job;
}
return CUPS_BACKEND_OK;
}
static int mitsud90_main_loop(void *vctx, const void *vjob, int wait_for_return) {
struct mitsud90_ctx *ctx = vctx;
struct mitsud90_status_resp resp;
uint8_t last_status[2] = {0xff, 0xff};
int sent;
int ret;
int copies;
struct mitsud90_printjob *job = (struct mitsud90_printjob *)vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (!job)
return CUPS_BACKEND_FAILED;
copies = job->common.copies;
/* Handle panorama state */
if (ctx->conn->type == P_MITSU_D90) {
if (job->hdr.pano.on) {
ctx->pano_page++;
if (be16_to_cpu(job->hdr.pano.page) != ctx->pano_page) {
ERROR("Invalid panorama state (page %d of %d)\n",
ctx->pano_page, be16_to_cpu(job->hdr.pano.page));
return CUPS_BACKEND_FAILED;
}
if (copies > 1) {
WARNING("Cannot print non-collated copies of a panorama job\n");
copies = 1;
}
} else if (ctx->pano_page) {
/* Clean up panorama state */
WARNING("Dangling panorama state!\n");
ctx->pano_page = 0;
}
} else {
ctx->pano_page = 0;
}
/* Bypass */
if (test_mode >= TEST_MODE_NOPRINT)
return CUPS_BACKEND_OK;
INFO("Waiting for printer idle...\n");
@ -2428,6 +2429,7 @@ static const char *mitsud90_prefixes[] = {
const struct dyesub_backend mitsud90_backend = {
.name = "Mitsubishi CP-D90/CP-M1/CP-W5000",
.version = "0.48" " (lib " LIBMITSU_VER ")",
.flags = BACKEND_FLAG_DUMMYPRINT,
.uri_prefixes = mitsud90_prefixes,
.cmdline_arg = mitsud90_cmdline_arg,
.cmdline_usage = mitsud90_cmdline,
@ -2480,10 +2482,10 @@ const struct dyesub_backend mitsud90_backend = {
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 MM == 0 for no margin cut, 1 for margin cut
QQ RR SS HH VV 00 00 00 00 00 ZZ 00 JJ II 09 7c QQ == 02 matte (D90) or 03 (M1), 00 glossy,
09 4c 00 00 02 58 00 0c 00 06 00 00 00 00 00 00 RR == 00 auto, (D90: 03 == fine, 02 == superfine), (M1: 05 == Fast)
Z0 Z1 Z2 00 00 00 00 00 00 00 00 00 00 00 00 00 SS == 00 colorcorr, 01 == none (always 01 on M1 or D90 if LUT done in driver)
Z0 Z1 Z2 00 00 00 00 00 00 00 00 00 00 00 00 00 SS == 00 colorcorr, 01 == none (always 01 on M1)
HH/VV sharpening for Horiz/Vert, 0-8, 0 is off, 4 is normal (always 00 on M1)
TT is waittime (100 max, always 100 on D90)
ZZ is 0x02 on M1, D90 see PANORAMA below
ZZ is 0x02 on M1, D90 see below
Z0 is 0x01 (M1 windows) (00 Linux and d90 UNK!)
Z1 is RGB Rate (M1)
Z2 is OP Rate (M1)
@ -2499,7 +2501,7 @@ const struct dyesub_backend mitsud90_backend = {
9x6div3 == 2724 02 03 90 01 00 07 14 00 00 00 00 00 00
9x6div4 == 2628 03 02 97 01 00 05 22 00 00 07 ad 00 00
PANORAMA: from [ZZ 00 03 03] onwards, only shows in PANORAMA prints. Assume 2" overlap.
from [ZZ 00 03 03] onwards, only shows in 8x20" PANORAMA prints. Assume 2" overlap.
ZZ == 00 (normal) or 01 (panorama)
JJ == 02 03 (num of panorama panels)
II == 01 02 03 (which panel # in panorama!)