Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

347 righe
10 KiB

  1. /*
  2. * view image viewer for libcaca
  3. * Copyright (c) 2003 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  21. * 02111-1307 USA
  22. */
  23. #include "config.h"
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <malloc.h>
  27. #include <unistd.h>
  28. #include <Imlib2.h>
  29. #include "caca.h"
  30. /* Local functions */
  31. static void load_image(const char *);
  32. static void draw_checkers(unsigned int, unsigned int,
  33. unsigned int, unsigned int);
  34. /* Local variables */
  35. Imlib_Image image = NULL;
  36. char *pixels = NULL;
  37. struct caca_bitmap *bitmap = NULL;
  38. int x, y, w, h;
  39. int main(int argc, char **argv)
  40. {
  41. int quit = 0, update = 1, help = 0, reload = 0, fullscreen = 0, zoom = 0;
  42. int dithering = CACA_DITHERING_ORDERED4;
  43. char **list = NULL;
  44. int current = 0, items = 0, opts = 1;
  45. int i;
  46. /* Initialise libcaca */
  47. if(caca_init())
  48. {
  49. fprintf(stderr, "%s: unable to initialise libcaca\n", argv[0]);
  50. return 1;
  51. }
  52. /* Load items into playlist */
  53. for(i = 1; i < argc; i++)
  54. {
  55. /* Skip options except after `--' */
  56. if(opts && argv[i][0] == '-')
  57. {
  58. if(argv[i][1] == '-' && argv[i][2] == '\0')
  59. opts = 0;
  60. continue;
  61. }
  62. /* Add argv[i] to the list */
  63. if(items)
  64. list = realloc(list, (items + 1) * sizeof(char *));
  65. else
  66. list = malloc(sizeof(char *));
  67. list[items] = argv[i];
  68. items++;
  69. reload = 1;
  70. }
  71. /* Go ! */
  72. while(!quit)
  73. {
  74. int ww = caca_get_width();
  75. int wh = caca_get_height();
  76. int event;
  77. while((event = caca_get_event()))
  78. {
  79. switch(event)
  80. {
  81. case CACA_EVENT_KEY_PRESS | 'n':
  82. case CACA_EVENT_KEY_PRESS | 'N':
  83. if(items) current = (current + 1) % items;
  84. reload = 1;
  85. break;
  86. case CACA_EVENT_KEY_PRESS | 'p':
  87. case CACA_EVENT_KEY_PRESS | 'P':
  88. if(items) current = (items + current - 1) % items;
  89. reload = 1;
  90. break;
  91. case CACA_EVENT_KEY_PRESS | 'f':
  92. case CACA_EVENT_KEY_PRESS | 'F':
  93. fullscreen = ~fullscreen;
  94. update = 1;
  95. break;
  96. case CACA_EVENT_KEY_PRESS | 'd':
  97. dithering = (dithering + 1) % 5;
  98. update = 1;
  99. break;
  100. case CACA_EVENT_KEY_PRESS | 'D':
  101. dithering = (dithering + 4) % 5;
  102. update = 1;
  103. break;
  104. case CACA_EVENT_KEY_PRESS | '+':
  105. zoom++;
  106. if(zoom > 48) zoom = 48; else update = 1;
  107. break;
  108. case CACA_EVENT_KEY_PRESS | '-':
  109. zoom--;
  110. if(zoom < -48) zoom = -48; else update = 1;
  111. break;
  112. case CACA_EVENT_KEY_PRESS | 'x':
  113. case CACA_EVENT_KEY_PRESS | 'X':
  114. zoom = 0;
  115. update = 1;
  116. break;
  117. case CACA_EVENT_KEY_PRESS | 'k':
  118. case CACA_EVENT_KEY_PRESS | 'K':
  119. case CACA_EVENT_KEY_PRESS | CACA_KEY_UP:
  120. if(zoom > 0) y -= 1 + h / (2 + zoom) / 8;
  121. update = 1;
  122. break;
  123. case CACA_EVENT_KEY_PRESS | 'j':
  124. case CACA_EVENT_KEY_PRESS | 'J':
  125. case CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN:
  126. if(zoom > 0) y += 1 + h / (2 + zoom) / 8;
  127. update = 1;
  128. break;
  129. case CACA_EVENT_KEY_PRESS | 'h':
  130. case CACA_EVENT_KEY_PRESS | 'H':
  131. case CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT:
  132. if(zoom > 0) x -= 1 + w / (2 + zoom) / 8;
  133. update = 1;
  134. break;
  135. case CACA_EVENT_KEY_PRESS | 'l':
  136. case CACA_EVENT_KEY_PRESS | 'L':
  137. case CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT:
  138. if(zoom > 0) x += 1 + w / (2 + zoom) / 8;
  139. update = 1;
  140. break;
  141. case CACA_EVENT_KEY_PRESS | '?':
  142. help = 1;
  143. update = 1;
  144. break;
  145. case CACA_EVENT_KEY_PRESS | 'q':
  146. case CACA_EVENT_KEY_PRESS | 'Q':
  147. quit = 1;
  148. break;
  149. }
  150. }
  151. if(items && reload)
  152. {
  153. char *buffer = malloc(ww + 1);
  154. /* Reset image-specific runtime variables */
  155. zoom = 0;
  156. snprintf(buffer, ww, " Loading `%s'... ", list[current]);
  157. buffer[ww] = '\0';
  158. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  159. caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer);
  160. caca_refresh();
  161. load_image(list[current]);
  162. reload = 0;
  163. update = 1;
  164. free(buffer);
  165. }
  166. if(!update)
  167. {
  168. usleep(10000);
  169. continue;
  170. }
  171. caca_clear();
  172. caca_set_dithering(dithering);
  173. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  174. if(!items)
  175. caca_printf(ww / 2 - 5, wh / 2, " No image. ");
  176. else if(!image)
  177. {
  178. char *buffer = malloc(ww + 1);
  179. snprintf(buffer, ww, " Error loading `%s'. ", list[current]);
  180. buffer[ww] = '\0';
  181. caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer);
  182. free(buffer);
  183. }
  184. else if(zoom < 0)
  185. {
  186. int xo = (ww - 1) / 2;
  187. int yo = (wh - 1) / 2;
  188. int xn = (ww - 1) / (2 - zoom);
  189. int yn = (wh - 1) / (2 - zoom);
  190. draw_checkers(xo - xn, yo - yn, xo + xn, yo + yn);
  191. caca_draw_bitmap(xo - xn, yo - yn, xo + xn, yo + yn,
  192. bitmap, pixels);
  193. }
  194. else if(zoom > 0)
  195. {
  196. struct caca_bitmap *newbitmap;
  197. int xn = w / (2 + zoom);
  198. int yn = h / (2 + zoom);
  199. if(x < xn) x = xn;
  200. if(y < yn) y = yn;
  201. if(xn + x > w) x = w - xn;
  202. if(yn + y > h) y = h - yn;
  203. newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w,
  204. 0x00ff0000, 0x0000ff00, 0x000000ff,
  205. 0xff000000);
  206. draw_checkers(0, fullscreen ? 0 : 1,
  207. ww - 1, fullscreen ? wh - 1 : wh - 2);
  208. caca_draw_bitmap(0, fullscreen ? 0 : 1,
  209. ww - 1, fullscreen ? wh - 1 : wh - 2,
  210. newbitmap,
  211. pixels + 4 * (x - xn) + 4 * w * (y - yn));
  212. caca_free_bitmap(newbitmap);
  213. }
  214. else
  215. {
  216. draw_checkers(0, fullscreen ? 0 : 1,
  217. ww - 1, fullscreen ? wh - 1 : wh - 2);
  218. caca_draw_bitmap(0, fullscreen ? 0 : 1,
  219. ww - 1, fullscreen ? wh - 1 : wh - 2,
  220. bitmap, pixels);
  221. }
  222. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  223. if(!fullscreen)
  224. {
  225. caca_draw_line(0, 0, ww - 1, 0, ' ');
  226. caca_draw_line(0, wh - 1, ww - 1, wh - 1, '-');
  227. caca_putstr(0, 0, "q:Quit n/p:Next/Prev +/-/x:Zoom "
  228. "h/j/k/l: Move d:Dithering");
  229. caca_putstr(ww - strlen("?:Help"), 0, "?:Help");
  230. caca_printf(3, wh - 1, "cacaview %s", VERSION);
  231. caca_printf(ww / 2 - 5, wh - 1, "(%s dithering)",
  232. caca_get_dithering_name(dithering));
  233. caca_printf(ww - 14, wh - 1,
  234. "(zoom: %s%i)", zoom > 0 ? "+" : "", zoom);
  235. }
  236. if(help)
  237. {
  238. caca_putstr(ww - 22, 2, " +: zoom in ");
  239. caca_putstr(ww - 22, 3, " -: zoom out ");
  240. caca_putstr(ww - 22, 4, " x: reset zoom ");
  241. caca_putstr(ww - 22, 5, " ------------------- ");
  242. caca_putstr(ww - 22, 6, " hjkl: move view ");
  243. caca_putstr(ww - 22, 7, " arrows: move view ");
  244. caca_putstr(ww - 22, 8, " ------------------- ");
  245. caca_putstr(ww - 22, 9, " d: dithering method ");
  246. caca_putstr(ww - 22, 10, " ------------------- ");
  247. caca_putstr(ww - 22, 11, " ?: help ");
  248. caca_putstr(ww - 22, 12, " q: quit ");
  249. help = 0;
  250. }
  251. caca_refresh();
  252. update = 0;
  253. }
  254. if(bitmap)
  255. caca_free_bitmap(bitmap);
  256. if(image)
  257. imlib_free_image();
  258. /* Clean up */
  259. caca_end();
  260. return 0;
  261. }
  262. static void load_image(const char *name)
  263. {
  264. /* Empty previous data */
  265. if(image)
  266. imlib_free_image();
  267. if(bitmap)
  268. caca_free_bitmap(bitmap);
  269. image = NULL;
  270. bitmap = NULL;
  271. /* Load the new image */
  272. image = imlib_load_image(name);
  273. if(!image)
  274. {
  275. return;
  276. }
  277. imlib_context_set_image(image);
  278. pixels = (char *)imlib_image_get_data_for_reading_only();
  279. w = imlib_image_get_width();
  280. h = imlib_image_get_height();
  281. x = w / 2;
  282. y = h / 2;
  283. /* Create the libcaca bitmap */
  284. bitmap = caca_create_bitmap(32, w, h, 4 * w, 0x00ff0000, 0x0000ff00,
  285. 0x000000ff, 0xff000000);
  286. if(!bitmap)
  287. {
  288. imlib_free_image();
  289. image = NULL;
  290. }
  291. }
  292. static void draw_checkers(unsigned int x1, unsigned int y1,
  293. unsigned int x2, unsigned int y2)
  294. {
  295. unsigned int xn, yn;
  296. for(yn = y1; yn <= y2; yn++)
  297. for(xn = x1; xn <= x2; xn++)
  298. {
  299. if(((xn / 4) ^ (yn / 2)) & 1)
  300. caca_set_color(CACA_COLOR_LIGHTGRAY, CACA_COLOR_DARKGRAY);
  301. else
  302. caca_set_color(CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY);
  303. caca_putchar(xn, yn, ' ');
  304. }
  305. }