You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

374 rivejä
12 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. char **list = NULL;
  43. int current = 0, items = 0, opts = 1;
  44. int i;
  45. /* Initialise libcaca */
  46. if(caca_init())
  47. {
  48. fprintf(stderr, "%s: unable to initialise libcaca\n", argv[0]);
  49. return 1;
  50. }
  51. /* Load items into playlist */
  52. for(i = 1; i < argc; i++)
  53. {
  54. /* Skip options except after `--' */
  55. if(opts && argv[i][0] == '-')
  56. {
  57. if(argv[i][1] == '-' && argv[i][2] == '\0')
  58. opts = 0;
  59. continue;
  60. }
  61. /* Add argv[i] to the list */
  62. if(items)
  63. list = realloc(list, (items + 1) * sizeof(char *));
  64. else
  65. list = malloc(sizeof(char *));
  66. list[items] = argv[i];
  67. items++;
  68. reload = 1;
  69. }
  70. /* Go ! */
  71. while(!quit)
  72. {
  73. int ww = caca_get_width();
  74. int wh = caca_get_height();
  75. int event;
  76. while((event = caca_get_event()))
  77. {
  78. switch(event)
  79. {
  80. case CACA_EVENT_KEY_PRESS | 'n':
  81. case CACA_EVENT_KEY_PRESS | 'N':
  82. if(items) current = (current + 1) % items;
  83. reload = 1;
  84. break;
  85. case CACA_EVENT_KEY_PRESS | 'p':
  86. case CACA_EVENT_KEY_PRESS | 'P':
  87. if(items) current = (items + current - 1) % items;
  88. reload = 1;
  89. break;
  90. case CACA_EVENT_KEY_PRESS | 'f':
  91. case CACA_EVENT_KEY_PRESS | 'F':
  92. fullscreen = ~fullscreen;
  93. update = 1;
  94. break;
  95. case CACA_EVENT_KEY_PRESS | 'b':
  96. i = 1 + caca_get_feature(CACA_BACKGROUND);
  97. if(i > CACA_BACKGROUND_MAX) i = CACA_BACKGROUND_MIN;
  98. caca_set_feature(i);
  99. update = 1;
  100. break;
  101. case CACA_EVENT_KEY_PRESS | 'B':
  102. i = -1 + caca_get_feature(CACA_BACKGROUND);
  103. if(i < CACA_BACKGROUND_MIN) i = CACA_BACKGROUND_MAX;
  104. caca_set_feature(i);
  105. update = 1;
  106. break;
  107. case CACA_EVENT_KEY_PRESS | 'a':
  108. i = 1 + caca_get_feature(CACA_ANTIALIASING);
  109. if(i > CACA_ANTIALIASING_MAX) i = CACA_ANTIALIASING_MIN;
  110. caca_set_feature(i);
  111. update = 1;
  112. break;
  113. case CACA_EVENT_KEY_PRESS | 'A':
  114. i = -1 + caca_get_feature(CACA_ANTIALIASING);
  115. if(i < CACA_ANTIALIASING_MIN) i = CACA_ANTIALIASING_MAX;
  116. caca_set_feature(i);
  117. update = 1;
  118. break;
  119. case CACA_EVENT_KEY_PRESS | 'd':
  120. i = 1 + caca_get_feature(CACA_DITHERING);
  121. if(i > CACA_DITHERING_MAX) i = CACA_DITHERING_MIN;
  122. caca_set_feature(i);
  123. update = 1;
  124. break;
  125. case CACA_EVENT_KEY_PRESS | 'D':
  126. i = -1 + caca_get_feature(CACA_DITHERING);
  127. if(i < CACA_DITHERING_MIN) i = CACA_DITHERING_MAX;
  128. caca_set_feature(i);
  129. update = 1;
  130. break;
  131. case CACA_EVENT_KEY_PRESS | '+':
  132. zoom++;
  133. if(zoom > 48) zoom = 48; else update = 1;
  134. break;
  135. case CACA_EVENT_KEY_PRESS | '-':
  136. zoom--;
  137. if(zoom < -48) zoom = -48; else update = 1;
  138. break;
  139. case CACA_EVENT_KEY_PRESS | 'x':
  140. case CACA_EVENT_KEY_PRESS | 'X':
  141. zoom = 0;
  142. update = 1;
  143. break;
  144. case CACA_EVENT_KEY_PRESS | 'k':
  145. case CACA_EVENT_KEY_PRESS | 'K':
  146. case CACA_EVENT_KEY_PRESS | CACA_KEY_UP:
  147. if(zoom > 0) y -= 1 + h / (2 + zoom) / 8;
  148. update = 1;
  149. break;
  150. case CACA_EVENT_KEY_PRESS | 'j':
  151. case CACA_EVENT_KEY_PRESS | 'J':
  152. case CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN:
  153. if(zoom > 0) y += 1 + h / (2 + zoom) / 8;
  154. update = 1;
  155. break;
  156. case CACA_EVENT_KEY_PRESS | 'h':
  157. case CACA_EVENT_KEY_PRESS | 'H':
  158. case CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT:
  159. if(zoom > 0) x -= 1 + w / (2 + zoom) / 8;
  160. update = 1;
  161. break;
  162. case CACA_EVENT_KEY_PRESS | 'l':
  163. case CACA_EVENT_KEY_PRESS | 'L':
  164. case CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT:
  165. if(zoom > 0) x += 1 + w / (2 + zoom) / 8;
  166. update = 1;
  167. break;
  168. case CACA_EVENT_KEY_PRESS | '?':
  169. help = 1;
  170. update = 1;
  171. break;
  172. case CACA_EVENT_KEY_PRESS | 'q':
  173. case CACA_EVENT_KEY_PRESS | 'Q':
  174. quit = 1;
  175. break;
  176. }
  177. }
  178. if(items && reload)
  179. {
  180. char *buffer = malloc(ww + 1);
  181. /* Reset image-specific runtime variables */
  182. zoom = 0;
  183. snprintf(buffer, ww, " Loading `%s'... ", list[current]);
  184. buffer[ww] = '\0';
  185. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  186. caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer);
  187. caca_refresh();
  188. load_image(list[current]);
  189. reload = 0;
  190. update = 1;
  191. free(buffer);
  192. }
  193. if(!update)
  194. {
  195. usleep(10000);
  196. continue;
  197. }
  198. caca_clear();
  199. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  200. if(!items)
  201. caca_printf(ww / 2 - 5, wh / 2, " No image. ");
  202. else if(!image)
  203. {
  204. char *buffer = malloc(ww + 1);
  205. snprintf(buffer, ww, " Error loading `%s'. ", list[current]);
  206. buffer[ww] = '\0';
  207. caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer);
  208. free(buffer);
  209. }
  210. else if(zoom < 0)
  211. {
  212. int xo = (ww - 1) / 2;
  213. int yo = (wh - 1) / 2;
  214. int xn = (ww - 1) / (2 - zoom);
  215. int yn = (wh - 1) / (2 - zoom);
  216. draw_checkers(xo - xn, yo - yn, xo + xn, yo + yn);
  217. caca_draw_bitmap(xo - xn, yo - yn, xo + xn, yo + yn,
  218. bitmap, pixels);
  219. }
  220. else if(zoom > 0)
  221. {
  222. struct caca_bitmap *newbitmap;
  223. int xn = w / (2 + zoom);
  224. int yn = h / (2 + zoom);
  225. if(x < xn) x = xn;
  226. if(y < yn) y = yn;
  227. if(xn + x > w) x = w - xn;
  228. if(yn + y > h) y = h - yn;
  229. newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w,
  230. 0x00ff0000, 0x0000ff00, 0x000000ff,
  231. 0xff000000);
  232. draw_checkers(0, fullscreen ? 0 : 1,
  233. ww - 1, fullscreen ? wh - 1 : wh - 2);
  234. caca_draw_bitmap(0, fullscreen ? 0 : 1,
  235. ww - 1, fullscreen ? wh - 1 : wh - 2,
  236. newbitmap,
  237. pixels + 4 * (x - xn) + 4 * w * (y - yn));
  238. caca_free_bitmap(newbitmap);
  239. }
  240. else
  241. {
  242. draw_checkers(0, fullscreen ? 0 : 1,
  243. ww - 1, fullscreen ? wh - 1 : wh - 2);
  244. caca_draw_bitmap(0, fullscreen ? 0 : 1,
  245. ww - 1, fullscreen ? wh - 1 : wh - 2,
  246. bitmap, pixels);
  247. }
  248. caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
  249. if(!fullscreen)
  250. {
  251. caca_draw_line(0, 0, ww - 1, 0, ' ');
  252. caca_draw_line(0, wh - 1, ww - 1, wh - 1, '-');
  253. caca_putstr(0, 0, "q:Quit np:Next/Prev +-x:Zoom "
  254. "hjkl:Move d:Dithering a:Antialias");
  255. caca_putstr(ww - strlen("?:Help"), 0, "?:Help");
  256. caca_printf(3, wh - 1, "cacaview %s (%s, %s)", VERSION,
  257. caca_get_feature_name(caca_get_feature(CACA_DITHERING)),
  258. caca_get_feature_name(caca_get_feature(CACA_ANTIALIASING)));
  259. caca_printf(ww - 14, wh - 1,
  260. "(zoom: %s%i)", zoom > 0 ? "+" : "", zoom);
  261. }
  262. if(help)
  263. {
  264. caca_putstr(ww - 22, 2, " +: zoom in ");
  265. caca_putstr(ww - 22, 3, " -: zoom out ");
  266. caca_putstr(ww - 22, 4, " x: reset zoom ");
  267. caca_putstr(ww - 22, 5, " ---------------------- ");
  268. caca_putstr(ww - 22, 6, " hjkl: move view ");
  269. caca_putstr(ww - 22, 7, " arrows: move view ");
  270. caca_putstr(ww - 22, 8, " ---------------------- ");
  271. caca_putstr(ww - 22, 9, " a: antialiasing method ");
  272. caca_putstr(ww - 22, 9, " d: dithering method ");
  273. caca_putstr(ww - 22, 10, " ---------------------- ");
  274. caca_putstr(ww - 22, 11, " ?: help ");
  275. caca_putstr(ww - 22, 12, " q: quit ");
  276. help = 0;
  277. }
  278. caca_refresh();
  279. update = 0;
  280. }
  281. if(bitmap)
  282. caca_free_bitmap(bitmap);
  283. if(image)
  284. imlib_free_image();
  285. /* Clean up */
  286. caca_end();
  287. return 0;
  288. }
  289. static void load_image(const char *name)
  290. {
  291. /* Empty previous data */
  292. if(image)
  293. imlib_free_image();
  294. if(bitmap)
  295. caca_free_bitmap(bitmap);
  296. image = NULL;
  297. bitmap = NULL;
  298. /* Load the new image */
  299. image = imlib_load_image(name);
  300. if(!image)
  301. {
  302. return;
  303. }
  304. imlib_context_set_image(image);
  305. pixels = (char *)imlib_image_get_data_for_reading_only();
  306. w = imlib_image_get_width();
  307. h = imlib_image_get_height();
  308. x = w / 2;
  309. y = h / 2;
  310. /* Create the libcaca bitmap */
  311. bitmap = caca_create_bitmap(32, w, h, 4 * w, 0x00ff0000, 0x0000ff00,
  312. 0x000000ff, 0xff000000);
  313. if(!bitmap)
  314. {
  315. imlib_free_image();
  316. image = NULL;
  317. }
  318. }
  319. static void draw_checkers(unsigned int x1, unsigned int y1,
  320. unsigned int x2, unsigned int y2)
  321. {
  322. unsigned int xn, yn;
  323. for(yn = y1; yn <= y2; yn++)
  324. for(xn = x1; xn <= x2; xn++)
  325. {
  326. if(((xn / 4) ^ (yn / 2)) & 1)
  327. caca_set_color(CACA_COLOR_LIGHTGRAY, CACA_COLOR_DARKGRAY);
  328. else
  329. caca_set_color(CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY);
  330. caca_putchar(xn, yn, ' ');
  331. }
  332. }