1 /* make an xy index image
2 *
3 * 21/4/04
4 * - from im_grey
5 * 1/2/11
6 * - gtk-doc
7 * 31/10/11
8 * - redo as a class
9 */
10
11 /*
12
13 This file is part of VIPS.
14
15 VIPS is free software; you can redistribute it and/or modify
16 it under the terms of the GNU Lesser General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 02110-1301 USA
29
30 */
31
32 /*
33
34 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
35
36 */
37
38 /*
39 #define VIPS_DEBUG
40 */
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif /*HAVE_CONFIG_H*/
45 #include <vips/intl.h>
46
47 #include <stdio.h>
48 #include <string.h>
49 #include <stdlib.h>
50
51 #include <vips/vips.h>
52 #include <vips/internal.h>
53 #include <vips/debug.h>
54
55 #include "pcreate.h"
56
57 typedef struct _VipsXyz {
58 VipsCreate parent_instance;
59
60 int width;
61 int height;
62 int csize;
63 int dsize;
64 int esize;
65
66 int dimensions;
67
68 } VipsXyz;
69
70 typedef VipsCreateClass VipsXyzClass;
71
72 G_DEFINE_TYPE( VipsXyz, vips_xyz, VIPS_TYPE_CREATE );
73
74 static int
vips_xyz_gen(VipsRegion * or,void * seq,void * a,void * b,gboolean * stop)75 vips_xyz_gen( VipsRegion *or, void *seq, void *a, void *b,
76 gboolean *stop )
77 {
78 VipsXyz *xyz = (VipsXyz *) a;
79 VipsRect *r = &or->valid;
80 int le = r->left;
81 int to = r->top;
82 int ri = VIPS_RECT_RIGHT( r );
83 int bo = VIPS_RECT_BOTTOM( r );
84
85 int x, y, i;
86
87 for( y = to; y < bo; y++ ) {
88 unsigned int *q = (unsigned int *)
89 VIPS_REGION_ADDR( or, le, y );
90
91 unsigned int dims[5];
92 int r;
93 int h;
94
95 h = xyz->height * xyz->csize * xyz->dsize;
96 dims[4] = y / h;
97 r = y % h;
98
99 h /= xyz->dsize;
100 dims[3] = r / h;
101 r %= h;
102
103 h /= xyz->csize;
104 dims[2] = r / h;
105 r %= h;
106
107 dims[1] = r;
108
109 for( x = le; x < ri; x++ ) {
110 dims[0] = x;
111 for( i = 0; i < xyz->dimensions; i++ )
112 q[i] = dims[i];
113
114 q += xyz->dimensions;
115 }
116 }
117
118 return( 0 );
119 }
120
121 static int
vips_xyz_build(VipsObject * object)122 vips_xyz_build( VipsObject *object )
123 {
124 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
125 VipsCreate *create = VIPS_CREATE( object );
126 VipsXyz *xyz = (VipsXyz *) object;
127
128 double d;
129 int ysize;
130
131 if( VIPS_OBJECT_CLASS( vips_xyz_parent_class )->build( object ) )
132 return( -1 );
133
134 if( (vips_object_argument_isset( object, "dsize" ) &&
135 !vips_object_argument_isset( object, "csize" )) ||
136 (vips_object_argument_isset( object, "esize" ) &&
137 !vips_object_argument_isset( object, "dsize" )) ) {
138 vips_error( class->nickname, "%s",
139 _( "lower dimensions not set" ) );
140 return( -1 );
141 }
142
143 if( vips_object_argument_isset( object, "csize" ) ) {
144 xyz->dimensions += 1;
145
146 if( vips_object_argument_isset( object, "dsize" ) ) {
147 xyz->dimensions += 1;
148
149 if( vips_object_argument_isset( object, "esize" ) )
150 xyz->dimensions += 1;
151 }
152 }
153
154 d = (double) xyz->height * xyz->csize * xyz->dsize * xyz->esize;
155 if( d > INT_MAX ) {
156 vips_error( class->nickname, "%s", _( "image too large" ) );
157 return( -1 );
158 }
159 ysize = d;
160
161 vips_image_init_fields( create->out,
162 xyz->width, ysize, xyz->dimensions,
163 VIPS_FORMAT_UINT, VIPS_CODING_NONE,
164 VIPS_INTERPRETATION_MULTIBAND,
165 1.0, 1.0 );
166 if( vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ) ||
167 vips_image_generate( create->out,
168 NULL, vips_xyz_gen, NULL, xyz, NULL ) )
169 return( -1 );
170
171 return( 0 );
172 }
173
174 static void
vips_xyz_class_init(VipsXyzClass * class)175 vips_xyz_class_init( VipsXyzClass *class )
176 {
177 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
178 VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
179
180 VIPS_DEBUG_MSG( "vips_xyz_class_init\n" );
181
182 gobject_class->set_property = vips_object_set_property;
183 gobject_class->get_property = vips_object_get_property;
184
185 vobject_class->nickname = "xyz";
186 vobject_class->description =
187 _( "make an image where pixel values are coordinates" );
188 vobject_class->build = vips_xyz_build;
189
190 VIPS_ARG_INT( class, "width", 4,
191 _( "Width" ),
192 _( "Image width in pixels" ),
193 VIPS_ARGUMENT_REQUIRED_INPUT,
194 G_STRUCT_OFFSET( VipsXyz, width ),
195 1, VIPS_MAX_COORD, 64 );
196
197 VIPS_ARG_INT( class, "height", 5,
198 _( "Height" ),
199 _( "Image height in pixels" ),
200 VIPS_ARGUMENT_REQUIRED_INPUT,
201 G_STRUCT_OFFSET( VipsXyz, height ),
202 1, VIPS_MAX_COORD, 64 );
203
204 VIPS_ARG_INT( class, "csize", 6,
205 _( "csize" ),
206 _( "Size of third dimension" ),
207 VIPS_ARGUMENT_OPTIONAL_INPUT,
208 G_STRUCT_OFFSET( VipsXyz, csize ),
209 1, VIPS_MAX_COORD, 1 );
210
211 VIPS_ARG_INT( class, "dsize", 7,
212 _( "dsize" ),
213 _( "Size of fourth dimension" ),
214 VIPS_ARGUMENT_OPTIONAL_INPUT,
215 G_STRUCT_OFFSET( VipsXyz, dsize ),
216 1, VIPS_MAX_COORD, 1 );
217
218 VIPS_ARG_INT( class, "esize", 8,
219 _( "esize" ),
220 _( "Size of fifth dimension" ),
221 VIPS_ARGUMENT_OPTIONAL_INPUT,
222 G_STRUCT_OFFSET( VipsXyz, esize ),
223 1, VIPS_MAX_COORD, 1 );
224
225 }
226
227 static void
vips_xyz_init(VipsXyz * xyz)228 vips_xyz_init( VipsXyz *xyz )
229 {
230 xyz->width = 64;
231 xyz->height = 64;
232 xyz->dimensions = 2;
233 xyz->csize = 1;
234 xyz->dsize = 1;
235 xyz->esize = 1;
236 }
237
238 /**
239 * vips_xyz:
240 * @out: (out): output image
241 * @width: horizontal size
242 * @height: vertical size
243 * @...: %NULL-terminated list of optional named arguments
244 *
245 * Optional arguments:
246 *
247 * * @csize: size for third dimension
248 * * @dsize: size for fourth dimension
249 * * @esize: size for fifth dimension
250 *
251 * Create a two-band uint32 image where the elements in the first band have the
252 * value of their x coordinate and elements in the second band have their y
253 * coordinate.
254 *
255 * You can make any image where the value of a pixel is a function of its (x,
256 * y) coordinate by combining this operator with the arithmetic operators.
257 *
258 * Set @csize, @dsize, @esize to generate higher dimensions and add more
259 * bands. The extra dimensions are placed down the vertical axis. Use
260 * vips_grid() to change the layout.
261 *
262 * See also: vips_grey(), vips_grid(), vips_identity().
263 *
264 * Returns: 0 on success, -1 on error
265 */
266 int
vips_xyz(VipsImage ** out,int width,int height,...)267 vips_xyz( VipsImage **out, int width, int height, ... )
268 {
269 va_list ap;
270 int result;
271
272 va_start( ap, height );
273 result = vips_call_split( "xyz", ap, out, width, height );
274 va_end( ap );
275
276 return( result );
277 }
278