mitsu70x: Major update.

Long story short, Library was sending rows in the wrong order, but to
 fix this, the row data needed to be reversed so the images weren't
 mirrored.

 Library given an extension (and API bump) to allow it to swap if
 necessary.  Backend tells library to swap unless Gutenprint is feeding
 data in that is in the correct order.

 For Gutenprint 5.2.12, this code will reverse the data.  Future
 Gutenprint releases will do the right thing so no swapping is needed.
This commit is contained in:
Solomon Peachy 2017-03-19 19:29:37 -04:00
parent 3d2e66a9df
commit 87683e610a
3 changed files with 85 additions and 88 deletions

View File

@ -84,7 +84,7 @@ struct BandImage {
};
#endif
#define REQUIRED_LIB_APIVERSION 3
#define REQUIRED_LIB_APIVERSION 4
/* Image processing library function prototypes */
#define LIB_NAME_RE "libMitsuD70ImageReProcess.so" // Reimplemented library
@ -96,7 +96,7 @@ typedef void (*Destroy3DColorTableFN)(struct CColorConv3D *this);
typedef void (*DoColorConvFN)(struct CColorConv3D *this, uint8_t *data, uint16_t cols, uint16_t rows, uint32_t bytes_per_row, int rgb_bgr);
typedef struct CPCData *(*get_CPCDataFN)(const char *filename);
typedef void (*destroy_CPCDataFN)(struct CPCData *data);
typedef int (*do_image_effectFN)(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, uint8_t rew[2]);
typedef int (*do_image_effectFN)(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, int reverse, uint8_t rew[2]);
typedef int (*send_image_dataFN)(struct BandImage *out, void *context,
int (*callback_fn)(void *context, void *buffer, uint32_t len));
@ -171,6 +171,7 @@ struct mitsu70x_ctx {
char *last_ecpcfname;
int raw_format;
int reverse;
int sharpen; /* ie mhdr.sharpen - 1 */
uint8_t rew[2]; /* 1 for rewind ok (default!) */
@ -375,8 +376,8 @@ struct mitsu70x_hdr {
uint8_t sharpen; /* 0-9. 5 is "normal", 0 is "off" */
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];
uint8_t reversed; /* 1 tells the backend the row data is correct */
uint8_t pad[447];
} __attribute__((packed));
/* Error dumps, etc */
@ -907,11 +908,13 @@ repeat:
ctx->lutfname = NULL;
ctx->sharpen = mhdr.sharpen - 1;
ctx->reverse = !mhdr.reversed;
/* Clean up header back to pristine. */
mhdr.use_lut = 0;
mhdr.mode = 0;
mhdr.sharpen = 0;
mhdr.reversed = 0;
/* Work out total printjob size */
ctx->cols = be16_to_cpu(mhdr.cols);
@ -1047,7 +1050,7 @@ repeat:
ctx->rew[0] = 1;
ctx->rew[1] = 1;
if (ctx->DoImageEffect(ctx->cpcdata, ctx->ecpcdata,
&input, &ctx->output, ctx->sharpen, ctx->rew)) {
&input, &ctx->output, ctx->sharpen, ctx->reverse, ctx->rew)) {
ERROR("Image Processing failed, aborting!\n");
return CUPS_BACKEND_CANCEL;
}
@ -1861,7 +1864,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.59",
.version = "0.60",
.uri_prefix = "mitsu70x",
.cmdline_usage = mitsu70x_cmdline,
.cmdline_arg = mitsu70x_cmdline_arg,

View File

