#include "common.h"
#include "image.h"
#include "raster.h"
#include <unistd.h>
#include <math.h>
int Flip = 0,
XPosition = 0,
YPosition = 0,
Collate = 0,
Copies = 1;
int Floyd16x16[16][16] =
{
{ 0, 128, 32, 160, 8, 136, 40, 168,
2, 130, 34, 162, 10, 138, 42, 170 },
{ 192, 64, 224, 96, 200, 72, 232, 104,
194, 66, 226, 98, 202, 74, 234, 106 },
{ 48, 176, 16, 144, 56, 184, 24, 152,
50, 178, 18, 146, 58, 186, 26, 154 },
{ 240, 112, 208, 80, 248, 120, 216, 88,
242, 114, 210, 82, 250, 122, 218, 90 },
{ 12, 140, 44, 172, 4, 132, 36, 164,
14, 142, 46, 174, 6, 134, 38, 166 },
{ 204, 76, 236, 108, 196, 68, 228, 100,
206, 78, 238, 110, 198, 70, 230, 102 },
{ 60, 188, 28, 156, 52, 180, 20, 148,
62, 190, 30, 158, 54, 182, 22, 150 },
{ 252, 124, 220, 92, 244, 116, 212, 84,
254, 126, 222, 94, 246, 118, 214, 86 },
{ 3, 131, 35, 163, 11, 139, 43, 171,
1, 129, 33, 161, 9, 137, 41, 169 },
{ 195, 67, 227, 99, 203, 75, 235, 107,
193, 65, 225, 97, 201, 73, 233, 105 },
{ 51, 179, 19, 147, 59, 187, 27, 155,
49, 177, 17, 145, 57, 185, 25, 153 },
{ 243, 115, 211, 83, 251, 123, 219, 91,
241, 113, 209, 81, 249, 121, 217, 89 },
{ 15, 143, 47, 175, 7, 135, 39, 167,
13, 141, 45, 173, 5, 133, 37, 165 },
{ 207, 79, 239, 111, 199, 71, 231, 103,
205, 77, 237, 109, 197, 69, 229, 101 },
{ 63, 191, 31, 159, 55, 183, 23, 151,
61, 189, 29, 157, 53, 181, 21, 149 },
{ 254, 127, 223, 95, 247, 119, 215, 87,
253, 125, 221, 93, 245, 117, 213, 85 }
};
int Floyd8x8[8][8] =
{
{ 0, 32, 8, 40, 2, 34, 10, 42 },
{ 48, 16, 56, 24, 50, 18, 58, 26 },
{ 12, 44, 4, 36, 14, 46, 6, 38 },
{ 60, 28, 52, 20, 62, 30, 54, 22 },
{ 3, 35, 11, 43, 1, 33, 9, 41 },
{ 51, 19, 59, 27, 49, 17, 57, 25 },
{ 15, 47, 7, 39, 13, 45, 5, 37 },
{ 63, 31, 55, 23, 61, 29, 53, 21 }
};
int Floyd4x4[4][4] =
{
{ 0, 8, 2, 10 },
{ 12, 4, 14, 6 },
{ 3, 11, 1, 9 },
{ 15, 7, 13, 5 }
};
ib_t OnPixels[256],
OffPixels[256];
int Planes[] =
{
1,
3,
4,
1,
3,
3,
4,
4,
4,
6,
4,
4,
1,
1,
1,
3,
3,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15
};
static void exec_code(cups_page_header_t *header, const char *code);
static void format_CMY(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_CMYK(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_K(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_KCMYcm(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_KCMY(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
#define format_RGB format_CMY
static void format_RGBA(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_W(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_YMC(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void format_YMCK(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
static void make_lut(ib_t *, int, float, float);
int
main(int argc,
char *argv[])
{
int i;
image_t *img;
float xprint,
yprint,
xinches,
yinches;
float xsize,
ysize,
xsize2,
ysize2;
float aspect;
int xpages,
ypages,
xpage,
ypage,
xtemp,
ytemp,
page;
int x0, y0,
x1, y1;
ppd_file_t *ppd;
ppd_choice_t *choice,
**choices;
int count;
char *resolution,
*media_type;
ppd_profile_t *profile;
ppd_profile_t userprofile;
cups_raster_t *ras;
cups_page_header_t header;
int num_options;
cups_option_t *options;
const char *val;
int slowcollate,
slowcopies;
float g;
float b;
float zoom;
int xppi, yppi;
int hue, sat;
izoom_t *z;
int primary,
secondary;
ib_t *row,
*r0,
*r1;
int y,
iy,
last_iy,
yerr0,
yerr1,
blank;
ib_t lut[256];
int plane,
num_planes;
char filename[1024];
setbuf(stderr, NULL);
if (argc < 6 || argc > 7)
{
fputs("ERROR: imagetoraster job-id user title copies options [file]\n", stderr);
return (1);
}
fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
argv[3], argv[4], argv[5], argv[6] ? argv[6] : "(null)");
options = NULL;
num_options = cupsParseOptions(argv[5], 0, &options);
if (getenv("CLASSIFICATION") ||
cupsGetOption("page-label", num_options, options))
{
int mypipes[2];
int pid;
cupsFreeOptions(num_options, options);
if (pipe(mypipes))
{
perror("ERROR: Unable to create pipes for imagetops | pstoraster");
return (errno);
}
if ((pid = fork()) == 0)
{
close(0);
dup(mypipes[0]);
close(mypipes[0]);
close(mypipes[1]);
execlp("pstoraster", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
NULL);
perror("ERROR: Unable to exec pstoraster");
return (errno);
}
else if (pid < 0)
{
perror("ERROR: Unable to fork pstoraster");
return (errno);
}
close(1);
dup(mypipes[1]);
close(mypipes[0]);
close(mypipes[1]);
execlp("imagetops", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], NULL);
perror("ERROR: Unable to exec imagetops");
return (errno);
}
if (argc == 6)
{
int fd;
char buffer[8192];
int bytes;
if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
{
perror("ERROR: Unable to copy image file");
return (1);
}
fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
filename);
while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
write(fd, buffer, bytes);
close(fd);
}
else
strlcpy(filename, argv[6], sizeof(filename));
zoom = 0.0;
xppi = 0;
yppi = 0;
hue = 0;
sat = 100;
g = 1.0;
b = 1.0;
Copies = atoi(argv[4]);
ppd = SetCommonOptions(num_options, options, 0);
if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
{
Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
}
if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
strcasecmp(val, "True") == 0)
Collate = 1;
if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
g = atoi(val) * 0.001f;
if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
b = atoi(val) * 0.01f;
if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
zoom = atoi(val) * 0.01;
if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
yppi = xppi;
if ((val = cupsGetOption("position", num_options, options)) != NULL)
{
if (strcasecmp(val, "center") == 0)
{
XPosition = 0;
YPosition = 0;
}
else if (strcasecmp(val, "top") == 0)
{
XPosition = 0;
YPosition = 1;
}
else if (strcasecmp(val, "left") == 0)
{
XPosition = -1;
YPosition = 0;
}
else if (strcasecmp(val, "right") == 0)
{
XPosition = 1;
YPosition = 0;
}
else if (strcasecmp(val, "top-left") == 0)
{
XPosition = -1;
YPosition = 1;
}
else if (strcasecmp(val, "top-right") == 0)
{
XPosition = 1;
YPosition = 1;
}
else if (strcasecmp(val, "bottom") == 0)
{
XPosition = 0;
YPosition = -1;
}
else if (strcasecmp(val, "bottom-left") == 0)
{
XPosition = -1;
YPosition = -1;
}
else if (strcasecmp(val, "bottom-right") == 0)
{
XPosition = 1;
YPosition = -1;
}
}
if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
sat = atoi(val);
if ((val = cupsGetOption("hue", num_options, options)) != NULL)
hue = atoi(val);
if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
strcasecmp(val, "True") == 0)
Flip = 1;
memset(&header, 0, sizeof(header));
header.HWResolution[0] = 100;
header.HWResolution[1] = 100;
header.cupsBitsPerColor = 1;
header.cupsColorOrder = CUPS_ORDER_CHUNKED;
header.cupsColorSpace = CUPS_CSPACE_K;
if (ppd && ppd->patches)
exec_code(&header, ppd->patches);
if ((count = ppdCollect(ppd, PPD_ORDER_DOCUMENT, &choices)) > 0)
for (i = 0; i < count; i ++)
exec_code(&header, choices[i]->code);
if ((count = ppdCollect(ppd, PPD_ORDER_ANY, &choices)) > 0)
for (i = 0; i < count; i ++)
exec_code(&header, choices[i]->code);
if ((count = ppdCollect(ppd, PPD_ORDER_PROLOG, &choices)) > 0)
for (i = 0; i < count; i ++)
exec_code(&header, choices[i]->code);
if ((count = ppdCollect(ppd, PPD_ORDER_PAGE, &choices)) > 0)
for (i = 0; i < count; i ++)
exec_code(&header, choices[i]->code);
if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL)
media_type = choice->choice;
else
media_type = "";
if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL)
resolution = choice->choice;
else
resolution = "";
switch (header.cupsColorSpace)
{
case CUPS_CSPACE_W :
primary = IMAGE_WHITE;
secondary = IMAGE_WHITE;
header.cupsBitsPerPixel = header.cupsBitsPerColor;
break;
default :
case CUPS_CSPACE_RGB :
case CUPS_CSPACE_RGBA :
primary = IMAGE_RGB;
secondary = IMAGE_RGB;
if (header.cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
header.cupsBitsPerColor < 8)
header.cupsBitsPerColor = 8;
if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
{
if (header.cupsBitsPerColor >= 8)
header.cupsBitsPerPixel = header.cupsBitsPerColor * 3;
else
header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
}
else
header.cupsBitsPerPixel = header.cupsBitsPerColor;
break;
case CUPS_CSPACE_K :
case CUPS_CSPACE_WHITE :
case CUPS_CSPACE_GOLD :
case CUPS_CSPACE_SILVER :
primary = IMAGE_BLACK;
secondary = IMAGE_BLACK;
header.cupsBitsPerPixel = header.cupsBitsPerColor;
break;
case CUPS_CSPACE_CMYK :
case CUPS_CSPACE_YMCK :
case CUPS_CSPACE_KCMY :
case CUPS_CSPACE_GMCK :
case CUPS_CSPACE_GMCS :
primary = IMAGE_CMYK;
secondary = IMAGE_CMYK;
if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
else
header.cupsBitsPerPixel = header.cupsBitsPerColor;
break;
case CUPS_CSPACE_CMY :
case CUPS_CSPACE_YMC :
primary = IMAGE_CMY;
secondary = IMAGE_CMY;
if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
{
if (header.cupsBitsPerColor >= 8)
header.cupsBitsPerPixel = 24;
else
header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
}
else
header.cupsBitsPerPixel = header.cupsBitsPerColor;
break;
case CUPS_CSPACE_KCMYcm :
if (header.cupsBitsPerPixel == 1)
{
primary = IMAGE_CMY;
secondary = IMAGE_CMY;
if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
header.cupsBitsPerPixel = 8;
else
header.cupsBitsPerPixel = 1;
}
else
{
primary = IMAGE_CMYK;
secondary = IMAGE_CMYK;
if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
else
header.cupsBitsPerPixel = header.cupsBitsPerColor;
}
break;
}
if ((val = cupsGetOption("profile", num_options, options)) != NULL)
{
profile = &userprofile;
sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
&(userprofile.density), &(userprofile.gamma),
userprofile.matrix[0] + 0, userprofile.matrix[0] + 1,
userprofile.matrix[0] + 2,
userprofile.matrix[1] + 0, userprofile.matrix[1] + 1,
userprofile.matrix[1] + 2,
userprofile.matrix[2] + 0, userprofile.matrix[2] + 1,
userprofile.matrix[2] + 2);
userprofile.density *= 0.001f;
userprofile.gamma *= 0.001f;
userprofile.matrix[0][0] *= 0.001f;
userprofile.matrix[0][1] *= 0.001f;
userprofile.matrix[0][2] *= 0.001f;
userprofile.matrix[1][0] *= 0.001f;
userprofile.matrix[1][1] *= 0.001f;
userprofile.matrix[1][2] *= 0.001f;
userprofile.matrix[2][0] *= 0.001f;
userprofile.matrix[2][1] *= 0.001f;
userprofile.matrix[2][2] *= 0.001f;
}
else if (ppd != NULL)
{
fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n",
resolution, media_type);
for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++)
{
fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution,
profile->media_type);
if ((strcmp(profile->resolution, resolution) == 0 ||
profile->resolution[0] == '-') &&
(strcmp(profile->media_type, media_type) == 0 ||
profile->media_type[0] == '-'))
{
fputs("MATCH!\n", stderr);
break;
}
else
fputs("no.\n", stderr);
}
if (i >= ppd->num_profiles)
profile = NULL;
}
else
profile = NULL;
if (profile)
ImageSetProfile(profile->density, profile->gamma, profile->matrix);
ImageSetColorSpace(header.cupsColorSpace);
make_lut(lut, primary, g, b);
fputs("INFO: Loading image file...\n", stderr);
img = ImageOpen(filename, primary, secondary, sat, hue, lut);
if (argc == 6)
unlink(filename);
if (img == NULL)
{
fputs("ERROR: Unable to open image file for printing!\n", stderr);
ppdClose(ppd);
return (1);
}
if (zoom == 0.0 && xppi == 0)
{
xppi = img->xppi;
yppi = img->yppi;
}
if (yppi == 0)
yppi = xppi;
fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
xppi, yppi, zoom);
if (xppi > 0)
{
if (Orientation & 1)
{
xprint = (PageTop - PageBottom) / 72.0;
yprint = (PageRight - PageLeft) / 72.0;
}
else
{
xprint = (PageRight - PageLeft) / 72.0;
yprint = (PageTop - PageBottom) / 72.0;
}
fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
xprint, yprint);
xinches = (float)img->xsize / (float)xppi;
yinches = (float)img->ysize / (float)yppi;
fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
xinches, yinches);
if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
{
xinches = xinches * atoi(val) / 100;
yinches = yinches * atoi(val) / 100;
}
if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
cupsGetOption("landscape", num_options, options) == NULL)
{
fputs("DEBUG: Auto orientation...\n", stderr);
if ((xinches > xprint || yinches > yprint) &&
xinches <= yprint && yinches <= xprint)
{
fputs("DEBUG: Using landscape orientation...\n", stderr);
Orientation = (Orientation + 1) & 3;
xsize = yprint;
yprint = xprint;
xprint = xsize;
}
}
}
else
{
xprint = (PageRight - PageLeft) / 72.0;
yprint = (PageTop - PageBottom) / 72.0;
aspect = (float)img->yppi / (float)img->xppi;
fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
xprint, yprint);
fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
img->xppi, img->yppi, aspect);
xsize = xprint * zoom;
ysize = xsize * img->ysize / img->xsize / aspect;
if (ysize > (yprint * zoom))
{
ysize = yprint * zoom;
xsize = ysize * img->xsize * aspect / img->ysize;
}
xsize2 = yprint * zoom;
ysize2 = xsize2 * img->ysize / img->xsize / aspect;
if (ysize2 > (xprint * zoom))
{
ysize2 = xprint * zoom;
xsize2 = ysize2 * img->xsize * aspect / img->ysize;
}
fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
cupsGetOption("landscape", num_options, options) == NULL)
{
fputs("DEBUG: Auto orientation...\n", stderr);
if ((xsize * ysize) < (xsize2 * xsize2))
{
fputs("DEBUG: Using landscape orientation...\n", stderr);
Orientation = 1;
xinches = xsize2;
yinches = ysize2;
xprint = (PageTop - PageBottom) / 72.0;
yprint = (PageRight - PageLeft) / 72.0;
}
else
{
fputs("DEBUG: Using portrait orientation...\n", stderr);
Orientation = 0;
xinches = xsize;
yinches = ysize;
}
}
else if (Orientation & 1)
{
fputs("DEBUG: Using landscape orientation...\n", stderr);
xinches = xsize2;
yinches = ysize2;
xprint = (PageTop - PageBottom) / 72.0;
yprint = (PageRight - PageLeft) / 72.0;
xsize = PageLeft;
PageLeft = PageBottom;
PageBottom = PageWidth - PageRight;
PageRight = PageTop;
PageTop = PageLength - xsize;
xsize = PageWidth;
PageWidth = PageLength;
PageLength = xsize;
}
else
{
fputs("DEBUG: Using portrait orientation...\n", stderr);
xinches = xsize;
yinches = ysize;
xprint = (PageRight - PageLeft) / 72.0;
yprint = (PageTop - PageBottom) / 72.0;
}
}
xpages = ceil(xinches / xprint);
ypages = ceil(yinches / yprint);
fprintf(stderr, "DEBUG: xpages = %d, ypages = %d\n", xpages, ypages);
xprint = xinches / xpages;
yprint = yinches / ypages;
if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
strcasecmp(choice->choice, "Custom") == 0)
{
float width,
length;
if (Orientation & 1)
{
width = yprint * 72.0;
length = xprint * 72.0;
}
else
{
width = xprint * 72.0;
length = yprint * 72.0;
}
width += ppd->custom_margins[0] + ppd->custom_margins[2];
length += ppd->custom_margins[1] + ppd->custom_margins[3];
if (width < ppd->custom_min[0])
width = ppd->custom_min[0];
if (length < ppd->custom_min[1])
length = ppd->custom_min[1];
fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
width / 72.0, length / 72.0);
header.PageSize[0] = width + 0.5;
header.PageSize[1] = length + 0.5;
PageWidth = width;
PageLength = length;
PageLeft = ppd->custom_margins[0];
PageRight = width - ppd->custom_margins[2];
PageBottom = ppd->custom_margins[1];
PageTop = length - ppd->custom_margins[3];
width -= ppd->custom_margins[0] + ppd->custom_margins[2];
length -= ppd->custom_margins[1] + ppd->custom_margins[3];
header.cupsWidth = width * header.HWResolution[0] / 72.0;
header.cupsHeight = length * header.HWResolution[1] / 72.0;
}
else
{
header.cupsWidth = (PageRight - PageLeft) * header.HWResolution[0] / 72.0;
header.cupsHeight = (PageTop - PageBottom) * header.HWResolution[1] / 72.0;
header.PageSize[0] = PageWidth;
header.PageSize[1] = PageLength;
}
header.Margins[0] = PageLeft;
header.Margins[1] = PageBottom;
fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0],
header.PageSize[1]);
switch (Orientation)
{
case 0 :
switch (XPosition)
{
case -1 :
header.ImagingBoundingBox[0] = PageLeft;
header.ImagingBoundingBox[2] = PageLeft + xprint * 72;
break;
default :
header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
break;
case 1 :
header.ImagingBoundingBox[0] = PageRight - xprint * 72;
header.ImagingBoundingBox[2] = PageRight;
break;
}
switch (YPosition)
{
case -1 :
header.ImagingBoundingBox[1] = PageBottom;
header.ImagingBoundingBox[3] = PageBottom + yprint * 72;
break;
default :
header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
break;
case 1 :
header.ImagingBoundingBox[1] = PageTop - yprint * 72;
header.ImagingBoundingBox[3] = PageTop;
break;
}
break;
case 1 :
switch (XPosition)
{
case -1 :
header.ImagingBoundingBox[0] = PageBottom;
header.ImagingBoundingBox[2] = PageBottom + yprint * 72;
break;
default :
header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
break;
case 1 :
header.ImagingBoundingBox[0] = PageTop - yprint * 72;
header.ImagingBoundingBox[2] = PageTop;
break;
}
switch (YPosition)
{
case -1 :
header.ImagingBoundingBox[1] = PageLeft;
header.ImagingBoundingBox[3] = PageLeft + xprint * 72;
break;
default :
header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
break;
case 1 :
header.ImagingBoundingBox[1] = PageRight - xprint * 72;
header.ImagingBoundingBox[3] = PageRight;
break;
}
break;
case 2 :
switch (XPosition)
{
case 1 :
header.ImagingBoundingBox[0] = PageLeft;
header.ImagingBoundingBox[2] = PageLeft + xprint * 72;
break;
default :
header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
break;
case -1 :
header.ImagingBoundingBox[0] = PageRight - xprint * 72;
header.ImagingBoundingBox[2] = PageRight;
break;
}
switch (YPosition)
{
case 1 :
header.ImagingBoundingBox[1] = PageBottom;
header.ImagingBoundingBox[3] = PageBottom + yprint * 72;
break;
default :
header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
break;
case -1 :
header.ImagingBoundingBox[1] = PageTop - yprint * 72;
header.ImagingBoundingBox[3] = PageTop;
break;
}
break;
case 3 :
switch (XPosition)
{
case 1 :
header.ImagingBoundingBox[0] = PageBottom;
header.ImagingBoundingBox[2] = PageBottom + yprint * 72;
break;
default :
header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
break;
case -1 :
header.ImagingBoundingBox[0] = PageTop - yprint * 72;
header.ImagingBoundingBox[2] = PageTop;
break;
}
switch (YPosition)
{
case 1 :
header.ImagingBoundingBox[1] = PageLeft;
header.ImagingBoundingBox[3] = PageLeft + xprint * 72;
break;
default :
header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
break;
case -1 :
header.ImagingBoundingBox[1] = PageRight - xprint * 72;
header.ImagingBoundingBox[3] = PageRight;
break;
}
break;
}
switch (header.cupsColorOrder)
{
default :
header.cupsBytesPerLine = (header.cupsBitsPerPixel *
header.cupsWidth + 7) / 8;
num_planes = 1;
break;
case CUPS_ORDER_BANDED :
if (header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
header.cupsBitsPerColor > 1)
header.cupsBytesPerLine = (header.cupsBitsPerPixel *
header.cupsWidth + 7) / 8 * 4;
else
header.cupsBytesPerLine = (header.cupsBitsPerPixel *
header.cupsWidth + 7) / 8 *
Planes[header.cupsColorSpace];
num_planes = 1;
break;
case CUPS_ORDER_PLANAR :
header.cupsBytesPerLine = (header.cupsBitsPerPixel *
header.cupsWidth + 7) / 8;
num_planes = Planes[header.cupsColorSpace];
break;
}
if (xpages == 1 && ypages == 1)
Collate = 0;
slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
if (ppd != NULL)
slowcopies = ppd->manual_copies;
else
slowcopies = 1;
if (Copies > 1 && !slowcollate && !slowcopies)
{
header.Collate = (cups_bool_t)Collate;
header.NumCopies = Copies;
Copies = 1;
}
else
header.NumCopies = 1;
OnPixels[0] = 0x00;
OnPixels[255] = 0xff;
OffPixels[0] = 0x00;
OffPixels[255] = 0xff;
switch (header.cupsBitsPerColor)
{
case 2 :
for (i = 1; i < 255; i ++)
{
OnPixels[i] = 0x55 * (i / 85 + 1);
OffPixels[i] = 0x55 * (i / 64);
}
break;
case 4 :
for (i = 1; i < 255; i ++)
{
OnPixels[i] = 17 * (i / 17 + 1);
OffPixels[i] = 17 * (i / 16);
}
OnPixels[255] = OffPixels[255] = 0xff;
break;
}
fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth);
fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight);
fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor);
fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel);
fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder);
fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace);
fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
row = malloc(2 * header.cupsBytesPerLine);
ras = cupsRasterOpen(1, CUPS_RASTER_WRITE);
blank = img->colorspace < 0 ? 0 : ~0;
for (i = 0, page = 1; i < Copies; i ++)
for (xpage = 0; xpage < xpages; xpage ++)
for (ypage = 0; ypage < ypages; ypage ++, page ++)
{
fprintf(stderr, "INFO: Formatting page %d...\n", page);
if (Orientation & 1)
{
x0 = img->xsize * ypage / ypages;
x1 = img->xsize * (ypage + 1) / ypages - 1;
y0 = img->ysize * xpage / xpages;
y1 = img->ysize * (xpage + 1) / xpages - 1;
xtemp = header.HWResolution[0] * yprint;
ytemp = header.HWResolution[1] * xprint;
}
else
{
x0 = img->xsize * xpage / xpages;
x1 = img->xsize * (xpage + 1) / xpages - 1;
y0 = img->ysize * ypage / ypages;
y1 = img->ysize * (ypage + 1) / ypages - 1;
xtemp = header.HWResolution[0] * xprint;
ytemp = header.HWResolution[1] * yprint;
}
cupsRasterWriteHeader(ras, &header);
for (plane = 0; plane < num_planes; plane ++)
{
if (Flip)
z = ImageZoomAlloc(img, x0, y0, x1, y1, -xtemp, ytemp,
Orientation & 1);
else
z = ImageZoomAlloc(img, x0, y0, x1, y1, xtemp, ytemp,
Orientation & 1);
if (header.cupsHeight > z->ysize && YPosition <= 0)
{
memset(row, blank, header.cupsBytesPerLine);
y = header.cupsHeight - z->ysize;
if (YPosition == 0)
y /= 2;
for (; y > 0; y --)
{
if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
header.cupsBytesPerLine)
{
fputs("ERROR: Unable to write raster data to driver!\n", stderr);
ImageClose(img);
exit(1);
}
}
}
for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2;
y > 0;
y --)
{
if (iy != last_iy)
{
if (header.cupsBitsPerColor >= 8)
{
if ((iy - last_iy) > 1)
ImageZoomFill(z, iy);
ImageZoomFill(z, iy + z->yincr);
}
else
{
ImageZoomQFill(z, iy);
}
last_iy = iy;
}
memset(row, blank, header.cupsBytesPerLine);
r0 = z->rows[z->row];
r1 = z->rows[1 - z->row];
switch (header.cupsColorSpace)
{
case CUPS_CSPACE_W :
format_W(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
default :
case CUPS_CSPACE_RGB :
format_RGB(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_RGBA :
format_RGBA(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_K :
case CUPS_CSPACE_WHITE :
case CUPS_CSPACE_GOLD :
case CUPS_CSPACE_SILVER :
format_K(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_CMY :
format_CMY(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_YMC :
format_YMC(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_CMYK :
format_CMYK(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_YMCK :
case CUPS_CSPACE_GMCK :
case CUPS_CSPACE_GMCS :
format_YMCK(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_KCMY :
format_KCMY(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
case CUPS_CSPACE_KCMYcm :
format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize,
yerr0, yerr1, r0, r1);
break;
}
if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
header.cupsBytesPerLine)
{
fputs("ERROR: Unable to write raster data to driver!\n", stderr);
ImageClose(img);
exit(1);
}
iy += z->ystep;
yerr0 += z->ymod;
yerr1 -= z->ymod;
if (yerr1 <= 0)
{
yerr0 -= z->ysize;
yerr1 += z->ysize;
iy += z->yincr;
}
}
if (header.cupsHeight > z->ysize && YPosition >= 0)
{
memset(row, blank, header.cupsBytesPerLine);
y = header.cupsHeight - z->ysize;
if (YPosition == 0)
y = y - y / 2;
for (; y > 0; y --)
{
if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
header.cupsBytesPerLine)
{
fputs("ERROR: Unable to write raster data to driver!\n", stderr);
ImageClose(img);
exit(1);
}
}
}
ImageZoomFree(z);
}
}
free(row);
cupsRasterClose(ras);
ImageClose(img);
ppdClose(ppd);
return (0);
}
static void
exec_code(cups_page_header_t *header,
const char *code)
{
char *ptr,
name[255],
value[1024];
for (; *code != '\0';)
{
while (*code != '/' && *code != '\0')
code ++;
if (*code == '\0')
break;
code ++;
for (ptr = name; isalnum(*code) && (ptr - name) < (sizeof(name) - 1);)
*ptr++ = *code++;
*ptr = '\0';
while (isspace(*code))
code ++;
if (*code == '\0')
break;
if (*code == '[')
{
code ++;
for (ptr = value;
*code != ']' && *code != '\0' &&
(ptr - value) < (sizeof(value) - 1);)
*ptr++ = *code++;
*ptr = '\0';
}
else if (*code == '(')
{
code ++;
for (ptr = value;
*code != ')' && *code != '\0' &&
(ptr - value) < (sizeof(value) - 1);)
if (*code == '\\')
{
code ++;
if (isdigit(*code))
*ptr++ = (char)strtol(code, (char **)&code, 8);
else
*ptr++ = *code++;
}
else
*ptr++ = *code++;
*ptr = '\0';
}
else if (isdigit(*code) || *code == '-')
{
for (ptr = value;
(isdigit(*code) || *code == '-') &&
(ptr - value) < (sizeof(value) - 1);)
*ptr++ = *code++;
*ptr = '\0';
}
else
{
for (ptr = value;
(isalnum(*code) || *code == '_') &&
(ptr - value) < (sizeof(value) - 1);)
*ptr++ = *code++;
*ptr = '\0';
}
if (!strcmp(name, "MediaClass"))
strlcpy(header->MediaClass, value, sizeof(header->MediaClass));
else if (!strcmp(name, "MediaColor"))
strlcpy(header->MediaColor, value, sizeof(header->MediaColor));
else if (!strcmp(name, "MediaType"))
strlcpy(header->MediaType, value, sizeof(header->MediaType));
else if (!strcmp(name, "OutputType"))
strlcpy(header->OutputType, value, sizeof(header->OutputType));
else if (!strcmp(name, "AdvanceDistance"))
header->AdvanceDistance = atoi(value);
else if (!strcmp(name, "AdvanceMedia"))
header->AdvanceMedia = atoi(value);
else if (!strcmp(name, "Collate"))
header->Collate = !strcmp(value, "true");
else if (!strcmp(name, "CutMedia"))
header->CutMedia = (cups_cut_t)atoi(value);
else if (!strcmp(name, "Duplex"))
header->Duplex = !strcmp(value, "true");
else if (!strcmp(name, "HWResolution"))
sscanf(value, "%d%d", header->HWResolution + 0, header->HWResolution + 1);
else if (!strcmp(name, "InsertSheet"))
header->InsertSheet = !strcmp(value, "true");
else if (!strcmp(name, "Jog"))
header->Jog = atoi(value);
else if (!strcmp(name, "LeadingEdge"))
header->LeadingEdge = atoi(value);
else if (!strcmp(name, "Margins"))
sscanf(value, "%d%d", header->Margins + 0, header->Margins + 1);
else if (!strcmp(name, "ManualFeed"))
header->ManualFeed = !strcmp(value, "true");
else if (!strcmp(name, "cupsMediaPosition") ||
!strcmp(name, "MediaPosition"))
header->MediaPosition = atoi(value);
else if (!strcmp(name, "MediaWeight"))
header->MediaWeight = atoi(value);
else if (!strcmp(name, "MirrorPrint"))
header->MirrorPrint = !strcmp(value, "true");
else if (!strcmp(name, "NegativePrint"))
header->NegativePrint = !strcmp(value, "true");
else if (!strcmp(name, "Orientation"))
header->Orientation = atoi(value);
else if (!strcmp(name, "OutputFaceUp"))
header->OutputFaceUp = !strcmp(value, "true");
else if (!strcmp(name, "Separations"))
header->Separations = !strcmp(value, "true");
else if (!strcmp(name, "TraySwitch"))
header->TraySwitch = !strcmp(value, "true");
else if (!strcmp(name, "Tumble"))
header->Tumble = !strcmp(value, "true");
else if (!strcmp(name, "cupsMediaType"))
header->cupsMediaType = atoi(value);
else if (!strcmp(name, "cupsBitsPerColor"))
header->cupsBitsPerColor = atoi(value);
else if (!strcmp(name, "cupsColorOrder"))
header->cupsColorOrder = (cups_order_t)atoi(value);
else if (!strcmp(name, "cupsColorSpace"))
header->cupsColorSpace = (cups_cspace_t)atoi(value);
else if (!strcmp(name, "cupsCompression"))
header->cupsCompression = atoi(value);
else if (!strcmp(name, "cupsRowCount"))
header->cupsRowCount = atoi(value);
else if (!strcmp(name, "cupsRowFeed"))
header->cupsRowFeed = atoi(value);
else if (!strcmp(name, "cupsRowStep"))
header->cupsRowStep = atoi(value);
}
}
static void
format_CMY(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
*cptr,
*mptr,
*yptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
bandwidth = header->cupsBytesPerLine / 3;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 64 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 2;
else
{
bitmask = 64;
ptr ++;
}
}
break;
case 2 :
dither = Floyd8x8[y & 7];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if ((r0[0] & 63) > dither[x & 7])
*ptr ^= (0x30 & OnPixels[r0[0]]);
else
*ptr ^= (0x30 & OffPixels[r0[0]]);
if ((r0[1] & 63) > dither[x & 7])
*ptr ^= (0x0c & OnPixels[r0[1]]);
else
*ptr ^= (0x0c & OffPixels[r0[1]]);
if ((r0[2] & 63) > dither[x & 7])
*ptr++ ^= (0x03 & OnPixels[r0[2]]);
else
*ptr++ ^= (0x03 & OffPixels[r0[2]]);
}
break;
case 4 :
dither = Floyd4x4[y & 3];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if ((r0[0] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[0]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[0]]);
if ((r0[1] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[1]]);
else
*ptr ^= (0xf0 & OffPixels[r0[1]]);
if ((r0[2] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[2]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[2]]);
}
break;
case 8 :
for (x = xsize * 3; x > 0; x --, r0 ++, r1 ++)
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
break;
}
break;
case CUPS_ORDER_BANDED :
cptr = ptr;
mptr = ptr + bandwidth;
yptr = ptr + 2 * bandwidth;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*cptr ^= bitmask;
if (*r0++ > dither[x & 15])
*mptr ^= bitmask;
if (*r0++ > dither[x & 15])
*yptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
switch (z)
{
case 0 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[0] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 1 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[1] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[2] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 3)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 3)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
r0 += z;
r1 += z;
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
format_CMYK(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
*cptr,
*mptr,
*yptr,
*kptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
bandwidth = header->cupsBytesPerLine / 4;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 128 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 128;
ptr ++;
}
}
break;
case 2 :
dither = Floyd8x8[y & 7];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if ((r0[0] & 63) > dither[x & 7])
*ptr ^= (0xc0 & OnPixels[r0[0]]);
else
*ptr ^= (0xc0 & OffPixels[r0[0]]);
if ((r0[1] & 63) > dither[x & 7])
*ptr ^= (0x30 & OnPixels[r0[1]]);
else
*ptr ^= (0x30 & OffPixels[r0[1]]);
if ((r0[2] & 63) > dither[x & 7])
*ptr ^= (0x0c & OnPixels[r0[2]]);
else
*ptr ^= (0x0c & OffPixels[r0[2]]);
if ((r0[3] & 63) > dither[x & 7])
*ptr++ ^= (0x03 & OnPixels[r0[3]]);
else
*ptr++ ^= (0x03 & OffPixels[r0[3]]);
}
break;
case 4 :
dither = Floyd4x4[y & 3];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if ((r0[0] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[0]]);
else
*ptr ^= (0xf0 & OffPixels[r0[0]]);
if ((r0[1] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[1]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[1]]);
if ((r0[2] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[2]]);
else
*ptr ^= (0xf0 & OffPixels[r0[2]]);
if ((r0[3] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[3]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[3]]);
}
break;
case 8 :
for (x = xsize * 4; x > 0; x --, r0 ++, r1 ++)
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
break;
}
break;
case CUPS_ORDER_BANDED :
cptr = ptr;
mptr = ptr + bandwidth;
yptr = ptr + 2 * bandwidth;
kptr = ptr + 3 * bandwidth;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*cptr ^= bitmask;
if (*r0++ > dither[x & 15])
*mptr ^= bitmask;
if (*r0++ > dither[x & 15])
*yptr ^= bitmask;
if (*r0++ > dither[x & 15])
*kptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*kptr ^= (bitmask & OnPixels[*r0++]);
else
*kptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*kptr ^= (bitmask & OnPixels[*r0++]);
else
*kptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
if (r0[3] == r1[3])
*kptr++ = r0[3];
else
*kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 4)
{
if (*r0 > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 4)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 4)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
r0 += z;
r1 += z;
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
format_K(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
bitmask;
int bitoffset;
int x,
*dither;
(void)z;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0++]);
else
*ptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0++]);
else
*ptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 ++, r1 ++)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
}
static void
format_KCMY(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
*cptr,
*mptr,
*yptr,
*kptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
bandwidth = header->cupsBytesPerLine / 4;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 128 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if (r0[3] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[0] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[1] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[2] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 128;
ptr ++;
}
}
break;
case 2 :
dither = Floyd8x8[y & 7];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if ((r0[3] & 63) > dither[x & 7])
*ptr ^= (0xc0 & OnPixels[r0[3]]);
else
*ptr ^= (0xc0 & OffPixels[r0[3]]);
if ((r0[0] & 63) > dither[x & 7])
*ptr ^= (0x30 & OnPixels[r0[0]]);
else
*ptr ^= (0x30 & OffPixels[r0[0]]);
if ((r0[1] & 63) > dither[x & 7])
*ptr ^= (0x0c & OnPixels[r0[1]]);
else
*ptr ^= (0x0c & OffPixels[r0[1]]);
if ((r0[2] & 63) > dither[x & 7])
*ptr++ ^= (0x03 & OnPixels[r0[2]]);
else
*ptr++ ^= (0x03 & OffPixels[r0[2]]);
}
break;
case 4 :
dither = Floyd4x4[y & 3];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if ((r0[3] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[3]]);
else
*ptr ^= (0xf0 & OffPixels[r0[3]]);
if ((r0[0] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[0]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[0]]);
if ((r0[1] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[1]]);
else
*ptr ^= (0xf0 & OffPixels[r0[1]]);
if ((r0[2] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[2]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[2]]);
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[3] == r1[3])
*ptr++ = r0[3];
else
*ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
if (r0[0] == r1[0])
*ptr++ = r0[0];
else
*ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*ptr++ = r0[1];
else
*ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*ptr++ = r0[2];
else
*ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_BANDED :
kptr = ptr;
cptr = ptr + bandwidth;
mptr = ptr + 2 * bandwidth;
yptr = ptr + 3 * bandwidth;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*cptr ^= bitmask;
if (*r0++ > dither[x & 15])
*mptr ^= bitmask;
if (*r0++ > dither[x & 15])
*yptr ^= bitmask;
if (*r0++ > dither[x & 15])
*kptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*kptr ^= (bitmask & OnPixels[*r0++]);
else
*kptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*kptr ^= (bitmask & OnPixels[*r0++]);
else
*kptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
if (r0[3] == r1[3])
*kptr++ = r0[3];
else
*kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
if (z == 0)
r0 += 3;
else
r0 += z - 1;
for (x = xsize; x > 0; x --, r0 += 4)
{
if (*r0 > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
if (z == 0)
r0 += 3;
else
r0 += z - 1;
for (x = xsize; x > 0; x --, r0 += 4)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
if (z == 0)
r0 += 3;
else
r0 += z - 1;
for (x = xsize; x > 0; x --, r0 += 4)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
if (z == 0)
{
r0 += 3;
r1 += 3;
}
else
{
r0 += z - 1;
r1 += z - 1;
}
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
format_KCMYcm(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
int pc, pm, py, pk;
ib_t *ptr,
*cptr,
*mptr,
*yptr,
*kptr,
*lcptr,
*lmptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
if (header->cupsBitsPerColor == 1)
bandwidth = header->cupsBytesPerLine / 6;
else
bandwidth = header->cupsBytesPerLine / 4;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --)
{
pc = *r0++ > dither[x & 15];
pm = *r0++ > dither[x & 15];
py = *r0++ > dither[x & 15];
pk = *r0++ > dither[x & 15];
if (pk)
*ptr++ ^= 32;
else if (pc && pm)
*ptr++ ^= 17;
else if (pc && py)
*ptr++ ^= 6;
else if (pm && py)
*ptr++ ^= 12;
else if (pc)
*ptr++ ^= 16;
else if (pm)
*ptr++ ^= 8;
else if (py)
*ptr++ ^= 4;
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[3] == r1[3])
*ptr++ = r0[3];
else
*ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
if (r0[0] == r1[0])
*ptr++ = r0[0];
else
*ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*ptr++ = r0[1];
else
*ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*ptr++ = r0[2];
else
*ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_BANDED :
kptr = ptr;
cptr = ptr + bandwidth;
mptr = ptr + 2 * bandwidth;
yptr = ptr + 3 * bandwidth;
lcptr = ptr + 4 * bandwidth;
lmptr = ptr + 5 * bandwidth;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
pc = *r0++ > dither[x & 15];
pm = *r0++ > dither[x & 15];
py = *r0++ > dither[x & 15];
pk = *r0++ > dither[x & 15];
if (pk)
*kptr ^= bitmask;
else if (pc && pm)
{
*cptr ^= bitmask;
*lmptr ^= bitmask;
}
else if (pc && py)
{
*lcptr ^= bitmask;
*yptr ^= bitmask;
}
else if (pm && py)
{
*mptr ^= bitmask;
*yptr ^= bitmask;
}
else if (pc)
*cptr ^= bitmask;
else if (pm)
*mptr ^= bitmask;
else if (py)
*yptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
lcptr ++;
lmptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
if (r0[3] == r1[3])
*kptr++ = r0[3];
else
*kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
switch (z)
{
case 0 :
for (x = xsize; x > 0; x --, r0 += 4)
{
if (r0[3] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 1 :
for (x = xsize; x > 0; x --, r0 += 4)
{
if (r0[0] > dither[x & 15] &&
r0[2] < dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
for (x = xsize; x > 0; x --, r0 += 4)
{
if (r0[1] > dither[x & 15] &&
(r0[0] < dither[x & 15] ||
r0[2] > dither[x & 15]))
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 3 :
for (x = xsize; x > 0; x --, r0 += 4)
{
if (r0[2] > dither[x & 15] &&
(r0[0] < dither[x & 15] ||
r0[1] < dither[x & 15]))
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 4 :
for (x = xsize; x > 0; x --, r0 += 4)
{
if (r0[0] > dither[x & 15] &&
r0[2] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 5 :
for (x = xsize; x > 0; x --, r0 += 4)
{
if (r0[0] > dither[x & 15] &&
r0[1] > dither[x & 15] &&
r0[2] < dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
}
break;
case 8 :
if (z == 0)
{
r0 += 3;
r1 += 3;
}
else
{
r0 += z - 1;
r1 += z - 1;
}
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
format_RGBA(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
*cptr,
*mptr,
*yptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
bandwidth = header->cupsBytesPerLine / 4;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 128 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 2)
{
*ptr ^= 16;
bitmask >>= 2;
}
else
{
bitmask = 128;
*ptr++ ^= 1;
}
}
break;
case 2 :
dither = Floyd8x8[y & 7];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if ((r0[0] & 63) > dither[x & 7])
*ptr ^= (0xc0 & OnPixels[r0[0]]);
else
*ptr ^= (0xc0 & OffPixels[r0[0]]);
if ((r0[1] & 63) > dither[x & 7])
*ptr ^= (0x30 & OnPixels[r0[1]]);
else
*ptr ^= (0x30 & OffPixels[r0[1]]);
if ((r0[2] & 63) > dither[x & 7])
*ptr ^= (0x0c & OnPixels[r0[2]]);
else
*ptr ^= (0x0c & OffPixels[r0[2]]);
*ptr++ ^= 0x03;
}
break;
case 4 :
dither = Floyd4x4[y & 3];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if ((r0[0] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[0]]);
else
*ptr ^= (0xf0 & OffPixels[r0[0]]);
if ((r0[1] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[1]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[1]]);
if ((r0[2] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[2]]);
else
*ptr ^= (0xf0 & OffPixels[r0[2]]);
*ptr++ ^= 0x0f;
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (r0[0] == r1[0])
*ptr++ = r0[0];
else
*ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*ptr++ = r0[1];
else
*ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*ptr++ = r0[2];
else
*ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
*ptr++ = 255;
}
break;
}
break;
case CUPS_ORDER_BANDED :
cptr = ptr;
mptr = ptr + bandwidth;
yptr = ptr + 2 * bandwidth;
memset(ptr + 3 * bandwidth, 255, bandwidth);
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*cptr ^= bitmask;
if (*r0++ > dither[x & 15])
*mptr ^= bitmask;
if (*r0++ > dither[x & 15])
*yptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
if (z == 3)
{
memset(row, 255, header->cupsBytesPerLine);
break;
}
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
switch (z)
{
case 0 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[0] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 1 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[1] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[2] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 3)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
r0 += z;
for (x = xsize; x > 0; x --, r0 += 3)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
r0 += z;
r1 += z;
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
format_W(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
bitmask;
int bitoffset;
int x,
*dither;
(void)z;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0++]);
else
*ptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0++]);
else
*ptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 ++, r1 ++)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
}
static void
format_YMC(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
*cptr,
*mptr,
*yptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
bandwidth = header->cupsBytesPerLine / 3;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 64 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if (r0[2] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[1] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[0] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 2;
else
{
bitmask = 64;
ptr ++;
}
}
break;
case 2 :
dither = Floyd8x8[y & 7];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if ((r0[2] & 63) > dither[x & 7])
*ptr ^= (0x30 & OnPixels[r0[2]]);
else
*ptr ^= (0x30 & OffPixels[r0[2]]);
if ((r0[1] & 63) > dither[x & 7])
*ptr ^= (0x0c & OnPixels[r0[1]]);
else
*ptr ^= (0x0c & OffPixels[r0[1]]);
if ((r0[0] & 63) > dither[x & 7])
*ptr++ ^= (0x03 & OnPixels[r0[0]]);
else
*ptr++ ^= (0x03 & OffPixels[r0[0]]);
}
break;
case 4 :
dither = Floyd4x4[y & 3];
for (x = xsize ; x > 0; x --, r0 += 3)
{
if ((r0[2] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[2]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[2]]);
if ((r0[1] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[1]]);
else
*ptr ^= (0xf0 & OffPixels[r0[1]]);
if ((r0[0] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[0]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[0]]);
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (r0[2] == r1[2])
*ptr++ = r0[2];
else
*ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
if (r0[1] == r1[1])
*ptr++ = r0[1];
else
*ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[0] == r1[0])
*ptr++ = r0[0];
else
*ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_BANDED :
yptr = ptr;
mptr = ptr + bandwidth;
cptr = ptr + 2 * bandwidth;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*cptr ^= bitmask;
if (*r0++ > dither[x & 15])
*mptr ^= bitmask;
if (*r0++ > dither[x & 15])
*yptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
cptr ++;
mptr ++;
yptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
switch (z)
{
case 2 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[0] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 1 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[1] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 0 :
for (x = xsize; x > 0; x --, r0 += 3)
{
if (r0[2] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
z = 2 - z;
r0 += z;
for (x = xsize; x > 0; x --, r0 += 3)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
z = 2 - z;
r0 += z;
for (x = xsize; x > 0; x --, r0 += 3)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
z = 2 - z;
r0 += z;
r1 += z;
for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
format_YMCK(cups_page_header_t *header,
unsigned char *row,
int y,
int z,
int xsize,
int ysize,
int yerr0,
int yerr1,
ib_t *r0,
ib_t *r1)
{
ib_t *ptr,
*cptr,
*mptr,
*yptr,
*kptr,
bitmask;
int bitoffset;
int bandwidth;
int x,
*dither;
switch (XPosition)
{
case -1 :
bitoffset = 0;
break;
default :
bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
break;
case 1 :
bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
break;
}
ptr = row + bitoffset / 8;
bandwidth = header->cupsBytesPerLine / 4;
switch (header->cupsColorOrder)
{
case CUPS_ORDER_CHUNKED :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 128 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if (r0[2] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[1] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[0] > dither[x & 15])
*ptr ^= bitmask;
bitmask >>= 1;
if (r0[3] > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 128;
ptr ++;
}
}
break;
case 2 :
dither = Floyd8x8[y & 7];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if ((r0[2] & 63) > dither[x & 7])
*ptr ^= (0xc0 & OnPixels[r0[2]]);
else
*ptr ^= (0xc0 & OffPixels[r0[2]]);
if ((r0[1] & 63) > dither[x & 7])
*ptr ^= (0x30 & OnPixels[r0[1]]);
else
*ptr ^= (0x30 & OffPixels[r0[1]]);
if ((r0[0] & 63) > dither[x & 7])
*ptr ^= (0x0c & OnPixels[r0[0]]);
else
*ptr ^= (0x0c & OffPixels[r0[0]]);
if ((r0[3] & 63) > dither[x & 7])
*ptr++ ^= (0x03 & OnPixels[r0[3]]);
else
*ptr++ ^= (0x03 & OffPixels[r0[3]]);
}
break;
case 4 :
dither = Floyd4x4[y & 3];
for (x = xsize ; x > 0; x --, r0 += 4)
{
if ((r0[2] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[2]]);
else
*ptr ^= (0xf0 & OffPixels[r0[2]]);
if ((r0[1] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[1]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[1]]);
if ((r0[0] & 15) > dither[x & 3])
*ptr ^= (0xf0 & OnPixels[r0[0]]);
else
*ptr ^= (0xf0 & OffPixels[r0[0]]);
if ((r0[3] & 15) > dither[x & 3])
*ptr++ ^= (0x0f & OnPixels[r0[3]]);
else
*ptr++ ^= (0x0f & OffPixels[r0[3]]);
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[2] == r1[2])
*ptr++ = r0[2];
else
*ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
if (r0[1] == r1[1])
*ptr++ = r0[1];
else
*ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[0] == r1[0])
*ptr++ = r0[0];
else
*ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[3] == r1[3])
*ptr++ = r0[3];
else
*ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_BANDED :
yptr = ptr;
mptr = ptr + bandwidth;
cptr = ptr + 2 * bandwidth;
kptr = ptr + 3 * bandwidth;
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
for (x = xsize; x > 0; x --)
{
if (*r0++ > dither[x & 15])
*cptr ^= bitmask;
if (*r0++ > dither[x & 15])
*mptr ^= bitmask;
if (*r0++ > dither[x & 15])
*yptr ^= bitmask;
if (*r0++ > dither[x & 15])
*kptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 63) > dither[x & 7])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 63) > dither[x & 7])
*kptr ^= (bitmask & OnPixels[*r0++]);
else
*kptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
for (x = xsize; x > 0; x --)
{
if ((*r0 & 15) > dither[x & 3])
*cptr ^= (bitmask & OnPixels[*r0++]);
else
*cptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*mptr ^= (bitmask & OnPixels[*r0++]);
else
*mptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*yptr ^= (bitmask & OnPixels[*r0++]);
else
*yptr ^= (bitmask & OffPixels[*r0++]);
if ((*r0 & 15) > dither[x & 3])
*kptr ^= (bitmask & OnPixels[*r0++]);
else
*kptr ^= (bitmask & OffPixels[*r0++]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
cptr ++;
mptr ++;
yptr ++;
kptr ++;
}
}
break;
case 8 :
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (r0[0] == r1[0])
*cptr++ = r0[0];
else
*cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
if (r0[1] == r1[1])
*mptr++ = r0[1];
else
*mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
if (r0[2] == r1[2])
*yptr++ = r0[2];
else
*yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
if (r0[3] == r1[3])
*kptr++ = r0[3];
else
*kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
}
break;
}
break;
case CUPS_ORDER_PLANAR :
switch (header->cupsBitsPerColor)
{
case 1 :
bitmask = 0x80 >> (bitoffset & 7);
dither = Floyd16x16[y & 15];
if (z < 3)
r0 += 2 - z;
else
r0 += z;
for (x = xsize; x > 0; x --, r0 += 4)
{
if (*r0 > dither[x & 15])
*ptr ^= bitmask;
if (bitmask > 1)
bitmask >>= 1;
else
{
bitmask = 0x80;
ptr ++;
}
}
break;
case 2 :
bitmask = 0xc0 >> (bitoffset & 7);
dither = Floyd8x8[y & 7];
if (z == 3)
r0 += 3;
else
r0 += 2 - z;
for (x = xsize; x > 0; x --, r0 += 4)
{
if ((*r0 & 63) > dither[x & 7])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask > 3)
bitmask >>= 2;
else
{
bitmask = 0xc0;
ptr ++;
}
}
break;
case 4 :
bitmask = 0xf0 >> (bitoffset & 7);
dither = Floyd4x4[y & 3];
if (z == 3)
r0 += 3;
else
r0 += 2 - z;
for (x = xsize; x > 0; x --, r0 += 4)
{
if ((*r0 & 15) > dither[x & 3])
*ptr ^= (bitmask & OnPixels[*r0]);
else
*ptr ^= (bitmask & OffPixels[*r0]);
if (bitmask == 0xf0)
bitmask = 0x0f;
else
{
bitmask = 0xf0;
ptr ++;
}
}
break;
case 8 :
if (z == 3)
{
r0 += 3;
r1 += 3;
}
else
{
r0 += 2 - z;
r1 += 2 - z;
}
for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
{
if (*r0 == *r1)
*ptr++ = *r0;
else
*ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
}
break;
}
break;
}
}
static void
make_lut(ib_t *lut,
int colorspace,
float g,
float b)
{
int i;
int v;
g = 1.0 / g;
b = 1.0 / b;
for (i = 0; i < 256; i ++)
{
if (colorspace < 0)
v = 255.0 * b * (1.0 - pow(1.0 - (float)i / 255.0, g)) + 0.5;
else
v = 255.0 * (1.0 - b * (1.0 - pow((float)i / 255.0, g))) + 0.5;
if (v < 0)
*lut++ = 0;
else if (v > 255)
*lut++ = 255;
else
*lut++ = v;
}
}