mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 10:50:10 +00:00
Check properly whether the XPM module has already been loaded
1999-10-27 Havoc Pennington <hp@pobox.com> * src/gdk-pixbuf-io.c (gdk_pixbuf_new_from_xpm_data): Check properly whether the XPM module has already been loaded (gdk_pixbuf_new_from_file): Check properly if loader module was already loaded (was checking if load symbol was present in order to decide whether to re-load; should check module != NULL, then load != NULL) (image_handler_load): Check in present working directory, makes it easier to debug for now (file_formats): This array initializer was seriously on crack, was assigning a function pointer to a GModule* * src/testpixbuf.c (main): Change type of pixbuf_loader to GdkPixbufLoader* * src/io-png.c: Progressive loading stuff compiles, untested.
This commit is contained in:
parent
2ec115ea80
commit
54f017171f
@ -409,7 +409,7 @@ main (int argc, char **argv)
|
||||
int found_valid = FALSE;
|
||||
|
||||
GdkPixbuf *pixbuf;
|
||||
GtkObject *pixbuf_loader;
|
||||
GdkPixbufLoader *pixbuf_loader;
|
||||
FILE *file;
|
||||
gint val;
|
||||
guchar buf;
|
||||
|
@ -136,17 +136,17 @@ pixbuf_check_ppm (guchar *buffer, int size)
|
||||
#endif
|
||||
|
||||
ModuleType file_formats [] = {
|
||||
{ "png", pixbuf_check_png, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "tiff", pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "gif", pixbuf_check_gif, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "png", NULL, pixbuf_check_png, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "jpeg", NULL, pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "tiff", NULL, pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "gif", NULL, pixbuf_check_gif, NULL, NULL, NULL, NULL, NULL },
|
||||
#define XPM_FILE_FORMAT_INDEX 4
|
||||
{ "xpm", pixbuf_check_xpm, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "xpm", NULL, pixbuf_check_xpm, NULL, NULL, NULL, NULL, NULL },
|
||||
#if 0
|
||||
{ "bmp", pixbuf_check_bmp, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "ppm", pixbuf_check_ppm, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "bmp", NULL, pixbuf_check_bmp, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "ppm", NULL, pixbuf_check_ppm, NULL, NULL, NULL, NULL, NULL },
|
||||
#endif
|
||||
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
@ -161,14 +161,29 @@ image_handler_load (ModuleType *image_module)
|
||||
|
||||
module_name = g_strconcat ("pixbuf-", image_module->module_name, NULL);
|
||||
path = g_module_build_path (PIXBUF_LIBDIR, module_name);
|
||||
g_free (module_name);
|
||||
|
||||
module = g_module_open (path, G_MODULE_BIND_LAZY);
|
||||
g_free (path);
|
||||
if (!module) {
|
||||
g_warning ("Unable to load module: %s", path);
|
||||
/* Debug feature, check in present working directory */
|
||||
g_free(path);
|
||||
path = g_module_build_path("", module_name);
|
||||
module = g_module_open(path, G_MODULE_BIND_LAZY);
|
||||
|
||||
if (!module) {
|
||||
g_warning ("Unable to load module: %s: %s", path, g_module_error());
|
||||
g_free (module_name);
|
||||
g_free(path);
|
||||
return;
|
||||
} else {
|
||||
printf("loaded module `%s'\n", module_name);
|
||||
}
|
||||
g_free(path);
|
||||
} else {
|
||||
printf("loaded module `%s'\n", path);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
g_free (module_name);
|
||||
|
||||
image_module->module = module;
|
||||
|
||||
@ -224,10 +239,10 @@ gdk_pixbuf_new_from_file (const char *filename)
|
||||
|
||||
image_module = gdk_pixbuf_get_module (buffer, size);
|
||||
if (image_module){
|
||||
if (!image_module->load)
|
||||
if (image_module->module == NULL)
|
||||
image_handler_load (image_module);
|
||||
|
||||
if (!image_module->load) {
|
||||
if (image_module->load == NULL) {
|
||||
fclose (f);
|
||||
return NULL;
|
||||
}
|
||||
@ -254,13 +269,16 @@ gdk_pixbuf_new_from_xpm_data (const gchar **data)
|
||||
GdkPixbuf *(* load_xpm_data) (const gchar **data);
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
|
||||
if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL) {
|
||||
image_handler_load(&file_formats[XPM_FILE_FORMAT_INDEX]);
|
||||
}
|
||||
|
||||
if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
|
||||
if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL) {
|
||||
g_warning("Can't find gdk-pixbuf module for parsing inline XPM data");
|
||||
return NULL;
|
||||
} else if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
|
||||
g_warning("gdk-pixbuf XPM module lacks XPM data capability");
|
||||
return NULL;
|
||||
} else {
|
||||
load_xpm_data = file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <stdio.h>
|
||||
#include <png.h>
|
||||
#include "gdk-pixbuf.h"
|
||||
#include "gdk-pixbuf-io.h"
|
||||
|
||||
|
||||
|
||||
@ -135,8 +136,299 @@ image_load (FILE *f)
|
||||
free_buffer, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
image_load_by_data (void *data, size_t count)
|
||||
/* These avoid the setjmp()/longjmp() crap in libpng */
|
||||
static void png_error_callback (png_structp png_read_ptr,
|
||||
png_const_charp error_msg);
|
||||
|
||||
static void png_warning_callback(png_structp png_read_ptr,
|
||||
png_const_charp warning_msg);
|
||||
|
||||
/* Called at the start of the progressive load */
|
||||
static void png_info_callback (png_structp png_read_ptr,
|
||||
png_infop png_info_ptr);
|
||||
|
||||
/* Called for each row; note that you will get duplicate row numbers
|
||||
for interlaced PNGs */
|
||||
static void png_row_callback (png_structp png_read_ptr,
|
||||
png_bytep new_row,
|
||||
png_uint_32 row_num,
|
||||
int pass_num);
|
||||
|
||||
/* Called after reading the entire image */
|
||||
static void png_end_callback (png_structp png_read_ptr,
|
||||
png_infop png_info_ptr);
|
||||
|
||||
typedef struct _LoadContext LoadContext;
|
||||
|
||||
struct _LoadContext {
|
||||
png_structp png_read_ptr;
|
||||
png_infop png_info_ptr;
|
||||
|
||||
ModulePreparedNotifyFunc notify_func;
|
||||
gpointer notify_user_data;
|
||||
|
||||
GdkPixbuf* pixbuf;
|
||||
|
||||
guint fatal_error_occurred : 1;
|
||||
|
||||
};
|
||||
|
||||
gpointer
|
||||
image_begin_load (ModulePreparedNotifyFunc func, gpointer user_data)
|
||||
{
|
||||
LoadContext* lc;
|
||||
|
||||
lc = g_new0(LoadContext, 1);
|
||||
|
||||
lc->fatal_error_occurred = FALSE;
|
||||
|
||||
lc->notify_func = func;
|
||||
lc->notify_user_data = user_data;
|
||||
|
||||
/* Create the main PNG context struct */
|
||||
|
||||
lc->png_read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
lc, /* error/warning callback data */
|
||||
png_error_callback,
|
||||
png_warning_callback);
|
||||
|
||||
if (lc->png_read_ptr == NULL) {
|
||||
g_free(lc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the two auxiliary context structs */
|
||||
|
||||
lc->png_info_ptr = png_create_info_struct(lc->png_read_ptr);
|
||||
|
||||
if (lc->png_info_ptr == NULL) {
|
||||
png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
|
||||
g_free(lc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_set_progressive_read_fn(lc->png_read_ptr,
|
||||
lc, /* callback data */
|
||||
png_info_callback,
|
||||
png_row_callback,
|
||||
png_end_callback);
|
||||
|
||||
|
||||
return lc;
|
||||
}
|
||||
|
||||
void
|
||||
image_stop_load (gpointer context)
|
||||
{
|
||||
LoadContext* lc = context;
|
||||
|
||||
g_return_if_fail(lc != NULL);
|
||||
|
||||
gdk_pixbuf_unref(lc->pixbuf);
|
||||
|
||||
png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
|
||||
g_free(lc);
|
||||
}
|
||||
|
||||
gboolean
|
||||
image_load_increment(gpointer context, guchar *buf, guint size)
|
||||
{
|
||||
LoadContext* lc = context;
|
||||
|
||||
g_return_val_if_fail(lc != NULL, FALSE);
|
||||
|
||||
/* Invokes our callbacks as needed */
|
||||
png_process_data(lc->png_read_ptr, lc->png_info_ptr, buf, size);
|
||||
|
||||
if (lc->fatal_error_occurred)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Called at the start of the progressive load, once we have image info */
|
||||
static void
|
||||
png_info_callback (png_structp png_read_ptr,
|
||||
png_infop png_info_ptr)
|
||||
{
|
||||
LoadContext* lc;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, filter_type,
|
||||
compression_type, interlace_type, channels;
|
||||
gboolean have_alpha = FALSE;
|
||||
|
||||
lc = png_get_progressive_ptr(png_read_ptr);
|
||||
|
||||
if (lc->fatal_error_occurred)
|
||||
return;
|
||||
|
||||
/* Get the image info */
|
||||
|
||||
png_get_IHDR (lc->png_read_ptr, lc->png_info_ptr,
|
||||
&width, &height,
|
||||
&bit_depth,
|
||||
&color_type,
|
||||
&interlace_type,
|
||||
&compression_type,
|
||||
&filter_type);
|
||||
|
||||
/* set_expand() basically needs to be called unless
|
||||
we are already in RGB/RGBA mode
|
||||
*/
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE &&
|
||||
bit_depth <= 8) {
|
||||
|
||||
/* Convert indexed images to RGB */
|
||||
png_set_expand (lc->png_read_ptr);
|
||||
|
||||
} else if (color_type == PNG_COLOR_TYPE_GRAY &&
|
||||
bit_depth < 8) {
|
||||
|
||||
/* Convert grayscale to RGB */
|
||||
png_set_expand (lc->png_read_ptr);
|
||||
|
||||
} else if (png_get_valid (lc->png_read_ptr,
|
||||
lc->png_info_ptr, PNG_INFO_tRNS)) {
|
||||
|
||||
/* If we have transparency header, convert it to alpha
|
||||
channel */
|
||||
png_set_expand(lc->png_read_ptr);
|
||||
|
||||
} else if (bit_depth < 8) {
|
||||
|
||||
/* If we have < 8 scale it up to 8 */
|
||||
png_set_expand(lc->png_read_ptr);
|
||||
|
||||
|
||||
/* Conceivably, png_set_packing() is a better idea;
|
||||
* God only knows how libpng works
|
||||
*/
|
||||
}
|
||||
|
||||
/* If we are 16-bit, convert to 8-bit */
|
||||
if (bit_depth == 16) {
|
||||
png_set_strip_16(lc->png_read_ptr);
|
||||
}
|
||||
|
||||
/* If gray scale, convert to RGB */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(lc->png_read_ptr);
|
||||
}
|
||||
|
||||
/* If we have alpha, set a flag */
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
have_alpha = TRUE;
|
||||
|
||||
/* Update the info the reflect our transformations */
|
||||
png_read_update_info(lc->png_read_ptr, lc->png_info_ptr);
|
||||
|
||||
png_get_IHDR (lc->png_read_ptr, lc->png_info_ptr,
|
||||
&width, &height,
|
||||
&bit_depth,
|
||||
&color_type,
|
||||
&interlace_type,
|
||||
&compression_type,
|
||||
&filter_type);
|
||||
|
||||
#ifndef G_DISABLE_CHECKS
|
||||
/* Check that the new info is what we want */
|
||||
|
||||
if (bit_depth != 8) {
|
||||
g_warning("Bits per channel of transformed PNG is %d, not 8.", bit_depth);
|
||||
lc->fatal_error_occurred = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! (color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) ) {
|
||||
g_warning("Transformed PNG not RGB or RGBA.");
|
||||
lc->fatal_error_occurred = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
channels = png_get_channels(lc->png_read_ptr, lc->png_info_ptr);
|
||||
if ( ! (channels == 3 || channels == 4) ) {
|
||||
g_warning("Transformed PNG has %d channels, must be 3 or 4.", channels);
|
||||
lc->fatal_error_occurred = TRUE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
lc->pixbuf = gdk_pixbuf_new(have_alpha, width, height);
|
||||
|
||||
if (lc->pixbuf == NULL) {
|
||||
/* Failed to allocate memory */
|
||||
lc->fatal_error_occurred = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Notify the client that we are ready to go */
|
||||
|
||||
if (lc->notify_func)
|
||||
(* lc->notify_func) (lc->pixbuf, lc->notify_user_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Called for each row; note that you will get duplicate row numbers
|
||||
for interlaced PNGs */
|
||||
static void
|
||||
png_row_callback (png_structp png_read_ptr,
|
||||
png_bytep new_row,
|
||||
png_uint_32 row_num,
|
||||
int pass_num)
|
||||
{
|
||||
LoadContext* lc;
|
||||
guchar* old_row = NULL;
|
||||
|
||||
lc = png_get_progressive_ptr(png_read_ptr);
|
||||
|
||||
if (lc->fatal_error_occurred)
|
||||
return;
|
||||
|
||||
old_row = lc->pixbuf->art_pixbuf->pixels + (row_num * lc->pixbuf->art_pixbuf->rowstride);
|
||||
|
||||
png_progressive_combine_row(lc->png_read_ptr, old_row, new_row);
|
||||
}
|
||||
|
||||
/* Called after reading the entire image */
|
||||
static void
|
||||
png_end_callback (png_structp png_read_ptr,
|
||||
png_infop png_info_ptr)
|
||||
{
|
||||
LoadContext* lc;
|
||||
|
||||
lc = png_get_progressive_ptr(png_read_ptr);
|
||||
|
||||
if (lc->fatal_error_occurred)
|
||||
return;
|
||||
|
||||
/* Doesn't do anything for now */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
png_error_callback(png_structp png_read_ptr,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
LoadContext* lc;
|
||||
|
||||
lc = png_get_error_ptr(png_read_ptr);
|
||||
|
||||
lc->fatal_error_occurred = TRUE;
|
||||
|
||||
fprintf(stderr, "Fatal error loading PNG: %s\n", error_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
png_warning_callback(png_structp png_read_ptr,
|
||||
png_const_charp warning_msg)
|
||||
{
|
||||
LoadContext* lc;
|
||||
|
||||
lc = png_get_error_ptr(png_read_ptr);
|
||||
|
||||
fprintf(stderr, "Warning loading PNG: %s\n", warning_msg);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user