diff options
author | Matthias Clasen <mclasen@redhat.com> | 2005-02-24 04:41:35 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2005-02-24 04:41:35 +0000 |
commit | 534d584ba69a9b4c1ceabd17e4498ecc63335607 (patch) | |
tree | 0afb6d0d5b2fb43d0ac1d39b8c310a1a38211d8f | |
parent | c06df5a44c552cc757b802ec57cfbb4508be0dae (diff) | |
download | gdk-pixbuf-534d584ba69a9b4c1ceabd17e4498ecc63335607.tar.gz |
Document BMP saving support.
2005-02-23 Matthias Clasen <mclasen@redhat.com>
* gdk-pixbuf-io.c: Document BMP saving support.
* io-bmp.c: Support saving as BMP. (168173, Ivan Wong)
-rw-r--r-- | gdk-pixbuf/ChangeLog | 4 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-io.c | 12 | ||||
-rw-r--r-- | gdk-pixbuf/io-bmp.c | 119 |
3 files changed, 128 insertions, 7 deletions
diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 4bde8bd49..35ad83df4 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,5 +1,9 @@ 2005-02-23 Matthias Clasen <mclasen@redhat.com> + * gdk-pixbuf-io.c: Document BMP saving support. + + * io-bmp.c: Support saving as BMP. (168173, Ivan Wong) + * io-ico.c: Fix a typo. (#168173, Ivan Wong) 2005-02-15 Matthias Clasen <mclasen@redhat.com> diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c index 3afb09f19..28ccaec7b 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.c +++ b/gdk-pixbuf/gdk-pixbuf-io.c @@ -1528,8 +1528,8 @@ gdk_pixbuf_real_save_to_callback (GdkPixbuf *pixbuf, * @error: return location for error, or %NULL * @Varargs: list of key-value save options * - * 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 + * Saves pixbuf to a file in format @type. By default, "jpeg", "png", "ico" + * and "bmp" 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: * @@ -1608,7 +1608,7 @@ 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", "png" or "ico". + * Saves pixbuf to a file in @type, which is currently "jpeg", "png", "ico" or "bmp". * If @error is set, %FALSE will be returned. * See gdk_pixbuf_save () for more details. * @@ -1738,7 +1738,7 @@ gdk_pixbuf_save_to_callback (GdkPixbuf *pixbuf, * @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 + * "png", "ico" or "bmp". If @error is set, %FALSE will be returned. See * gdk_pixbuf_save_to_callback () for more details. * * Return value: whether an error was set @@ -1784,7 +1784,7 @@ gdk_pixbuf_save_to_callbackv (GdkPixbuf *pixbuf, * @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 + * "png", "ico" or "bmp". 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 @@ -1872,7 +1872,7 @@ 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", - * "png" or "ico". See gdk_pixbuf_save_to_buffer() for more details. + * "png", "ico" or "bmp". See gdk_pixbuf_save_to_buffer() for more details. * * Return value: whether an error was set * diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index 2724914ab..82882048d 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -1123,12 +1123,129 @@ gdk_pixbuf__bmp_image_load_increment(gpointer data, return TRUE; } +/* for our convenience when filling file header */ +#define put16u(buf,data) { *(guint16*)(buf) = GUINT16_TO_LE (data); buf += 2; } +#define put32u(buf,data) { *(guint32*)(buf) = GUINT32_TO_LE (data); buf += 4; } +#define put16(buf,data) { *(gint16*)(buf) = GINT16_TO_LE (data); buf += 2; } +#define put32(buf,data) { *(gint32*)(buf) = GINT32_TO_LE (data); buf += 4; } + +static gboolean +gdk_pixbuf__bmp_image_save_to_callback (GdkPixbufSaveFunc save_func, + gpointer user_data, + GdkPixbuf *pixbuf, + gchar **keys, + gchar **values, + GError **error) +{ + guint width, height, channel, size, stride, src_stride, x, y; + guchar BFH_BIH[40], *pixels, *buf, *src, *dst, *dst_line; + gboolean ret; + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + channel = gdk_pixbuf_get_n_channels (pixbuf); + pixels = gdk_pixbuf_get_pixels (pixbuf); + src_stride = gdk_pixbuf_get_rowstride (pixbuf); + stride = (width * 3 + 3) & ~3; + size = stride * height; + + /* filling BFH */ + dst = BFH_BIH; + *dst++ = 'B'; /* bfType */ + *dst++ = 'M'; + put32u (dst, size + 14 + 40); /* bfSize */ + put32u (dst, 0); /* bfReserved1 + bfReserved2 */ + put32u (dst, 14 + 40); /* bfOffBits */ + + /* filling BIH */ + put32u (dst, 40); /* biSize */ + put32 (dst, width); /* biWidth */ + put32 (dst, height); /* biHeight */ + put16 (dst, 1); /* biPlanes */ + put16 (dst, 24); /* biBitCount */ + put32u (dst, BI_RGB); /* biCompression */ + put32u (dst, size); /* biSizeImage */ + put32 (dst, 0); /* biXPelsPerMeter */ + put32 (dst, 0); /* biYPelsPerMeter */ + put32u (dst, 0); /* biClrUsed */ + put32u (dst, 0); /* biClrImportant */ + + if (!save_func (BFH_BIH, 14 + 40, error, user_data)) + return FALSE; + + dst_line = buf = g_try_malloc (size); + if (!buf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Couldn't allocate memory for saving BMP file")); + return FALSE; + } + + /* saving as a bottom-up bmp */ + pixels += (height - 1) * src_stride; + for (y = 0; y < height; ++y, pixels -= src_stride, dst_line += stride) { + dst = dst_line; + src = pixels; + for (x = 0; x < width; ++x, dst += 3, src += channel) { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + } + } + ret = save_func (buf, size, error, user_data); + g_free (buf); + + return ret; +} + +static gboolean +save_to_file_cb (const gchar *buf, + gsize count, + GError **error, + gpointer data) +{ + gint bytes; + + while (count > 0) { + bytes = fwrite (buf, sizeof (gchar), count, (FILE *) data); + if (bytes <= 0) + break; + count -= bytes; + buf += bytes; + } + + if (count) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_FAILED, + _("Couldn't write to BMP file")); + return FALSE; + } + + return TRUE; +} + +static gboolean +gdk_pixbuf__bmp_image_save (FILE *f, + GdkPixbuf *pixbuf, + gchar **keys, + gchar **values, + GError **error) +{ + return gdk_pixbuf__bmp_image_save_to_callback (save_to_file_cb, + f, pixbuf, keys, + values, error); +} + void MODULE_ENTRY (bmp, fill_vtable) (GdkPixbufModule *module) { module->begin_load = gdk_pixbuf__bmp_image_begin_load; module->stop_load = gdk_pixbuf__bmp_image_stop_load; module->load_increment = gdk_pixbuf__bmp_image_load_increment; + module->save = gdk_pixbuf__bmp_image_save; + module->save_to_callback = gdk_pixbuf__bmp_image_save_to_callback; } void @@ -1154,7 +1271,7 @@ MODULE_ENTRY (bmp, fill_info) (GdkPixbufFormat *info) info->description = N_("The BMP image format"); info->mime_types = mime_types; info->extensions = extensions; - info->flags = GDK_PIXBUF_FORMAT_THREADSAFE; + info->flags = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE; info->license = "LGPL"; } |