327 строки
9.4 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. #ifdef HAVE_ENDIAN_H
  29. # include <endian.h>
  30. #endif
  31. #include <Imlib2.h>
  32. #include "caca.h"
  33. Imlib_Image image = NULL;
  34. char *pixels = NULL;
  35. struct caca_bitmap *bitmap = NULL;
  36. int x, y, w, h;
  37. unsigned int rmask, gmask, bmask;
  38. int dithering = CACA_DITHERING_ORDERED4;
  39. static void load_image(const char *);
  40. int main(int argc, char **argv)
  41. {
  42. int quit = 0, update = 1, help = 0, reload = 0;
  43. int i, zoom = 0;
  44. char **list = NULL;
  45. int current = 0, items = 0, opts = 1;
  46. #ifdef HAVE_ENDIAN_H
  47. if(__BYTE_ORDER == __BIG_ENDIAN)
  48. #else
  49. rmask = 0x12345678;
  50. if(*(char *)&rmask == 0x12)
  51. #endif
  52. {
  53. rmask = 0x00ff0000; gmask = 0x0000ff00; bmask = 0x000000ff;
  54. }
  55. else
  56. {
  57. rmask = 0x0000ff00; gmask = 0x00ff0000; bmask = 0xff000000;
  58. }
  59. /* Initialise libcaca */
  60. if(caca_init())
  61. {
  62. fprintf(stderr, "%s: unable to initialise libcaca\n", argv[0]);
  63. return 1;
  64. }
  65. /* Load items into playlist */
  66. for(i = 1; i < argc; i++)
  67. {
  68. /* Skip options except after `--' */
  69. if(opts && argv[i][0] == '-')
  70. {
  71. if(argv[i][1] == '-' && argv[i][2] == '\0')
  72. opts = 0;
  73. continue;
  74. }
  75. /* Add argv[i] to the list */
  76. if(items)
  77. list = realloc(list, (items + 1) * sizeof(char *));
  78. else
  79. list = malloc(sizeof(char *));
  80. list[items] = argv[i];
  81. items++;
  82. reload = 1;
  83. }
  84. /* Go ! */
  85. while(!quit)
  86. {
  87. int ww = caca_get_width();
  88. int wh = caca_get_height();
  89. int event;
  90. while((event = caca_get_event()))
  91. {
  92. switch(event)
  93. {
  94. case CACA_EVENT_KEY_PRESS | 'n':
  95. case CACA_EVENT_KEY_PRESS | 'N':
  96. if(items) current = (current + 1) % items;
  97. reload = 1;
  98. break;
  99. case CACA_EVENT_KEY_PRESS | 'p':
  100. case CACA_EVENT_KEY_PRESS | 'P':
  101. if(items) current = (items + current - 1) % items;
  102. reload = 1;
  103. break;
  104. case CACA_EVENT_KEY_PRESS | 'd':
  105. dithering = (dithering + 1) % 5;
  106. update = 1;
  107. break;
  108. case CACA_EVENT_KEY_PRESS | 'D':
  109. dithering = (dithering + 4) % 5;
  110. update = 1;
  111. break;
  112. case CACA_EVENT_KEY_PRESS | '+':
  113. zoom++;
  114. if(zoom > 48) zoom = 48; else update = 1;
  115. break;
  116. case CACA_EVENT_KEY_PRESS | '-':
  117. zoom--;
  118. if(zoom < -48) zoom = -48; else update = 1;
  119. break;
  120. case CACA_EVENT_KEY_PRESS | 'x':
  121. case CACA_EVENT_KEY_PRESS | 'X':
  122. zoom = 0;
  123. update = 1;
  124. break;
  125. case CACA_EVENT_KEY_PRESS | 'k':
  126. case CACA_EVENT_KEY_PRESS | 'K':
  127. case CACA_EVENT_KEY_PRESS | CACA_KEY_UP:
  128. if(zoom > 0) y -= 1 + h / (2 + zoom) / 8;
  129. update = 1;
  130. break;
  131. case CACA_EVENT_KEY_PRESS | 'j':
  132. case CACA_EVENT_KEY_PRESS | 'J':
  133. case CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN:
  134. if(zoom > 0) y += 1 + h / (2 + zoom) / 8;
  135. update = 1;
  136. break;
  137. case CACA_EVENT_KEY_PRESS | 'h':
  138. case CACA_EVENT_KEY_PRESS | 'H':
  139. case CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT:
  140. if(zoom > 0) x -= 1 + w / (2 + zoom) / 8;
  141. update = 1;
  142. break;
  143. case CACA_EVENT_KEY_PRESS | 'l':
  144. case CACA_EVENT_KEY_PRESS | 'L':
  145. case CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT:
  146. if(zoom > 0) x += 1 + w / (2 + zoom) / 8;
  147. update = 1;
  148. break;
  149. case CACA_EVENT_KEY_PRESS | '?':
  150. help = 1;
  151. update = 1;
  152. break;
  153. case CACA_EVENT_KEY_PRESS | 'q':
  154. case CACA_EVENT_KEY_PRESS | 'Q':
  155. quit = 1;
  156. break;
  157. }
  158. }
  159. if(items && reload)
  160. {
  161. char *buffer = malloc(ww + 1);
  162. /* Reset image-specific runtime variables */
  163. zoom = 0;
  164. snprintf(buffer, ww, " Loading `%s'... ", list[current]);
  165. buffer[ww] = '\0';
  166. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  167. caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer);
  168. caca_refresh();
  169. load_image(list[current]);
  170. reload = 0;
  171. update = 1;
  172. free(buffer);
  173. }
  174. if(!update)
  175. {
  176. usleep(10000);
  177. continue;
  178. }
  179. caca_clear();
  180. caca_set_dithering(dithering);
  181. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  182. if(!items)
  183. caca_printf(ww / 2 - 5, wh / 2, " No image. ");
  184. else if(!image)
  185. {
  186. char *buffer = malloc(ww + 1);
  187. snprintf(buffer, ww, " Error loading `%s'. ", list[current]);
  188. buffer[ww] = '\0';
  189. caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer);
  190. free(buffer);
  191. }
  192. else if(zoom < 0)
  193. {
  194. int xo = (ww - 1) / 2;
  195. int yo = (wh - 1) / 2;
  196. int xn = (ww - 1) / (2 - zoom);
  197. int yn = (wh - 1) / (2 - zoom);
  198. caca_draw_bitmap(xo - xn, yo - yn, xo + xn, yo + yn,
  199. bitmap, pixels);
  200. }
  201. else if(zoom > 0)
  202. {
  203. struct caca_bitmap *newbitmap;
  204. int xn = w / (2 + zoom);
  205. int yn = h / (2 + zoom);
  206. if(x < xn) x = xn;
  207. if(y < yn) y = yn;
  208. if(xn + x > w) x = w - xn;
  209. if(yn + y > h) y = h - yn;
  210. newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w,
  211. rmask, gmask, bmask);
  212. caca_draw_bitmap(0, 0, ww - 1, wh - 1, newbitmap,
  213. pixels + 4 * (x - xn) + 4 * w * (y - yn));
  214. caca_free_bitmap(newbitmap);
  215. }
  216. else
  217. {
  218. caca_draw_bitmap(0, 0, ww - 1, wh - 1, bitmap, pixels);
  219. }
  220. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  221. caca_draw_line(0, 0, ww - 1, 0, ' ');
  222. caca_draw_line(0, wh - 1, ww - 1, wh - 1, '-');
  223. caca_putstr(0, 0, "q:Quit n/p:Next/Prev +/-/x:Zoom "
  224. "h/j/k/l: Move d:Dithering");
  225. caca_putstr(ww - strlen("?:Help"), 0, "?:Help");
  226. caca_printf(3, wh - 1, "cacaview %s", VERSION);
  227. caca_printf(ww / 2 - 5, wh - 1, "(%s dithering)",
  228. caca_get_dithering_name(dithering));
  229. caca_printf(ww - 14, wh - 1,
  230. "(zoom: %s%i)", zoom > 0 ? "+" : "", zoom);
  231. if(help)
  232. {
  233. caca_putstr(ww - 22, 2, " +: zoom in ");
  234. caca_putstr(ww - 22, 3, " -: zoom out ");
  235. caca_putstr(ww - 22, 4, " x: reset zoom ");
  236. caca_putstr(ww - 22, 5, " ------------------- ");
  237. caca_putstr(ww - 22, 6, " hjkl: move view ");
  238. caca_putstr(ww - 22, 7, " arrows: move view ");
  239. caca_putstr(ww - 22, 8, " ------------------- ");
  240. caca_putstr(ww - 22, 9, " d: dithering method ");
  241. caca_putstr(ww - 22, 10, " ------------------- ");
  242. caca_putstr(ww - 22, 11, " ?: help ");
  243. caca_putstr(ww - 22, 12, " q: quit ");
  244. help = 0;
  245. }
  246. caca_refresh();
  247. update = 0;
  248. }
  249. if(bitmap)
  250. caca_free_bitmap(bitmap);
  251. if(image)
  252. imlib_free_image();
  253. /* Clean up */
  254. caca_end();
  255. return 0;
  256. }
  257. static void load_image(const char *name)
  258. {
  259. /* Empty previous data */
  260. if(image)
  261. imlib_free_image();
  262. if(bitmap)
  263. caca_free_bitmap(bitmap);
  264. image = NULL;
  265. bitmap = NULL;
  266. /* Load the new image */
  267. image = imlib_load_image(name);
  268. if(!image)
  269. {
  270. return;
  271. }
  272. imlib_context_set_image(image);
  273. pixels = (char *)imlib_image_get_data_for_reading_only();
  274. w = imlib_image_get_width();
  275. h = imlib_image_get_height();
  276. x = w / 2;
  277. y = h / 2;
  278. /* Create the libcaca bitmap */
  279. bitmap = caca_create_bitmap(32, w, h, 4 * w, rmask, gmask, bmask);
  280. if(!bitmap)
  281. {
  282. imlib_free_image();
  283. image = NULL;
  284. }
  285. }