app: port XCF saving to reading from the GeglBuffer
This commit is contained in:
@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user