source: mainline/uspace/app/viewer/viewer.c@ 554a5f1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 554a5f1 was 0576df9, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Decoding images without libdraw

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/*
2 * Copyright (c) 2020 Jiri Svoboda
3 * Copyright (c) 2013 Martin Decky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup viewer
31 * @{
32 */
33/** @file
34 */
35
36#include <errno.h>
37#include <gfximage/tga.h>
38#include <stdbool.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <str.h>
42#include <ui/image.h>
43#include <ui/ui.h>
44#include <ui/wdecor.h>
45#include <ui/window.h>
46#include <vfs/vfs.h>
47
48#define NAME "viewer"
49
50typedef struct {
51 ui_t *ui;
52} viewer_t;
53
54static size_t imgs_count;
55static size_t imgs_current = 0;
56static char **imgs;
57
58static ui_window_t *window;
59static gfx_bitmap_t *bitmap = NULL;
60static ui_image_t *image = NULL;
61static gfx_context_t *window_gc;
62
63static gfx_rect_t img_rect;
64
65static bool img_load(gfx_context_t *gc, const char *, gfx_bitmap_t **,
66 gfx_rect_t *);
67static bool img_setup(gfx_context_t *, gfx_bitmap_t *, gfx_rect_t *);
68
69static void wnd_close(ui_window_t *, void *);
70static void wnd_kbd_event(ui_window_t *, void *, kbd_event_t *);
71
72static ui_window_cb_t window_cb = {
73 .close = wnd_close,
74 .kbd = wnd_kbd_event
75};
76
77/** Window close request
78 *
79 * @param window Window
80 * @param arg Argument (calc_t *)
81 */
82static void wnd_close(ui_window_t *window, void *arg)
83{
84 viewer_t *viewer = (viewer_t *) arg;
85
86 ui_quit(viewer->ui);
87}
88
89static void wnd_kbd_event(ui_window_t *window, void *arg,
90 kbd_event_t *event)
91{
92 bool update = false;
93
94 if ((event->type == KEY_PRESS) && (event->c == 'q'))
95 exit(0);
96
97 if ((event->type == KEY_PRESS) && (event->key == KC_PAGE_DOWN)) {
98 if (imgs_current == imgs_count - 1)
99 imgs_current = 0;
100 else
101 imgs_current++;
102
103 update = true;
104 }
105
106 if ((event->type == KEY_PRESS) && (event->key == KC_PAGE_UP)) {
107 if (imgs_current == 0)
108 imgs_current = imgs_count - 1;
109 else
110 imgs_current--;
111
112 update = true;
113 }
114
115 if (update) {
116 gfx_bitmap_t *lbitmap;
117 gfx_rect_t lrect;
118
119 if (!img_load(window_gc, imgs[imgs_current], &lbitmap, &lrect)) {
120 printf("Cannot load image \"%s\".\n", imgs[imgs_current]);
121 exit(4);
122 }
123 if (!img_setup(window_gc, lbitmap, &lrect)) {
124 printf("Cannot setup image \"%s\".\n", imgs[imgs_current]);
125 exit(6);
126 }
127 }
128}
129
130static bool img_load(gfx_context_t *gc, const char *fname,
131 gfx_bitmap_t **rbitmap, gfx_rect_t *rect)
132{
133 int fd;
134 errno_t rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, &fd);
135 if (rc != EOK)
136 return false;
137
138 vfs_stat_t stat;
139 rc = vfs_stat(fd, &stat);
140 if (rc != EOK) {
141 vfs_put(fd);
142 return false;
143 }
144
145 void *tga = malloc(stat.size);
146 if (tga == NULL) {
147 vfs_put(fd);
148 return false;
149 }
150
151 size_t nread;
152 rc = vfs_read(fd, (aoff64_t []) { 0 }, tga, stat.size, &nread);
153 if (rc != EOK || nread != stat.size) {
154 free(tga);
155 vfs_put(fd);
156 return false;
157 }
158
159 vfs_put(fd);
160
161 rc = decode_tga(gc, tga, stat.size, rbitmap, rect);
162 if (rc != EOK) {
163 free(tga);
164 return false;
165 }
166
167 free(tga);
168
169 img_rect = *rect;
170 return true;
171}
172
173static bool img_setup(gfx_context_t *gc, gfx_bitmap_t *bmp, gfx_rect_t *rect)
174{
175 gfx_rect_t arect;
176 gfx_rect_t irect;
177 ui_resource_t *ui_res;
178 errno_t rc;
179
180 ui_res = ui_window_get_res(window);
181
182 ui_window_get_app_rect(window, &arect);
183 gfx_rect_translate(&arect.p0, rect, &irect);
184
185 if (image != NULL) {
186 ui_image_set_bmp(image, bmp, rect);
187 (void) ui_image_paint(image);
188 ui_image_set_rect(image, &irect);
189 } else {
190 rc = ui_image_create(ui_res, bmp, rect, &image);
191 if (rc != EOK) {
192 gfx_bitmap_destroy(bmp);
193 return false;
194 }
195
196 ui_image_set_rect(image, &irect);
197 ui_window_add(window, ui_image_ctl(image));
198 }
199
200 if (bitmap != NULL)
201 gfx_bitmap_destroy(bitmap);
202
203 bitmap = bmp;
204 return true;
205}
206
207static void print_syntax(void)
208{
209 printf("Syntax: %s [<options] <image-file>...\n", NAME);
210 printf("\t-d <display-spec> Use the specified display\n");
211 printf("\t-f Full-screen mode\n");
212}
213
214int main(int argc, char *argv[])
215{
216 const char *display_spec = DISPLAY_DEFAULT;
217 gfx_bitmap_t *lbitmap;
218 gfx_rect_t lrect;
219 bool fullscreen = false;
220 gfx_rect_t rect;
221 gfx_rect_t wrect;
222 gfx_coord2_t off;
223 ui_t *ui;
224 ui_wnd_params_t params;
225 viewer_t viewer;
226 errno_t rc;
227 int i;
228
229 i = 1;
230 while (i < argc && argv[i][0] == '-') {
231 if (str_cmp(argv[i], "-d") == 0) {
232 ++i;
233 if (i >= argc) {
234 printf("Argument missing.\n");
235 print_syntax();
236 return 1;
237 }
238
239 display_spec = argv[i++];
240 } else if (str_cmp(argv[i], "-f") == 0) {
241 fullscreen = true;
242 } else {
243 printf("Invalid option '%s'.\n", argv[i]);
244 print_syntax();
245 return 1;
246 }
247 }
248
249 if (i >= argc) {
250 printf("No image files specified.\n");
251 print_syntax();
252 return 1;
253 }
254
255 imgs_count = argc - i;
256 imgs = calloc(imgs_count, sizeof(char *));
257 if (imgs == NULL) {
258 printf("Out of memory.\n");
259 return 1;
260 }
261
262 for (int j = 0; j < argc - i; j++) {
263 imgs[j] = str_dup(argv[i + j]);
264 if (imgs[j] == NULL) {
265 printf("Out of memory.\n");
266 return 3;
267 }
268 }
269
270 // TODO Fullscreen mode
271 if (fullscreen) {
272 printf("Fullscreen mode not implemented.\n");
273 return 1;
274 }
275
276 rc = ui_create(display_spec, &ui);
277 if (rc != EOK) {
278 printf("Error creating UI on display %s.\n", display_spec);
279 return 1;
280 }
281
282 viewer.ui = ui;
283
284 /*
285 * We don't know the image size yet, so create tiny window and resize
286 * later.
287 */
288 ui_wnd_params_init(&params);
289 params.caption = "Viewer";
290 params.rect.p0.x = 0;
291 params.rect.p0.y = 0;
292 params.rect.p1.x = 1;
293 params.rect.p1.y = 1;
294
295 rc = ui_window_create(ui, &params, &window);
296 if (rc != EOK) {
297 printf("Error creating window.\n");
298 return 1;
299 }
300
301 window_gc = ui_window_get_gc(window);
302
303 ui_window_set_cb(window, &window_cb, (void *) &viewer);
304
305 if (!img_load(window_gc, imgs[imgs_current], &lbitmap, &lrect)) {
306 printf("Cannot load image \"%s\".\n", imgs[imgs_current]);
307 return 1;
308 }
309
310 /*
311 * Compute window rectangle such that application area corresponds
312 * to rect
313 */
314 ui_wdecor_rect_from_app(&lrect, &wrect);
315 off = wrect.p0;
316 gfx_rect_rtranslate(&off, &wrect, &rect);
317 rc = ui_window_resize(window, &rect);
318 if (rc != EOK) {
319 printf("Error resizing window.\n");
320 return 1;
321 }
322
323 if (!img_setup(window_gc, lbitmap, &lrect)) {
324 printf("Cannot setup image \"%s\".\n", imgs[imgs_current]);
325 return 1;
326 }
327
328 rc = ui_window_paint(window);
329 if (rc != EOK) {
330 printf("Error painting window.\n");
331 return 1;
332 }
333
334 ui_run(ui);
335
336 return 0;
337}
338
339/** @}
340 */
Note: See TracBrowser for help on using the repository browser.