1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied,
8
modified or distributed except as expressly authorized under the terms
9
of the license contained in the file LICENSE in this distribution.
11
Refer to licensing information at http://www.artifex.com or contact
12
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
CA 94903, U.S.A., +1(415)492-9861, for further information.
17
/* Gimp (XCF) export device, supporting DeviceN color models. */
29
#include "gsicc_cache.h"
30
#include "gsicc_manage.h"
32
#ifndef cmm_gcmmhlink_DEFINED
33
#define cmm_gcmmhlink_DEFINED
34
typedef void* gcmmhlink_t;
37
#ifndef cmm_gcmmhprofile_DEFINED
38
#define cmm_gcmmhprofile_DEFINED
39
typedef void* gcmmhprofile_t;
46
/* Define the device parameters. */
54
/* The device descriptor */
55
static dev_proc_get_params(xcf_get_params);
56
static dev_proc_close_device(xcf_prn_close);
57
static dev_proc_put_params(xcf_put_params);
58
static dev_proc_print_page(xcf_print_page);
59
static dev_proc_map_color_rgb(xcf_map_color_rgb);
60
static dev_proc_get_color_mapping_procs(get_spotrgb_color_mapping_procs);
62
static dev_proc_get_color_mapping_procs(get_spotcmyk_color_mapping_procs);
64
static dev_proc_get_color_mapping_procs(get_xcf_color_mapping_procs);
65
static dev_proc_get_color_comp_index(xcf_get_color_comp_index);
66
static dev_proc_encode_color(xcf_encode_color);
67
static dev_proc_decode_color(xcf_decode_color);
70
* Type definitions associated with the fixed color model names.
72
typedef const char * fixed_colorant_name;
73
typedef fixed_colorant_name fixed_colorant_names_list[];
76
* Structure for holding SeparationNames and SeparationOrder elements.
78
typedef struct gs_separation_names_s {
80
const gs_param_string * names[GX_DEVICE_COLOR_MAX_COMPONENTS];
81
} gs_separation_names;
83
/* This is redundant with color_info.cm_name. We may eliminate this
84
typedef and use the latter string for everything. */
93
* A structure definition for a DeviceN type device
95
typedef struct xcf_device_s {
99
/* ... device-specific parameters ... */
101
xcf_color_model color_model;
104
* Bits per component (device colorant). Currently only 1 and 8 are
107
int bitspercomponent;
110
* Pointer to the colorant names for the color model. This will be
111
* null if we have DeviceN type device. The actual possible colorant
112
* names are those in this list plus those in the separation_names
115
const fixed_colorant_names_list * std_colorant_names;
116
int num_std_colorant_names; /* Number of names in list */
119
* Separation names (if any).
121
gs_separation_names separation_names;
124
* Separation Order (if specified).
126
gs_separation_names separation_order;
128
/* ICC color profile objects, for color conversion.
129
These are all device link profiles. At least that
130
is how it appears looking at how this code
131
was written to work with the old icclib. Just
132
doing minimal updates here so that it works
133
with the new CMM API. I would be interested
134
to hear how people are using this. */
136
char profile_rgb_fn[256];
137
cmm_profile_t *rgb_profile;
138
gcmmhlink_t rgb_icc_link;
140
char profile_cmyk_fn[256];
141
cmm_profile_t *cmyk_profile;
142
gcmmhlink_t cmyk_icc_link;
144
char profile_out_fn[256];
145
cmm_profile_t *output_profile;
146
gcmmhlink_t output_icc_link;
151
* Macro definition for DeviceN procedures
153
#define device_procs(get_color_mapping_procs)\
155
gx_default_get_initial_matrix,\
156
NULL, /* sync_output */\
157
/* Since the print_page doesn't alter the device, this device can print in the background */\
158
gdev_prn_bg_output_page, /* output_page */\
159
xcf_prn_close, /* close */\
160
NULL, /* map_rgb_color - not used */\
161
xcf_map_color_rgb, /* map_color_rgb */\
162
NULL, /* fill_rectangle */\
163
NULL, /* tile_rectangle */\
164
NULL, /* copy_mono */\
165
NULL, /* copy_color */\
166
NULL, /* draw_line */\
167
NULL, /* get_bits */\
168
xcf_get_params, /* get_params */\
169
xcf_put_params, /* put_params */\
170
NULL, /* map_cmyk_color - not used */\
171
NULL, /* get_xfont_procs */\
172
NULL, /* get_xfont_device */\
173
NULL, /* map_rgb_alpha_color */\
174
gx_page_device_get_page_device, /* get_page_device */\
175
NULL, /* get_alpha_bits */\
176
NULL, /* copy_alpha */\
177
NULL, /* get_band */\
178
NULL, /* copy_rop */\
179
NULL, /* fill_path */\
180
NULL, /* stroke_path */\
181
NULL, /* fill_mask */\
182
NULL, /* fill_trapezoid */\
183
NULL, /* fill_parallelogram */\
184
NULL, /* fill_triangle */\
185
NULL, /* draw_thin_line */\
186
NULL, /* begin_image */\
187
NULL, /* image_data */\
188
NULL, /* end_image */\
189
NULL, /* strip_tile_rectangle */\
190
NULL, /* strip_copy_rop */\
191
NULL, /* get_clipping_box */\
192
NULL, /* begin_typed_image */\
193
NULL, /* get_bits_rectangle */\
194
NULL, /* map_color_rgb_alpha */\
195
NULL, /* create_compositor */\
196
NULL, /* get_hardware_params */\
197
NULL, /* text_begin */\
198
NULL, /* finish_copydevice */\
199
NULL, /* begin_transparency_group */\
200
NULL, /* end_transparency_group */\
201
NULL, /* begin_transparency_mask */\
202
NULL, /* end_transparency_mask */\
203
NULL, /* discard_transparency_layer */\
204
get_color_mapping_procs, /* get_color_mapping_procs */\
205
xcf_get_color_comp_index, /* get_color_comp_index */\
206
xcf_encode_color, /* encode_color */\
207
xcf_decode_color /* decode_color */\
210
static const fixed_colorant_names_list DeviceGrayComponents = {
212
0 /* List terminator */
215
static const fixed_colorant_names_list DeviceRGBComponents = {
219
0 /* List terminator */
222
static const fixed_colorant_names_list DeviceCMYKComponents = {
227
0 /* List terminator */
231
* Example device with RGB and spot color support
233
static const gx_device_procs spot_rgb_procs = device_procs(get_spotrgb_color_mapping_procs);
235
const xcf_device gs_xcf_device =
237
prn_device_body_extended(xcf_device, spot_rgb_procs, "xcf",
238
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
239
X_DPI, Y_DPI, /* X and Y hardware resolution */
240
0, 0, 0, 0, /* margins */
241
GX_DEVICE_COLOR_MAX_COMPONENTS, 3, /* MaxComponents, NumComp */
242
GX_CINFO_POLARITY_ADDITIVE, /* Polarity */
243
24, 0, /* Depth, Gray_index, */
244
255, 255, 256, 256, /* MaxGray, MaxColor, DitherGray, DitherColor */
245
GX_CINFO_UNKNOWN_SEP_LIN, /* Let check_device_separable set up values */
246
"DeviceN", /* Process color model name */
247
xcf_print_page), /* Printer page print routine */
248
/* DeviceN device specific parameters */
249
XCF_DEVICE_RGB, /* Color model */
250
8, /* Bits per color - must match ncomp, depth, etc. above */
251
(&DeviceRGBComponents), /* Names of color model colorants */
252
3, /* Number colorants for RGB */
253
{0}, /* SeparationNames */
254
{0} /* SeparationOrder names */
257
static const gx_device_procs spot_cmyk_procs = device_procs(get_xcf_color_mapping_procs);
259
const xcf_device gs_xcfcmyk_device =
261
prn_device_body_extended(xcf_device, spot_cmyk_procs, "xcfcmyk",
262
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
263
X_DPI, Y_DPI, /* X and Y hardware resolution */
264
0, 0, 0, 0, /* margins */
265
GX_DEVICE_COLOR_MAX_COMPONENTS, 4, /* MaxComponents, NumComp */
266
GX_CINFO_POLARITY_SUBTRACTIVE, /* Polarity */
267
32, 0, /* Depth, Gray_index, */
268
255, 255, 256, 256, /* MaxGray, MaxColor, DitherGray, DitherColor */
269
GX_CINFO_UNKNOWN_SEP_LIN, /* Let check_device_separable set up values */
270
"DeviceN", /* Process color model name */
271
xcf_print_page), /* Printer page print routine */
272
/* DeviceN device specific parameters */
273
XCF_DEVICE_CMYK, /* Color model */
274
8, /* Bits per color - must match ncomp, depth, etc. above */
275
(&DeviceCMYKComponents), /* Names of color model colorants */
276
4, /* Number colorants for RGB */
277
{0}, /* SeparationNames */
278
{0} /* SeparationOrder names */
282
* The following procedures are used to map the standard color spaces into
283
* the color components for the spotrgb device.
286
gray_cs_to_spotrgb_cm(gx_device * dev, frac gray, frac out[])
288
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
289
int i = ((xcf_device *)dev)->separation_names.num_names;
291
out[0] = out[1] = out[2] = gray;
292
for(; i>0; i--) /* Clear spot colors */
297
rgb_cs_to_spotrgb_cm(gx_device * dev, const gs_imager_state *pis,
298
frac r, frac g, frac b, frac out[])
300
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
301
int i = ((xcf_device *)dev)->separation_names.num_names;
306
for(; i>0; i--) /* Clear spot colors */
311
cmyk_cs_to_spotrgb_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
313
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
314
int i = ((xcf_device *)dev)->separation_names.num_names;
316
color_cmyk_to_rgb(c, m, y, k, NULL, out, dev->memory);
317
for(; i>0; i--) /* Clear spot colors */
322
gray_cs_to_spotcmyk_cm(gx_device * dev, frac gray, frac out[])
324
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
325
int i = ((xcf_device *)dev)->separation_names.num_names;
327
out[0] = out[1] = out[2] = 0;
328
out[3] = frac_1 - gray;
329
for(; i>0; i--) /* Clear spot colors */
334
rgb_cs_to_spotcmyk_cm(gx_device * dev, const gs_imager_state *pis,
335
frac r, frac g, frac b, frac out[])
337
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
338
xcf_device *xdev = (xcf_device *)dev;
339
int n = xdev->separation_names.num_names;
342
color_rgb_to_cmyk(r, g, b, pis, out, dev->memory);
343
for(i = 0; i < n; i++) /* Clear spot colors */
348
cmyk_cs_to_spotcmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
350
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
351
xcf_device *xdev = (xcf_device *)dev;
352
int n = xdev->separation_names.num_names;
359
for(i = 0; i < n; i++) /* Clear spot colors */
364
cmyk_cs_to_spotn_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
366
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
367
xcf_device *xdev = (xcf_device *)dev;
368
int n = xdev->separation_names.num_names;
370
gcmmhlink_t link = xdev->cmyk_icc_link;
374
unsigned short in[4];
375
unsigned short tmp[MAX_CHAN];
376
int outn = xdev->cmyk_profile->num_comps_out;
378
in[0] = frac2ushort(c);
379
in[1] = frac2ushort(m);
380
in[2] = frac2ushort(y);
381
in[3] = frac2ushort(k);
383
gscms_transform_color(dev, link, &(in[0]), &(tmp[0]), 2);
384
for (i = 0; i < outn; i++)
385
out[i] = ushort2frac(tmp[i]);
386
for (; i < n + 4; i++)
390
/* If no profile given, assume CMYK */
395
for(i = 0; i < n; i++) /* Clear spot colors */
401
gray_cs_to_spotn_cm(gx_device * dev, frac gray, frac out[])
403
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
405
cmyk_cs_to_spotn_cm(dev, 0, 0, 0, frac_1 - gray, out);
409
rgb_cs_to_spotn_cm(gx_device * dev, const gs_imager_state *pis,
410
frac r, frac g, frac b, frac out[])
412
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
413
xcf_device *xdev = (xcf_device *)dev;
414
int n = xdev->separation_names.num_names;
415
gcmmhlink_t link = xdev->rgb_icc_link;
419
unsigned short in[3];
420
unsigned short tmp[MAX_CHAN];
421
int outn = xdev->rgb_profile->num_comps_out;
423
in[0] = frac2ushort(r);
424
in[1] = frac2ushort(g);
425
in[2] = frac2ushort(b);
427
gscms_transform_color(dev, link, &(in[0]), &(tmp[0]), 2);
429
for (i = 0; i < outn; i++)
430
out[i] = ushort2frac(tmp[i]);
431
for (; i < n + 4; i++)
436
color_rgb_to_cmyk(r, g, b, pis, cmyk, dev->memory);
437
cmyk_cs_to_spotn_cm(dev, cmyk[0], cmyk[1], cmyk[2], cmyk[3],
442
static const gx_cm_color_map_procs spotRGB_procs = {
443
gray_cs_to_spotrgb_cm, rgb_cs_to_spotrgb_cm, cmyk_cs_to_spotrgb_cm
446
static const gx_cm_color_map_procs spotCMYK_procs = {
447
gray_cs_to_spotcmyk_cm, rgb_cs_to_spotcmyk_cm, cmyk_cs_to_spotcmyk_cm
450
static const gx_cm_color_map_procs spotN_procs = {
451
gray_cs_to_spotn_cm, rgb_cs_to_spotn_cm, cmyk_cs_to_spotn_cm
455
* These are the handlers for returning the list of color space
456
* to color model conversion routines.
458
static const gx_cm_color_map_procs *
459
get_spotrgb_color_mapping_procs(const gx_device * dev)
461
return &spotRGB_procs;
465
static const gx_cm_color_map_procs *
466
get_spotcmyk_color_mapping_procs(const gx_device * dev)
468
return &spotCMYK_procs;
472
static const gx_cm_color_map_procs *
473
get_xcf_color_mapping_procs(const gx_device * dev)
475
const xcf_device *xdev = (const xcf_device *)dev;
477
if (xdev->color_model == XCF_DEVICE_RGB)
478
return &spotRGB_procs;
479
else if (xdev->color_model == XCF_DEVICE_CMYK)
480
return &spotCMYK_procs;
481
else if (xdev->color_model == XCF_DEVICE_N)
488
* Encode a list of colorant values into a gx_color_index_value.
490
static gx_color_index
491
xcf_encode_color(gx_device *dev, const gx_color_value colors[])
493
int bpc = ((xcf_device *)dev)->bitspercomponent;
494
gx_color_index color = 0;
496
int ncomp = dev->color_info.num_components;
500
for (; i<ncomp; i++) {
502
color |= COLROUND_ROUND(colors[i]);
504
return (color == gx_no_color_index ? color ^ 1 : color);
508
* Decode a gx_color_index value back to a list of colorant values.
511
xcf_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
513
int bpc = ((xcf_device *)dev)->bitspercomponent;
514
int mask = (1 << bpc) - 1;
516
int ncomp = dev->color_info.num_components;
520
for (; i<ncomp; i++) {
521
out[ncomp - i - 1] = COLDUP_DUP(color & mask);
528
* Convert a gx_color_index to RGB.
531
xcf_map_color_rgb(gx_device *dev, gx_color_index color, gx_color_value rgb[3])
533
xcf_device *xdev = (xcf_device *)dev;
535
if (xdev->color_model == XCF_DEVICE_RGB)
536
return xcf_decode_color(dev, color, rgb);
537
/* TODO: return reasonable values. */
545
* This routine will extract a specified set of bits from a buffer and pack
546
* them into a given buffer.
549
* source - The source of the data
550
* dest - The destination for the data
551
* depth - The size of the bits per pixel - must be a multiple of 8
552
* first_bit - The location of the first data bit (LSB).
553
* bit_width - The number of bits to be extracted.
554
* npixel - The number of pixels.
557
* Length of the output line (in bytes)
562
repack_data(byte * source, byte * dest, int depth, int first_bit,
563
int bit_width, int npixel)
565
int in_nbyte = depth >> 3; /* Number of bytes per input pixel */
566
int out_nbyte = bit_width >> 3; /* Number of bytes per output pixel */
567
gx_color_index mask = 1;
569
int i, j, length = 0;
570
int in_byte_loc = 0, out_byte_loc = 0;
573
int max_bit_byte = 8 - bit_width;
575
mask = (mask << bit_width) - 1;
576
for (i=0; i<npixel; i++) {
577
/* Get the pixel data */
578
if (!in_nbyte) { /* Multiple pixels per byte */
580
data >>= in_byte_loc;
581
in_byte_loc += depth;
582
if (in_byte_loc >= 8) { /* If finished with byte */
587
else { /* One or more bytes per pixel */
589
for (j=1; j<in_nbyte; j++)
590
data = (data << 8) + *source++;
595
/* Put the output data */
596
if (!out_nbyte) { /* Multiple pixels per byte */
597
temp = *out & ~(mask << out_byte_loc);
598
*out = temp | (data << out_byte_loc);
599
out_byte_loc += bit_width;
600
if (out_byte_loc > max_bit_byte) { /* If finished with byte */
605
else { /* One or more bytes per pixel */
606
*out++ = data >> ((out_nbyte - 1) * 8);
607
for (j=1; j<out_nbyte; j++) {
608
*out++ = data >> ((out_nbyte - 1 - j) * 8);
612
/* Return the number of bytes in the destination buffer. */
614
if (out_byte_loc) /* If partially filled last byte */
621
xcf_open_profile(const char *profile_out_fn, cmm_profile_t *icc_profile, gcmmhlink_t icc_link, gs_memory_t *memory)
624
gsicc_rendering_param_t rendering_params;
626
icc_profile = gsicc_get_profile_handle_file(profile_out_fn,
627
strlen(profile_out_fn), memory);
629
if (icc_profile == NULL)
630
return gs_throw(-1, "Could not create profile for xcf device");
632
/* Set up the rendering parameters */
634
rendering_params.black_point_comp = gsBPNOTSPECIFIED;
635
rendering_params.graphics_type_tag = GS_UNKNOWN_TAG; /* Already rendered */
636
rendering_params.rendering_intent = gsPERCEPTUAL;
638
/* Call with a NULL destination profile since we are using a device link profile here */
639
icc_link = gscms_get_link(icc_profile,
640
NULL, &rendering_params, memory);
642
if (icc_link == NULL)
643
return gs_throw(-1, "Could not create link handle for xdev device");
650
xcf_open_profiles(xcf_device *xdev)
654
if (xdev->output_icc_link == NULL && xdev->profile_out_fn[0]) {
656
code = xcf_open_profile(xdev->profile_out_fn, xdev->output_profile,
657
xdev->output_icc_link, xdev->memory);
661
if (code >= 0 && xdev->rgb_icc_link == NULL && xdev->profile_rgb_fn[0]) {
663
code = xcf_open_profile(xdev->profile_rgb_fn, xdev->rgb_profile,
664
xdev->rgb_icc_link, xdev->memory);
668
if (code >= 0 && xdev->cmyk_icc_link == NULL && xdev->profile_cmyk_fn[0]) {
670
code = xcf_open_profile(xdev->profile_cmyk_fn, xdev->cmyk_profile,
671
xdev->cmyk_icc_link, xdev->memory);
678
#define set_param_array(a, d, s)\
679
(a.data = d, a.size = s, a.persistent = false);
681
/* Get parameters. We provide a default CRD. */
683
xcf_get_params(gx_device * pdev, gs_param_list * plist)
685
xcf_device *xdev = (xcf_device *)pdev;
688
gs_param_string_array scna;
690
gs_param_string prgbs;
691
gs_param_string pcmyks;
693
set_param_array(scna, NULL, 0);
695
if ( (code = gdev_prn_get_params(pdev, plist)) < 0 ||
696
(code = sample_device_crd_get_params(pdev, plist, "CRDDefault")) < 0 ||
697
(code = param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
698
(code = param_write_bool(plist, "Separations", &seprs)) < 0)
701
pos.data = (const byte *)xdev->profile_out_fn,
702
pos.size = strlen(xdev->profile_out_fn),
703
pos.persistent = false;
704
code = param_write_string(plist, "ProfileOut", &pos);
708
prgbs.data = (const byte *)xdev->profile_rgb_fn,
709
prgbs.size = strlen(xdev->profile_rgb_fn),
710
prgbs.persistent = false;
711
code = param_write_string(plist, "ProfileRgb", &prgbs);
713
pcmyks.data = (const byte *)xdev->profile_cmyk_fn,
714
pcmyks.size = strlen(xdev->profile_cmyk_fn),
715
pcmyks.persistent = false;
716
code = param_write_string(plist, "ProfileCmyk", &prgbs);
720
#undef set_param_array
722
#define compare_color_names(name, name_size, str, str_size) \
723
(name_size == str_size && \
724
(strncmp((const char *)name, (const char *)str, name_size) == 0))
727
* This routine will check if a name matches any item in a list of process model
728
* color component names.
731
check_process_color_names(const fixed_colorant_names_list * pcomp_list,
732
const gs_param_string * pstring)
735
const fixed_colorant_name * plist = *pcomp_list;
736
uint size = pstring->size;
739
if (compare_color_names(*plist, strlen(*plist), pstring->data, size)) {
749
* This utility routine calculates the number of bits required to store
750
* color information. In general the values are rounded up to an even
751
* byte boundary except those cases in which mulitple pixels can evenly
752
* into a single byte.
755
* ncomp - The number of components (colorants) for the device. Valid
756
* values are 1 to GX_DEVICE_COLOR_MAX_COMPONENTS
757
* bpc - The number of bits per component. Valid values are 1, 2, 4, 5,
759
* Input values are not tested for validity.
762
bpc_to_depth(int ncomp, int bpc)
764
static const byte depths[4][8] = {
765
{1, 2, 0, 4, 8, 0, 0, 8},
766
{2, 4, 0, 8, 16, 0, 0, 16},
767
{4, 8, 0, 16, 16, 0, 0, 24},
768
{4, 8, 0, 16, 32, 0, 0, 32}
771
if (ncomp <=4 && bpc <= 8)
772
return depths[ncomp -1][bpc-1];
774
return (ncomp * bpc + 7) & ~7;
777
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
779
switch (code = pread(plist, (param_name = pname), &(pa))) {\
781
if ((pa).size != psize) {\
782
ecode = gs_note_error(gs_error_rangecheck);\
783
(pa).data = 0; /* mark as not filled */\
785
#define END_ARRAY_PARAM(pa, e)\
789
e: param_signal_error(plist, param_name, ecode);\
791
(pa).data = 0; /* mark as not filled */\
796
xcf_param_read_fn(gs_param_list *plist, const char *name,
797
gs_param_string *pstr, int max_len)
799
int code = param_read_string(plist, name, pstr);
802
if (pstr->size >= max_len)
803
param_signal_error(plist, name, code = gs_error_rangecheck);
810
/* Compare a C string and a gs_param_string. */
812
param_string_eq(const gs_param_string *pcs, const char *str)
814
return (strlen(str) == pcs->size &&
815
!strncmp(str, (const char *)pcs->data, pcs->size));
819
xcf_set_color_model(xcf_device *xdev, xcf_color_model color_model)
821
xdev->color_model = color_model;
822
if (color_model == XCF_DEVICE_GRAY) {
823
xdev->std_colorant_names = &DeviceGrayComponents;
824
xdev->num_std_colorant_names = 1;
825
xdev->color_info.cm_name = "DeviceGray";
826
xdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
827
} else if (color_model == XCF_DEVICE_RGB) {
828
xdev->std_colorant_names = &DeviceRGBComponents;
829
xdev->num_std_colorant_names = 3;
830
xdev->color_info.cm_name = "DeviceRGB";
831
xdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
832
} else if (color_model == XCF_DEVICE_CMYK) {
833
xdev->std_colorant_names = &DeviceCMYKComponents;
834
xdev->num_std_colorant_names = 4;
835
xdev->color_info.cm_name = "DeviceCMYK";
836
xdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
837
} else if (color_model == XCF_DEVICE_N) {
838
xdev->std_colorant_names = &DeviceCMYKComponents;
839
xdev->num_std_colorant_names = 4;
840
xdev->color_info.cm_name = "DeviceN";
841
xdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
850
* Close device and clean up ICC structures.
854
xcf_prn_close(gx_device *dev)
856
xcf_device * const xdev = (xcf_device *) dev;
858
if (xdev->cmyk_icc_link != NULL) {
859
gscms_release_link(xdev->cmyk_icc_link);
860
rc_decrement(xdev->cmyk_profile, "xcf_prn_close");
863
if (xdev->rgb_icc_link != NULL) {
864
gscms_release_link(xdev->rgb_icc_link);
865
rc_decrement(xdev->rgb_profile, "xcf_prn_close");
868
if (xdev->output_icc_link != NULL) {
869
gscms_release_link(xdev->output_icc_link);
870
rc_decrement(xdev->output_profile, "xcf_prn_close");
873
return gdev_prn_close(dev);
876
/* Set parameters. We allow setting the number of bits per component. */
878
xcf_put_params(gx_device * pdev, gs_param_list * plist)
880
xcf_device * const pdevn = (xcf_device *) pdev;
881
gx_device_color_info save_info;
882
gs_param_name param_name;
884
int num_spot = pdevn->separation_names.num_names;
887
gs_param_string_array scna;
889
gs_param_string prgb;
890
gs_param_string pcmyk;
892
xcf_color_model color_model = pdevn->color_model;
894
BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames", scna, scna.size, scne) {
896
} END_ARRAY_PARAM(scna, scne);
899
code = xcf_param_read_fn(plist, "ProfileOut", &po,
900
sizeof(pdevn->profile_out_fn));
902
code = xcf_param_read_fn(plist, "ProfileRgb", &prgb,
903
sizeof(pdevn->profile_rgb_fn));
905
code = xcf_param_read_fn(plist, "ProfileCmyk", &pcmyk,
906
sizeof(pdevn->profile_cmyk_fn));
909
code = param_read_name(plist, "ProcessColorModel", &pcm);
911
if (param_string_eq (&pcm, "DeviceGray"))
912
color_model = XCF_DEVICE_GRAY;
913
else if (param_string_eq (&pcm, "DeviceRGB"))
914
color_model = XCF_DEVICE_RGB;
915
else if (param_string_eq (&pcm, "DeviceCMYK"))
916
color_model = XCF_DEVICE_CMYK;
917
else if (param_string_eq (&pcm, "DeviceN"))
918
color_model = XCF_DEVICE_N;
920
param_signal_error(plist, "ProcessColorModel",
921
code = gs_error_rangecheck);
928
* Save the color_info in case gdev_prn_put_params fails, and for
931
save_info = pdevn->color_info;
932
ecode = xcf_set_color_model(pdevn, color_model);
934
ecode = gdev_prn_put_params(pdev, plist);
936
pdevn->color_info = save_info;
940
/* Separations are only valid with a subrtractive color model */
941
if (pdev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
943
* Process the separation color names. Remove any names that already
944
* match the process color model colorant names for the device.
946
if (scna.data != 0) {
948
int num_names = scna.size;
949
const fixed_colorant_names_list * pcomp_names =
950
((xcf_device *)pdev)->std_colorant_names;
952
for (i = num_spot = 0; i < num_names; i++) {
953
if (!check_process_color_names(pcomp_names, &scna.data[i]))
954
pdevn->separation_names.names[num_spot++] = &scna.data[i];
956
pdevn->separation_names.num_names = num_spot;
958
gs_closedevice(pdev);
960
npcmcolors = pdevn->num_std_colorant_names;
961
pdevn->color_info.num_components = npcmcolors + num_spot;
963
* The DeviceN device can have zero components if nothing has been
964
* specified. This causes some problems so force at least one
965
* component until something is specified.
967
if (!pdevn->color_info.num_components)
968
pdevn->color_info.num_components = 1;
969
pdevn->color_info.depth = bpc_to_depth(pdevn->color_info.num_components,
970
pdevn->bitspercomponent);
971
if (pdevn->color_info.depth != save_info.depth) {
972
gs_closedevice(pdev);
977
memcpy(pdevn->profile_out_fn, po.data, po.size);
978
pdevn->profile_out_fn[po.size] = 0;
980
if (prgb.data != 0) {
981
memcpy(pdevn->profile_rgb_fn, prgb.data, prgb.size);
982
pdevn->profile_rgb_fn[prgb.size] = 0;
984
if (pcmyk.data != 0) {
985
memcpy(pdevn->profile_cmyk_fn, pcmyk.data, pcmyk.size);
986
pdevn->profile_cmyk_fn[pcmyk.size] = 0;
988
code = xcf_open_profiles(pdevn);
994
* This routine will check to see if the color component name match those
995
* that are available amoung the current device's color components.
998
* dev - pointer to device data structure.
999
* pname - pointer to name (zero termination not required)
1000
* nlength - length of the name
1002
* This routine returns a positive value (0 to n) which is the device colorant
1003
* number if the name is found. It returns a negative value if not found.
1006
xcf_get_color_comp_index(gx_device * dev, const char * pname, int name_size,
1009
/* TO_DO_DEVICEN This routine needs to include the effects of the SeparationOrder array */
1010
const fixed_colorant_names_list * list = ((const xcf_device *)dev)->std_colorant_names;
1011
const fixed_colorant_name * pcolor = *list;
1012
int color_component_number = 0;
1015
/* Check if the component is in the implied list. */
1018
if (compare_color_names(pname, name_size, *pcolor, strlen(*pcolor)))
1019
return color_component_number;
1021
color_component_number++;
1025
/* Check if the component is in the separation names list. */
1027
const gs_separation_names * separations = &((const xcf_device *)dev)->separation_names;
1028
int num_spot = separations->num_names;
1030
for (i=0; i<num_spot; i++) {
1031
if (compare_color_names((const char *)separations->names[i]->data,
1032
separations->names[i]->size, pname, name_size)) {
1033
return color_component_number;
1035
color_component_number++;
1042
/* ------ Private definitions ------ */
1044
/* All two-byte quantities are stored MSB-first! */
1045
#if arch_is_big_endian
1046
# define assign_u16(a,v) a = (v)
1047
# define assign_u32(a,v) a = (v)
1049
# define assign_u16(a,v) a = ((v) >> 8) + ((v) << 8)
1050
# define assign_u32(a,v) a = (((v) >> 24) & 0xff) + (((v) >> 8) & 0xff00) + (((v) & 0xff00) << 8) + (((v) & 0xff) << 24)
1059
int base_bytes_pp; /* almost always 3 (rgb) */
1060
int n_extra_channels;
1067
/* byte offset of image data */
1071
#define TILE_WIDTH 64
1072
#define TILE_HEIGHT 64
1075
xcf_calc_levels(int size, int tile_size)
1078
while (size > tile_size) {
1086
xcf_setup_tiles(xcf_write_ctx *xc, xcf_device *dev)
1088
xc->base_bytes_pp = 3;
1089
xc->n_extra_channels = dev->separation_names.num_names;
1090
xc->width = dev->width;
1091
xc->height = dev->height;
1092
xc->n_tiles_x = (dev->width + TILE_WIDTH - 1) / TILE_WIDTH;
1093
xc->n_tiles_y = (dev->height + TILE_HEIGHT - 1) / TILE_HEIGHT;
1094
xc->n_tiles = xc->n_tiles_x * xc->n_tiles_y;
1095
xc->n_levels = max(xcf_calc_levels(dev->width, TILE_WIDTH),
1096
xcf_calc_levels(dev->height, TILE_HEIGHT));
1101
/* Return value: Size of tile in pixels. */
1103
xcf_tile_sizeof(xcf_write_ctx *xc, int tile_idx)
1105
int tile_i = tile_idx % xc->n_tiles_x;
1106
int tile_j = tile_idx / xc->n_tiles_x;
1107
int tile_size_x = min(TILE_WIDTH, xc->width - tile_i * TILE_WIDTH);
1108
int tile_size_y = min(TILE_HEIGHT, xc->height - tile_j * TILE_HEIGHT);
1109
return tile_size_x * tile_size_y;
1113
xcf_write(xcf_write_ctx *xc, const byte *buf, int size) {
1116
code = fwrite(buf, 1, size, xc->f);
1124
xcf_write_32(xcf_write_ctx *xc, bits32 v)
1129
return xcf_write(xc, (byte *)&buf, 4);
1133
xcf_write_image_props(xcf_write_ctx *xc)
1137
xcf_write_32(xc, 0);
1138
xcf_write_32(xc, 0);
1144
* Return value: Number of bytes needed to write layer.
1147
xcf_base_size(xcf_write_ctx *xc, const char *layer_name)
1149
int bytes_pp = xc->base_bytes_pp + xc->n_extra_channels;
1151
return 17 + strlen (layer_name) + /* header and name */
1152
8 + /* layer props */
1153
12 + xc->n_levels * 16 + /* layer tile hierarchy */
1154
12 + xc->n_tiles * 4 + /* tile offsets */
1155
xc->width * xc->height * bytes_pp; /* image data */
1159
xcf_channel_size(xcf_write_ctx *xc, int name_size)
1161
return 17 + name_size + /* header and name */
1162
8 + /* channel props */
1163
4 + xc->n_levels * 16 + /* channel tile hiearchy */
1164
12 + xc->n_tiles * 4; /* tile offsets */
1168
xcf_write_header(xcf_write_ctx *xc, xcf_device *pdev)
1171
const char *layer_name = "Background";
1175
int n_extra_channels = xc->n_extra_channels;
1176
int bytes_pp = xc->base_bytes_pp + n_extra_channels;
1179
xcf_write(xc, (const byte *)"gimp xcf file", 14);
1180
xcf_write_32(xc, xc->width);
1181
xcf_write_32(xc, xc->height);
1182
xcf_write_32(xc, 0);
1184
xcf_write_image_props(xc);
1187
xcf_write_32(xc, xc->offset + 12 + 4 * n_extra_channels);
1188
xcf_write_32(xc, 0);
1190
/* channel offsets */
1191
tile_offset = xc->offset + 4 + 4 * n_extra_channels +
1192
xcf_base_size(xc, layer_name);
1193
for (channel_idx = 0; channel_idx < n_extra_channels; channel_idx++) {
1194
const gs_param_string *separation_name =
1195
pdev->separation_names.names[channel_idx];
1196
dmlprintf1(pdev->memory, "tile offset: %d\n", tile_offset);
1197
xcf_write_32(xc, tile_offset);
1198
tile_offset += xcf_channel_size(xc, separation_name->size);
1200
xcf_write_32(xc, 0);
1203
xcf_write_32(xc, xc->width);
1204
xcf_write_32(xc, xc->height);
1205
xcf_write_32(xc, 0);
1206
xcf_write_32(xc, strlen(layer_name) + 1);
1207
xcf_write(xc, (const byte *)layer_name, strlen(layer_name) + 1);
1210
xcf_write_32(xc, 0);
1211
xcf_write_32(xc, 0);
1213
/* layer tile hierarchy */
1214
xcf_write_32(xc, xc->offset + 8);
1215
xcf_write_32(xc, 0);
1217
xcf_write_32(xc, xc->width);
1218
xcf_write_32(xc, xc->height);
1219
xcf_write_32(xc, xc->base_bytes_pp);
1220
xcf_write_32(xc, xc->offset + (1 + xc->n_levels) * 4);
1221
tile_offset = xc->offset + xc->width * xc->height * bytes_pp +
1222
xc->n_tiles * 4 + 12;
1223
for (level = 1; level < xc->n_levels; level++) {
1224
xcf_write_32(xc, tile_offset);
1227
xcf_write_32(xc, 0);
1229
/* layer tile offsets */
1230
xcf_write_32(xc, xc->width);
1231
xcf_write_32(xc, xc->height);
1232
tile_offset = xc->offset + (xc->n_tiles + 1) * 4;
1233
for (tile_idx = 0; tile_idx < xc->n_tiles; tile_idx++) {
1234
xcf_write_32(xc, tile_offset);
1235
tile_offset += xcf_tile_sizeof(xc, tile_idx) * bytes_pp;
1237
xcf_write_32(xc, 0);
1239
xc->image_data_off = xc->offset;
1245
xcf_shuffle_to_tile(xcf_write_ctx *xc, byte **tile_data, const byte *row,
1248
int tile_j = y / TILE_HEIGHT;
1249
int yrem = y % TILE_HEIGHT;
1251
int base_bytes_pp = xc->base_bytes_pp;
1252
int n_extra_channels = xc->n_extra_channels;
1255
for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
1257
int tile_width = min(TILE_WIDTH, xc->width - tile_i * TILE_WIDTH);
1258
int tile_height = min(TILE_HEIGHT, xc->height - tile_j * TILE_HEIGHT);
1259
byte *base_ptr = tile_data[tile_i] +
1260
yrem * tile_width * base_bytes_pp;
1261
int extra_stride = tile_width * tile_height;
1262
byte *extra_ptr = tile_data[tile_i] + extra_stride * base_bytes_pp +
1267
for (x = 0; x < tile_width; x++) {
1269
for (plane_idx = 0; plane_idx < base_bytes_pp; plane_idx++)
1270
base_ptr[base_idx++] = row[row_idx++];
1271
for (plane_idx = 0; plane_idx < n_extra_channels; plane_idx++)
1272
extra_ptr[plane_idx * extra_stride + x] = 255 ^ row[row_idx++];
1278
xcf_icc_to_tile(gx_device_printer *pdev, xcf_write_ctx *xc, byte **tile_data, const byte *row,
1279
int y, gcmmhlink_t link)
1281
int tile_j = y / TILE_HEIGHT;
1282
int yrem = y % TILE_HEIGHT;
1284
int base_bytes_pp = xc->base_bytes_pp;
1285
int n_extra_channels = xc->n_extra_channels;
1288
for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
1290
int tile_width = min(TILE_WIDTH, xc->width - tile_i * TILE_WIDTH);
1291
int tile_height = min(TILE_HEIGHT, xc->height - tile_j * TILE_HEIGHT);
1292
byte *base_ptr = tile_data[tile_i] +
1293
yrem * tile_width * base_bytes_pp;
1294
int extra_stride = tile_width * tile_height;
1295
byte *extra_ptr = tile_data[tile_i] + extra_stride * base_bytes_pp +
1300
for (x = 0; x < tile_width; x++) {
1304
/* This loop could be optimized. I don't quite
1305
understand what is going on in the loop
1306
with the 255^row[row_idx++] operation */
1308
gscms_transform_color((gx_device*) pdev, link,
1309
(void *) (&(row[row_idx])),
1310
&(base_ptr[base_idx]), 1);
1312
for (plane_idx = 0; plane_idx < n_extra_channels; plane_idx++)
1313
extra_ptr[plane_idx * extra_stride + x] = 255 ^ row[row_idx++];
1319
xcf_write_image_data(xcf_write_ctx *xc, gx_device_printer *pdev)
1322
int raster = gdev_prn_raster(pdev);
1326
int base_bytes_pp = xc->base_bytes_pp;
1327
int n_extra_channels = xc->n_extra_channels;
1328
int bytes_pp = base_bytes_pp + n_extra_channels;
1330
xcf_device *xdev = (xcf_device *)pdev;
1331
gcmmhlink_t link = xdev->output_icc_link;
1333
line = gs_alloc_bytes(pdev->memory, raster, "xcf_write_image_data");
1334
tile_data = (byte **)gs_alloc_bytes(pdev->memory,
1335
xc->n_tiles_x * sizeof(byte *),
1336
"xcf_write_image_data");
1337
for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
1338
int tile_bytes = xcf_tile_sizeof(xc, tile_i) * bytes_pp;
1340
tile_data[tile_i] = gs_alloc_bytes(pdev->memory, tile_bytes,
1341
"xcf_write_image_data");
1343
for (tile_j = 0; tile_j < xc->n_tiles_y; tile_j++) {
1348
y0 = tile_j * TILE_HEIGHT;
1349
y1 = min(xc->height, y0 + TILE_HEIGHT);
1350
for (y = y0; y < y1; y++) {
1351
code = gdev_prn_get_bits(pdev, y, line, &row);
1353
xcf_shuffle_to_tile(xc, tile_data, row, y);
1355
xcf_icc_to_tile(pdev, xc, tile_data, row, y, link);
1357
for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
1358
int tile_idx = tile_j * xc->n_tiles_x + tile_i;
1359
int tile_size = xcf_tile_sizeof(xc, tile_idx);
1360
int base_size = tile_size * base_bytes_pp;
1362
xcf_write(xc, tile_data[tile_i], base_size);
1363
for (chan_idx = 0; chan_idx < n_extra_channels; chan_idx++) {
1364
xcf_write(xc, tile_data[tile_i] + base_size +
1365
tile_size * chan_idx, tile_size);
1370
for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
1371
gs_free_object(pdev->memory, tile_data[tile_i],
1372
"xcf_write_image_data");
1374
gs_free_object(pdev->memory, tile_data, "xcf_write_image_data");
1375
gs_free_object(pdev->memory, line, "xcf_write_image_data");
1380
xcf_write_fake_hierarchy(xcf_write_ctx *xc)
1382
int widthf = xc->width, heightf = xc->height;
1385
for (i = 1; i < xc->n_levels; i++) {
1388
xcf_write_32(xc, widthf);
1389
xcf_write_32(xc, heightf);
1390
xcf_write_32(xc, 0);
1396
xcf_write_footer(xcf_write_ctx *xc, xcf_device *pdev)
1399
int base_bytes_pp = xc->base_bytes_pp;
1400
int n_extra_channels = xc->n_extra_channels;
1401
int bytes_pp = base_bytes_pp + n_extra_channels;
1404
xcf_write_fake_hierarchy(xc);
1406
for (chan_idx = 0; chan_idx < xc->n_extra_channels; chan_idx++) {
1407
const gs_param_string *separation_name =
1408
pdev->separation_names.names[chan_idx];
1409
byte nullbyte[] = { 0 };
1414
dmlprintf2(pdev->memory, "actual tile offset: %d %d\n", xc->offset, (int)arch_sizeof_color_index);
1415
xcf_write_32(xc, xc->width);
1416
xcf_write_32(xc, xc->height);
1417
xcf_write_32(xc, separation_name->size + 1);
1418
xcf_write(xc, separation_name->data, separation_name->size);
1419
xcf_write(xc, nullbyte, 1);
1422
xcf_write_32(xc, 0);
1423
xcf_write_32(xc, 0);
1425
/* channel tile hierarchy */
1426
xcf_write_32(xc, xc->offset + 4);
1428
xcf_write_32(xc, xc->width);
1429
xcf_write_32(xc, xc->height);
1430
xcf_write_32(xc, 1);
1431
xcf_write_32(xc, xc->offset + xc->n_levels * 16 - 8);
1432
offset = xc->offset + xc->n_levels * 4;
1433
for (level = 1; level < xc->n_levels; level++) {
1434
xcf_write_32(xc, offset);
1437
xcf_write_32(xc, 0);
1438
xcf_write_fake_hierarchy(xc);
1440
/* channel tile offsets */
1441
xcf_write_32(xc, xc->width);
1442
xcf_write_32(xc, xc->height);
1443
offset = xc->image_data_off;
1444
for (tile_idx = 0; tile_idx < xc->n_tiles; tile_idx++) {
1445
int tile_size = xcf_tile_sizeof(xc, tile_idx);
1447
xcf_write_32(xc, offset + (base_bytes_pp + chan_idx) * tile_size);
1448
offset += bytes_pp * tile_size;
1450
xcf_write_32(xc, 0);
1457
xcf_print_page(gx_device_printer *pdev, FILE *file)
1464
xcf_setup_tiles(&xc, (xcf_device *)pdev);
1465
xcf_write_header(&xc, (xcf_device *)pdev);
1466
xcf_write_image_data(&xc, pdev);
1467
xcf_write_footer(&xc, (xcf_device *)pdev);