main.c
上传用户:hengzhunsh
上传日期:2013-09-07
资源大小:19k
文件大小:13k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /*
  2. fbv  --  simple image viewer for the linux framebuffer
  3. Copyright (C) 2000, 2001, 2003, 2004  Mateusz 'mteg' Golicz
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include <stdio.h>
  17. #include <sys/time.h>
  18. #include <sys/types.h>
  19. #include <unistd.h>
  20. #include <getopt.h>
  21. #include <stdlib.h>
  22. #include <termios.h>
  23. #include <string.h>
  24. #include <signal.h>
  25. #include "config.h"
  26. #include "fbv.h"
  27. #define PAN_STEPPING 20
  28. static int opt_clear = 1,
  29.    opt_alpha = 0,
  30.    opt_hide_cursor = 1,
  31.    opt_image_info = 1,
  32.    opt_stretch = 0,
  33.    opt_delay = 0,
  34.    opt_enlarge = 0,
  35.    opt_ignore_aspect = 0;
  36. void setup_console(int t)
  37. {
  38. struct termios our_termios;
  39. static struct termios old_termios;
  40. if(t)
  41. {
  42. tcgetattr(0, &old_termios);
  43. memcpy(&our_termios, &old_termios, sizeof(struct termios));
  44. our_termios.c_lflag &= !(ECHO | ICANON);
  45. tcsetattr(0, TCSANOW, &our_termios);
  46. }
  47. else
  48. tcsetattr(0, TCSANOW, &old_termios);
  49. }
  50. static inline void do_rotate(struct image *i, int rot)
  51. {
  52. if(rot)
  53. {
  54. unsigned char *image, *alpha = NULL;
  55. int t;
  56. image = rotate(i->rgb, i->width, i->height, rot);
  57. if(i->alpha)
  58. alpha = alpha_rotate(i->alpha, i->width, i->height, rot);
  59. if(i->do_free)
  60. {
  61. free(i->alpha);
  62. free(i->rgb);
  63. }
  64. i->rgb = image;
  65. i->alpha = alpha;
  66. i->do_free = 1;
  67. if(rot & 1)
  68. {
  69. t = i->width;
  70. i->width = i->height;
  71. i->height = t;
  72. }
  73. }
  74. }
  75. static inline void do_enlarge(struct image *i, int screen_width, int screen_height, int ignoreaspect)
  76. {
  77. if(((i->width > screen_width) || (i->height > screen_height)) && (!ignoreaspect))
  78. return;
  79. if((i->width < screen_width) || (i->height < screen_height))
  80. {
  81. int xsize = i->width, ysize = i->height;
  82. unsigned char * image, * alpha = NULL;
  83. if(ignoreaspect)
  84. {
  85. if(i->width < screen_width)
  86. xsize = screen_width;
  87. if(i->height < screen_height)
  88. ysize = screen_height;
  89. goto have_sizes;
  90. }
  91. if((i->height * screen_width / i->width) <= screen_height)
  92. {
  93. xsize = screen_width;
  94. ysize = i->height * screen_width / i->width;
  95. goto have_sizes;
  96. }
  97. if((i->width * screen_height / i->height) <= screen_width)
  98. {
  99. xsize = i->width * screen_height / i->height;
  100. ysize = screen_height;
  101. goto have_sizes;
  102. }
  103. return;
  104. have_sizes:
  105. image = simple_resize(i->rgb, i->width, i->height, xsize, ysize);
  106. if(i->alpha)
  107. alpha = alpha_resize(i->alpha, i->width, i->height, xsize, ysize);
  108. if(i->do_free)
  109. {
  110. free(i->alpha);
  111. free(i->rgb);
  112. }
  113. i->rgb = image;
  114. i->alpha = alpha;
  115. i->do_free = 1;
  116. i->width = xsize;
  117. i->height = ysize;
  118. }
  119. }
  120. static inline void do_fit_to_screen(struct image *i, int screen_width, int screen_height, int ignoreaspect, int cal)
  121. {
  122. if((i->width > screen_width) || (i->height > screen_height))
  123. {
  124. unsigned char * new_image, * new_alpha = NULL;
  125. int nx_size = i->width, ny_size = i->height;
  126. if(ignoreaspect)
  127. {
  128. if(i->width > screen_width)
  129. nx_size = screen_width;
  130. if(i->height > screen_height)
  131. ny_size = screen_height;
  132. }
  133. else
  134. {
  135. if((i->height * screen_width / i->width) <= screen_height)
  136. {
  137. nx_size = screen_width;
  138. ny_size = i->height * screen_width / i->width;
  139. }
  140. else
  141. {
  142. nx_size = i->width * screen_height / i->height;
  143. ny_size = screen_height;
  144. }
  145. }
  146. if(cal)
  147. new_image = color_average_resize(i->rgb, i->width, i->height, nx_size, ny_size);
  148. else
  149. new_image = simple_resize(i->rgb, i->width, i->height, nx_size, ny_size);
  150. if(i->alpha)
  151. new_alpha = alpha_resize(i->alpha, i->width, i->height, nx_size, ny_size);
  152. if(i->do_free)
  153. {
  154. free(i->alpha);
  155. free(i->rgb);
  156. }
  157. i->rgb = new_image;
  158. i->alpha = new_alpha;
  159. i->do_free = 1;
  160. i->width = nx_size;
  161. i->height = ny_size;
  162. }
  163. }
  164. int show_image(char *filename)
  165. {
  166. int (*load)(char *, unsigned char *, unsigned char **, int, int);
  167. unsigned char * image = NULL;
  168. unsigned char * alpha = NULL;
  169. int x_size, y_size, screen_width, screen_height;
  170. int x_pan, y_pan, x_offs, y_offs, refresh = 1, c, ret = 1;
  171. int delay = opt_delay, retransform = 1;
  172. int transform_stretch = opt_stretch, transform_enlarge = opt_enlarge, transform_cal = (opt_stretch == 2),
  173.     transform_iaspect = opt_ignore_aspect, transform_rotation = 0;
  174. struct image i;
  175. #ifdef FBV_SUPPORT_GIF
  176. if(fh_gif_id(filename))
  177. if(fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)
  178. {
  179. load = fh_gif_load;
  180. goto identified;
  181. }
  182. #endif
  183. #ifdef FBV_SUPPORT_PNG
  184. if(fh_png_id(filename))
  185. if(fh_png_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)
  186. {
  187. load = fh_png_load;
  188. goto identified;
  189. }
  190. #endif
  191. #ifdef FBV_SUPPORT_JPEG
  192. if(fh_jpeg_id(filename))
  193. if(fh_jpeg_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)
  194. {
  195. load = fh_jpeg_load;
  196. goto identified;
  197. }
  198. #endif
  199. #ifdef FBV_SUPPORT_BMP
  200. if(fh_bmp_id(filename))
  201. if(fh_bmp_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)
  202. {
  203. load = fh_bmp_load;
  204. goto identified;
  205. }
  206. #endif
  207. fprintf(stderr, "%s: Unable to access file or file format unknown.n", filename);
  208. return(1);
  209. identified:
  210. if(!(image = (unsigned char*) malloc(x_size * y_size * 3)))
  211. {
  212. fprintf(stderr, "%s: Out of memory.n", filename);
  213. goto error_mem;
  214. }
  215. if(load(filename, image, &alpha, x_size, y_size) != FH_ERROR_OK)
  216. {
  217. fprintf(stderr, "%s: Image data is corrupt?n", filename);
  218. goto error_mem;
  219. }
  220. if(!opt_alpha)
  221. {
  222. free(alpha);
  223. alpha = NULL;
  224. }
  225. getCurrentRes(&screen_width, &screen_height);
  226. i.do_free = 0;
  227. while(1)
  228. {
  229. if(retransform)
  230. {
  231. if(i.do_free)
  232. {
  233. free(i.rgb);
  234. free(i.alpha);
  235. }
  236. i.width = x_size;
  237. i.height = y_size;
  238. i.rgb = image;
  239. i.alpha = alpha;
  240. i.do_free = 0;
  241. if(transform_rotation)
  242. do_rotate(&i, transform_rotation);
  243. if(transform_stretch)
  244. do_fit_to_screen(&i, screen_width, screen_height, transform_iaspect, transform_cal);
  245. if(transform_enlarge)
  246. do_enlarge(&i, screen_width, screen_height, transform_iaspect);
  247. x_pan = y_pan = 0;
  248. refresh = 1; retransform = 0;
  249. if(opt_clear)
  250. {
  251. printf("33[H33[J");
  252. fflush(stdout);
  253. }
  254. if(opt_image_info)
  255. printf("fbv - The Framebuffer Viewern%sn%d x %dn", filename, x_size, y_size); 
  256. }
  257. if(refresh)
  258. {
  259. if(i.width < screen_width)
  260. x_offs = (screen_width - i.width) / 2;
  261. else
  262. x_offs = 0;
  263. if(i.height < screen_height)
  264. y_offs = (screen_height - i.height) / 2;
  265. else
  266. y_offs = 0;
  267. fb_display(i.rgb, i.alpha, i.width, i.height, x_pan, y_pan, x_offs, y_offs);
  268. refresh = 0;
  269. }
  270. if(delay)
  271. {
  272. struct timeval tv;
  273. fd_set fds;
  274. tv.tv_sec = delay / 10;
  275. tv.tv_usec = (delay % 10) * 100000;
  276. FD_ZERO(&fds);
  277. FD_SET(0, &fds);
  278. if(select(1, &fds, NULL, NULL, &tv) <= 0)
  279. break;
  280. delay = 0;
  281. }
  282. c = getchar();
  283. switch(c)
  284. {
  285. case EOF:
  286. case 'q':
  287. ret = 0;
  288. goto done;
  289. case ' ': case 10: case 13: 
  290. goto done;
  291. case '>': case '.':
  292. goto done;
  293. case '<': case ',':
  294. ret = -1;
  295. goto done;
  296. case 'r':
  297. refresh = 1;
  298. break;
  299. case 'a': case 'D':
  300. if(x_pan == 0) break;
  301. x_pan -= i.width / PAN_STEPPING;
  302. if(x_pan < 0) x_pan = 0;
  303. refresh = 1;
  304. break;
  305. case 'd': case 'C':
  306. if(x_offs) break;
  307. if(x_pan >= (i.width - screen_width)) break;
  308. x_pan += i.width / PAN_STEPPING;
  309. if(x_pan > (i.width - screen_width)) x_pan = i.width - screen_width;
  310. refresh = 1;
  311. break;
  312. case 'w': case 'A':
  313. if(y_pan == 0) break;
  314. y_pan -= i.height / PAN_STEPPING;
  315. if(y_pan < 0) y_pan = 0;
  316. refresh = 1;
  317. break;
  318. case 'x': case 'B':
  319. if(y_offs) break;
  320. if(y_pan >= (i.height - screen_height)) break;
  321. y_pan += i.height / PAN_STEPPING;
  322. if(y_pan > (i.height - screen_height)) y_pan = i.height - screen_height;
  323. refresh = 1;
  324. break;
  325. case 'f': 
  326. transform_stretch = !transform_stretch;
  327. retransform = 1;
  328. break;
  329. case 'e':
  330. transform_enlarge = !transform_enlarge;
  331. retransform = 1;
  332. break;
  333. case 'k':
  334. transform_cal = !transform_cal;
  335. retransform = 1;
  336. break;
  337. case 'i':
  338. transform_iaspect = !transform_iaspect;
  339. retransform = 1;
  340. break;
  341. case 'p':
  342. transform_cal = 0;
  343. transform_iaspect = 0;
  344. transform_enlarge = 0;
  345. transform_stretch = 0;
  346. retransform = 1;
  347. break;
  348. case 'n':
  349. transform_rotation -= 1;
  350. if(transform_rotation < 0)
  351. transform_rotation += 4;
  352. retransform = 1;
  353. break;
  354. case 'm':
  355. transform_rotation += 1;
  356. if(transform_rotation > 3)
  357. transform_rotation -= 4;
  358. retransform = 1;
  359. break;
  360. }
  361. }
  362. done:
  363. if(opt_clear)
  364. {
  365. printf("33[H33[J");
  366. fflush(stdout);
  367. }
  368. error_mem:
  369. free(image);
  370. free(alpha);
  371. if(i.do_free)
  372. {
  373. free(i.rgb);
  374. free(i.alpha);
  375. }
  376. return(ret);
  377. }
  378. void help(char *name)
  379. {
  380. printf("Usage: %s [options] image1 image2 image3 ...nn"
  381.    "Available options:n"
  382.    " --help        | -h : Show this helpn"
  383.    " --alpha       | -a : Use the alpha channel (if applicable)n"
  384.    " --dontclear   | -c : Do not clear the screen before and after displaying the imagen"
  385.    " --donthide    | -u : Do not hide the cursor before and after displaying the imagen"
  386.    " --noinfo      | -i : Supress image informationn"
  387.    " --stretch     | -f : Strech (using a simple resizing routine) the image to fit onto screen if necessaryn"
  388.    " --colorstretch| -k : Strech (using a 'color average' resizing routine) the image to fit onto screen if necessaryn"
  389.    " --enlarge     | -e : Enlarge the image to fit the whole screen if necessaryn"
  390.    " --ignore-aspect| -r : Ignore the image aspect while resizingn"
  391.                    " --delay <d>   | -s <delay> : Slideshow, 'delay' is the slideshow delay in tenths of seconds.nn"
  392.    "Keys:n"
  393.    " r            : Redraw the imagen"
  394.    " a, d, w, x   : Pan the imagen"
  395.    " f            : Toggle resizing on/offn"
  396.    " k            : Toggle resizing qualityn"
  397.    " e            : Toggle enlarging on/offn"
  398.    " i            : Toggle respecting the image aspect on/offn"
  399.    " n            : Rotate the image 90 degrees leftn"
  400.    " m            : Rotate the image 90 degrees rightn"
  401.    " p            : Disable all transformationsn"
  402.    "Copyright (C) 2000 - 2004 Mateusz Golicz, Tomasz Sterna.n", name);
  403. }
  404. void sighandler(int s)
  405. {
  406. if(opt_hide_cursor)
  407. {
  408. printf("33[?25h");
  409. fflush(stdout);
  410. }
  411. setup_console(0);
  412. _exit(128 + s);
  413. }
  414. int main(int argc, char **argv)
  415. {
  416. static struct option long_options[] =
  417. {
  418. {"help", no_argument, 0, 'h'},
  419. {"noclear",  no_argument,  0, 'c'},
  420. {"alpha",  no_argument,  0, 'a'},
  421. {"unhide",   no_argument,  0, 'u'},
  422. {"noinfo",   no_argument,  0, 'i'},
  423. {"stretch",  no_argument,  0, 'f'},
  424. {"colorstrech", no_argument,  0, 'k'},
  425. {"delay",  required_argument, 0, 's'},
  426. {"enlarge", no_argument, 0, 'e'},
  427. {"ignore-aspect", no_argument, 0, 'r'},
  428. {0, 0, 0, 0}
  429. };
  430. int c, i;
  431. if(argc < 2)
  432. {
  433. help(argv[0]);
  434. fprintf(stderr, "Error: Required argument missing.n");
  435. return(1);
  436. }
  437. while((c = getopt_long_only(argc, argv, "hcauifks:er", long_options, NULL)) != EOF)
  438. {
  439. switch(c)
  440. {
  441. case 'a':
  442. opt_alpha = 1;
  443. break;
  444. case 'c':
  445. opt_clear = 0;
  446. break;
  447. case 's':
  448. opt_delay = atoi(optarg);
  449. break;
  450. case 'u':
  451. opt_hide_cursor = 0;
  452. break;
  453. case 'h':
  454. help(argv[0]);
  455. return(0);
  456. case 'i':
  457. opt_image_info = 0;
  458. break;
  459. case 'f':
  460. opt_stretch = 1;
  461. break;
  462. case 'k':
  463. opt_stretch = 2;
  464. break;
  465. case 'e':
  466. opt_enlarge = 1;
  467. break;
  468. case 'r':
  469. opt_ignore_aspect = 1;
  470. break;
  471. }
  472. }
  473. if(!argv[optind])
  474. {
  475. fprintf(stderr, "Required argument missing! Consult %s -h.n", argv[0]);
  476. return(1);
  477. }
  478. signal(SIGHUP, sighandler);
  479. signal(SIGINT, sighandler);
  480. signal(SIGQUIT, sighandler);
  481. signal(SIGSEGV, sighandler);
  482. signal(SIGTERM, sighandler);
  483. signal(SIGABRT, sighandler);
  484. if(opt_hide_cursor)
  485. {
  486. printf("33[?25l");
  487. fflush(stdout);
  488. }
  489. setup_console(1);
  490. for(i = optind; argv[i]; )
  491. {
  492. int r = show_image(argv[i]);
  493. if(!r) break;
  494. i += r;
  495. if(i < optind)
  496. i = optind;
  497. }
  498. setup_console(0);
  499. if(opt_hide_cursor)
  500. {
  501. printf("33[?25h");
  502. fflush(stdout);
  503. }
  504. return(0);
  505. }