app: port XCF saving to reading from the GeglBuffer

This commit is contained in:
Michael Natterer
2012-04-03 00:00:15 +02:00
parent 91c39463c4
commit 73108152ea

View File

@ -28,9 +28,7 @@
#include "core/core-types.h" #include "core/core-types.h"
#include "base/tile.h" #include "gegl/gimp-gegl-tile-compat.h"
#include "base/tile-manager.h"
#include "base/tile-manager-private.h"
#include "core/gimp.h" #include "core/gimp.h"
#include "core/gimpcontainer.h" #include "core/gimpcontainer.h"
@ -92,17 +90,19 @@ static gboolean xcf_save_channel (XcfInfo *info,
GimpImage *image, GimpImage *image,
GimpChannel *channel, GimpChannel *channel,
GError **error); GError **error);
static gboolean xcf_save_hierarchy (XcfInfo *info, static gboolean xcf_save_buffer (XcfInfo *info,
TileManager *tiles, GeglBuffer *buffer,
GError **error); GError **error);
static gboolean xcf_save_level (XcfInfo *info, static gboolean xcf_save_level (XcfInfo *info,
TileManager *tiles, GeglBuffer *buffer,
GError **error); GError **error);
static gboolean xcf_save_tile (XcfInfo *info, static gboolean xcf_save_tile (XcfInfo *info,
Tile *tile, GeglBuffer *buffer,
GeglRectangle *tile_rect,
GError **error); GError **error);
static gboolean xcf_save_tile_rle (XcfInfo *info, static gboolean xcf_save_tile_rle (XcfInfo *info,
Tile *tile, GeglBuffer *buffer,
GeglRectangle *tile_rect,
guchar *rlebuf, guchar *rlebuf,
GError **error); GError **error);
static gboolean xcf_save_parasite (XcfInfo *info, static gboolean xcf_save_parasite (XcfInfo *info,
@ -1192,8 +1192,8 @@ xcf_save_layer (XcfInfo *info,
xcf_check_error (xcf_seek_pos (info, info->cp + 8, error)); xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
offset = info->cp; offset = info->cp;
xcf_check_error (xcf_save_hierarchy (info, xcf_check_error (xcf_save_buffer (info,
gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)), gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
error)); error));
xcf_check_error (xcf_seek_pos (info, saved_pos, error)); xcf_check_error (xcf_seek_pos (info, saved_pos, error));
@ -1270,8 +1270,8 @@ xcf_save_channel (XcfInfo *info,
xcf_check_error (xcf_seek_pos (info, info->cp + 4, error)); xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
offset = info->cp; offset = info->cp;
xcf_check_error (xcf_save_hierarchy (info, xcf_check_error (xcf_save_buffer (info,
gimp_drawable_get_tiles (GIMP_DRAWABLE (channel)), gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
error)); error));
xcf_check_error (xcf_seek_pos (info, saved_pos, error)); xcf_check_error (xcf_seek_pos (info, saved_pos, error));
@ -1299,10 +1299,11 @@ xcf_calc_levels (gint size,
static gboolean static gboolean
xcf_save_hierarchy (XcfInfo *info, xcf_save_buffer (XcfInfo *info,
TileManager *tiles, GeglBuffer *buffer,
GError **error) GError **error)
{ {
const Babl *format;
guint32 saved_pos; guint32 saved_pos;
guint32 offset; guint32 offset;
guint32 width; guint32 width;
@ -1311,12 +1312,13 @@ xcf_save_hierarchy (XcfInfo *info,
gint i; gint i;
gint nlevels; gint nlevels;
gint tmp1, tmp2; gint tmp1, tmp2;
GError *tmp_error = NULL; GError *tmp_error = NULL;
width = tile_manager_width (tiles); format = gegl_buffer_get_format (buffer);
height = tile_manager_height (tiles);
bpp = tile_manager_bpp (tiles); width = gegl_buffer_get_width (buffer);
height = gegl_buffer_get_height (buffer);
bpp = babl_format_get_bytes_per_pixel (format);
xcf_write_int32_check_error (info, (guint32 *) &width, 1); xcf_write_int32_check_error (info, (guint32 *) &width, 1);
xcf_write_int32_check_error (info, (guint32 *) &height, 1); xcf_write_int32_check_error (info, (guint32 *) &height, 1);
@ -1324,8 +1326,8 @@ xcf_save_hierarchy (XcfInfo *info,
saved_pos = info->cp; saved_pos = info->cp;
tmp1 = xcf_calc_levels (width, TILE_WIDTH); tmp1 = xcf_calc_levels (width, XCF_TILE_WIDTH);
tmp2 = xcf_calc_levels (height, TILE_HEIGHT); tmp2 = xcf_calc_levels (height, XCF_TILE_HEIGHT);
nlevels = MAX (tmp1, tmp2); nlevels = MAX (tmp1, tmp2);
xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error)); xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
@ -1337,7 +1339,7 @@ xcf_save_hierarchy (XcfInfo *info,
if (i == 0) if (i == 0)
{ {
/* write out the level. */ /* write out the level. */
xcf_check_error (xcf_save_level (info, tiles, error)); xcf_check_error (xcf_save_level (info, buffer, error));
} }
else else
{ {
@ -1379,21 +1381,27 @@ xcf_save_hierarchy (XcfInfo *info,
static gboolean static gboolean
xcf_save_level (XcfInfo *info, xcf_save_level (XcfInfo *info,
TileManager *level, GeglBuffer *buffer,
GError **error) GError **error)
{ {
const Babl *format;
guint32 saved_pos; guint32 saved_pos;
guint32 offset; guint32 offset;
guint32 width; guint32 width;
guint32 height; guint32 height;
gint bpp;
gint n_tile_rows;
gint n_tile_cols;
guint ntiles; guint ntiles;
gint i; gint i;
guchar *rlebuf; guchar *rlebuf;
GError *tmp_error = NULL; GError *tmp_error = NULL;
width = tile_manager_width (level); format = gegl_buffer_get_format (buffer);
height = tile_manager_height (level);
width = gegl_buffer_get_width (buffer);
height = gegl_buffer_get_height (buffer);
bpp = babl_format_get_bytes_per_pixel (format);
xcf_write_int32_check_error (info, (guint32 *) &width, 1); xcf_write_int32_check_error (info, (guint32 *) &width, 1);
xcf_write_int32_check_error (info, (guint32 *) &height, 1); xcf_write_int32_check_error (info, (guint32 *) &height, 1);
@ -1401,30 +1409,37 @@ xcf_save_level (XcfInfo *info,
saved_pos = info->cp; saved_pos = info->cp;
/* allocate a temporary buffer to store the rle data before it is /* allocate a temporary buffer to store the rle data before it is
written to disk */ * written to disk
rlebuf = */
g_malloc (TILE_WIDTH * TILE_HEIGHT * tile_manager_bpp (level) * 1.5); rlebuf = g_alloca (XCF_TILE_WIDTH * XCF_TILE_HEIGHT * bpp * 1.5);
if (level->tiles) n_tile_rows = gimp_gegl_buffer_get_n_tile_rows (buffer, XCF_TILE_HEIGHT);
{ n_tile_cols = gimp_gegl_buffer_get_n_tile_cols (buffer, XCF_TILE_WIDTH);
ntiles = level->ntile_rows * level->ntile_cols;
ntiles = n_tile_rows * n_tile_cols;
xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error)); xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
for (i = 0; i < ntiles; i++) for (i = 0; i < ntiles; i++)
{ {
GeglRectangle rect;
/* save the start offset of where we are writing /* save the start offset of where we are writing
* out the next tile. * out the next tile.
*/ */
offset = info->cp; offset = info->cp;
gimp_gegl_buffer_get_tile_rect (buffer,
XCF_TILE_WIDTH, XCF_TILE_HEIGHT,
i, &rect);
/* write out the tile. */ /* write out the tile. */
switch (info->compression) switch (info->compression)
{ {
case COMPRESS_NONE: case COMPRESS_NONE:
xcf_check_error (xcf_save_tile (info, level->tiles[i], error)); xcf_check_error (xcf_save_tile (info, buffer, &rect, error));
break; break;
case COMPRESS_RLE: case COMPRESS_RLE:
xcf_check_error (xcf_save_tile_rle (info, level->tiles[i], xcf_check_error (xcf_save_tile_rle (info, buffer, &rect,
rlebuf, error)); rlebuf, error));
break; break;
case COMPRESS_ZLIB: case COMPRESS_ZLIB:
@ -1451,9 +1466,6 @@ xcf_save_level (XcfInfo *info,
*/ */
xcf_check_error (xcf_seek_end (info, error)); xcf_check_error (xcf_seek_end (info, error));
} }
}
g_free (rlebuf);
/* write out a '0' offset position to indicate the end /* write out a '0' offset position to indicate the end
* of the level offsets. * of the level offsets.
@ -1468,42 +1480,49 @@ xcf_save_level (XcfInfo *info,
static gboolean static gboolean
xcf_save_tile (XcfInfo *info, xcf_save_tile (XcfInfo *info,
Tile *tile, GeglBuffer *buffer,
GeglRectangle *tile_rect,
GError **error) GError **error)
{ {
const Babl *format = gegl_buffer_get_format (buffer);
gint bpp = babl_format_get_bytes_per_pixel (format);
gint tile_size = bpp * tile_rect->width * tile_rect->height;
guchar *tile_data = g_alloca (tile_size);
GError *tmp_error = NULL; GError *tmp_error = NULL;
tile_lock (tile); gegl_buffer_get (buffer, tile_rect, 1.0, NULL, tile_data,
xcf_write_int8_check_error (info, tile_data_pointer (tile, 0, 0), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
tile_size (tile));
tile_release (tile, FALSE); xcf_write_int8_check_error (info, tile_data, tile_size);
return TRUE; return TRUE;
} }
static gboolean static gboolean
xcf_save_tile_rle (XcfInfo *info, xcf_save_tile_rle (XcfInfo *info,
Tile *tile, GeglBuffer *buffer,
GeglRectangle *tile_rect,
guchar *rlebuf, guchar *rlebuf,
GError **error) GError **error)
{ {
GError *tmp_error = NULL; const Babl *format = gegl_buffer_get_format (buffer);
gint bpp = babl_format_get_bytes_per_pixel (format);
gint tile_size = bpp * tile_rect->width * tile_rect->height;
guchar *tile_data = g_alloca (tile_size);
gint len = 0; gint len = 0;
gint bpp;
gint i, j; gint i, j;
GError *tmp_error = NULL;
tile_lock (tile); gegl_buffer_get (buffer, tile_rect, 1.0, NULL, tile_data,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
bpp = tile_bpp (tile);
for (i = 0; i < bpp; i++) for (i = 0; i < bpp; i++)
{ {
const guchar *data = (const guchar *) tile_data_pointer (tile, 0, 0) + i; const guchar *data = tile_data + i;
gint state = 0; gint state = 0;
gint length = 0; gint length = 0;
gint count = 0; gint count = 0;
gint size = tile_ewidth (tile) * tile_eheight (tile); gint size = tile_rect->width * tile_rect->height;
guint last = -1; guint last = -1;
while (size > 0) while (size > 0)
@ -1589,12 +1608,11 @@ xcf_save_tile_rle (XcfInfo *info,
} }
} }
if (count != (tile_ewidth (tile) * tile_eheight (tile))) if (count != (tile_rect->width * tile_rect->height))
g_message ("xcf: uh oh! xcf rle tile saving error: %d", count); g_message ("xcf: uh oh! xcf rle tile saving error: %d", count);
} }
xcf_write_int8_check_error (info, rlebuf, len); xcf_write_int8_check_error (info, rlebuf, len);
tile_release (tile, FALSE);
return TRUE; return TRUE;
} }