1 /* xsane -- a graphical (X11, gtk) scanner-oriented SANE frontend
2
3 xsane-viewer.c
4
5 Oliver Rauch <Oliver.Rauch@rauch-domain.de>
6 Copyright (C) 1998-2010 Oliver Rauch
7 This file is part of the XSANE package.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 /* ---------------------------------------------------------------------------------------------------------------------- */
24
25 #include "xsane.h"
26 #include "xsane-back-gtk.h"
27 #include "xsane-front-gtk.h"
28 #include "xsane-preferences.h"
29 #include "xsane-viewer.h"
30 #include "xsane-gamma.h"
31 #include "xsane-icons.h"
32 #include "xsane-save.h"
33 #include <gdk/gdkkeysyms.h>
34 #include <sys/wait.h>
35
36 #ifndef PATH_MAX
37 # define PATH_MAX 1024
38 #endif
39
40 /* ---------------------------------------------------------------------------------------------------------------------- */
41
42 static int xsane_viewer_zoom[] = {9, 13, 18, 25, 35, 50, 71, 100, 141, 200, 282, 400 };
43
44 /* ---------------------------------------------------------------------------------------------------------------------- */
45
46 static void xsane_viewer_set_sensitivity(Viewer *v, int sensitivity);
47 static gint xsane_viewer_close_callback(GtkWidget *window, gpointer data);
48 static void xsane_viewer_dialog_cancel(GtkWidget *window, gpointer data);
49 static void xsane_viewer_save_callback(GtkWidget *window, gpointer data);
50 static void xsane_viewer_ocr_callback(GtkWidget *window, gpointer data);
51 static void xsane_viewer_clone_callback(GtkWidget *window, gpointer data);
52 static void xsane_viewer_despeckle_callback(GtkWidget *window, gpointer data);
53 static void xsane_viewer_blur_callback(GtkWidget *window, gpointer data);
54 static void xsane_viewer_scale_image(GtkWidget *window, gpointer data);
55 static void xsane_viewer_despeckle_image(GtkWidget *window, gpointer data);
56 static void xsane_viewer_blur_image(GtkWidget *window, gpointer data);
57 static void xsane_viewer_rotate(Viewer *v, int rotation);
58 static void xsane_viewer_rotate90_callback(GtkWidget *window, gpointer data);
59 static void xsane_viewer_rotate180_callback(GtkWidget *window, gpointer data);
60 static void xsane_viewer_rotate270_callback(GtkWidget *window, gpointer data);
61 static void xsane_viewer_mirror_x_callback(GtkWidget *window, gpointer data);
62 static void xsane_viewer_mirror_y_callback(GtkWidget *window, gpointer data);
63 static GtkWidget *xsane_viewer_file_build_menu(Viewer *v);
64 static GtkWidget *xsane_viewer_edit_build_menu(Viewer *v);
65 static GtkWidget *xsane_viewer_filters_build_menu(Viewer *v);
66 static int xsane_viewer_read_image(Viewer *v);
67 Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_reduction_to_lineart,
68 char *output_filename, viewer_modification allow_modification, int image_saved);
69
70 /* ---------------------------------------------------------------------------------------------------------------------- */
71
xsane_viewer_set_sensitivity(Viewer * v,int sensitivity)72 static void xsane_viewer_set_sensitivity(Viewer *v, int sensitivity)
73 {
74 if (sensitivity)
75 {
76 v->block_actions = FALSE;
77 gtk_widget_set_sensitive(GTK_WIDGET(v->file_menu), TRUE);
78 gtk_widget_set_sensitive(GTK_WIDGET(v->button_box), TRUE);
79
80 switch (v->allow_modification)
81 {
82 case VIEWER_NO_MODIFICATION:
83 gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), FALSE);
84 gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
85 gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
86 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), FALSE);
87 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), FALSE);
88 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
89 gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
90
91 gtk_widget_set_sensitive(GTK_WIDGET(v->save), FALSE);
92 gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
93 gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
94 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), FALSE);
95 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), FALSE);
96 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), FALSE);
97 break;
98
99 case VIEWER_NO_NAME_AND_SIZE_MODIFICATION:
100 gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), TRUE);
101 gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
102 gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
103 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), TRUE);
104 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), TRUE);
105 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
106 gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
107
108 gtk_widget_set_sensitive(GTK_WIDGET(v->save), TRUE);
109 gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
110 gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
111 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), TRUE);
112 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), TRUE);
113 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), FALSE);
114 break;
115
116 case VIEWER_NO_NAME_MODIFICATION:
117 gtk_widget_set_sensitive(GTK_WIDGET(v->ocr_menu_item), FALSE);
118 gtk_widget_set_sensitive(GTK_WIDGET(v->clone_menu_item), FALSE);
119 gtk_widget_set_sensitive(GTK_WIDGET(v->ocr), FALSE);
120 gtk_widget_set_sensitive(GTK_WIDGET(v->clone), FALSE);
121 /* fall through */
122
123 case VIEWER_FULL_MODIFICATION:
124 default:
125 gtk_widget_set_sensitive(GTK_WIDGET(v->save_menu_item), TRUE);
126 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), TRUE);
127 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), TRUE);
128 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), TRUE);
129 gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
130
131 gtk_widget_set_sensitive(GTK_WIDGET(v->save), TRUE);
132 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_button_box), TRUE);
133 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_button_box), TRUE);
134 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_button_box), TRUE);
135 break;
136 }
137 }
138 else
139 {
140 v->block_actions = TRUE;
141 gtk_widget_set_sensitive(GTK_WIDGET(v->file_menu), FALSE);
142 gtk_widget_set_sensitive(GTK_WIDGET(v->edit_menu), FALSE);
143 gtk_widget_set_sensitive(GTK_WIDGET(v->filters_menu), FALSE);
144 gtk_widget_set_sensitive(GTK_WIDGET(v->geometry_menu), FALSE);
145 gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu),FALSE);
146 gtk_widget_set_sensitive(GTK_WIDGET(v->button_box), FALSE);
147 }
148 }
149
150 /* ---------------------------------------------------------------------------------------------------------------------- */
151
xsane_viewer_close_callback(GtkWidget * widget,gpointer data)152 static gint xsane_viewer_close_callback(GtkWidget *widget, gpointer data)
153 {
154 Viewer *v, *list, **prev_list;
155
156 DBG(DBG_proc, "xsane_viewer_close_callback\n");
157
158 v = (Viewer*) gtk_object_get_data(GTK_OBJECT(widget), "Viewer");
159
160 if (v->block_actions) /* actions blocked: return */
161 {
162 gdk_beep();
163 DBG(DBG_info, "xsane_viewer_close_callback: actions are blocked\n");
164 return TRUE;
165 }
166
167 if (!v->image_saved)
168 {
169 char buf[TEXTBUFSIZE];
170
171 snprintf(buf, sizeof(buf), WARN_VIEWER_IMAGE_NOT_SAVED);
172 xsane_viewer_set_sensitivity(v, FALSE);
173 if (xsane_back_gtk_decision(ERR_HEADER_WARNING, (gchar **) warning_xpm, buf, BUTTON_DO_NOT_CLOSE, BUTTON_DISCARD_IMAGE, TRUE /* wait */))
174 {
175 xsane_viewer_set_sensitivity(v, TRUE);
176 return TRUE;
177 }
178 }
179
180 /* when no modification is allowed then we work with the original file */
181 /* so we should not erase it */
182 if (v->allow_modification != VIEWER_NO_MODIFICATION)
183 {
184 remove(v->filename);
185 }
186
187 if (v->undo_filename)
188 {
189 remove(v->undo_filename);
190 }
191
192 gtk_widget_destroy(v->top);
193
194
195 list = xsane.viewer_list;
196 prev_list = &xsane.viewer_list;
197
198 while (list)
199 {
200 if (list == v)
201 {
202 DBG(DBG_info, "removing viewer from viewer list\n");
203 *prev_list = list->next_viewer;
204 break;
205 }
206
207 prev_list = &list->next_viewer;
208 list = list->next_viewer;
209 }
210
211 if (v->active_dialog)
212 {
213 gtk_widget_destroy(v->active_dialog);
214 }
215
216 if (v->filename)
217 {
218 free(v->filename);
219 }
220
221 if (v->undo_filename)
222 {
223 free(v->undo_filename);
224 }
225
226 if (v->output_filename)
227 {
228 free(v->output_filename);
229 }
230
231 if (v->last_saved_filename)
232 {
233 free(v->last_saved_filename);
234 }
235
236 free(v);
237
238 return TRUE;
239 }
240
241 /* ---------------------------------------------------------------------------------------------------------------------- */
242
xsane_viewer_dialog_cancel(GtkWidget * window,gpointer data)243 static void xsane_viewer_dialog_cancel(GtkWidget *window, gpointer data)
244 {
245 Viewer *v = (Viewer *) data;
246
247 xsane_viewer_set_sensitivity(v, TRUE);
248 v->active_dialog = NULL;
249 }
250
251 /* ---------------------------------------------------------------------------------------------------------------------- */
252
xsane_viewer_save_callback(GtkWidget * window,gpointer data)253 static void xsane_viewer_save_callback(GtkWidget *window, gpointer data)
254 {
255 Viewer *v = (Viewer *) data;
256 char outputfilename[1024];
257 char *inputfilename;
258 char windowname[TEXTBUFSIZE];
259 int output_format;
260 int abort = 0;
261 int show_extra_widgets;
262 char buf[TEXTBUFSIZE];
263
264 if (v->block_actions) /* actions blocked: return */
265 {
266 gdk_beep();
267 DBG(DBG_info, "xsane_viewer_save_callback: actions are blocked\n");
268 return;
269 }
270
271 DBG(DBG_proc, "xsane_viewer_save_callback\n");
272
273 xsane_viewer_set_sensitivity(v, FALSE);
274
275 if (v->output_filename)
276 {
277 strncpy(outputfilename, v->output_filename, sizeof(outputfilename));
278 }
279 else
280 {
281 strncpy(outputfilename, preferences.filename, sizeof(outputfilename));
282 }
283
284 if (v->allow_modification == VIEWER_FULL_MODIFICATION) /* it is allowed to rename the image */
285 {
286 snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_VIEWER_OUTPUT_FILENAME, xsane.device_text);
287
288 show_extra_widgets = XSANE_GET_FILENAME_SHOW_FILETYPE;
289 if (v->cms_enable)
290 {
291 show_extra_widgets |= XSANE_GET_FILENAME_SHOW_CMS_FUNCTION;
292 }
293
294 umask((mode_t) preferences.directory_umask); /* define new file permissions */
295 abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, &v->selection_filetype, &v->cms_function, XSANE_FILE_CHOOSER_ACTION_SAVE, show_extra_widgets, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES);
296 umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
297
298 if (abort)
299 {
300 xsane_viewer_set_sensitivity(v, TRUE);
301 return;
302 }
303 }
304
305 if (v->output_filename)
306 {
307 free(v->output_filename);
308 }
309
310 v->output_filename = strdup(outputfilename);
311
312 #if 0
313 /* to be removed */
314 xsane_update_counter_in_filename(&v->output_filename, FALSE, 0, preferences.filename_counter_len); /* set correct counter length */
315 #endif
316
317
318 if ((preferences.overwrite_warning) && (!v->keep_viewer_pnm_format)) /* test if filename already used when filename can be changed by user */
319 {
320 FILE *testfile;
321
322 testfile = fopen(v->output_filename, "rb"); /* read binary (b for win32) */
323 if (testfile) /* filename used: skip */
324 {
325 char buf[TEXTBUFSIZE];
326
327 fclose(testfile);
328 snprintf(buf, sizeof(buf), WARN_FILE_EXISTS, v->output_filename);
329 if (xsane_back_gtk_decision(ERR_HEADER_WARNING, (gchar **) warning_xpm, buf, BUTTON_OVERWRITE, BUTTON_CANCEL, TRUE /* wait */) == FALSE)
330 {
331 xsane_viewer_set_sensitivity(v, TRUE);
332 return;
333 }
334 }
335 }
336
337 inputfilename = strdup(v->filename);
338
339 output_format = xsane_identify_output_format(v->output_filename, v->selection_filetype, 0);
340
341 if (((!v->allow_reduction_to_lineart) && (output_format == XSANE_PNM)) || /* save PNM but do not reduce to lineart (if lineart) */
342 (v->keep_viewer_pnm_format)) /* we have to make sure that we save in viewer pnm format */
343 {
344 if (xsane_create_secure_file(v->output_filename)) /* remove possibly existing symbolic links for security */
345 {
346 char buf[TEXTBUFSIZE];
347
348 snprintf(buf, sizeof(buf), "%s %s %s\n", ERR_DURING_SAVE, ERR_CREATE_SECURE_FILE, v->output_filename);
349 xsane_back_gtk_error(buf, TRUE);
350 xsane_viewer_set_sensitivity(v, TRUE);
351 return; /* error */
352 }
353
354 snprintf(buf, sizeof(buf), "%s: %s", PROGRESS_SAVING_DATA, v->output_filename);
355 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), buf);
356
357 xsane_copy_file_by_name(v->output_filename, v->filename, v->progress_bar, &v->cancel_save);
358 }
359 else
360 {
361 xsane_save_image_as(v->output_filename, inputfilename, output_format, v->cms_enable, v->cms_function, v->cms_intent, v->cms_bpc, v->progress_bar, &v->cancel_save);
362 }
363
364 free(inputfilename);
365
366 v->image_saved = TRUE;
367
368 v->last_saved_filename = strdup(v->output_filename);
369 snprintf(buf, sizeof(buf), "%s %s - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text);
370 gtk_window_set_title(GTK_WINDOW(v->top), buf);
371
372 if (xsane.print_filenames) /* print created filenames to stdout? */
373 {
374 if (v->output_filename[0] != '/') /* relative path */
375 {
376 char pathname[512];
377 getcwd(pathname, sizeof(pathname));
378 printf("XSANE_IMAGE_FILENAME: %s/%s\n", pathname, v->output_filename);
379 fflush(stdout);
380 }
381 else /* absolute path */
382 {
383 printf("XSANE_IMAGE_FILENAME: %s\n", v->output_filename);
384 fflush(stdout);
385 }
386 }
387
388 xsane_viewer_set_sensitivity(v, TRUE);
389 }
390
391 /* ---------------------------------------------------------------------------------------------------------------------- */
392
xsane_viewer_ocr_callback(GtkWidget * window,gpointer data)393 static void xsane_viewer_ocr_callback(GtkWidget *window, gpointer data)
394 {
395 Viewer *v = (Viewer *) data;
396 char outputfilename[1024];
397 char *extensionptr;
398 char windowname[TEXTBUFSIZE];
399 int abort = 0;
400
401 if (v->block_actions) /* actions blocked: return */
402 {
403 gdk_beep();
404 DBG(DBG_info, "xsane_viewer_ocr_callback: actions are blocked\n");
405 return;
406 }
407
408 DBG(DBG_proc, "xsane_viewer_ocr_callback\n");
409
410 xsane_viewer_set_sensitivity(v, FALSE);
411
412 strncpy(outputfilename, preferences.filename, sizeof(outputfilename)-5);
413
414 extensionptr = strchr(outputfilename, '.');
415 if (!extensionptr)
416 {
417 extensionptr=outputfilename + strlen(outputfilename);
418 }
419 strcpy(extensionptr, ".txt");
420
421 snprintf(windowname, sizeof(windowname), "%s %s %s", xsane.prog_name, WINDOW_OCR_OUTPUT_FILENAME, xsane.device_text);
422
423 umask((mode_t) preferences.directory_umask); /* define new file permissions */
424 abort = xsane_back_gtk_get_filename(windowname, outputfilename, sizeof(outputfilename), outputfilename, NULL, NULL, XSANE_FILE_CHOOSER_ACTION_SAVE, XSANE_GET_FILENAME_SHOW_FILETYPE, XSANE_FILE_FILTER_ALL | XSANE_FILE_FILTER_IMAGES, XSANE_FILE_FILTER_IMAGES);
425 umask(XSANE_DEFAULT_UMASK); /* define new file permissions */
426
427 if (abort)
428 {
429 xsane_viewer_set_sensitivity(v, TRUE);
430 return;
431 }
432
433 while (gtk_events_pending()) /* give gtk the chance to remove the file selection dialog */
434 {
435 gtk_main_iteration();
436 }
437
438 xsane_save_image_as_text(outputfilename, v->filename, v->progress_bar, &v->cancel_save);
439
440 xsane_viewer_set_sensitivity(v, TRUE);
441 }
442
443 /* ---------------------------------------------------------------------------------------------------------------------- */
444
xsane_viewer_clone_callback(GtkWidget * window,gpointer data)445 static void xsane_viewer_clone_callback(GtkWidget *window, gpointer data)
446 {
447 Viewer *v = (Viewer *) data;
448 char outfilename[PATH_MAX];
449
450 if (v->block_actions) /* actions blocked: return */
451 {
452 gdk_beep();
453 DBG(DBG_info, "xsane_viewer_clone_callback: actions are blocked\n");
454 return;
455 }
456
457 DBG(DBG_proc, "xsane_viewer_clone_callback\n");
458
459 xsane_viewer_set_sensitivity(v, FALSE);
460
461 xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
462 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), PROGRESS_CLONING_DATA);
463 xsane_copy_file_by_name(outfilename, v->filename, v->progress_bar, &v->cancel_save);
464
465 xsane_viewer_set_sensitivity(v, TRUE);
466
467 if (v->last_saved_filename)
468 {
469 char buf[TEXTBUFSIZE];
470 snprintf(buf, sizeof(buf), "%s%s", FILENAME_PREFIX_CLONE_OF, v->last_saved_filename);
471 xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, buf, v->allow_modification, v->image_saved);
472 }
473 else
474 {
475 xsane_viewer_new(outfilename, v->selection_filetype, v->allow_reduction_to_lineart, NULL, v->allow_modification, v->image_saved);
476 }
477 }
478
479 /* ---------------------------------------------------------------------------------------------------------------------- */
480
xsane_viewer_adjustment_float_changed(GtkAdjustment * adj_data,float * val)481 static void xsane_viewer_adjustment_float_changed(GtkAdjustment *adj_data, float *val)
482 {
483 *val = (float) adj_data->value;
484 }
485
486 /* ---------------------------------------------------------------------------------------------------------------------- */
487
xsane_viewer_adjustment_int_changed(GtkAdjustment * adj_data,int * val)488 static void xsane_viewer_adjustment_int_changed(GtkAdjustment *adj_data, int *val)
489 {
490 *val = (int) adj_data->value;
491 }
492
493 /* ---------------------------------------------------------------------------------------------------------------------- */
494
xsane_viewer_button_changed(GtkWidget * button,int * val)495 static void xsane_viewer_button_changed(GtkWidget *button, int *val)
496 {
497 *val = GTK_TOGGLE_BUTTON(button)->active;
498 }
499
500 /* ---------------------------------------------------------------------------------------------------------------------- */
501
xsane_viewer_scale_set_scale_value_and_adjustments(GtkAdjustment * adj_data,double * scale_val)502 static void xsane_viewer_scale_set_scale_value_and_adjustments(GtkAdjustment *adj_data, double *scale_val)
503 {
504 GtkAdjustment *adj;
505 int image_width, image_height;
506
507 *scale_val = adj_data->value;
508
509 image_width = (int) gtk_object_get_data(GTK_OBJECT(adj_data), "image_width");
510 image_height = (int) gtk_object_get_data(GTK_OBJECT(adj_data), "image_height");
511
512 adj = (GtkAdjustment*) gtk_object_get_data(GTK_OBJECT(adj_data), "size-x-adjustment");
513 if ((adj) && (image_width))
514 {
515 gtk_adjustment_set_value(adj, (*scale_val) * image_width);
516 }
517
518 adj = (GtkAdjustment*) gtk_object_get_data(GTK_OBJECT(adj_data), "size-y-adjustment");
519 if ((adj) && (image_height))
520 {
521 gtk_adjustment_set_value(adj, (*scale_val) * image_height);
522 }
523 }
524
525 /* ---------------------------------------------------------------------------------------------------------------------- */
526
xsane_viewer_scale_set_size_x_value_and_adjustments(GtkAdjustment * adj_data,double * scale_val)527 static void xsane_viewer_scale_set_size_x_value_and_adjustments(GtkAdjustment *adj_data, double *scale_val)
528 {
529 GtkAdjustment *adj;
530 int image_width, image_height;
531
532 image_width = (int) gtk_object_get_data(GTK_OBJECT(adj_data), "image_width");
533 image_height = (int) gtk_object_get_data(GTK_OBJECT(adj_data), "image_height");
534
535 if (!image_width)
536 {
537 return; /* we are not able to calulate the scale value */
538 }
539
540 *scale_val = adj_data->value / image_width;
541
542 adj = (GtkAdjustment*) gtk_object_get_data(GTK_OBJECT(adj_data), "scale-adjustment");
543 if (adj)
544 {
545 gtk_adjustment_set_value(adj, *scale_val);
546 }
547 }
548
549 /* ---------------------------------------------------------------------------------------------------------------------- */
550
xsane_viewer_scale_set_size_y_value_and_adjustments(GtkAdjustment * adj_data,double * scale_val)551 static void xsane_viewer_scale_set_size_y_value_and_adjustments(GtkAdjustment *adj_data, double *scale_val)
552 {
553 GtkAdjustment *adj;
554 int image_width, image_height;
555
556 image_width = (int) gtk_object_get_data(GTK_OBJECT(adj_data), "image_width");
557 image_height = (int) gtk_object_get_data(GTK_OBJECT(adj_data), "image_height");
558
559 if (!image_height)
560 {
561 return; /* we are not able to calulate the scale value */
562 }
563
564 *scale_val = adj_data->value / image_height;
565
566 adj = (GtkAdjustment*) gtk_object_get_data(GTK_OBJECT(adj_data), "scale-adjustment");
567 if (adj)
568 {
569 gtk_adjustment_set_value(adj, *scale_val);
570 }
571 }
572
573 /* ---------------------------------------------------------------------------------------------------------------------- */
574
xsane_viewer_scale_callback(GtkWidget * window,gpointer data)575 static void xsane_viewer_scale_callback(GtkWidget *window, gpointer data)
576 {
577 Viewer *v = (Viewer *) data;
578 GtkWidget *selection_dialog;
579 GtkWidget *frame;
580 GtkWidget *hbox, *vbox;
581 GtkWidget *button;
582 GtkWidget *scale_widget, *scalex_widget, *scaley_widget;
583 GtkAdjustment *adjustment_size_x;
584 GtkAdjustment *adjustment_size_y;
585 GtkWidget *spinbutton;
586 GdkPixmap *pixmap;
587 GdkBitmap *mask;
588 GtkWidget *pixmapwidget;
589 char buf[TEXTBUFSIZE];
590 FILE *infile;
591 Image_info image_info;
592
593 if (v->block_actions == TRUE) /* actions blocked: return */
594 {
595 gdk_beep();
596 DBG(DBG_info, "xsane_viewer_scale_callback: actions are blocked\n");
597 return;
598 }
599
600 DBG(DBG_proc, "xsane_viewer_scale_callback\n");
601
602 xsane_viewer_set_sensitivity(v, FALSE);
603 v->block_actions = 2; /* do not set it to TRUE because we have to recall this dialog! */
604
605 infile = fopen(v->filename, "rb");
606 if (!infile)
607 {
608 DBG(DBG_error, "could not load file %s\n", v->filename);
609 xsane_viewer_set_sensitivity(v, TRUE);
610 return;
611 }
612
613 xsane_read_pnm_header(infile, &image_info);
614
615 fclose(infile);
616
617
618 if (v->output_filename)
619 {
620 snprintf(buf, sizeof(buf), "%s: %s", WINDOW_SCALE, v->output_filename);
621 }
622 else
623 {
624 snprintf(buf, sizeof(buf), WINDOW_SCALE);
625 }
626
627 if (v->active_dialog) /* use active dialog */
628 {
629 selection_dialog = v->active_dialog;
630 gtk_container_foreach(GTK_CONTAINER(selection_dialog), (GtkCallback) gtk_widget_destroy, NULL);
631 if (!v->bind_scale)
632 {
633 v->y_scale_factor = v->x_scale_factor;
634 }
635 }
636 else /* first time the dialog is opened */
637 {
638 selection_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
639 gtk_window_set_resizable(GTK_WINDOW(selection_dialog), FALSE);
640 gtk_window_set_position(GTK_WINDOW(selection_dialog), GTK_WIN_POS_MOUSE);
641 gtk_window_set_title(GTK_WINDOW(selection_dialog), buf);
642 xsane_set_window_icon(selection_dialog, 0);
643 g_signal_connect(GTK_OBJECT(selection_dialog), "destroy", (GtkSignalFunc) xsane_viewer_dialog_cancel, (void *) v);
644
645 v->active_dialog = selection_dialog;
646 v->x_scale_factor = 1.0;
647 v->y_scale_factor = 1.0;
648 v->bind_scale = TRUE;
649 }
650
651 frame = gtk_frame_new(0);
652 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
653 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
654 gtk_container_add(GTK_CONTAINER(selection_dialog), frame);
655 gtk_widget_show(frame);
656
657 vbox = gtk_vbox_new(FALSE, 5);
658 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
659 gtk_container_add(GTK_CONTAINER(frame), vbox);
660 gtk_widget_show(vbox);
661
662 /* bind scale */
663 button = gtk_check_button_new_with_label(BUTTON_SCALE_BIND);
664 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5);
665 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), v->bind_scale);
666 g_signal_connect(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_viewer_button_changed, (void *) &v->bind_scale);
667 g_signal_connect_after(GTK_OBJECT(button), "toggled", (GtkSignalFunc) xsane_viewer_scale_callback, (void *) v);
668 gtk_widget_show(button);
669
670 if (v->bind_scale)
671 {
672 hbox = gtk_hbox_new(FALSE, 0);
673 gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
674 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
675 gtk_widget_show(hbox);
676
677 /* scale factor: <-> */
678 xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(hbox), zoom_xpm,
679 DESC_SCALE_FACTOR,
680 0.01, 4.0, 0.01, 0.1, 2, &v->x_scale_factor, &scale_widget,
681 0, xsane_viewer_scale_set_scale_value_and_adjustments,
682 TRUE);
683
684 /* x-size */
685 pixmap = gdk_pixmap_create_from_xpm_d(selection_dialog->window, &mask, xsane.bg_trans, (gchar **) size_x_xpm);
686 pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
687 gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 20);
688 gtk_widget_show(pixmapwidget);
689 gdk_drawable_unref(pixmap);
690 gdk_drawable_unref(mask);
691
692 adjustment_size_x = (GtkAdjustment *) gtk_adjustment_new(v->x_scale_factor * image_info.image_width , 0.01 * image_info.image_width, 4.0 * image_info.image_width, 1.0, 5.0, 0.0);
693 spinbutton = gtk_spin_button_new(adjustment_size_x, 0, 0);
694 g_signal_connect(GTK_OBJECT(adjustment_size_x), "value_changed", (GtkSignalFunc) xsane_viewer_scale_set_size_x_value_and_adjustments, (void *) &v->x_scale_factor);
695 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE);
696 gtk_widget_set_size_request(spinbutton, 80, -1);
697 gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 0);
698 gtk_widget_show(spinbutton);
699 xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, DESC_SCALE_WIDTH);
700
701 /* y-size */
702 pixmap = gdk_pixmap_create_from_xpm_d(selection_dialog->window, &mask, xsane.bg_trans, (gchar **) size_y_xpm);
703 pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
704 gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 20);
705 gtk_widget_show(pixmapwidget);
706 gdk_drawable_unref(pixmap);
707 gdk_drawable_unref(mask);
708
709 adjustment_size_y = (GtkAdjustment *) gtk_adjustment_new(v->x_scale_factor * image_info.image_height , 0.01 * image_info.image_height, 4.0 * image_info.image_height, 1.0, 5.0, 0.0);
710 spinbutton = gtk_spin_button_new(adjustment_size_y, 0, 0);
711 g_signal_connect(GTK_OBJECT(adjustment_size_y), "value_changed", (GtkSignalFunc) xsane_viewer_scale_set_size_y_value_and_adjustments, (void *) &v->x_scale_factor);
712 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE);
713 gtk_widget_set_size_request(spinbutton, 80, -1);
714 gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 0);
715 gtk_widget_show(spinbutton);
716 xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, DESC_SCALE_HEIGHT);
717
718 gtk_object_set_data(GTK_OBJECT(scale_widget), "size-x-adjustment", (void *) adjustment_size_x);
719 gtk_object_set_data(GTK_OBJECT(scale_widget), "size-y-adjustment", (void *) adjustment_size_y);
720 gtk_object_set_data(GTK_OBJECT(scale_widget), "image_width", (void *) image_info.image_width);
721 gtk_object_set_data(GTK_OBJECT(scale_widget), "image_height", (void *) image_info.image_height);
722
723 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "scale-adjustment", (void *) scale_widget);
724 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "size-y-adjustment", (void *) adjustment_size_y);
725 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "image_width", (void *) image_info.image_width);
726 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "image_height", (void *) image_info.image_height);
727
728 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "scale-adjustment", (void *) scale_widget);
729 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "size-x-adjustment", (void *) adjustment_size_x);
730 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "image_width", (void *) image_info.image_width);
731 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "image_height", (void *) image_info.image_height);
732 }
733 else
734 {
735 /* X */
736 hbox = gtk_hbox_new(FALSE, 0);
737 gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
738 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
739 gtk_widget_show(hbox);
740
741 /* x_scale factor: <-> */
742 xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(hbox), zoom_x_xpm,
743 DESC_X_SCALE_FACTOR,
744 0.01, 4.0, 0.01, 0.1, 2, &v->x_scale_factor, &scalex_widget,
745 0, xsane_viewer_scale_set_scale_value_and_adjustments,
746 TRUE);
747
748 /* x-size */
749 pixmap = gdk_pixmap_create_from_xpm_d(selection_dialog->window, &mask, xsane.bg_trans, (gchar **) size_x_xpm);
750 pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
751 gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 20);
752 gtk_widget_show(pixmapwidget);
753 gdk_drawable_unref(pixmap);
754 gdk_drawable_unref(mask);
755
756 adjustment_size_x = (GtkAdjustment *) gtk_adjustment_new(v->x_scale_factor * image_info.image_width , 0.01 * image_info.image_width, 4.0 * image_info.image_width, 1.0, 5.0, 0.0);
757 spinbutton = gtk_spin_button_new(adjustment_size_x, 0, 0);
758 g_signal_connect(GTK_OBJECT(adjustment_size_x), "value_changed", (GtkSignalFunc) xsane_viewer_scale_set_size_x_value_and_adjustments, (void *) &v->x_scale_factor);
759 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE);
760 gtk_widget_set_size_request(spinbutton, 80, -1);
761 gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 0);
762 gtk_widget_show(spinbutton);
763 xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, DESC_SCALE_WIDTH);
764
765 gtk_object_set_data(GTK_OBJECT(scalex_widget), "size-x-adjustment", (void *) adjustment_size_x);
766 gtk_object_set_data(GTK_OBJECT(scalex_widget), "image_width", (void *) image_info.image_width);
767 gtk_object_set_data(GTK_OBJECT(scalex_widget), "image_height", (void *) image_info.image_height);
768
769 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "scale-adjustment", (void *) scalex_widget);
770 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "image_width", (void *) image_info.image_width);
771 gtk_object_set_data(GTK_OBJECT(adjustment_size_x), "image_height", (void *) image_info.image_height);
772
773
774 /* Y */
775 hbox = gtk_hbox_new(FALSE, 0);
776 gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
777 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
778 gtk_widget_show(hbox);
779
780 /* y_scale factor: <-> */
781 xsane_range_new_with_pixmap(xsane.xsane_window->window, GTK_BOX(hbox), zoom_y_xpm,
782 DESC_Y_SCALE_FACTOR,
783 0.01, 4.0, 0.01, 0.1, 2, &v->y_scale_factor, &scaley_widget,
784 0, xsane_viewer_scale_set_scale_value_and_adjustments,
785 TRUE);
786
787 /* y-size */
788 pixmap = gdk_pixmap_create_from_xpm_d(selection_dialog->window, &mask, xsane.bg_trans, (gchar **) size_y_xpm);
789 pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
790 gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 20);
791 gtk_widget_show(pixmapwidget);
792 gdk_drawable_unref(pixmap);
793 gdk_drawable_unref(mask);
794
795 adjustment_size_y = (GtkAdjustment *) gtk_adjustment_new(v->y_scale_factor * image_info.image_height , 0.01 * image_info.image_height, 4.0 * image_info.image_height, 1.0, 5.0, 0.0);
796 spinbutton = gtk_spin_button_new(adjustment_size_y, 0, 0);
797 g_signal_connect(GTK_OBJECT(adjustment_size_y), "value_changed", (GtkSignalFunc) xsane_viewer_scale_set_size_y_value_and_adjustments, (void *) &v->y_scale_factor);
798 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), FALSE);
799 gtk_widget_set_size_request(spinbutton, 80, -1);
800 gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 0);
801 gtk_widget_show(spinbutton);
802 xsane_back_gtk_set_tooltip(xsane.tooltips, spinbutton, DESC_SCALE_HEIGHT);
803
804 gtk_object_set_data(GTK_OBJECT(scaley_widget), "size-y-adjustment", (void *) adjustment_size_y);
805 gtk_object_set_data(GTK_OBJECT(scaley_widget), "image_width", (void *) image_info.image_width);
806 gtk_object_set_data(GTK_OBJECT(scaley_widget), "image_height", (void *) image_info.image_height);
807
808 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "scale-adjustment", (void *) scaley_widget);
809 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "image_width", (void *) image_info.image_width);
810 gtk_object_set_data(GTK_OBJECT(adjustment_size_y), "image_height", (void *) image_info.image_height);
811 }
812
813 /* Apply Cancel */
814
815 hbox = gtk_hbox_new(FALSE, 0);
816 gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
817 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
818 gtk_widget_show(hbox);
819
820 button = gtk_button_new_with_label(BUTTON_APPLY);
821 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
822 g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_viewer_scale_image, (void *) v);
823 g_signal_connect_swapped(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, (GtkObject *) selection_dialog);
824
825 gtk_container_add(GTK_CONTAINER(hbox), button);
826 gtk_widget_grab_default(button);
827 gtk_widget_show(button);
828
829 button = gtk_button_new_with_label(BUTTON_CANCEL);
830 g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_viewer_dialog_cancel, (void *) v);
831 g_signal_connect_swapped(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, (GtkObject *) selection_dialog);
832 gtk_container_add(GTK_CONTAINER(hbox), button);
833 gtk_widget_show(button);
834
835 gtk_widget_show(selection_dialog);
836 }
837
838 /* ---------------------------------------------------------------------------------------------------------------------- */
839
xsane_viewer_despeckle_callback(GtkWidget * window,gpointer data)840 static void xsane_viewer_despeckle_callback(GtkWidget *window, gpointer data)
841 {
842 Viewer *v = (Viewer *) data;
843 GtkWidget *selection_dialog;
844 GtkWidget *frame;
845 GtkWidget *hbox, *vbox;
846 GtkWidget *label, *spinbutton, *button;
847 GtkAdjustment *adjustment;
848 char buf[TEXTBUFSIZE];
849
850 if (v->block_actions) /* actions blocked: return */
851 {
852 gdk_beep();
853 DBG(DBG_info, "xsane_viewer_despeckle_callback: actions are blocked\n");
854 return;
855 }
856
857 DBG(DBG_proc, "xsane_viewer_despeckle_callback\n");
858
859 xsane_viewer_set_sensitivity(v, FALSE);
860
861 if (v->output_filename)
862 {
863 snprintf(buf, sizeof(buf), "%s: %s", WINDOW_DESPECKLE, v->output_filename);
864 }
865 else
866 {
867 snprintf(buf, sizeof(buf), WINDOW_DESPECKLE);
868 }
869
870 selection_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
871 gtk_window_set_position(GTK_WINDOW(selection_dialog), GTK_WIN_POS_MOUSE);
872 gtk_window_set_title(GTK_WINDOW(selection_dialog), buf);
873 xsane_set_window_icon(selection_dialog, 0);
874 g_signal_connect(GTK_OBJECT(selection_dialog), "destroy", (GtkSignalFunc) xsane_viewer_dialog_cancel, (void *) v);
875
876 v->active_dialog = selection_dialog;
877
878 frame = gtk_frame_new(0);
879 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
880 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
881 gtk_container_add(GTK_CONTAINER(selection_dialog), frame);
882 gtk_widget_show(frame);
883
884 vbox = gtk_vbox_new(FALSE, 5);
885 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
886 gtk_container_add(GTK_CONTAINER(frame), vbox);
887 gtk_widget_show(vbox);
888
889 /* Despeckle radius: <-> */
890
891 v->despeckle_radius = 2;
892
893 hbox = gtk_hbox_new(FALSE, 2);
894 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
895 gtk_widget_show(hbox);
896
897 label = gtk_label_new(TEXT_DESPECKLE_RADIUS);
898 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
899 gtk_widget_show(label);
900
901 adjustment = (GtkAdjustment *) gtk_adjustment_new(2.0, 2.0, 10.0, 1.0, 5.0, 0.0);
902 spinbutton = gtk_spin_button_new(adjustment, 0, 0);
903 g_signal_connect(GTK_OBJECT(adjustment), "value_changed", (GtkSignalFunc) xsane_viewer_adjustment_int_changed, (void *) &v->despeckle_radius);
904 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE);
905 gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10);
906 gtk_widget_show(spinbutton);
907
908 /* Apply Cancel */
909
910 hbox = gtk_hbox_new(FALSE, 0);
911 gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
912 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
913 gtk_widget_show(hbox);
914
915 button = gtk_button_new_with_label(BUTTON_APPLY);
916 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
917 g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_viewer_despeckle_image, (void *) v);
918 g_signal_connect_swapped(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, (GtkObject *) selection_dialog);
919 gtk_container_add(GTK_CONTAINER(hbox), button);
920 gtk_widget_grab_default(button);
921 gtk_widget_show(button);
922
923 button = gtk_button_new_with_label(BUTTON_CANCEL);
924 g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_viewer_dialog_cancel, (void *) v);
925 g_signal_connect_swapped(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, (GtkObject *) selection_dialog);
926 gtk_container_add(GTK_CONTAINER(hbox), button);
927 gtk_widget_show(button);
928
929 gtk_widget_show(selection_dialog);
930 }
931
932 /* ---------------------------------------------------------------------------------------------------------------------- */
933
xsane_viewer_blur_callback(GtkWidget * window,gpointer data)934 static void xsane_viewer_blur_callback(GtkWidget *window, gpointer data)
935 {
936 Viewer *v = (Viewer *) data;
937 GtkWidget *selection_dialog;
938 GtkWidget *frame;
939 GtkWidget *hbox, *vbox;
940 GtkWidget *label, *spinbutton, *button;
941 GtkAdjustment *adjustment;
942 char buf[TEXTBUFSIZE];
943
944 if (v->block_actions) /* actions blocked: return */
945 {
946 gdk_beep();
947 DBG(DBG_info, "xsane_viewer_blur_callback: actions are blocked\n");
948 return;
949 }
950
951 DBG(DBG_proc, "xsane_viewer_blur_callback\n");
952
953 xsane_viewer_set_sensitivity(v, FALSE);
954
955 if (v->output_filename)
956 {
957 snprintf(buf, sizeof(buf), "%s: %s", WINDOW_BLUR, v->output_filename);
958 }
959 else
960 {
961 snprintf(buf, sizeof(buf), WINDOW_BLUR);
962 }
963
964 selection_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
965 gtk_window_set_position(GTK_WINDOW(selection_dialog), GTK_WIN_POS_MOUSE);
966 gtk_window_set_title(GTK_WINDOW(selection_dialog), buf);
967 xsane_set_window_icon(selection_dialog, 0);
968 g_signal_connect(GTK_OBJECT(selection_dialog), "destroy", (GtkSignalFunc) xsane_viewer_dialog_cancel, (void *) v);
969
970 v->active_dialog = selection_dialog;
971
972 frame = gtk_frame_new(0);
973 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
974 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
975 gtk_container_add(GTK_CONTAINER(selection_dialog), frame);
976 gtk_widget_show(frame);
977
978 vbox = gtk_vbox_new(FALSE, 5);
979 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
980 gtk_container_add(GTK_CONTAINER(frame), vbox);
981 gtk_widget_show(vbox);
982
983
984 /* Blur radius: <-> */
985
986 v->blur_radius = 1.0;
987
988 hbox = gtk_hbox_new(FALSE, 2);
989 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
990 gtk_widget_show(hbox);
991
992 label = gtk_label_new(TEXT_BLUR_RADIUS);
993 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
994 gtk_widget_show(label);
995
996 adjustment = (GtkAdjustment *) gtk_adjustment_new(1.0, 1.0, 20.0, 0.1, 1.0, 0.0);
997 spinbutton = gtk_spin_button_new(adjustment, 0, 2);
998 g_signal_connect(GTK_OBJECT(adjustment), "value_changed", (GtkSignalFunc) xsane_viewer_adjustment_float_changed, (void *) &v->blur_radius);
999 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE);
1000 gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10);
1001 gtk_widget_show(spinbutton);
1002
1003 /* Apply Cancel */
1004
1005 hbox = gtk_hbox_new(FALSE, 0);
1006 gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
1007 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
1008 gtk_widget_show(hbox);
1009
1010 button = gtk_button_new_with_label(BUTTON_APPLY);
1011 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1012 g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_viewer_blur_image, (void *) v);
1013 gtk_container_add(GTK_CONTAINER(hbox), button);
1014 gtk_widget_grab_default(button);
1015 gtk_widget_show(button);
1016
1017 button = gtk_button_new_with_label(BUTTON_CANCEL);
1018 g_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) xsane_viewer_dialog_cancel, (void *) v);
1019 g_signal_connect_swapped(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, (GtkObject *) selection_dialog);
1020 gtk_container_add(GTK_CONTAINER(hbox), button);
1021 gtk_widget_show(button);
1022
1023 gtk_widget_show(selection_dialog);
1024 }
1025
1026 /* ---------------------------------------------------------------------------------------------------------------------- */
1027
xsane_viewer_undo_callback(GtkWidget * window,gpointer data)1028 static void xsane_viewer_undo_callback(GtkWidget *window, gpointer data)
1029 {
1030 Viewer *v = (Viewer *) data;
1031
1032 DBG(DBG_proc, "xsane_viewer_undo_callback\n");
1033
1034 if (!v->undo_filename)
1035 {
1036 DBG(DBG_info, "no undo file\n");
1037 return;
1038 }
1039
1040 DBG(DBG_info, "removing file %s\n", v->filename);
1041 remove(v->filename);
1042
1043 DBG(DBG_info, "using undo file %s\n", v->undo_filename);
1044 v->filename = v->undo_filename;
1045
1046 v->undo_filename = NULL;
1047 v->image_saved = FALSE;
1048
1049 xsane_viewer_read_image(v);
1050
1051 if (v->last_saved_filename)
1052 {
1053 char buf[TEXTBUFSIZE];
1054 snprintf(buf, sizeof(buf), "%s (%s) - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text);
1055 gtk_window_set_title(GTK_WINDOW(v->top), buf);
1056 }
1057
1058 gtk_widget_set_sensitive(GTK_WIDGET(v->undo), FALSE);
1059 gtk_widget_set_sensitive(GTK_WIDGET(v->undo_menu_item), FALSE);
1060 }
1061
1062 /* ---------------------------------------------------------------------------------------------------------------------- */
1063
xsane_viewer_scale_image(GtkWidget * window,gpointer data)1064 static void xsane_viewer_scale_image(GtkWidget *window, gpointer data)
1065 {
1066 FILE *outfile;
1067 FILE *infile;
1068 char outfilename[PATH_MAX];
1069 Viewer *v = (Viewer *) data;
1070 Image_info image_info;
1071
1072 DBG(DBG_proc, "xsane_viewer_scale_image\n");
1073
1074 gtk_widget_destroy(v->active_dialog);
1075
1076 xsane_viewer_set_sensitivity(v, FALSE);
1077
1078 infile = fopen(v->filename, "rb");
1079 if (!infile)
1080 {
1081 DBG(DBG_error, "could not load file %s\n", v->filename);
1082 xsane_viewer_set_sensitivity(v, TRUE);
1083 return;
1084 }
1085
1086 xsane_read_pnm_header(infile, &image_info);
1087
1088 DBG(DBG_info, "scaling image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
1089
1090 xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
1091
1092 outfile = fopen(outfilename, "wb");
1093 if (!outfile)
1094 {
1095 DBG(DBG_error, "could not save file %s\n", outfilename);
1096 xsane_viewer_set_sensitivity(v, TRUE);
1097 return;
1098 }
1099
1100 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), PROGRESS_SCALING_DATA);
1101
1102 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1103
1104 if (v->bind_scale)
1105 {
1106 v->y_scale_factor = v->x_scale_factor;
1107 }
1108
1109 xsane_save_scaled_image(outfile, infile, &image_info, v->x_scale_factor, v->y_scale_factor, v->progress_bar, &v->cancel_save);
1110
1111 fclose(infile);
1112 fclose(outfile);
1113
1114 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), "");
1115 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1116
1117 if (v->undo_filename)
1118 {
1119 DBG(DBG_info, "removing file %s\n", v->undo_filename);
1120 remove(v->undo_filename);
1121 free(v->undo_filename);
1122 }
1123
1124 v->undo_filename = v->filename;
1125 DBG(DBG_info, "undo file is %s\n", v->undo_filename);
1126 gtk_widget_set_sensitive(GTK_WIDGET(v->undo), TRUE);
1127 gtk_widget_set_sensitive(GTK_WIDGET(v->undo_menu_item), TRUE);
1128
1129 v->filename = strdup(outfilename);
1130 v->image_saved = FALSE;
1131
1132 xsane_viewer_read_image(v);
1133
1134 if (v->last_saved_filename)
1135 {
1136 char buf[TEXTBUFSIZE];
1137 snprintf(buf, sizeof(buf), "%s (%s) - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text);
1138 gtk_window_set_title(GTK_WINDOW(v->top), buf);
1139 }
1140
1141 xsane_viewer_set_sensitivity(v, TRUE);
1142 }
1143
1144 /* ---------------------------------------------------------------------------------------------------------------------- */
1145
xsane_viewer_despeckle_image(GtkWidget * window,gpointer data)1146 static void xsane_viewer_despeckle_image(GtkWidget *window, gpointer data)
1147 {
1148 FILE *outfile;
1149 FILE *infile;
1150 char outfilename[PATH_MAX];
1151 Viewer *v = (Viewer *) data;
1152 Image_info image_info;
1153
1154 DBG(DBG_proc, "xsane_viewer_despeckle_image\n");
1155
1156 gtk_widget_destroy(v->active_dialog);
1157
1158 xsane_viewer_set_sensitivity(v, FALSE);
1159
1160 infile = fopen(v->filename, "rb");
1161 if (!infile)
1162 {
1163 DBG(DBG_error, "could not load file %s\n", v->filename);
1164 xsane_viewer_set_sensitivity(v, TRUE);
1165 return;
1166 }
1167
1168 xsane_read_pnm_header(infile, &image_info);
1169
1170 DBG(DBG_info, "despeckling image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
1171
1172 xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
1173
1174 outfile = fopen(outfilename, "wb");
1175 if (!outfile)
1176 {
1177 DBG(DBG_error, "could not save file %s\n", outfilename);
1178 xsane_viewer_set_sensitivity(v, TRUE);
1179 return;
1180 }
1181
1182 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), PROGRESS_DESPECKLING_DATA);
1183
1184 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1185
1186 xsane_save_despeckle_image(outfile, infile, &image_info, v->despeckle_radius, v->progress_bar, &v->cancel_save);
1187
1188 fclose(infile);
1189 fclose(outfile);
1190
1191 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), "");
1192 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1193
1194 if (v->undo_filename)
1195 {
1196 DBG(DBG_info, "removing file %s\n", v->undo_filename);
1197 remove(v->undo_filename);
1198 free(v->undo_filename);
1199 }
1200
1201 v->undo_filename = v->filename;
1202 DBG(DBG_info, "undo file is %s\n", v->undo_filename);
1203 gtk_widget_set_sensitive(GTK_WIDGET(v->undo), TRUE);
1204 gtk_widget_set_sensitive(GTK_WIDGET(v->undo_menu_item), TRUE);
1205
1206 v->filename = strdup(outfilename);
1207 v->image_saved = FALSE;
1208
1209 xsane_viewer_read_image(v);
1210
1211 if (v->last_saved_filename)
1212 {
1213 char buf[TEXTBUFSIZE];
1214 snprintf(buf, sizeof(buf), "%s (%s) - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text);
1215 gtk_window_set_title(GTK_WINDOW(v->top), buf);
1216 }
1217
1218 xsane_viewer_set_sensitivity(v, TRUE);
1219 }
1220
1221 /* ---------------------------------------------------------------------------------------------------------------------- */
1222
xsane_viewer_blur_image(GtkWidget * window,gpointer data)1223 static void xsane_viewer_blur_image(GtkWidget *window, gpointer data)
1224 {
1225 FILE *outfile;
1226 FILE *infile;
1227 char outfilename[PATH_MAX];
1228 Viewer *v = (Viewer *) data;
1229 Image_info image_info;
1230
1231 DBG(DBG_proc, "xsane_viewer_blur_image\n");
1232
1233 gtk_widget_destroy(v->active_dialog);
1234
1235 xsane_viewer_set_sensitivity(v, FALSE);
1236
1237 infile = fopen(v->filename, "rb");
1238 if (!infile)
1239 {
1240 DBG(DBG_error, "could not load file %s\n", v->filename);
1241 xsane_viewer_set_sensitivity(v, TRUE);
1242 return;
1243 }
1244
1245 xsane_read_pnm_header(infile, &image_info);
1246
1247 DBG(DBG_info, "bluring image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
1248
1249 xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
1250
1251 outfile = fopen(outfilename, "wb");
1252 if (!outfile)
1253 {
1254 DBG(DBG_error, "could not save file %s\n", outfilename);
1255 xsane_viewer_set_sensitivity(v, TRUE);
1256 return;
1257 }
1258
1259 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), PROGRESS_BLURING_DATA);
1260
1261 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1262
1263 xsane_save_blur_image(outfile, infile, &image_info, v->blur_radius, v->progress_bar, &v->cancel_save);
1264
1265 fclose(infile);
1266 fclose(outfile);
1267
1268 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), "");
1269 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1270
1271 if (v->undo_filename)
1272 {
1273 DBG(DBG_info, "removing file %s\n", v->undo_filename);
1274 remove(v->undo_filename);
1275 free(v->undo_filename);
1276 }
1277
1278 v->undo_filename = v->filename;
1279 DBG(DBG_info, "undo file is %s\n", v->undo_filename);
1280 gtk_widget_set_sensitive(GTK_WIDGET(v->undo), TRUE);
1281 gtk_widget_set_sensitive(GTK_WIDGET(v->undo_menu_item), TRUE);
1282
1283 v->filename = strdup(outfilename);
1284 v->image_saved = FALSE;
1285
1286 xsane_viewer_read_image(v);
1287
1288 if (v->last_saved_filename)
1289 {
1290 char buf[TEXTBUFSIZE];
1291 snprintf(buf, sizeof(buf), "%s (%s) - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text);
1292 gtk_window_set_title(GTK_WINDOW(v->top), buf);
1293 }
1294
1295 xsane_viewer_set_sensitivity(v, TRUE);
1296 }
1297
1298 /* ---------------------------------------------------------------------------------------------------------------------- */
1299
xsane_viewer_rotate(Viewer * v,int rotation)1300 static void xsane_viewer_rotate(Viewer *v, int rotation)
1301 {
1302 FILE *outfile;
1303 FILE *infile;
1304 char outfilename[PATH_MAX];
1305 Image_info image_info;
1306
1307 if (v->block_actions) /* actions blocked: return */
1308 {
1309 gdk_beep();
1310 DBG(DBG_info, "xsane_viewer_rotate: actions are blocked\n");
1311 return;
1312 }
1313
1314 DBG(DBG_proc, "xsane_viewer_rotate(%d)\n", rotation);
1315
1316 xsane_viewer_set_sensitivity(v, FALSE);
1317
1318 infile = fopen(v->filename, "rb");
1319 if (!infile)
1320 {
1321 DBG(DBG_error, "could not load file %s\n", v->filename);
1322 xsane_viewer_set_sensitivity(v, TRUE);
1323
1324 return;
1325 }
1326
1327 xsane_read_pnm_header(infile, &image_info);
1328
1329 DBG(DBG_info, "rotating image %s with geometry: %d x %d x %d, %d channels\n", v->filename, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
1330
1331 xsane_back_gtk_make_path(sizeof(outfilename), outfilename, 0, 0, "xsane-viewer-", xsane.dev_name, ".ppm", XSANE_PATH_TMP);
1332
1333 outfile = fopen(outfilename, "wb");
1334 if (!outfile)
1335 {
1336 DBG(DBG_error, "could not save file %s\n", outfilename);
1337 xsane_viewer_set_sensitivity(v, TRUE);
1338
1339 return;
1340 }
1341
1342 if (rotation <4)
1343 {
1344 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), PROGRESS_ROTATING_DATA);
1345 }
1346 else
1347 {
1348 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), PROGRESS_MIRRORING_DATA);
1349 }
1350
1351 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1352
1353 xsane_save_rotate_image(outfile, infile, &image_info, rotation, v->progress_bar, &v->cancel_save);
1354
1355 fclose(infile);
1356 fclose(outfile);
1357
1358 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), "");
1359 xsane_progress_bar_set_fraction(GTK_PROGRESS_BAR(v->progress_bar), 0.0);
1360
1361 if (v->undo_filename)
1362 {
1363 DBG(DBG_info, "removing file %s\n", v->undo_filename);
1364 remove(v->undo_filename);
1365 free(v->undo_filename);
1366 }
1367
1368 v->undo_filename = v->filename;
1369 DBG(DBG_info, "undo file is %s\n", v->undo_filename);
1370 gtk_widget_set_sensitive(GTK_WIDGET(v->undo), TRUE);
1371 gtk_widget_set_sensitive(GTK_WIDGET(v->undo_menu_item), TRUE);
1372
1373 v->filename = strdup(outfilename);
1374 v->image_saved = FALSE;
1375
1376 xsane_viewer_read_image(v);
1377
1378 if (v->last_saved_filename)
1379 {
1380 char buf[TEXTBUFSIZE];
1381 snprintf(buf, sizeof(buf), "%s (%s) - %s", WINDOW_VIEWER, v->last_saved_filename, xsane.device_text);
1382 gtk_window_set_title(GTK_WINDOW(v->top), buf);
1383 }
1384
1385 xsane_viewer_set_sensitivity(v, TRUE);
1386 }
1387
1388 /* ---------------------------------------------------------------------------------------------------------------------- */
1389
xsane_viewer_rotate90_callback(GtkWidget * window,gpointer data)1390 static void xsane_viewer_rotate90_callback(GtkWidget *window, gpointer data)
1391 {
1392 Viewer *v = (Viewer *) data;
1393
1394 DBG(DBG_proc, "xsane_viewer_rotate90_callback\n");
1395 xsane_viewer_rotate(v, 1);
1396 }
1397
1398 /* ---------------------------------------------------------------------------------------------------------------------- */
1399
xsane_viewer_rotate180_callback(GtkWidget * window,gpointer data)1400 static void xsane_viewer_rotate180_callback(GtkWidget *window, gpointer data)
1401 {
1402 Viewer *v = (Viewer *) data;
1403
1404 DBG(DBG_proc, "xsane_viewer_rotate180_callback\n");
1405 xsane_viewer_rotate(v, 2);
1406 }
1407
1408 /* ---------------------------------------------------------------------------------------------------------------------- */
1409
xsane_viewer_rotate270_callback(GtkWidget * window,gpointer data)1410 static void xsane_viewer_rotate270_callback(GtkWidget *window, gpointer data)
1411 {
1412 Viewer *v = (Viewer *) data;
1413
1414 DBG(DBG_proc, "xsane_viewer_rotate270_callback\n");
1415 xsane_viewer_rotate(v, 3);
1416 }
1417
1418 /* ---------------------------------------------------------------------------------------------------------------------- */
1419
xsane_viewer_mirror_x_callback(GtkWidget * window,gpointer data)1420 static void xsane_viewer_mirror_x_callback(GtkWidget *window, gpointer data)
1421 {
1422 Viewer *v = (Viewer *) data;
1423
1424 DBG(DBG_proc, "xsane_viewer_mirror_x_callback\n");
1425 xsane_viewer_rotate(v, 4);
1426 }
1427
1428 /* ---------------------------------------------------------------------------------------------------------------------- */
1429
xsane_viewer_mirror_y_callback(GtkWidget * window,gpointer data)1430 static void xsane_viewer_mirror_y_callback(GtkWidget *window, gpointer data)
1431 {
1432 Viewer *v = (Viewer *) data;
1433
1434 DBG(DBG_proc, "xsane_viewer_mirror_y_callback\n");
1435 xsane_viewer_rotate(v, 6);
1436 }
1437
1438 /* ---------------------------------------------------------------------------------------------------------------------- */
1439
xsane_viewer_zoom_callback(GtkWidget * widget,gpointer data)1440 static void xsane_viewer_zoom_callback(GtkWidget *widget, gpointer data)
1441 {
1442 Viewer *v = (Viewer *) data;
1443 int val;
1444
1445 DBG(DBG_proc, "xsane_viewer_zoom_callback\n");
1446
1447 val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
1448 v->zoom = (float) val / 100;
1449 DBG(DBG_info, "setting zoom factor to %f\n", v->zoom);
1450 xsane_viewer_read_image(v);
1451 }
1452
1453 /* ---------------------------------------------------------------------------------------------------------------------- */
1454
xsane_viewer_file_build_menu(Viewer * v)1455 static GtkWidget *xsane_viewer_file_build_menu(Viewer *v)
1456 {
1457 GtkWidget *menu, *item;
1458
1459 DBG(DBG_proc, "xsane_viewer_file_build_menu\n");
1460
1461 menu = gtk_menu_new();
1462 gtk_menu_set_accel_group(GTK_MENU(menu), xsane.accelerator_group);
1463
1464 /* XSane save dialog */
1465
1466 item = gtk_menu_item_new_with_label(MENU_ITEM_SAVE_IMAGE);
1467 #if 0
1468 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1469 #endif
1470 gtk_menu_append(GTK_MENU(menu), item);
1471 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_save_callback, v);
1472 gtk_widget_show(item);
1473 v->save_menu_item = item;
1474
1475 /* XSane save as text (ocr) */
1476
1477 item = gtk_menu_item_new_with_label(MENU_ITEM_OCR);
1478 #if 0
1479 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1480 #endif
1481 gtk_menu_append(GTK_MENU(menu), item);
1482 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_ocr_callback, v);
1483 gtk_widget_show(item);
1484 v->ocr_menu_item = item;
1485
1486 /* Clone */
1487
1488 item = gtk_menu_item_new_with_label(MENU_ITEM_CLONE);
1489 #if 0
1490 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1491 #endif
1492 gtk_menu_append(GTK_MENU(menu), item);
1493 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_clone_callback, v);
1494 gtk_widget_show(item);
1495 v->clone_menu_item = item;
1496
1497
1498 /* Close */
1499
1500 item = gtk_menu_item_new_with_label(MENU_ITEM_CLOSE);
1501 #if 0
1502 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_Q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1503 #endif
1504 gtk_container_add(GTK_CONTAINER(menu), item);
1505 gtk_object_set_data(GTK_OBJECT(item), "Viewer", (void *) v);
1506 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_close_callback, v);
1507 gtk_widget_show(item);
1508
1509 return menu;
1510 }
1511
1512 /* ---------------------------------------------------------------------------------------------------------------------- */
1513
xsane_viewer_edit_build_menu(Viewer * v)1514 static GtkWidget *xsane_viewer_edit_build_menu(Viewer *v)
1515 {
1516 GtkWidget *menu, *item;
1517
1518 DBG(DBG_proc, "xsane_viewer_edit_build_menu\n");
1519
1520 menu = gtk_menu_new();
1521 gtk_menu_set_accel_group(GTK_MENU(menu), xsane.accelerator_group);
1522
1523 /* undo */
1524
1525 item = gtk_menu_item_new_with_label(MENU_ITEM_UNDO);
1526 #if 0
1527 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1528 #endif
1529 gtk_menu_append(GTK_MENU(menu), item);
1530 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_undo_callback, v);
1531 gtk_widget_show(item);
1532 v->undo_menu_item = item;
1533
1534 return menu;
1535 }
1536
1537 /* ---------------------------------------------------------------------------------------------------------------------- */
1538
xsane_viewer_filters_build_menu(Viewer * v)1539 static GtkWidget *xsane_viewer_filters_build_menu(Viewer *v)
1540 {
1541 GtkWidget *menu, *item;
1542
1543 DBG(DBG_proc, "xsane_viewer_filters_build_menu\n");
1544
1545 menu = gtk_menu_new();
1546 gtk_menu_set_accel_group(GTK_MENU(menu), xsane.accelerator_group);
1547
1548 /* Despeckle */
1549
1550 item = gtk_menu_item_new_with_label(MENU_ITEM_DESPECKLE);
1551 #if 0
1552 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1553 #endif
1554 gtk_menu_append(GTK_MENU(menu), item);
1555 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_despeckle_callback, v);
1556 gtk_widget_show(item);
1557 v->despeckle_menu_item = item;
1558
1559
1560 /* Blur */
1561
1562 item = gtk_menu_item_new_with_label(MENU_ITEM_BLUR);
1563 #if 0
1564 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_Q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1565 #endif
1566 gtk_container_add(GTK_CONTAINER(menu), item);
1567 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_blur_callback, v);
1568 gtk_widget_show(item);
1569 v->blur_menu_item = item;
1570
1571 return menu;
1572 }
1573
1574 /* ---------------------------------------------------------------------------------------------------------------------- */
1575
xsane_viewer_geometry_build_menu(Viewer * v)1576 static GtkWidget *xsane_viewer_geometry_build_menu(Viewer *v)
1577 {
1578 GtkWidget *menu, *item;
1579
1580 DBG(DBG_proc, "xsane_viewer_geometry_build_menu\n");
1581
1582 menu = gtk_menu_new();
1583 gtk_menu_set_accel_group(GTK_MENU(menu), xsane.accelerator_group);
1584
1585
1586 /* Scale */
1587
1588 item = gtk_menu_item_new_with_label(MENU_ITEM_SCALE);
1589 #if 0
1590 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1591 #endif
1592 gtk_menu_append(GTK_MENU(menu), item);
1593 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_scale_callback, v);
1594 gtk_widget_show(item);
1595
1596
1597 /* insert separator: */
1598
1599 item = gtk_menu_item_new();
1600 gtk_menu_append(GTK_MENU(menu), item);
1601 gtk_widget_show(item);
1602
1603
1604 /* rotate90 */
1605
1606 item = gtk_menu_item_new_with_label(MENU_ITEM_ROTATE90);
1607 #if 0
1608 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_1, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1609 #endif
1610 gtk_menu_append(GTK_MENU(menu), item);
1611 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_rotate90_callback, v);
1612 gtk_widget_show(item);
1613
1614
1615 /* rotate180 */
1616
1617 item = gtk_menu_item_new_with_label(MENU_ITEM_ROTATE180);
1618 #if 0
1619 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_2, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1620 #endif
1621 gtk_container_add(GTK_CONTAINER(menu), item);
1622 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_rotate180_callback, v);
1623 gtk_widget_show(item);
1624
1625
1626 /* rotate270 */
1627
1628 item = gtk_menu_item_new_with_label(MENU_ITEM_ROTATE270);
1629 #if 0
1630 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_3, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1631 #endif
1632 gtk_container_add(GTK_CONTAINER(menu), item);
1633 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_rotate270_callback, v);
1634 gtk_widget_show(item);
1635
1636
1637 /* insert separator: */
1638
1639 item = gtk_menu_item_new();
1640 gtk_menu_append(GTK_MENU(menu), item);
1641 gtk_widget_show(item);
1642
1643
1644 /* mirror_x */
1645
1646 item = gtk_menu_item_new_with_label(MENU_ITEM_MIRROR_X);
1647 #if 0
1648 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_X, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1649 #endif
1650 gtk_container_add(GTK_CONTAINER(menu), item);
1651 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_mirror_x_callback, v);
1652 gtk_widget_show(item);
1653
1654
1655 /* mirror_y */
1656
1657 item = gtk_menu_item_new_with_label(MENU_ITEM_MIRROR_Y);
1658 #if 0
1659 gtk_widget_add_accelerator(item, "activate", xsane.accelerator_group, GDK_Y, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED);
1660 #endif
1661 gtk_container_add(GTK_CONTAINER(menu), item);
1662 g_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc) xsane_viewer_mirror_y_callback, v);
1663 gtk_widget_show(item);
1664
1665
1666 return menu;
1667 }
1668
1669 /* ---------------------------------------------------------------------------------------------------------------------- */
1670
1671 #ifdef HAVE_LIBLCMS
1672 #define INTENT_PERCEPTUAL 0
1673 #define INTENT_RELATIVE_COLORIMETRIC 1
1674 #define INTENT_SATURATION 2
1675 #define INTENT_ABSOLUTE_COLORIMETRIC 3
1676
1677 /* ---------------------------------------------------------------------------------------------------------------------- */
1678
xsane_viewer_set_cms_enable_callback(GtkWidget * widget,gpointer data)1679 static void xsane_viewer_set_cms_enable_callback(GtkWidget *widget, gpointer data)
1680 {
1681 Viewer *v = (Viewer *) data;
1682
1683 v->cms_enable = (GTK_CHECK_MENU_ITEM(widget)->active != 0);
1684 DBG(DBG_proc, "xsane_viewer_set_cms_enable_callback (%d)\n", v->cms_enable);
1685
1686 xsane_viewer_read_image(v);
1687 }
1688
1689 /* ---------------------------------------------------------------------------------------------------------------------- */
1690
xsane_viewer_set_cms_black_point_compensation_callback(GtkWidget * widget,gpointer data)1691 static void xsane_viewer_set_cms_black_point_compensation_callback(GtkWidget *widget, gpointer data)
1692 {
1693 Viewer *v = (Viewer *) data;
1694
1695 v->cms_bpc = (GTK_CHECK_MENU_ITEM(widget)->active != 0);
1696 DBG(DBG_proc, "xsane_viewer_set_cms_black_point_compensation_callback (%d)\n", v->cms_bpc);
1697
1698 xsane_viewer_read_image(v);
1699 }
1700
1701 /* ---------------------------------------------------------------------------------------------------------------------- */
1702
xsane_viewer_set_cms_gamut_check_callback(GtkWidget * widget,gpointer data)1703 static void xsane_viewer_set_cms_gamut_check_callback(GtkWidget *widget, gpointer data)
1704 {
1705 Viewer *v = (Viewer *) data;
1706
1707 v->cms_gamut_check = (GTK_CHECK_MENU_ITEM(widget)->active != 0);
1708 DBG(DBG_proc, "xsane_viewer_set_cms_gamut_check_callback (%d)\n", v->cms_gamut_check);
1709
1710 xsane_viewer_read_image(v);
1711 }
1712
1713 /* ---------------------------------------------------------------------------------------------------------------------- */
1714
xsane_viewer_set_cms_proofing_callback(GtkWidget * widget,gpointer data)1715 static void xsane_viewer_set_cms_proofing_callback(GtkWidget *widget, gpointer data)
1716 {
1717 Viewer *v = (Viewer *) data;
1718 int val;
1719
1720 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1721 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1722 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1723
1724 val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
1725
1726 DBG(DBG_proc, "xsane_viewer_set_cms_proofing_callback (%d)\n", val);
1727
1728 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_widget[v->cms_proofing]), FALSE);
1729 v->cms_proofing = val;
1730 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_widget[v->cms_proofing]), TRUE);
1731
1732 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1733 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1734 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1735
1736 xsane_viewer_read_image(v);
1737 }
1738
1739 /* ---------------------------------------------------------------------------------------------------------------------- */
1740
xsane_viewer_set_cms_intent_callback(GtkWidget * widget,gpointer data)1741 static void xsane_viewer_set_cms_intent_callback(GtkWidget *widget, gpointer data)
1742 {
1743 Viewer *v = (Viewer *) data;
1744 int val;
1745
1746 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1747 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1748 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1749 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_intent_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1750
1751 val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
1752
1753 DBG(DBG_proc, "xsane_viewer_set_cms_intent_callback (%d)\n", val);
1754
1755 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_intent_widget[v->cms_intent]), FALSE);
1756 v->cms_intent = val;
1757 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_intent_widget[v->cms_intent]), TRUE);
1758
1759 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1760 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1761 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1762 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_intent_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1763
1764 xsane_viewer_read_image(v);
1765 }
1766
1767 /* ---------------------------------------------------------------------------------------------------------------------- */
1768
xsane_viewer_set_cms_proofing_intent_callback(GtkWidget * widget,gpointer data)1769 static void xsane_viewer_set_cms_proofing_intent_callback(GtkWidget *widget, gpointer data)
1770 {
1771 Viewer *v = (Viewer *) data;
1772 int val;
1773
1774 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
1775 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
1776
1777 val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
1778
1779 DBG(DBG_proc, "xsane_viewer_set_cms_proofing_intent_callback (%d)\n", val);
1780
1781 /* we have cms_proofing_intent = 1 and 3 and widget[0] and widget[1] => widget[(cms_proofing_intent-1)/2] */
1782 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_intent_widget[(v->cms_proofing_intent-1)/2]), FALSE);
1783 v->cms_proofing_intent = val;
1784 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_proofing_intent_widget[(v->cms_proofing_intent-1)/2]), TRUE);
1785
1786 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
1787 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_proofing_intent_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
1788
1789 xsane_viewer_read_image(v);
1790 }
1791
1792 /* ---------------------------------------------------------------------------------------------------------------------- */
1793
xsane_viewer_set_cms_gamut_alarm_color_callback(GtkWidget * widget,gpointer data)1794 static void xsane_viewer_set_cms_gamut_alarm_color_callback(GtkWidget *widget, gpointer data)
1795 {
1796 Viewer *v = (Viewer *) data;
1797 int val;
1798
1799 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1800 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1801 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1802 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1803 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[4]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1804 g_signal_handlers_block_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[5]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1805
1806 val = (int) gtk_object_get_data(GTK_OBJECT(widget), "Selection");
1807
1808 DBG(DBG_proc, "xsane_viewer_set_cms_gamut_alarm_color_callback (%d)\n", val);
1809
1810 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_gamut_alarm_color_widget[v->cms_gamut_alarm_color]), FALSE);
1811 v->cms_gamut_alarm_color = val;
1812 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(v->cms_gamut_alarm_color_widget[v->cms_gamut_alarm_color]), TRUE);
1813
1814 switch(v->cms_gamut_alarm_color)
1815 {
1816 default:
1817 case 0: /* black */
1818 cmsSetAlarmCodes(0, 0, 0);
1819 break;
1820
1821 case 1: /* gray */
1822 cmsSetAlarmCodes(128, 128, 128);
1823 break;
1824
1825 case 2: /* white */
1826 cmsSetAlarmCodes(255, 255, 255);
1827 break;
1828
1829 case 3: /* red */
1830 cmsSetAlarmCodes(255, 0, 0);
1831 break;
1832
1833 case 4: /* green */
1834 cmsSetAlarmCodes(0, 255, 0);
1835 break;
1836
1837 case 5: /* blue */
1838 cmsSetAlarmCodes(0, 0, 255);
1839 break;
1840 }
1841
1842 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[0]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1843 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[1]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1844 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[2]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1845 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[3]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1846 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[4]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1847 g_signal_handlers_unblock_by_func(GTK_OBJECT(v->cms_gamut_alarm_color_widget[5]), (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
1848
1849 if (v->cms_gamut_check)
1850 {
1851 xsane_viewer_read_image(v);
1852 }
1853 }
1854
1855 /* ---------------------------------------------------------------------------------------------------------------------- */
1856
xsane_viewer_color_management_build_menu(Viewer * v)1857 static GtkWidget *xsane_viewer_color_management_build_menu(Viewer *v)
1858 {
1859 GtkWidget *menu, *item, *submenu, *subitem;
1860
1861 DBG(DBG_proc, "xsane_viewer_color_management_build_menu\n");
1862
1863 menu = gtk_menu_new();
1864 gtk_menu_set_accel_group(GTK_MENU(menu), xsane.accelerator_group);
1865
1866 /* cms enable */
1867 item = gtk_check_menu_item_new_with_label(MENU_ITEM_CMS_ENABLE_COLOR_MANAGEMENT);
1868 gtk_menu_append(GTK_MENU(menu), item);
1869 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), v->cms_enable);
1870 g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_enable_callback, v);
1871 gtk_widget_show(item);
1872
1873 /* black point compensation */
1874 item = gtk_check_menu_item_new_with_label(MENU_ITEM_CMS_BLACK_POINT_COMPENSATION);
1875 gtk_menu_append(GTK_MENU(menu), item);
1876 if (v->cms_bpc)
1877 {
1878 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
1879 }
1880 g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_black_point_compensation_callback, v);
1881 gtk_widget_show(item);
1882
1883
1884 /* Output Device submenu */
1885 item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_PROOFING);
1886 gtk_menu_append(GTK_MENU(menu), item);
1887 gtk_widget_show(item);
1888
1889 submenu = gtk_menu_new();
1890
1891 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_PROOF_OFF);
1892 gtk_menu_append(GTK_MENU(submenu), subitem);
1893 if (v->cms_proofing == 0)
1894 {
1895 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1896 }
1897 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1898 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 0);
1899 gtk_widget_show(subitem);
1900 v->cms_proofing_widget[0] = subitem;
1901
1902 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_PROOF_PRINTER);
1903 gtk_menu_append(GTK_MENU(submenu), subitem);
1904 if (v->cms_proofing == 1)
1905 {
1906 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1907 }
1908 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1909 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 1);
1910 gtk_widget_show(subitem);
1911 v->cms_proofing_widget[1] = subitem;
1912
1913 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_PROOF_CUSTOM);
1914 gtk_menu_append(GTK_MENU(submenu), subitem);
1915 if (v->cms_proofing == 2)
1916 {
1917 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1918 }
1919 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_callback, v);
1920 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 2);
1921 gtk_widget_show(subitem);
1922 v->cms_proofing_widget[2] = subitem;
1923
1924 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1925
1926
1927 /* Intent submenu */
1928 item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_RENDERING_INTENT);
1929 gtk_menu_append(GTK_MENU(menu), item);
1930 gtk_widget_show(item);
1931
1932 submenu = gtk_menu_new();
1933
1934 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_PERCEPTUAL);
1935 gtk_menu_append(GTK_MENU(submenu), subitem);
1936 if (v->cms_intent == INTENT_PERCEPTUAL)
1937 {
1938 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1939 }
1940 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1941 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_PERCEPTUAL);
1942 gtk_widget_show(subitem);
1943 v->cms_intent_widget[INTENT_PERCEPTUAL] = subitem;
1944
1945 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_RELATIVE_COLORIMETRIC);
1946 gtk_menu_append(GTK_MENU(submenu), subitem);
1947 if (v->cms_intent == INTENT_RELATIVE_COLORIMETRIC)
1948 {
1949 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1950 }
1951 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1952 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_RELATIVE_COLORIMETRIC);
1953 gtk_widget_show(subitem);
1954 v->cms_intent_widget[INTENT_RELATIVE_COLORIMETRIC] = subitem;
1955
1956 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_ABSOLUTE_COLORIMETRIC);
1957 gtk_menu_append(GTK_MENU(submenu), subitem);
1958 if (v->cms_intent == INTENT_ABSOLUTE_COLORIMETRIC)
1959 {
1960 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1961 }
1962 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1963 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_ABSOLUTE_COLORIMETRIC);
1964 gtk_widget_show(subitem);
1965 v->cms_intent_widget[INTENT_ABSOLUTE_COLORIMETRIC] = subitem;
1966
1967 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_SATURATION);
1968 gtk_menu_append(GTK_MENU(submenu), subitem);
1969 if (v->cms_intent == INTENT_SATURATION)
1970 {
1971 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1972 }
1973 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_intent_callback, v);
1974 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_SATURATION);
1975 gtk_widget_show(subitem);
1976 v->cms_intent_widget[INTENT_SATURATION] = subitem;
1977
1978 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1979
1980
1981 /* proofing_intent submenu */
1982 item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_PROOFING_INTENT);
1983 gtk_menu_append(GTK_MENU(menu), item);
1984 gtk_widget_show(item);
1985
1986 submenu = gtk_menu_new();
1987
1988 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_RELATIVE_COLORIMETRIC);
1989 gtk_menu_append(GTK_MENU(submenu), subitem);
1990 if (v->cms_proofing_intent == INTENT_RELATIVE_COLORIMETRIC)
1991 {
1992 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
1993 }
1994 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
1995 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_RELATIVE_COLORIMETRIC);
1996 gtk_widget_show(subitem);
1997 v->cms_proofing_intent_widget[0] = subitem;
1998
1999 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_INTENT_ABSOLUTE_COLORIMETRIC);
2000 gtk_menu_append(GTK_MENU(submenu), subitem);
2001 if (v->cms_proofing_intent == INTENT_ABSOLUTE_COLORIMETRIC)
2002 {
2003 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2004 }
2005 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_proofing_intent_callback, v);
2006 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) INTENT_ABSOLUTE_COLORIMETRIC);
2007 gtk_widget_show(subitem);
2008 v->cms_proofing_intent_widget[1] = subitem;
2009
2010 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
2011
2012
2013 /* cms gamut check */
2014 item = gtk_check_menu_item_new_with_label(MENU_ITEM_CMS_GAMUT_CHECK);
2015 gtk_menu_append(GTK_MENU(menu), item);
2016 g_signal_connect(GTK_OBJECT(item), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_check_callback, v);
2017 gtk_widget_show(item);
2018
2019
2020 /* gamut alarm color */
2021 item = gtk_menu_item_new_with_label(MENU_ITEM_CMS_GAMUT_ALARM_COLOR);
2022 gtk_menu_append(GTK_MENU(menu), item);
2023 gtk_widget_show(item);
2024
2025 submenu = gtk_menu_new();
2026
2027 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_BLACK);
2028 gtk_menu_append(GTK_MENU(submenu), subitem);
2029 if (v->cms_gamut_alarm_color == 0)
2030 {
2031 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2032 }
2033 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
2034 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 0);
2035 gtk_widget_show(subitem);
2036 v->cms_gamut_alarm_color_widget[0] = subitem;
2037
2038 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_GRAY);
2039 gtk_menu_append(GTK_MENU(submenu), subitem);
2040 if (v->cms_gamut_alarm_color == 1)
2041 {
2042 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2043 }
2044 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
2045 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 1);
2046 gtk_widget_show(subitem);
2047 v->cms_gamut_alarm_color_widget[1] = subitem;
2048
2049 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_WHITE);
2050 gtk_menu_append(GTK_MENU(submenu), subitem);
2051 if (v->cms_gamut_alarm_color == 2)
2052 {
2053 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2054 }
2055 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
2056 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 2);
2057 gtk_widget_show(subitem);
2058 v->cms_gamut_alarm_color_widget[2] = subitem;
2059
2060 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_RED);
2061 gtk_menu_append(GTK_MENU(submenu), subitem);
2062 if (v->cms_gamut_alarm_color == 3)
2063 {
2064 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2065 }
2066 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
2067 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 3);
2068 gtk_widget_show(subitem);
2069 v->cms_gamut_alarm_color_widget[3] = subitem;
2070
2071 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_GREEN);
2072 gtk_menu_append(GTK_MENU(submenu), subitem);
2073 if (v->cms_gamut_alarm_color == 4)
2074 {
2075 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2076 }
2077 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
2078 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 4);
2079 gtk_widget_show(subitem);
2080 v->cms_gamut_alarm_color_widget[4] = subitem;
2081
2082 subitem = gtk_check_menu_item_new_with_label(SUBMENU_ITEM_CMS_COLOR_BLUE);
2083 gtk_menu_append(GTK_MENU(submenu), subitem);
2084 if (v->cms_gamut_alarm_color == 5)
2085 {
2086 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(subitem), TRUE);
2087 }
2088 g_signal_connect(GTK_OBJECT(subitem), "toggled", (GtkSignalFunc) xsane_viewer_set_cms_gamut_alarm_color_callback, v);
2089 gtk_object_set_data(GTK_OBJECT(subitem), "Selection", (void *) 5);
2090 gtk_widget_show(subitem);
2091 v->cms_gamut_alarm_color_widget[5] = subitem;
2092
2093 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
2094
2095 return menu;
2096 }
2097 #endif
2098
2099 /* ---------------------------------------------------------------------------------------------------------------------- */
2100
2101
xsane_viewer_read_image_header(Viewer * v)2102 static int xsane_viewer_read_image_header(Viewer *v)
2103 {
2104 int pos0;
2105 FILE *infile;
2106 Image_info image_info;
2107
2108 /* open imagefile */
2109
2110 infile = fopen(v->filename, "rb");
2111 if (!infile)
2112 {
2113 DBG(DBG_error, "could not load file %s\n", v->filename);
2114 return -1;
2115 }
2116
2117 xsane_read_pnm_header(infile, &image_info);
2118
2119 pos0 = ftell(infile);
2120
2121 if (!image_info.channels) /* == 0 (grayscale) ? */
2122 {
2123 image_info.channels = 1; /* we have one color component */
2124 }
2125
2126 DBG(DBG_info, "reading image header %s with geometry: %d x %d x %d, %d channels\n", v->filename,
2127 image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
2128
2129 /* init color management */
2130 v->enable_color_management = image_info.enable_color_management;
2131 if (!image_info.enable_color_management)
2132 {
2133 v->cms_enable = FALSE;
2134 }
2135
2136 v->cms_function = image_info.cms_function;
2137 v->cms_intent = image_info.cms_intent;
2138 v->cms_bpc = image_info.cms_bpc;
2139
2140 if ((v->enable_color_management) && (image_info.reduce_to_lineart))
2141 {
2142 v->enable_color_management = FALSE;
2143 v->cms_enable = FALSE;
2144 }
2145
2146 fclose(infile);
2147
2148 return 0;
2149 }
2150
2151 /* ---------------------------------------------------------------------------------------------------------------------- */
2152
2153
xsane_viewer_read_image(Viewer * v)2154 static int xsane_viewer_read_image(Viewer *v)
2155 {
2156 unsigned char *cms_row, *row, *src_row;
2157 int x, y;
2158 int last_y;
2159 int nread;
2160 int pos0;
2161 FILE *infile;
2162 Image_info image_info;
2163 char buf[TEXTBUFSIZE];
2164 float size;
2165 char *size_unit;
2166 int width, height;
2167
2168 #ifdef HAVE_LIBLCMS
2169 cmsHPROFILE hInProfile = NULL;
2170 cmsHPROFILE hOutProfile = NULL;
2171 cmsHPROFILE hProofProfile = NULL;
2172 cmsHTRANSFORM hTransform = NULL;
2173 int proof = 0;
2174 char *cms_proof_icm_profile = NULL;
2175 DWORD cms_input_format;
2176 DWORD cms_output_format;
2177 DWORD cms_flags = 0;
2178 #endif
2179
2180 /* open imagefile */
2181
2182 infile = fopen(v->filename, "rb");
2183 if (!infile)
2184 {
2185 DBG(DBG_error, "could not load file %s\n", v->filename);
2186 return -1;
2187 }
2188
2189 xsane_read_pnm_header(infile, &image_info);
2190
2191 pos0 = ftell(infile);
2192
2193 if (!image_info.channels) /* == 0 (grayscale) ? */
2194 {
2195 image_info.channels = 1; /* we have one color component */
2196 }
2197
2198 DBG(DBG_info, "reading image %s with geometry: %d x %d x %d, %d channels\n", v->filename,
2199 image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
2200
2201 #ifdef HAVE_LIBLCMS
2202 /* init color management */
2203
2204 if ((v->enable_color_management) && (v->cms_enable))
2205 {
2206 cmsErrorAction(LCMS_ERROR_SHOW);
2207
2208 if (v->cms_bpc)
2209 {
2210 cms_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
2211 }
2212
2213 if (image_info.channels == 1) /* == 1 (grayscale) */
2214 {
2215 if (image_info.depth == 8)
2216 {
2217 cms_input_format = TYPE_GRAY_8;
2218 cms_output_format = TYPE_GRAY_8;
2219 }
2220 else
2221 {
2222 cms_input_format = TYPE_GRAY_16;
2223 cms_output_format = TYPE_GRAY_8;
2224 }
2225 }
2226 else /* color */
2227 {
2228 if (image_info.depth == 8)
2229 {
2230 cms_input_format = TYPE_RGB_8;
2231 cms_output_format = TYPE_RGB_8;
2232 }
2233 else
2234 {
2235 cms_input_format = TYPE_RGB_16;
2236 cms_output_format = TYPE_RGB_8;
2237 }
2238 }
2239
2240 switch (v->cms_proofing)
2241 {
2242 default:
2243 case 0: /* display */
2244 proof = 0;
2245 break;
2246
2247 case 1: /* proof printer */
2248 cms_proof_icm_profile = preferences.printer[preferences.printernr]->icm_profile;
2249 proof = 1;
2250 break;
2251
2252 case 2: /* proof custom proofing */
2253 cms_proof_icm_profile = preferences.custom_proofing_icm_profile;
2254 proof = 1;
2255 break;
2256 }
2257
2258 hInProfile = cmsOpenProfileFromFile(image_info.icm_profile, "r");
2259 if (!hInProfile)
2260 {
2261 char buf[TEXTBUFSIZE];
2262
2263 snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_SCANNER_ICM, image_info.icm_profile);
2264 xsane_back_gtk_error(buf, TRUE);
2265 return -1;
2266 }
2267
2268 hOutProfile = cmsOpenProfileFromFile(preferences.display_icm_profile, "r");
2269 if (!hOutProfile)
2270 {
2271 char buf[TEXTBUFSIZE];
2272
2273 cmsCloseProfile(hInProfile);
2274
2275 snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_DISPLAY_ICM, preferences.display_icm_profile);
2276 xsane_back_gtk_error(buf, TRUE);
2277 return -1;
2278 }
2279
2280
2281 if (proof == 0)
2282 {
2283 hTransform = cmsCreateTransform(hInProfile, cms_input_format,
2284 hOutProfile, cms_output_format,
2285 v->cms_intent, cms_flags);
2286 }
2287 else /* proof */
2288 {
2289 cms_flags |= cmsFLAGS_SOFTPROOFING;
2290
2291 if (v->cms_gamut_check)
2292 {
2293 cms_flags |= cmsFLAGS_GAMUTCHECK;
2294 }
2295
2296 hProofProfile = cmsOpenProfileFromFile(cms_proof_icm_profile, "r");
2297 if (!hProofProfile)
2298 {
2299 char buf[TEXTBUFSIZE];
2300
2301 cmsCloseProfile(hInProfile);
2302 cmsCloseProfile(hOutProfile);
2303
2304 snprintf(buf, sizeof(buf), "%s\n%s %s: %s\n", ERR_CMS_CONVERSION, ERR_CMS_OPEN_ICM_FILE, CMS_PROOF_ICM, cms_proof_icm_profile);
2305 xsane_back_gtk_error(buf, TRUE);
2306 return -1;
2307 }
2308
2309 hTransform = cmsCreateProofingTransform(hInProfile, cms_input_format,
2310 hOutProfile, cms_output_format,
2311 hProofProfile,
2312 v->cms_intent, v->cms_proofing_intent, cms_flags);
2313 }
2314
2315 cmsCloseProfile(hInProfile);
2316 cmsCloseProfile(hOutProfile);
2317 if (proof)
2318 {
2319 cmsCloseProfile(hProofProfile);
2320 }
2321
2322 if (!hTransform)
2323 {
2324 char buf[TEXTBUFSIZE];
2325
2326 snprintf(buf, sizeof(buf), "%s\n%s\n", ERR_CMS_CONVERSION, ERR_CMS_CREATE_TRANSFORM);
2327 xsane_back_gtk_error(buf, TRUE);
2328 return -1;
2329 }
2330 }
2331 #endif
2332
2333 /* open infile */
2334
2335 if (v->window) /* we already have an existing viewer preview window? */
2336 {
2337 gtk_widget_destroy(v->window);
2338 }
2339
2340 /* the preview area */
2341 if (image_info.channels == 3) /* RGB */
2342 {
2343 v->window = gtk_preview_new(GTK_PREVIEW_COLOR);
2344 }
2345 else /* grayscale */
2346 {
2347 v->window = gtk_preview_new(GTK_PREVIEW_GRAYSCALE);
2348 }
2349
2350 gtk_preview_size(GTK_PREVIEW(v->window), image_info.image_width * v->zoom, image_info.image_height * v->zoom);
2351 gtk_container_add(GTK_CONTAINER(v->viewport), v->window);
2352 gtk_widget_show(v->window);
2353
2354
2355
2356 /* get memory for one row of the image */
2357 src_row = malloc(image_info.image_width * image_info.channels * image_info.depth / 8);
2358
2359 if ((v->enable_color_management) && (v->cms_enable))
2360 {
2361 row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels * image_info.depth / 8);
2362 }
2363 else
2364 {
2365 row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels);
2366 }
2367
2368 #ifdef HAVE_LIBLCMS
2369 if ((v->enable_color_management) && (v->cms_enable))
2370 {
2371 cms_row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels);
2372 }
2373 else
2374 #endif
2375 {
2376 cms_row = row;
2377 }
2378
2379 if (!row || !src_row || !cms_row)
2380 {
2381 if (src_row)
2382 {
2383 free(src_row);
2384 }
2385
2386 if (row)
2387 {
2388 free(row);
2389 }
2390
2391 #ifdef HAVE_LIBLCMS
2392 if ((cms_row) && (v->enable_color_management) && (v->cms_enable))
2393 {
2394 free(cms_row);
2395 }
2396 #endif
2397
2398 fclose(infile);
2399 DBG(DBG_error, "could not allocate memory\n");
2400 return -1;
2401 }
2402
2403
2404 last_y = -99999;
2405
2406 /* read the image from file */
2407 for (y = 0; y < (int) (image_info.image_height * v->zoom); y++)
2408 {
2409 if ((int) (last_y / v->zoom) != (int) (y / v->zoom))
2410 {
2411 last_y = y;
2412
2413 if (image_info.depth == 8) /* 8 bits/pixel */
2414 {
2415 fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels, SEEK_SET);
2416 nread = fread(src_row, image_info.channels, image_info.image_width, infile);
2417
2418 if (image_info.channels > 1)
2419 {
2420 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2421 {
2422 int xoff = ((int) (x / v->zoom)) * image_info.channels;
2423
2424 row[3*x+0] = src_row[xoff + 0];
2425 row[3*x+1] = src_row[xoff + 1];
2426 row[3*x+2] = src_row[xoff + 2];
2427 }
2428 }
2429 else
2430 {
2431 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2432 {
2433 row[x] = src_row[((int) (x / v->zoom))];
2434 }
2435 }
2436 }
2437 else if ((!v->enable_color_management) || (!v->cms_enable)) /* 16 bits/pixel => reduce to 8 bits/pixel */
2438 {
2439 guint16 *src_row16 = (guint16 *) src_row;
2440
2441 fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels * 2, SEEK_SET);
2442 nread = fread(src_row, 2 * image_info.channels, image_info.image_width, infile);
2443
2444 if (image_info.channels > 1)
2445 {
2446 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2447 {
2448 int xoff = ((int) (x / v->zoom)) * image_info.channels;
2449
2450 row[3*x+0] = (unsigned char) (src_row16[xoff + 0] / 256);
2451 row[3*x+1] = (unsigned char) (src_row16[xoff + 1] / 256);
2452 row[3*x+2] = (unsigned char) (src_row16[xoff + 2] / 256);
2453 }
2454 }
2455 else
2456 {
2457 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2458 {
2459 row[x] = (unsigned char) (src_row16[(int) (x / v->zoom)] / 256);
2460 }
2461 }
2462 }
2463 else /* 16 bits/pixel with color management enabled, cms does 16->8 conversion */
2464 {
2465 guint16 *src_row16 = (guint16 *) src_row;
2466 guint16 *dst_row16 = (guint16 *) row;
2467
2468 fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels * 2, SEEK_SET);
2469 nread = fread(src_row, 2 * image_info.channels, image_info.image_width, infile);
2470
2471 if (image_info.channels > 1)
2472 {
2473 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2474 {
2475 int xoff = ((int) (x / v->zoom)) * image_info.channels;
2476
2477 dst_row16[3*x+0] = src_row16[xoff + 0];
2478 dst_row16[3*x+1] = src_row16[xoff + 1];
2479 dst_row16[3*x+2] = src_row16[xoff + 2];
2480 }
2481 }
2482 else
2483 {
2484 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2485 {
2486 dst_row16[x] = src_row16[(int) (x / v->zoom)];
2487 }
2488 }
2489 }
2490 }
2491
2492 #ifdef HAVE_LIBLCMS
2493 if ((v->enable_color_management) && (v->cms_enable))
2494 {
2495 cmsDoTransform(hTransform, row, cms_row, image_info.image_width * v->zoom);
2496 }
2497 #endif
2498 gtk_preview_draw_row(GTK_PREVIEW(v->window), cms_row, 0, y, image_info.image_width * v->zoom);
2499 }
2500
2501 gtk_preview_put(GTK_PREVIEW(v->window), v->window->window, v->window->style->black_gc, 0, 0, 0, 0,
2502 image_info.image_width * v->zoom, image_info.image_height * v->zoom);
2503
2504 size = (float) image_info.image_width * image_info.image_height * image_info.channels;
2505 if (image_info.depth == 16)
2506 {
2507 size *= 2.0;
2508 }
2509
2510 if (image_info.reduce_to_lineart)
2511 {
2512 size /= 8.0;
2513 }
2514
2515 size_unit = "B";
2516
2517 if (size >= 1024 * 1024)
2518 {
2519 size /= (1024.0 * 1024.0);
2520 size_unit = "MB";
2521 }
2522 else if (size >= 1024)
2523 {
2524 size /= 1024.0;
2525 size_unit = "KB";
2526 }
2527
2528 if (image_info.reduce_to_lineart)
2529 {
2530 snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, 1, image_info.channels,
2531 image_info.resolution_x, image_info.resolution_y, size, size_unit);
2532 }
2533 else
2534 {
2535 snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels,
2536 image_info.resolution_x, image_info.resolution_y, size, size_unit);
2537 }
2538 gtk_label_set(GTK_LABEL(v->image_info_label), buf);
2539
2540 width = image_info.image_width * v->zoom + 26;
2541 height = image_info.image_height * v->zoom + 136;
2542
2543 if (width >= gdk_screen_width())
2544 {
2545 width = gdk_screen_width()-1;
2546 }
2547
2548 if (height >= gdk_screen_height())
2549 {
2550 height = gdk_screen_height()-1;
2551 }
2552
2553 #ifdef HAVE_GTK2
2554 if (GTK_WIDGET_REALIZED(v->top))
2555 {
2556 gtk_window_resize(GTK_WINDOW(v->top), width, height);
2557 }
2558 else
2559 #endif
2560 {
2561 gtk_window_set_default_size(GTK_WINDOW(v->top), width, height);
2562 }
2563
2564 free(row);
2565 free(src_row);
2566 fclose(infile);
2567
2568 #ifdef HAVE_LIBLCMS
2569 if ((v->enable_color_management) && (v->cms_enable))
2570 {
2571 cmsDeleteTransform(hTransform);
2572 }
2573 #endif
2574
2575 return 0;
2576 }
2577
2578 #if 0 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2579
2580 static int xsane_viewer_read_image(Viewer *v)
2581 {
2582 unsigned char *row, *src_row;
2583 int x, y;
2584 int last_y;
2585 int nread;
2586 int pos0;
2587 FILE *infile;
2588 Image_info image_info;
2589 char buf[TEXTBUFSIZE];
2590 float size;
2591 char *size_unit;
2592 int width, height;
2593
2594 infile = fopen(v->filename, "rb");
2595 if (!infile)
2596 {
2597 DBG(DBG_error, "could not load file %s\n", v->filename);
2598 return -1;
2599 }
2600
2601 xsane_read_pnm_header(infile, &image_info);
2602
2603 pos0 = ftell(infile);
2604
2605 if (!image_info.channels) /* == 0 (grayscale) ? */
2606 {
2607 image_info.channels = 1; /* we have one color component */
2608 }
2609
2610 DBG(DBG_info, "reading image %s with geometry: %d x %d x %d, %d channels\n", v->filename,
2611 image_info.image_width, image_info.image_height, image_info.depth, image_info.channels);
2612 /* open infile */
2613
2614 if (v->window) /* we already have an existing viewer preview window? */
2615 {
2616 gtk_widget_destroy(v->window);
2617 }
2618
2619 /* the preview area */
2620 if (image_info.channels == 3) /* RGB */
2621 {
2622 v->window = gtk_preview_new(GTK_PREVIEW_COLOR);
2623 }
2624 else /* grayscale */
2625 {
2626 v->window = gtk_preview_new(GTK_PREVIEW_GRAYSCALE);
2627 }
2628
2629 gtk_preview_size(GTK_PREVIEW(v->window), image_info.image_width * v->zoom, image_info.image_height * v->zoom);
2630 gtk_container_add(GTK_CONTAINER(v->viewport), v->window);
2631 gtk_widget_show(v->window);
2632
2633
2634
2635 /* get memory for one row of the image */
2636 src_row = malloc(image_info.image_width * image_info.channels * image_info.depth / 8);
2637 row = malloc(((int) image_info.image_width * v->zoom) * image_info.channels);
2638
2639 if (!row || !src_row)
2640 {
2641 if (src_row)
2642 {
2643 free(src_row);
2644 }
2645
2646 if (row)
2647 {
2648 free(row);
2649 }
2650
2651 fclose(infile);
2652 DBG(DBG_error, "could not allocate memory\n");
2653 return -1;
2654 }
2655
2656
2657 last_y = -99999;
2658
2659 /* read the image from file */
2660 for (y = 0; y < (int) (image_info.image_height * v->zoom); y++)
2661 {
2662 if ((int) (last_y / v->zoom) != (int) (y / v->zoom))
2663 {
2664 last_y = y;
2665
2666 if (image_info.depth == 8) /* 8 bits/pixel */
2667 {
2668 fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels, SEEK_SET);
2669 nread = fread(src_row, image_info.channels, image_info.image_width, infile);
2670
2671 if (image_info.channels > 1)
2672 {
2673 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2674 {
2675 int xoff = ((int) (x / v->zoom)) * image_info.channels;
2676
2677 row[3*x+0] = src_row[xoff + 0];
2678 row[3*x+1] = src_row[xoff + 1];
2679 row[3*x+2] = src_row[xoff + 2];
2680 }
2681 }
2682 else
2683 {
2684 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2685 {
2686 row[x] = src_row[((int) (x / v->zoom))];
2687 }
2688 }
2689 }
2690 else /* 16 bits/pixel => reduce to 8 bits/pixel */
2691 {
2692 guint16 *src_row16 = (guint16 *) src_row;
2693
2694 fseek(infile, pos0 + (((int) (y / v->zoom)) * image_info.image_width) * image_info.channels * 2, SEEK_SET);
2695 nread = fread(src_row, 2 * image_info.channels, image_info.image_width, infile);
2696
2697 if (image_info.channels > 1)
2698 {
2699 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2700 {
2701 int xoff = ((int) (x / v->zoom)) * image_info.channels;
2702
2703 row[3*x+0] = (unsigned char) (src_row16[xoff + 0] / 256);
2704 row[3*x+1] = (unsigned char) (src_row16[xoff + 1] / 256);
2705 row[3*x+2] = (unsigned char) (src_row16[xoff + 2] / 256);
2706 }
2707 }
2708 else
2709 {
2710 for (x=0; x < (int) (image_info.image_width * v->zoom); x++)
2711 {
2712 row[x] = (unsigned char) (src_row16[(int) (x / v->zoom)] / 256);
2713 }
2714 }
2715 }
2716 }
2717
2718 gtk_preview_draw_row(GTK_PREVIEW(v->window), row, 0, y, image_info.image_width * v->zoom);
2719 }
2720
2721 gtk_preview_put(GTK_PREVIEW(v->window), v->window->window, v->window->style->black_gc, 0, 0, 0, 0,
2722 image_info.image_width * v->zoom, image_info.image_height * v->zoom);
2723
2724 size = (float) image_info.image_width * image_info.image_height * image_info.channels;
2725 if (image_info.depth == 16)
2726 {
2727 size *= 2.0;
2728 }
2729
2730 if (image_info.reduce_to_lineart)
2731 {
2732 size /= 8.0;
2733 }
2734
2735 size_unit = "B";
2736
2737 if (size >= 1024 * 1024)
2738 {
2739 size /= (1024.0 * 1024.0);
2740 size_unit = "MB";
2741 }
2742 else if (size >= 1024)
2743 {
2744 size /= 1024.0;
2745 size_unit = "KB";
2746 }
2747
2748 if (image_info.reduce_to_lineart)
2749 {
2750 snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, 1, image_info.channels,
2751 image_info.resolution_x, image_info.resolution_y, size, size_unit);
2752 }
2753 else
2754 {
2755 snprintf(buf, sizeof(buf), TEXT_VIEWER_IMAGE_INFO, image_info.image_width, image_info.image_height, image_info.depth, image_info.channels,
2756 image_info.resolution_x, image_info.resolution_y, size, size_unit);
2757 }
2758 gtk_label_set(GTK_LABEL(v->image_info_label), buf);
2759
2760 width = image_info.image_width * v->zoom + 26;
2761 height = image_info.image_height * v->zoom + 136;
2762
2763 if (width >= gdk_screen_width())
2764 {
2765 width = gdk_screen_width()-1;
2766 }
2767
2768 if (height >= gdk_screen_height())
2769 {
2770 height = gdk_screen_height()-1;
2771 }
2772
2773 #ifdef HAVE_GTK2
2774 if (GTK_WIDGET_REALIZED(v->top))
2775 {
2776 gtk_window_resize(GTK_WINDOW(v->top), width, height);
2777 }
2778 else
2779 #endif
2780 {
2781 gtk_window_set_default_size(GTK_WINDOW(v->top), width, height);
2782 }
2783
2784 free(row);
2785 free(src_row);
2786 fclose(infile);
2787
2788 return 0;
2789 }
2790 #endif
2791
2792 /* ---------------------------------------------------------------------------------------------------------------------- */
2793
xsane_viewer_new(char * filename,char * selection_filetype,int allow_reduction_to_lineart,char * output_filename,viewer_modification allow_modification,int image_saved)2794 Viewer *xsane_viewer_new(char *filename, char *selection_filetype, int allow_reduction_to_lineart,
2795 char *output_filename, viewer_modification allow_modification, int image_saved)
2796 {
2797 char buf[TEXTBUFSIZE];
2798 Viewer *v;
2799 GtkWidget *vbox, *hbox;
2800 GtkWidget *menubar, *menubar_item;
2801 GtkWidget *scrolled_window;
2802 GtkWidget *zoom_option_menu, *zoom_menu, *zoom_menu_item;
2803 int i, selection;
2804
2805 DBG(DBG_proc, "viewer_new(%s)\n", filename);
2806
2807 /* create viewer structure v */
2808 v = malloc(sizeof(*v));
2809 if (!v)
2810 {
2811 DBG(DBG_error, "could not allocate memory\n");
2812 return 0;
2813 }
2814 memset(v, 0, sizeof(*v));
2815
2816 v->filename = strdup(filename);
2817 v->undo_filename = NULL;
2818 v->allow_reduction_to_lineart = allow_reduction_to_lineart;
2819 v->zoom = 1.0;
2820 v->image_saved = image_saved;
2821 v->keep_viewer_pnm_format = FALSE;
2822 v->allow_modification = allow_modification;
2823 v->next_viewer = xsane.viewer_list;
2824 #ifdef HAVE_LIBLCMS
2825 v->enable_color_management = FALSE;
2826 v->cms_enable = TRUE;
2827 v->cms_function = XSANE_CMS_FUNCTION_EMBED_SCANNER_ICM_PROFILE;
2828 v->cms_intent = INTENT_PERCEPTUAL;
2829 v->cms_proofing = 0; /* display */
2830 v->cms_proofing_intent = INTENT_ABSOLUTE_COLORIMETRIC;
2831 v->cms_gamut_check = 0;
2832 v->cms_gamut_alarm_color = 3; /* red */
2833 cmsSetAlarmCodes(255, 0, 0);
2834 #endif
2835 if (selection_filetype)
2836 {
2837 v->selection_filetype = strdup(selection_filetype);
2838 }
2839 else
2840 {
2841 v->selection_filetype = NULL;
2842 }
2843
2844 xsane.viewer_list = v;
2845
2846 if (v->allow_modification != VIEWER_FULL_MODIFICATION)
2847 {
2848 v->keep_viewer_pnm_format = TRUE;
2849 v->last_saved_filename = strdup(output_filename); /* output_filename MUST be defined in this case */
2850 }
2851
2852 if (output_filename)
2853 {
2854 v->output_filename = strdup(output_filename);
2855
2856 if (v->image_saved)
2857 {
2858 snprintf(buf, sizeof(buf), "%s %s - %s", WINDOW_VIEWER, v->output_filename, xsane.device_text);
2859 }
2860 else
2861 {
2862 /* add brackets around filename because file is not saved */
2863 snprintf(buf, sizeof(buf), "%s (%s) - %s", WINDOW_VIEWER, v->output_filename, xsane.device_text);
2864 }
2865 }
2866 else
2867 {
2868 snprintf(buf, sizeof(buf), "%s %s", WINDOW_VIEWER, xsane.device_text);
2869 }
2870
2871 xsane_viewer_read_image_header(v);
2872
2873 v->top = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2874 gtk_window_set_title(GTK_WINDOW(v->top), buf);
2875 xsane_set_window_icon(v->top, 0);
2876 gtk_window_add_accel_group(GTK_WINDOW(v->top), xsane.accelerator_group);
2877 gtk_object_set_data(GTK_OBJECT(v->top), "Viewer", (void *) v);
2878 g_signal_connect(GTK_OBJECT(v->top), "delete_event", GTK_SIGNAL_FUNC(xsane_viewer_close_callback), NULL);
2879
2880 /* set the main vbox */
2881 vbox = gtk_vbox_new(FALSE, 0);
2882 gtk_container_set_border_width(GTK_CONTAINER(vbox), 0);
2883 gtk_container_add(GTK_CONTAINER(v->top), vbox);
2884 gtk_widget_show(vbox);
2885
2886
2887 /* create the menubar */
2888 menubar = gtk_menu_bar_new();
2889 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
2890
2891 /* "File" submenu: */
2892 menubar_item = gtk_menu_item_new_with_label(MENU_FILE);
2893 gtk_container_add(GTK_CONTAINER(menubar), menubar_item);
2894 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_viewer_file_build_menu(v));
2895 /* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
2896 gtk_widget_show(menubar_item);
2897 v->file_menu = menubar_item;
2898
2899 /* "Edit" submenu: */
2900 menubar_item = gtk_menu_item_new_with_label(MENU_EDIT);
2901 gtk_container_add(GTK_CONTAINER(menubar), menubar_item);
2902 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_viewer_edit_build_menu(v));
2903 /* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
2904 gtk_widget_show(menubar_item);
2905 v->edit_menu = menubar_item;
2906
2907 /* "Filters" submenu: */
2908 menubar_item = gtk_menu_item_new_with_label(MENU_FILTERS);
2909 gtk_container_add(GTK_CONTAINER(menubar), menubar_item);
2910 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_viewer_filters_build_menu(v));
2911 /* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
2912 gtk_widget_show(menubar_item);
2913 v->filters_menu = menubar_item;
2914
2915 /* "Geometry" submenu: */
2916 menubar_item = gtk_menu_item_new_with_label(MENU_GEOMETRY);
2917 gtk_container_add(GTK_CONTAINER(menubar), menubar_item);
2918 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_viewer_geometry_build_menu(v));
2919 /* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
2920 gtk_widget_show(menubar_item);
2921 v->geometry_menu = menubar_item;
2922
2923 #ifdef HAVE_LIBLCMS
2924 /* "Color management" submenu: */
2925 menubar_item = gtk_menu_item_new_with_label(MENU_COLOR_MANAGEMENT);
2926 gtk_container_add(GTK_CONTAINER(menubar), menubar_item);
2927 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_viewer_color_management_build_menu(v));
2928 /* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
2929 gtk_widget_show(menubar_item);
2930 v->color_management_menu = menubar_item;
2931 gtk_widget_set_sensitive(GTK_WIDGET(v->color_management_menu), v->enable_color_management);
2932 #endif
2933
2934 gtk_widget_show(menubar);
2935
2936
2937 /* set the main hbox */
2938 hbox = gtk_hbox_new(FALSE, 0);
2939 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
2940 gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
2941 gtk_widget_show(hbox);
2942
2943
2944 /* top hbox for icons */
2945 v->button_box = gtk_hbox_new(FALSE, 1);
2946 gtk_container_set_border_width(GTK_CONTAINER(v->button_box), 1);
2947 gtk_box_pack_start(GTK_BOX(vbox), v->button_box, FALSE, FALSE, 0);
2948 gtk_widget_show(v->button_box);
2949
2950
2951 /* top hbox for file icons */
2952 v->file_button_box = gtk_hbox_new(FALSE, 0);
2953 gtk_container_set_border_width(GTK_CONTAINER(v->file_button_box), 0);
2954 gtk_box_pack_start(GTK_BOX(v->button_box), v->file_button_box, FALSE, FALSE, 0);
2955 gtk_widget_show(v->file_button_box);
2956
2957 v->save = xsane_button_new_with_pixmap(v->top->window, v->file_button_box, save_xpm, DESC_VIEWER_SAVE, (GtkSignalFunc) xsane_viewer_save_callback, v);
2958 v->ocr = xsane_button_new_with_pixmap(v->top->window, v->file_button_box, ocr_xpm, DESC_VIEWER_OCR, (GtkSignalFunc) xsane_viewer_ocr_callback, v);
2959 v->clone = xsane_button_new_with_pixmap(v->top->window, v->button_box, clone_xpm, DESC_VIEWER_CLONE, (GtkSignalFunc) xsane_viewer_clone_callback, v);
2960
2961
2962 /* top hbox for edit icons */
2963 v->edit_button_box = gtk_hbox_new(FALSE, 0);
2964 gtk_container_set_border_width(GTK_CONTAINER(v->edit_button_box), 0);
2965 gtk_box_pack_start(GTK_BOX(v->button_box), v->edit_button_box, FALSE, FALSE, 0);
2966 gtk_widget_show(v->edit_button_box);
2967
2968 v->undo = xsane_button_new_with_pixmap(v->top->window, v->edit_button_box, undo_xpm, DESC_VIEWER_UNDO, (GtkSignalFunc) xsane_viewer_undo_callback, v);
2969
2970
2971 /* top hbox for filter icons */
2972 v->filters_button_box = gtk_hbox_new(FALSE, 0);
2973 gtk_container_set_border_width(GTK_CONTAINER(v->filters_button_box), 0);
2974 gtk_box_pack_start(GTK_BOX(v->button_box), v->filters_button_box, FALSE, FALSE, 0);
2975 gtk_widget_show(v->filters_button_box);
2976
2977 v->despeckle = xsane_button_new_with_pixmap(v->top->window, v->filters_button_box, despeckle_xpm, DESC_VIEWER_DESPECKLE, (GtkSignalFunc) xsane_viewer_despeckle_callback, v);
2978 v->blur = xsane_button_new_with_pixmap(v->top->window, v->filters_button_box, blur_xpm, DESC_VIEWER_BLUR, (GtkSignalFunc) xsane_viewer_blur_callback, v);
2979
2980
2981 /* top hbox for geometry icons */
2982 v->geometry_button_box = gtk_hbox_new(FALSE, 0);
2983 gtk_container_set_border_width(GTK_CONTAINER(v->geometry_button_box), 0);
2984 gtk_box_pack_start(GTK_BOX(v->button_box), v->geometry_button_box, FALSE, FALSE, 0);
2985 gtk_widget_show(v->geometry_button_box);
2986
2987 xsane_button_new_with_pixmap(v->top->window, v->geometry_button_box, scale_xpm, DESC_VIEWER_SCALE, (GtkSignalFunc) xsane_viewer_scale_callback, v);
2988 xsane_button_new_with_pixmap(v->top->window, v->geometry_button_box, rotate90_xpm, DESC_ROTATE90, (GtkSignalFunc) xsane_viewer_rotate90_callback, v);
2989 xsane_button_new_with_pixmap(v->top->window, v->geometry_button_box, rotate180_xpm, DESC_ROTATE180, (GtkSignalFunc) xsane_viewer_rotate180_callback, v);
2990 xsane_button_new_with_pixmap(v->top->window, v->geometry_button_box, rotate270_xpm, DESC_ROTATE270, (GtkSignalFunc) xsane_viewer_rotate270_callback, v);
2991 xsane_button_new_with_pixmap(v->top->window, v->geometry_button_box, mirror_x_xpm, DESC_MIRROR_X, (GtkSignalFunc) xsane_viewer_mirror_x_callback, v);
2992 xsane_button_new_with_pixmap(v->top->window, v->geometry_button_box, mirror_y_xpm, DESC_MIRROR_Y, (GtkSignalFunc) xsane_viewer_mirror_y_callback, v);
2993
2994
2995 /* "Zoom" submenu: */
2996 zoom_option_menu = gtk_option_menu_new();
2997 xsane_back_gtk_set_tooltip(xsane.tooltips, zoom_option_menu, DESC_VIEWER_ZOOM);
2998 gtk_box_pack_start(GTK_BOX(v->button_box), zoom_option_menu, FALSE, FALSE, 0);
2999 gtk_widget_show(zoom_option_menu);
3000
3001 zoom_menu = gtk_menu_new();
3002 selection = 0;
3003
3004 for (i = 0; i < sizeof(xsane_viewer_zoom) / sizeof(int); i++)
3005 {
3006 snprintf(buf, sizeof(buf), "%d %%", xsane_viewer_zoom[i]);
3007 zoom_menu_item = gtk_menu_item_new_with_label(buf);
3008 gtk_menu_append(GTK_MENU(zoom_menu), zoom_menu_item);
3009 g_signal_connect(GTK_OBJECT(zoom_menu_item), "activate", (GtkSignalFunc) xsane_viewer_zoom_callback, v);
3010 gtk_object_set_data(GTK_OBJECT(zoom_menu_item), "Selection", (void *) xsane_viewer_zoom[i]);
3011 gtk_widget_show(zoom_menu_item);
3012 if (v->zoom*100 == xsane_viewer_zoom[i])
3013 {
3014 selection = i;
3015 }
3016 }
3017 gtk_option_menu_set_menu(GTK_OPTION_MENU(zoom_option_menu), zoom_menu);
3018 gtk_option_menu_set_history(GTK_OPTION_MENU(zoom_option_menu), selection);
3019 /* gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, 0, GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED); */
3020 gtk_widget_show(zoom_menu);
3021
3022
3023
3024 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
3025 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3026 gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
3027 gtk_widget_show(scrolled_window);
3028
3029
3030 /* the viewport */
3031 v->viewport = gtk_frame_new(/* label */ 0);
3032 gtk_frame_set_shadow_type(GTK_FRAME(v->viewport), GTK_SHADOW_IN);
3033 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), v->viewport);
3034 gtk_widget_show(v->viewport);
3035
3036
3037 /* image info label */
3038 hbox = gtk_hbox_new(FALSE, 1);
3039 gtk_container_set_border_width(GTK_CONTAINER(hbox), 1);
3040 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
3041 gtk_widget_show(hbox);
3042 v->image_info_label = gtk_label_new("");
3043 gtk_box_pack_start(GTK_BOX(hbox), v->image_info_label, FALSE, FALSE, 2);
3044 gtk_widget_show(v->image_info_label);
3045
3046
3047 if (xsane_viewer_read_image(v)) /* read image and add preview to the viewport */
3048 {
3049 /* error */
3050 }
3051 gtk_widget_show(v->top);
3052
3053 v->progress_bar = (GtkProgressBar *) gtk_progress_bar_new();
3054 #if 0
3055 gtk_widget_set_size_request(v->progress_bar, 0, 25);
3056 #endif
3057 gtk_box_pack_start(GTK_BOX(vbox), (GtkWidget *) v->progress_bar, FALSE, FALSE, 0);
3058 gtk_progress_set_show_text(GTK_PROGRESS(v->progress_bar), TRUE);
3059 gtk_progress_set_format_string(GTK_PROGRESS(v->progress_bar), "");
3060 gtk_widget_show(GTK_WIDGET(v->progress_bar));
3061
3062 xsane_viewer_set_sensitivity(v, TRUE);
3063
3064 gtk_widget_set_sensitive(GTK_WIDGET(v->undo), FALSE);
3065 gtk_widget_set_sensitive(GTK_WIDGET(v->undo_menu_item), FALSE);
3066
3067 return v;
3068 }
3069
3070