diff --git a/plug-ins/file-psd/psd-export.c b/plug-ins/file-psd/psd-export.c index 1ce11dd72b..75c992cc85 100644 --- a/plug-ins/file-psd/psd-export.c +++ b/plug-ins/file-psd/psd-export.c @@ -123,12 +123,13 @@ typedef struct PsdImageData typedef struct PsdResourceOptions { + gboolean psb; gboolean cmyk; gboolean duotone; gboolean clipping_path; gchar *clipping_path_name; gdouble clipping_path_flatness; -} PSD_Resource_Options; +} PSDResourceOptions; static PSD_Image_Data PSDImageData; @@ -142,8 +143,8 @@ static void reshuffle_cmap_write (guchar *mapGimp); static void save_header (GOutputStream *output, GimpImage *image, - gboolean export_cmyk, - gboolean export_duotone); + PSDResourceOptions + *options); static void save_color_mode_data (GOutputStream *output, GimpImage *image, @@ -151,7 +152,7 @@ static void save_color_mode_data (GOutputStream *output, static void save_resources (GOutputStream *output, GimpImage *image, - PSD_Resource_Options + PSDResourceOptions *options); static void save_paths (GOutputStream *output, @@ -163,11 +164,13 @@ static void save_clipping_path (GOutputStream *output, static void save_layer_and_mask (GOutputStream *output, GimpImage *image, - gboolean export_cmyk); + PSDResourceOptions + *options); static void save_data (GOutputStream *output, GimpImage *image, - gboolean export_cmyk); + PSDResourceOptions + *options); static void double_to_psd_fixed (gdouble value, gchar *target); @@ -198,6 +201,10 @@ static void write_gint32 (GOutputStream *output, gint32 val, const gchar *why); +static void write_gint64 (GOutputStream *output, + gint64 val, + const gchar *why); + static void write_datablock_luni (GOutputStream *output, const gchar *val, const gchar *why); @@ -209,7 +216,8 @@ static void write_pixel_data (GOutputStream *output, goffset *ChanLenPosition, goffset rowlenOffset, gboolean write_mask, - gboolean export_cmyk); + PSDResourceOptions + *options); static GimpLayer * create_merged_image (GimpImage *image); @@ -383,6 +391,32 @@ write_gint32 (GOutputStream *output, } } +static void +write_gint64 (GOutputStream *output, + gint64 val, + const gchar *why) +{ + guchar b[8]; + gsize bytes_written; + + b[7] = val & 255; + b[6] = (val >> 8) & 255; + b[5] = (val >> 16) & 255; + b[4] = (val >> 24) & 255; + b[3] = (val >> 32) & 255; + b[2] = (val >> 40) & 255; + b[1] = (val >> 48) & 255; + b[0] = (val >> 56) & 255; + + /* FIXME: Use error */ + if (! g_output_stream_write_all (output, &b, 8, + &bytes_written, NULL, NULL)) + { + g_printerr ("%s: Error while writing '%s'\n", G_STRFUNC, why); + gimp_quit (); + } +} + static void write_datablock_luni (GOutputStream *output, const gchar *val, @@ -555,10 +589,9 @@ reshuffle_cmap_write (guchar *mapGimp) } static void -save_header (GOutputStream *output, - GimpImage *image, - gboolean export_cmyk, - gboolean export_duotone) +save_header (GOutputStream *output, + GimpImage *image, + PSDResourceOptions *options) { gint nChannels; @@ -570,7 +603,7 @@ save_header (GOutputStream *output, PSDImageData.image_height, PSDImageData.image_width, PSDImageData.baseType, PSDImageData.nChannels); - if (export_cmyk) + if (options->cmyk) { nChannels = gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)) ? @@ -583,16 +616,16 @@ save_header (GOutputStream *output, } xfwrite (output, "8BPS", 4, "signature"); - write_gint16 (output, 1, "version"); + write_gint16 (output, options->psb ? 2 : 1, "version"); write_gint32 (output, 0, "reserved 1"); /* 6 for the 'reserved' field + 4 bytes for a long */ write_gint16 (output, 0, "reserved 1"); /* and 2 bytes for a short */ write_gint16 (output, nChannels, "channels"); write_gint32 (output, PSDImageData.image_height, "rows"); write_gint32 (output, PSDImageData.image_width, "columns"); write_gint16 (output, 8 * get_bpc (image), "depth"); - if (export_cmyk) + if (options->cmyk) write_gint16 (output, PSD_CMYK, "mode"); - else if (export_duotone) + else if (options->duotone) write_gint16 (output, PSD_DUOTONE, "mode"); else write_gint16 (output, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode"); @@ -676,9 +709,9 @@ save_color_mode_data (GOutputStream *output, } static void -save_resources (GOutputStream *output, - GimpImage *image, - PSD_Resource_Options *options) +save_resources (GOutputStream *output, + GimpImage *image, + PSDResourceOptions *options) { GList *iter; gint i; @@ -1033,7 +1066,7 @@ get_compress_channel_data (guchar *channel_data, gint32 channel_rows, gint32 stride, gint32 bpc, - gint16 *LengthsTable, + gint32 *LengthsTable, guchar *remdata) { gint i; @@ -1335,9 +1368,9 @@ save_clipping_path (GOutputStream *output, } static void -save_layer_and_mask (GOutputStream *output, - GimpImage *image, - gboolean export_cmyk) +save_layer_and_mask (GOutputStream *output, + GimpImage *image, + PSDResourceOptions *options) { gint i,j; gint idChannel; @@ -1349,7 +1382,7 @@ save_layer_and_mask (GOutputStream *output, guchar layerOpacity; /* Opacity of the layer */ guchar flags; /* Layer flags */ gint nChannelsLayer; /* Number of channels of a layer */ - gint32 ChanSize; /* Data length for a channel */ + gint64 ChanSize; /* Data length for a channel */ gchar *layerName; /* Layer name */ GimpLayerMask *mask; /* Layer mask */ gint depth; /* Layer group nesting depth */ @@ -1372,12 +1405,18 @@ save_layer_and_mask (GOutputStream *output, /* Layer and mask information section */ LayerMaskPos = g_seekable_tell (G_SEEKABLE (output)); - write_gint32 (output, 0, "layers & mask information length"); + if (! options->psb) + write_gint32 (output, 0, "layers & mask information length"); + else + write_gint64 (output, 0, "layers & mask information length"); /* Layer info section */ LayerInfoPos = g_seekable_tell (G_SEEKABLE (output)); - write_gint32 (output, 0, "layers info section length"); + if (! options->psb) + write_gint32 (output, 0, "layers info section length"); + else + write_gint64 (output, 0, "layers info section length"); /* Layer structure section */ @@ -1454,7 +1493,7 @@ save_layer_and_mask (GOutputStream *output, /* Manually set channels to 4 or 5 when export as CMYK; * Can be removed once CMYK channels are accessible in GIMP */ - if (export_cmyk) + if (options->cmyk) { nChannelsLayer = gimp_drawable_has_alpha (GIMP_DRAWABLE (psd_layer->layer)) ? @@ -1486,10 +1525,17 @@ save_layer_and_mask (GOutputStream *output, will modify it later when writing data. */ ChannelLengthPos[i-1][j] = g_seekable_tell (G_SEEKABLE (output)); - ChanSize = sizeof (gint16) + (layerWidth * layerHeight * bpc); - - write_gint32 (output, ChanSize, "Channel Size"); - IFDBG(1) g_debug ("\t\t\tLength: %d", ChanSize); + if (! options->psb) + { + ChanSize = sizeof (gint16) + (layerWidth * layerHeight * bpc); + write_gint32 (output, ChanSize, "Channel Size"); + } + else + { + ChanSize = sizeof (gint32) + (layerWidth * layerHeight * bpc); + write_gint64 (output, ChanSize, "Channel Size"); + } + IFDBG(1) g_debug ("\t\t\tLength: %" G_GSIZE_FORMAT, ChanSize); } xfwrite (output, "8BIM", 4, "blend mode signature"); @@ -1661,7 +1707,7 @@ save_layer_and_mask (GOutputStream *output, IFDBG(1) g_debug ("\t\tWriting pixel data for layer slot %d", i-1); write_pixel_data (output, image, GIMP_DRAWABLE (psd_layer->layer), ChannelLengthPos[i-1], 0, - psd_layer->type != PSD_LAYER_TYPE_GROUP_END, export_cmyk); + psd_layer->type != PSD_LAYER_TYPE_GROUP_END, options); g_free (ChannelLengthPos[i-1]); } @@ -1673,18 +1719,42 @@ save_layer_and_mask (GOutputStream *output, g_seekable_seek (G_SEEKABLE (output), LayerInfoPos, G_SEEK_SET, NULL, NULL /*FIXME: error*/); - write_gint32 (output, eof_pos - LayerInfoPos - sizeof (gint32), "layers info section length"); - IFDBG(1) g_debug ("\t\tTotal layers info section length: %d", - (int) (eof_pos - LayerInfoPos - sizeof (gint32))); + if (! options->psb) + { + write_gint32 (output, eof_pos - LayerInfoPos - sizeof (gint32), + "layers info section length"); + IFDBG(1) g_debug ("\t\tTotal layers info section length: %d", + (gint) (eof_pos - LayerInfoPos - sizeof (gint32))); + } + else + { + write_gint64 (output, eof_pos - LayerInfoPos - sizeof (gint64), + "layers info section length"); + IFDBG(1) g_debug ("\t\tTotal layers info section length: %" + G_GSIZE_FORMAT, + (gint64) (eof_pos - LayerInfoPos - sizeof (gint64))); + } /* Write actual size of Layer and mask information section */ g_seekable_seek (G_SEEKABLE (output), LayerMaskPos, G_SEEK_SET, NULL, NULL /*FIXME: error*/); - write_gint32 (output, eof_pos - LayerMaskPos - sizeof (gint32), "layers & mask information length"); - IFDBG(1) g_debug ("\t\tTotal layers & mask information length: %d", - (int) (eof_pos - LayerMaskPos - sizeof (gint32))); + if (! options->psb) + { + write_gint32 (output, eof_pos - LayerMaskPos - sizeof (gint32), + "layers & mask information length"); + IFDBG(1) g_debug ("\t\tTotal layers & mask information length: %d", + (gint) (eof_pos - LayerMaskPos - sizeof (gint32))); + } + else + { + write_gint64 (output, eof_pos - LayerMaskPos - sizeof (gint64), + "layers & mask information length"); + IFDBG(1) g_debug ("\t\tTotal layers & mask information length: %" + G_GSIZE_FORMAT, + (gint64) (eof_pos - LayerMaskPos - sizeof (gint64))); + } /* Return to EOF to continue writing */ @@ -1694,13 +1764,13 @@ save_layer_and_mask (GOutputStream *output, } static void -write_pixel_data (GOutputStream *output, - GimpImage *image, - GimpDrawable *drawable, - goffset *ChanLenPosition, - goffset ltable_offset, - gboolean write_mask, - gboolean export_cmyk) +write_pixel_data (GOutputStream *output, + GimpImage *image, + GimpDrawable *drawable, + goffset *ChanLenPosition, + goffset ltable_offset, + gboolean write_mask, + PSDResourceOptions *options) { GeglBuffer *buffer = gimp_drawable_get_buffer (drawable); const Babl *format; @@ -1717,7 +1787,7 @@ write_pixel_data (GOutputStream *output, gint32 colors; gint32 y; gsize len; /* Length of compressed data */ - gint16 *LengthsTable; /* Lengths of every compressed row */ + gint32 *LengthsTable; /* Lengths of every compressed row */ guchar *rledata; /* Compressed data from a region */ guchar *data; /* Temporary copy of pixel data */ goffset length_table_pos; /* position in file of the length table */ @@ -1743,7 +1813,7 @@ write_pixel_data (GOutputStream *output, else format = get_pixel_format (drawable); - if (export_cmyk && ! gimp_item_is_channel (GIMP_ITEM (drawable))) + if (options->cmyk && ! gimp_item_is_channel (GIMP_ITEM (drawable))) { profile = gimp_image_get_simulation_profile (image); if (profile && gimp_color_profile_is_cmyk (profile)) @@ -1790,7 +1860,7 @@ write_pixel_data (GOutputStream *output, ! gimp_drawable_is_indexed (drawable)) colors -= 1; - LengthsTable = g_new (gint16, height); + LengthsTable = g_new (gint32, height); rledata = g_new (guchar, (MIN (height, tile_height) * (width + 10 + (width / 100))) * bpc); @@ -1833,15 +1903,26 @@ write_pixel_data (GOutputStream *output, if (ltable_offset > 0) { - length_table_pos = ltable_offset + 2 * chan * height; + gint byte_offset = (! options->psb) ? 2 : 4; + + length_table_pos = ltable_offset + byte_offset * chan * height; } else { length_table_pos = g_seekable_tell (G_SEEKABLE (output)); - xfwrite (output, LengthsTable, height * sizeof(gint16), - "Dummy RLE length"); - len += height * sizeof(gint16); + if (! options->psb) + { + xfwrite (output, LengthsTable, height * sizeof (gint16), + "Dummy RLE length"); + len += height * sizeof (gint16); + } + else + { + xfwrite (output, LengthsTable, height * sizeof (gint32), + "Dummy RLE length"); + len += height * sizeof (gint32); + } IFDBG(3) g_debug ("\t\t\t\t. ltable, pos %" G_GOFFSET_FORMAT " len %" G_GSIZE_FORMAT, length_table_pos, len); @@ -1872,14 +1953,23 @@ write_pixel_data (GOutputStream *output, length_table_pos, G_SEEK_SET, NULL, NULL /*FIXME: error*/); for (j = 0; j < height; j++) /* write real length table */ - write_gint16 (output, LengthsTable[j], "RLE length"); + { + if (! options->psb) + write_gint16 (output, LengthsTable[j], "RLE length"); + else + write_gint32 (output, LengthsTable[j], "RLE length"); + } if (ChanLenPosition) /* Update total compressed length */ { g_seekable_seek (G_SEEKABLE (output), ChanLenPosition[i], G_SEEK_SET, NULL, NULL /*FIXME: error*/); - write_gint32 (output, len, "channel data length"); + + if (! options->psb) + write_gint32 (output, len, "channel data length"); + else + write_gint64 (output, len, "channel data length"); IFDBG(1) g_debug ("\t\tUpdating data len to %" G_GSIZE_FORMAT, len); } g_seekable_seek (G_SEEKABLE (output), @@ -1950,7 +2040,10 @@ write_pixel_data (GOutputStream *output, NULL, NULL /*FIXME: error*/); for (j = 0; j < height; j++) /* write real length table */ { - write_gint16 (output, LengthsTable[j], "RLE length"); + if (! options->psb) + write_gint16 (output, LengthsTable[j], "RLE length"); + else + write_gint32 (output, LengthsTable[j], "RLE length"); IFDBG(3) g_debug ("\t\t\t\t. Updating RLE len %d", LengthsTable[j]); } @@ -1962,7 +2055,10 @@ write_pixel_data (GOutputStream *output, ChanLenPosition[components], G_SEEK_SET, NULL, NULL /*FIXME: error*/); - write_gint32 (output, len, "channel data length"); + if (! options->psb) + write_gint32 (output, len, "channel data length"); + else + write_gint64 (output, len, "channel data length"); IFDBG(1) g_debug ("\t\tUpdating data len to %" G_GSIZE_FORMAT ", at %" G_GOFFSET_FORMAT, len, g_seekable_tell (G_SEEKABLE (output))); @@ -1984,9 +2080,9 @@ write_pixel_data (GOutputStream *output, } static void -save_data (GOutputStream *output, - GimpImage *image, - gboolean export_cmyk) +save_data (GOutputStream *output, + GimpImage *image, + PSDResourceOptions *options) { GList *iter; gint ChanCount; @@ -1997,7 +2093,7 @@ save_data (GOutputStream *output, IFDBG(1) g_debug ("Function: save_data"); - if (! export_cmyk) + if (! options->cmyk) chan = nChansLayer (PSDImageData.baseType, gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)), 0); else @@ -2015,18 +2111,25 @@ save_data (GOutputStream *output, for (i = 0; i < ChanCount; i++) for (j = 0; j < imageHeight; j++) - write_gint16 (output, 0, "junk line lengths"); + { + if (! options->psb) + write_gint16 (output, 0, "junk line lengths"); + else + write_gint32 (output, 0, "junk line lengths"); + } IFDBG(1) g_debug ("\t\tWriting compressed image data"); write_pixel_data (output, image, GIMP_DRAWABLE (PSDImageData.merged_layer), - NULL, offset, FALSE, export_cmyk); + NULL, offset, FALSE, options); for (iter = PSDImageData.lChannels; iter; iter = g_list_next (iter)) { + gint bpc = (! options->psb) ? 2 : 4; + IFDBG(1) g_debug ("\t\tWriting compressed channel data for channel %d", i); write_pixel_data (output, image, iter->data, NULL, - offset + 2*imageHeight*chan, FALSE, - export_cmyk); //check how imgs are channels here + offset + bpc * imageHeight * chan, FALSE, + options); //check how imgs are channels here chan++; } } @@ -2129,18 +2232,22 @@ clear_image_data (void) } gboolean -export_image (GFile *file, - GimpImage *image, - GObject *config, - GError **error) +export_image (GFile *file, + GimpImage *image, + GimpProcedure *procedure, + GObject *config, + GError **error) { - GOutputStream *output; - GeglBuffer *buffer; - GList *iter; - GError *local_error = NULL; - GimpParasite *parasite = NULL; - PSD_Resource_Options resource_options; + GOutputStream *output; + GeglBuffer *buffer; + GList *iter; + GError *local_error = NULL; + GimpParasite *parasite = NULL; + PSDResourceOptions resource_options; + gsize max_dim; + resource_options.psb = + (! strcmp (gimp_procedure_get_name (procedure), EXPORT_PSB_PROC)); g_object_get (config, "cmyk", &resource_options.cmyk, "duotone", &resource_options.duotone, @@ -2154,14 +2261,23 @@ export_image (GFile *file, if (resource_options.cmyk) resource_options.duotone = FALSE; - if (gimp_image_get_width (image) > 30000 || - gimp_image_get_height (image) > 30000) + max_dim = (! resource_options.psb) ? 30000 : 300000; + + if (gimp_image_get_width (image) > max_dim || + gimp_image_get_height (image) > max_dim) { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("Unable to export '%s'. The PSD file format does not " - "support images that are more than 30,000 pixels wide " - "or tall."), - gimp_file_get_utf8_name (file)); + if (! resource_options.psb) + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + _("Unable to export '%s'. The PSD file format does not " + "support images that are more than 30,000 pixels wide " + "or tall."), + gimp_file_get_utf8_name (file)); + else + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + _("Unable to export '%s'. The PSB file format does not " + "support images that are more than 300,000 pixels wide " + "or tall."), + gimp_file_get_utf8_name (file)); return FALSE; } @@ -2195,14 +2311,21 @@ export_image (GFile *file, { buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer->layer)); - if (gegl_buffer_get_width (buffer) > 30000 || - gegl_buffer_get_height (buffer) > 30000) + if (gegl_buffer_get_width (buffer) > max_dim || + gegl_buffer_get_height (buffer) > max_dim) { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("Unable to export '%s'. The PSD file format does not " - "support images with layers that are more than 30,000 " - "pixels wide or tall."), - gimp_file_get_utf8_name (file)); + if (! resource_options.psb) + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + _("Unable to export '%s'. The PSD file format " + "does not support images with layers that are " + "more than 30,000 pixels wide or tall."), + gimp_file_get_utf8_name (file)); + else + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + _("Unable to export '%s'. The PSB file format " + "does not support images with layers that are " + "more than 300,000 pixels wide or tall."), + gimp_file_get_utf8_name (file)); clear_image_data (); return FALSE; } @@ -2235,20 +2358,27 @@ export_image (GFile *file, IFDBG(1) g_debug ("\tFile '%s' has been opened", gimp_file_get_utf8_name (file)); - save_header (output, image, resource_options.cmyk, resource_options.duotone); + save_header (output, image, &resource_options); save_color_mode_data (output, image, resource_options.duotone); save_resources (output, image, &resource_options); /* PSD format does not support layers in indexed images */ if (PSDImageData.baseType == GIMP_INDEXED) - write_gint32 (output, 0, "layers info section length"); + { + if (! resource_options.psb) + write_gint32 (output, 0, "layers info section length"); + else + write_gint64 (output, 0, "layers info section length"); + } else - save_layer_and_mask (output, image, resource_options.cmyk); + { + save_layer_and_mask (output, image, &resource_options); + } /* If this is an indexed image, write now channel and layer info */ - save_data (output, image, resource_options.cmyk); + save_data (output, image, &resource_options); /* Delete merged image now */ diff --git a/plug-ins/file-psd/psd-export.h b/plug-ins/file-psd/psd-export.h index 8734bd14e8..5691aa63b2 100644 --- a/plug-ins/file-psd/psd-export.h +++ b/plug-ins/file-psd/psd-export.h @@ -19,13 +19,14 @@ #define __PSD_EXPORT_H__ -gboolean export_image (GFile *file, - GimpImage *image, - GObject *config, - GError **error); +gboolean export_image (GFile *file, + GimpImage *image, + GimpProcedure *procedure, + GObject *config, + GError **error); -gboolean save_dialog (GimpImage *image, - GimpProcedure *procedure, - GObject *config); +gboolean save_dialog (GimpImage *image, + GimpProcedure *procedure, + GObject *config); #endif /* __PSD_EXPORT_H__ */ diff --git a/plug-ins/file-psd/psd.c b/plug-ins/file-psd/psd.c index 93cd37c339..77ba6976b4 100644 --- a/plug-ins/file-psd/psd.c +++ b/plug-ins/file-psd/psd.c @@ -115,6 +115,7 @@ psd_query_procedures (GimpPlugIn *plug_in) list = g_list_append (list, g_strdup (LOAD_PROC)); list = g_list_append (list, g_strdup (LOAD_MERGED_PROC)); list = g_list_append (list, g_strdup (EXPORT_PROC)); + list = g_list_append (list, g_strdup (EXPORT_PSB_PROC)); list = g_list_append (list, g_strdup (LOAD_METADATA_PROC)); return list; @@ -204,7 +205,8 @@ psd_create_procedure (GimpPlugIn *plug_in, "John Marshall", "2007"); } - else if (! strcmp (name, EXPORT_PROC)) + else if (! strcmp (name, EXPORT_PROC) || + ! strcmp (name, EXPORT_PSB_PROC)) { procedure = gimp_export_procedure_new (plug_in, name, GIMP_PDB_PROC_TYPE_PLUGIN, @@ -212,30 +214,54 @@ psd_create_procedure (GimpPlugIn *plug_in, gimp_procedure_set_image_types (procedure, "*"); - gimp_procedure_set_menu_label (procedure, _("Photoshop image")); - gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure), - _("Photoshop image")); + if (! strcmp (name, EXPORT_PROC)) + { + gimp_procedure_set_menu_label (procedure, _("Photoshop image")); + gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure), + _("Photoshop image")); + + gimp_procedure_set_documentation (procedure, + _("Saves files in the Photoshop (TM) " + "PSD file format"), + _("This plug-in saves files of Adobe " + "Photoshop (TM) native PSD format. " + "These files may be of any image type " + "supported by GIMP, with or without " + "layers, layer masks, aux channels " + "and guides."), + name); + gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), + "image/x-psd"); + gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), + "psd"); + } + else + { + gimp_procedure_set_menu_label (procedure, _("Photoshop Large image")); + gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure), + _("Photoshop Large image")); + + gimp_procedure_set_documentation (procedure, + _("Saves files in the Photoshop (TM) " + "Large PSB file format"), + _("This plug-in saves files of Adobe " + "Photoshop (TM) Large native PSB format. " + "These files may be of any image type " + "supported by GIMP, with or without " + "layers, layer masks, aux channels " + "and guides."), + name); + gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), + "image/x-psb"); + gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), + "psb"); + } - gimp_procedure_set_documentation (procedure, - _("Saves files in the Photoshop (TM) " - "PSD file format"), - _("This plug-in saves files of Adobe " - "Photoshop (TM) native PSD format. " - "These files may be of any image type " - "supported by GIMP, with or without " - "layers, layer masks, aux channels " - "and guides."), - name); gimp_procedure_set_attribution (procedure, "Monigotes", "Monigotes", "2000"); - gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), - "image/x-psd"); - gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), - "psd"); - gimp_export_procedure_set_capabilities (GIMP_EXPORT_PROCEDURE (procedure), GIMP_EXPORT_CAN_HANDLE_RGB | GIMP_EXPORT_CAN_HANDLE_GRAY | @@ -463,7 +489,7 @@ psd_export (GimpProcedure *procedure, export = gimp_export_options_get_image (options, &image); drawables = gimp_image_list_layers (image); - if (export_image (file, image, G_OBJECT (config), &error)) + if (export_image (file, image, procedure, G_OBJECT (config), &error)) { if (metadata) gimp_metadata_set_bits_per_sample (metadata, 8); diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h index bf90a1951a..059fb1d666 100644 --- a/plug-ins/file-psd/psd.h +++ b/plug-ins/file-psd/psd.h @@ -35,6 +35,7 @@ #define LOAD_MERGED_PROC "file-psd-load-merged" #define LOAD_THUMB_PROC "file-psd-load-thumb" #define EXPORT_PROC "file-psd-export" +#define EXPORT_PSB_PROC "file-psb-export" #define LOAD_METADATA_PROC "file-psd-load-metadata" #define PLUG_IN_BINARY "file-psd" #define PLUG_IN_ROLE "gimp-file-psd"