plug-ins: option to choose whether loading a PDF with white background.

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! 😅
This commit is contained in:
Jehan 2023-02-14 23:46:30 +01:00
parent 4c61ea6ebf
commit 41f40f530a

View file

@ -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;
}