mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-20 05:50:11 +00:00
New public API to save pixbufs to non-file locations. (#82203, Tim Evans)
Wed Jan 7 02:41:14 2004 Matthias Clasen <maclas@gmx.de> * gdk-pixbuf-io.c (gdk_pixbuf_save_to_bufferv): * gdk-pixbuf-io.c (gdk_pixbuf_save_to_buffer): * gdk-pixbuf-io.c (gdk_pixbuf_save_to_callbackv): * gdk-pixbuf-io.c (gdk_pixbuf_save_to_callback): New public API to save pixbufs to non-file locations. (#82203, Tim Evans) * gdk-pixbuf.h: * gdk_pixbuf.def: Declare the new public API. * gdk-pixbuf-io.h: Add save_to_callback to the module interface. * io-jpeg.c: * io-png.c: Implement save_to_callback. * gdk-pixbuf-io.c (gdk_pixbuf_savev): * gdk-pixbuf-io.c (gdk_pixbuf_save): Update documentation. * gdk-pixbuf-io.c (gdk_pixbuf_real_save): Support saving via image_module->save_to_callback. * gdk-pixbuf-io.c (gdk_pixbuf_real_save_to_callback): New generic save_to_callback function which falls back to image_module->save on a temp file.
This commit is contained in:
parent
5b26e695a1
commit
03376d79fa
@ -1,3 +1,29 @@
|
||||
Wed Jan 7 02:41:14 2004 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_save_to_bufferv):
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_save_to_buffer):
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_save_to_callbackv):
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_save_to_callback): New public API
|
||||
to save pixbufs to non-file locations. (#82203, Tim Evans)
|
||||
|
||||
* gdk-pixbuf.h:
|
||||
* gdk-pixbuf.def: Declare the new public API.
|
||||
|
||||
* gdk-pixbuf-io.h: Add save_to_callback to the module interface.
|
||||
|
||||
* io-jpeg.c:
|
||||
* io-png.c: Implement save_to_callback.
|
||||
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_savev):
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_save): Update documentation.
|
||||
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_real_save): Support saving via
|
||||
image_module->save_to_callback.
|
||||
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_real_save_to_callback): New generic
|
||||
save_to_callback function which falls back to image_module->save
|
||||
on a temp file.
|
||||
|
||||
Wed Jan 7 01:17:36 2004 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_size_func):
|
||||
|
@ -1073,6 +1073,27 @@ collect_save_options (va_list opts,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
save_to_file_callback (const gchar *buf,
|
||||
gsize count,
|
||||
GError **error,
|
||||
gpointer data)
|
||||
{
|
||||
FILE *filehandle = data;
|
||||
gsize n;
|
||||
|
||||
n = fwrite (buf, 1, count, filehandle);
|
||||
if (n != count) {
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errno),
|
||||
_("Error writing to image file: %s"),
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
|
||||
FILE *filehandle,
|
||||
@ -1092,7 +1113,137 @@ gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
|
||||
if (!_gdk_pixbuf_load_module (image_module, error))
|
||||
return FALSE;
|
||||
|
||||
if (image_module->save == NULL) {
|
||||
if (image_module->save) {
|
||||
/* save normally */
|
||||
return (* image_module->save) (filehandle, pixbuf,
|
||||
keys, values,
|
||||
error);
|
||||
}
|
||||
else if (image_module->save_to_callback) {
|
||||
/* save with simple callback */
|
||||
return (* image_module->save_to_callback) (save_to_file_callback,
|
||||
filehandle, pixbuf,
|
||||
keys, values,
|
||||
error);
|
||||
}
|
||||
else {
|
||||
/* can't save */
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
|
||||
_("This build of gdk-pixbuf does not support saving the image format: %s"),
|
||||
type);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#define TMP_FILE_BUF_SIZE 4096
|
||||
|
||||
static gboolean
|
||||
save_to_callback_with_tmp_file (GdkPixbufModule *image_module,
|
||||
GdkPixbuf *pixbuf,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
int fd;
|
||||
FILE *f = NULL;
|
||||
gboolean retval = FALSE;
|
||||
gchar *buf = NULL;
|
||||
gsize n;
|
||||
gchar *filename = NULL;
|
||||
|
||||
buf = g_try_malloc (TMP_FILE_BUF_SIZE);
|
||||
if (buf == NULL) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
|
||||
_("Insufficient memory to save image to callback"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
fd = g_file_open_tmp ("gdkpixbuf-save-tmp.XXXXXX", &filename, error);
|
||||
if (fd == -1)
|
||||
goto end;
|
||||
f = fdopen (fd, "wb+");
|
||||
if (f == NULL) {
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errno),
|
||||
_("Failed to open temporary file"));
|
||||
goto end;
|
||||
}
|
||||
if (!(* image_module->save) (f, pixbuf, keys, values, error))
|
||||
goto end;
|
||||
rewind (f);
|
||||
for (;;) {
|
||||
n = fread (buf, 1, TMP_FILE_BUF_SIZE, f);
|
||||
if (n > 0) {
|
||||
if (!save_func (buf, n, error, user_data))
|
||||
goto end;
|
||||
}
|
||||
if (n != TMP_FILE_BUF_SIZE)
|
||||
break;
|
||||
}
|
||||
if (ferror (f)) {
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errno),
|
||||
_("Failed to read from temporary file"));
|
||||
goto end;
|
||||
}
|
||||
retval = TRUE;
|
||||
|
||||
end:
|
||||
/* cleanup and return retval */
|
||||
if (f)
|
||||
fclose (f);
|
||||
if (filename) {
|
||||
unlink (filename);
|
||||
g_free (filename);
|
||||
}
|
||||
g_free (buf);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf_real_save_to_callback (GdkPixbuf *pixbuf,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
const char *type,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
GdkPixbufModule *image_module = NULL;
|
||||
|
||||
image_module = _gdk_pixbuf_get_named_module (type, error);
|
||||
|
||||
if (image_module == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (image_module->module == NULL)
|
||||
if (!_gdk_pixbuf_load_module (image_module, error))
|
||||
return FALSE;
|
||||
|
||||
if (image_module->save_to_callback) {
|
||||
/* save normally */
|
||||
return (* image_module->save_to_callback) (save_func, user_data,
|
||||
pixbuf, keys, values,
|
||||
error);
|
||||
}
|
||||
else if (image_module->save) {
|
||||
/* use a temporary file */
|
||||
return save_to_callback_with_tmp_file (image_module, pixbuf,
|
||||
save_func, user_data,
|
||||
keys, values,
|
||||
error);
|
||||
}
|
||||
else {
|
||||
/* can't save */
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
|
||||
@ -1100,10 +1251,6 @@ gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
|
||||
type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (* image_module->save) (filehandle, pixbuf,
|
||||
keys, values,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
@ -1115,8 +1262,25 @@ gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
|
||||
* @error: return location for error, or %NULL
|
||||
* @Varargs: list of key-value save options
|
||||
*
|
||||
* Saves pixbuf to a file in @type, which is currently "jpeg", "png" or
|
||||
* "ico". If @error is set, %FALSE will be returned. Possible errors include
|
||||
* Saves pixbuf to a file in format @type. By default, "jpeg", "png" and
|
||||
* "ico" are possible file formats to save in, but more formats may be
|
||||
* installed. The list of all writable formats can be determined in the
|
||||
* following way:
|
||||
*
|
||||
* <informalexample><programlisting>
|
||||
* void add_if_writable (GdkPixbufFormat *data, GSList **list)
|
||||
* {
|
||||
* if (gdk_pixbuf_format_is_writable (data))
|
||||
* *list = g_slist_prepend (*list, data);
|
||||
* }
|
||||
*
|
||||
* GSList *formats = gdk_pixbuf_get_formats (<!-- -->);
|
||||
* GSList *writable_formats = NULL;
|
||||
* g_slist_foreach (formats, add_if_writable, &writable_formats);
|
||||
* g_slist_free (formats);
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
* If @error is set, %FALSE will be returned. Possible errors include
|
||||
* those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
|
||||
*
|
||||
* The variable argument list should be %NULL-terminated; if not empty,
|
||||
@ -1178,9 +1342,9 @@ gdk_pixbuf_save (GdkPixbuf *pixbuf,
|
||||
* @option_values: values for named options
|
||||
* @error: return location for error, or %NULL
|
||||
*
|
||||
* Saves pixbuf to a file in @type, which is currently "jpeg" or "png".
|
||||
* If @error is set, %FALSE will be returned. See gdk_pixbuf_save () for more
|
||||
* details.
|
||||
* Saves pixbuf to a file in @type, which is currently "jpeg", "png" or "ico".
|
||||
* If @error is set, %FALSE will be returned.
|
||||
* See gdk_pixbuf_save () for more details.
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
**/
|
||||
@ -1236,6 +1400,251 @@ gdk_pixbuf_savev (GdkPixbuf *pixbuf,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_save_to_callback:
|
||||
* @pixbuf: a #GdkPixbuf.
|
||||
* @save_func: a function that is called to save each block of data that
|
||||
* the save routine generates.
|
||||
* @user_data: user data to pass to the save function.
|
||||
* @type: name of file format.
|
||||
* @error: return location for error, or %NULL
|
||||
* @Varargs: list of key-value save options
|
||||
*
|
||||
* Saves pixbuf in format @type by feeding the produced data to a
|
||||
* callback. Can be used when you want to store the image to something
|
||||
* other than a file, such as an in-memory buffer or a socket.
|
||||
* If @error is set, %FALSE will be returned. Possible errors
|
||||
* include those in the #GDK_PIXBUF_ERROR domain and whatever the save
|
||||
* function generates.
|
||||
*
|
||||
* See gdk_pixbuf_save() for more details.
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_pixbuf_save_to_callback (GdkPixbuf *pixbuf,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
const char *type,
|
||||
GError **error,
|
||||
...)
|
||||
{
|
||||
gchar **keys = NULL;
|
||||
gchar **values = NULL;
|
||||
va_list args;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
va_start (args, error);
|
||||
|
||||
collect_save_options (args, &keys, &values);
|
||||
|
||||
va_end (args);
|
||||
|
||||
result = gdk_pixbuf_save_to_callbackv (pixbuf, save_func, user_data,
|
||||
type, keys, values,
|
||||
error);
|
||||
|
||||
g_strfreev (keys);
|
||||
g_strfreev (values);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_save_to_callbackv:
|
||||
* @pixbuf: a #GdkPixbuf.
|
||||
* @save_func: a function that is called to save each block of data that
|
||||
* the save routine generates.
|
||||
* @user_data: user data to pass to the save function.
|
||||
* @type: name of file format.
|
||||
* @option_keys: name of options to set, %NULL-terminated
|
||||
* @option_values: values for named options
|
||||
* @error: return location for error, or %NULL
|
||||
*
|
||||
* Saves pixbuf to a callback in format @type, which is currently "jpeg",
|
||||
* "png" or "ico". If @error is set, %FALSE will be returned. See
|
||||
* gdk_pixbuf_save_to_callback () for more details.
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_pixbuf_save_to_callbackv (GdkPixbuf *pixbuf,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
const char *type,
|
||||
char **option_keys,
|
||||
char **option_values,
|
||||
GError **error)
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
|
||||
g_return_val_if_fail (save_func != NULL, FALSE);
|
||||
g_return_val_if_fail (type != NULL, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
result = gdk_pixbuf_real_save_to_callback (pixbuf,
|
||||
save_func, user_data, type,
|
||||
option_keys, option_values,
|
||||
error);
|
||||
|
||||
if (!result) {
|
||||
g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_save_to_buffer:
|
||||
* @pixbuf: a #GdkPixbuf.
|
||||
* @buffer: location to receive a pointer to the new buffer.
|
||||
* @buffer_size: location to receive the size of the new buffer.
|
||||
* @type: name of file format.
|
||||
* @error: return location for error, or %NULL
|
||||
* @Varargs: list of key-value save options
|
||||
*
|
||||
* Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
|
||||
* "png" or "ico". This is a convenience function that uses
|
||||
* gdk_pixbuf_save_to_callback() to do the real work. Note that the buffer
|
||||
* is not nul-terminated and may contain embedded nuls.
|
||||
* If @error is set, %FALSE will be returned and @string will be set to
|
||||
* %NULL. Possible errors include those in the #GDK_PIXBUF_ERROR
|
||||
* domain.
|
||||
*
|
||||
* See gdk_pixbuf_save() for more details.
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_pixbuf_save_to_buffer (GdkPixbuf *pixbuf,
|
||||
gchar **buffer,
|
||||
gsize *buffer_size,
|
||||
const char *type,
|
||||
GError **error,
|
||||
...)
|
||||
{
|
||||
gchar **keys = NULL;
|
||||
gchar **values = NULL;
|
||||
va_list args;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
va_start (args, error);
|
||||
|
||||
collect_save_options (args, &keys, &values);
|
||||
|
||||
va_end (args);
|
||||
|
||||
result = gdk_pixbuf_save_to_bufferv (pixbuf, buffer, buffer_size,
|
||||
type, keys, values,
|
||||
error);
|
||||
|
||||
g_strfreev (keys);
|
||||
g_strfreev (values);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct SaveToBufferData {
|
||||
gchar *buffer;
|
||||
gsize len, max;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
save_to_buffer_callback (const gchar *data,
|
||||
gsize count,
|
||||
GError **error,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct SaveToBufferData *sdata = user_data;
|
||||
gchar *new_buffer;
|
||||
gsize new_max;
|
||||
|
||||
if (sdata->len + count > sdata->max) {
|
||||
new_max = MAX (sdata->max*2, sdata->len + count);
|
||||
new_buffer = g_try_realloc (sdata->buffer, new_max);
|
||||
if (!new_buffer) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
|
||||
_("Insufficient memory to save image into a buffer"));
|
||||
return FALSE;
|
||||
}
|
||||
sdata->buffer = new_buffer;
|
||||
sdata->max = new_max;
|
||||
}
|
||||
memcpy (sdata->buffer + sdata->len, data, count);
|
||||
sdata->len += count;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_save_to_bufferv:
|
||||
* @pixbuf: a #GdkPixbuf.
|
||||
* @buffer: location to receive a pointer to the new buffer.
|
||||
* @buffer_size: location to receive the size of the new buffer.
|
||||
* @type: name of file format.
|
||||
* @option_keys: name of options to set, %NULL-terminated
|
||||
* @option_values: values for named options
|
||||
* @error: return location for error, or %NULL
|
||||
*
|
||||
* Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
|
||||
* "png" or "ico". See gdk_pixbuf_save_to_buffer() for more details.
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_pixbuf_save_to_bufferv (GdkPixbuf *pixbuf,
|
||||
gchar **buffer,
|
||||
gsize *buffer_size,
|
||||
const char *type,
|
||||
char **option_keys,
|
||||
char **option_values,
|
||||
GError **error)
|
||||
{
|
||||
static const gint initial_max = 1024;
|
||||
struct SaveToBufferData sdata;
|
||||
|
||||
*buffer = NULL;
|
||||
*buffer_size = 0;
|
||||
|
||||
sdata.buffer = g_try_malloc (initial_max);
|
||||
sdata.max = initial_max;
|
||||
sdata.len = 0;
|
||||
if (!sdata.buffer) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
|
||||
_("Insufficient memory to save image into a buffer"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gdk_pixbuf_save_to_callbackv (pixbuf,
|
||||
save_to_buffer_callback, &sdata,
|
||||
type, option_keys, option_values,
|
||||
error)) {
|
||||
g_free (sdata.buffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*buffer = sdata.buffer;
|
||||
*buffer_size = sdata.len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_format_get_name:
|
||||
* @format: a #GdkPixbufFormat
|
||||
|
@ -89,11 +89,19 @@ struct _GdkPixbufModule {
|
||||
GdkPixbufAnimation *(* load_animation) (FILE *f,
|
||||
GError **error);
|
||||
|
||||
/* Saving */
|
||||
gboolean (* save) (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **param_keys,
|
||||
gchar **param_values,
|
||||
GError **error);
|
||||
|
||||
gboolean (*save_to_callback) (GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **option_keys,
|
||||
gchar **option_values,
|
||||
GError **error);
|
||||
|
||||
/*< private >*/
|
||||
void (*_reserved1) (void);
|
||||
@ -101,7 +109,6 @@ struct _GdkPixbufModule {
|
||||
void (*_reserved3) (void);
|
||||
void (*_reserved4) (void);
|
||||
void (*_reserved5) (void);
|
||||
void (*_reserved6) (void);
|
||||
|
||||
};
|
||||
|
||||
@ -116,7 +123,7 @@ gboolean gdk_pixbuf_set_option (GdkPixbuf *pixbuf,
|
||||
|
||||
typedef enum /*< skip >*/
|
||||
{
|
||||
GDK_PIXBUF_FORMAT_WRITABLE = 1 << 0
|
||||
GDK_PIXBUF_FORMAT_WRITABLE = 1 << 0,
|
||||
} GdkPixbufFormatFlags;
|
||||
|
||||
struct _GdkPixbufFormat {
|
||||
|
@ -225,7 +225,6 @@ gdk_pixbuf_loader_finalize (GObject *object)
|
||||
|
||||
if (!priv->closed)
|
||||
g_warning ("GdkPixbufLoader finalized without calling gdk_pixbuf_loader_close() - this is not allowed. You must explicitly end the data stream to the loader before dropping the last reference.");
|
||||
|
||||
if (priv->animation)
|
||||
g_object_unref (priv->animation);
|
||||
|
||||
|
@ -170,6 +170,45 @@ gboolean gdk_pixbuf_savev (GdkPixbuf *pixbuf,
|
||||
char **option_values,
|
||||
GError **error);
|
||||
|
||||
/* Saving to a callback function */
|
||||
|
||||
typedef gboolean (*GdkPixbufSaveFunc) (const gchar *buf,
|
||||
gsize count,
|
||||
GError **error,
|
||||
gpointer data);
|
||||
|
||||
gboolean gdk_pixbuf_save_to_callback (GdkPixbuf *pixbuf,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
const char *type,
|
||||
GError **error,
|
||||
...);
|
||||
|
||||
gboolean gdk_pixbuf_save_to_callbackv (GdkPixbuf *pixbuf,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
const char *type,
|
||||
char **option_keys,
|
||||
char **option_values,
|
||||
GError **error);
|
||||
|
||||
/* Saving into a newly allocated char array */
|
||||
|
||||
gboolean gdk_pixbuf_save_to_buffer (GdkPixbuf *pixbuf,
|
||||
gchar **buffer,
|
||||
gsize *buffer_size,
|
||||
const char *type,
|
||||
GError **error,
|
||||
...);
|
||||
|
||||
gboolean gdk_pixbuf_save_to_bufferv (GdkPixbuf *pixbuf,
|
||||
gchar **buffer,
|
||||
gsize *buffer_size,
|
||||
const char *type,
|
||||
char **option_keys,
|
||||
char **option_values,
|
||||
GError **error);
|
||||
|
||||
/* Adding an alpha channel */
|
||||
GdkPixbuf *gdk_pixbuf_add_alpha (const GdkPixbuf *pixbuf, gboolean substitute_color,
|
||||
guchar r, guchar g, guchar b);
|
||||
|
@ -33,6 +33,7 @@ EXPORTS
|
||||
gdk_pixbuf_from_pixdata
|
||||
gdk_pixbuf_get_bits_per_sample
|
||||
gdk_pixbuf_get_colorspace
|
||||
gdk_pixbuf_get_file_info
|
||||
gdk_pixbuf_get_formats
|
||||
gdk_pixbuf_get_has_alpha
|
||||
gdk_pixbuf_get_height
|
||||
@ -60,6 +61,10 @@ EXPORTS
|
||||
gdk_pixbuf_ref
|
||||
gdk_pixbuf_saturate_and_pixelate
|
||||
gdk_pixbuf_save
|
||||
gdk_pixbuf_save_to_callback
|
||||
gdk_pixbuf_save_to_callbackv
|
||||
gdk_pixbuf_save_to_buffer
|
||||
gdk_pixbuf_save_to_bufferv
|
||||
gdk_pixbuf_savev
|
||||
gdk_pixbuf_scale
|
||||
gdk_pixbuf_scale_simple
|
||||
|
@ -780,12 +780,85 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Save */
|
||||
|
||||
#define TO_FUNCTION_BUF_SIZE 4096
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_destination_mgr pub;
|
||||
JOCTET *buffer;
|
||||
GdkPixbufSaveFunc save_func;
|
||||
gpointer user_data;
|
||||
GError **error;
|
||||
} ToFunctionDestinationManager;
|
||||
|
||||
void
|
||||
to_callback_init (j_compress_ptr cinfo)
|
||||
{
|
||||
ToFunctionDestinationManager *destmgr;
|
||||
|
||||
destmgr = (ToFunctionDestinationManager*) cinfo->dest;
|
||||
destmgr->pub.next_output_byte = destmgr->buffer;
|
||||
destmgr->pub.free_in_buffer = TO_FUNCTION_BUF_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
to_callback_do_write (j_compress_ptr cinfo, gsize length)
|
||||
{
|
||||
ToFunctionDestinationManager *destmgr;
|
||||
|
||||
destmgr = (ToFunctionDestinationManager*) cinfo->dest;
|
||||
if (!destmgr->save_func (destmgr->buffer,
|
||||
length,
|
||||
destmgr->error,
|
||||
destmgr->user_data)) {
|
||||
struct error_handler_data *errmgr;
|
||||
|
||||
errmgr = (struct error_handler_data *) cinfo->err;
|
||||
/* Use a default error message if the callback didn't set one,
|
||||
* which it should have.
|
||||
*/
|
||||
if (errmgr->error && *errmgr->error == NULL) {
|
||||
g_set_error (errmgr->error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
|
||||
"write function failed");
|
||||
}
|
||||
siglongjmp (errmgr->setjmp_buffer, 1);
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static guchar
|
||||
to_callback_empty_output_buffer (j_compress_ptr cinfo)
|
||||
{
|
||||
ToFunctionDestinationManager *destmgr;
|
||||
|
||||
destmgr = (ToFunctionDestinationManager*) cinfo->dest;
|
||||
to_callback_do_write (cinfo, TO_FUNCTION_BUF_SIZE);
|
||||
destmgr->pub.next_output_byte = destmgr->buffer;
|
||||
destmgr->pub.free_in_buffer = TO_FUNCTION_BUF_SIZE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
to_callback_terminate (j_compress_ptr cinfo)
|
||||
{
|
||||
ToFunctionDestinationManager *destmgr;
|
||||
|
||||
destmgr = (ToFunctionDestinationManager*) cinfo->dest;
|
||||
to_callback_do_write (cinfo, TO_FUNCTION_BUF_SIZE - destmgr->pub.free_in_buffer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
real_save_jpeg (GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error,
|
||||
gboolean to_callback,
|
||||
FILE *f,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* FIXME error handling is broken */
|
||||
|
||||
@ -800,6 +873,9 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
int w, h = 0;
|
||||
int rowstride = 0;
|
||||
struct error_handler_data jerr;
|
||||
ToFunctionDestinationManager to_callback_destmgr;
|
||||
|
||||
to_callback_destmgr.buffer = NULL;
|
||||
|
||||
if (keys && *keys) {
|
||||
gchar **kiter = keys;
|
||||
@ -854,7 +930,9 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
g_return_val_if_fail (pixels != NULL, FALSE);
|
||||
|
||||
/* allocate a small buffer to convert image data */
|
||||
/* Allocate a small buffer to convert image data,
|
||||
* and a larger buffer if doing to_callback save.
|
||||
*/
|
||||
buf = g_try_malloc (w * 3 * sizeof (guchar));
|
||||
if (!buf) {
|
||||
g_set_error (error,
|
||||
@ -863,6 +941,16 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
_("Couldn't allocate memory for loading JPEG file"));
|
||||
return FALSE;
|
||||
}
|
||||
if (to_callback) {
|
||||
to_callback_destmgr.buffer = g_try_malloc (TO_FUNCTION_BUF_SIZE);
|
||||
if (!to_callback_destmgr.buffer) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
|
||||
_("Couldn't allocate memory for loading JPEG file"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* set up error handling */
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
@ -873,12 +961,23 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
if (sigsetjmp (jerr.setjmp_buffer, 1)) {
|
||||
jpeg_destroy_compress (&cinfo);
|
||||
g_free (buf);
|
||||
g_free (to_callback_destmgr.buffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* setup compress params */
|
||||
jpeg_create_compress (&cinfo);
|
||||
jpeg_stdio_dest (&cinfo, f);
|
||||
if (to_callback) {
|
||||
to_callback_destmgr.pub.init_destination = to_callback_init;
|
||||
to_callback_destmgr.pub.empty_output_buffer = to_callback_empty_output_buffer;
|
||||
to_callback_destmgr.pub.term_destination = to_callback_terminate;
|
||||
to_callback_destmgr.error = error;
|
||||
to_callback_destmgr.save_func = save_func;
|
||||
to_callback_destmgr.user_data = user_data;
|
||||
cinfo.dest = (struct jpeg_destination_mgr*) &to_callback_destmgr;
|
||||
} else {
|
||||
jpeg_stdio_dest (&cinfo, f);
|
||||
}
|
||||
cinfo.image_width = w;
|
||||
cinfo.image_height = h;
|
||||
cinfo.input_components = 3;
|
||||
@ -909,9 +1008,33 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
jpeg_finish_compress (&cinfo);
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
g_free (buf);
|
||||
g_free (to_callback_destmgr.buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
return real_save_jpeg (pixbuf, keys, values, error,
|
||||
FALSE, f, NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf__jpeg_image_save_to_callback (GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
return real_save_jpeg (pixbuf, keys, values, error,
|
||||
TRUE, NULL, save_func, user_data);
|
||||
}
|
||||
|
||||
void
|
||||
MODULE_ENTRY (jpeg, fill_vtable) (GdkPixbufModule *module)
|
||||
{
|
||||
@ -920,6 +1043,7 @@ MODULE_ENTRY (jpeg, fill_vtable) (GdkPixbufModule *module)
|
||||
module->stop_load = gdk_pixbuf__jpeg_image_stop_load;
|
||||
module->load_increment = gdk_pixbuf__jpeg_image_load_increment;
|
||||
module->save = gdk_pixbuf__jpeg_image_save;
|
||||
module->save_to_callback = gdk_pixbuf__jpeg_image_save_to_callback;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -741,12 +741,40 @@ png_warning_callback(png_structp png_read_ptr,
|
||||
|
||||
/* Save */
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf__png_image_save (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
typedef struct {
|
||||
GdkPixbufSaveFunc save_func;
|
||||
gpointer user_data;
|
||||
GError **error;
|
||||
} SaveToFunctionIoPtr;
|
||||
|
||||
static void
|
||||
png_save_to_callback_write_func (png_structp png_ptr,
|
||||
png_bytep data,
|
||||
png_size_t length)
|
||||
{
|
||||
SaveToFunctionIoPtr *ioptr = png_get_io_ptr (png_ptr);
|
||||
|
||||
if (!ioptr->save_func (data, length, ioptr->error, ioptr->user_data)) {
|
||||
/* If save_func has already set an error, which it
|
||||
should have done, this won't overwrite it. */
|
||||
png_error (png_ptr, "write function failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
png_save_to_callback_flush_func (png_structp png_ptr)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static gboolean real_save_png (GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error,
|
||||
gboolean to_callback,
|
||||
FILE *f,
|
||||
GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
@ -762,6 +790,7 @@ gdk_pixbuf__png_image_save (FILE *f,
|
||||
int bpc;
|
||||
int num_keys;
|
||||
gboolean success = TRUE;
|
||||
SaveToFunctionIoPtr to_callback_ioptr;
|
||||
|
||||
num_keys = 0;
|
||||
|
||||
@ -860,7 +889,16 @@ gdk_pixbuf__png_image_save (FILE *f,
|
||||
png_set_text (png_ptr, info_ptr, text_ptr, num_keys);
|
||||
}
|
||||
|
||||
png_init_io (png_ptr, f);
|
||||
if (to_callback) {
|
||||
to_callback_ioptr.save_func = save_func;
|
||||
to_callback_ioptr.user_data = user_data;
|
||||
to_callback_ioptr.error = error;
|
||||
png_set_write_fn (png_ptr, &to_callback_ioptr,
|
||||
png_save_to_callback_write_func,
|
||||
png_save_to_callback_flush_func);
|
||||
} else {
|
||||
png_init_io (png_ptr, f);
|
||||
}
|
||||
|
||||
if (has_alpha) {
|
||||
png_set_IHDR (png_ptr, info_ptr, w, h, bpc,
|
||||
@ -901,6 +939,29 @@ cleanup:
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf__png_image_save (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
return real_save_png (pixbuf, keys, values, error,
|
||||
FALSE, f, NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf__png_image_save_to_callback (GdkPixbufSaveFunc save_func,
|
||||
gpointer user_data,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
return real_save_png (pixbuf, keys, values, error,
|
||||
TRUE, NULL, save_func, user_data);
|
||||
}
|
||||
|
||||
void
|
||||
MODULE_ENTRY (png, fill_vtable) (GdkPixbufModule *module)
|
||||
{
|
||||
@ -909,6 +970,7 @@ MODULE_ENTRY (png, fill_vtable) (GdkPixbufModule *module)
|
||||
module->stop_load = gdk_pixbuf__png_image_stop_load;
|
||||
module->load_increment = gdk_pixbuf__png_image_load_increment;
|
||||
module->save = gdk_pixbuf__png_image_save;
|
||||
module->save_to_callback = gdk_pixbuf__png_image_save_to_callback;
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user