Root/
Source at commit f4ff8931231afa35765fbd0c149c6b7ba9ecffb4 created 13 years 9 months ago. By Xiangfu Liu, update to 0.2.1 | |
---|---|
1 | // imgv, a simple SDL-based image viewer for the Ben Nanonote |
2 | // Version 0.2.1 |
3 | // Last edited by Fernando Carello <fcarello@libero.it> 2010-05-24 |
4 | // |
5 | #include <stdlib.h> |
6 | #include <unistd.h> |
7 | #include <SDL/SDL.h> |
8 | #include <SDL/SDL_image.h> |
9 | #include <SDL/SDL_rotozoom.h> |
10 | |
11 | #define TRUE 1 |
12 | #define FALSE 0 |
13 | #define SCREENWIDTH 320 |
14 | #define SCREENHEIGHT 240 |
15 | #define SCREENBPP 32 |
16 | #define SMOOTHING_OFF 0 |
17 | #define SMOOTHING_ON 1 |
18 | #define PANSTEP 40 |
19 | #define ZOOMSTEP 0.05 |
20 | |
21 | int main(int argc, char *argv[]) |
22 | { |
23 | SDL_Surface *screen = NULL, |
24 | *scaled_img = NULL, |
25 | *temp_img = NULL, |
26 | *picture = NULL; |
27 | SDL_Event event; |
28 | SDL_Rect picturePortion, |
29 | screenPortion; |
30 | int imgWidth, |
31 | imgHeight, |
32 | smoothing = SMOOTHING_ON, |
33 | fPressed, |
34 | zPressed, |
35 | iPressed, |
36 | oPressed, |
37 | alreadyFit, |
38 | pixelFit, |
39 | lPressed, |
40 | rPressed, |
41 | leftPressed, |
42 | rightPressed, |
43 | upPressed, |
44 | downPressed; |
45 | char sFilename[255] = "\0", |
46 | sVersion[] = "0.2.1"; |
47 | double scale_x = 1.0, |
48 | scale_y = 1.0, |
49 | scale = 1.0; |
50 | |
51 | |
52 | atexit(SDL_Quit); |
53 | |
54 | // Process command line |
55 | if (argc != 2) |
56 | { |
57 | fprintf (stderr, "\n imgv v%s. Syntax: imgv <image file>\n\n Hotkeys:\n 'f' fit to screen\n 'z' zoom at pixel level\n 'i' zoom in 'o' zoom out\n 'l' rotate left 'r' rotate right\n 'arrows' pan 'ESC' quit\n\n", sVersion); |
58 | exit (1); |
59 | } |
60 | strncpy (sFilename, argv[1], 254); |
61 | |
62 | // Initialize the SDL library |
63 | if (SDL_Init(SDL_INIT_VIDEO) < 0) |
64 | { |
65 | fprintf(stderr, "\n Couldn't initialize SDL: %s\n\n", SDL_GetError()); |
66 | exit(1); |
67 | } |
68 | |
69 | // Load Picture |
70 | temp_img = IMG_Load(sFilename); |
71 | if (temp_img == (SDL_Surface *) (NULL)) |
72 | { |
73 | fprintf(stderr, "\n Couldn't load image file %s: %s\n\n", sFilename, SDL_GetError()); |
74 | exit (1); |
75 | } |
76 | |
77 | // Set video mode |
78 | screen = SDL_SetVideoMode |
79 | (SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWACCEL); |
80 | if (screen == (SDL_Surface *) (NULL)) |
81 | { |
82 | fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n\n", SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SDL_GetError()); |
83 | exit(1); |
84 | } |
85 | |
86 | // Can't stand the useless arrow... Ben has no pointing device |
87 | SDL_ShowCursor(SDL_DISABLE); |
88 | |
89 | // Convert picture in same format as video framebuffer, to optimize blit performances |
90 | picture = SDL_DisplayFormat (temp_img); |
91 | if (picture == (SDL_Surface *) (NULL)) |
92 | { |
93 | fprintf(stderr, "\n Internal error from DisplayFormat\n\n"); |
94 | exit (1); |
95 | } |
96 | SDL_FreeSurface (temp_img); |
97 | |
98 | imgWidth = picture->w; |
99 | imgHeight = picture->h; |
100 | |
101 | // Starting point (default view): uniform scaling to best screen fit, keep aspect ratio |
102 | scale_x = (double) (SCREENWIDTH) / (double) (imgWidth); |
103 | scale_y = (double) (SCREENHEIGHT) / (double) (imgHeight); |
104 | if (scale_y < scale_x) |
105 | scale = scale_y; |
106 | else |
107 | scale = scale_x; |
108 | scaled_img = zoomSurface (picture, scale, scale, SMOOTHING_ON); |
109 | if (scaled_img == (SDL_Surface *) (NULL)) |
110 | { |
111 | fprintf (stderr, "\n Error from zoomSurface()\n\n"); |
112 | exit (1); |
113 | } |
114 | |
115 | screenPortion.x = 0; // destination coordinates: origin |
116 | screenPortion.y = 0; |
117 | picturePortion.x = 0; |
118 | picturePortion.y = 0; |
119 | picturePortion.w = (Uint16) imgWidth; |
120 | picturePortion.h = (Uint16) imgHeight; |
121 | |
122 | // off-cycle: first image drawing |
123 | SDL_FillRect(screen, NULL, 0); // draw background color (black) |
124 | SDL_BlitSurface(scaled_img, &picturePortion, screen, &screenPortion); |
125 | SDL_Flip(screen); |
126 | |
127 | leftPressed = FALSE; |
128 | rightPressed = FALSE; |
129 | upPressed = FALSE; |
130 | downPressed = FALSE; |
131 | fPressed = FALSE; |
132 | zPressed = FALSE; |
133 | lPressed = FALSE; |
134 | rPressed = FALSE; |
135 | iPressed = FALSE; |
136 | oPressed = FALSE; |
137 | pixelFit = FALSE; |
138 | alreadyFit = TRUE; |
139 | |
140 | while(1) |
141 | { |
142 | if (SDL_WaitEvent( &event )) |
143 | { |
144 | // We only process SDL_KEYDOWN and SDL_KEYUP events |
145 | switch (event.type) |
146 | { |
147 | case SDL_KEYDOWN: |
148 | switch (event.key.keysym.sym) |
149 | { |
150 | case SDLK_LEFT: |
151 | leftPressed = TRUE; |
152 | break; |
153 | case SDLK_RIGHT: |
154 | rightPressed = TRUE; |
155 | break; |
156 | case SDLK_DOWN: |
157 | downPressed = TRUE; |
158 | break; |
159 | case SDLK_f: |
160 | fPressed = TRUE; |
161 | break; |
162 | case SDLK_z: |
163 | zPressed = TRUE; |
164 | break; |
165 | case SDLK_i: |
166 | iPressed = TRUE; |
167 | break; |
168 | case SDLK_o: |
169 | oPressed = TRUE; |
170 | break; |
171 | case SDLK_l: |
172 | lPressed = TRUE; |
173 | break; |
174 | case SDLK_r: |
175 | rPressed = TRUE; |
176 | break; |
177 | case SDLK_UP: |
178 | upPressed = TRUE; |
179 | break; |
180 | case SDLK_ESCAPE: |
181 | if (picture) |
182 | SDL_FreeSurface (picture); |
183 | if (scaled_img) |
184 | SDL_FreeSurface (scaled_img); |
185 | if (screen) |
186 | SDL_FreeSurface (screen); |
187 | exit(0); |
188 | default: |
189 | break; |
190 | } |
191 | break; |
192 | case SDL_KEYUP: |
193 | switch (event.key.keysym.sym) |
194 | { |
195 | case SDLK_LEFT: |
196 | leftPressed = FALSE; |
197 | break; |
198 | case SDLK_RIGHT: |
199 | rightPressed = FALSE; |
200 | break; |
201 | case SDLK_DOWN: |
202 | downPressed = FALSE; |
203 | break; |
204 | case SDLK_UP: |
205 | upPressed = FALSE; |
206 | break; |
207 | case SDLK_f: |
208 | fPressed = FALSE; |
209 | break; |
210 | case SDLK_z: |
211 | zPressed = FALSE; |
212 | break; |
213 | case SDLK_i: |
214 | iPressed = FALSE; |
215 | break; |
216 | case SDLK_o: |
217 | oPressed = FALSE; |
218 | break; |
219 | case SDLK_l: |
220 | lPressed = FALSE; |
221 | break; |
222 | case SDLK_r: |
223 | rPressed = FALSE; |
224 | break; |
225 | default: |
226 | break; |
227 | } |
228 | break; |
229 | } // end of switch (event.type) |
230 | |
231 | // Process commands |
232 | if (fPressed && !alreadyFit) |
233 | { // Fit image to screen |
234 | if (scaled_img != (SDL_Surface *) (NULL)) |
235 | SDL_FreeSurface (scaled_img); // since zoomSurface() creates a new surface every time |
236 | alreadyFit = TRUE; |
237 | pixelFit = FALSE; |
238 | scale_x = (double) (SCREENWIDTH) / (double) (imgWidth); |
239 | scale_y = (double) (SCREENHEIGHT) / (double) (imgHeight); |
240 | if (scale_y < scale_x) |
241 | scale = scale_y; |
242 | else |
243 | scale = scale_x; |
244 | picturePortion.x = 0; |
245 | picturePortion.y = 0; |
246 | picturePortion.w = (Uint16) imgWidth; |
247 | picturePortion.h = (Uint16) imgHeight; |
248 | scaled_img = zoomSurface (picture, scale, scale, smoothing); |
249 | if (scaled_img == (SDL_Surface *) (NULL)) |
250 | { |
251 | fprintf (stderr, "\n Error from zoomSurface()\n\n"); |
252 | exit (1); |
253 | } |
254 | } |
255 | if (zPressed && !pixelFit) |
256 | { // Zoom at 1:1 (100% zoom / actual pixels) |
257 | if (scaled_img != (SDL_Surface *) (NULL)) |
258 | SDL_FreeSurface (scaled_img); |
259 | alreadyFit = FALSE; |
260 | pixelFit = TRUE; |
261 | picturePortion.w = (Uint16) SCREENWIDTH; |
262 | picturePortion.h = (Uint16) SCREENHEIGHT; |
263 | scale = 1.0; |
264 | scaled_img = SDL_ConvertSurface (picture, picture->format, picture->flags); |
265 | if (scaled_img == (SDL_Surface *) (NULL)) |
266 | { |
267 | fprintf (stderr, "\n Error from ConvertSurface()\n\n"); |
268 | exit (1); |
269 | } |
270 | } |
271 | if (iPressed) |
272 | { // Zoom in |
273 | if (scaled_img != (SDL_Surface *) (NULL)) |
274 | SDL_FreeSurface (scaled_img); |
275 | alreadyFit = FALSE; |
276 | pixelFit = FALSE; |
277 | scale += ZOOMSTEP; |
278 | picturePortion.w = (Uint16) ((double) (imgWidth) * scale); |
279 | if ( (picturePortion.w - picturePortion.x) >= imgWidth ) |
280 | picturePortion.w = imgWidth - picturePortion.x; |
281 | if (picturePortion.w < 1) |
282 | picturePortion.w = 1; |
283 | picturePortion.h = (Uint16) ((double) (imgHeight) * scale); |
284 | if ( (picturePortion.h - picturePortion.y) >= imgHeight ) |
285 | picturePortion.h = imgHeight - picturePortion.y; |
286 | if (picturePortion.h < 1) |
287 | picturePortion.h = 1; |
288 | scaled_img = zoomSurface (picture, scale, scale, smoothing); |
289 | //scaled_img = rotozoomSurface (picture, 0, scale, SMOOTHING_ON); |
290 | |
291 | if (scaled_img == (SDL_Surface *) (NULL)) |
292 | { |
293 | fprintf (stderr, "\n Error from zoomSurface()\n\n"); |
294 | exit (1); |
295 | } |
296 | } |
297 | if (oPressed) |
298 | { // Zoom out |
299 | if (scaled_img != (SDL_Surface *) (NULL)) |
300 | SDL_FreeSurface (scaled_img); |
301 | alreadyFit = FALSE; |
302 | pixelFit = FALSE; |
303 | scale -= ZOOMSTEP; |
304 | if (scale <= 0.0) |
305 | scale = 0.01; |
306 | picturePortion.w = (Uint16) ((double) (imgWidth) * scale); |
307 | if ( (picturePortion.w - picturePortion.x) >= imgWidth) |
308 | picturePortion.w = imgWidth - picturePortion.x; |
309 | if (picturePortion.w < 1) |
310 | picturePortion.w = 1; |
311 | picturePortion.h = (Uint16) ((double) (imgHeight) * scale); |
312 | if ( (picturePortion.h - picturePortion.y) >= imgHeight ) |
313 | picturePortion.h = imgHeight - picturePortion.y; |
314 | if (picturePortion.h < 1) |
315 | picturePortion.h = 1; |
316 | |
317 | scaled_img = zoomSurface (picture, scale, scale, smoothing); |
318 | //scaled_img = rotozoomSurface (picture, 0, scale, SMOOTHING_ON); |
319 | if (scaled_img == (SDL_Surface *) (NULL)) |
320 | { |
321 | fprintf (stderr, "\n Error from zoomSurface()\n\n"); |
322 | exit (1); |
323 | } |
324 | } |
325 | |
326 | if (lPressed) |
327 | { // Rotate left 90° |
328 | if (scaled_img != (SDL_Surface *) (NULL)) |
329 | temp_img = scaled_img; |
330 | else |
331 | { |
332 | fprintf (stderr, "\n Error: NULL scaled_img\n\n"); |
333 | exit (1); |
334 | } |
335 | alreadyFit = FALSE; |
336 | scaled_img = rotozoomSurface (temp_img, -90, 1.0, SMOOTHING_OFF); |
337 | SDL_FreeSurface (temp_img); |
338 | if (scaled_img == (SDL_Surface *) (NULL)) |
339 | { |
340 | fprintf (stderr, "\n Error from rotozoomSurface()\n\n"); |
341 | exit (1); |
342 | } |
343 | } |
344 | if (rPressed) |
345 | { // Rotate right 90° |
346 | if (scaled_img != (SDL_Surface *) (NULL)) |
347 | temp_img = scaled_img; |
348 | else |
349 | { |
350 | fprintf (stderr, "\n Error: NULL scaled_img\n\n"); |
351 | exit (1); |
352 | } |
353 | alreadyFit = FALSE; |
354 | scaled_img = rotozoomSurface (temp_img, 90, 1.0, SMOOTHING_OFF); |
355 | SDL_FreeSurface (temp_img); |
356 | if (scaled_img == (SDL_Surface *) (NULL)) |
357 | { |
358 | fprintf (stderr, "\n Error from rotozoomSurface()\n\n"); |
359 | exit (1); |
360 | } |
361 | } |
362 | |
363 | if (leftPressed) |
364 | { |
365 | picturePortion.x -= PANSTEP; |
366 | if (picturePortion.x < 0) |
367 | picturePortion.x = 0; |
368 | alreadyFit = FALSE; |
369 | } |
370 | if (rightPressed) |
371 | { |
372 | picturePortion.x += PANSTEP; |
373 | if (picturePortion.x >= imgWidth) |
374 | picturePortion.x = (Sint16) (imgWidth - 1); |
375 | alreadyFit = FALSE; |
376 | } |
377 | if (upPressed) |
378 | { |
379 | picturePortion.y -= PANSTEP; |
380 | if (picturePortion.y < 0) |
381 | picturePortion.y = 0; |
382 | alreadyFit = FALSE; |
383 | } |
384 | if (downPressed) |
385 | { |
386 | picturePortion.y += PANSTEP; |
387 | if (picturePortion.y >= imgHeight) |
388 | picturePortion.y = (Sint16) (imgHeight - 1); |
389 | alreadyFit = FALSE; |
390 | } |
391 | |
392 | SDL_FillRect(screen, (SDL_Rect *) NULL, 0); // draw background color (black) |
393 | SDL_BlitSurface(scaled_img, &picturePortion, screen, &screenPortion); |
394 | SDL_Flip(screen); |
395 | } // end of if(SDL_WaitEvent()) |
396 | } // end of while(1) |
397 | |
398 | return 0; |
399 | } |
400 | |
401 |
Branches:
master