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