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
|
/* Copyright (C) 2001-2020 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
Refer to licensing information at http://www.artifex.com or contact
Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
CA 94945, U.S.A., +1(415)492-9861, for further information.
*/
/* Generic image rendering interface */
/* Requires gsstate.h */
#ifndef gsimage_INCLUDED
# define gsimage_INCLUDED
#include "gsiparam.h"
#include "gsdevice.h"
/*
The API defined in this file and implemented in gsimage.c provides a
layer of buffering between clients and the underlying image processing
interface defined in gxdevcli.h (begin_[typed_]image device procedure) and
gxiparam.h (image processing procedures).
Two of the underlying image processing procedures defined in gxiparam.h
define and process the actual data:
- The underlying planes_wanted image processing procedure indicates which
data planes are needed (not necessarily all of them, in the case of
images with differently scaled planes), and may also change the widths
and/or depths of the planes. It may return different results at
different times, if the widths, depths, or planes wanted changes in the
course of the image.
- The underlying plane_data procedure actually processes the image. Each
call of plane_data requires an integral number of scan lines for each
wanted plane. If the widths, depths, or planes wanted vary from call to
call, plane_data may choose to accept fewer scan lines than provided.
If this happens, it is the client's responsibility to call planes_wanted
to find out which planes are now wanted, and then call plane_data again
with data for (only) the wanted planes.
Conceptually, the gs_image_next_planes procedure defined here provides the
same function as the plane_data procedure, except that:
- The data need not consist of complete scan lines, or be aligned in any
way;
- If a single call passes multiple scan lines for a single plane, each
scan line is only padded to a byte boundary, not to an alignment
boundary;
- Different amounts of data (including none) may be passed for each plane,
independent of which planes need data or the amount of data that makes
up a complete scan line for a plane;
- The amount actually used is returned as a count of bytes used
(separately for each plane) rather than a count of scan lines.
There is one added complication. To avoid allocating large amounts of
storage, gs_image_next_planes may choose to copy only part of the data,
retaining the rest of it by reference. Clients must be informed about
this, since if the data is in a stream buffer, the data may move. To
accommodate this possibility, on subsequent calls, any data passed by the
client for a plane with retained data *replaces* the retained data rather
than (as one might expect) appending to it; if the client passes no data
for that plane, the retained data stays retained if needed.
gs_image_next_planes returns information about retained data on each call,
so the client need not keep track of it.
The gs_image_planes_wanted procedure is analogous to planes_wanted. It
identifies a plane as wanted if both of the following are true:
- The underlying planes_wanted procedure says the plane is wanted.
- Less than a full scan line of data is already buffered for that plane
(including retained data if any).
This is not sufficient information for the PostScript interpreter for the
case where the data sources are procedures, which must be called in a
cyclic order even if they return less than a full scan line. For this
case, the interpreter must keep track of a plane index itself, cycling
through the planes that gs_image_planes_wanted says are wanted (which may
vary from cycle to cycle).
There is an older, simpler procedure gs_image_next that simply cycles
through the planes in order. It does not offer the option of replacing
retained data, of passing data for more than one plane at a time, or of
passing data for planes in an arbitrary order. Consequently, it is only
usable with image types where all planes are always wanted. gs_image_next
should also only be used when all planes have the same width and depth and
the same amount of data is passed for each plane in a given cycle of
calls. This is not currently checked; however, gs_image_next will give an
error if an attempt is made to pass data for a plane that has any retained
data.
*/
/*
* The image painting interface uses an enumeration style:
* the client initializes an enumerator, then supplies data incrementally.
*/
/*
* Create an image enumerator given image parameters and a graphics state.
* This calls the device's begin_typed_image procedure with appropriate
* parameters. Note that this is an enumerator that requires entire
* rows of data, not the buffered enumerator used by the procedures below:
* for this reason, we may move the prototype elsewhere in the future.
*/
typedef struct gx_image_enum_common_s gx_image_enum_common_t;
typedef struct gs_image_enum_s gs_image_enum;
int gs_image_begin_typed(const gs_image_common_t * pic, gs_gstate * pgs,
bool uses_color, bool image_is_text,
gx_image_enum_common_t ** ppie);
gs_image_enum *gs_image_enum_alloc(gs_memory_t *, client_name_t);
/*
* gs_image_init returns 1 for an empty image, 0 normally, <0 on error.
* Note that gs_image_init serves for both image and imagemask,
* depending on the value of ImageMask in the image structure.
*/
/* Initialize the common part of the image class */
int gs_image_common_init(gs_image_enum * penum,
gx_image_enum_common_t * pie,
const gs_data_image_t * pim, gx_device * dev);
/* Initialize an enumerator for an ImageType 1 image. */
int gs_image_init(gs_image_enum * penum, const gs_image_t * pim,
bool MultipleDataSources, bool image_is_text, gs_gstate * pgs);
/* Initialize an enumerator for a general image.
penum->memory must be initialized in advance.
*/
int gs_image_enum_init(gs_image_enum * penum,
gx_image_enum_common_t * pie,
const gs_data_image_t * pim, gs_gstate *pgs);
/*
* Return the number of bytes of data per row
* (per plane, if there are multiple planes).
*/
uint gs_image_bytes_per_plane_row(const gs_image_enum * penum, int plane);
#define gs_image_bytes_per_row(penum)\
gs_image_bytes_per_plane_row(penum, 0)
/*
* Return a byte vector indicating which planes (still) need data for the
* current row. See above for details.
*/
const byte *gs_image_planes_wanted(gs_image_enum *penum);
/*
* Pass multiple or selected planes of data for an image. See above for
* details.
*
* plane_data[] is an array of size num_planes of gs_const_string type
* which contains the pointer and the length for each.
* used[] is also of size num_planes and will be set to the number of
* bytes consumed for each plane.
*
* The amount of data available for a plane (i.e., the size of a
* plane_data[] element) can be 0 in order to provide data for a single
* plane or only some of the planes. Note that if data is retained,
* it is not "consumed": e.g., if all of the data for a given plane is
* retained, used[] for that plane will be set to 0.
*
* Returns 1 if end of image, < 0 error code, otherwise 0. In any case,
* stores pointers to the retained strings into plane_data[]. Note that
* used[] and plane_data[] are set even in the error or end-of-image case.
*/
int gs_image_next_planes(gs_image_enum *penum, gs_const_string *plane_data,
uint *used);
/* Pass the next plane of data for an image. See above for details. */
int gs_image_next(gs_image_enum * penum, const byte * dbytes,
uint dsize, uint * pused);
/* Clean up after processing an image. */
int gs_image_cleanup(gs_image_enum * penum, gs_gstate *pgs);
/* Clean up after processing an image and free the enumerator. */
int gs_image_cleanup_and_free_enum(gs_image_enum * penum, gs_gstate *pgs);
#endif /* gsimage_INCLUDED */
|