Skip to content

Commit

Permalink
raster_base_header(): Several fixes on color space selection
Browse files Browse the repository at this point in the history
Fixes #38

The internal (static) funcrion raster_base_header() creates a CUPS or
PWG Raster header from scratch, without using data of a PPD file by
means of Raster header derived from the PPD. It solely uses IPP
attributes or command line options.

It distinguishes between CUPS Raster and PWG/Apple Raster headers.

There were several bugs in selecting the correct color space and depth
settings:

- For PWG-Raster all attributes and options got ignored and standard
  8-bit sRGB set.

- Without any valid color space/depth setting attribute or "auto"
  always standard 8-bit sRGB got set as the default, regardless
  whether the printer is actually a color printer.

- Color spaces for printing in color could be set on monochrome
  printers by options or atrributes.

- Color spaces not valid on PWG Raster could be set on PWG Raster.

- DeviceN modes could only be set by specifying a depth, like
  "Device4_8" not just "Device4".

Now we use 8-bit SGray as default for monochrome printers and 8-bit
RGB for color printers. We use the printer IPP attribute
"color-supported" to check whether the printer is color.

IPP ttributes or command line options setting a color mode on a
monochrome printer are ignored now, also, if the output format is PWG
Raster, setting a color space not supported by PWG Raster is ignored.

Now for monochrome AirPrint (Apple Raster) printers, the Raster data
sent should be actually monochrome (grayscale) and not color.
  • Loading branch information
