mitsu_m1: Move all image processing code into library.

master
Solomon Peachy 3 years ago
parent d8fdaa7841
commit 40312f5c0b
  1. 15
      backend_mitsu.c
  2. 24
      backend_mitsu.h
  3. 689
      backend_mitsud90.c
  4. 599
      lib70x/libMitsuD70ImageReProcess.c
  5. 25
      lib70x/libMitsuD70ImageReProcess.h

@ -53,6 +53,7 @@ int mitsu_loadlib(struct mitsu_lib *lib, int type)
return CUPS_BACKEND_FAILED;
}
lib->Get3DColorTable = DL_SYM(lib->dl_handle, "CColorConv3D_Get3DColorTable");
lib->Load3DColorTable = DL_SYM(lib->dl_handle, "CColorConv3D_Load3DColorTable");
lib->Destroy3DColorTable = DL_SYM(lib->dl_handle, "CColorConv3D_Destroy3DColorTable");
lib->DoColorConv = DL_SYM(lib->dl_handle, "CColorConv3D_DoColorConv");
@ -65,9 +66,21 @@ int mitsu_loadlib(struct mitsu_lib *lib, int type)
lib->CP98xx_DoConvert = DL_SYM(lib->dl_handle, "CP98xx_DoConvert");
lib->CP98xx_GetData = DL_SYM(lib->dl_handle, "CP98xx_GetData");
lib->CP98xx_DestroyData = DL_SYM(lib->dl_handle, "CP98xx_DestroyData");
if (!lib->Load3DColorTable ||
lib->M1_GetCPCData = DL_SYM(lib->dl_handle, "M1_GetCPCData");
lib->M1_DestroyCPCData = DL_SYM(lib->dl_handle, "M1_DestroyCPCData");
lib->M1_Gamma8to14 = DL_SYM(lib->dl_handle, "M1_Gamma8to14");
lib->M1_CLocalEnhancer = DL_SYM(lib->dl_handle, "M1_CLocalEnhancer");
lib->M1_CalcRGBRate = DL_SYM(lib->dl_handle, "M1_CalcRGBRate");
lib->M1_CalcOpRateMatte = DL_SYM(lib->dl_handle, "M1_CalcOpRateMatte");
lib->M1_CalcOpRateGloss = DL_SYM(lib->dl_handle, "M1_CalcOpRateGloss");
if (!lib->Get3DColorTable || !lib->Load3DColorTable ||
!lib->CP98xx_DoConvert || !lib->CP98xx_GetData ||
!lib->CP98xx_DestroyData ||
!lib->M1_GetCPCData || !lib->M1_DestroyCPCData ||
!lib->M1_Gamma8to14 || !lib->M1_CLocalEnhancer ||
!lib->M1_CalcOpRateMatte || !lib->M1_CalcOpRateGloss ||
!lib->M1_CalcRGBRate ||
!lib->Destroy3DColorTable || !lib->DoColorConv ||
!lib->GetCPCData || !lib->DestroyCPCData ||
!lib->DoImageEffect60 || !lib->DoImageEffect70 ||

@ -45,6 +45,7 @@ struct BandImage {
// @24
};
struct mitsu98xx_data; /* Forward declaration */
struct M1CPCData;
#endif
typedef int (*lib70x_getapiversionFN)(void);
@ -65,11 +66,23 @@ typedef int (*CP98xx_DoConvertFN)(const struct mitsu98xx_data *table,
typedef struct mitsu98xx_data *(*CP98xx_GetDataFN)(const char *filename);
typedef void (*CP98xx_DestroyDataFN)(const struct mitsu98xx_data *data);
typedef struct M1CPCData *(*M1_GetCPCDataFN)(const char *corrtable_path,
const char *filename,
const char *gammafilename);
typedef void (*M1_DestroyCPCDataFN)(struct M1CPCData *dat);
typedef void (*M1_Gamma8to14FN)(const struct M1CPCData *cpc,
const struct BandImage *in, struct BandImage *out);
typedef int (*M1_CLocalEnhancerFN)(const struct M1CPCData *cpc,
int sharp, struct BandImage *img);
typedef int (*M1_CalcRGBRateFN)(uint16_t rows, uint16_t cols, uint8_t *data);
typedef uint8_t (*M1_CalcOpRateMatteFN)(uint16_t rows, uint16_t cols, uint8_t *data);
typedef uint8_t (*M1_CalcOpRateGlossFN)(uint16_t rows, uint16_t cols);
#ifndef WITH_DYNAMIC
#warning "No dynamic loading support!"
#endif
#define REQUIRED_LIB_APIVERSION 5
#define REQUIRED_LIB_APIVERSION 6
#define LIBMITSU_VER "0.05"
@ -79,6 +92,7 @@ typedef void (*CP98xx_DestroyDataFN)(const struct mitsu98xx_data *data);
struct mitsu_lib {
void *dl_handle;
lib70x_getapiversionFN GetAPIVersion;
Get3DColorTableFN Get3DColorTable;
Load3DColorTableFN Load3DColorTable;
Destroy3DColorTableFN Destroy3DColorTable;
DoColorConvFN DoColorConv;
@ -92,7 +106,13 @@ struct mitsu_lib {
CP98xx_DoConvertFN CP98xx_DoConvert;
CP98xx_GetDataFN CP98xx_GetData;
CP98xx_DestroyDataFN CP98xx_DestroyData;
M1_GetCPCDataFN M1_GetCPCData;
M1_DestroyCPCDataFN M1_DestroyCPCData;
M1_CLocalEnhancerFN M1_CLocalEnhancer;
M1_Gamma8to14FN M1_Gamma8to14;
M1_CalcRGBRateFN M1_CalcRGBRate;
M1_CalcOpRateGlossFN M1_CalcOpRateGloss;
M1_CalcOpRateMatteFN M1_CalcOpRateMatte;
struct CColorConv3D *lut;
struct CPCData *cpcdata;
struct CPCData *ecpcdata;

@ -830,18 +830,30 @@ static int mitsud90_read_parse(void *vctx, const void **vjob, int data_fd, int c
return CUPS_BACKEND_OK;
}
struct M1CPCData;
static int M1_calc_rgbrate(uint16_t rows, uint16_t cols, uint8_t *data);
static uint8_t M1_calc_oprate_gloss(uint16_t rows, uint16_t cols);
static uint8_t M1_calc_oprate_matte(uint16_t rows, uint16_t cols, uint8_t *data);
static int cpm1_fillmatte(struct mitsud90_printjob *job);
static struct M1CPCData *get_M1CPCData(const char *filename,
const char *gammafilename);
static void free_M1CPCData(struct M1CPCData *dat);
static void M1_gamma8to14(const struct M1CPCData *cpc,
const struct BandImage *in, struct BandImage *out);
static int M1_CLocalEnhancer(const struct M1CPCData *cpc, int sharp,
struct BandImage *img);
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) {
struct mitsud90_ctx *ctx = vctx;
@ -888,12 +900,12 @@ static int mitsud90_main_loop(void *vctx, const void *vjob) {
memcpy(convbuf, job->databuf, sizeof(struct mitsud90_plane_hdr));
// Do CContrastConv prior to RGBRate
job->hdr.rgbrate = M1_calc_rgbrate(input.rows,
input.cols,
input.imgbuf);
job->hdr.rgbrate = ctx->lib.M1_CalcRGBRate(input.rows,
input.cols,
input.imgbuf);
// XXX CPC_G5_FNAME is never used by mitsu driver!?
cpc = get_M1CPCData(CPM1_CPC_FNAME, CPM1_CPC_G1_FNAME);
cpc = ctx->lib.M1_GetCPCData(corrtable_path, CPM1_CPC_FNAME, CPM1_CPC_G1_FNAME);
if (!cpc) {
ERROR("Cannot read data tables\n");
free(convbuf);
@ -901,7 +913,7 @@ static int mitsud90_main_loop(void *vctx, const void *vjob) {
}
/* Do gamma conversion */
M1_gamma8to14(cpc, &input, &output);
ctx->lib.M1_Gamma8to14(cpc, &input, &output);
if (job->hdr.sharp_h || job->hdr.sharp_v) {
/* 0 is off, 1-7 corresponds to level 0-6 */
@ -910,16 +922,16 @@ static int mitsud90_main_loop(void *vctx, const void *vjob) {
job->hdr.sharp_v = 0;
/* And do the sharpening */
if (M1_CLocalEnhancer(cpc, sharp, &output)) {
if (ctx->lib.M1_CLocalEnhancer(cpc, sharp, &output)) {
ERROR("CLocalEnhancer failed (out of memory?)\n");
free(convbuf);
free_M1CPCData(cpc);
ctx->lib.M1_DestroyCPCData(cpc);
return CUPS_BACKEND_RETRY_CURRENT;
}
}
/* We're done with the CPC data */
free_M1CPCData(cpc);
ctx->lib.M1_DestroyCPCData(cpc);
#if (__BYTE_ORDER == __BIG_ENDIAN)
/* Convert data to LITTLE ENDIAN if needed */
@ -942,12 +954,12 @@ static int mitsud90_main_loop(void *vctx, const void *vjob) {
mitsud90_cleanup_job(job);
return ret;
}
job->hdr.oprate = M1_calc_oprate_matte(output.rows,
output.cols,
ptr);
job->hdr.oprate = ctx->lib.M1_CalcOpRateMatte(output.rows,
output.cols,
ptr);
} else {
job->hdr.oprate = M1_calc_oprate_gloss(output.rows,
output.cols);
job->hdr.oprate = ctx->lib.M1_CalcOpRateGloss(output.rows,
output.cols);
}
}
@ -1659,11 +1671,9 @@ struct dyesub_backend mitsud90_backend = {
* job control (job id, active job, buffer status, etc)
* any sort of counters
* figure out "margin" parameter on the cut list
* finish M1 image processing code
* move M1 image processing code into lib70x
* sleep and waking up
* cut limit?
* put FW version into
* put FW version into stats structure
*/
/*
@ -1930,626 +1940,3 @@ Comms Protocol for D90 & CP-M1
*/
/* XXX XXX XXX CP-M1 series stuff */
#define M1CPCDATA_GAMMA_ROWS 256
#define M1CPCDATA_ROWS 7 /* Correlates to sharpening levels */
struct M1CPCData {
uint16_t GNMaB[M1CPCDATA_GAMMA_ROWS];
uint16_t GNMaG[M1CPCDATA_GAMMA_ROWS];
uint16_t GNMaR[M1CPCDATA_GAMMA_ROWS];
uint16_t EnHTH[M1CPCDATA_ROWS]; // fixed @96
uint16_t NoISetH[M1CPCDATA_ROWS]; // fixed @8
uint16_t NRGain[M1CPCDATA_ROWS]; // fixed @40
uint16_t NRTH[M1CPCDATA_ROWS]; // fixed @32
uint8_t NRK[M1CPCDATA_ROWS]; // fixed @1
uint16_t HDEnhGain[M1CPCDATA_ROWS]; // Varies!
uint16_t EnhDarkGain[M1CPCDATA_ROWS]; // Fixed @0
uint8_t DtctArea[M1CPCDATA_ROWS]; // Fixed @1
uint8_t CorCol[M1CPCDATA_ROWS]; // Fixed @2
uint8_t HighDownMode[M1CPCDATA_ROWS]; // Fixed @1
uint16_t HighTH[M1CPCDATA_ROWS]; // Fixed @800
double HighG[M1CPCDATA_ROWS]; // Fixed @0.1
};
/* Do the 8bpp->14bpp gamma conversion */
static void M1_gamma8to14(const struct M1CPCData *cpc,
const struct BandImage *in, struct BandImage *out)
{
int rows, cols, row, col;
const uint8_t *inp;
uint16_t *outp;
rows = in->rows - in->origin_rows;
cols = in->cols - in->origin_cols;
inp = in->imgbuf;
outp = (uint16_t*) out->imgbuf;
for (row = 0 ; row < rows ; row ++) {
for (col = 0 ; col < cols * 3 ; col+=3) {
outp[col] = cpc->GNMaR[inp[col]]; /* R */
outp[col+1] = cpc->GNMaG[inp[col+1]]; /* G */
outp[col+2] = cpc->GNMaB[inp[col+2]]; /* B */
}
inp += in->bytes_per_row;
outp += out->bytes_per_row / 2;
}
}
/* Sharpening! */
struct SIZE {
int32_t cx;
int32_t cy;
};
struct POINT {
uint32_t x;
uint32_t y;
};
/* Get all pixel values around a given point */
static void M1_GetAroundBrightness(const uint16_t *pSrcBrightness,
const struct SIZE *pSrcSize,
const struct POINT *pPtCenter,
uint16_t *pDstBrightness,
struct SIZE *pDstSize)
{
uint16_t center;
int32_t vert, horiz;
int32_t UVar1;
int32_t UVar2;
int bottom, right, top, left;
int i;
uint16_t *pBottomRight;
const uint16_t *pTopLeft;
int32_t col;
int32_t row;
uint16_t *pDstRow;
center = pSrcBrightness[pSrcSize->cx * pPtCenter->y + pPtCenter->x];
pDstRow = pDstBrightness + pDstSize->cx;
for (row = 0 ; row < pDstSize->cx ; row++) {
pDstBrightness[row] = center;
}
for (col = 1; col < pDstSize->cy; col++) {
memcpy(pDstRow, pDstBrightness, pDstSize->cx * sizeof(uint16_t));
pDstRow += pDstSize->cx;
}
vert = pPtCenter->x + (pDstSize->cx >> 1);
horiz = pPtCenter->y + (pDstSize->cy >> 1);
top = pPtCenter->x - vert;
bottom = 0;
if (top < 0) {
bottom = -top;
top = 0;
}
left = pPtCenter->y - horiz;
right = 0;
if (left < 0) {
right = -left;
left = 0;
}
if (pSrcSize->cx - 1 < vert) {
UVar1 = pDstSize->cx - ((vert - pSrcSize->cx) + 1);
} else {
UVar1 = pDstSize->cx;
}
if (pSrcSize->cy - 1 < horiz) {
UVar2 = pDstSize->cy - ((horiz - pSrcSize->cy) + 1);
} else {
UVar2 = pDstSize->cy;
}
pTopLeft = pSrcBrightness + pSrcSize->cx * left + top;
pBottomRight = pDstBrightness + pDstSize->cx * right + bottom;
for (i = right ; i < UVar2 ; i++) {
memcpy(pBottomRight, pTopLeft, (UVar1 - bottom) * sizeof(uint16_t));
pTopLeft = pTopLeft + pSrcSize->cx;
pBottomRight += pDstSize->cx;
}
return;
}
static const int16_t aroundMap08[9] = { 1, 1, 1,
1, 0, 1,
1, 1, 1};
static const int16_t aroundMap16[25] = { 0, 0, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 0, 1, 1,
0, 1, 1, 1, 1,
0, 1, 1, 0, 0 };
static const int16_t aroundMap64[81] = { 0, 0, 0, 1, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 5, 5, 1, 1, 0,
1, 1, 5, 5, 5, 5, 1, 1, 1,
1, 1, 5, 5, 1, 5, 5, 1, 1,
1, 1, 1, 5, 5, 5, 5, 1, 0,
0, 1, 1, 5, 5, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0 };
static double M1_GetBrightnessAverage(const uint16_t *pBitBrightness,
const struct SIZE *pSize,
const struct POINT *pPtCenter,
uint8_t dtctArea,
int32_t enhTh, int32_t noiseTh)
{
uint16_t srcPixel;
struct SIZE dtct;
uint16_t pDestBrightness [85];
uint16_t intPixel;
int32_t col, row;
uint16_t *pDestPtr;
uint16_t local_12 = 0;
uint32_t local_10 = 0;
const int16_t *aroundMapPtr;
const int16_t *aroundMap;
if (dtctArea == 0) {
aroundMap = aroundMap64;
dtct.cx = 9;
dtct.cy = 9;
} else if (dtctArea == 1) {
aroundMap = aroundMap16;
dtct.cx = 5;
dtct.cy = 5;
} else {
aroundMap = aroundMap08;
dtct.cx = 3;
dtct.cy = 3;
}
M1_GetAroundBrightness(pBitBrightness,pSize,pPtCenter,pDestBrightness,&dtct);
srcPixel = pBitBrightness[pSize->cx * pPtCenter->y + pPtCenter->x];
pDestPtr = pDestBrightness;
aroundMapPtr = aroundMap;
for (row = 0 ; row < dtct.cy ; row++) {
for (col = 0 ; col < dtct.cx ; col++) {
int32_t iVar1 = *pDestPtr - srcPixel;
if ((noiseTh + enhTh) < iVar1) {
intPixel = enhTh + srcPixel;
} else {
if (noiseTh < iVar1) {
intPixel = *pDestPtr - noiseTh;
} else if (-(noiseTh + enhTh) == iVar1 || -iVar1 < (noiseTh + enhTh)) {
intPixel = srcPixel;
if (-noiseTh != iVar1 && noiseTh <= -iVar1) {
intPixel = noiseTh + *pDestPtr;
}
} else {
intPixel = srcPixel - enhTh;
}
}
local_10 += *aroundMapPtr * intPixel;
local_12 += *aroundMapPtr;
pDestPtr++;
aroundMapPtr++;
}
}
return (double)local_10 / (double)local_12;
}
static int M1_CLocalEnhancer(const struct M1CPCData *cpc,
int sharp, struct BandImage *img)
{
struct SIZE size;
double NRK;
uint16_t *rowBuffer, *rowPtr;
uint16_t *inBasePtr, *inRowPtr, *inPixelPtr;
int row, col;
struct POINT pt;
int i;
double avgBrightness;
size.cx = img->cols - img->origin_cols;
size.cy = img->rows - img->origin_rows;
switch (cpc->NRK[sharp]) {
case 3:
NRK = 3.0;
break;
case 2:
NRK = 2.0;
break;
case 1:
NRK = 1.0;
break;
default:
NRK = 0.5;
break;
}
rowBuffer = malloc(size.cx * size.cy * 2);
if (!rowBuffer)
return CUPS_BACKEND_FAILED;
if (img->bytes_per_row < 0)
inBasePtr = img->imgbuf;
else
inBasePtr = img->imgbuf + (size.cy - 1) * img->bytes_per_row;
inRowPtr = inBasePtr;
rowPtr = rowBuffer;
/* Work out the luminence of each pixel */
for (col = 0 ; col < size.cy ; col ++) {
inPixelPtr = inRowPtr;
for (row = 0 ; row < size.cx ; row ++) {
*rowPtr = ((inPixelPtr[0] * 0.299 +
inPixelPtr[1] * 0.587 +
inPixelPtr[2] * 0.114) / 16.0) + 0.5;
inPixelPtr += 3;
rowPtr ++;
}
inRowPtr -= img->bytes_per_row / sizeof(int16_t);
}
inRowPtr = inBasePtr;
rowPtr = rowBuffer;
for (pt.y = 0 ; (int)pt.y < size.cy ; pt.y++) {
inPixelPtr = inRowPtr;
for (pt.x = 0 ; (int)pt.x < size.cx ; pt.x++) {
double outVals[3];
double dVar5;
double local_100, local_1b0, local_1b8;
uint8_t local_102, local_101;
uint16_t uVar2, uVar1;
memset(outVals, 0, sizeof(outVals));
/* Get the average brightness of each point */
avgBrightness = M1_GetBrightnessAverage(rowBuffer, &size, &pt,
cpc->DtctArea[sharp],
cpc->EnHTH[sharp],
cpc->NoISetH[sharp]);
/* Work out the amount of compensation for this point */
dVar5 = *rowPtr - avgBrightness;
if (dVar5 < 0.0) {
dVar5 *= -1.0;
}
if (dVar5 >= cpc->NRTH[sharp]) {
if (dVar5 >= cpc->NRTH[sharp] + cpc->NRGain[sharp] / NRK) {
dVar5 = 0.0;
} else {
dVar5 = cpc->NRGain[sharp] - NRK * (dVar5 - cpc->NRTH[sharp]);
}
} else {
dVar5 = cpc->NRGain[sharp];
}
dVar5 = ((cpc->HDEnhGain[sharp] + avgBrightness * cpc->EnhDarkGain[sharp]) - dVar5) / 32.0;
if (*rowPtr != 0) {
avgBrightness /= *rowPtr;
}
if (1.0 <= avgBrightness) {
local_1b0 = 1.00000000 - dVar5 * (avgBrightness - 1.0);
} else {
local_1b0 = dVar5 * (1.00000000 - avgBrightness) + 1.0;
}
if (0.0 <= local_1b0) {
if (local_1b0 <= 8.0) {
local_1b8 = local_1b0;
} else {
local_1b8 = 8.0;
}
} else {
local_1b8 = 0.0;
}
/* Work out relative pixel weights */
if (inPixelPtr[1] < inPixelPtr[2]) {
if (inPixelPtr[2] < *inPixelPtr) {
local_101 = 0;
local_102 = 1;
} else {
local_102 = inPixelPtr[1] < *inPixelPtr;
local_101 = 2;
}
} else {
if (inPixelPtr[1] < *inPixelPtr) {
local_101 = 0;
local_102 = 1;
} else {
if (inPixelPtr[2] < *inPixelPtr) {
local_102 = 1;
} else {
local_102 = 0;
}
local_101 = 1;
}
}
/* Figure out the per-pixel compensation */
uVar2 = inPixelPtr[(int)local_101];
uVar1 = inPixelPtr[(int)local_102];
if (1.0 <= local_1b0) {
local_100 = local_1b8;
} else {
if (cpc->CorCol[sharp] == 1) {
local_100 = 1.0 -
((1.0 - local_1b8) * (double)((0x4000 - (uint)uVar2) + (uint)uVar1)) / 16384.0;
} else if (cpc->CorCol[sharp] == 2) {
if ((int)(uVar2 - uVar1) < 0x2000) {
local_100 = 1.0 -
((1.0 - local_1b8) * (double)((0x2000 - (uint)uVar2) + (uint)uVar1)) / 16384.0;
} else {
local_100 = 1.0;
}
} else {
local_100 = local_1b8;
}
}
dVar5 = *rowPtr * local_100;
/* Apply the compensation to each point */
if (((local_100 <= 1.0) || (cpc->HighDownMode[sharp] != 1)) ||
(dVar5 <= cpc->HighTH[sharp])) {
for (i = 0 ; i < 3 ; i++) {
outVals[i] = inPixelPtr[i] * local_100;
}
} else {
double dVar4 = 1.0 -
((dVar5 - cpc->HighTH[sharp]) * cpc->HighG[sharp]) /
(0x400 - cpc->HighTH[sharp]);
if (*rowPtr <= dVar5 * dVar4) {
for (i = 0 ; i < 3 ; i++) {
outVals[i] = inPixelPtr[i] * local_100 * dVar4;
}
} else {
for (i = 0 ; i < 3 ; i++) {
outVals[i] = inPixelPtr[i];
}
}
}
/* Finally, spit out the final (capped) values */
for (i = 0 ; i < 3 ; i++) {
if (outVals[i] < 0)
inPixelPtr[i] = 0;
else if (outVals[i] > 0x3fff)
inPixelPtr[i] = 0x3fff;
else
inPixelPtr[i] = outVals[i];
}
inPixelPtr+=3;
rowPtr++;
}
inRowPtr -= img->bytes_per_row / sizeof(uint16_t);
}
free(rowBuffer);
return CUPS_BACKEND_OK;
}
/* Essentially this yields a fixed value for any given print size */
static uint8_t M1_calc_oprate_gloss(uint16_t rows, uint16_t cols)
{
double d;
rows += 12;
/* Do not know the significance of this magic number */
d = (((rows * cols * 0x80) / 1183483560.0) * 100.0) + 0.5;
/* Truncate to 8 bit integer */
return (uint8_t) d;
}
/* Assumes rowstride = cols */
static uint8_t M1_calc_oprate_matte(uint16_t rows, uint16_t cols, uint8_t *data)
{
uint64_t sum = 0;
int i;
double d;
for (i = 0 ; i < (rows * cols) ; i++) {
sum += data[i];
}
sum = (rows * cols * 0xff) - sum;
/* Do not know the significance of this magic number */
d = ((sum / 1183483560.0) * 100.0) + 0.5;
/* Truncate to 8 bit integer */
return (uint8_t)d;
}
/* Assumes rowstride = cols * 3 */
static int M1_calc_rgbrate(uint16_t rows, uint16_t cols, uint8_t *data)
{
uint64_t sum = 0;
int i;
double d;
for (i = 0 ; i < (rows * cols * 3) ; i++) {
sum += data[i];
}
sum = (rows * cols * 3 * 255) - sum;
d = ((sum / 3533449320.0) * 100) + 0.5;
return (uint8_t)d;
}
static void free_M1CPCData(struct M1CPCData *dat)
{
free(dat);
}
static struct M1CPCData *get_M1CPCData(const char *filename,
const char *gammafilename)
{
struct M1CPCData *data;
FILE *f;
char buf[4096];
int line;
char *ptr;
const char *delim = " ,\t\n\r";
if (!filename || !gammafilename)
return NULL;
data = malloc(sizeof(*data));
if (!data)
return NULL;
snprintf(buf, sizeof(buf), "%s/%s", corrtable_path, gammafilename);
f = fopen(buf, "r");
if (!f)
goto done_free;
/* Skip the first two rows */
for (line = 0 ; line < 2 ; line++) {
if (fgets(buf, sizeof(buf), f) == NULL)
goto abort;
}
/* Read in the row data */
for (line = 0 ; line < M1CPCDATA_GAMMA_ROWS ; line++) {
if (fgets(buf, sizeof(buf), f) == NULL)
goto abort;
ptr = strtok(buf, delim); // Always skip first column
if (!ptr)
goto abort;
/* Pull out the BGR mappings */
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->GNMaB[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->GNMaG[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->GNMaR[line] = strtol(ptr, NULL, 10);
};
fclose(f);
snprintf(buf, sizeof(buf), "%s/%s", corrtable_path, filename);
/* Now for the CPC Data */
f = fopen(buf, "r");
if (!f)
goto done_free;
/* Skip the first two rows */
for (line = 0 ; line < 2 ; line++) {
if (fgets(buf, sizeof(buf), f) == NULL)
goto abort;
}
/* Read in the row data */
for (line = 0 ; line < M1CPCDATA_ROWS ; line++) {
if (fgets(buf, sizeof(buf), f) == NULL)
goto abort;
ptr = strtok(buf, delim); // Always skip first column
if (!ptr)
goto abort;
/* Pull out the mappings */
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->EnHTH[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->NoISetH[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->NRGain[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->NRTH[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->NRK[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->HDEnhGain[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->EnhDarkGain[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->DtctArea[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->CorCol[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->HighDownMode[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->HighTH[line] = strtol(ptr, NULL, 10);
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->HighG[line] = strtod(ptr, NULL);
};
fclose(f);
return data;
abort:
fclose(f);
done_free:
free(data);
return NULL;
}
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;
}

@ -2325,3 +2325,602 @@ int CP98xx_DoConvert(const struct mitsu98xx_data *table,
return 1;
}
/* Mitsubishi CP-M1 family */
#define M1CPCDATA_GAMMA_ROWS 256
#define M1CPCDATA_ROWS 7 /* Correlates to sharpening levels */
struct M1CPCData {
uint16_t GNMaB[M1CPCDATA_GAMMA_ROWS];
uint16_t GNMaG[M1CPCDATA_GAMMA_ROWS];
uint16_t GNMaR[M1CPCDATA_GAMMA_ROWS];
uint16_t EnHTH[M1CPCDATA_ROWS]; // fixed @96
uint16_t NoISetH[M1CPCDATA_ROWS]; // fixed @8
uint16_t NRGain[M1CPCDATA_ROWS]; // fixed @40
uint16_t NRTH[M1CPCDATA_ROWS]; // fixed @32
uint8_t NRK[M1CPCDATA_ROWS]; // fixed @1
uint16_t HDEnhGain[M1CPCDATA_ROWS]; // Varies!
uint16_t EnhDarkGain[M1CPCDATA_ROWS]; // Fixed @0
uint8_t DtctArea[M1CPCDATA_ROWS]; // Fixed @1
uint8_t CorCol[M1CPCDATA_ROWS]; // Fixed @2
uint8_t HighDownMode[M1CPCDATA_ROWS]; // Fixed @1
uint16_t HighTH[M1CPCDATA_ROWS]; // Fixed @800
double HighG[M1CPCDATA_ROWS]; // Fixed @0.1
};
struct SIZE {
int32_t cx;
int32_t cy;
};
struct POINT {
uint32_t x;
uint32_t y;
};
/* Sharpening stuff */
static void M1_GetAroundBrightness(const uint16_t *pSrcBrightness,
const struct SIZE *pSrcSize,
const struct POINT *pPtCenter,
uint16_t *pDstBrightness,
struct SIZE *pDstSize)
{
uint16_t center;
int32_t vert, horiz;
int32_t UVar1;
int32_t UVar2;
int bottom, right, top, left;
int i;
uint16_t *pBottomRight;
const uint16_t *pTopLeft;
int32_t col;
int32_t row;
uint16_t *pDstRow;
center = pSrcBrightness[pSrcSize->cx * pPtCenter->y + pPtCenter->x];
pDstRow = pDstBrightness + pDstSize->cx;
for (row = 0 ; row < pDstSize->cx ; row++) {
pDstBrightness[row] = center;
}
for (col = 1; col < pDstSize->cy; col++) {
memcpy(pDstRow, pDstBrightness, pDstSize->cx * sizeof(uint16_t));
pDstRow += pDstSize->cx;
}
vert = pPtCenter->x + (pDstSize->cx >> 1);
horiz = pPtCenter->y + (pDstSize->cy >> 1);
top = pPtCenter->x - vert;
bottom = 0;
if (top < 0) {
bottom = -top;
top = 0;
}
left = pPtCenter->y - horiz;
right = 0;
if (left < 0) {
right = -left;
left = 0;
}
if (pSrcSize->cx - 1 < vert) {
UVar1 = pDstSize->cx - ((vert - pSrcSize->cx) + 1);
} else {
UVar1 = pDstSize->cx;
}
if (pSrcSize->cy - 1 < horiz) {
UVar2 = pDstSize->cy - ((horiz - pSrcSize->cy) + 1);
} else {
UVar2 = pDstSize->cy;
}
pTopLeft = pSrcBrightness + pSrcSize->cx * left + top;
pBottomRight = pDstBrightness + pDstSize->cx * right + bottom;
for (i = right ; i < UVar2 ; i++) {
memcpy(pBottomRight, pTopLeft, (UVar1 - bottom) * sizeof(uint16_t));
pTopLeft = pTopLeft + pSrcSize->cx;
pBottomRight += pDstSize->cx;
}
return;
}
static const int16_t aroundMap08[9] = { 1, 1, 1,
1, 0, 1,
1, 1, 1};
static const int16_t aroundMap16[25] = { 0, 0, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 0, 1, 1,
0, 1, 1, 1, 1,
0, 1, 1, 0, 0 };
static const int16_t aroundMap64[81] = { 0, 0, 0, 1, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 5, 5, 1, 1, 0,
1, 1, 5, 5, 5, 5, 1, 1, 1,
1, 1, 5, 5, 1, 5, 5, 1, 1,
1, 1, 1, 5, 5, 5, 5, 1, 0,
0, 1, 1, 5, 5, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0 };
static double M1_GetBrightnessAverage(const uint16_t *pBitBrightness,
const struct SIZE *pSize,
const struct POINT *pPtCenter,
uint8_t dtctArea,
int32_t enhTh, int32_t noiseTh)
{
uint16_t srcPixel;
struct SIZE dtct;
uint16_t pDestBrightness [85];
uint16_t intPixel;
int32_t col, row;
uint16_t *pDestPtr;
uint16_t local_12 = 0;
uint32_t local_10 = 0;
const int16_t *aroundMapPtr;
const int16_t *aroundMap;
if (dtctArea == 0) {
aroundMap = aroundMap64;
dtct.cx = 9;
dtct.cy = 9;
} else if (dtctArea == 1) {
aroundMap = aroundMap16;
dtct.cx = 5;
dtct.cy = 5;
} else {
aroundMap = aroundMap08;
dtct.cx = 3;
dtct.cy = 3;
}
M1_GetAroundBrightness(pBitBrightness,pSize,pPtCenter,pDestBrightness,&dtct);
srcPixel = pBitBrightness[pSize->cx * pPtCenter->y + pPtCenter->x];
pDestPtr = pDestBrightness;
aroundMapPtr = aroundMap;
for (row = 0 ; row < dtct.cy ; row++) {
for (col = 0 ; col < dtct.cx ; col++) {
int32_t iVar1 = *pDestPtr - srcPixel;
if ((noiseTh + enhTh) < iVar1) {
intPixel = enhTh + srcPixel;
} else {
if (noiseTh < iVar1) {
intPixel = *pDestPtr - noiseTh;
} else if (-(noiseTh + enhTh) == iVar1 || -iVar1 < (noiseTh + enhTh)) {
intPixel = srcPixel;
if (-noiseTh != iVar1 && noiseTh <= -iVar1) {
intPixel = noiseTh + *pDestPtr;
}
} else {
intPixel = srcPixel - enhTh;
}
}
local_10 += *aroundMapPtr * intPixel;
local_12 += *aroundMapPtr;
pDestPtr++;
aroundMapPtr++;
}
}
return (double)local_10 / (double)local_12;
}
int M1_CLocalEnhancer(const struct M1CPCData *cpc,
int sharp, struct BandImage *img)
{
struct SIZE size;
double NRK;
uint16_t *rowBuffer, *rowPtr;
uint16_t *inBasePtr, *inRowPtr, *inPixelPtr;
int row, col;
struct POINT pt;
int i;
double avgBrightness;
size.cx = img->cols - img->origin_cols;
size.cy = img->rows - img->origin_rows;
switch (cpc->NRK[sharp]) {
case 3:
NRK = 3.0;
break;
case 2:
NRK = 2.0;
break;
case 1:
NRK = 1.0;
break;
default:
NRK = 0.5;
break;
}
rowBuffer = malloc(size.cx * size.cy * 2);
if (!rowBuffer)
return -1;
if (img->bytes_per_row < 0)
inBasePtr = img->imgbuf;
else
inBasePtr = img->imgbuf + (size.cy - 1) * img->bytes_per_row;
inRowPtr = inBasePtr;
rowPtr = rowBuffer;
/* Work out the luminence of each pixel */
for (col = 0 ; col < size.cy ; col ++) {
inPixelPtr = inRowPtr;
for (row = 0 ; row < size.cx ; row ++) {
*rowPtr = ((inPixelPtr[0] * 0.299 +
inPixelPtr[1] * 0.587 +
inPixelPtr[2] * 0.114) / 16.0) + 0.5;
inPixelPtr += 3;
rowPtr ++;
}
inRowPtr -= img->bytes_per_row / sizeof(int16_t);
}
inRowPtr = inBasePtr;
rowPtr = rowBuffer;
for (pt.y = 0 ; (int)pt.y < size.cy ; pt.y++) {
inPixelPtr = inRowPtr;
for (pt.x = 0 ; (int)pt.x < size.cx ; pt.x++) {
double outVals[3];
double dVar5;
double local_100, local_1b0, local_1b8;
uint8_t local_102, local_101;
uint16_t uVar2, uVar1;
memset(outVals, 0, sizeof(outVals));
/* Get the average brightness of each point */
avgBrightness = M1_GetBrightnessAverage(rowBuffer, &size, &pt,
cpc->DtctArea[sharp],
cpc->EnHTH[sharp],
cpc->NoISetH[sharp]);
/* Work out the amount of compensation for this point */
dVar5 = *rowPtr - avgBrightness;
if (dVar5 < 0.0) {
dVar5 *= -1.0;
}
if (dVar5 >= cpc->NRTH[sharp]) {
if (dVar5 >= cpc->NRTH[sharp] + cpc->NRGain[sharp] / NRK) {
dVar5 = 0.0;
} else {
dVar5 = cpc->NRGain[sharp] - NRK * (dVar5 - cpc->NRTH[sharp]);
}
} else {
dVar5 = cpc->NRGain[sharp];
}
dVar5 = ((cpc->HDEnhGain[sharp] + avgBrightness * cpc->EnhDarkGain[sharp]) - dVar5) / 32.0;
if (*rowPtr != 0) {
avgBrightness /= *rowPtr;
}
if (1.0 <= avgBrightness) {
local_1b0 = 1.00000000 - dVar5 * (avgBrightness - 1.0);
} else {
local_1b0 = dVar5 * (1.00000000 - avgBrightness) + 1.0;
}
if (0.0 <= local_1b0) {
if (local_1b0 <= 8.0) {
local_1b8 = local_1b0;
} else {
local_1b8 = 8.0;
}
} else {
local_1b8 = 0.0;
}
/* Work out relative pixel weights */
if (inPixelPtr[1] < inPixelPtr[2]) {
if (inPixelPtr[2] < *inPixelPtr) {
local_101 = 0;
local_102 = 1;
} else {
local_102 = inPixelPtr[1] < *inPixelPtr;
local_101 = 2;
}
} else {
if (inPixelPtr[1] < *inPixelPtr) {
local_101 = 0;
local_102 = 1;
} else {
if (inPixelPtr[2] < *inPixelPtr) {
local_102 = 1;
} else {
local_102 = 0;
}
local_101 = 1;
}
}
/* Figure out the per-pixel compensation */
uVar2 = inPixelPtr[(int)local_101];
uVar1 = inPixelPtr[(int)local_102];
if (1.0 <= local_1b0) {
local_100 = local_1b8;
} else {
if (cpc->CorCol[sharp] == 1) {
local_100 = 1.0 -
((1.0 - local_1b8) * (double)((0x4000 - uVar2) + uVar1)) / 16384.0;
} else if (cpc->CorCol[sharp] == 2) {
if ((int)(uVar2 - uVar1) < 0x2000) {
local_100 = 1.0 -
((1.0 - local_1b8) * (double)((0x2000 - uVar2) + uVar1)) / 16384.0;
} else {
local_100 = 1.0;
}
} else {
local_100 = local_1b8;
}
}
dVar5 = *rowPtr * local_100;
/* Apply the compensation to each point */
if (((local_100 <= 1.0) || (cpc->HighDownMode[sharp] != 1)) ||
(dVar5 <= cpc->HighTH[sharp])) {
for (i = 0 ; i < 3 ; i++) {
outVals[i] = inPixelPtr[i] * local_100;
}
} else {
double dVar4 = 1.0 -
((dVar5 - cpc->HighTH[sharp]) * cpc->HighG[sharp]) /
(0x400 - cpc->HighTH[sharp]);
if (*rowPtr <= dVar5 * dVar4) {
for (i = 0 ; i < 3 ; i++) {
outVals[i] = inPixelPtr[i] * local_100 * dVar4;
}
} else {
for (i = 0 ; i < 3 ; i++) {
outVals[i] = inPixelPtr[i];
}
}
}
/* Finally, spit out the final (capped) values */
for (i = 0 ; i < 3 ; i++) {
if (outVals[i] < 0)
inPixelPtr[i] = 0;
else if (outVals[i] > 0x3fff)
inPixelPtr[i] = 0x3fff;
else
inPixelPtr[i] = outVals[i];
}
inPixelPtr+=3;
rowPtr++;
}
inRowPtr -= img->bytes_per_row / sizeof(uint16_t);
}
free(rowBuffer);
return 0;
}
/* Do the 8bpp->14bpp gamma conversion */
void M1_Gamma8to14(const struct M1CPCData *cpc,
const struct BandImage *in, struct BandImage *out)
{
int rows, cols, row, col;
const uint8_t *inp;
uint16_t *outp;
dump_announce();
rows = in->rows - in->origin_rows;
cols = in->cols - in->origin_cols;
inp = in->imgbuf;
outp = (uint16_t*) out->imgbuf;
for (row = 0 ; row < rows ; row ++) {
for (col = 0 ; col < cols * 3 ; col+=3) {
outp[col] = cpc->GNMaR[inp[col]]; /* R */
outp[col+1] = cpc->GNMaG[inp[col+1]]; /* G */
outp[col+2] = cpc->GNMaB[inp[col+2]]; /* B */
}
inp += in->bytes_per_row;
outp += out->bytes_per_row / 2;
}
}
/* Essentially this yields a fixed value for any given print size */
uint8_t M1_CalcOpRateGloss(uint16_t rows, uint16_t cols)
{
double d;
rows += 12;
/* Do not know the significance of this magic number */
d = (((rows * cols * 0x80) / 1183483560.0) * 100.0) + 0.5;
/* Truncate to 8 bit integer */
return (uint8_t) d;
}
/* Assumes rowstride = cols */
uint8_t M1_CalcOpRateMatte(uint16_t rows, uint16_t cols, uint8_t *data)
{
uint64_t sum = 0;
int i;
double d;
for (i = 0 ; i < (rows * cols) ; i++) {
sum += data[i];
}
sum = (rows * cols * 0xff) - sum;
/* Do not know the significance of this magic number */
d = ((sum / 1183483560.0) * 100.0) + 0.5;
/* Truncate to 8 bit integer */
return (uint8_t)d;
}
/* Assumes rowstride = cols * 3 */
int M1_CalcRGBRate(uint16_t rows, uint16_t cols, uint8_t *data)
{
uint64_t sum = 0;
int i;
double d;
for (i = 0 ; i < (rows * cols * 3) ; i++) {
sum += data[i];
}
sum = (rows * cols * 3 * 255) - sum;
d = ((sum / 3533449320.0) * 100) + 0.5;
return (uint8_t)d;
}
void M1_DestroyCPCData(struct M1CPCData *dat)
{
free(dat);
}
struct M1CPCData *M1_GetCPCData(const char *corrtable_path, const char *filename,
const char *gammafilename)
{
struct M1CPCData *data;
FILE *f;
char buf[4096];
int line;
char *ptr;
const char *delim = " ,\t\n\r";
if (!filename || !gammafilename)
return NULL;
data = malloc(sizeof(*data));
if (!data)
return NULL;
snprintf(buf, sizeof(buf), "%s/%s", corrtable_path, gammafilename);
f = fopen(buf, "r");
if (!f)
goto done_free;
/* Skip the first two rows */
for (line = 0 ; line < 2 ; line++) {
if (fgets(buf, sizeof(buf), f) == NULL)
goto abort;
}
/* Read in the row data */
for (line = 0 ; line < M1CPCDATA_GAMMA_ROWS ; line++) {
if (fgets(buf, sizeof(buf), f) == NULL)
goto abort;
ptr = strtok(buf, delim); // Always skip first column
if (!ptr)
goto abort;
/* Pull out the BGR mappings */
ptr = strtok(NULL, delim);
if (!ptr)
goto abort;
data->GNMaB[line] = strtol(ptr, NULL, 10);