summaryrefslogtreecommitdiff
path: root/net-print/libcupsfilters/files/libcupsfilters-2.0.0-color-space.patch
blob: 37a8bce64d7b307b1bb093cec18931aebf3f0cbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
https://bugs.gentoo.org/927137
https://github.com/OpenPrinting/cups-filters/issues/578
https://github.com/OpenPrinting/libcupsfilters/commit/c6175a2f3f66dbf76bb35ec8d1ba0dc094c9dbac

From c6175a2f3f66dbf76bb35ec8d1ba0dc094c9dbac Mon Sep 17 00:00:00 2001
From: Till Kamppeter <till.kamppeter@gmail.com>
Date: Wed, 29 Nov 2023 00:25:16 +0100
Subject: [PATCH] raster_base_header(): Several fixes on color space selection

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.
---
 cupsfilters/raster.c | 103 +++++++++++++++++++++++++------------------
 1 file changed, 61 insertions(+), 42 deletions(-)

diff --git a/cupsfilters/raster.c b/cupsfilters/raster.c
index 32a8b807..5e10f3bb 100644
--- a/cupsfilters/raster.c
+++ b/cupsfilters/raster.c
@@ -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_header2_t *h, // O - Raster header
+raster_base_header(cups_page_header2_t *h,  // O - Raster header
 		   cf_filter_data_t *data, // I - Filter data
 		   int pwg_raster)         // I - 1 if PWG/Apple Raster
 {
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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
@@ -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)