mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 02:40:11 +00:00
Pixbuf saving, patch from David Welton.
2000-10-05 Havoc Pennington <hp@redhat.com> Pixbuf saving, patch from David Welton. * Makefile.am (GDK_PIXBUF_LIBS): add INTLLIBS (libgdk_pixbuf_1_3_la_SOURCES): add gdk-pixbuf-i18n.h * gdk-pixbuf-i18n.h: Add _() to gdk-pixbuf * io-png.c (gdk_pixbuf__png_image_save): PNG save routine. * io-jpeg.c (gdk_pixbuf__jpeg_image_save): JPEG save routine. * gdk-pixbuf-io.c (gdk_pixbuf_save): (gdk_pixbuf_savev): Implement pixbuf saving routines * gdk-pixbuf.c (gdk_pixbuf_error_quark): pixbuf error quark function * gdk-pixbuf.h: Add public save routines; add pixbuf error types * gdk-pixbuf-io.h: Add save function to GdkPixbufModule 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test * demos/Makefile.am: add testpixbuf-save.c
This commit is contained in:
parent
a7e20093e9
commit
6b9f907270
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -1,3 +1,9 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* demos/testpixbuf-save.c: add pixbuf save test
|
||||
|
||||
* demos/Makefile.am: add testpixbuf-save.c
|
||||
|
||||
2000-10-05 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gtk/gtktree.h (GTK_TREE_SELECTION): Replaced with
|
||||
|
@ -34,6 +34,7 @@ noinst_PROGRAMS = \
|
||||
testpixbuf \
|
||||
testpixbuf-drawable \
|
||||
testanimation \
|
||||
testpixbuf-save \
|
||||
testpixbuf-scale \
|
||||
pixbuf-demo
|
||||
|
||||
@ -44,18 +45,21 @@ test-inline-pixbufs.h: $(top_builddir)/gdk-pixbuf/make-inline-pixbuf apple-red.p
|
||||
|
||||
testpixbuf_DEPENDENCIES = $(DEPS)
|
||||
testpixbuf_drawable_DEPENDENCIES = $(DEPS)
|
||||
testpixbuf_save_DEPENDENCIES = $(DEPS)
|
||||
testpixbuf_scale_DEPENDENCIES = $(DEPS)
|
||||
testanimation_DEPENDENCIES = $(DEPS)
|
||||
pixbuf_demo_DEPENDENCIES = $(DEPS)
|
||||
|
||||
testpixbuf_LDADD = $(LDADDS)
|
||||
testpixbuf_drawable_LDADD = $(LDADDS)
|
||||
testpixbuf_save_LDADD = $(LDADDS)
|
||||
testpixbuf_scale_LDADD = $(LDADDS)
|
||||
testanimation_LDADD = $(LDADDS)
|
||||
pixbuf_demo_LDADD = $(LDADDS)
|
||||
|
||||
testpixbuf_SOURCES = testpixbuf.c pixbuf-init.c
|
||||
testpixbuf_drawable_SOURCES = testpixbuf-drawable.c pixbuf-init.c
|
||||
testpixbuf_save_SOURCES = testpixbuf-save.c
|
||||
testpixbuf_scale_SOURCES = testpixbuf-scale.c pixbuf-init.c
|
||||
testanimation_SOURCES = testanimation.c pixbuf-init.c
|
||||
pixbuf_demo_SOURCES = pixbuf-demo.c pixbuf-init.c
|
||||
|
154
demos/testpixbuf-save.c
Normal file
154
demos/testpixbuf-save.c
Normal file
@ -0,0 +1,154 @@
|
||||
|
||||
#include <config.h>
|
||||
/* if building outside GTK, remove /x11 part */
|
||||
#include <gdk/x11/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void
|
||||
keypress_check (GtkWidget *widget, GdkEventKey *evt, gpointer data)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GtkDrawingArea *da = (GtkDrawingArea*)data;
|
||||
GError *err = NULL;
|
||||
|
||||
pixbuf = (GdkPixbuf *) gtk_object_get_data (GTK_OBJECT (da), "pixbuf");
|
||||
|
||||
if (evt->keyval == 'q')
|
||||
gtk_main_quit ();
|
||||
if (evt->keyval == 's') {
|
||||
if (pixbuf == NULL) {
|
||||
fprintf (stderr, "PIXBUF NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gdk_pixbuf_save (pixbuf, "foo.jpg", "jpeg",
|
||||
&err,
|
||||
"quality", "100",
|
||||
NULL)) {
|
||||
fprintf (stderr, "%s", err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
|
||||
} else if (evt->keyval == 'p') {
|
||||
if (pixbuf == NULL) {
|
||||
fprintf (stderr, "PIXBUF NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gdk_pixbuf_save (pixbuf, "foo.png", "png", &err, NULL)) {
|
||||
fprintf (stderr, "%s", err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
close_app (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
expose_cb (GtkWidget *drawing_area, GdkEventExpose *evt, gpointer data)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = (GdkPixbuf *) gtk_object_get_data (GTK_OBJECT (drawing_area),
|
||||
"pixbuf");
|
||||
if (gdk_pixbuf_get_has_alpha (pixbuf)) {
|
||||
gdk_draw_rgb_32_image (drawing_area->window,
|
||||
drawing_area->style->black_gc,
|
||||
evt->area.x, evt->area.y,
|
||||
evt->area.width,
|
||||
evt->area.height,
|
||||
GDK_RGB_DITHER_MAX,
|
||||
gdk_pixbuf_get_pixels (pixbuf) +
|
||||
(evt->area.y * gdk_pixbuf_get_rowstride (pixbuf)) +
|
||||
(evt->area.x * gdk_pixbuf_get_n_channels (pixbuf)),
|
||||
gdk_pixbuf_get_rowstride (pixbuf));
|
||||
} else {
|
||||
gdk_draw_rgb_image (drawing_area->window,
|
||||
drawing_area->style->black_gc,
|
||||
evt->area.x, evt->area.y,
|
||||
evt->area.width,
|
||||
evt->area.height,
|
||||
GDK_RGB_DITHER_NORMAL,
|
||||
gdk_pixbuf_get_pixels (pixbuf) +
|
||||
(evt->area.y * gdk_pixbuf_get_rowstride (pixbuf)) +
|
||||
(evt->area.x * gdk_pixbuf_get_n_channels (pixbuf)),
|
||||
gdk_pixbuf_get_rowstride (pixbuf));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
configure_cb (GtkWidget *drawing_area, GdkEventConfigure *evt, gpointer data)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = (GdkPixbuf *) gtk_object_get_data (GTK_OBJECT (drawing_area),
|
||||
"pixbuf");
|
||||
|
||||
g_print ("X:%d Y:%d\n", evt->width, evt->height);
|
||||
if (evt->width != gdk_pixbuf_get_width (pixbuf) || evt->height != gdk_pixbuf_get_height (pixbuf)) {
|
||||
GdkWindow *root;
|
||||
GdkPixbuf *new_pixbuf;
|
||||
|
||||
root = GDK_ROOT_PARENT ();
|
||||
new_pixbuf = gdk_pixbuf_get_from_drawable (NULL, root, NULL,
|
||||
0, 0, 0, 0, evt->width, evt->height);
|
||||
gtk_object_set_data (GTK_OBJECT (drawing_area), "pixbuf", new_pixbuf);
|
||||
gdk_pixbuf_unref (pixbuf);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GdkWindow *root;
|
||||
GtkWidget *window;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *drawing_area;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
|
||||
|
||||
root = GDK_ROOT_PARENT ();
|
||||
pixbuf = gdk_pixbuf_get_from_drawable (NULL, root, NULL,
|
||||
0, 0, 0, 0, 150, 160);
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
|
||||
GTK_SIGNAL_FUNC (close_app), NULL);
|
||||
gtk_signal_connect (GTK_OBJECT (window), "destroy",
|
||||
GTK_SIGNAL_FUNC (close_app), NULL);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 0);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
drawing_area = gtk_drawing_area_new ();
|
||||
gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area),
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf));
|
||||
gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
|
||||
GTK_SIGNAL_FUNC (expose_cb), NULL);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (drawing_area), "configure_event",
|
||||
GTK_SIGNAL_FUNC (configure_cb), NULL);
|
||||
gtk_signal_connect (GTK_OBJECT (window), "key_press_event",
|
||||
GTK_SIGNAL_FUNC (keypress_check), drawing_area);
|
||||
gtk_object_set_data (GTK_OBJECT (drawing_area), "pixbuf", pixbuf);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
|
||||
|
||||
gtk_widget_show_all (window);
|
||||
gtk_main ();
|
||||
return 0;
|
||||
}
|
@ -1,3 +1,27 @@
|
||||
2000-10-05 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
Pixbuf saving, patch from David Welton.
|
||||
|
||||
* Makefile.am (GDK_PIXBUF_LIBS): add INTLLIBS
|
||||
(libgdk_pixbuf_1_3_la_SOURCES): add gdk-pixbuf-i18n.h
|
||||
|
||||
* gdk-pixbuf-i18n.h: Add _() to gdk-pixbuf
|
||||
|
||||
* io-png.c (gdk_pixbuf__png_image_save): PNG save routine.
|
||||
|
||||
* io-jpeg.c (gdk_pixbuf__jpeg_image_save): JPEG save routine.
|
||||
|
||||
* gdk-pixbuf-io.c (gdk_pixbuf_save):
|
||||
(gdk_pixbuf_savev): Implement pixbuf saving routines
|
||||
|
||||
* gdk-pixbuf.c (gdk_pixbuf_error_quark): pixbuf error quark
|
||||
function
|
||||
|
||||
* gdk-pixbuf.h: Add public save routines; add pixbuf error
|
||||
types
|
||||
|
||||
* gdk-pixbuf-io.h: Add save function to GdkPixbufModule
|
||||
|
||||
2000-10-05 Dan Winship <danw@helixcode.com>
|
||||
|
||||
* io-png.c, io-tiff.c, io-xpm.c: Fix comments to not claim that
|
||||
|
@ -154,7 +154,7 @@ make_inline_pixbuf_SOURCES=make-inline-pixbuf.c
|
||||
|
||||
make_inline_pixbuf_LDADD = $(LDADDS)
|
||||
|
||||
GDK_PIXBUF_LIBS = $(GLIB_LIBS)
|
||||
GDK_PIXBUF_LIBS = $(GLIB_LIBS) $(INTLLIBS)
|
||||
|
||||
#
|
||||
# The GdkPixBuf library
|
||||
@ -163,6 +163,7 @@ GDK_PIXBUF_LIBS = $(GLIB_LIBS)
|
||||
libgdk_pixbufincludedir = $(includedir)/gtk-2.0/gdk-pixbuf
|
||||
|
||||
libgdk_pixbuf_1_3_la_SOURCES = \
|
||||
gdk-pixbuf-i18n.h \
|
||||
gdk-pixbuf.c \
|
||||
gdk-pixbuf-animation.c \
|
||||
gdk-pixbuf-data.c \
|
||||
|
24
gdk-pixbuf/gdk-pixbuf-i18n.h
Normal file
24
gdk-pixbuf/gdk-pixbuf-i18n.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __GDKPIXBUFINTL_H__
|
||||
#define __GDKPIXBUFINTL_H__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
#include<libintl.h>
|
||||
#define _(String) dgettext(GETTEXT_PACKAGE,String)
|
||||
#ifdef gettext_noop
|
||||
#define N_(String) gettext_noop(String)
|
||||
#else
|
||||
#define N_(String) (String)
|
||||
#endif
|
||||
#else /* NLS is disabled */
|
||||
#define _(String) (String)
|
||||
#define N_(String) (String)
|
||||
#define textdomain(String) (String)
|
||||
#define gettext(String) (String)
|
||||
#define dgettext(Domain,String) (String)
|
||||
#define dcgettext(Domain,String,Type) (String)
|
||||
#define bindtextdomain(Domain,Directory) (Domain)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -24,6 +24,7 @@
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include <errno.h>
|
||||
#include "gdk-pixbuf-private.h"
|
||||
#include "gdk-pixbuf-io.h"
|
||||
|
||||
@ -185,17 +186,17 @@ pixbuf_check_wbmp (guchar *buffer, int size)
|
||||
}
|
||||
|
||||
static GdkPixbufModule 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", pixbuf_check_png, NULL, NULL, NULL, NULL, NULL, NULL, NULL, },
|
||||
{ "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "tiff", pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "gif", pixbuf_check_gif, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
#define XPM_FILE_FORMAT_INDEX 4
|
||||
{ "xpm", pixbuf_check_xpm, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "pnm", pixbuf_check_pnm, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "ras", pixbuf_check_sunras, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "ico", pixbuf_check_ico, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "bmp", pixbuf_check_bmp, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "wbmp", pixbuf_check_wbmp, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "xpm", pixbuf_check_xpm, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "pnm", pixbuf_check_pnm, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "ras", pixbuf_check_sunras, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "ico", pixbuf_check_ico, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "bmp", pixbuf_check_bmp, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ "wbmp", pixbuf_check_wbmp, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -281,6 +282,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
|
||||
char *path;
|
||||
GModule *module;
|
||||
gpointer load_sym;
|
||||
gpointer save_sym;
|
||||
char *name;
|
||||
|
||||
g_return_if_fail (image_module->module == NULL);
|
||||
@ -333,6 +335,9 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
|
||||
|
||||
if (pixbuf_module_symbol (module, name, "image_load_animation", &load_sym))
|
||||
image_module->load_animation = load_sym;
|
||||
|
||||
if (pixbuf_module_symbol (module, name, "image_save", &save_sym))
|
||||
image_module->save = save_sym;
|
||||
}
|
||||
#else
|
||||
|
||||
@ -354,6 +359,7 @@ m_load (png);
|
||||
m_begin_load (png);
|
||||
m_load_increment (png);
|
||||
m_stop_load (png);
|
||||
m_save (png);
|
||||
/* BMP */
|
||||
m_load (bmp);
|
||||
m_begin_load (bmp);
|
||||
@ -380,6 +386,7 @@ m_load (jpeg);
|
||||
m_begin_load (jpeg);
|
||||
m_load_increment (jpeg);
|
||||
m_stop_load (jpeg);
|
||||
m_save (jpeg);
|
||||
/* PNM */
|
||||
m_load (pnm);
|
||||
m_begin_load (pnm);
|
||||
@ -409,6 +416,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
|
||||
image_module->begin_load = mname (png,begin_load);
|
||||
image_module->load_increment = mname (png,load_increment);
|
||||
image_module->stop_load = mname (png,stop_load);
|
||||
image_module->save = mname (png,save);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -450,6 +458,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
|
||||
image_module->begin_load = mname (jpeg,begin_load);
|
||||
image_module->load_increment = mname (jpeg,load_increment);
|
||||
image_module->stop_load = mname (jpeg,stop_load);
|
||||
image_module->save = mname (jpeg,save);
|
||||
return;
|
||||
}
|
||||
if (strcmp (image_module->module_name, "pnm") == 0){
|
||||
@ -596,3 +605,197 @@ gdk_pixbuf_new_from_xpm_data (const char **data)
|
||||
pixbuf = (* load_xpm_data) (data);
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
collect_save_options (va_list opts,
|
||||
gchar ***keys,
|
||||
gchar ***vals)
|
||||
{
|
||||
gchar *key;
|
||||
gchar *val;
|
||||
gchar *next;
|
||||
gint count;
|
||||
|
||||
count = 0;
|
||||
*keys = NULL;
|
||||
*vals = NULL;
|
||||
|
||||
next = va_arg (opts, gchar*);
|
||||
while (next)
|
||||
{
|
||||
key = next;
|
||||
val = va_arg (opts, gchar*);
|
||||
|
||||
++count;
|
||||
|
||||
/* woo, slow */
|
||||
*keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
|
||||
*vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
|
||||
|
||||
(*keys)[count-1] = g_strdup (key);
|
||||
(*vals)[count-1] = g_strdup (val);
|
||||
|
||||
(*keys)[count] = NULL;
|
||||
(*vals)[count] = NULL;
|
||||
|
||||
next = va_arg (opts, gchar*);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
|
||||
FILE *filehandle,
|
||||
const char *format,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
int i;
|
||||
GdkPixbufModule *image_module = NULL;
|
||||
|
||||
for (i = 0; file_formats[i].module_name; i++) {
|
||||
if (!strcmp (file_formats[i].module_name, format)) {
|
||||
image_module = &(file_formats[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!image_module) {
|
||||
g_warning ("gdk-pixbuf does not support the format: %s", format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (image_module->module == NULL)
|
||||
gdk_pixbuf_load_module (image_module);
|
||||
|
||||
g_return_val_if_fail (image_module->save != NULL, FALSE);
|
||||
|
||||
|
||||
|
||||
return (* image_module->save) (filehandle, pixbuf,
|
||||
keys, values,
|
||||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_save:
|
||||
* @pixbuf: pointer to GdkPixbuf.
|
||||
* @filename: Name of file to save.
|
||||
* @format: name of file format.
|
||||
* @error: return location for error, or NULL
|
||||
* @Varargs: list of key-value save options
|
||||
*
|
||||
* Saves pixbuf to a file in @format, which is currently "jpeg" or
|
||||
* "png". If @error is set, FALSE will be returned. Possible errors include those
|
||||
* from #GdkPixbufErrorType and those from #GFileErrorType.
|
||||
*
|
||||
* The variable argument list should be NULL-terminated; if not empty,
|
||||
* it should contain pairs of strings that modify the save
|
||||
* parameters. For example:
|
||||
*
|
||||
* <programlisting>
|
||||
* gdk_pixbuf_save (pixbuf, handle, "jpeg", &error,
|
||||
* "quality", "100", NULL);
|
||||
* </programlisting>
|
||||
*
|
||||
* The only save parameter that currently exists is the "quality" field
|
||||
* for JPEG images; its value should be in the range [0,100].
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
**/
|
||||
|
||||
gboolean
|
||||
gdk_pixbuf_save (GdkPixbuf *pixbuf,
|
||||
const char *filename,
|
||||
const char *format,
|
||||
GError **error,
|
||||
...)
|
||||
{
|
||||
gchar **keys = NULL;
|
||||
gchar **values = NULL;
|
||||
va_list args;
|
||||
gboolean result;
|
||||
|
||||
va_start (args, error);
|
||||
|
||||
collect_save_options (args, &keys, &values);
|
||||
|
||||
va_end (args);
|
||||
|
||||
result = gdk_pixbuf_savev (pixbuf, filename, format,
|
||||
keys, values,
|
||||
error);
|
||||
|
||||
g_strfreev (keys);
|
||||
g_strfreev (values);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_pixbuf_savev:
|
||||
* @pixbuf: pointer to GdkPixbuf.
|
||||
* @filename: Name of file to save.
|
||||
* @format: 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 file in @format, which is currently "jpeg" or "png".
|
||||
* If @error is set, FALSE will be returned. See gdk_pixbuf_save () for more
|
||||
* details. Possible errors include those from #GdkPixbufErrorType and
|
||||
* those from #GFileErrorType.
|
||||
*
|
||||
* Return value: whether an error was set
|
||||
**/
|
||||
|
||||
gboolean
|
||||
gdk_pixbuf_savev (GdkPixbuf *pixbuf,
|
||||
const char *filename,
|
||||
const char *format,
|
||||
char **option_keys,
|
||||
char **option_values,
|
||||
GError **error)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
gboolean result;
|
||||
|
||||
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
g_return_val_if_fail (format != NULL, FALSE);
|
||||
|
||||
f = fopen (filename, "w");
|
||||
|
||||
if (f == NULL) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_IO,
|
||||
_("Failed to open '%s' for writing: %s"),
|
||||
filename, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
result = gdk_pixbuf_real_save (pixbuf, f, format,
|
||||
option_keys, option_values,
|
||||
error);
|
||||
|
||||
|
||||
if (!result) {
|
||||
g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
|
||||
fclose (f);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (fclose (f) < 0) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_IO,
|
||||
_("Failed to close '%s' while writing image, all data may not have been saved: %s"),
|
||||
filename, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <gmodule.h>
|
||||
#include <stdio.h>
|
||||
#include "gdk-pixbuf.h"
|
||||
#include "gdk-pixbuf-i18n.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -64,11 +65,19 @@ struct _GdkPixbufModule {
|
||||
ModuleFrameDoneNotifyFunc frame_done_func,
|
||||
ModuleAnimationDoneNotifyFunc anim_done_func,
|
||||
gpointer user_data);
|
||||
void (* stop_load) (gpointer context);
|
||||
gboolean (* load_increment) (gpointer context, const guchar *buf, guint size);
|
||||
void (* stop_load) (gpointer context);
|
||||
gboolean (* load_increment) (gpointer context,
|
||||
const guchar *buf,
|
||||
guint size);
|
||||
|
||||
/* Animation loading */
|
||||
GdkPixbufAnimation *(* load_animation) (FILE *f);
|
||||
|
||||
gboolean (* save) (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **param_keys,
|
||||
gchar **param_values,
|
||||
GError **err);
|
||||
};
|
||||
|
||||
|
||||
|
@ -361,3 +361,14 @@ gdk_pixbuf_init (void)
|
||||
gdk_pixbuf_preinit (NULL, NULL);
|
||||
gdk_pixbuf_postinit (NULL, NULL);
|
||||
}
|
||||
|
||||
/* Error quark */
|
||||
GQuark
|
||||
gdk_pixbuf_error_quark (void)
|
||||
{
|
||||
static GQuark q = 0;
|
||||
if (q == 0)
|
||||
q = g_quark_from_static_string ("gdk-pixbuf-error-quark");
|
||||
|
||||
return q;
|
||||
}
|
||||
|
@ -61,6 +61,18 @@ typedef struct _GdkPixbufFrame GdkPixbufFrame;
|
||||
/* Handler that must free the pixel array */
|
||||
typedef void (* GdkPixbufDestroyNotify) (guchar *pixels, gpointer data);
|
||||
|
||||
#define GDK_PIXBUF_ERROR gdk_pixbuf_error_quark ()
|
||||
|
||||
typedef enum {
|
||||
/* some kind of failure reading or writing files */
|
||||
GDK_PIXBUF_ERROR_IO,
|
||||
/* bad option value passed to save routine */
|
||||
GDK_PIXBUF_ERROR_BAD_OPTION_VALUE,
|
||||
GDK_PIXBUF_ERROR_FAILED
|
||||
} GdkPixbufErrorType;
|
||||
|
||||
GQuark gdk_pixbuf_error_quark () G_GNUC_CONST;
|
||||
|
||||
|
||||
|
||||
GType gdk_pixbuf_get_type (void) G_GNUC_CONST;
|
||||
@ -111,6 +123,22 @@ GdkPixbuf *gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
|
||||
gboolean copy_pixels,
|
||||
int length);
|
||||
|
||||
|
||||
/* Saving */
|
||||
|
||||
gboolean gdk_pixbuf_save (GdkPixbuf *pixbuf,
|
||||
const char *filename,
|
||||
const char *format,
|
||||
GError **err,
|
||||
...);
|
||||
|
||||
gboolean gdk_pixbuf_savev (GdkPixbuf *pixbuf,
|
||||
const char *filename,
|
||||
const char *format,
|
||||
char **option_keys,
|
||||
char **option_values,
|
||||
GError **err);
|
||||
|
||||
/* Adding an alpha channel */
|
||||
GdkPixbuf *gdk_pixbuf_add_alpha (const GdkPixbuf *pixbuf, gboolean substitute_color,
|
||||
guchar r, guchar g, guchar b);
|
||||
|
@ -565,3 +565,126 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, guchar *buf, guint size)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_pixbuf__jpeg_image_save (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
/* FIXME error handling is broken */
|
||||
|
||||
struct jpeg_compress_struct cinfo;
|
||||
guchar *buf = NULL;
|
||||
guchar *ptr;
|
||||
guchar *pixels = NULL;
|
||||
JSAMPROW *jbuf;
|
||||
int y = 0;
|
||||
int quality = 75; /* default; must be between 0 and 100 */
|
||||
int i, j;
|
||||
int w, h = 0;
|
||||
int rowstride = 0;
|
||||
struct error_handler_data jerr;
|
||||
|
||||
if (keys && *keys) {
|
||||
gchar **kiter = keys;
|
||||
gchar **viter = values;
|
||||
|
||||
while (*kiter) {
|
||||
if (strcmp (*kiter, "quality") == 0) {
|
||||
char *endptr = NULL;
|
||||
quality = strtol (*viter, &endptr, 10);
|
||||
|
||||
if (endptr == *viter) {
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_BAD_OPTION_VALUE,
|
||||
_("JPEG quality must be a value between 0 and 100; value '%s' could not be parsed."),
|
||||
*viter);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (quality < 0 ||
|
||||
quality > 100) {
|
||||
/* This is a user-visible error;
|
||||
* lets people skip the range-checking
|
||||
* in their app.
|
||||
*/
|
||||
g_set_error (error,
|
||||
GDK_PIXBUF_ERROR,
|
||||
GDK_PIXBUF_ERROR_BAD_OPTION_VALUE,
|
||||
_("JPEG quality must be a value between 0 and 100; value '%d' is not allowed."),
|
||||
quality);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
g_warning ("Bad option name '%s' passed to JPEG saver",
|
||||
*kiter);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
++kiter;
|
||||
++viter;
|
||||
}
|
||||
}
|
||||
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
w = gdk_pixbuf_get_width (pixbuf);
|
||||
h = gdk_pixbuf_get_height (pixbuf);
|
||||
|
||||
/* no image data? abort */
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
g_return_val_if_fail (pixels != NULL, FALSE);
|
||||
|
||||
/* allocate a small buffer to convert image data */
|
||||
buf = malloc (w * 3 * sizeof (guchar));
|
||||
g_return_val_if_fail (buf != NULL, FALSE);
|
||||
|
||||
/* set up error handling */
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
|
||||
cinfo.err = jpeg_std_error (&(jerr.pub));
|
||||
if (sigsetjmp (jerr.setjmp_buffer, 1)) {
|
||||
jpeg_destroy_compress (&cinfo);
|
||||
free (buf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* setup compress params */
|
||||
jpeg_create_compress (&cinfo);
|
||||
jpeg_stdio_dest (&cinfo, f);
|
||||
cinfo.image_width = w;
|
||||
cinfo.image_height = h;
|
||||
cinfo.input_components = 3;
|
||||
cinfo.in_color_space = JCS_RGB;
|
||||
|
||||
/* set up jepg compression parameters */
|
||||
jpeg_set_defaults (&cinfo);
|
||||
jpeg_set_quality (&cinfo, quality, TRUE);
|
||||
jpeg_start_compress (&cinfo, TRUE);
|
||||
/* get the start pointer */
|
||||
ptr = pixels;
|
||||
/* go one scanline at a time... and save */
|
||||
i = 0;
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
/* convert scanline from ARGB to RGB packed */
|
||||
for (j = 0; j < w; j++)
|
||||
memcpy (&(buf[j*3]), &(ptr[i*rowstride + j*3]), 3);
|
||||
|
||||
/* write scanline */
|
||||
jbuf = (JSAMPROW *)(&buf);
|
||||
jpeg_write_scanlines (&cinfo, jbuf, 1);
|
||||
i++;
|
||||
y++;
|
||||
|
||||
}
|
||||
|
||||
/* finish off */
|
||||
jpeg_finish_compress (&cinfo);
|
||||
free (buf);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -537,5 +537,112 @@ png_warning_callback(png_structp png_read_ptr,
|
||||
}
|
||||
|
||||
|
||||
/* Save */
|
||||
gboolean
|
||||
gdk_pixbuf__png_image_save (FILE *f,
|
||||
GdkPixbuf *pixbuf,
|
||||
gchar **keys,
|
||||
gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
/* FIXME error handling is broken */
|
||||
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
guchar *ptr;
|
||||
guchar *pixels;
|
||||
int x, y, j;
|
||||
png_bytep row_ptr, data = NULL;
|
||||
png_color_8 sig_bit;
|
||||
int w, h, rowstride;
|
||||
int has_alpha;
|
||||
int bpc;
|
||||
|
||||
if (keys && *keys) {
|
||||
g_warning ("Bad option name '%s' passed to PNG saver",
|
||||
*keys);
|
||||
return FALSE;
|
||||
#if 0
|
||||
gchar **kiter = keys;
|
||||
gchar **viter = values;
|
||||
|
||||
|
||||
while (*kiter) {
|
||||
|
||||
++kiter;
|
||||
++viter;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bpc = gdk_pixbuf_get_bits_per_sample (pixbuf);
|
||||
w = gdk_pixbuf_get_width (pixbuf);
|
||||
h = gdk_pixbuf_get_height (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
|
||||
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
g_return_val_if_fail (png_ptr != NULL, FALSE);
|
||||
|
||||
info_ptr = png_create_info_struct (png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
|
||||
return FALSE;
|
||||
}
|
||||
if (setjmp (png_ptr->jmpbuf)) {
|
||||
png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
|
||||
return FALSE;
|
||||
}
|
||||
png_init_io (png_ptr, f);
|
||||
if (has_alpha) {
|
||||
png_set_IHDR (png_ptr, info_ptr, w, h, bpc,
|
||||
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
png_set_swap_alpha (png_ptr);
|
||||
#else
|
||||
png_set_bgr (png_ptr);
|
||||
#endif
|
||||
} else {
|
||||
png_set_IHDR (png_ptr, info_ptr, w, h, bpc,
|
||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
data = malloc (w * 3 * sizeof (char));
|
||||
}
|
||||
sig_bit.red = bpc;
|
||||
sig_bit.green = bpc;
|
||||
sig_bit.blue = bpc;
|
||||
sig_bit.alpha = bpc;
|
||||
png_set_sBIT (png_ptr, info_ptr, &sig_bit);
|
||||
png_write_info (png_ptr, info_ptr);
|
||||
png_set_shift (png_ptr, &sig_bit);
|
||||
png_set_packing (png_ptr);
|
||||
|
||||
ptr = pixels;
|
||||
for (y = 0; y < h; y++) {
|
||||
if (has_alpha)
|
||||
row_ptr = (png_bytep)ptr;
|
||||
else {
|
||||
for (j = 0, x = 0; x < w; x++)
|
||||
memcpy (&(data[x*3]), &(ptr[x*3]), 3);
|
||||
|
||||
row_ptr = (png_bytep)data;
|
||||
}
|
||||
png_write_rows (png_ptr, &row_ptr, 1);
|
||||
ptr += rowstride;
|
||||
}
|
||||
|
||||
if (data)
|
||||
free (data);
|
||||
|
||||
png_write_end (png_ptr, info_ptr);
|
||||
png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user