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,9 +1192,9 @@ 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));
xcf_write_int32_check_error (info, &offset, 1); xcf_write_int32_check_error (info, &offset, 1);
@ -1270,9 +1270,9 @@ 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));
xcf_write_int32_check_error (info, &offset, 1); xcf_write_int32_check_error (info, &offset, 1);
@ -1299,24 +1299,26 @@ 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)
{ {
guint32 saved_pos; const Babl *format;
guint32 offset; guint32 saved_pos;
guint32 width; guint32 offset;
guint32 height; guint32 width;
guint32 bpp; guint32 height;
gint i; guint32 bpp;
gint nlevels; gint i;
gint tmp1, tmp2; gint nlevels;
gint tmp1, tmp2;
GError *tmp_error = NULL;
GError *tmp_error = NULL; format = gegl_buffer_get_format (buffer);
width = tile_manager_width (tiles); width = gegl_buffer_get_width (buffer);
height = tile_manager_height (tiles); height = gegl_buffer_get_height (buffer);
bpp = tile_manager_bpp (tiles); 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
{ {
@ -1378,22 +1380,28 @@ 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)
{ {
guint32 saved_pos; const Babl *format;
guint32 offset; guint32 saved_pos;
guint32 width; guint32 offset;
guint32 height; guint32 width;
guint ntiles; guint32 height;
gint i; gint bpp;
guchar *rlebuf; gint n_tile_rows;
gint n_tile_cols;
guint ntiles;
gint i;
guchar *rlebuf;
GError *tmp_error = NULL;
GError *tmp_error = NULL; format = gegl_buffer_get_format (buffer);
width = tile_manager_width (level); width = gegl_buffer_get_width (buffer);
height = tile_manager_height (level); 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,59 +1409,63 @@ 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 = n_tile_rows * n_tile_cols;
xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
for (i = 0; i < ntiles; i++)
{ {
ntiles = level->ntile_rows * level->ntile_cols; GeglRectangle rect;
xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
for (i = 0; i < ntiles; i++) /* save the start offset of where we are writing
* out the next tile.
*/
offset = info->cp;
gimp_gegl_buffer_get_tile_rect (buffer,
XCF_TILE_WIDTH, XCF_TILE_HEIGHT,
i, &rect);
/* write out the tile. */
switch (info->compression)
{ {
/* save the start offset of where we are writing case COMPRESS_NONE:
* out the next tile. xcf_check_error (xcf_save_tile (info, buffer, &rect, error));
*/ break;
offset = info->cp; case COMPRESS_RLE:
xcf_check_error (xcf_save_tile_rle (info, buffer, &rect,
/* write out the tile. */ rlebuf, error));
switch (info->compression) break;
{ case COMPRESS_ZLIB:
case COMPRESS_NONE: g_error ("xcf: zlib compression unimplemented");
xcf_check_error (xcf_save_tile (info, level->tiles[i], error)); break;
break; case COMPRESS_FRACTAL:
case COMPRESS_RLE: g_error ("xcf: fractal compression unimplemented");
xcf_check_error (xcf_save_tile_rle (info, level->tiles[i], break;
rlebuf, error));
break;
case COMPRESS_ZLIB:
g_error ("xcf: zlib compression unimplemented");
break;
case COMPRESS_FRACTAL:
g_error ("xcf: fractal compression unimplemented");
break;
}
/* seek back to where we are to write out the next
* tile offset and write it out.
*/
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
/* increment the location we are to write out the
* next offset.
*/
saved_pos = info->cp;
/* seek to the end of the file which is where
* we will write out the next tile.
*/
xcf_check_error (xcf_seek_end (info, error));
} }
}
g_free (rlebuf); /* seek back to where we are to write out the next
* tile offset and write it out.
*/
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
/* increment the location we are to write out the
* next offset.
*/
saved_pos = info->cp;
/* seek to the end of the file which is where
* we will write out the next tile.
*/
xcf_check_error (xcf_seek_end (info, error));
}
/* 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.
@ -1467,44 +1479,51 @@ xcf_save_level (XcfInfo *info,
} }
static gboolean static gboolean
xcf_save_tile (XcfInfo *info, xcf_save_tile (XcfInfo *info,
Tile *tile, GeglBuffer *buffer,
GError **error) GeglRectangle *tile_rect,
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);
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,
guchar *rlebuf, GeglRectangle *tile_rect,
GError **error) guchar *rlebuf,
GError **error)
{ {
GError *tmp_error = NULL; const Babl *format = gegl_buffer_get_format (buffer);
gint len = 0; gint bpp = babl_format_get_bytes_per_pixel (format);
gint bpp; gint tile_size = bpp * tile_rect->width * tile_rect->height;
gint i, j; guchar *tile_data = g_alloca (tile_size);
gint len = 0;
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_rect->width * tile_rect->height;
gint size = tile_ewidth (tile) * tile_eheight (tile); 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;
} }