1 #include "config.h"
2
3 #include <string.h>
4 #include <stdlib.h>
5
6 /****h* libAfterImage/tutorials/ASScale
7 * NAME
8 * ASScale
9 * SYNOPSIS
10 * Simple program based on libAfterImage to scale an image.
11 * DESCRIPTION
12 * We will load image and scale it up to new size, specified as command
13 * line arguments
14 * We then display the result in simple window.
15 * After that we would want to wait, until user closes our window.
16 *
17 * In this tutorial we will only explain new steps, not described in
18 * previous tutorial. New steps described in this tutorial are :
19 * ASScale.1. Parsing geometry spec.
20 * ASScale.2. Scaling ASImage.
21 * SEE ALSO
22 * Tutorial 1: ASView - explanation of basic steps needed to use
23 * libAfterImage and some other simple things.
24 * SOURCE
25 */
26
27 #include "../afterbase.h"
28 #include "../afterimage.h"
29 #include "common.h"
30
usage()31 void usage()
32 {
33 printf( "Usage: asscale [-h]|[image [WIDTH[xHEIGHT]]]\n");
34 printf( "Where: image - is image filename.\n");
35 printf( " WIDTH - width to scale image to.( Naturally :)\n");
36 printf( " HEIGHT- height to scale image to.\n");
37 }
38
main(int argc,char * argv[])39 int main(int argc, char* argv[])
40 {
41 char *image_file = "rose512.jpg" ;
42 int dummy, geom_flags = 0;
43 unsigned int to_width, to_height ;
44 ASImage *im ;
45 int clip_x = 0, clip_y = 0, clip_width = 0, clip_height = 0 ;
46 int slice_x_start = 0, slice_x_end = 0, slice_y_start = 0, slice_y_end = 0 ;
47 Bool slice_scale = False ;
48 Display *dpy = NULL;
49
50 /* see ASView.1 : */
51 set_application_name( argv[0] );
52
53 if( argc > 1 )
54 {
55 int i = 2;
56 if( strncmp( argv[1], "-h", 2 ) == 0 )
57 {
58 usage();
59 return 0;
60 }
61 image_file = argv[1] ;
62 if( argc > 2 ) /* see ASScale.1 : */
63 geom_flags = XParseGeometry( argv[2], &dummy, &dummy,
64 &to_width, &to_height );
65
66 while( ++i < argc )
67 {
68 if( strncmp( argv[i], "-sx1", 4 ) == 0 && i+1 < argc )
69 slice_x_start = atoi(argv[++i]) ;
70 else if( strncmp( argv[i], "-sx2", 4 ) == 0 && i+1 < argc )
71 slice_x_end = atoi(argv[++i]) ;
72 else if( strncmp( argv[i], "-sy1", 4 ) == 0 && i+1 < argc )
73 slice_y_start = atoi(argv[++i]) ;
74 else if( strncmp( argv[i], "-sy2", 4 ) == 0 && i+1 < argc )
75 slice_y_end = atoi(argv[++i]) ;
76 else if( strncmp( argv[i], "-cx", 4 ) == 0 && i+1 < argc )
77 clip_x = atoi(argv[++i]) ;
78 else if( strncmp( argv[i], "-cy", 4 ) == 0 && i+1 < argc )
79 clip_y = atoi(argv[++i]) ;
80 else if( strncmp( argv[i], "-cwidth", 7 ) == 0 && i+1 < argc )
81 clip_width = atoi(argv[++i]) ;
82 else if( strncmp( argv[i], "-cheight", 8 ) == 0 && i+1 < argc )
83 clip_height = atoi(argv[++i]) ;
84 else if( strncmp( argv[i], "-ss", 3 ) == 0 )
85 slice_scale = True ;
86 }
87
88
89 }else
90 {
91 show_warning( "no image file or scale geometry - defaults used:"
92 " \"%s\" ",
93 image_file );
94 usage();
95 }
96 /* see ASView.2 : */
97 im = file2ASImage( image_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, getenv("IMAGE_PATH"), NULL );
98
99 if( im != NULL )
100 {
101 ASVisual *asv ;
102 ASImage *scaled_im ;
103 /* Making sure tiling geometry is sane : */
104 if( !get_flags(geom_flags, WidthValue ) )
105 to_width = im->width*2 ;
106 if( !get_flags(geom_flags, HeightValue ) )
107 to_height = im->height*2;
108 printf( "%s: scaling image \"%s\" to %dx%d by factor of %fx%f\n",
109 get_application_name(), image_file, to_width, to_height,
110 (double)to_width/(double)(im->width),
111 (double)to_height/(double)(im->height) );
112
113 #ifndef X_DISPLAY_MISSING
114 {
115 Window w ;
116 int screen, depth ;
117
118 dpy = XOpenDisplay(NULL);
119 _XA_WM_DELETE_WINDOW = XInternAtom( dpy,
120 "WM_DELETE_WINDOW",
121 False);
122 screen = DefaultScreen(dpy);
123 depth = DefaultDepth( dpy, screen );
124 /* see ASView.3 : */
125 asv = create_asvisual( dpy, screen, depth, NULL );
126 /* see ASView.4 : */
127 w = create_top_level_window( asv, DefaultRootWindow(dpy),
128 32, 32,
129 to_width, to_height, 1, 0, NULL,
130 "ASScale", image_file );
131 if( w != None )
132 {
133 Pixmap p ;
134
135 XMapRaised (dpy, w);
136 /* see ASScale.2 : */
137 if( slice_x_start == 0 && slice_x_end == 0 &&
138 slice_y_start == 0 && slice_y_end == 0 )
139 {
140 scaled_im = scale_asimage2( asv, im,
141 clip_x, clip_y, clip_width, clip_height,
142 to_width, to_height,
143 ASA_XImage, 0,
144 ASIMAGE_QUALITY_DEFAULT );
145 }else
146 {
147 scaled_im = slice_asimage2( asv, im, slice_x_start, slice_x_end,
148 slice_y_start, slice_y_end,
149 to_width, to_height, slice_scale,
150 ASA_XImage, 0,
151 ASIMAGE_QUALITY_DEFAULT );
152 }
153 destroy_asimage( &im );
154 /* see ASView.5 : */
155 p = asimage2pixmap(asv, DefaultRootWindow(dpy), scaled_im,
156 NULL, True );
157 /* print_storage(NULL); */
158 destroy_asimage( &scaled_im );
159 /* see common.c: set_window_background_and_free() : */
160 p = set_window_background_and_free( w, p );
161 }
162 /* see common.c: wait_closedown() : */
163 wait_closedown(w);
164 dpy = NULL;
165 }
166 #else
167 asv = create_asvisual( NULL, 0, 0, NULL );
168 scaled_im = scale_asimage(asv, im, to_width, to_height,
169 ASA_ASImage, 0,
170 ASIMAGE_QUALITY_DEFAULT );
171 /* writing result into the file */
172 ASImage2file( scaled_im, NULL, "asscale.jpg", ASIT_Jpeg, NULL );
173 destroy_asimage( &scaled_im );
174 destroy_asimage( &im );
175 #endif
176 }
177 return 0 ;
178 }
179 /**************/
180
181 /****f* libAfterImage/tutorials/ASScale.1 [2.1]
182 * SYNOPSIS
183 * Step 1. Parsing the geometry.
184 * DESCRIPTION
185 * Geometry can be specified in WIDTHxHEIGHT+X+Y format. Accordingly we
186 * use standard X function to parse it: XParseGeometry. Returned flags
187 * tell us what values has been specified. Since we only need size -
188 * we check if it is specified and if not - simply default it to twice
189 * as big as original image. Accordingly we use dummy variable to pass
190 * to XParseGeometry.
191 * EXAMPLE
192 * geom_flags = XParseGeometry( argv[3], &dummy, &dummy,
193 * &to_width, &to_height );
194 ********/
195 /****f* libAfterImage/tutorials/ASScale.2 [2.2]
196 * SYNOPSIS
197 * Step 2. Actual scaling the image.
198 * DESCRIPTION
199 * scale_asimage() scales image both up and down, and is very easy to
200 * use - just pass it new size. In this example we use default quality.
201 * Default is equivalent to GOOD which should be sufficient in
202 * most cases. Compression is set to 0 since we do not intend to store
203 * image for long time. Even better - we don't need to store it at all -
204 * all we need is XImage, so we can transfer it to the server easily.
205 * That is why to_xim argument is set to ASA_XImage. As the result obtained
206 * ASImage will not have any data in its buffers, but it will have
207 * ximage member set to point to valid XImage. Subsequently we enjoy
208 * that convenience, by setting use_cached to True in call to
209 * asimage2pixmap. That ought to save us alot of processing.
210 *
211 * Scaling algorithm is rather sophisticated and is implementing 4 point
212 * interpolation. Which basically means that we try to approximate each
213 * missing point as an extension of the trend of 4 neighboring points -
214 * two on each side. Closest neighbor's have more weight then outside
215 * ones. 2D scaling is performed by scaling each scanline first, and
216 * then interpolating missing scanlines.
217 * Scaling down is somewhat skimpier, as it amounts to simple averaging
218 * of the multiple pixels. All calculations are done in integer math on
219 * per channel basis, and with precision 24.8 bits per channel per pixel.
220 *
221 * EXAMPLE
222 * scaled_im = scale_asimage( asv, im, to_width, to_height,
223 * ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT );
224 * destroy_asimage( &im );
225 * NOTES
226 * Scaling image up to very large height is much slower then to same
227 * width due to algorithm specifics. Yet even on inferior hardware it
228 * yields decent speeds.
229 * When we successfully scaled image - we no longer need the original -
230 * getting rid of it so it does not clog memory.
231 * SEE ALSO
232 * scale_asimage().
233 ********/
234