Index: xsane/src/xsane-save.c diff -c xsane/src/xsane-save.c:1.1.1.1 xsane/src/xsane-save.c:1.1.1.1.2.7 *** xsane/src/xsane-save.c:1.1.1.1 Mon Apr 22 18:38:42 2002 --- xsane/src/xsane-save.c Mon Apr 29 15:47:40 2002 *************** *** 623,634 **** /* ---------------------------------------------------------------------------------------------------------------------- */ ! int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save) { int original_image_width = image_info->image_width; int original_image_height = image_info->image_height; ! int new_image_width = image_info->image_width * x_scale; ! int new_image_height = image_info->image_height * y_scale; unsigned char *original_line; guint16 *original_line16 = NULL; unsigned char *new_line; --- 623,634 ---- /* ---------------------------------------------------------------------------------------------------------------------- */ ! int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int new_image_width, int new_image_height, GtkProgressBar *progress_bar, int *cancel_save) { int original_image_width = image_info->image_width; int original_image_height = image_info->image_height; ! float x_scale = (float)new_image_width / (float)image_info->image_width; ! float y_scale = (float)new_image_height / (float)image_info->image_height; unsigned char *original_line; guint16 *original_line16 = NULL; unsigned char *new_line; *************** *** 830,835 **** --- 830,1065 ---- return (*cancel_save); } + + + static void + rotate_pointers(double **row_buf, unsigned int n) + { + unsigned int i; + double *tmp = row_buf[0]; + for (i = 0; i < n-1; i++) { + row_buf[i] = row_buf[i+1]; + } + row_buf[i] = tmp; + } + + + static void get_next_row_from_file (FILE *infile, + int y, + int src_image_width, + unsigned char *src_tmp, + int bytespp) + { + int colors = 3; + size_t ret; + + ret = fread(src_tmp, src_image_width * bytespp, colors, infile); + + if ( ret != colors ) { + printf("fread could not read enough data.\n"); + } + } + + + static void write_next_row_to_file (FILE *outfile, + int y, + int dst_image_width, + unsigned char *dst_tmp, + int bytespp) + { + int colors = 3; + size_t ret; + + ret = fwrite(dst_tmp, dst_image_width * bytespp, colors, outfile); + + if ( ret != colors ) { + printf("fwrite couln not write enough data.\n"); + } + } + + static void + convert_to_padded_double(FILE *infile, + int y, + int src_image_width, + double *src_row, + guchar *src_tmp, + int bytespp) + { + int b; + int colors = 3; + int x; + unsigned short *src_short_tmp = (unsigned short *)src_tmp; + + switch (bytespp) { + case 2: + for (x = 0; x < src_image_width * colors; x++) { + src_row[x + colors] = src_short_tmp[x]; + } + break; + default: + for (x = 0; x < src_image_width * colors; x++) { + src_row[x + colors] = src_tmp[x]; + } + } + + /* padd one pixel left and two pixel on the right */ + for (b = 0; b < colors; b++) { + src_row[b] = src_row[b + colors]; + } + + for (b = 0; b < colors * 2; b++) { + src_row[src_image_width*colors + b] = src_row[(src_image_width - 1) * colors + (b%colors)]; + } + } + + + static double Cubic( double d, + double f0, + double f1, + double f2, + double f3 ) { + return( ( -f0 + f1 - f2 + f3) * d*d*d + + (2.0*f0 - 2.0*f1 + f2 - f3) * d*d + + ( -f0 + f2 ) * d + + f1 ); + } + + /* + * cubic interpolation as described in + * http://www.pcigeomatics.com/cgi-bin/pcihlp/GCPWORKS|Theory|Resampling + */ + int xsane_save_cubic_scaled_image( FILE *outfile, + FILE *infile, + Image_info *image_info, + int dst_image_width, + int dst_image_height, + GtkProgressBar *progress_bar, + int *cancel_save ) + { + int src_image_width = image_info->image_width; + int src_image_height = image_info->image_height; + double x_scale = (double)dst_image_width / (double)src_image_width; + double y_scale = (double)dst_image_height / (double)src_image_height; + double x_inv_scale = (double)src_image_width / (double)dst_image_width; + double y_inv_scale = (double)src_image_height / (double)dst_image_height; + double *row_buf[4]; + double *tmp_row; + unsigned char *src_tmp; + unsigned char *dst_tmp; + unsigned short *dst_short_tmp; + int i; + int x; + int last_read_src_y = 0; + int colors = 3; + int bytespp; + + int src_i, src_j, dst_i, dst_j; + double src_x, src_y; + double src_d_x, src_d_y; + int c; + + DBG(DBG_proc, "xsane_save_bicubic_scaled_image\n"); + + image_info->image_width = dst_image_width; + image_info->image_height = dst_image_height; + image_info->resolution_x *= (float)x_scale; + image_info->resolution_y *= (float)y_scale; + + if ( image_info->depth > 8 ) { + bytespp = 2; + } else { + bytespp = 1; + } + + for ( i = 0; i < 4 ; i++ ) { + row_buf[i] = calloc(sizeof(double), (src_image_width + 3) * colors); + } + src_tmp = calloc(sizeof(unsigned char), src_image_width * colors * bytespp); + dst_tmp = calloc(sizeof(unsigned char), dst_image_width * colors * bytespp); + tmp_row = calloc(sizeof(double), dst_image_width * colors); + + xsane_write_pnm_header(outfile, image_info); + + get_next_row_from_file(infile, last_read_src_y, src_image_width, src_tmp, bytespp); + convert_to_padded_double(infile, -1, src_image_width, row_buf[0], src_tmp, bytespp); + convert_to_padded_double(infile, 0, src_image_width, row_buf[1], src_tmp, bytespp); + get_next_row_from_file(infile, ++last_read_src_y, src_image_width, src_tmp, bytespp); + convert_to_padded_double(infile, 1, src_image_width, row_buf[2], src_tmp, bytespp); + get_next_row_from_file(infile, ++last_read_src_y, src_image_width, src_tmp, bytespp); + convert_to_padded_double(infile, 2, src_image_width, row_buf[3], src_tmp, bytespp); + + for ( dst_j = 0; dst_j < dst_image_height; dst_j++) { + src_y = (double) dst_j * y_inv_scale; + src_j = (int) src_y; + src_d_y = src_y - (double)src_j; + + while (last_read_src_y < src_j + 2 ) { + last_read_src_y++; + if ( last_read_src_y < src_image_height ) { + get_next_row_from_file(infile, last_read_src_y, src_image_width, src_tmp, bytespp); + } + rotate_pointers(row_buf, 4); + convert_to_padded_double(infile, 1, src_image_width, row_buf[3], src_tmp, bytespp); + } + + gtk_progress_bar_update(progress_bar, (float) dst_j / dst_image_height); + while (gtk_events_pending()) { + gtk_main_iteration(); + } + + for ( dst_i = 0; dst_i < dst_image_width; dst_i++) { + src_x = (double) dst_i * x_inv_scale; + src_i = (int) src_x; + src_d_x = src_x - (double)src_i; + + for ( c = 0; c < 3 ; c++ ) { + #define POINT(a,b) row_buf[(a)+1][(src_i+(b)+1)*3+c] + double p0 = Cubic(src_d_x, POINT(-1,-1), POINT(-1,0), POINT(-1,1), POINT(-1,2)); + double p1 = Cubic(src_d_x, POINT(0,-1), POINT(0,0), POINT(0,1), POINT(0,2)); + double p2 = Cubic(src_d_x, POINT(1,-1), POINT(1,0), POINT(1,1), POINT(1,2)); + double p3 = Cubic(src_d_x, POINT(2,-1), POINT(2,0), POINT(2,1), POINT(2,2)); + tmp_row[dst_i * 3 + c] = Cubic(src_d_y, p0, p1, p2, p3); + } + } + + switch (bytespp) { + case 2: + dst_short_tmp = (unsigned short *)dst_tmp; + for (x = 0; x < dst_image_width * colors; x++) { + if (tmp_row[x] < 0.0) { + dst_short_tmp[x] = 0; + } else if (tmp_row[x] > 65535.0) { + dst_short_tmp[x] = 65535; + } else { + dst_short_tmp[x] = tmp_row[x] + 0.5; + } + } + break; + default: + for (x = 0; x < dst_image_width * colors; x++) { + if (tmp_row[x] < 0.0) { + dst_tmp[x] = 0; + } else if (tmp_row[x] > 255.0) { + dst_tmp[x] = 255; + } else { + dst_tmp[x] = tmp_row[x] + 0.5; + } + } + } + + write_next_row_to_file (outfile, dst_j, dst_image_width, dst_tmp, bytespp); + } + + for (i = 0; i < 4; i++) { + free (row_buf[i]); + } + free (src_tmp); + free (dst_tmp); + free (tmp_row); + + return (*cancel_save); + } + /* ---------------------------------------------------------------------------------------------------------------------- */ #if 0 Index: xsane/src/xsane-save.h diff -c xsane/src/xsane-save.h:1.1.1.1 xsane/src/xsane-save.h:1.1.1.1.2.3 *** xsane/src/xsane-save.h:1.1.1.1 Mon Apr 22 18:38:42 2002 --- xsane/src/xsane-save.h Mon Apr 29 15:47:40 2002 *************** *** 30,36 **** extern void xsane_read_pnm_header(FILE *infile, Image_info *image_info); extern void xsane_write_pnm_header(FILE *outfile, Image_info *image_info); extern int xsane_save_grayscale_image_as_lineart(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save); ! extern int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float x_scale, float y_scale, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float radius, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int rotation, GtkProgressBar *progress_bar, int *cancel_save); --- 30,37 ---- extern void xsane_read_pnm_header(FILE *infile, Image_info *image_info); extern void xsane_write_pnm_header(FILE *outfile, Image_info *image_info); extern int xsane_save_grayscale_image_as_lineart(FILE *outfile, FILE *imagefile, Image_info *image_info, GtkProgressBar *progress_bar, int *cancel_save); ! extern int xsane_save_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int new_image_width, int new_image_height, GtkProgressBar *progress_bar, int *cancel_save); ! extern int xsane_save_cubic_scaled_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int new_image_width, int new_image_height, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_despeckle_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int radius, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_blur_image(FILE *outfile, FILE *imagefile, Image_info *image_info, float radius, GtkProgressBar *progress_bar, int *cancel_save); extern int xsane_save_rotate_image(FILE *outfile, FILE *imagefile, Image_info *image_info, int rotation, GtkProgressBar *progress_bar, int *cancel_save); Index: xsane/src/xsane-text.h diff -c xsane/src/xsane-text.h:1.1.1.1 xsane/src/xsane-text.h:1.1.1.1.2.1 *** xsane/src/xsane-text.h:1.1.1.1 Mon Apr 22 18:38:43 2002 --- xsane/src/xsane-text.h Mon Apr 22 19:25:38 2002 *************** *** 221,226 **** --- 221,228 ---- #define TEXT_VIEWER_IMAGE_INFO _("Size %d x %d pixel, %d bit/color, %d colors, %1.0f dpi x %1.0f dpi, %1.1f %s") #define TEXT_X_SCALE_FACTOR _("X-Scale factor:") #define TEXT_Y_SCALE_FACTOR _("Y-Scale factor:") + #define TEXT_X_WIDTH_OUTPUT _("X-Output width: ") + #define TEXT_Y_HEIGHT_OUTPUT _("Y-Output height:") #define TEXT_DESPECKLE_RADIUS _("Despeckle radius:") #define TEXT_BLUR_RADIUS _("Blur radius:") Index: xsane/src/xsane-viewer.c diff -c xsane/src/xsane-viewer.c:1.1.1.1 xsane/src/xsane-viewer.c:1.1.1.1.2.5 *** xsane/src/xsane-viewer.c:1.1.1.1 Mon Apr 22 18:38:43 2002 --- xsane/src/xsane-viewer.c Mon Apr 29 15:47:40 2002 *************** *** 89,94 **** --- 89,95 ---- } remove(v->filename); + free(v->filename); gtk_widget_destroy(v->top); *************** *** 109,117 **** list = list->next_viewer; } free(v); ! return TRUE; } /* ---------------------------------------------------------------------------------------------------------------------- */ --- 110,126 ---- list = list->next_viewer; } + if ( v->output_filename != NULL ) { + free(v->output_filename); + } + + if ( v->image_info != NULL ) { + free(v->image_info); + } + free(v); ! return TRUE; } /* ---------------------------------------------------------------------------------------------------------------------- */ *************** *** 478,483 **** --- 487,605 ---- #endif } + static void xsane_viewer_spinbutton_float_changed_set_scale_output_width(GtkWidget *spinbutton, gpointer data) + { + Viewer *v = (Viewer *)data; + float val; + + #ifdef HAVE_GTK2 + val = (float) gtk_spin_button_get_value((GtkSpinButton *) spinbutton); + #else + val = gtk_spin_button_get_value_as_float((GtkSpinButton *) spinbutton); + #endif + + v->scale_output_width = val * v->image_info->image_width + 0.5; + gtk_spin_button_set_value(v->scale_spinbutton_output_width, val * v->image_info->image_width); + } + + static void xsane_viewer_spinbutton_float_changed_set_scale_output_height(GtkWidget *spinbutton, gpointer data) + { + Viewer *v = (Viewer *)data; + float val; + + #ifdef HAVE_GTK2 + val = (float) gtk_spin_button_get_value((GtkSpinButton *) spinbutton); + #else + val = gtk_spin_button_get_value_as_float((GtkSpinButton *) spinbutton); + #endif + + v->scale_output_height = val * v->image_info->image_height + 0.5; + gtk_spin_button_set_value(v->scale_spinbutton_output_height, val * v->image_info->image_height); + } + + static void xsane_viewer_spinbutton_float_changed_set_scale_x_factor(GtkWidget *spinbutton, gpointer data) + { + Viewer *v = (Viewer *)data; + float val; + + #ifdef HAVE_GTK2 + val = (float) gtk_spin_button_get_value((GtkSpinButton *) spinbutton); + #else + val = gtk_spin_button_get_value_as_float((GtkSpinButton *) spinbutton); + #endif + + val = val / v->image_info->image_width; + + gtk_spin_button_set_value(v->scale_spinbutton_x_factor, val); + } + + static void xsane_viewer_spinbutton_float_changed_set_scale_y_factor(GtkWidget *spinbutton, gpointer data) + { + Viewer *v = (Viewer *)data; + float val; + + #ifdef HAVE_GTK2 + val = (float) gtk_spin_button_get_value((GtkSpinButton *) spinbutton); + #else + val = gtk_spin_button_get_value_as_float((GtkSpinButton *) spinbutton); + #endif + + val = val / v->image_info->image_height; + + gtk_spin_button_set_value(v->scale_spinbutton_y_factor, val); + } + + static void xsane_viewer_button_set_scale_1024_768(GtkWidget *button, gpointer data) + { + Viewer *v = (Viewer *)data; + float x_scale; + float y_scale; + + x_scale = (1024.0 / v->image_info->image_width) + 0.0005; + y_scale = (768.0 / v->image_info->image_height) + 0.0005; + + gtk_spin_button_set_value(v->scale_spinbutton_x_factor, x_scale); + gtk_spin_button_set_value(v->scale_spinbutton_y_factor, y_scale); + gtk_spin_button_set_value(v->scale_spinbutton_output_width, 1024.0); + gtk_spin_button_set_value(v->scale_spinbutton_output_height, 768.0); + + v->scale_output_width = 1024; + v->scale_output_height = 768; + } + + static void xsane_viewer_button_set_scale_768_1024(GtkWidget *button, gpointer data) + { + Viewer *v = (Viewer *)data; + float x_scale; + float y_scale; + + x_scale = (768.0 / v->image_info->image_width) + 0.0005; + y_scale = (1024.0 / v->image_info->image_height) + 0.0005; + + gtk_spin_button_set_value(v->scale_spinbutton_x_factor, x_scale); + gtk_spin_button_set_value(v->scale_spinbutton_y_factor, y_scale); + gtk_spin_button_set_value(v->scale_spinbutton_output_width, 768.0); + gtk_spin_button_set_value(v->scale_spinbutton_output_height, 1024.0); + + v->scale_output_width = 768; + v->scale_output_height = 1024; + } + + static void xsane_viewer_radio_button_scale_interpolation_nearest_neighbour(GtkWidget *button, gpointer data) + { + Viewer *v = (Viewer *)data; + + v->scale_interpolation_type = SCALE_NEAREST_NEIGHBOUR; + } + + + static void xsane_viewer_radio_button_scale_interpolation_cubic(GtkWidget *button, gpointer data) + { + Viewer *v = (Viewer *)data; + + v->scale_interpolation_type = SCALE_INTERPOLATION_CUBIC; + } + /* ---------------------------------------------------------------------------------------------------------------------- */ static void xsane_viewer_spinbutton_int_changed(GtkWidget *spinbutton, gpointer data) *************** *** 496,501 **** --- 618,624 ---- GtkWidget *frame; GtkWidget *hbox, *vbox; GtkWidget *label, *spinbutton, *button; + GSList *group; GtkAdjustment *adjustment; char buf[256]; *************** *** 540,547 **** #endif /* x_scale factor: <-> */ ! ! v->x_scale_factor = 1.0; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); --- 663,669 ---- #endif /* x_scale factor: <-> */ ! v->scale_output_width = v->image_info->image_width; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); *************** *** 553,566 **** adjustment = (GtkAdjustment *) gtk_adjustment_new(1.0, 0.01, 10.0, 0.01, 0.1, 0.0); spinbutton = gtk_spin_button_new(adjustment, 0, 2); ! g_signal_connect(GTK_OBJECT(spinbutton), DEF_GTK_SIGNAL_SPINBUTTON_VALUE_CHANGED, (GtkSignalFunc) xsane_viewer_spinbutton_float_changed, (void *) &v->x_scale_factor); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE); ! gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10); gtk_widget_show(spinbutton); ! /* y_scale factor: <-> */ ! v->y_scale_factor = 1.0; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); --- 675,705 ---- adjustment = (GtkAdjustment *) gtk_adjustment_new(1.0, 0.01, 10.0, 0.01, 0.1, 0.0); spinbutton = gtk_spin_button_new(adjustment, 0, 2); ! v->scale_spinbutton_x_factor = (GtkSpinButton *)spinbutton; ! g_signal_connect(GTK_OBJECT(spinbutton), DEF_GTK_SIGNAL_SPINBUTTON_VALUE_CHANGED, (GtkSignalFunc) xsane_viewer_spinbutton_float_changed_set_scale_output_width, (void *) v); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE); ! gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10); gtk_widget_show(spinbutton); ! label = gtk_label_new(TEXT_X_WIDTH_OUTPUT); ! gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); ! gtk_widget_show(label); ! ! adjustment = (GtkAdjustment *) gtk_adjustment_new(v->image_info->image_width, 1.0, G_MAXFLOAT, 1.0, 10.0, 0.0); ! spinbutton = gtk_spin_button_new(adjustment, 0, 0); ! v->scale_spinbutton_output_width = (GtkSpinButton *) spinbutton; ! g_signal_connect(GTK_OBJECT(spinbutton), DEF_GTK_SIGNAL_SPINBUTTON_VALUE_CHANGED, (GtkSignalFunc) xsane_viewer_spinbutton_float_changed_set_scale_x_factor, (void *) v); ! gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE); ! gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10); ! gtk_widget_show(spinbutton); ! ! button = gtk_button_new_with_label("1024x768"); ! g_signal_connect(GTK_OBJECT(button), "pressed", (GtkSignalFunc) xsane_viewer_button_set_scale_1024_768, (void *) v); ! gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10); ! gtk_widget_show(button); ! /* y_scale factor: <-> */ ! v->scale_output_height = v->image_info->image_height; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); *************** *** 572,584 **** adjustment = (GtkAdjustment *) gtk_adjustment_new(1.0, 0.01, 10.0, 0.01, 0.1, 0.0); spinbutton = gtk_spin_button_new(adjustment, 0, 2); ! g_signal_connect(GTK_OBJECT(spinbutton), DEF_GTK_SIGNAL_SPINBUTTON_VALUE_CHANGED, (GtkSignalFunc) xsane_viewer_spinbutton_float_changed, (void *) &v->y_scale_factor); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE); ! gtk_box_pack_end(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10); gtk_widget_show(spinbutton); ! /* Apply Cancel */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); --- 711,757 ---- adjustment = (GtkAdjustment *) gtk_adjustment_new(1.0, 0.01, 10.0, 0.01, 0.1, 0.0); spinbutton = gtk_spin_button_new(adjustment, 0, 2); ! v->scale_spinbutton_y_factor = (GtkSpinButton *)spinbutton; ! g_signal_connect(GTK_OBJECT(spinbutton), DEF_GTK_SIGNAL_SPINBUTTON_VALUE_CHANGED, (GtkSignalFunc) xsane_viewer_spinbutton_float_changed_set_scale_output_height, (void *)v); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE); ! gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10); gtk_widget_show(spinbutton); ! label = gtk_label_new(TEXT_Y_HEIGHT_OUTPUT); ! gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10); ! gtk_widget_show(label); ! ! adjustment = (GtkAdjustment *) gtk_adjustment_new(v->image_info->image_height, 1.0, G_MAXFLOAT, 1.0, 10.0, 0.0); ! spinbutton = gtk_spin_button_new(adjustment, 0, 0); ! v->scale_spinbutton_output_height = (GtkSpinButton *) spinbutton; ! g_signal_connect(GTK_OBJECT(spinbutton), DEF_GTK_SIGNAL_SPINBUTTON_VALUE_CHANGED, (GtkSignalFunc) xsane_viewer_spinbutton_float_changed_set_scale_y_factor, (void *) v); ! gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinbutton), TRUE); ! gtk_box_pack_start(GTK_BOX(hbox), spinbutton, FALSE, FALSE, 10); ! gtk_widget_show(spinbutton); ! ! button = gtk_button_new_with_label("768x1024"); ! g_signal_connect(GTK_OBJECT(button), "pressed", (GtkSignalFunc) xsane_viewer_button_set_scale_768_1024, (void *) v); ! gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10); ! gtk_widget_show(button); ! ! button = gtk_radio_button_new_with_label(NULL, "NEAREST_NEIGHBOUR"); ! if ( v->scale_interpolation_type == SCALE_NEAREST_NEIGHBOUR ) { ! gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE); ! } ! g_signal_connect(GTK_OBJECT(button), "pressed", (GtkSignalFunc) xsane_viewer_radio_button_scale_interpolation_nearest_neighbour, (void *) v); ! gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10); ! gtk_widget_show(button); ! ! group = gtk_radio_button_group(GTK_RADIO_BUTTON(button)); ! button = gtk_radio_button_new_with_label(group, "CUBIC"); ! if ( v->scale_interpolation_type == SCALE_INTERPOLATION_CUBIC ) { ! gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE); ! } ! g_signal_connect(GTK_OBJECT(button), "pressed", (GtkSignalFunc) xsane_viewer_radio_button_scale_interpolation_cubic, (void *) v); ! gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10); ! gtk_widget_show(button); + /* Apply Cancel */ hbox = gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2); *************** *** 818,824 **** gtk_progress_bar_update(GTK_PROGRESS_BAR(v->progress_bar), 0.0); ! xsane_save_scaled_image(outfile, infile, &image_info, v->x_scale_factor, v->y_scale_factor, v->progress_bar, &v->cancel_save); fclose(infile); fclose(outfile); --- 991,1003 ---- gtk_progress_bar_update(GTK_PROGRESS_BAR(v->progress_bar), 0.0); ! switch ( v->scale_interpolation_type ) { ! case SCALE_INTERPOLATION_CUBIC: ! xsane_save_cubic_scaled_image(outfile, infile, &image_info, v->scale_output_width, v->scale_output_height, v->progress_bar, &v->cancel_save); ! break; ! default: ! xsane_save_scaled_image(outfile, infile, &image_info, v->scale_output_width, v->scale_output_height, v->progress_bar, &v->cancel_save); ! } fclose(infile); fclose(outfile); *************** *** 1226,1231 **** --- 1405,1412 ---- xsane_read_pnm_header(infile, &image_info); + *v->image_info = image_info; + pos0 = ftell(infile); if (!image_info.colors) /* == 0 (grayscale) ? */ *************** *** 1433,1441 **** --- 1614,1629 ---- memset(v, 0, sizeof(*v)); v->filename = strdup(filename); + if ( (v->image_info = malloc(sizeof(*v->image_info))) == NULL) { + free(v); + DBG(DBG_error, "could not allocate memory\n"); + return 0; + } + memset(v->image_info, 0, sizeof(*v->image_info)); v->reduce_to_lineart = reduce_to_lineart; v->zoom = 1.0; v->image_saved = FALSE; + v->scale_interpolation_type = SCALE_INTERPOLATION_CUBIC; v->next_viewer = xsane.viewer_list; xsane.viewer_list = v; Index: xsane/src/xsane-viewer.h diff -c xsane/src/xsane-viewer.h:1.1.1.1 xsane/src/xsane-viewer.h:1.1.1.1.2.4 *** xsane/src/xsane-viewer.h:1.1.1.1 Mon Apr 22 18:38:41 2002 --- xsane/src/xsane-viewer.h Mon Apr 29 15:47:40 2002 *************** *** 25,34 **** --- 25,41 ---- #ifndef XSANE_VIEWER_H #define XSANE_VIEWER_H + #include "xsane.h" + #include #include #include + typedef enum scale_interpolation_e { + SCALE_NEAREST_NEIGHBOUR = 0, + SCALE_INTERPOLATION_CUBIC = 1 + } scale_interpolation_t; + typedef struct Viewer { struct Viewer *next_viewer; *************** *** 36,41 **** --- 43,50 ---- char *filename; char *output_filename; + struct Image_info *image_info; + int reduce_to_lineart; float zoom; int image_saved; *************** *** 44,51 **** int despeckle_radius; float blur_radius; ! float x_scale_factor; ! float y_scale_factor; GtkWidget *top; GtkWidget *button_box; --- 53,61 ---- int despeckle_radius; float blur_radius; ! int scale_output_width; ! int scale_output_height; ! scale_interpolation_t scale_interpolation_type; GtkWidget *top; GtkWidget *button_box; *************** *** 57,62 **** --- 67,76 ---- GtkWidget *ocr; GtkWidget *clone; GtkWidget *scale; + GtkSpinButton *scale_spinbutton_x_factor; + GtkSpinButton *scale_spinbutton_y_factor; + GtkSpinButton *scale_spinbutton_output_width; + GtkSpinButton *scale_spinbutton_output_height; GtkWidget *despeckle; GtkWidget *blur;