[gimp] Bug 730211 - Extra zeroes appear in XCF files
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 730211 - Extra zeroes appear in XCF files
- Date: Wed, 15 Oct 2014 21:19:30 +0000 (UTC)
commit 1368f73354070a40c0a73e92c5075164b3a07848
Author: Massimo Valentini <mvalentini src gnome org>
Date: Wed Oct 15 23:15:18 2014 +0200
Bug 730211 - Extra zeroes appear in XCF files
Don't use xcf_seek_end() because that seems to be broken on certain
file systems / operating systems / FUSE mounts / whatever. Instead,
seek to explicitly calculated file offsets.
Ported Massimo's patch to master and added comments --Mitch
The same commit in gimp-2-8 is a57e49b1bbd318b06c4f8d578557b63256a1e66d
app/xcf/xcf-save.c | 235 +++++++++++++++++++++-------------------------------
1 files changed, 93 insertions(+), 142 deletions(-)
---
diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c
index 1ceb521..b52d6ce 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -185,6 +185,9 @@ static gboolean xcf_save_vectors (XcfInfo *info,
} G_STMT_END
+static const guint32 zero = 0;
+
+
gboolean
xcf_save_image (XcfInfo *info,
GimpImage *image,
@@ -255,98 +258,66 @@ xcf_save_image (XcfInfo *info,
xcf_progress_update (info);
- /* save the current file position as it is the start of where
- * we place the layer offset information.
+ /* 'offset' is where we will write the next layer or channel, which
+ * is after the offset table
*/
- saved_pos = info->cp;
-
- /* seek to after the offset lists */
- xcf_check_error (xcf_seek_pos (info,
- info->cp + (n_layers + n_channels + 2) * 4,
- error));
+ offset = info->cp + (n_layers + n_channels + 2) * 4;
for (list = all_layers; list; list = g_list_next (list))
{
GimpLayer *layer = list->data;
- /* save the start offset of where we are writing
- * out the next layer.
- */
- offset = info->cp;
+ /* write the offset of the layer */
+ xcf_write_int32_check_error (info, &offset, 1);
- /* write out the layer. */
+ /* 'saved_pos' is the next slot in the layer offset table */
+ saved_pos = info->cp;
+
+ /* seek to the layer offset and save the layer */
+ xcf_check_error (xcf_seek_pos (info, offset, error));
xcf_check_error (xcf_save_layer (info, image, layer, error));
- xcf_progress_update (info);
+ /* the next layer's offset is after the layer we just wrote */
+ offset = info->cp;
- /* seek back to where we are to write out the next
- * layer offset and write it out.
- */
+ /* seek back to the next slot in the offset table */
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 layer.
- */
- xcf_check_error (xcf_seek_end (info, error));
+ xcf_progress_update (info);
}
- /* write out a '0' offset position to indicate the end
- * of the layer offsets.
- */
- offset = 0;
- xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
- saved_pos = info->cp;
- xcf_check_error (xcf_seek_end (info, error));
+ /* write out a '0' offset to indicate the end of the layer offsets */
+ xcf_write_int32_check_error (info, &zero, 1);
for (list = all_channels; list; list = g_list_next (list))
{
GimpChannel *channel = list->data;
- /* save the start offset of where we are writing
- * out the next channel.
- */
- offset = info->cp;
+ /* write the offset of the channel */
+ xcf_write_int32_check_error (info, &offset, 1);
- /* write out the layer. */
+ /* 'saved_pos' is the next slot in the channel offset table */
+ saved_pos = info->cp;
+
+ /* seek to the channel offset and save the channel */
+ xcf_check_error (xcf_seek_pos (info, offset, error));
xcf_check_error (xcf_save_channel (info, image, channel, error));
- xcf_progress_update (info);
+ /* the next channels's offset is after the layer we just wrote */
+ offset = info->cp;
- /* seek back to where we are to write out the next
- * channel offset and write it out.
- */
+ /* seek back to the next slot in the offset table */
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 channel.
- */
- xcf_check_error (xcf_seek_end (info, error));
+ xcf_progress_update (info);
}
+ /* write out a '0' offset to indicate the end of the channel offsets */
+ xcf_write_int32_check_error (info, &zero, 1);
+
g_list_free (all_layers);
g_list_free (all_channels);
- /* write out a '0' offset position to indicate the end
- * of the channel offsets.
- */
- offset = 0;
- xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
- saved_pos = info->cp;
-
return ! g_output_stream_is_closed (info->output);
}
@@ -994,7 +965,7 @@ xcf_save_prop (XcfInfo *info,
return FALSE;
}
- xcf_check_error (xcf_seek_end (info, error));
+ xcf_check_error (xcf_seek_pos (info, base + length, error));
}
}
break;
@@ -1041,7 +1012,7 @@ xcf_save_prop (XcfInfo *info,
return FALSE;
}
- xcf_check_error (xcf_seek_end (info, error));
+ xcf_check_error (xcf_seek_pos (info, base + length, error));
}
break;
@@ -1107,7 +1078,7 @@ xcf_save_prop (XcfInfo *info,
return FALSE;
}
- xcf_check_error (xcf_seek_end (info, error));
+ xcf_check_error (xcf_seek_pos (info, base + length, error));
}
break;
@@ -1204,43 +1175,36 @@ xcf_save_layer (XcfInfo *info,
/* write out the layer properties */
xcf_save_layer_props (info, image, layer, error);
- /* save the current position which is where the hierarchy offset
- * will be stored.
- */
- saved_pos = info->cp;
-
/* write out the layer tile hierarchy */
- xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
- offset = info->cp;
+ offset = info->cp + 8;
+ xcf_write_int32_check_error (info, &offset, 1);
+
+ saved_pos = info->cp;
+ xcf_check_error (xcf_seek_pos (info, offset, error));
xcf_check_error (xcf_save_buffer (info,
gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
error));
+ offset = info->cp;
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
-
- /* save the current position which is where the layer mask offset
- * will be stored.
- */
- saved_pos = info->cp;
/* write out the layer mask */
if (gimp_layer_get_mask (layer))
{
GimpLayerMask *mask = gimp_layer_get_mask (layer);
- xcf_check_error (xcf_seek_end (info, error));
- offset = info->cp;
+ xcf_write_int32_check_error (info, &offset, 1);
+ xcf_check_error (xcf_seek_pos (info, offset, error));
xcf_check_error (xcf_save_channel (info, image, GIMP_CHANNEL (mask),
error));
}
else
- offset = 0;
-
- xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
+ {
+ xcf_write_int32_check_error (info, &zero, 1);
+ xcf_check_error (xcf_seek_pos (info, offset, error));
+ }
return TRUE;
}
@@ -1282,23 +1246,14 @@ xcf_save_channel (XcfInfo *info,
/* write out the channel properties */
xcf_save_channel_props (info, image, channel, error);
- /* save the current position which is where the hierarchy offset
- * will be stored.
- */
- saved_pos = info->cp;
-
/* write out the channel tile hierarchy */
- xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
- offset = info->cp;
+ offset = info->cp + 4;
+ xcf_write_int32_check_error (info, &offset, 1);
xcf_check_error (xcf_save_buffer (info,
gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
error));
- xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
- saved_pos = info->cp;
-
return TRUE;
}
@@ -1351,11 +1306,21 @@ xcf_save_buffer (XcfInfo *info,
tmp2 = xcf_calc_levels (height, XCF_TILE_HEIGHT);
nlevels = MAX (tmp1, tmp2);
- xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
+ /* 'offset' is where we will save the next level, which is after the
+ * level offset table
+ */
+ offset = info->cp + (1 + nlevels) * 4;
for (i = 0; i < nlevels; i++)
{
- offset = info->cp;
+ /* write the offset of the level */
+ xcf_write_int32_check_error (info, &offset, 1);
+
+ /* 'saved_pos' is the next slot in the level offset table */
+ saved_pos = info->cp;
+
+ /* seek to the level offset and save the level */
+ xcf_check_error (xcf_seek_pos (info, offset, error));
if (i == 0)
{
@@ -1373,29 +1338,18 @@ xcf_save_buffer (XcfInfo *info,
xcf_write_int32_check_error (info, (guint32 *) &tmp1, 1);
}
- /* seek back to where we are to write out the next
- * level 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;
+ /* the next level's offset if after the level we just wrote */
+ offset = info->cp;
- /* seek to the end of the file which is where
- * we will write out the next level.
- */
- xcf_check_error (xcf_seek_end (info, error));
+ /* seek back to the next slot in the offset table */
+ xcf_check_error (xcf_seek_pos (info, saved_pos, error));
}
- /* write out a '0' offset position to indicate the end
- * of the level offsets.
- */
- offset = 0;
- xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
+ /* write out a '0' offset to indicate the end of the level offsets */
+ xcf_write_int32_check_error (info, &zero, 1);
+
+ /* seek to after the last level we just wrote */
+ xcf_check_error (xcf_seek_pos (info, offset, error));
return TRUE;
}
@@ -1438,16 +1392,24 @@ xcf_save_level (XcfInfo *info,
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));
+
+ /* 'offset' is where we will write the next tile, which is after the
+ * tile offset table
+ */
+ offset = info->cp + (ntiles + 1) * 4;
for (i = 0; i < ntiles; i++)
{
GeglRectangle rect;
- /* save the start offset of where we are writing
- * out the next tile.
- */
- offset = info->cp;
+ /* write the offset of the tile */
+ xcf_write_int32_check_error (info, &offset, 1);
+
+ /* 'saved_pos' is the next slot in the tile offset table */
+ saved_pos = info->cp;
+
+ /* seek to the tile offset and save the tile */
+ xcf_check_error (xcf_seek_pos (info, offset, error));
gimp_gegl_buffer_get_tile_rect (buffer,
XCF_TILE_WIDTH, XCF_TILE_HEIGHT,
@@ -1473,29 +1435,18 @@ xcf_save_level (XcfInfo *info,
return FALSE;
}
- /* 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;
+ /* the next tile's offset is after the tile we just wrote */
+ offset = 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));
+ /* seek back to the next slot in the offset table */
+ xcf_check_error (xcf_seek_pos (info, saved_pos, error));
}
- /* write out a '0' offset position to indicate the end
- * of the level offsets.
- */
- offset = 0;
- xcf_check_error (xcf_seek_pos (info, saved_pos, error));
- xcf_write_int32_check_error (info, &offset, 1);
+ /* write out a '0' offset to indicate the end of the tile offsets */
+ xcf_write_int32_check_error (info, &zero, 1);
+
+ /* seek to after the last tile we just wrote */
+ xcf_check_error (xcf_seek_pos (info, offset, error));
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]