[gimp/alxsa-psd-paths-export: 2/2] plug-ins: Export PSD with paths
- From: Alx Sa <sawyeralex src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/alxsa-psd-paths-export: 2/2] plug-ins: Export PSD with paths
- Date: Sat, 1 Oct 2022 19:17:59 +0000 (UTC)
commit fcbe548b87d5ea64056fa0d7102fff02f0e8bf1c
Author: Alx Sa <cmyk student gmail com>
Date: Fri Sep 30 18:27:17 2022 +0000
plug-ins: Export PSD with paths
Ports PSD path export from file-tiff-save.c so that paths are carried
over in PSD project files as well.
plug-ins/file-psd/psd-save.c | 172 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 172 insertions(+)
---
diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c
index 2b942e0b4d..0392b233f3 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -145,6 +145,9 @@ static void save_resources (GOutputStream *output,
gboolean export_cmyk,
gboolean export_duotone);
+static void save_paths (GOutputStream *output,
+ GimpImage *image);
+
static void save_layer_and_mask (GOutputStream *output,
GimpImage *image,
gboolean export_cmyk);
@@ -153,6 +156,9 @@ static void save_data (GOutputStream *output,
GimpImage *image,
gboolean export_cmyk);
+static void double_to_psd_fixed (gdouble value,
+ gchar *target);
+
static void xfwrite (GOutputStream *output,
gconstpointer buf,
gsize len,
@@ -844,6 +850,9 @@ save_resources (GOutputStream *output,
(int) sizeof (gint16));
}
+ /* --------------- Write paths ------------------- */
+ save_paths (output, image);
+
/* --------------- Write resolution data ------------------- */
{
gdouble xres = 0, yres = 0;
@@ -1066,6 +1075,169 @@ get_compress_channel_data (guchar *channel_data,
return len;
}
+/* Ported /from plug-ins/file-tiff/file-tiff-save.c */
+static void
+double_to_psd_fixed (gdouble value,
+ gchar *target)
+{
+ gdouble in, frac;
+ gint i, f;
+
+ frac = modf (value, &in);
+ if (frac < 0)
+ {
+ in -= 1;
+ frac += 1;
+ }
+
+ i = (gint) CLAMP (in, -16, 15);
+ f = CLAMP ((gint) (frac * 0xFFFFFF), 0, 0xFFFFFF);
+
+ target[0] = i & 0xFF;
+ target[1] = (f >> 16) & 0xFF;
+ target[2] = (f >> 8) & 0xFF;
+ target[3] = f & 0xFF;
+}
+
+/* Ported from /plug-ins/file-tiff/file-tiff-save.c */
+static void
+save_paths (GOutputStream *output,
+ GimpImage *image)
+{
+ gshort id = 0x07D0; /* Photoshop paths have IDs >= 2000 */
+ gdouble width = gimp_image_get_width (image);
+ gdouble height = gimp_image_get_height (image);
+ GList *vectors;
+ GList *iter;
+ gint v;
+ gint num_strokes;
+ gint *strokes;
+ gint s;
+
+ vectors = gimp_image_list_vectors (image);
+
+ if (! vectors)
+ return;
+
+ /* Only up to 997 paths supported */
+ for (iter = vectors, v = 0;
+ iter && v <= 997;
+ iter = g_list_next (iter), v++)
+ {
+ GString *data;
+ gchar *name, *nameend;
+ gsize len;
+ gint lenpos;
+ gchar pointrecord[26] = { 0, };
+ gchar *tmpname;
+ GError *err = NULL;
+
+ data = g_string_new ("8BIM");
+ g_string_append_c (data, id / 256);
+ g_string_append_c (data, id % 256);
+
+ /*
+ * - use iso8859-1 if possible
+ * - otherwise use UTF-8, prepended with \xef\xbb\xbf (Byte-Order-Mark)
+ */
+ name = gimp_item_get_name (iter->data);
+ tmpname = g_convert (name, -1, "iso8859-1", "utf-8", NULL, &len, &err);
+
+ if (tmpname && err == NULL)
+ {
+ g_string_append_c (data, MIN (len, 255));
+ g_string_append_len (data, tmpname, MIN (len, 255));
+ g_free (tmpname);
+ }
+ else
+ {
+ /* conversion failed, we fall back to UTF-8 */
+ len = g_utf8_strlen (name, 255 - 3); /* need three marker-bytes */
+
+ nameend = g_utf8_offset_to_pointer (name, len);
+ len = nameend - name; /* in bytes */
+ g_assert (len + 3 <= 255);
+
+ g_string_append_c (data, len + 3);
+ g_string_append_len (data, "\xEF\xBB\xBF", 3); /* Unicode 0xfeff */
+ g_string_append_len (data, name, len);
+
+ if (tmpname)
+ g_free (tmpname);
+ }
+
+ if (data->len % 2) /* padding to even size */
+ g_string_append_c (data, 0);
+ g_free (name);
+
+ lenpos = data->len;
+ g_string_append_len (data, "\0\0\0\0", 4); /* will be filled in later */
+ len = data->len; /* to calculate the data size later */
+
+ pointrecord[1] = 6; /* fill rule record */
+ g_string_append_len (data, pointrecord, 26);
+
+ strokes = gimp_vectors_get_strokes (iter->data, &num_strokes);
+
+ for (s = 0; s < num_strokes; s++)
+ {
+ GimpVectorsStrokeType type;
+ gdouble *points;
+ gint num_points;
+ gboolean closed;
+ gint p = 0;
+
+ type = gimp_vectors_stroke_get_points (iter->data, strokes[s],
+ &num_points, &points, &closed);
+
+ if (type != GIMP_VECTORS_STROKE_TYPE_BEZIER ||
+ num_points > 65535 ||
+ num_points % 6)
+ {
+ g_printerr ("psd-save: unsupported stroke type: "
+ "%d (%d points)\n", type, num_points);
+ continue;
+ }
+
+ memset (pointrecord, 0, 26);
+ pointrecord[1] = closed ? 0 : 3;
+ pointrecord[2] = (num_points / 6) / 256;
+ pointrecord[3] = (num_points / 6) % 256;
+ g_string_append_len (data, pointrecord, 26);
+
+ for (p = 0; p < num_points; p += 6)
+ {
+ pointrecord[1] = closed ? 2 : 5;
+
+ double_to_psd_fixed (points[p+1] / height, pointrecord + 2);
+ double_to_psd_fixed (points[p+0] / width, pointrecord + 6);
+ double_to_psd_fixed (points[p+3] / height, pointrecord + 10);
+ double_to_psd_fixed (points[p+2] / width, pointrecord + 14);
+ double_to_psd_fixed (points[p+5] / height, pointrecord + 18);
+ double_to_psd_fixed (points[p+4] / width, pointrecord + 22);
+
+ g_string_append_len (data, pointrecord, 26);
+ }
+ }
+
+ g_free (strokes);
+
+ /* fix up the length */
+
+ len = data->len - len;
+ data->str[lenpos + 0] = (len & 0xFF000000) >> 24;
+ data->str[lenpos + 1] = (len & 0x00FF0000) >> 16;
+ data->str[lenpos + 2] = (len & 0x0000FF00) >> 8;
+ data->str[lenpos + 3] = (len & 0x000000FF) >> 0;
+
+ xfwrite (output, data->str, data->len, "path resources data");
+ g_string_free (data, TRUE);
+ id += 0x01;
+ }
+
+ g_list_free (vectors);
+}
+
static void
save_layer_and_mask (GOutputStream *output,
GimpImage *image,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]