1asmerge(1) AfterStep X11 window manager asmerge(1)
2
3
4
6 asmerge - demonstrates blending of multiple image using different algo‐
7 rithms libAfterImage/tutorials/ASMerge
8
11 Scaling and blending of arbitrary number of images
12 using libAfterImage.
13
15 We will attempt to interpret command line arguments as sequence of
16 image filenames, geometries and blending types. We'll then try and
17 load all the images, scaling first one to requested size, and
18 blending others at specifyed locations of the first image.
19 We then display the result in simple window.
20 After that we would want to wait, until user closes our window.
21
22 New steps described in this tutorial are :
23 Step 1. Layers.
24 Step 2. Merging methods.
25 Step 3. Layer parameters.
26 Step 4. Actual blending of the set of images.
27
29 Tutorial 1: ASView - explanation of basic steps needed to use
30 libAfterImage and some other simple things.
31 Tutorial 2: ASScale - image scaling basics.
32 Tutorial 3: ASTile - image tiling and tinting
33
35 Source :
36 #include "../afterbase.h"
37 #include "../afterimage.h"
38 #include "common.h"
39
40 char *burning_rose[] =
41 {
42 "asmerge",
43 "rose512.jpg",
44 "add",
45 "back.xpm:512x386",
46 "hue",
47 "fore.xpm:512x386"
48 };
49
50 void usage()
51 {
52 printf( "Usage: asmerge [-h]|[image op1 image1 [op2 image2 [...]]]0);
53 printf( "Where: image - is background image filename0);
54 printf( " image1 - is first overlay's filename0);
55 printf( " op1,op2,... - overlay operation."
56 " Supported operations are :0);
57 list_scanline_merging( stdout,
58 " %-15.15s- %s0);
59 }
60
61 int main(int argc, char* argv[])
62 {
63 ASVisual *asv ;
64 int screen = 0, depth = 0;
65 int to_width = 1, to_height = 1;
66 ASImageLayer *layers ;
67 int layers_num = 0, i;
68 ASImage *merged_im ;
69
70 /* see ASView.1 : */
71 set_application_name( argv[0] );
72 #if (HAVE_AFTERBASE_FLAG==1)
73 set_output_threshold(OUTPUT_LEVEL_DEBUG);
74 #endif
75 if( argc == 2 && strncmp(argv[1],"-h", 2) == 0 )
76 {
77 usage();
78 return 0;
79 }
80 if( argc <= 3 )
81 {
82 show_error( "not enough arguments, please see usage:%s", " ");
83 usage() ;
84 printf( "Using the default,
85 printf( "rose512.jpg add back.xpm:512x386 hue "
86 "fore.xpm:512x3860);
87 argv = &(burning_rose[0]) ;
88 argc = 6;
89 }
90
91 #ifndef X_DISPLAY_MISSING
92 dpy = XOpenDisplay(NULL);
93 _XA_WM_DELETE_WINDOW = XInternAtom( dpy, "WM_DELETE_WINDOW", False);
94 screen = DefaultScreen(dpy);
95 depth = DefaultDepth( dpy, screen );
96 #endif
97 /* see ASView.3 : */
98 asv = create_asvisual( dpy, screen, depth, NULL );
99
100 /* see ASMerge.1 : */
101 layers = safecalloc( argc/2, sizeof(ASImageLayer) );
102
103 for( i = 1 ; i < argc ; i++ )
104 {
105 int x = 0, y = 0;
106 unsigned int width, height ;
107 int geom_flags = 0 ;
108 char *separator;
109 char *filename ;
110 /* see ASMerge.2 */
111 if( i > 1 )
112 {
113 /* see blend_scanlines_name2func() : */
114 if((layers[layers_num].merge_scanlines =
115 blend_scanlines_name2func( argv[i] )) == NULL )
116 continue ;
117 if( ++i >= argc )
118 break;
119 }
120 if( (separator = strchr( argv[i], ':' )) != NULL )
121 { /* see ASTile.1 : */
122 geom_flags = XParseGeometry( separator+1,
123 &x, &y, &width, &height);
124 filename = mystrndup( argv[i], separator-argv[i] );
125 }else
126 filename = argv[i] ;
127 layers[layers_num].im = file2ASImage( filename, 0xFFFFFFFF,
128 SCREEN_GAMMA, 100, getenv("IMAGE_PATH"), NULL );
129 if( filename != argv[i] )
130 free( filename );
131 if( layers[layers_num].im != NULL )
132 {
133 if( !get_flags(geom_flags, WidthValue) )
134 width = layers[layers_num].im->width ;
135 if( !get_flags(geom_flags, HeightValue) )
136 height = layers[layers_num].im->height ;
137 /* see ASMerge.3 : */
138 if( layers[layers_num].merge_scanlines == NULL )
139 layers[layers_num].merge_scanlines =
140 alphablend_scanlines ;
141 layers[layers_num].clip_width = width ;
142 layers[layers_num].clip_height = height ;
143 if( layers_num > 0 )
144 {
145 layers[layers_num].dst_x = x ;
146 layers[layers_num].dst_y = y ;
147 }else
148 {
149 to_width = width ;
150 to_height = height ;
151 if( width != layers[layers_num].im->width ||
152 height != layers[layers_num].im->height )
153 {
154 ASImage *scaled_bottom ;
155 /* see ASScale.2 : */
156 scaled_bottom = scale_asimage( asv,
157 layers[layers_num].im,
158 width, height,
159 False, 100,
160 ASIMAGE_QUALITY_DEFAULT );
161 destroy_asimage( &(layers[layers_num].im) );
162 layers[layers_num].im = scaled_bottom ;
163 }
164 }
165 ++layers_num ;
166 }
167 }
168
169 if( layers_num <= 0 )
170 {
171 show_error( "there is no images to merge. Aborting");
172 return 2;
173 }
174
175 /* see ASMerge.4 */
176 merged_im = merge_layers( asv, layers, layers_num,
177 to_width, to_height,
178 #ifndef X_DISPLAY_MISSING
179 ASA_XImage,
180 #else
181 ASA_ASImage,
182 #endif
183 0, ASIMAGE_QUALITY_DEFAULT );
184 while( --layers_num >= 0 )
185 destroy_asimage( &(layers[layers_num].im) );
186 free( layers );
187
188 if( merged_im )
189 {
190 #ifndef X_DISPLAY_MISSING
191 /* see ASView.4 : */
192 Window w = create_top_level_window( asv, DefaultRootWindow(dpy),
193 32, 32,
194 to_width, to_height,
195 1, 0, NULL,
196 "ASMerge", NULL );
197 if( w != None )
198 {
199 Pixmap p ;
200
201 XMapRaised (dpy, w);
202 /* see ASView.5 : */
203 p = asimage2pixmap( asv, DefaultRootWindow(dpy), merged_im,
204 NULL, True );
205
206 destroy_asimage( &merged_im );
207 /* see common.c: set_window_background_and_free() : */
208 p = set_window_background_and_free( w, p );
209 /* see common.c: wait_closedown() : */
210 wait_closedown(w);
211 }
212 if( dpy )
213 XCloseDisplay (dpy);
214 #else
215 /* writing result into the file */
216 ASImage2file( merged_im, NULL, "asmerge.jpg", ASIT_Jpeg, NULL );
217 destroy_asimage( &merged_im );
218 #endif
219 }
220 #ifdef DEBUG_ALLOCS
221 build_xpm_colormap(NULL);
222 print_unfreed_mem();
223 #endif
224 return 0 ;
225 }
226
228 Step 1. Layers.
229
231 libAfterImage performs blending/merging of different images, using
232 arrays of ASImageLayer structures, with first element representing
233 the bottommost image. Each structure specifies exact position on
234 resulting image where overlay should be blended to, tint of the
235 overlay, size, to which overlay should be tiled, overlay's origin,
236 and overlay's background color. Arbitrary number of layers can be
237 merged whithin single run.
238
239 Accordingly all that is needed to merge bunch of images is to create
240 array of ASImageLayer structures and fill it up appropriately.
241
243 layers = safecalloc( argc/2, sizeof(ASImageLayer) );
244
246 Step 2. Merging methods.
247
249 Each layer can be merged in using its own method. There are about 15
250 different methods implemented in libAfterImage, and user app can
251 implement other methods of its own. To specify method all that is
252 needed is to set merge_scanlines member of ASImageLayer to pointer
253 to the function, implementing specific method.
254
255 libAfterImage provides facility to parse method name strings into
256 actuall function pointers. That could be used to simplifi scripting,
257 etc.
258
260 if((layers[layers_num].merge_scanlines =
261 blend_scanlines_name2func( argv[i] )) == NULL )
262 continue ;
263 NOTE
264 All layers MUST have valid merge_scanlines pointer, even the
265 bottommost layer, despite the fact that it has nothing to be merged
266 with. If merge_scanlines is set to NULL - this layer will be ignored.
267 That could be used to turn on/off particular layers.
268
270 Step 3. Layer parameters.
271
273 Several ASImageLayer members are mandatory and cannot be set to 0.
274 Such as : im - image to be merged; clip_width, clip_height - this will
275 be used to tile the image; merge_scanlines - must be set to a pointer
276 to the function implementing merging method. If any of this is set
277 to 0 - then layer will be ignored. The rest of the parameters are
278 optional. Note thou that tint parameter will tint overlay's RGB
279 components and alpha component, as the result it could be used to
280 make opaque images - semitransparent.
281
283 if( layers[layers_num].merge_scanlines == NULL )
284 layers[layers_num].merge_scanlines =
285 alphablend_scanlines ;
286 layers[layers_num].clip_width = width ;
287 layers[layers_num].clip_height = height ;
288 if( layers_num > 0 )
289 {
290 layers[layers_num].dst_x = x ;
291 layers[layers_num].dst_y = y ;
292 }
293
295 Step 4. Actual blending of the set of images.
296
298 After set of layers has been prepared - it can be passed to
299 merge_layers() function, that will create new ASImage of specifyed
300 size, and then blend all the layers together to fill this image.
301
303 merged_im = merge_layers( asv, layers, layers_num,
304 to_width, to_height,
305 ASA_ASImage, 0,
306 ASIMAGE_QUALITY_DEFAULT );
307 while( --layers_num >= 0 )
308 destroy_asimage( &(layers[layers_num].im) );
309 free( layers );
310
312 After we've blended layers - we no longer need ASImageLayer array.
313 So proceeding to clean it up, by destroying overlay AsImages first,
314 and then freeing array itself.
315
317 merge_asimage().
318
319
320
3213rd Berkeley Distribution AfterStep v.2.2.6 asmerge(1)