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