From 41f40f530ac5ce4b4d1756a5aec1829bbdf04579 Mon Sep 17 00:00:00 2001 From: Jehan Date: Tue, 14 Feb 2023 23:46:30 +0100 Subject: [PATCH] plug-ins: option to choose whether loading a PDF with white background. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While at first, the idea of always loading PDF with transparency seemed good (commit 7aff7e9c70), I realized that a lot of administrative PDF (generated with text and vector graphics, rather than scans or alike containing raster) actually have transparency. So now all these documents load with transparent background. Clearly all the office software are assuming that PDF readers will fill the background with white. So add a checkbox to decide whether or not to fill the image with white. I don't update the PDB procedure. I'll just do this on the main dev branch (while also updating a bit the code to newer API). Fortunately I regularly open such PDF documents with GIMP and could witness this no-transparency expectation before we released GIMP 2.10.34! 😅 --- plug-ins/common/file-pdf-load.c | 124 ++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 22 deletions(-) diff --git a/plug-ins/common/file-pdf-load.c b/plug-ins/common/file-pdf-load.c index 5b14968cf6..a1ff026fb6 100644 --- a/plug-ins/common/file-pdf-load.c +++ b/plug-ins/common/file-pdf-load.c @@ -58,6 +58,7 @@ typedef struct gboolean antialias; gboolean reverse_order; gchar *PDF_password; + gboolean white_background; } PdfLoadVals; static PdfLoadVals loadvals = @@ -66,7 +67,8 @@ static PdfLoadVals loadvals = 100.00, /* resolution in dpi */ TRUE, /* antialias */ FALSE, /* reverse_order */ - NULL /* pdf_password */ + NULL, /* pdf_password */ + TRUE, /* white_background */ }; typedef struct @@ -89,6 +91,7 @@ static gint32 load_image (PopplerDocument *doc, GimpPageSelectorTarget target, gdouble resolution, gboolean antialias, + gboolean white_background, gboolean reverse_order, PdfSelectedPages *pages); @@ -102,11 +105,13 @@ static PopplerDocument * open_document (const gchar *filename, static cairo_surface_t * get_thumb_surface (PopplerDocument *doc, gint page, - gint preferred_size); + gint preferred_size, + gboolean white_background); static GdkPixbuf * get_thumb_pixbuf (PopplerDocument *doc, gint page, - gint preferred_size); + gint preferred_size, + gboolean white_background); static gint32 layer_from_surface (gint32 image, const gchar *layer_name, @@ -541,6 +546,7 @@ run (const gchar *name, loadvals.target, loadvals.resolution, loadvals.antialias, + loadvals.white_background, loadvals.reverse_order, &pages); @@ -604,7 +610,7 @@ run (const gchar *name, num_pages = poppler_document_get_n_pages (doc); - surface = get_thumb_surface (doc, 0, param[1].data.d_int32); + surface = get_thumb_surface (doc, 0, param[1].data.d_int32, TRUE); g_object_unref (doc); } @@ -955,7 +961,8 @@ render_page_to_surface (PopplerPage *page, int width, int height, double scale, - gboolean antialias) + gboolean antialias, + gboolean white_background) { cairo_surface_t *surface; cairo_t *cr; @@ -984,6 +991,13 @@ render_page_to_surface (PopplerPage *page, poppler_page_render (page, cr); cairo_restore (cr); + if (white_background) + { + cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_paint (cr); + } + cairo_destroy (cr); return surface; @@ -1021,6 +1035,7 @@ load_image (PopplerDocument *doc, GimpPageSelectorTarget target, gdouble resolution, gboolean antialias, + gboolean white_background, gboolean reverse_order, PdfSelectedPages *pages) { @@ -1088,7 +1103,8 @@ load_image (PopplerDocument *doc, gimp_image_set_resolution (image_ID, resolution, resolution); } - surface = render_page_to_surface (page, width, height, scale, antialias); + surface = render_page_to_surface (page, width, height, scale, + antialias, white_background); layer_from_surface (image_ID, page_label, 0, surface, doc_progress, 1.0 / pages->n_pages); @@ -1139,7 +1155,8 @@ load_image (PopplerDocument *doc, static cairo_surface_t * get_thumb_surface (PopplerDocument *doc, gint page_num, - gint preferred_size) + gint preferred_size, + gboolean white_background) { PopplerPage *page; cairo_surface_t *surface; @@ -1164,7 +1181,7 @@ get_thumb_surface (PopplerDocument *doc, width *= scale; height *= scale; - surface = render_page_to_surface (page, width, height, scale, TRUE); + surface = render_page_to_surface (page, width, height, scale, TRUE, white_background); } g_object_unref (page); @@ -1175,12 +1192,13 @@ get_thumb_surface (PopplerDocument *doc, static GdkPixbuf * get_thumb_pixbuf (PopplerDocument *doc, gint page_num, - gint preferred_size) + gint preferred_size, + gboolean white_background) { cairo_surface_t *surface; GdkPixbuf *pixbuf; - surface = get_thumb_surface (doc, page_num, preferred_size); + surface = get_thumb_surface (doc, page_num, preferred_size, white_background); pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface)); @@ -1194,6 +1212,10 @@ typedef struct PopplerDocument *document; GimpPageSelector *selector; gboolean stop_thumbnailing; + gboolean white_background; + + GMutex mutex; + GCond render_thumb; } ThreadData; typedef struct @@ -1220,32 +1242,69 @@ idle_set_thumbnail (gpointer data) static gpointer thumbnail_thread (gpointer data) { - ThreadData *thread_data = data; - gint n_pages; - gint i; + ThreadData *thread_data = data; + gboolean first_loop = TRUE; + gint n_pages; + gint i; n_pages = poppler_document_get_n_pages (thread_data->document); - for (i = 0; i < n_pages; i++) + while (TRUE) { - IdleData *idle_data = g_new0 (IdleData, 1); + gboolean white_background; + gboolean stop_thumbnailing; - idle_data->selector = thread_data->selector; - idle_data->page_no = i; + g_mutex_lock (&thread_data->mutex); + if (! first_loop) + g_cond_wait (&thread_data->render_thumb, &thread_data->mutex); + white_background = thread_data->white_background; + stop_thumbnailing = thread_data->stop_thumbnailing; + g_mutex_unlock (&thread_data->mutex); - /* FIXME get preferred size from somewhere? */ - idle_data->pixbuf = get_thumb_pixbuf (thread_data->document, i, - THUMBNAIL_SIZE); + if (stop_thumbnailing) + break; - g_idle_add (idle_set_thumbnail, idle_data); + for (i = 0; i < n_pages; i++) + { + IdleData *idle_data = g_new0 (IdleData, 1); + gboolean white_background2; - if (thread_data->stop_thumbnailing) + idle_data->selector = thread_data->selector; + idle_data->page_no = i; + + /* FIXME get preferred size from somewhere? */ + idle_data->pixbuf = get_thumb_pixbuf (thread_data->document, i, + THUMBNAIL_SIZE, + white_background); + + g_idle_add (idle_set_thumbnail, idle_data); + + g_mutex_lock (&thread_data->mutex); + white_background2 = thread_data->white_background; + stop_thumbnailing = thread_data->stop_thumbnailing; + g_mutex_unlock (&thread_data->mutex); + + if (stop_thumbnailing || white_background2 != white_background) + break; + } + + if (stop_thumbnailing) break; } return NULL; } +static void +white_background_toggled (GtkToggleButton *widget, + ThreadData *thread_data) +{ + g_mutex_lock (&thread_data->mutex); + thread_data->white_background = gtk_toggle_button_get_active (widget); + g_cond_signal (&thread_data->render_thumb); + g_mutex_unlock (&thread_data->mutex); +} + static GimpPDBStatusType load_dialog (PopplerDocument *doc, PdfSelectedPages *pages) @@ -1256,6 +1315,7 @@ load_dialog (PopplerDocument *doc, GtkWidget *selector; GtkWidget *resolution; GtkWidget *antialias; + GtkWidget *white_bg; GtkWidget *hbox; GtkWidget *reverse_order; GtkWidget *separator; @@ -1346,6 +1406,9 @@ load_dialog (PopplerDocument *doc, thread_data.document = doc; thread_data.selector = GIMP_PAGE_SELECTOR (selector); thread_data.stop_thumbnailing = FALSE; + thread_data.white_background = loadvals.white_background; + g_mutex_init (&thread_data.mutex); + g_cond_init (&thread_data.render_thumb); thread = g_thread_new ("thumbnailer", thumbnail_thread, &thread_data); @@ -1390,6 +1453,17 @@ load_dialog (PopplerDocument *doc, G_CALLBACK (gimp_toggle_button_update), &loadvals.antialias); gtk_widget_show (antialias); + /* White Background */ + white_bg = gtk_check_button_new_with_mnemonic (_("_Fill transparent areas with white")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (white_bg), loadvals.white_background); + gtk_box_pack_start (GTK_BOX (vbox), white_bg, FALSE, FALSE, 0); + + g_signal_connect (white_bg, "toggled", + G_CALLBACK (gimp_toggle_button_update), &loadvals.white_background); + g_signal_connect (white_bg, "toggled", + G_CALLBACK (white_background_toggled), &thread_data); + gtk_widget_show (white_bg); + /* Setup done; display the dialog */ gtk_widget_show (dialog); @@ -1414,9 +1488,15 @@ load_dialog (PopplerDocument *doc, } /* cleanup */ + g_mutex_lock (&thread_data.mutex); thread_data.stop_thumbnailing = TRUE; + g_cond_signal (&thread_data.render_thumb); + g_mutex_unlock (&thread_data.mutex); g_thread_join (thread); + g_mutex_clear (&thread_data.mutex); + g_cond_clear (&thread_data.render_thumb); + return run ? GIMP_PDB_SUCCESS : GIMP_PDB_CANCEL; }