xref: /plan9/sys/src/cmd/gs/src/gximage4.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1998, 2000 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gximage4.c,v 1.6 2005/04/13 20:04:46 ray Exp $ */
18 /* ImageType 4 image implementation */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gscspace.h"
23 #include "gsiparm4.h"
24 #include "gxiparam.h"
25 #include "gximage.h"
26 #include "stream.h"
27 
28 /* Forward references */
29 private dev_proc_begin_typed_image(gx_begin_image4);
30 
31 /* Structure descriptor */
32 private_st_gs_image4();
33 
34 /* Define the image type for ImageType 4 images. */
35 private image_proc_sput(gx_image4_sput);
36 private image_proc_sget(gx_image4_sget);
37 private image_proc_release(gx_image4_release);
38 const gx_image_type_t gs_image_type_4 = {
39     &st_gs_image4, gx_begin_image4, gx_data_image_source_size,
40     gx_image4_sput, gx_image4_sget, gx_image4_release, 4
41 };
42 /*
43  * The implementation is shared with ImageType 1, so we don't need our own
44  * enum_procs.
45  */
46 /*
47   private const gx_image_enum_procs_t image4_enum_procs = {
48     gx_image1_plane_data, gx_image1_end_image
49   };
50 */
51 
52 /* Initialize an ImageType 4 image. */
53 void
gs_image4_t_init(gs_image4_t * pim,const gs_color_space * color_space)54 gs_image4_t_init(gs_image4_t * pim, const gs_color_space * color_space)
55 {
56     gs_pixel_image_t_init((gs_pixel_image_t *) pim, color_space);
57     pim->type = &gs_image_type_4;
58     pim->MaskColor_is_range = false;
59 }
60 
61 /* Start processing an ImageType 4 image. */
62 private int
gx_begin_image4(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)63 gx_begin_image4(gx_device * dev,
64 		const gs_imager_state * pis, const gs_matrix * pmat,
65 		const gs_image_common_t * pic, const gs_int_rect * prect,
66 		const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
67 		gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
68 {
69     gx_image_enum *penum;
70     const gs_image4_t *pim = (const gs_image4_t *)pic;
71     int code = gx_image_enum_alloc(pic, prect, mem, &penum);
72 
73     if (code < 0)
74 	return code;
75     penum->alpha = gs_image_alpha_none;
76     penum->masked = false;
77     penum->adjust = fixed_0;
78     /* Check that MaskColor values are within the valid range. */
79     {
80 	bool opaque = false;
81 	uint max_value = (1 << pim->BitsPerComponent) - 1;
82 	int spp = cs_num_components(pim->ColorSpace);
83 	int i;
84 
85 	for (i = 0; i < spp * 2; i += 2) {
86 	    uint c0, c1;
87 
88 	    if (pim->MaskColor_is_range)
89 		c0 = pim->MaskColor[i], c1 = pim->MaskColor[i + 1];
90 	    else
91 		c0 = c1 = pim->MaskColor[i >> 1];
92 
93 	    if ((c0 | c1) > max_value) {
94 		gs_free_object(mem, penum, "gx_begin_image4");
95 		return_error(gs_error_rangecheck);
96 	    }
97 	    if (c0 > c1) {
98 		opaque = true;	/* pixel can never match mask color */
99 		break;
100 	    }
101 	    penum->mask_color.values[i] = c0;
102 	    penum->mask_color.values[i + 1] = c1;
103 	}
104 	penum->use_mask_color = !opaque;
105     }
106     code = gx_image_enum_begin(dev, pis, pmat, pic, pdcolor, pcpath, mem,
107 			       penum);
108     if (code >= 0)
109 	*pinfo = (gx_image_enum_common_t *)penum;
110     return code;
111 }
112 
113 /* Serialization */
114 
115 private int
gx_image4_sput(const gs_image_common_t * pic,stream * s,const gs_color_space ** ppcs)116 gx_image4_sput(const gs_image_common_t *pic, stream *s,
117 	       const gs_color_space **ppcs)
118 {
119     const gs_image4_t *pim = (const gs_image4_t *)pic;
120     bool is_range = pim->MaskColor_is_range;
121     int code = gx_pixel_image_sput((const gs_pixel_image_t *)pim, s, ppcs,
122 				   is_range);
123     int num_values =
124 	gs_color_space_num_components(pim->ColorSpace) * (is_range ? 2 : 1);
125     int i;
126 
127     if (code < 0)
128 	return code;
129     for (i = 0; i < num_values; ++i)
130 	sput_variable_uint(s, pim->MaskColor[i]);
131     *ppcs = pim->ColorSpace;
132     return 0;
133 }
134 
135 private int
gx_image4_sget(gs_image_common_t * pic,stream * s,const gs_color_space * pcs)136 gx_image4_sget(gs_image_common_t *pic, stream *s,
137 	       const gs_color_space *pcs)
138 {
139     gs_image4_t *const pim = (gs_image4_t *)pic;
140     int num_values;
141     int i;
142     int code = gx_pixel_image_sget((gs_pixel_image_t *)pim, s, pcs);
143 
144     if (code < 0)
145 	return code;
146     pim->type = &gs_image_type_4;
147     pim->MaskColor_is_range = code;
148     num_values =
149 	gs_color_space_num_components(pcs) *
150 	(pim->MaskColor_is_range ? 2 : 1);
151     for (i = 0; i < num_values; ++i)
152 	sget_variable_uint(s, &pim->MaskColor[i]);
153     return 0;
154 }
155 
156 private void
gx_image4_release(gs_image_common_t * pic,gs_memory_t * mem)157 gx_image4_release(gs_image_common_t *pic, gs_memory_t *mem)
158 {
159     gx_pixel_image_release((gs_pixel_image_t *)pic, mem);
160 }
161