mirror of https://github.com/GNOME/gimp.git
app: port XCF loading to writing to the drawable's GeglBuffer
This commit is contained in:
parent
3e140fd105
commit
91c39463c4
|
@ -27,6 +27,20 @@
|
|||
#include "gimp-gegl-tile-compat.h"
|
||||
|
||||
|
||||
gint
|
||||
gimp_gegl_buffer_get_n_tile_rows (GeglBuffer *buffer,
|
||||
gint tile_height)
|
||||
{
|
||||
return (gegl_buffer_get_height (buffer) + tile_height - 1) / tile_height;
|
||||
}
|
||||
|
||||
gint
|
||||
gimp_gegl_buffer_get_n_tile_cols (GeglBuffer *buffer,
|
||||
gint tile_width)
|
||||
{
|
||||
return (gegl_buffer_get_width (buffer) + tile_width - 1) / tile_width;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_gegl_buffer_get_tile_rect (GeglBuffer *buffer,
|
||||
gint tile_width,
|
||||
|
@ -39,13 +53,8 @@ gimp_gegl_buffer_get_tile_rect (GeglBuffer *buffer,
|
|||
gint tile_row;
|
||||
gint tile_column;
|
||||
|
||||
n_tile_rows =
|
||||
(gegl_buffer_get_height (buffer) + tile_height - 1) /
|
||||
tile_height;
|
||||
|
||||
n_tile_columns =
|
||||
(gegl_buffer_get_width (buffer) + tile_width - 1) /
|
||||
tile_width;
|
||||
n_tile_rows = gimp_gegl_buffer_get_n_tile_rows (buffer, tile_height);
|
||||
n_tile_columns = gimp_gegl_buffer_get_n_tile_cols (buffer, tile_width);
|
||||
|
||||
if (tile_num > n_tile_rows * n_tile_columns - 1)
|
||||
return FALSE;
|
||||
|
|
|
@ -22,11 +22,15 @@
|
|||
#define __GIMP_GEGL_TILE_COMPAT_H__
|
||||
|
||||
|
||||
gboolean gimp_gegl_buffer_get_tile_rect (GeglBuffer *buffer,
|
||||
gint tile_width,
|
||||
gint tile_height,
|
||||
gint tile_num,
|
||||
GeglRectangle *rect);
|
||||
gint gimp_gegl_buffer_get_n_tile_rows (GeglBuffer *buffer,
|
||||
gint tile_height);
|
||||
gint gimp_gegl_buffer_get_n_tile_cols (GeglBuffer *buffer,
|
||||
gint tile_width);
|
||||
gboolean gimp_gegl_buffer_get_tile_rect (GeglBuffer *buffer,
|
||||
gint tile_width,
|
||||
gint tile_height,
|
||||
gint tile_num,
|
||||
GeglRectangle *rect);
|
||||
|
||||
|
||||
#endif /* __GIMP_GEGL_TILE_COMPAT_H__ */
|
||||
|
|
|
@ -28,12 +28,10 @@
|
|||
|
||||
#include "core/core-types.h"
|
||||
|
||||
#include "base/tile.h"
|
||||
#include "base/tile-manager.h"
|
||||
#include "base/tile-manager-private.h"
|
||||
|
||||
#include "config/gimpcoreconfig.h"
|
||||
|
||||
#include "gegl/gimp-gegl-tile-compat.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpcontainer.h"
|
||||
#include "core/gimpdrawable-private.h" /* eek */
|
||||
|
@ -73,52 +71,54 @@
|
|||
|
||||
/* #define GIMP_XCF_PATH_DEBUG */
|
||||
|
||||
static void xcf_load_add_masks (GimpImage *image);
|
||||
static gboolean xcf_load_image_props (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_layer_props (XcfInfo *info,
|
||||
GimpImage *image,
|
||||
GimpLayer **layer,
|
||||
GList **item_path,
|
||||
gboolean *apply_mask,
|
||||
gboolean *edit_mask,
|
||||
gboolean *show_mask,
|
||||
guint32 *text_layer_flags,
|
||||
guint32 *group_layer_flags);
|
||||
static gboolean xcf_load_channel_props (XcfInfo *info,
|
||||
GimpImage *image,
|
||||
GimpChannel **channel);
|
||||
static gboolean xcf_load_prop (XcfInfo *info,
|
||||
PropType *prop_type,
|
||||
guint32 *prop_size);
|
||||
static GimpLayer * xcf_load_layer (XcfInfo *info,
|
||||
GimpImage *image,
|
||||
GList **item_path);
|
||||
static GimpChannel * xcf_load_channel (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static GimpLayerMask * xcf_load_layer_mask (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_hierarchy (XcfInfo *info,
|
||||
TileManager *tiles);
|
||||
static gboolean xcf_load_level (XcfInfo *info,
|
||||
TileManager *tiles);
|
||||
static gboolean xcf_load_tile (XcfInfo *info,
|
||||
Tile *tile);
|
||||
static gboolean xcf_load_tile_rle (XcfInfo *info,
|
||||
Tile *tile,
|
||||
gint data_length);
|
||||
static GimpParasite * xcf_load_parasite (XcfInfo *info);
|
||||
static gboolean xcf_load_old_paths (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_old_path (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_vectors (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_vector (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static void xcf_load_add_masks (GimpImage *image);
|
||||
static gboolean xcf_load_image_props (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_layer_props (XcfInfo *info,
|
||||
GimpImage *image,
|
||||
GimpLayer **layer,
|
||||
GList **item_path,
|
||||
gboolean *apply_mask,
|
||||
gboolean *edit_mask,
|
||||
gboolean *show_mask,
|
||||
guint32 *text_layer_flags,
|
||||
guint32 *group_layer_flags);
|
||||
static gboolean xcf_load_channel_props (XcfInfo *info,
|
||||
GimpImage *image,
|
||||
GimpChannel **channel);
|
||||
static gboolean xcf_load_prop (XcfInfo *info,
|
||||
PropType *prop_type,
|
||||
guint32 *prop_size);
|
||||
static GimpLayer * xcf_load_layer (XcfInfo *info,
|
||||
GimpImage *image,
|
||||
GList **item_path);
|
||||
static GimpChannel * xcf_load_channel (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static GimpLayerMask * xcf_load_layer_mask (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_buffer (XcfInfo *info,
|
||||
GeglBuffer *buffer);
|
||||
static gboolean xcf_load_level (XcfInfo *info,
|
||||
GeglBuffer *buffer);
|
||||
static gboolean xcf_load_tile (XcfInfo *info,
|
||||
GeglBuffer *buffer,
|
||||
GeglRectangle *tile_rect);
|
||||
static gboolean xcf_load_tile_rle (XcfInfo *info,
|
||||
GeglBuffer *buffer,
|
||||
GeglRectangle *tile_rect,
|
||||
gint data_length);
|
||||
static GimpParasite * xcf_load_parasite (XcfInfo *info);
|
||||
static gboolean xcf_load_old_paths (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_old_path (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_vectors (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
static gboolean xcf_load_vector (XcfInfo *info,
|
||||
GimpImage *image);
|
||||
|
||||
static gboolean xcf_skip_unknown_prop (XcfInfo *info,
|
||||
gsize size);
|
||||
static gboolean xcf_skip_unknown_prop (XcfInfo *info,
|
||||
gsize size);
|
||||
|
||||
|
||||
#define xcf_progress_update(info) G_STMT_START \
|
||||
|
@ -1147,8 +1147,8 @@ xcf_load_layer (XcfInfo *info,
|
|||
if (! xcf_seek_pos (info, hierarchy_offset, NULL))
|
||||
goto error;
|
||||
|
||||
if (! xcf_load_hierarchy (info,
|
||||
gimp_drawable_get_tiles (GIMP_DRAWABLE (layer))))
|
||||
if (! xcf_load_buffer (info,
|
||||
gimp_drawable_get_buffer (GIMP_DRAWABLE (layer))))
|
||||
goto error;
|
||||
|
||||
xcf_progress_update (info);
|
||||
|
@ -1239,8 +1239,8 @@ xcf_load_channel (XcfInfo *info,
|
|||
if (!xcf_seek_pos (info, hierarchy_offset, NULL))
|
||||
goto error;
|
||||
|
||||
if (!xcf_load_hierarchy (info,
|
||||
gimp_drawable_get_tiles (GIMP_DRAWABLE (channel))))
|
||||
if (!xcf_load_buffer (info,
|
||||
gimp_drawable_get_buffer (GIMP_DRAWABLE (channel))))
|
||||
goto error;
|
||||
|
||||
xcf_progress_update (info);
|
||||
|
@ -1298,8 +1298,8 @@ xcf_load_layer_mask (XcfInfo *info,
|
|||
if (! xcf_seek_pos (info, hierarchy_offset, NULL))
|
||||
goto error;
|
||||
|
||||
if (!xcf_load_hierarchy (info,
|
||||
gimp_drawable_get_tiles (GIMP_DRAWABLE (layer_mask))))
|
||||
if (!xcf_load_buffer (info,
|
||||
gimp_drawable_get_buffer (GIMP_DRAWABLE (layer_mask))))
|
||||
goto error;
|
||||
|
||||
xcf_progress_update (info);
|
||||
|
@ -1316,15 +1316,18 @@ xcf_load_layer_mask (XcfInfo *info,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
xcf_load_hierarchy (XcfInfo *info,
|
||||
TileManager *tiles)
|
||||
xcf_load_buffer (XcfInfo *info,
|
||||
GeglBuffer *buffer)
|
||||
{
|
||||
guint32 saved_pos;
|
||||
guint32 offset;
|
||||
guint32 junk;
|
||||
gint width;
|
||||
gint height;
|
||||
gint bpp;
|
||||
const Babl *format;
|
||||
guint32 saved_pos;
|
||||
guint32 offset;
|
||||
guint32 junk;
|
||||
gint width;
|
||||
gint height;
|
||||
gint bpp;
|
||||
|
||||
format = gegl_buffer_get_format (buffer);
|
||||
|
||||
info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1);
|
||||
info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1);
|
||||
|
@ -1333,9 +1336,9 @@ xcf_load_hierarchy (XcfInfo *info,
|
|||
/* make sure the values in the file correspond to the values
|
||||
* calculated when the TileManager was created.
|
||||
*/
|
||||
if (width != tile_manager_width (tiles) ||
|
||||
height != tile_manager_height (tiles) ||
|
||||
bpp != tile_manager_bpp (tiles))
|
||||
if (width != gegl_buffer_get_width (buffer) ||
|
||||
height != gegl_buffer_get_height (buffer) ||
|
||||
bpp != babl_format_get_bytes_per_pixel (format))
|
||||
return FALSE;
|
||||
|
||||
/* load in the levels...we make sure that the number of levels
|
||||
|
@ -1363,7 +1366,7 @@ xcf_load_hierarchy (XcfInfo *info,
|
|||
return FALSE;
|
||||
|
||||
/* read in the level */
|
||||
if (!xcf_load_level (info, tiles))
|
||||
if (!xcf_load_level (info, buffer))
|
||||
return FALSE;
|
||||
|
||||
/* restore the saved position so we'll be ready to
|
||||
|
@ -1377,24 +1380,24 @@ xcf_load_hierarchy (XcfInfo *info,
|
|||
|
||||
|
||||
static gboolean
|
||||
xcf_load_level (XcfInfo *info,
|
||||
TileManager *tiles)
|
||||
xcf_load_level (XcfInfo *info,
|
||||
GeglBuffer *buffer)
|
||||
{
|
||||
guint32 saved_pos;
|
||||
guint32 offset, offset2;
|
||||
guint ntiles;
|
||||
gint width;
|
||||
gint height;
|
||||
gint i;
|
||||
gint fail;
|
||||
Tile *previous;
|
||||
Tile *tile;
|
||||
gint n_tile_rows;
|
||||
gint n_tile_cols;
|
||||
guint ntiles;
|
||||
gint width;
|
||||
gint height;
|
||||
gint i;
|
||||
gint fail;
|
||||
|
||||
info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1);
|
||||
info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1);
|
||||
|
||||
if (width != tile_manager_width (tiles) ||
|
||||
height != tile_manager_height (tiles))
|
||||
if (width != gegl_buffer_get_width (buffer) ||
|
||||
height != gegl_buffer_get_height (buffer))
|
||||
return FALSE;
|
||||
|
||||
/* read in the first tile offset.
|
||||
|
@ -1405,13 +1408,14 @@ xcf_load_level (XcfInfo *info,
|
|||
if (offset == 0)
|
||||
return TRUE;
|
||||
|
||||
/* Initialise the reference for the in-memory tile-compression
|
||||
*/
|
||||
previous = NULL;
|
||||
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 = tiles->ntile_rows * tiles->ntile_cols;
|
||||
ntiles = n_tile_rows * n_tile_cols;
|
||||
for (i = 0; i < ntiles; i++)
|
||||
{
|
||||
GeglRectangle rect;
|
||||
|
||||
fail = FALSE;
|
||||
|
||||
if (offset == 0)
|
||||
|
@ -1434,7 +1438,7 @@ xcf_load_level (XcfInfo *info,
|
|||
/* if the offset is 0 then we need to read in the maximum possible
|
||||
allowing for negative compression */
|
||||
if (offset2 == 0)
|
||||
offset2 = offset + TILE_WIDTH * TILE_WIDTH * 4 * 1.5;
|
||||
offset2 = offset + XCF_TILE_WIDTH * XCF_TILE_WIDTH * 4 * 1.5;
|
||||
/* 1.5 is probably more
|
||||
than we need to allow */
|
||||
|
||||
|
@ -1443,17 +1447,19 @@ xcf_load_level (XcfInfo *info,
|
|||
return FALSE;
|
||||
|
||||
/* get the tile from the tile manager */
|
||||
tile = tile_manager_get (tiles, i, TRUE, TRUE);
|
||||
gimp_gegl_buffer_get_tile_rect (buffer,
|
||||
XCF_TILE_WIDTH, XCF_TILE_HEIGHT,
|
||||
i, &rect);
|
||||
|
||||
/* read in the tile */
|
||||
switch (info->compression)
|
||||
{
|
||||
case COMPRESS_NONE:
|
||||
if (!xcf_load_tile (info, tile))
|
||||
if (!xcf_load_tile (info, buffer, &rect))
|
||||
fail = TRUE;
|
||||
break;
|
||||
case COMPRESS_RLE:
|
||||
if (!xcf_load_tile_rle (info, tile, offset2 - offset))
|
||||
if (!xcf_load_tile_rle (info, buffer, &rect, offset2 - offset))
|
||||
fail = TRUE;
|
||||
break;
|
||||
case COMPRESS_ZLIB:
|
||||
|
@ -1467,30 +1473,7 @@ xcf_load_level (XcfInfo *info,
|
|||
}
|
||||
|
||||
if (fail)
|
||||
{
|
||||
tile_release (tile, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* To potentially save memory, we compare the
|
||||
* newly-fetched tile against the last one, and
|
||||
* if they're the same we copy-on-write mirror one against
|
||||
* the other.
|
||||
*/
|
||||
if (previous != NULL)
|
||||
{
|
||||
tile_lock (previous);
|
||||
if (tile_ewidth (tile) == tile_ewidth (previous) &&
|
||||
tile_eheight (tile) == tile_eheight (previous) &&
|
||||
tile_bpp (tile) == tile_bpp (previous) &&
|
||||
memcmp (tile_data_pointer (tile, 0, 0),
|
||||
tile_data_pointer (previous, 0, 0),
|
||||
tile_size (tile)) == 0)
|
||||
tile_manager_map (tiles, i, previous);
|
||||
tile_release (previous, FALSE);
|
||||
}
|
||||
tile_release (tile, TRUE);
|
||||
previous = tile_manager_get (tiles, i, FALSE, FALSE);
|
||||
return FALSE;
|
||||
|
||||
/* restore the saved position so we'll be ready to
|
||||
* read the next offset.
|
||||
|
@ -1513,29 +1496,38 @@ xcf_load_level (XcfInfo *info,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
xcf_load_tile (XcfInfo *info,
|
||||
Tile *tile)
|
||||
xcf_load_tile (XcfInfo *info,
|
||||
GeglBuffer *buffer,
|
||||
GeglRectangle *tile_rect)
|
||||
{
|
||||
info->cp += xcf_read_int8 (info->fp, tile_data_pointer (tile, 0, 0),
|
||||
tile_size (tile));
|
||||
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);
|
||||
|
||||
info->cp += xcf_read_int8 (info->fp, tile_data, tile_size);
|
||||
|
||||
gegl_buffer_set (buffer, tile_rect, 0, NULL, tile_data,
|
||||
GEGL_AUTO_ROWSTRIDE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xcf_load_tile_rle (XcfInfo *info,
|
||||
Tile *tile,
|
||||
int data_length)
|
||||
xcf_load_tile_rle (XcfInfo *info,
|
||||
GeglBuffer *buffer,
|
||||
GeglRectangle *tile_rect,
|
||||
gint data_length)
|
||||
{
|
||||
guchar *data;
|
||||
guchar val;
|
||||
gint size;
|
||||
gint count;
|
||||
gint length;
|
||||
gint bpp;
|
||||
gint i, j;
|
||||
gint nmemb_read_successfully;
|
||||
guchar *xcfdata, *xcfodata, *xcfdatalimit;
|
||||
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 i;
|
||||
gint nmemb_read_successfully;
|
||||
guchar *xcfdata;
|
||||
guchar *xcfodata;
|
||||
guchar *xcfdatalimit;
|
||||
|
||||
/* Workaround for bug #357809: avoid crashing on g_malloc() and skip
|
||||
* this tile (return TRUE without storing data) as if it did not
|
||||
|
@ -1546,12 +1538,11 @@ xcf_load_tile_rle (XcfInfo *info,
|
|||
if (data_length <= 0)
|
||||
return TRUE;
|
||||
|
||||
bpp = tile_bpp (tile);
|
||||
|
||||
xcfdata = xcfodata = g_malloc (data_length);
|
||||
xcfdata = xcfodata = g_alloca (data_length);
|
||||
|
||||
/* we have to use fread instead of xcf_read_* because we may be
|
||||
reading past the end of the file here */
|
||||
* reading past the end of the file here
|
||||
*/
|
||||
nmemb_read_successfully = fread ((gchar *) xcfdata, sizeof (gchar),
|
||||
data_length, info->fp);
|
||||
info->cp += nmemb_read_successfully;
|
||||
|
@ -1560,9 +1551,12 @@ xcf_load_tile_rle (XcfInfo *info,
|
|||
|
||||
for (i = 0; i < bpp; i++)
|
||||
{
|
||||
data = (guchar *) tile_data_pointer (tile, 0, 0) + i;
|
||||
size = tile_ewidth (tile) * tile_eheight (tile);
|
||||
count = 0;
|
||||
guchar *data = tile_data + i;
|
||||
gint size = tile_rect->width * tile_rect->height;
|
||||
gint count = 0;
|
||||
guchar val;
|
||||
gint length;
|
||||
gint j;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
|
@ -1644,12 +1638,13 @@ xcf_load_tile_rle (XcfInfo *info,
|
|||
}
|
||||
}
|
||||
}
|
||||
g_free (xcfodata);
|
||||
|
||||
gegl_buffer_set (buffer, tile_rect, 0, NULL, tile_data,
|
||||
GEGL_AUTO_ROWSTRIDE);
|
||||
|
||||
return TRUE;
|
||||
|
||||
bogus_rle:
|
||||
if (xcfodata)
|
||||
g_free (xcfodata);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#define __XCF_PRIVATE_H__
|
||||
|
||||
|
||||
#define XCF_TILE_WIDTH 64
|
||||
#define XCF_TILE_HEIGHT 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROP_END = 0,
|
||||
|
|
Loading…
Reference in New Issue