@ -46,8 +46,7 @@
*/
#define LIB_VERSION "0.6"
#define LIB_APIVERSION 3
#define LIB_VERSION "0.7"
#include <stdio.h>
#include <stdint.h>
@ -55,6 +54,8 @@
#include <string.h>
#include <arpa/inet.h>
#include "libMitsuD70ImageReProcess.h"
#define UNUSED(expr) do { (void)(expr); } while (0)
//-------------------------------------------------------------------------
@ -95,7 +96,6 @@
//-------------------------------------------------------------------------
// Data declarations
#define LUT_LEN 14739
#define CPC_DATA_ROWS 2730
#define CHUNK_LEN (256*1024)
@ -104,17 +104,6 @@ struct CColorConv3D {
uint8_t lut[17][17][17][3];
};
/* Defines an image. Note that origin_cols/origin_rows should always = 0 */
struct BandImage {
void *imgbuf; // @ 0
int32_t bytes_per_row;// @ 4 bytes per row (respect 8bpp and 16bpp!)
uint16_t origin_cols; // @ 8 origin_cols
uint16_t origin_rows; // @12 origin_rows
uint16_t cols; // @16 cols
uint16_t rows; // @20 rows
// @24
};
/* State for image processing algorithm */
struct CImageEffect70 {
uint32_t pad; // @0
@ -138,12 +127,12 @@ struct CImageEffect70 {
uint32_t cur_row; // @4800/1200 // row index.
uint32_t band_pixels; // @4804/1201 // pixels per output band (always columns * 3)
uint32_t linebuf_stride; // @4808/1202 // band_pixels + 6 -- line buffer row stride
double unk_1203; // @4812/1203 // FH[0]
double unk_1205; // @4820/1205 // FH[1]
double unk_1207; // @4828/1207 // FH[2]
double unk_1209; // @4836/1209 // FH[3] - FH[2]
double unk_1211; // @4844/1211 // FH[4] - FH[3]
double unk_1213; // @4852/1213 // FH[4]
double fhdiv_up; // @4812/1203 // FH[0] // division factor for positive comp
double fhdiv_dn; // @4820/1205 // FH[1] // divison factor for negative comp
double fh_cur; // @4828/1207 // FH[2]
double fh_prev1; // @4836/1209 // FH[3] - FH[2]
double fh_prev2; // @4844/1211 // FH[4] - FH[3]
double fh_prev3; // @4852/1213 // FH[4]
// @4860/1215
};
@ -325,9 +314,6 @@ static void CColorConv3D_DoColorConvPixel(struct CColorConv3D *this, uint8_t *re
// printf("=> %d %d %d\n", *redp, *grnp, *blup);
}
#define COLORCONV_RGB 0
#define COLORCONV_BGR 1
/* Perform a total conversion on an entire image */
void CColorConv3D_DoColorConv(struct CColorConv3D *this, uint8_t *data, uint16_t cols, uint16_t rows, uint32_t stride, int rgb_bgr)
{
@ -519,8 +505,8 @@ static struct CImageEffect70 *CImageEffect70_Create(struct CPCData *cpc)
memset(data, 0, sizeof(*data));
data->sharpen = -1;
data->unk_1203 = 1.0;
data->unk_1205 = 1.0;
data->fhdiv_up = 1.0;
data->fhdiv_dn = 1.0;
data->cpc = cpc;
return data;
}
@ -691,11 +677,13 @@ static void CImageEffect70_CalcFCC(struct CImageEffect70 *data)
double s[3];
double *row_comp;
int i, j;
double *v12, *v11, *v10;
double *prev1, *prev2, *prev3;
/* Figure out where we need to be */
row_comp = &data->fcc_rowcomps[3*data->cur_row];
/* Initialize correction factor for this row based on the
buckets of HTD.. */
row_comp = &data->fcc_rowcomps[3*data->cur_row];
buckets that CalcHTD handed us */
for (j = 0 ; j < 3 ; j++) {
row_comp[j] = 127 * data->htd_fcc_scratch[j][127];
}
@ -706,40 +694,41 @@ static void CImageEffect70_CalcFCC(struct CImageEffect70 *data)
}
}
/* Set up pointers to adjacent rows */
/* Set up pointers to previous rows. Or if we're on the first
three rows, take special action. */
if (data->cur_row > 2) {
v12 = row_comp - 3;
v11 = row_comp - 6;
v10 = row_comp - 9;
prev1 = row_comp - 3;
prev2 = row_comp - 6;
prev3 = row_comp - 9;
} else if (data->cur_row == 2) {
v12 = row_comp - 3;
v11 = row_comp - 6;
v10 = row_comp - 6;
prev1 = row_comp - 3;
prev2 = row_comp - 6;
prev3 = row_comp - 6;
} else if (data->cur_row == 1) {
v12 = row_comp - 3;
v11 = row_comp - 3;
v10 = row_comp - 3;
prev1 = row_comp - 3;
prev2 = row_comp - 3;
prev3 = row_comp - 3;
} else {
v12 = row_comp;
v11 = row_comp;
v10 = row_comp;
prev1 = row_comp;
prev2 = row_comp;
prev3 = row_comp;
}
/* Foreach plane in the row, work out the global scaling factor. */
/* For each plane in the row, work out the global scaling factor */
for (i = 0 ; i < 3 ; i++) {
double v5;
/* Average it out over the number of columns */
row_comp[i] /= data->columns;
v5 = data->unk_1207 * row_comp[i]
+ data->unk_1209 * v12[i]
+ data->unk_1211 * v11[i]
- data->unk_1213 * v10[i];
v5 = data->fh_cur * row_comp[i]
+ data->fh_prev1 * prev1[i]
+ data->fh_prev2 * prev2[i]
- data->fh_prev3 * prev3[i];
/* Different factors for scaling up vs down */
if (v5 > 0.0) {
data->fcc_ymc_scale[i] = v5 / data->unk_1203 + 1.0;
data->fcc_ymc_scale[i] = v5 / data->fhdiv_up + 1.0;
} else {
data->fcc_ymc_scale[i] = v5 / data->unk_1205 + 1.0;
data->fcc_ymc_scale[i] = v5 / data->fhdiv_dn + 1.0;
}
}
@ -748,10 +737,10 @@ static void CImageEffect70_CalcFCC(struct CImageEffect70 *data)
memset(s, 0, sizeof(s));
for (i = 0 ; i < 128 ; i++) {
for (j = 0 ; j < 3 ; j++) {
int v3 = 255 * data->htd_fcc_scratch[j][i] / 1864;
if (v3 > 255)
v3 = 255;
s[j] += data->cpc->FM[v3];
int val = 255 * data->htd_fcc_scratch[j][i] / 1864;
if (val > 255)
val = 255;
s[j] += data->cpc->FM[val];
data->fcc_ymc_scratch[j][i] = s[j] / (i + 1);
}
}
@ -1081,12 +1070,12 @@ static void CImageEffect70_DoConv(struct CImageEffect70 *data,
struct BandImage *out,
int sharpen)
{
double v8[3];
double maxval[3];
double *v9 = NULL;
double *v10 = NULL;
uint32_t i, j;
int v12;
int offset;
int outstride;
uint16_t *outptr;
uint16_t *inptr;
@ -1097,12 +1086,12 @@ static void CImageEffect70_DoConv(struct CImageEffect70 *data,
sharpen = 8;
data->sharpen = sharpen;
data->unk_1203 = cpc->FH[0];
data->unk_1205 = cpc->FH[1];
data->unk_1207 = cpc->FH[2];
data->unk_1209 = cpc->FH[3] - cpc->FH[2];
data->unk_1211 = cpc->FH[4] - cpc->FH[3];
data->unk_1213 = cpc->FH[4];
data->fhdiv_up = cpc->FH[0];
data->fhdiv_dn = cpc->FH[1];
data->fh_cur = cpc->FH[2];
data->fh_prev1 = cpc->FH[3] - cpc->FH[2];
data->fh_prev2 = cpc->FH[4] - cpc->FH[3];
data->fh_prev3 = cpc->FH[4];
data->columns = in->cols - in->origin_cols;
data->rows = in->rows - in->origin_rows;
@ -1131,14 +1120,15 @@ static void CImageEffect70_DoConv(struct CImageEffect70 *data,
memset(v10, 0, (data->band_pixels * sizeof(double)));
v9 = malloc(data->band_pixels * sizeof(double));
memset(v9, 0, (data->band_pixels * sizeof(double)));
v8[0] = cpc->GNMby[255];
v8[1] = cpc->GNMgm[255];
v8[2] = cpc->GNMrc[255];
maxval[0] = cpc->GNMby[255];
maxval[1] = cpc->GNMgm[255];
maxval[2] = cpc->GNMrc[255];
v12 = 0;
/* Initialize ttd_htd structures */
offset = 0;
for(j = 0; j < data->columns ; j++) {
for (i = 0 ; i < 3 ; i++) {
data->ttd_htd_scratch[v12++] = v8[i];
data->ttd_htd_scratch[offset++] = maxval[i];
}
}
@ -1166,7 +1156,7 @@ static void CImageEffect70_DoConv(struct CImageEffect70 *data,
free(v9);
}
static void CImageEffect70_DoGamma(struct CImageEffect70 *data, struct BandImage *input, struct BandImage *out)
static void CImageEffect70_DoGamma(struct CImageEffect70 *data, struct BandImage *input, struct BandImage *out, int reverse)
{
int cols, rows;
int i, j;
@ -1188,15 +1178,22 @@ static void CImageEffect70_DoGamma(struct CImageEffect70 *data, struct BandImage
inptr = (uint8_t*) input->imgbuf;
outptr = out->imgbuf;
/* HACK: Reverse the row data when we perform gamma correction,
because Old Gutenprint sends it in the wrong order. */
for (i = 0; i < rows; i++) {
uint8_t *v10 = inptr;
uint16_t *v9 = (uint16_t*)outptr;
if (reverse)
v9 += (cols - 1) * 3;
for (j = 0 ; j < cols ; j++) {
v9[0] = cpc->GNMby[v10[0]];
v9[1] = cpc->GNMgm[v10[1]];
v9[2] = cpc->GNMrc[v10[2]];
v10 += 3;
v9 += 3;
if (reverse)
v9 -= 3;
else
v9 += 3;
}
inptr += in_stride;
outptr += out_stride;
@ -1212,7 +1209,7 @@ static void dump_announce(void)
fprintf(stderr, "INFO: *** This code is NOT supported or endorsed by Mitsubishi! ***\n");
}
int do_image_effect80(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, uint8_t rew[2])
int do_image_effect80(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, int reverse, uint8_t rew[2])
{
struct CImageEffect70 *data;
@ -1222,7 +1219,7 @@ int do_image_effect80(struct CPCData *cpc, struct CPCData *ecpc, struct BandImag
if (!data)
return -1;
CImageEffect70_DoGamma(data, input, output);
CImageEffect70_DoGamma(data, input, output, reverse);
/* Figure out if we can get away with rewinding, or not... */
if (cpc->REV[0]) {
@ -1251,7 +1248,7 @@ int do_image_effect80(struct CPCData *cpc, struct CPCData *ecpc, struct BandImag
if (!data)
return -1;
CImageEffect70_DoGamma(data, input, output);
CImageEffect70_DoGamma(data, input, output, reverse);
}
CImageEffect70_DoConv(data, cpc, output, output, sharpen);
@ -1261,7 +1258,7 @@ int do_image_effect80(struct CPCData *cpc, struct CPCData *ecpc, struct BandImag
return 0;
}
int do_image_effect60(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, uint8_t rew[2])
int do_image_effect60(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, int reverse, uint8_t rew[2])
{
struct CImageEffect70 *data;
@ -1273,7 +1270,7 @@ int do_image_effect60(struct CPCData *cpc, struct CPCData *ecpc, struct BandImag
if (!data)
return -1;
CImageEffect70_DoGamma(data, input, output);
CImageEffect70_DoGamma(data, input, output, reverse);
CImageEffect70_DoConv(data, cpc, output, output, sharpen);
/* Figure out if we can get away with rewinding, or not... */
@ -1297,7 +1294,7 @@ int do_image_effect60(struct CPCData *cpc, struct CPCData *ecpc, struct BandImag
return 0;
}
int do_image_effect70(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, uint8_t rew[2])
int do_image_effect70(struct CPCData *cpc, struct CPCData *ecpc, struct BandImage *input, struct BandImage *output, int sharpen, int reverse, uint8_t rew[2])
{
struct CImageEffect70 *data;
@ -1310,7 +1307,7 @@ int do_image_effect70(struct CPCData *cpc, struct CPCData *ecpc, struct BandImag
if (!data)
return -1;
CImageEffect70_DoGamma(data, input, output);
CImageEffect70_DoGamma(data, input, output, reverse);
CImageEffect70_DoConv(data, cpc, output, output, sharpen);
CImageEffect70_Destroy(data);
@ -1335,11 +1332,6 @@ int send_image_data(struct BandImage *out, void *context,
if (!callback_fn)
goto done;
// XXX hacky workaround. Doing this right results in the image
// being incorrectly mirrored. There's a missing step somewhere
// that flips each row. Until then, this stays in.
out->bytes_per_row = -out->bytes_per_row;
if (out->bytes_per_row > 0) {
v15 = out->imgbuf + ((rows - 1) * out->bytes_per_row);
} else {

View File

@ -49,6 +49,8 @@
#ifndef __MITSU_D70_H
#define __MITSU_D70_H
#define LIB_APIVERSION 4
#include <stdint.h>
/* Defines an image. Note that origin_cols/origin_rows should always = 0 */
@ -79,13 +81,13 @@ void destroy_CPCData(struct CPCData *data);
Returns 0 if successful, non-zero for error */
int do_image_effect70(struct CPCData *cpc, struct CPCData *ecpc,
struct BandImage *input, struct BandImage *output,
int sharpen, uint8_t rew[2]);
int sharpen, int reverse, uint8_t rew[2]);
int do_image_effect60(struct CPCData *cpc, struct CPCData *ecpc,
struct BandImage *input, struct BandImage *output,
int sharpen, uint8_t rew[2]);
int sharpen, int reverse, uint8_t rew[2]);
int do_image_effect80(struct CPCData *cpc, struct CPCData *ecpc,
struct BandImage *input, struct BandImage *output,
int sharpen, uint8_t rew[2]);
int sharpen, int reverse, uint8_t rew[2]);
/* Converts the packed 16bpp YMC image into 16bpp YMC planes, with
proper padding after each plane. Calls the callback function for each