Krolyxon
Commit 229830a

Branches

Refs →

nsxivimage.c

306 lines · 6.0 KB · C

1/* sxiv: image.c
2 * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
3 *
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 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <stdlib.h>
20#include <stdio.h>
21
22#include <Imlib2.h>
23
24#include "sxiv.h"
25#include "image.h"
26
27int zl_cnt;
28float zoom_min;
29float zoom_max;
30
31void img_init(img_t *img, win_t *win) {
32 zl_cnt = sizeof(zoom_levels) / sizeof(zoom_levels[0]);
33 zoom_min = zoom_levels[0] / 100.0;
34 zoom_max = zoom_levels[zl_cnt - 1] / 100.0;
35
36 if (img) {
37 img->zoom = options->zoom;
38 img->zoom = MAX(img->zoom, zoom_min);
39 img->zoom = MIN(img->zoom, zoom_max);
40 img->aa = options->aa;
41 }
42
43 if (win) {
44 imlib_context_set_display(win->env.dpy);
45 imlib_context_set_visual(win->env.vis);
46 imlib_context_set_colormap(win->env.cmap);
47 }
48}
49
50void img_free(img_t* img) {
51 if (imlib_context_get_image())
52 imlib_free_image();
53}
54
55int img_load(img_t *img, const char *filename) {
56 Imlib_Image *im;
57
58 if (!img || !filename)
59 return -1;
60
61 if (imlib_context_get_image())
62 imlib_free_image();
63
64 if (!(im = imlib_load_image(filename))) {
65 WARN("could not open image: %s", filename);
66 return -1;
67 }
68
69 imlib_context_set_image(im);
70 imlib_context_set_anti_alias(img->aa);
71
72 img->re = 0;
73 img->checkpan = 0;
74 img->zoomed = 0;
75
76 img->w = imlib_image_get_width();
77 img->h = imlib_image_get_height();
78
79 return 0;
80}
81
82void img_check_pan(img_t *img, win_t *win) {
83 if (!img)
84 return;
85
86 if (img->w * img->zoom > win->w) {
87 if (img->x > 0 && img->x + img->w * img->zoom > win->w)
88 img->x = 0;
89 if (img->x < 0 && img->x + img->w * img->zoom < win->w)
90 img->x = win->w - img->w * img->zoom;
91 } else {
92 img->x = (win->w - img->w * img->zoom) / 2;
93 }
94 if (img->h * img->zoom > win->h) {
95 if (img->y > 0 && img->y + img->h * img->zoom > win->h)
96 img->y = 0;
97 if (img->y < 0 && img->y + img->h * img->zoom < win->h)
98 img->y = win->h - img->h * img->zoom;
99 } else {
100 img->y = (win->h - img->h * img->zoom) / 2;
101 }
102}
103
104void img_render(img_t *img, win_t *win) {
105 int sx, sy, sw, sh;
106 int dx, dy, dw, dh;
107
108 if (!img || !win || !imlib_context_get_image())
109 return;
110
111 if (!img->zoomed && options->scalemode != SCALE_ZOOM) {
112 img_fit(img, win);
113 if (options->scalemode == SCALE_DOWN && img->zoom > 1.0)
114 img->zoom = 1.0;
115 }
116
117 if (!img->re) {
118 /* rendered for the first time */
119 img->re = 1;
120 img_center(img, win);
121 }
122
123 if (img->checkpan) {
124 img_check_pan(img, win);
125 img->checkpan = 0;
126 }
127
128 /* calculate source and destination offsets */
129 if (img->x < 0) {
130 sx = -img->x / img->zoom;
131 sw = win->w / img->zoom;
132 dx = 0;
133 dw = win->w;
134 } else {
135 sx = 0;
136 sw = img->w;
137 dx = img->x;
138 dw = img->w * img->zoom;
139 }
140 if (img->y < 0) {
141 sy = -img->y / img->zoom;
142 sh = win->h / img->zoom;
143 dy = 0;
144 dh = win->h;
145 } else {
146 sy = 0;
147 sh = img->h;
148 dy = img->y;
149 dh = img->h * img->zoom;
150 }
151
152 win_clear(win);
153
154 imlib_context_set_drawable(win->pm);
155 imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh);
156
157 win_draw(win);
158}
159
160int img_fit(img_t *img, win_t *win) {
161 float oz, zw, zh;
162
163 if (!img || !win)
164 return 0;
165
166 oz = img->zoom;
167 zw = (float) win->w / (float) img->w;
168 zh = (float) win->h / (float) img->h;
169
170 img->zoom = MIN(zw, zh);
171 img->zoom = MAX(img->zoom, zoom_min);
172 img->zoom = MIN(img->zoom, zoom_max);
173
174 return oz != img->zoom;
175}
176
177void img_center(img_t *img, win_t *win) {
178 if (!img || !win)
179 return;
180
181 img->x = (win->w - img->w * img->zoom) / 2;
182 img->y = (win->h - img->h * img->zoom) / 2;
183}
184
185int img_zoom(img_t *img, float z) {
186 if (!img)
187 return 0;
188
189 z = MAX(z, zoom_min);
190 z = MIN(z, zoom_max);
191
192 if (z != img->zoom) {
193 img->x -= (img->w * z - img->w * img->zoom) / 2;
194 img->y -= (img->h * z - img->h * img->zoom) / 2;
195 img->zoom = z;
196 img->checkpan = 1;
197 img->zoomed = 1;
198 return 1;
199 } else {
200 return 0;
201 }
202}
203
204int img_zoom_in(img_t *img) {
205 int i;
206
207 if (!img)
208 return 0;
209
210 for (i = 1; i < zl_cnt; ++i) {
211 if (zoom_levels[i] > img->zoom * 100.0)
212 return img_zoom(img, zoom_levels[i] / 100.0);
213 }
214
215 return 0;
216}
217
218int img_zoom_out(img_t *img) {
219 int i;
220
221 if (!img)
222 return 0;
223
224 for (i = zl_cnt - 2; i >= 0; --i) {
225 if (zoom_levels[i] < img->zoom * 100.0)
226 return img_zoom(img, zoom_levels[i] / 100.0);
227 }
228
229 return 0;
230}
231
232int img_move(img_t *img, win_t *win, int dx, int dy) {
233 int ox, oy;
234
235 if (!img || !win)
236 return 0;
237
238 ox = img->x;
239 oy = img->y;
240
241 img->x += dx;
242 img->y += dy;
243
244 img_check_pan(img, win);
245
246 return ox != img->x || oy != img->y;
247}
248
249int img_pan(img_t *img, win_t *win, pandir_t dir) {
250 if (!img || !win)
251 return 0;
252
253 switch (dir) {
254 case PAN_LEFT:
255 return img_move(img, win, win->w / 5, 0);
256 case PAN_RIGHT:
257 return img_move(img, win, win->w / 5 * -1, 0);
258 case PAN_UP:
259 return img_move(img, win, 0, win->h / 5);
260 case PAN_DOWN:
261 return img_move(img, win, 0, win->h / 5 * -1);
262 }
263
264 return 0;
265}
266
267int img_rotate(img_t *img, win_t *win, int d) {
268 int ox, oy, tmp;
269
270 if (!img || !win)
271 return 0;
272
273 ox = d == 1 ? img->x : win->w - img->x - img->w * img->zoom;
274 oy = d == 3 ? img->y : win->h - img->y - img->h * img->zoom;
275
276 imlib_image_orientate(d);
277
278 img->x = oy + (win->w - win->h) / 2;
279 img->y = ox + (win->h - win->w) / 2;
280
281 tmp = img->w;
282 img->w = img->h;
283 img->h = tmp;
284
285 img->checkpan = 1;
286
287 return 1;
288}
289
290int img_rotate_left(img_t *img, win_t *win) {
291 return img_rotate(img, win, 3);
292}
293
294int img_rotate_right(img_t *img, win_t *win) {
295 return img_rotate(img, win, 1);
296}
297
298int img_toggle_antialias(img_t *img) {
299 if (!img)
300 return 0;
301
302 img->aa ^= 1;
303 imlib_context_set_anti_alias(img->aa);
304
305 return 1;
306}