|
|
|
@ -27,14 +27,17 @@
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
|
|
|
|
|
#include "gdk-pixbuf-private.h"
|
|
|
|
|
#include "gdk-pixbuf-io.h"
|
|
|
|
|
#include "gdk-pixbuf-loader.h"
|
|
|
|
|
#include "gdk-pixbuf-alias.h"
|
|
|
|
|
|
|
|
|
|
#include <glib/gstdio.h>
|
|
|
|
@ -45,6 +48,9 @@
|
|
|
|
|
#undef STRICT
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define SNIFF_BUFFER_SIZE 4096
|
|
|
|
|
#define LOAD_BUFFER_SIZE 65536
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
|
format_check (GdkPixbufModule *module, guchar *buffer, int size)
|
|
|
|
|
{
|
|
|
|
@ -755,7 +761,7 @@ _gdk_pixbuf_generic_image_load (GdkPixbufModule *module,
|
|
|
|
|
FILE *f,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
guchar buffer[4096];
|
|
|
|
|
guchar buffer[LOAD_BUFFER_SIZE];
|
|
|
|
|
size_t length;
|
|
|
|
|
GdkPixbuf *pixbuf = NULL;
|
|
|
|
|
GdkPixbufAnimation *animation = NULL;
|
|
|
|
@ -829,7 +835,7 @@ gdk_pixbuf_new_from_file (const char *filename,
|
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
int size;
|
|
|
|
|
FILE *f;
|
|
|
|
|
guchar buffer[1024];
|
|
|
|
|
guchar buffer[SNIFF_BUFFER_SIZE];
|
|
|
|
|
GdkPixbufModule *image_module;
|
|
|
|
|
gchar *display_name;
|
|
|
|
|
|
|
|
|
@ -934,49 +940,6 @@ gdk_pixbuf_new_from_file (const char *filename,
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
size_prepared_cb (GdkPixbufLoader *loader,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
struct {
|
|
|
|
|
gint width;
|
|
|
|
|
gint height;
|
|
|
|
|
gboolean preserve_aspect_ratio;
|
|
|
|
|
} *info = data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (width > 0 && height > 0);
|
|
|
|
|
|
|
|
|
|
if (info->preserve_aspect_ratio &&
|
|
|
|
|
(info->width > 0 || info->height > 0)) {
|
|
|
|
|
if (info->width < 0)
|
|
|
|
|
{
|
|
|
|
|
width = width * (double)info->height/(double)height;
|
|
|
|
|
height = info->height;
|
|
|
|
|
}
|
|
|
|
|
else if (info->height < 0)
|
|
|
|
|
{
|
|
|
|
|
height = height * (double)info->width/(double)width;
|
|
|
|
|
width = info->width;
|
|
|
|
|
}
|
|
|
|
|
else if ((double)height * (double)info->width >
|
|
|
|
|
(double)width * (double)info->height) {
|
|
|
|
|
width = 0.5 + (double)width * (double)info->height / (double)height;
|
|
|
|
|
height = info->height;
|
|
|
|
|
} else {
|
|
|
|
|
height = 0.5 + (double)height * (double)info->width / (double)width;
|
|
|
|
|
width = info->width;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (info->width > 0)
|
|
|
|
|
width = info->width;
|
|
|
|
|
if (info->height > 0)
|
|
|
|
|
height = info->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gdk_pixbuf_loader_set_size (loader, width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gdk_pixbuf_new_from_file_at_size:
|
|
|
|
@ -1037,6 +1000,52 @@ gdk_pixbuf_new_from_file_at_size (const char *filename,
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
gint width;
|
|
|
|
|
gint height;
|
|
|
|
|
gboolean preserve_aspect_ratio;
|
|
|
|
|
} AtScaleData;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
at_scale_size_prepared_cb (GdkPixbufLoader *loader,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
AtScaleData *info = data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (width > 0 && height > 0);
|
|
|
|
|
|
|
|
|
|
if (info->preserve_aspect_ratio &&
|
|
|
|
|
(info->width > 0 || info->height > 0)) {
|
|
|
|
|
if (info->width < 0)
|
|
|
|
|
{
|
|
|
|
|
width = width * (double)info->height/(double)height;
|
|
|
|
|
height = info->height;
|
|
|
|
|
}
|
|
|
|
|
else if (info->height < 0)
|
|
|
|
|
{
|
|
|
|
|
height = height * (double)info->width/(double)width;
|
|
|
|
|
width = info->width;
|
|
|
|
|
}
|
|
|
|
|
else if ((double)height * (double)info->width >
|
|
|
|
|
(double)width * (double)info->height) {
|
|
|
|
|
width = 0.5 + (double)width * (double)info->height / (double)height;
|
|
|
|
|
height = info->height;
|
|
|
|
|
} else {
|
|
|
|
|
height = 0.5 + (double)height * (double)info->width / (double)width;
|
|
|
|
|
width = info->width;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (info->width > 0)
|
|
|
|
|
width = info->width;
|
|
|
|
|
if (info->height > 0)
|
|
|
|
|
height = info->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gdk_pixbuf_loader_set_size (loader, width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gdk_pixbuf_new_from_file_at_scale:
|
|
|
|
|
* @filename: Name of file to load, in the GLib file name encoding
|
|
|
|
@ -1075,15 +1084,10 @@ gdk_pixbuf_new_from_file_at_scale (const char *filename,
|
|
|
|
|
|
|
|
|
|
GdkPixbufLoader *loader;
|
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
|
|
|
|
|
guchar buffer [4096];
|
|
|
|
|
guchar buffer[LOAD_BUFFER_SIZE];
|
|
|
|
|
int length;
|
|
|
|
|
FILE *f;
|
|
|
|
|
struct {
|
|
|
|
|
gint width;
|
|
|
|
|
gint height;
|
|
|
|
|
gboolean preserve_aspect_ratio;
|
|
|
|
|
} info;
|
|
|
|
|
AtScaleData info;
|
|
|
|
|
GdkPixbufAnimation *animation;
|
|
|
|
|
GdkPixbufAnimationIter *iter;
|
|
|
|
|
gboolean has_frame;
|
|
|
|
@ -1112,7 +1116,8 @@ gdk_pixbuf_new_from_file_at_scale (const char *filename,
|
|
|
|
|
info.height = height;
|
|
|
|
|
info.preserve_aspect_ratio = preserve_aspect_ratio;
|
|
|
|
|
|
|
|
|
|
g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info);
|
|
|
|
|
g_signal_connect (loader, "size-prepared",
|
|
|
|
|
G_CALLBACK (at_scale_size_prepared_cb), &info);
|
|
|
|
|
|
|
|
|
|
has_frame = FALSE;
|
|
|
|
|
while (!has_frame && !feof (f) && !ferror (f)) {
|
|
|
|
@ -1193,6 +1198,157 @@ gdk_pixbuf_new_from_file_at_scale (const char *filename,
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static GdkPixbuf *
|
|
|
|
|
load_from_stream (GdkPixbufLoader *loader,
|
|
|
|
|
GInputStream *stream,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
gssize n_read;
|
|
|
|
|
guchar buffer[LOAD_BUFFER_SIZE];
|
|
|
|
|
gboolean res;
|
|
|
|
|
|
|
|
|
|
res = TRUE;
|
|
|
|
|
while (1) {
|
|
|
|
|
n_read = g_input_stream_read (stream,
|
|
|
|
|
buffer,
|
|
|
|
|
sizeof (buffer),
|
|
|
|
|
cancellable,
|
|
|
|
|
error);
|
|
|
|
|
if (n_read < 0) {
|
|
|
|
|
res = FALSE;
|
|
|
|
|
error = NULL; /* Ignore further errors */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (n_read == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (!gdk_pixbuf_loader_write (loader,
|
|
|
|
|
buffer,
|
|
|
|
|
n_read,
|
|
|
|
|
error)) {
|
|
|
|
|
res = FALSE;
|
|
|
|
|
error = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!gdk_pixbuf_loader_close (loader, error)) {
|
|
|
|
|
res = FALSE;
|
|
|
|
|
error = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pixbuf = NULL;
|
|
|
|
|
if (res) {
|
|
|
|
|
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
|
|
|
|
|
if (pixbuf)
|
|
|
|
|
g_object_ref (pixbuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pixbuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gdk_pixbuf_new_from_stream_at_scale:
|
|
|
|
|
* @stream: a #GInputStream to load the pixbuf from
|
|
|
|
|
* @width: The width the image should have or -1 to not constrain the width
|
|
|
|
|
* @height: The height the image should have or -1 to not constrain the height
|
|
|
|
|
* @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
|
|
|
|
|
* @cancellable: optional #GCancellable object, %NULL to ignore
|
|
|
|
|
* @error: Return location for an error
|
|
|
|
|
*
|
|
|
|
|
* Creates a new pixbuf by loading an image from an input stream.
|
|
|
|
|
*
|
|
|
|
|
* The file format is detected automatically. If %NULL is returned, then
|
|
|
|
|
* @error will be set. The @cancellable can be used to abort the operation
|
|
|
|
|
* from another thread. If the operation was cancelled, the error
|
|
|
|
|
* %GIO_ERROR_CANCELLED will be returned. Other possible errors are in
|
|
|
|
|
* the #GDK_PIXBUF_ERROR and %G_IO_ERROR domains.
|
|
|
|
|
*
|
|
|
|
|
* The image will be scaled to fit in the requested size, optionally
|
|
|
|
|
* preserving the image's aspect ratio. When preserving the aspect ratio,
|
|
|
|
|
* a @width of -1 will cause the image to be scaled to the exact given
|
|
|
|
|
* height, and a @height of -1 will cause the image to be scaled to the
|
|
|
|
|
* exact given width. When not preserving aspect ratio, a @width or
|
|
|
|
|
* @height of -1 means to not scale the image at all in that dimension.
|
|
|
|
|
*
|
|
|
|
|
* The stream is not closed.
|
|
|
|
|
*
|
|
|
|
|
* Return value: A newly-created pixbuf, or %NULL if any of several error
|
|
|
|
|
* conditions occurred: the file could not be opened, the image format is
|
|
|
|
|
* not supported, there was not enough memory to allocate the image buffer,
|
|
|
|
|
* the stream contained invalid data, or the operation was cancelled.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.16
|
|
|
|
|
*/
|
|
|
|
|
GdkPixbuf *
|
|
|
|
|
gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
|
|
|
|
gint width,
|
|
|
|
|
gint height,
|
|
|
|
|
gboolean preserve_aspect_ratio,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GdkPixbufLoader *loader;
|
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
AtScaleData info;
|
|
|
|
|
|
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
|
|
|
|
|
|
|
|
info.width = width;
|
|
|
|
|
info.height = height;
|
|
|
|
|
info.preserve_aspect_ratio = preserve_aspect_ratio;
|
|
|
|
|
|
|
|
|
|
g_signal_connect (loader, "size-prepared",
|
|
|
|
|
G_CALLBACK (at_scale_size_prepared_cb), &info);
|
|
|
|
|
|
|
|
|
|
pixbuf = load_from_stream (loader, stream, cancellable, error);
|
|
|
|
|
g_object_unref (loader);
|
|
|
|
|
|
|
|
|
|
return pixbuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gdk_pixbuf_new_from_stream:
|
|
|
|
|
* @stream: a #GInputStream to load the pixbuf from
|
|
|
|
|
* @cancellable: optional #GCancellable object, %NULL to ignore
|
|
|
|
|
* @error: Return location for an error
|
|
|
|
|
*
|
|
|
|
|
* Creates a new pixbuf by loading an image from an input stream.
|
|
|
|
|
*
|
|
|
|
|
* The file format is detected automatically. If %NULL is returned, then
|
|
|
|
|
* @error will be set. The @cancellable can be used to abort the operation
|
|
|
|
|
* from another thread. If the operation was cancelled, the error
|
|
|
|
|
* %GIO_ERROR_CANCELLED will be returned. Other possible errors are in
|
|
|
|
|
* the #GDK_PIXBUF_ERROR and %G_IO_ERROR domains.
|
|
|
|
|
*
|
|
|
|
|
* The stream is not closed.
|
|
|
|
|
*
|
|
|
|
|
* Return value: A newly-created pixbuf, or %NULL if any of several error
|
|
|
|
|
* conditions occurred: the file could not be opened, the image format is
|
|
|
|
|
* not supported, there was not enough memory to allocate the image buffer,
|
|
|
|
|
* the stream contained invalid data, or the operation was cancelled.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.16
|
|
|
|
|
**/
|
|
|
|
|
GdkPixbuf *
|
|
|
|
|
gdk_pixbuf_new_from_stream (GInputStream *stream,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
|
GdkPixbufLoader *loader;
|
|
|
|
|
|
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
|
|
|
pixbuf = load_from_stream (loader, stream, cancellable, error);
|
|
|
|
|
g_object_unref (loader);
|
|
|
|
|
|
|
|
|
|
return pixbuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
info_cb (GdkPixbufLoader *loader,
|
|
|
|
|
int width,
|
|
|
|
@ -1234,7 +1390,7 @@ gdk_pixbuf_get_file_info (const gchar *filename,
|
|
|
|
|
gint *height)
|
|
|
|
|
{
|
|
|
|
|
GdkPixbufLoader *loader;
|
|
|
|
|
guchar buffer [4096];
|
|
|
|
|
guchar buffer[SNIFF_BUFFER_SIZE];
|
|
|
|
|
int length;
|
|
|
|
|
FILE *f;
|
|
|
|
|
struct {
|
|
|
|
@ -1579,18 +1735,18 @@ gdk_pixbuf_real_save_to_callback (GdkPixbuf *pixbuf,
|
|
|
|
|
* 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 *formats = gdk_pixbuf_get_formats ();
|
|
|
|
|
* GSList *writable_formats = NULL;
|
|
|
|
|
* g_slist_foreach (formats, add_if_writable, &writable_formats);
|
|
|
|
|
* 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.
|
|
|
|
@ -1999,7 +2155,8 @@ save_to_buffer_callback (const gchar *data,
|
|
|
|
|
* @error: return location for error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
|
|
|
|
|
* "tiff", "png", "ico" or "bmp". See gdk_pixbuf_save_to_buffer() for more details.
|
|
|
|
|
* "tiff", "png", "ico" or "bmp". See gdk_pixbuf_save_to_buffer()
|
|
|
|
|
* for more details.
|
|
|
|
|
*
|
|
|
|
|
* Return value: whether an error was set
|
|
|
|
|
*
|
|
|
|
@ -2044,6 +2201,87 @@ gdk_pixbuf_save_to_bufferv (GdkPixbuf *pixbuf,
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GOutputStream *stream;
|
|
|
|
|
GCancellable *cancellable;
|
|
|
|
|
} SaveToStreamData;
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
save_to_stream (const gchar *buffer,
|
|
|
|
|
gsize count,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
SaveToStreamData *sdata = (SaveToStreamData *)data;
|
|
|
|
|
|
|
|
|
|
g_output_stream_write (sdata->stream,
|
|
|
|
|
buffer, count,
|
|
|
|
|
sdata->cancellable,
|
|
|
|
|
error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gdk_pixbuf_save_to_stream:
|
|
|
|
|
* @pixbuf: a #GdkPixbuf
|
|
|
|
|
* @stream: a #GOutputStream to save the pixbuf to
|
|
|
|
|
* @type: name of file format
|
|
|
|
|
* @cancellable: optional #GCancellable object, %NULL to ignore
|
|
|
|
|
* @error: return location for error, or %NULL
|
|
|
|
|
* @Varargs: list of key-value save options
|
|
|
|
|
*
|
|
|
|
|
* Saves @pixbuf to an output stream.
|
|
|
|
|
*
|
|
|
|
|
* Supported file formats are currently "jpeg", "tiff", "png", "ico" or
|
|
|
|
|
* "bmp". See gdk_pixbuf_save_to_buffer() for more details.
|
|
|
|
|
*
|
|
|
|
|
* The @cancellable can be used to abort the operation from another
|
|
|
|
|
* thread. If the operation was cancelled, the error %GIO_ERROR_CANCELLED
|
|
|
|
|
* will be returned. Other possible errors are in the #GDK_PIXBUF_ERROR
|
|
|
|
|
* and %G_IO_ERROR domains.
|
|
|
|
|
*
|
|
|
|
|
* The stream is not closed.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the pixbuf was saved successfully, %FALSE if an
|
|
|
|
|
* error was set.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.16
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
gdk_pixbuf_save_to_stream (GdkPixbuf *pixbuf,
|
|
|
|
|
GOutputStream *stream,
|
|
|
|
|
const char *type,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error,
|
|
|
|
|
...)
|
|
|
|
|
{
|
|
|
|
|
gboolean res;
|
|
|
|
|
gchar **keys = NULL;
|
|
|
|
|
gchar **values = NULL;
|
|
|
|
|
va_list args;
|
|
|
|
|
SaveToStreamData data;
|
|
|
|
|
|
|
|
|
|
va_start (args, error);
|
|
|
|
|
collect_save_options (args, &keys, &values);
|
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
|
|
data.stream = stream;
|
|
|
|
|
data.cancellable = cancellable;
|
|
|
|
|
|
|
|
|
|
if (!gdk_pixbuf_save_to_callbackv (pixbuf, save_to_stream,
|
|
|
|
|
&data, type,
|
|
|
|
|
keys, values,
|
|
|
|
|
error)) {
|
|
|
|
|
error = NULL; /* Ignore further errors */
|
|
|
|
|
res = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_strfreev (keys);
|
|
|
|
|
g_strfreev (values);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gdk_pixbuf_format_get_name:
|
|
|
|
|
* @format: a #GdkPixbufFormat
|
|
|
|
|