tillkamppeter committed Nov 28, 2023
1 parent 26f9c3f commit c6175a2
Showing 1 changed file with 61 additions and 42 deletions.
103 changes: 61 additions & 42 deletions cupsfilters/raster.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ cfRasterSetColorSpace(cups_page_header_t *h, // I - Raster header


static int // O - -1 on error, 0 on success
raster_base_header(cups_page_header_t *h, // O - Raster header
raster_base_header(cups_page_header_t *h, // O - Raster header
cf_filter_data_t *data, // I - Filter data
int pwg_raster) // I - 1 if PWG/Apple Raster
{
Expand Down Expand Up @@ -1420,41 +1420,46 @@ raster_base_header(cups_page_header_t *h, // O - Raster header
// TODO - Support for MediaType number
h->cupsMediaType = 0;

// Only for CUPS Raster, if we do not have a sample header from a PPD file
if (pwg_raster == 0 &&
((val = cupsGetOption("pwg-raster-document-type", num_options,
options)) != NULL ||
(val = cupsGetOption("PwgRasterDocumentType", num_options,
options)) != NULL ||
(val = cupsGetOption("color-space", num_options, options)) != NULL ||
(val = cupsGetOption("ColorSpace", num_options, options)) != NULL ||
(val = cupsGetOption("color-model", num_options, options)) != NULL ||
(val = cupsGetOption("ColorModel", num_options, options)) != NULL ||
(val = cupsGetOption("print-color-mode", num_options, options)) !=
NULL ||
(val = cupsGetOption("output-mode", num_options, options)) != NULL ||
(val = cupsGetOption("OutputMode", num_options, options)) != NULL ||
(val = cfIPPAttrEnumValForPrinter(data->printer_attrs,
data->job_attrs,
"print-color-mode")) != NULL))

// Do we have a color printer?
bool is_color =
((attr = ippFindAttribute(data->printer_attrs, "color-supported",
IPP_TAG_BOOLEAN)) != NULL &&
ippGetBoolean(attr, 0));

// Color modes
int numcolors = 0; // Number of colorants
if ((val = cupsGetOption("pwg-raster-document-type", num_options,
options)) != NULL ||
(val = cupsGetOption("PwgRasterDocumentType", num_options,
options)) != NULL ||
(val = cupsGetOption("color-space", num_options, options)) != NULL ||
(val = cupsGetOption("ColorSpace", num_options, options)) != NULL ||
(val = cupsGetOption("color-model", num_options, options)) != NULL ||
(val = cupsGetOption("ColorModel", num_options, options)) != NULL ||
(val = cupsGetOption("print-color-mode", num_options, options)) !=
NULL ||
(val = cupsGetOption("output-mode", num_options, options)) != NULL ||
(val = cupsGetOption("OutputMode", num_options, options)) != NULL ||
(val = cfIPPAttrEnumValForPrinter(data->printer_attrs,
data->job_attrs,
"print-color-mode")) != NULL)
{
int bitspercolor, // Bits per color
bitsperpixel, // Bits per pixel
colorspace, // CUPS/PWG raster color space
numcolors; // Number of colorants
colorspace; // CUPS/PWG raster color space;
const char *ptr; // Pointer into value

ptr = NULL;
numcolors = 0;
bitspercolor = 8;
if (!strncasecmp(val, "AdobeRgb", 8))
if (is_color && !strncasecmp(val, "AdobeRgb", 8))
{
if (*(val + 8) == '_' || *(val + 8) == '-')
ptr = val + 9;
colorspace = 20;
numcolors = 3;
}
else if (!strncasecmp(val, "adobe-rgb", 9))
else if (is_color && !strncasecmp(val, "adobe-rgb", 9))
{
if (*(val + 9) == '_' || *(val + 9) == '-')
ptr = val + 10;
Expand Down Expand Up @@ -1500,19 +1505,19 @@ raster_base_header(cups_page_header_t *h, // O - Raster header
colorspace = 18;
numcolors = 1;
}
else if (!strcasecmp(val, "color"))
else if (is_color && !strcasecmp(val, "color"))
{
colorspace = 19;
numcolors = 3;
}
else if (!strncasecmp(val, "Cmyk", 4))
else if (is_color && !strncasecmp(val, "Cmyk", 4))
{
if (*(val + 4) == '_' || *(val + 4) == '-')
ptr = val + 5;
colorspace = 6;
numcolors = 4;
}
else if (!strncasecmp(val, "Cmy", 3))
else if (!pwg_raster && is_color && !strncasecmp(val, "Cmy", 3))
{
if (*(val + 3) == '_' || *(val + 3) == '-')
ptr = val + 4;
Expand All @@ -1524,10 +1529,9 @@ raster_base_header(cups_page_header_t *h, // O - Raster header
ptr = val + 6;
numcolors = strtol(ptr, (char **)&ptr, 10);
if (*ptr == '_' || *ptr == '-')
{
ptr ++;
if (numcolors > 0 && numcolors < 16)
colorspace = 47 + numcolors;
}
else
{
numcolors = 0;
Expand All @@ -1548,21 +1552,21 @@ raster_base_header(cups_page_header_t *h, // O - Raster header
colorspace = 18;
numcolors = 1;
}
else if (!strncasecmp(val, "Srgb", 4))
else if (is_color && !strncasecmp(val, "Srgb", 4))
{
if (*(val + 4) == '_' || *(val + 4) == '-')
ptr = val + 5;
colorspace = 19;
numcolors = 3;
}
else if (!strncasecmp(val, "Rgbw", 4))
else if (!pwg_raster && is_color && !strncasecmp(val, "Rgbw", 4))
{
if (*(val + 4) == '_' || *(val + 4) == '-')
ptr = val + 5;
colorspace = 17;
numcolors = 4;
}
else if (!strncasecmp(val, "Rgb", 3))
else if (is_color && !strncasecmp(val, "Rgb", 3))
{
if (*(val + 3) == '_' || *(val + 3) == '-')
ptr = val + 4;
Expand All @@ -1572,12 +1576,22 @@ raster_base_header(cups_page_header_t *h, // O - Raster header
else if (!strcasecmp(val, "auto"))
{
// Let "auto" not look like an error
colorspace = 19;
numcolors = 3;
if (is_color)
{
colorspace = 19;
numcolors = 3;
}
else
{
colorspace = 18;
numcolors = 1;
}
}

// Color mode found
if (numcolors > 0)
{
if (ptr)
if (ptr && *ptr)
bitspercolor = strtol(ptr, (char **)&ptr, 10);
bitsperpixel = bitspercolor * numcolors;
// In 1-bit-per-color RGB modes we add a forth bit to each pixel
Expand All @@ -1590,20 +1604,25 @@ raster_base_header(cups_page_header_t *h, // O - Raster header
h->cupsColorSpace = colorspace;
h->cupsNumColors = numcolors;
}
else
}

// No color mode found
if (numcolors == 0)
{
if (is_color)
{
h->cupsBitsPerColor = 8;
h->cupsBitsPerPixel = 24;
h->cupsColorSpace = 19;
h->cupsNumColors = 3;
}
}
else
{
h->cupsBitsPerColor = 8;
h->cupsBitsPerPixel = 24;
h->cupsColorSpace = 19;
h->cupsNumColors = 3;
else
{
h->cupsBitsPerColor = 8;
h->cupsBitsPerPixel = 8;
h->cupsColorSpace = 18;
h->cupsNumColors = 1;
}
}

// TODO - Support for color orders 1 (banded) and 2 (planar)
Expand Down

0 comments on commit c6175a2

Please sign in to comment.