/* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * GIMP PSD Plug-in * Copyright 2007 by John Marshall * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include #include #include "psd.h" #include "psd-util.h" #include "psd-image-res-load.h" #include "psd-layer-res-load.h" #include "psd-load.h" #include "libgimp/stdplugins-intl.h" #define COMP_MODE_SIZE sizeof(guint16) /* Local function prototypes */ static gint read_header_block (PSDimage *img_a, FILE *f, GError **error); static gint read_color_mode_block (PSDimage *img_a, FILE *f, GError **error); static gint read_image_resource_block (PSDimage *img_a, FILE *f, GError **error); static PSDlayer ** read_layer_block (PSDimage *img_a, FILE *f, GError **error); static gint read_merged_image_block (PSDimage *img_a, FILE *f, GError **error); static gint32 create_gimp_image (PSDimage *img_a, const gchar *filename); static gint add_color_map (gint32 image_id, PSDimage *img_a); static gint add_image_resources (gint32 image_id, PSDimage *img_a, FILE *f, gboolean *resolution_loaded, gboolean *profile_loaded, GError **error); static gint add_layers (gint32 image_id, PSDimage *img_a, PSDlayer **lyr_a, FILE *f, GError **error); static gint add_merged_image (gint32 image_id, PSDimage *img_a, FILE *f, GError **error); /* Local utility function prototypes */ static gint32 add_clipping_group (gint32 image_id, gint32 parent_id); static gchar * get_psd_color_mode_name (PSDColorMode mode); static void psd_to_gimp_color_map (guchar *map256); static GimpImageType get_gimp_image_type (GimpImageBaseType image_base_type, gboolean alpha); static gint read_channel_data (PSDchannel *channel, guint16 bps, guint16 compression, const guint16 *rle_pack_len, FILE *f, guint32 comp_len, GError **error); static void convert_1_bit (const gchar *src, gchar *dst, guint32 rows, guint32 columns); static const Babl* get_layer_format (PSDimage *img_a, gboolean alpha); static const Babl* get_channel_format (PSDimage *img_a); static const Babl* get_mask_format (PSDimage *img_a); /* Main file load function */ gint32 load_image (const gchar *filename, gboolean merged_image_only, gboolean *resolution_loaded, gboolean *profile_loaded, GError **load_error) { FILE *f; GStatBuf st; PSDimage img_a; PSDlayer **lyr_a; gint32 image_id = -1; GError *error = NULL; img_a.cmyk_transform = img_a.cmyk_transform_alpha = NULL; img_a.cmyk_profile = NULL; /* ----- Open PSD file ----- */ if (g_stat (filename, &st) == -1) return -1; gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); IFDBG(1) g_debug ("Open file %s", gimp_filename_to_utf8 (filename)); f = g_fopen (filename, "rb"); if (f == NULL) { g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); return -1; } img_a.merged_image_only = merged_image_only; /* ----- Read the PSD file Header block ----- */ IFDBG(2) g_debug ("Read header block"); if (read_header_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.1); /* ----- Read the PSD file Color Mode block ----- */ IFDBG(2) g_debug ("Read color mode block"); if (read_color_mode_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.2); /* ----- Read the PSD file Image Resource block ----- */ IFDBG(2) g_debug ("Read image resource block"); if (read_image_resource_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.3); /* ----- Read the PSD file Layer & Mask block ----- */ IFDBG(2) g_debug ("Read layer & mask block"); lyr_a = read_layer_block (&img_a, f, &error); if (! img_a.merged_image_only && img_a.num_layers != 0 && lyr_a == NULL) goto load_error; gimp_progress_update (0.4); /* ----- Read the PSD file Merged Image Data block ----- */ IFDBG(2) g_debug ("Read merged image and extra alpha channel block"); if (read_merged_image_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.5); /* ----- Create GIMP image ----- */ IFDBG(2) g_debug ("Create GIMP image"); image_id = create_gimp_image (&img_a, filename); if (image_id < 0) goto load_error; gimp_progress_update (0.6); /* ----- Add color map ----- */ IFDBG(2) g_debug ("Add color map"); if (add_color_map (image_id, &img_a) < 0) goto load_error; gimp_progress_update (0.7); /* ----- Add image resources ----- */ IFDBG(2) g_debug ("Add image resources"); if (add_image_resources (image_id, &img_a, f, resolution_loaded, profile_loaded, &error) < 0) goto load_error; gimp_progress_update (0.8); /* ----- Add layers -----*/ IFDBG(2) g_debug ("Add layers"); if (add_layers (image_id, &img_a, lyr_a, f, &error) < 0) goto load_error; gimp_progress_update (0.9); /* ----- Add merged image data and extra alpha channels ----- */ IFDBG(2) g_debug ("Add merged image data and extra alpha channels"); if (add_merged_image (image_id, &img_a, f, &error) < 0) goto load_error; gimp_progress_update (1.0); IFDBG(2) g_debug ("Close file & return, image id: %d", image_id); IFDBG(1) g_debug ("\n----------------------------------------" "----------------------------------------\n"); gimp_image_clean_all (image_id); gimp_image_undo_enable (image_id); fclose (f); return image_id; /* ----- Process load errors ----- */ load_error: if (error) { g_set_error (load_error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error loading PSD file: %s"), error->message); g_error_free (error); } /* Delete partially loaded image */ if (image_id > 0) gimp_image_delete (image_id); /* Close file if Open */ if (! (f == NULL)) fclose (f); return -1; } /* Local functions */ static gint read_header_block (PSDimage *img_a, FILE *f, GError **error) { guint16 version; gchar sig[4]; gchar buf[6]; if (fread (sig, 4, 1, f) < 1 || fread (&version, 2, 1, f) < 1 || fread (buf, 6, 1, f) < 1 || fread (&img_a->channels, 2, 1, f) < 1 || fread (&img_a->rows, 4, 1, f) < 1 || fread (&img_a->columns, 4, 1, f) < 1 || fread (&img_a->bps, 2, 1, f) < 1 || fread (&img_a->color_mode, 2, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } version = GUINT16_FROM_BE (version); img_a->channels = GUINT16_FROM_BE (img_a->channels); img_a->rows = GUINT32_FROM_BE (img_a->rows); img_a->columns = GUINT32_FROM_BE (img_a->columns); img_a->bps = GUINT16_FROM_BE (img_a->bps); img_a->color_mode = GUINT16_FROM_BE (img_a->color_mode); IFDBG(1) g_debug ("\n\n\tSig: %.4s\n\tVer: %d\n\tChannels: " "%d\n\tSize: %dx%d\n\tBPS: %d\n\tMode: %d\n", sig, version, img_a->channels, img_a->columns, img_a->rows, img_a->bps, img_a->color_mode); if (memcmp (sig, "8BPS", 4) != 0) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Not a valid Photoshop document file")); return -1; } if (version != 1) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported file format version: %d"), version); return -1; } if (img_a->channels > MAX_CHANNELS) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Too many channels in file: %d"), img_a->channels); return -1; } /* Photoshop CS (version 8) supports 300000 x 300000, but this is currently larger than GIMP_MAX_IMAGE_SIZE */ if (img_a->rows < 1 || img_a->rows > GIMP_MAX_IMAGE_SIZE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid image height: %d"), img_a->rows); return -1; } if (img_a->columns < 1 || img_a->columns > GIMP_MAX_IMAGE_SIZE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid image width: %d"), img_a->columns); return -1; } /* img_a->rows is sanitized above, so a division by zero is avoided here */ if (img_a->columns > G_MAXINT32 / img_a->rows) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid image size: %dx%d"), img_a->columns, img_a->rows); return -1; } if (img_a->color_mode != PSD_BITMAP && img_a->color_mode != PSD_GRAYSCALE && img_a->color_mode != PSD_INDEXED && img_a->color_mode != PSD_RGB && img_a->color_mode != PSD_MULTICHANNEL && img_a->color_mode != PSD_CMYK && img_a->color_mode != PSD_DUOTONE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported color mode: %s"), get_psd_color_mode_name (img_a->color_mode)); return -1; } if (img_a->color_mode == PSD_CMYK) { if (img_a->bps != 8) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported color mode: %s"), get_psd_color_mode_name (img_a->color_mode)); return -1; } } /* Warning for unsupported bit depth */ switch (img_a->bps) { case 32: IFDBG(3) g_debug ("32 Bit Data"); break; case 16: IFDBG(3) g_debug ("16 Bit Data"); break; case 8: IFDBG(3) g_debug ("8 Bit Data"); break; case 1: IFDBG(3) g_debug ("1 Bit Data"); break; default: g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported bit depth: %d"), img_a->bps); return -1; break; } return 0; } static gint read_color_mode_block (PSDimage *img_a, FILE *f, GError **error) { static guchar cmap[] = { 0, 0, 0, 255, 255, 255 }; guint32 block_len; img_a->color_map_entries = 0; img_a->color_map_len = 0; if (fread (&block_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } block_len = GUINT32_FROM_BE (block_len); IFDBG(1) g_debug ("Color map block size = %d", block_len); if (block_len == 0) { if (img_a->color_mode == PSD_INDEXED || img_a->color_mode == PSD_DUOTONE ) { IFDBG(1) g_debug ("No color block for indexed or duotone image"); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("The file is corrupt!")); return -1; } } else if (img_a->color_mode == PSD_INDEXED) { if (block_len != 768) { IFDBG(1) g_debug ("Invalid color block size for indexed image"); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("The file is corrupt!")); return -1; } else { img_a->color_map_len = block_len; img_a->color_map = g_malloc (img_a->color_map_len); if (fread (img_a->color_map, block_len, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } else { psd_to_gimp_color_map (img_a->color_map); img_a->color_map_entries = 256; } } } else if (img_a->color_mode == PSD_DUOTONE) { img_a->color_map_len = block_len; img_a->color_map = g_malloc (img_a->color_map_len); if (fread (img_a->color_map, block_len, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } } /* Create color map for bitmap image */ if (img_a->color_mode == PSD_BITMAP) { img_a->color_map_len = 6; img_a->color_map = g_malloc (img_a->color_map_len); memcpy (img_a->color_map, cmap, img_a->color_map_len); img_a->color_map_entries = 2; } IFDBG(2) g_debug ("Color map data length %d", img_a->color_map_len); return 0; } static gint read_image_resource_block (PSDimage *img_a, FILE *f, GError **error) { guint32 block_len; guint32 block_end; if (fread (&block_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } img_a->image_res_len = GUINT32_FROM_BE (block_len); IFDBG(1) g_debug ("Image resource block size = %d", (int)img_a->image_res_len); img_a->image_res_start = ftell (f); block_end = img_a->image_res_start + img_a->image_res_len; if (fseek (f, block_end, SEEK_SET) < 0) { psd_set_error (feof (f), errno, error); return -1; } return 0; } static PSDlayer ** read_layer_info (PSDimage *img_a, FILE *f, GError **error) { PSDlayer **lyr_a = NULL; guint32 block_len; guint32 block_rem; gint32 read_len; gint32 write_len; gint lidx; /* Layer index */ gint cidx; /* Channel index */ /* Get number of layers */ if (fread (&img_a->num_layers, 2, 1, f) < 1) { psd_set_error (feof (f), errno, error); img_a->num_layers = -1; return NULL; } img_a->num_layers = GINT16_FROM_BE (img_a->num_layers); IFDBG(2) g_debug ("Number of layers: %d", img_a->num_layers); if (img_a->num_layers < 0) { img_a->transparency = TRUE; img_a->num_layers = -img_a->num_layers; } if (! img_a->merged_image_only && img_a->num_layers) { /* Read layer records */ PSDlayerres res_a; /* Create pointer array for the layer records */ lyr_a = g_new (PSDlayer *, img_a->num_layers); for (lidx = 0; lidx < img_a->num_layers; ++lidx) { /* Allocate layer record */ lyr_a[lidx] = (PSDlayer *) g_malloc (sizeof (PSDlayer) ); /* Initialise record */ lyr_a[lidx]->drop = FALSE; lyr_a[lidx]->id = 0; lyr_a[lidx]->group_type = 0; if (fread (&lyr_a[lidx]->top, 4, 1, f) < 1 || fread (&lyr_a[lidx]->left, 4, 1, f) < 1 || fread (&lyr_a[lidx]->bottom, 4, 1, f) < 1 || fread (&lyr_a[lidx]->right, 4, 1, f) < 1 || fread (&lyr_a[lidx]->num_channels, 2, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } lyr_a[lidx]->top = GINT32_FROM_BE (lyr_a[lidx]->top); lyr_a[lidx]->left = GINT32_FROM_BE (lyr_a[lidx]->left); lyr_a[lidx]->bottom = GINT32_FROM_BE (lyr_a[lidx]->bottom); lyr_a[lidx]->right = GINT32_FROM_BE (lyr_a[lidx]->right); lyr_a[lidx]->num_channels = GUINT16_FROM_BE (lyr_a[lidx]->num_channels); if (lyr_a[lidx]->num_channels > MAX_CHANNELS) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Too many channels in layer: %d"), lyr_a[lidx]->num_channels); return NULL; } if (lyr_a[lidx]->bottom < lyr_a[lidx]->top || lyr_a[lidx]->bottom - lyr_a[lidx]->top > GIMP_MAX_IMAGE_SIZE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid layer height: %d"), lyr_a[lidx]->bottom - lyr_a[lidx]->top); return NULL; } if (lyr_a[lidx]->right < lyr_a[lidx]->left || lyr_a[lidx]->right - lyr_a[lidx]->left > GIMP_MAX_IMAGE_SIZE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid layer width: %d"), lyr_a[lidx]->right - lyr_a[lidx]->left); return NULL; } if ((lyr_a[lidx]->right - lyr_a[lidx]->left) > G_MAXINT32 / MAX (lyr_a[lidx]->bottom - lyr_a[lidx]->top, 1)) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid layer size: %dx%d"), lyr_a[lidx]->right - lyr_a[lidx]->left, lyr_a[lidx]->bottom - lyr_a[lidx]->top); return NULL; } IFDBG(2) g_debug ("Layer %d, Coords %d %d %d %d, channels %d, ", lidx, lyr_a[lidx]->left, lyr_a[lidx]->top, lyr_a[lidx]->right, lyr_a[lidx]->bottom, lyr_a[lidx]->num_channels); lyr_a[lidx]->chn_info = g_new (ChannelLengthInfo, lyr_a[lidx]->num_channels); for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx) { if (fread (&lyr_a[lidx]->chn_info[cidx].channel_id, 2, 1, f) < 1 || fread (&lyr_a[lidx]->chn_info[cidx].data_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } lyr_a[lidx]->chn_info[cidx].channel_id = GINT16_FROM_BE (lyr_a[lidx]->chn_info[cidx].channel_id); lyr_a[lidx]->chn_info[cidx].data_len = GUINT32_FROM_BE (lyr_a[lidx]->chn_info[cidx].data_len); img_a->layer_data_len += lyr_a[lidx]->chn_info[cidx].data_len; IFDBG(3) g_debug ("Channel ID %d, data len %d", lyr_a[lidx]->chn_info[cidx].channel_id, lyr_a[lidx]->chn_info[cidx].data_len); } if (fread (lyr_a[lidx]->mode_key, 4, 1, f) < 1 || fread (lyr_a[lidx]->blend_mode, 4, 1, f) < 1 || fread (&lyr_a[lidx]->opacity, 1, 1, f) < 1 || fread (&lyr_a[lidx]->clipping, 1, 1, f) < 1 || fread (&lyr_a[lidx]->flags, 1, 1, f) < 1 || fread (&lyr_a[lidx]->filler, 1, 1, f) < 1 || fread (&lyr_a[lidx]->extra_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } if (memcmp (lyr_a[lidx]->mode_key, "8BIM", 4) != 0) { IFDBG(1) g_debug ("Incorrect layer mode signature %.4s", lyr_a[lidx]->mode_key); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("The file is corrupt!")); return NULL; } lyr_a[lidx]->layer_flags.trans_prot = lyr_a[lidx]->flags & 1 ? TRUE : FALSE; lyr_a[lidx]->layer_flags.visible = lyr_a[lidx]->flags & 2 ? FALSE : TRUE; if (lyr_a[lidx]->flags & 8) lyr_a[lidx]->layer_flags.irrelevant = lyr_a[lidx]->flags & 16 ? TRUE : FALSE; else lyr_a[lidx]->layer_flags.irrelevant = FALSE; lyr_a[lidx]->extra_len = GUINT32_FROM_BE (lyr_a[lidx]->extra_len); block_rem = lyr_a[lidx]->extra_len; IFDBG(2) g_debug ("\n\tLayer mode sig: %.4s\n\tBlend mode: %.4s\n\t" "Opacity: %d\n\tClipping: %d\n\tExtra data len: %d\n\t" "Alpha lock: %d\n\tVisible: %d\n\tIrrelevant: %d", lyr_a[lidx]->mode_key, lyr_a[lidx]->blend_mode, lyr_a[lidx]->opacity, lyr_a[lidx]->clipping, lyr_a[lidx]->extra_len, lyr_a[lidx]->layer_flags.trans_prot, lyr_a[lidx]->layer_flags.visible, lyr_a[lidx]->layer_flags.irrelevant); IFDBG(3) g_debug ("Remaining length %d", block_rem); /* Layer mask data */ if (fread (&block_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } block_len = GUINT32_FROM_BE (block_len); IFDBG(3) g_debug ("Layer mask record size %u", block_len); if (block_len + 4 > block_rem) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid mask info size: %d"), block_len); return NULL; } block_rem -= (block_len + 4); IFDBG(3) g_debug ("Remaining length %d", block_rem); lyr_a[lidx]->layer_mask_extra.top = 0; lyr_a[lidx]->layer_mask_extra.left = 0; lyr_a[lidx]->layer_mask_extra.bottom = 0; lyr_a[lidx]->layer_mask_extra.right = 0; lyr_a[lidx]->layer_mask.top = 0; lyr_a[lidx]->layer_mask.left = 0; lyr_a[lidx]->layer_mask.bottom = 0; lyr_a[lidx]->layer_mask.right = 0; lyr_a[lidx]->layer_mask.def_color = 0; lyr_a[lidx]->layer_mask.extra_def_color = 0; lyr_a[lidx]->layer_mask.flags = 0; lyr_a[lidx]->layer_mask.extra_flags = 0; lyr_a[lidx]->layer_mask.mask_params = 0; lyr_a[lidx]->layer_mask.mask_flags.relative_pos = FALSE; lyr_a[lidx]->layer_mask.mask_flags.disabled = FALSE; lyr_a[lidx]->layer_mask.mask_flags.invert = FALSE; lyr_a[lidx]->layer_mask.mask_flags.rendered = FALSE; lyr_a[lidx]->layer_mask.mask_flags.params_present = FALSE; if (block_len > 0) { if (fread (&lyr_a[lidx]->layer_mask.top, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask.left, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask.bottom, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask.right, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask.def_color, 1, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask.flags, 1, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } lyr_a[lidx]->layer_mask.top = GINT32_FROM_BE (lyr_a[lidx]->layer_mask.top); lyr_a[lidx]->layer_mask.left = GINT32_FROM_BE (lyr_a[lidx]->layer_mask.left); lyr_a[lidx]->layer_mask.bottom = GINT32_FROM_BE (lyr_a[lidx]->layer_mask.bottom); lyr_a[lidx]->layer_mask.right = GINT32_FROM_BE (lyr_a[lidx]->layer_mask.right); lyr_a[lidx]->layer_mask.mask_flags.relative_pos = lyr_a[lidx]->layer_mask.flags & 1 ? TRUE : FALSE; lyr_a[lidx]->layer_mask.mask_flags.disabled = lyr_a[lidx]->layer_mask.flags & 2 ? TRUE : FALSE; lyr_a[lidx]->layer_mask.mask_flags.invert = lyr_a[lidx]->layer_mask.flags & 4 ? TRUE : FALSE; lyr_a[lidx]->layer_mask.mask_flags.rendered = lyr_a[lidx]->layer_mask.flags & 8 ? TRUE : FALSE; lyr_a[lidx]->layer_mask.mask_flags.params_present = lyr_a[lidx]->layer_mask.flags & 16 ? TRUE : FALSE; IFDBG(3) { if (lyr_a[lidx]->layer_mask.flags & 32) g_debug ("Layer mask flags bit 5 set."); if (lyr_a[lidx]->layer_mask.flags & 64) g_debug ("Layer mask flags bit 6 set."); if (lyr_a[lidx]->layer_mask.flags & 128) g_debug ("Layer mask flags bit 7 set."); } block_len -= 18; /* According to psd-tools this part comes before reading the * mask parameters. However if all mask parameter flags are * set the size of that would also be more than 18. I'm not * sure if all those flags could be set at the same time or * how to distinguish them. */ if (block_len >= 18) { if (fread (&lyr_a[lidx]->layer_mask.extra_flags, 1, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask.extra_def_color, 1, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask_extra.top, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask_extra.left, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask_extra.bottom, 4, 1, f) < 1 || fread (&lyr_a[lidx]->layer_mask_extra.right, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } block_len -= 18; lyr_a[lidx]->layer_mask_extra.top = GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.top); lyr_a[lidx]->layer_mask_extra.left = GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.left); lyr_a[lidx]->layer_mask_extra.bottom = GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.bottom); lyr_a[lidx]->layer_mask_extra.right = GINT32_FROM_BE (lyr_a[lidx]->layer_mask_extra.right); IFDBG(2) g_debug ("Rect enclosing Layer mask %d %d %d %d", lyr_a[lidx]->layer_mask_extra.left, lyr_a[lidx]->layer_mask_extra.top, lyr_a[lidx]->layer_mask_extra.right, lyr_a[lidx]->layer_mask_extra.bottom); } if (block_len > 2 && lyr_a[lidx]->layer_mask.mask_flags.params_present) { gint extra_bytes = 0; if (fread (&lyr_a[lidx]->layer_mask.mask_params, 1, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } block_len--; IFDBG(3) g_debug ("Mask params: %u", lyr_a[lidx]->layer_mask.mask_params); /* FIXME Extra bytes with user/vector mask density and feather follow. * We currently can't handle that so we will skip it. */ extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 1 ? 1 : 0); extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 2 ? 8 : 0); extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 4 ? 1 : 0); extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 8 ? 8 : 0); IFDBG(3) g_debug ("Extra bytes according to mask parameters %d", extra_bytes); if (fseek (f, extra_bytes, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return NULL; } block_len -= extra_bytes; } if (block_len > 0) { /* We have some remaining unknown mask data. * If size is less than 4 it is most likely padding. */ IFDBG(1) { if (block_len > 3) g_debug ("Skipping %u bytes of unknown layer mask data", block_len); } if (fseek (f, block_len, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return NULL; } } IFDBG(2) g_debug ("Layer mask coords %d %d %d %d", lyr_a[lidx]->layer_mask.left, lyr_a[lidx]->layer_mask.top, lyr_a[lidx]->layer_mask.right, lyr_a[lidx]->layer_mask.bottom); IFDBG(3) g_debug ("Default mask color %d, real color %d", lyr_a[lidx]->layer_mask.def_color, lyr_a[lidx]->layer_mask.extra_def_color); IFDBG(3) g_debug ("Mask flags %u, real flags %u, mask params %u", lyr_a[lidx]->layer_mask.flags, lyr_a[lidx]->layer_mask.extra_flags, lyr_a[lidx]->layer_mask.mask_params); /* Rendered masks can have invalid dimensions: 0, 0, 0, -1 */ if (! lyr_a[lidx]->layer_mask.mask_flags.rendered) { /* sanity checks */ if (lyr_a[lidx]->layer_mask.bottom < lyr_a[lidx]->layer_mask.top || lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top > GIMP_MAX_IMAGE_SIZE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid layer mask height: %d"), lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top); return NULL; } if (lyr_a[lidx]->layer_mask.right < lyr_a[lidx]->layer_mask.left || lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left > GIMP_MAX_IMAGE_SIZE) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid layer mask width: %d"), lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left); return NULL; } if ((lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left) > G_MAXINT32 / MAX (lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top, 1)) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid layer mask size: %dx%d"), lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left, lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top); return NULL; } } } /* Layer blending ranges */ /* FIXME */ if (fread (&block_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); return NULL; } block_len = GUINT32_FROM_BE (block_len); block_rem -= (block_len + 4); IFDBG(3) g_debug ("Remaining length %d", block_rem); if (block_len > 0) { if (fseek (f, block_len, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return NULL; } } lyr_a[lidx]->name = fread_pascal_string (&read_len, &write_len, 4, f, error); if (*error) return NULL; block_rem -= read_len; IFDBG(3) g_debug ("Remaining length %d", block_rem); /* Adjustment layer info */ /* FIXME */ while (block_rem > 7) { if (get_layer_resource_header (&res_a, f, error) < 0) return NULL; block_rem -= 12; if (res_a.data_len % 2 != 0) { /* Warn the user about an invalid length value but * try to recover graciously. See bug #771558. */ g_printerr ("psd-load: Layer extra data length should " "be even, but it is %d.", res_a.data_len); } if (res_a.data_len > block_rem) { IFDBG(1) g_debug ("Unexpected end of layer resource data"); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("The file is corrupt!")); return NULL; } if (load_layer_resource (&res_a, lyr_a[lidx], f, error) < 0) return NULL; block_rem -= res_a.data_len; } if (block_rem > 0) { if (fseek (f, block_rem, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return NULL; } } } img_a->layer_data_start = ftell(f); if (fseek (f, img_a->layer_data_len, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return NULL; } IFDBG(1) g_debug ("Layer image data block size %d", img_a->layer_data_len); } return lyr_a; } static PSDlayer ** read_layer_block (PSDimage *img_a, FILE *f, GError **error) { PSDlayer **lyr_a = NULL; guint32 block_len; guint32 block_end; if (fread (&block_len, 4, 1, f) < 1) { psd_set_error (feof (f), errno, error); img_a->num_layers = -1; return NULL; } img_a->mask_layer_len = GUINT32_FROM_BE (block_len); IFDBG(1) g_debug ("Layer and mask block size = %d", img_a->mask_layer_len); img_a->transparency = FALSE; img_a->layer_data_len = 0; if (!img_a->mask_layer_len) { img_a->num_layers = 0; return NULL; } else { guint32 total_len = img_a->mask_layer_len; img_a->mask_layer_start = ftell (f); block_end = img_a->mask_layer_start + img_a->mask_layer_len; /* Layer info */ if (fread (&block_len, 4, 1, f) == 1 && block_len) { block_len = GUINT32_FROM_BE (block_len); IFDBG(1) g_debug ("Layer info size = %d", block_len); lyr_a = read_layer_info (img_a, f, error); total_len -= block_len; } else { img_a->num_layers = 0; lyr_a = NULL; } /* Global layer mask info */ if (fread (&block_len, 4, 1, f) == 1 && block_len) { block_len = GUINT32_FROM_BE (block_len); IFDBG(1) g_debug ("Global layer mask info size = %d", block_len); /* read_global_layer_mask_info (img_a, f, error); */ fseek (f, block_len, SEEK_CUR); total_len -= block_len; } /* Additional Layer Information */ if (total_len > 12) { gchar signature_key[8]; if (fread (&signature_key, 4, 2, f) == 2 && (memcmp (signature_key, "8BIMLr16", 8) == 0 || memcmp (signature_key, "8BIMLr32", 8) == 0) && fread (&block_len, 4, 1, f) == 1 && block_len) lyr_a = read_layer_info (img_a, f, error); } /* Skip to end of block */ if (fseek (f, block_end, SEEK_SET) < 0) { psd_set_error (feof (f), errno, error); return NULL; } } return lyr_a; } static gint read_merged_image_block (PSDimage *img_a, FILE *f, GError **error) { img_a->merged_image_start = ftell(f); if (fseek (f, 0, SEEK_END) < 0) { psd_set_error (feof (f), errno, error); return -1; } img_a->merged_image_len = ftell(f) - img_a->merged_image_start; IFDBG(1) g_debug ("Merged image data block: Start: %d, len: %d", img_a->merged_image_start, img_a->merged_image_len); return 0; } static gint32 create_gimp_image (PSDimage *img_a, const gchar *filename) { gint32 image_id = -1; GimpPrecision precision; switch (img_a->color_mode) { case PSD_MULTICHANNEL: case PSD_GRAYSCALE: case PSD_DUOTONE: img_a->base_type = GIMP_GRAY; break; case PSD_BITMAP: case PSD_INDEXED: img_a->base_type = GIMP_INDEXED; break; case PSD_CMYK: case PSD_RGB: img_a->base_type = GIMP_RGB; break; default: /* Color mode already validated - should not be here */ g_warning ("Invalid color mode"); return -1; break; } switch (img_a->bps) { case 32: precision = GIMP_PRECISION_U32_GAMMA; break; case 16: precision = GIMP_PRECISION_U16_GAMMA; break; case 8: case 1: if (img_a->color_mode == PSD_CMYK) precision = GIMP_PRECISION_FLOAT_GAMMA; else precision = GIMP_PRECISION_U8_GAMMA; break; default: /* Precision not supported */ g_warning ("Invalid precision"); return -1; break; } /* Create gimp image */ IFDBG(2) g_debug ("Create image"); image_id = gimp_image_new_with_precision (img_a->columns, img_a->rows, img_a->base_type, precision); gimp_image_set_filename (image_id, filename); gimp_image_undo_disable (image_id); return image_id; } static gint add_color_map (gint32 image_id, PSDimage *img_a) { GimpParasite *parasite; if (img_a->color_map_len) { if (img_a->color_mode != PSD_DUOTONE) { gimp_image_set_colormap (image_id, img_a->color_map, img_a->color_map_entries); } else { /* Add parasite for Duotone color data */ IFDBG(2) g_debug ("Add Duotone color data parasite"); parasite = gimp_parasite_new (PSD_PARASITE_DUOTONE_DATA, 0, img_a->color_map_len, img_a->color_map); gimp_image_attach_parasite (image_id, parasite); gimp_parasite_free (parasite); } g_free (img_a->color_map); } return 0; } static gint add_image_resources (gint32 image_id, PSDimage *img_a, FILE *f, gboolean *resolution_loaded, gboolean *profile_loaded, GError **error) { PSDimageres res_a; if (fseek (f, img_a->image_res_start, SEEK_SET) < 0) { psd_set_error (feof (f), errno, error); return -1; } /* Initialise image resource variables */ img_a->no_icc = FALSE; img_a->layer_state = 0; img_a->alpha_names = NULL; img_a->alpha_display_info = NULL; img_a->alpha_display_count = 0; img_a->alpha_id = NULL; img_a->alpha_id_count = 0; img_a->quick_mask_id = 0; while (ftell (f) < img_a->image_res_start + img_a->image_res_len) { if (get_image_resource_header (&res_a, f, error) < 0) return -1; if (res_a.data_start + res_a.data_len > img_a->image_res_start + img_a->image_res_len) { IFDBG(1) g_debug ("Unexpected end of image resource data"); return 0; } if (load_image_resource (&res_a, image_id, img_a, f, resolution_loaded, profile_loaded, error) < 0) return -1; } return 0; } static guchar * psd_convert_cmyk_to_srgb (PSDimage *img_a, guchar *dst, guchar *src, gint width, gint height, gboolean alpha) { if (img_a->cmyk_profile) { if (alpha) { if (! img_a->cmyk_transform_alpha) { GimpColorProfile *srgb = gimp_color_profile_new_rgb_srgb (); img_a->cmyk_transform_alpha = gimp_color_transform_new (img_a->cmyk_profile, babl_format ("cmykA u8"), srgb, babl_format ("R'G'B'A float"), 0, 0); g_object_unref (srgb); } gimp_color_transform_process_pixels (img_a->cmyk_transform_alpha, babl_format ("cmykA u8"), src, babl_format ("R'G'B'A float"), dst, width * height); } else { if (! img_a->cmyk_transform) { GimpColorProfile *srgb = gimp_color_profile_new_rgb_srgb (); img_a->cmyk_transform = gimp_color_transform_new (img_a->cmyk_profile, babl_format ("cmyk u8"), srgb, babl_format ("R'G'B' float"), 0, 0); g_object_unref (srgb); } gimp_color_transform_process_pixels (img_a->cmyk_transform, babl_format ("cmyk u8"), src, babl_format ("R'G'B' float"), dst, width * height); } } else { const Babl *fish; if (alpha) fish = babl_fish ("cmykA u8", "R'G'B'A float"); else fish = babl_fish ("cmyk u8", "R'G'B' float"); babl_process (fish, src, dst, width * height); } return (guchar*) dst; } static gint add_layers (gint32 image_id, PSDimage *img_a, PSDlayer **lyr_a, FILE *f, GError **error) { PSDchannel **lyr_chn; GArray *parent_group_stack; gint32 parent_group_id = -1; gint32 clipping_group_id = -1; guint16 alpha_chn; guint16 user_mask_chn; guint16 layer_channels, base_channels; guint16 channel_idx[MAX_CHANNELS]; guint16 *rle_pack_len; guint16 bps; gint32 l_x; /* Layer x */ gint32 l_y; /* Layer y */ gint32 l_w; /* Layer width */ gint32 l_h; /* Layer height */ gint32 lm_x; /* Layer mask x */ gint32 lm_y; /* Layer mask y */ gint32 lm_w; /* Layer mask width */ gint32 lm_h; /* Layer mask height */ gint32 layer_id = -1; gint32 mask_id = -1; gint32 active_layer_id = -1; gint lidx; /* Layer index */ gint cidx; /* Channel index */ gint gidx; /* Clipping group start index */ gint rowi; /* Row index */ gboolean alpha; gboolean user_mask; gboolean empty; gboolean empty_mask; gboolean use_clipping_group; GeglBuffer *buffer; GimpImageType image_type; LayerModeInfo mode_info; IFDBG(2) g_debug ("Number of layers: %d", img_a->num_layers); if (img_a->merged_image_only || img_a->num_layers == 0) { IFDBG(2) g_debug ("No layers to process"); return 0; } /* Layered image - Photoshop 3 style */ if (fseek (f, img_a->layer_data_start, SEEK_SET) < 0) { psd_set_error (feof (f), errno, error); return -1; } IFDBG(3) g_debug ("Pre process layers..."); use_clipping_group = FALSE; gidx = -1; for (lidx = 0; lidx < img_a->num_layers; ++lidx) { if (lyr_a[lidx]->clipping == 1) { /* Photoshop handles layers with clipping differently than GIMP does. * To correctly show these layers we need to make a new group * starting with the first non-clipping layer and including all * the clipping layers above it. */ if (lidx > 0) { if (lyr_a[lidx]->group_type != 0) { /* Ignoring group layers with clipping set for now. */ IFDBG(3) g_debug ("Group Layer with clipping: [%d] %s", lidx, lyr_a[lidx]->name); use_clipping_group = FALSE; gidx = -1; } else if (gidx == -1) { use_clipping_group = TRUE; /* Looking at the results we should ignore layer groups */ if (lyr_a[lidx-1]->group_type == 0) gidx = lidx - 1; else gidx = lidx; lyr_a[gidx]->clipping_group_type = 1; /* start clipping group */ IFDBG(3) g_debug ("Layer: %s - start of clipping group", lyr_a[gidx]->name); } else if (lidx + 1 == img_a->num_layers && use_clipping_group) { /* end clipping group at the top of the layer stack */ lyr_a[lidx]->clipping_group_type = 2; /* end clipping group */ IFDBG(3) g_debug ("Layer: %s - end of clipping group", lyr_a[lidx]->name); use_clipping_group = FALSE; gidx = -1; } else { lyr_a[lidx]->clipping_group_type = 0; } } } else if (use_clipping_group) { /* end clipping group */ lyr_a[lidx-1]->clipping_group_type = 2; IFDBG(3) g_debug ("Layer: %s - end of clipping group", lyr_a[lidx-1]->name); use_clipping_group = FALSE; gidx = -1; } else { lyr_a[lidx]->clipping_group_type = 0; } } /* set the root of the group hierarchy */ parent_group_stack = g_array_new (FALSE, FALSE, sizeof (gint32)); g_array_append_val (parent_group_stack, parent_group_id); for (lidx = 0; lidx < img_a->num_layers; ++lidx) { IFDBG(2) g_debug ("Process Layer No %d (%s).", lidx, lyr_a[lidx]->name); if (lyr_a[lidx]->drop) { IFDBG(2) g_debug ("Drop layer %d", lidx); /* Step past layer data */ for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx) { if (fseek (f, lyr_a[lidx]->chn_info[cidx].data_len, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return -1; } } } else { /* Empty layer */ if (lyr_a[lidx]->bottom - lyr_a[lidx]->top == 0 || lyr_a[lidx]->right - lyr_a[lidx]->left == 0) empty = TRUE; else empty = FALSE; /* Empty mask */ if (lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top == 0 || lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left == 0) empty_mask = TRUE; else empty_mask = FALSE; IFDBG(3) g_debug ("Empty mask %d, size %d %d", empty_mask, lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top, lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left); /* Load layer channel data */ IFDBG(2) g_debug ("Number of channels: %d", lyr_a[lidx]->num_channels); /* Create pointer array for the channel records */ lyr_chn = g_new (PSDchannel *, lyr_a[lidx]->num_channels); for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx) { guint16 comp_mode = PSD_COMP_RAW; /* Allocate channel record */ lyr_chn[cidx] = g_malloc (sizeof (PSDchannel) ); lyr_chn[cidx]->id = lyr_a[lidx]->chn_info[cidx].channel_id; lyr_chn[cidx]->rows = lyr_a[lidx]->bottom - lyr_a[lidx]->top; lyr_chn[cidx]->columns = lyr_a[lidx]->right - lyr_a[lidx]->left; lyr_chn[cidx]->data = NULL; if (lyr_chn[cidx]->id == PSD_CHANNEL_EXTRA_MASK) { if (fseek (f, lyr_a[lidx]->chn_info[cidx].data_len, SEEK_CUR) != 0) { psd_set_error (feof (f), errno, error); return -1; } continue; } else if (lyr_chn[cidx]->id == PSD_CHANNEL_MASK) { /* Works around a bug in panotools psd files where the layer mask size is given as 0 but data exists. Set mask size to layer size. */ if (empty_mask && lyr_a[lidx]->chn_info[cidx].data_len - 2 > 0) { empty_mask = FALSE; if (lyr_a[lidx]->layer_mask.top == lyr_a[lidx]->layer_mask.bottom) { lyr_a[lidx]->layer_mask.top = lyr_a[lidx]->top; lyr_a[lidx]->layer_mask.bottom = lyr_a[lidx]->bottom; } if (lyr_a[lidx]->layer_mask.right == lyr_a[lidx]->layer_mask.left) { lyr_a[lidx]->layer_mask.right = lyr_a[lidx]->right; lyr_a[lidx]->layer_mask.left = lyr_a[lidx]->left; } } lyr_chn[cidx]->rows = (lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top); lyr_chn[cidx]->columns = (lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left); } IFDBG(3) g_debug ("Channel id %d, %dx%d", lyr_chn[cidx]->id, lyr_chn[cidx]->columns, lyr_chn[cidx]->rows); /* Only read channel data if there is any channel * data. Note that the channel data can contain a * compression method but no actual data. */ if (lyr_a[lidx]->chn_info[cidx].data_len >= COMP_MODE_SIZE) { if (fread (&comp_mode, COMP_MODE_SIZE, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } comp_mode = GUINT16_FROM_BE (comp_mode); IFDBG(3) g_debug ("Compression mode: %d", comp_mode); } if (lyr_a[lidx]->chn_info[cidx].data_len > COMP_MODE_SIZE) { switch (comp_mode) { case PSD_COMP_RAW: /* Planar raw data */ IFDBG(3) g_debug ("Raw data length: %d", lyr_a[lidx]->chn_info[cidx].data_len - 2); if (read_channel_data (lyr_chn[cidx], img_a->bps, PSD_COMP_RAW, NULL, f, 0, error) < 1) return -1; break; case PSD_COMP_RLE: /* Packbits */ IFDBG(3) g_debug ("RLE channel length %d, RLE length data: %d, " "RLE data block: %d", lyr_a[lidx]->chn_info[cidx].data_len - 2, lyr_chn[cidx]->rows * 2, (lyr_a[lidx]->chn_info[cidx].data_len - 2 - lyr_chn[cidx]->rows * 2)); rle_pack_len = g_malloc (lyr_chn[cidx]->rows * 2); for (rowi = 0; rowi < lyr_chn[cidx]->rows; ++rowi) { if (fread (&rle_pack_len[rowi], 2, 1, f) < 1) { psd_set_error (feof (f), errno, error); g_free (rle_pack_len); return -1; } rle_pack_len[rowi] = GUINT16_FROM_BE (rle_pack_len[rowi]); } IFDBG(3) g_debug ("RLE decode - data"); if (read_channel_data (lyr_chn[cidx], img_a->bps, PSD_COMP_RLE, rle_pack_len, f, 0, error) < 1) return -1; g_free (rle_pack_len); break; case PSD_COMP_ZIP: /* ? */ case PSD_COMP_ZIP_PRED: if (read_channel_data (lyr_chn[cidx], img_a->bps, comp_mode, NULL, f, lyr_a[lidx]->chn_info[cidx].data_len - 2, error) < 1) return -1; break; default: g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported compression mode: %d"), comp_mode); return -1; break; } } } /* Draw layer */ alpha = FALSE; alpha_chn = -1; user_mask = FALSE; user_mask_chn = -1; layer_channels = 0; l_x = 0; l_y = 0; l_w = img_a->columns; l_h = img_a->rows; if (parent_group_stack->len > 0) parent_group_id = g_array_index (parent_group_stack, gint32, parent_group_stack->len - 1); else parent_group_id = -1; /* root */ if (img_a->color_mode == PSD_CMYK) base_channels = 4; else if (img_a->color_mode == PSD_RGB || img_a->color_mode == PSD_LAB) base_channels = 3; else base_channels = 1; IFDBG(3) g_debug ("Re-hash channel indices"); for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx) { if (lyr_chn[cidx]->id == PSD_CHANNEL_MASK) { user_mask = TRUE; user_mask_chn = cidx; } else if (lyr_chn[cidx]->id == PSD_CHANNEL_ALPHA) { alpha = TRUE; alpha_chn = cidx; } else if (lyr_chn[cidx]->data) { if (layer_channels < base_channels) { channel_idx[layer_channels] = cidx; /* Assumes in sane order */ layer_channels++; /* RGB, Lab, CMYK etc. */ } else { /* channel_idx[base_channels] is reserved for alpha channel, * but this layer apparently has extra channels. * From the one example I have (see #8411) it looks like * that channel is the same as the alpha channel. */ IFDBG(2) g_debug ("This layer has an extra channel (id: %d)", lyr_chn[cidx]->id); channel_idx[layer_channels+1] = cidx; /* Assumes in sane order */ layer_channels += 2; /* RGB, Lab, CMYK etc. */ } } else { IFDBG(4) g_debug ("Channel %d (id: %d) has no data", cidx, lyr_chn[cidx]->id); } } if (alpha) { if (layer_channels <= base_channels) { channel_idx[layer_channels] = alpha_chn; layer_channels++; } else { channel_idx[base_channels] = alpha_chn; } base_channels++; } IFDBG(4) g_debug ("Create the layer (group type: %d, clipping group type: %d)", lyr_a[lidx]->group_type, lyr_a[lidx]->clipping_group_type); /* Create the layer */ if (lyr_a[lidx]->group_type != 0) { if (lyr_a[lidx]->group_type == 3) { /* the marker layers are used to * assemble the layer structure in a single pass */ IFDBG(2) g_debug ("Create placeholder group layer"); layer_id = gimp_layer_group_new (image_id); /* add this group layer as the new parent */ g_array_append_val (parent_group_stack, layer_id); } else /* group-type == 1 || group_type == 2 */ { if (parent_group_stack->len) { layer_id = g_array_index (parent_group_stack, gint32, parent_group_stack->len - 1); IFDBG(2) g_debug ("End group layer id %d.", layer_id); /* since the layers are stored in reverse, the group * layer start marker actually means we're done with * that layer group */ g_array_remove_index (parent_group_stack, parent_group_stack->len - 1); gimp_drawable_offsets (layer_id, &l_x, &l_y); l_w = gimp_drawable_width (layer_id); l_h = gimp_drawable_height (layer_id); } else { IFDBG(1) g_debug ("WARNING: Unmatched group layer start marker."); layer_id = -1; } } } else { if (lyr_a[lidx]->clipping_group_type == 1) { clipping_group_id = add_clipping_group (image_id, parent_group_id); } if (empty) { IFDBG(2) g_debug ("Create blank layer"); } else { IFDBG(2) g_debug ("Create normal layer"); l_x = lyr_a[lidx]->left; l_y = lyr_a[lidx]->top; l_w = lyr_a[lidx]->right - lyr_a[lidx]->left; l_h = lyr_a[lidx]->bottom - lyr_a[lidx]->top; } image_type = get_gimp_image_type (img_a->base_type, TRUE); IFDBG(3) g_debug ("Layer type %d", image_type); layer_id = gimp_layer_new (image_id, lyr_a[lidx]->name, l_w, l_h, image_type, 100, GIMP_LAYER_MODE_NORMAL); } if (layer_id != -1) { /* Set the layer name. Note that we do this even for group-end * markers, to avoid having the default group name collide with * subsequent layers; the real group name is set by the group * start marker. */ gimp_item_set_name (layer_id, lyr_a[lidx]->name); /* Set the layer properties (skip this for layer group end * markers; we set their properties when processing the start * marker.) */ if (lyr_a[lidx]->group_type != 3) { /* Mode */ psd_to_gimp_blend_mode (lyr_a[lidx], &mode_info); gimp_layer_set_mode (layer_id, mode_info.mode); gimp_layer_set_blend_space (layer_id, mode_info.blend_space); gimp_layer_set_composite_space (layer_id, mode_info.composite_space); gimp_layer_set_composite_mode (layer_id, mode_info.composite_mode); /* Opacity */ gimp_layer_set_opacity (layer_id, lyr_a[lidx]->opacity * 100.0 / 255.0); /* Flags */ gimp_layer_set_lock_alpha (layer_id, lyr_a[lidx]->layer_flags.trans_prot); gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible); #if 0 /* according to the spec, the 'irrelevant' flag indicates * that the layer's "pixel data is irrelevant to the * appearance of the document". what this seems to mean is * not that the layer doesn't contribute to the image, but * rather that its appearance can be entirely derived from * sources other than the pixel data, such as vector data. * in particular, this doesn't mean that the layer is * invisible. since we only support raster layers atm, we can * just ignore this flag. */ if (lyr_a[lidx]->layer_flags.irrelevant && lyr_a[lidx]->group_type == 0) { gimp_item_set_visible (layer_id, FALSE); } #endif /* Position */ if (l_x != 0 || l_y != 0) gimp_layer_set_offsets (layer_id, l_x, l_y); /* Color tag */ gimp_item_set_color_tag (layer_id, psd_to_gimp_layer_color_tag (lyr_a[lidx]->color_tag[0])); /* Tattoo */ if (lyr_a[lidx]->id) gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id); /* For layer groups, expand or collapse the group */ if (lyr_a[lidx]->group_type != 0) { gimp_item_set_expanded (layer_id, lyr_a[lidx]->group_type == 1); } } /* Remember the active layer ID */ if (lidx == img_a->layer_state) { active_layer_id = layer_id; } /* Set the layer data */ if (lyr_a[lidx]->group_type == 0) { IFDBG(3) g_debug ("Draw layer"); if (empty) { gimp_drawable_fill (layer_id, GIMP_FILL_TRANSPARENT); } else { GeglBufferIterator *iter; bps = img_a->bps / 8; if (bps == 0) bps++; buffer = gimp_drawable_get_buffer (layer_id); iter = gegl_buffer_iterator_new ( buffer, NULL, 0, get_layer_format (img_a, alpha), GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1); while (gegl_buffer_iterator_next (iter)) { const GeglRectangle *roi = &iter->items[0].roi; guint8 *dst0 = iter->items[0].data; gint src_step = bps; gint dst_step = bps * base_channels; if (img_a->color_mode == PSD_CMYK) { dst0 = gegl_scratch_alloc (base_channels * iter->length); } for (cidx = 0; cidx < base_channels; ++cidx) { gint b; if (roi->x == 0 && roi->y == 0) IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]); for (b = 0; b < bps; ++b) { guint8 *dst; gint y; dst = &dst0[cidx * bps + b]; for (y = 0; y < roi->height; y++) { const guint8 *src; gint x; src = (const guint8 *) &lyr_chn[channel_idx[cidx]]->data[ ((roi->y + y) * l_w + roi->x) * bps + b]; for (x = 0; x < roi->width; ++x) { *dst = *src; src += src_step; dst += dst_step; } } } } if (img_a->color_mode == PSD_CMYK) { psd_convert_cmyk_to_srgb ( img_a, iter->items[0].data, dst0, roi->width, roi->height, alpha); gegl_scratch_free (dst0); } } for (cidx = 0; cidx < layer_channels; ++cidx) g_free (lyr_chn[channel_idx[cidx]]->data); g_object_unref (buffer); } } /* Layer mask */ if (user_mask && lyr_a[lidx]->group_type != 3) { if (empty_mask) { IFDBG(3) g_debug ("Create empty mask"); if (lyr_a[lidx]->layer_mask.def_color == 255) mask_id = gimp_layer_create_mask (layer_id, GIMP_ADD_MASK_WHITE); else mask_id = gimp_layer_create_mask (layer_id, GIMP_ADD_MASK_BLACK); gimp_layer_add_mask (layer_id, mask_id); gimp_layer_set_apply_mask (layer_id, ! lyr_a[lidx]->layer_mask.mask_flags.disabled); } else { GeglRectangle mask_rect; /* Load layer mask data */ lm_x = lyr_a[lidx]->layer_mask.left - l_x; lm_y = lyr_a[lidx]->layer_mask.top - l_y; lm_w = lyr_a[lidx]->layer_mask.right - lyr_a[lidx]->layer_mask.left; lm_h = lyr_a[lidx]->layer_mask.bottom - lyr_a[lidx]->layer_mask.top; IFDBG(3) g_debug ("Mask channel index %d", user_mask_chn); IFDBG(3) g_debug ("Original Mask %d %d %d %d", lm_x, lm_y, lm_w, lm_h); /* Crop mask at layer boundary, and draw layer mask data, * if any */ if (gegl_rectangle_intersect ( &mask_rect, GEGL_RECTANGLE (0, 0, l_w, l_h), GEGL_RECTANGLE (lm_x, lm_y, lm_w, lm_h))) { IFDBG(3) g_debug ("Layer %d %d %d %d", l_x, l_y, l_w, l_h); IFDBG(3) g_debug ("Mask %d %d %d %d", mask_rect.x, mask_rect.y, mask_rect.width, mask_rect.height); if (lyr_a[lidx]->layer_mask.def_color == 255) mask_id = gimp_layer_create_mask (layer_id, GIMP_ADD_MASK_WHITE); else mask_id = gimp_layer_create_mask (layer_id, GIMP_ADD_MASK_BLACK); bps = img_a->bps / 8; if (bps == 0) bps++; IFDBG(3) g_debug ("New layer mask %d", mask_id); gimp_layer_add_mask (layer_id, mask_id); buffer = gimp_drawable_get_buffer (mask_id); gegl_buffer_set (buffer, &mask_rect, 0, get_mask_format (img_a), lyr_chn[user_mask_chn]->data + ( (mask_rect.y - lm_y) * lm_w + (mask_rect.x - lm_x)) * bps, lm_w * bps); g_object_unref (buffer); gimp_layer_set_apply_mask (layer_id, ! lyr_a[lidx]->layer_mask.mask_flags.disabled); } g_free (lyr_chn[user_mask_chn]->data); } } /* Insert the layer */ if (lyr_a[lidx]->group_type == 0 || /* normal layer */ lyr_a[lidx]->group_type == 3 /* group layer end marker */) { if (clipping_group_id != -1) { gimp_image_insert_layer (image_id, layer_id, clipping_group_id, 0); if (lyr_a[lidx]->clipping_group_type == 2) { /* End of our clipping group. */ clipping_group_id = -1; } } else { gimp_image_insert_layer (image_id, layer_id, parent_group_id, 0); } } } for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx) if (lyr_chn[cidx]) g_free (lyr_chn[cidx]); g_free (lyr_chn); } g_free (lyr_a[lidx]->chn_info); g_free (lyr_a[lidx]->name); g_free (lyr_a[lidx]); } g_free (lyr_a); g_array_free (parent_group_stack, FALSE); /* Set the active layer */ if (active_layer_id >= 0) gimp_image_set_active_layer (image_id, active_layer_id); return 0; } static gint add_merged_image (gint32 image_id, PSDimage *img_a, FILE *f, GError **error) { PSDchannel chn_a[MAX_CHANNELS]; gchar *alpha_name; guchar *pixels; guint16 comp_mode; guint16 base_channels; guint16 extra_channels; guint16 total_channels; guint16 bps; guint16 *rle_pack_len[MAX_CHANNELS]; guint32 alpha_id; gint32 layer_size; gint32 layer_id = -1; gint32 channel_id = -1; gint16 alpha_opacity; gint cidx; /* Channel index */ gint rowi; /* Row index */ gint offset; gint i; gboolean alpha_visible; gboolean alpha_channel = FALSE; GeglBuffer *buffer; GimpImageType image_type; GimpRGB alpha_rgb; total_channels = img_a->channels; extra_channels = 0; bps = img_a->bps / 8; if (bps == 0) bps++; if (img_a->num_layers > 0 && img_a->color_mode == PSD_CMYK) { /* In this case there is no conversion. Merged image is RGB. */ img_a->color_mode = PSD_RGB; if (! img_a->transparency) total_channels--; } if ((img_a->color_mode == PSD_BITMAP || img_a->color_mode == PSD_MULTICHANNEL || img_a->color_mode == PSD_GRAYSCALE || img_a->color_mode == PSD_DUOTONE || img_a->color_mode == PSD_INDEXED) && total_channels > 1) { extra_channels = total_channels - 1; } else if ((img_a->color_mode == PSD_RGB || img_a->color_mode == PSD_LAB) && total_channels > 3) { extra_channels = total_channels - 3; } else if ((img_a->color_mode == PSD_CMYK) && total_channels > 4) { extra_channels = total_channels - 4; } if (img_a->transparency && extra_channels > 0) extra_channels--; base_channels = total_channels - extra_channels; if (img_a->merged_image_only) { if (! img_a->transparency && extra_channels > 0) { alpha_channel = TRUE; base_channels += 1; } extra_channels = 0; total_channels = base_channels; } /* ----- Read merged image & extra channel pixel data ----- */ if (img_a->merged_image_only || img_a->num_layers == 0 || extra_channels > 0) { guint32 block_len; guint32 block_start; block_start = img_a->merged_image_start; block_len = img_a->merged_image_len; fseek (f, block_start, SEEK_SET); if (fread (&comp_mode, COMP_MODE_SIZE, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } comp_mode = GUINT16_FROM_BE (comp_mode); switch (comp_mode) { case PSD_COMP_RAW: /* Planar raw data */ IFDBG(3) g_debug ("Raw data length: %d", block_len); for (cidx = 0; cidx < total_channels; ++cidx) { chn_a[cidx].columns = img_a->columns; chn_a[cidx].rows = img_a->rows; if (read_channel_data (&chn_a[cidx], img_a->bps, PSD_COMP_RAW, NULL, f, 0, error) < 1) return -1; } break; case PSD_COMP_RLE: /* Packbits */ /* Image data is stored as packed scanlines in planar order with all compressed length counters stored first */ IFDBG(3) g_debug ("RLE length data: %d, RLE data block: %d", total_channels * img_a->rows * 2, block_len - (total_channels * img_a->rows * 2)); for (cidx = 0; cidx < total_channels; ++cidx) { chn_a[cidx].columns = img_a->columns; chn_a[cidx].rows = img_a->rows; rle_pack_len[cidx] = g_malloc (img_a->rows * 2); for (rowi = 0; rowi < img_a->rows; ++rowi) { if (fread (&rle_pack_len[cidx][rowi], 2, 1, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } rle_pack_len[cidx][rowi] = GUINT16_FROM_BE (rle_pack_len[cidx][rowi]); } } /* Skip channel length data for unloaded channels */ if (fseek (f, (img_a->channels - total_channels) * img_a->rows * 2, SEEK_CUR) < 0) { psd_set_error (feof (f), errno, error); return -1; } IFDBG(3) g_debug ("RLE decode - data"); for (cidx = 0; cidx < total_channels; ++cidx) { if (read_channel_data (&chn_a[cidx], img_a->bps, PSD_COMP_RLE, rle_pack_len[cidx], f, 0, error) < 1) return -1; g_free (rle_pack_len[cidx]); } break; case PSD_COMP_ZIP: /* ? */ case PSD_COMP_ZIP_PRED: default: g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported compression mode: %d"), comp_mode); return -1; break; } } /* ----- Draw merged image ----- */ if (img_a->merged_image_only || img_a->num_layers == 0) /* Merged image - Photoshop 2 style */ { image_type = get_gimp_image_type (img_a->base_type, img_a->transparency || alpha_channel); layer_size = img_a->columns * img_a->rows; pixels = g_malloc (layer_size * base_channels * bps); for (cidx = 0; cidx < base_channels; ++cidx) { for (i = 0; i < layer_size; ++i) { memcpy (&pixels[((i * base_channels) + cidx) * bps], &chn_a[cidx].data[i * bps], bps); } g_free (chn_a[cidx].data); } /* Add background layer */ IFDBG(2) g_debug ("Draw merged image"); layer_id = gimp_layer_new (image_id, _("Background"), img_a->columns, img_a->rows, image_type, 100, gimp_image_get_default_new_layer_mode (image_id)); gimp_image_insert_layer (image_id, layer_id, -1, 0); buffer = gimp_drawable_get_buffer (layer_id); if (img_a->color_mode == PSD_CMYK) { guchar *dst0; dst0 = g_malloc (base_channels * layer_size * sizeof(float)); psd_convert_cmyk_to_srgb ( img_a, dst0, pixels, img_a->columns, img_a->rows, alpha_channel); g_free (pixels); pixels = dst0; } gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)), 0, get_layer_format (img_a, img_a->transparency || alpha_channel), pixels, GEGL_AUTO_ROWSTRIDE); if (img_a->color_mode == PSD_CMYK) img_a->color_mode = PSD_RGB; /* Merged image data is blended against white. Unblend it. */ if (img_a->transparency) { GeglBufferIterator *iter; iter = gegl_buffer_iterator_new (buffer, NULL, 0, babl_format ("R'G'B'A float"), GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, 1); while (gegl_buffer_iterator_next (iter)) { gfloat *data = iter->items[0].data; for (i = 0; i < iter->length; i++) { gint c; if (data[3]) { for (c = 0; c < 3; c++) data[c] = (data[c] + data[3] - 1.0f) / data[3]; } data += 4; } } } g_object_unref (buffer); g_free (pixels); } else { /* Free merged image data for layered image */ if (extra_channels) for (cidx = 0; cidx < base_channels; ++cidx) g_free (chn_a[cidx].data); } if (img_a->transparency) { /* Free "Transparency" channel name */ if (img_a->alpha_names) { alpha_name = g_ptr_array_index (img_a->alpha_names, 0); if (alpha_name) g_free (alpha_name); } } /* ----- Draw extra alpha channels ----- */ if (extra_channels /* Extra alpha channels */ && image_id > -1) { IFDBG(2) g_debug ("Add extra channels"); pixels = g_malloc(0); /* Get channel resource data */ if (img_a->transparency) offset = 1; else offset = 0; /* Draw channels */ IFDBG(2) g_debug ("Number of channels: %d", extra_channels); for (i = 0; i < extra_channels; ++i) { /* Alpha channel name */ alpha_name = NULL; alpha_visible = FALSE; /* Quick mask channel*/ if (img_a->quick_mask_id) if (i == img_a->quick_mask_id - base_channels + offset) { /* Free "Quick Mask" channel name */ alpha_name = g_ptr_array_index (img_a->alpha_names, i + offset); if (alpha_name) g_free (alpha_name); alpha_name = g_strdup (GIMP_IMAGE_QUICK_MASK_NAME); alpha_visible = TRUE; } if (! alpha_name && img_a->alpha_names) if (offset < img_a->alpha_names->len && i + offset <= img_a->alpha_names->len) alpha_name = g_ptr_array_index (img_a->alpha_names, i + offset); if (! alpha_name) alpha_name = g_strdup (_("Extra")); if (offset < img_a->alpha_id_count && offset + i <= img_a->alpha_id_count) alpha_id = img_a->alpha_id[i + offset]; else alpha_id = 0; if (offset < img_a->alpha_display_count && i + offset <= img_a->alpha_display_count) { alpha_rgb = img_a->alpha_display_info[i + offset]->gimp_color; alpha_opacity = img_a->alpha_display_info[i + offset]->opacity; } else { gimp_rgba_set (&alpha_rgb, 1.0, 0.0, 0.0, 1.0); alpha_opacity = 50; } cidx = base_channels + i; pixels = g_realloc (pixels, chn_a[cidx].columns * chn_a[cidx].rows * bps); memcpy (pixels, chn_a[cidx].data, chn_a[cidx].columns * chn_a[cidx].rows * bps); channel_id = gimp_channel_new (image_id, alpha_name, chn_a[cidx].columns, chn_a[cidx].rows, alpha_opacity, &alpha_rgb); gimp_image_insert_channel (image_id, channel_id, -1, i); g_free (alpha_name); buffer = gimp_drawable_get_buffer (channel_id); if (alpha_id) gimp_item_set_tattoo (channel_id, alpha_id); gimp_item_set_visible (channel_id, alpha_visible); gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)), 0, get_channel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE); g_object_unref (buffer); g_free (chn_a[cidx].data); } g_free (pixels); if (img_a->alpha_names) g_ptr_array_free (img_a->alpha_names, TRUE); if (img_a->alpha_id) g_free (img_a->alpha_id); if (img_a->alpha_display_info) { for (cidx = 0; cidx < img_a->alpha_display_count; ++cidx) g_free (img_a->alpha_display_info[cidx]); g_free (img_a->alpha_display_info); } } /* FIXME gimp image tattoo state */ return 0; } /* Local utility functions */ static gint32 add_clipping_group (gint32 image_id, gint32 parent_id) { gint32 clipping_group_id = -1; /* We need to create a group because GIMP handles clipping and * composition mode in a different manner than PS. */ IFDBG(2) g_debug ("Creating a layer group to handle PS transparency clipping correctly."); clipping_group_id = gimp_layer_group_new (image_id); gimp_item_set_name (clipping_group_id, "Group added by GIMP"); gimp_layer_set_blend_space (clipping_group_id, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL); gimp_layer_set_composite_space (clipping_group_id, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL); gimp_layer_set_composite_mode (clipping_group_id, GIMP_LAYER_COMPOSITE_UNION); gimp_image_insert_layer (image_id, clipping_group_id, parent_id, 0); return clipping_group_id; } static gchar * get_psd_color_mode_name (PSDColorMode mode) { static gchar * const psd_color_mode_names[] = { "BITMAP", "GRAYSCALE", "INDEXED", "RGB", "CMYK", "UNKNOWN (5)", "UNKNOWN (6)", "MULTICHANNEL", "DUOTONE", "LAB" }; static gchar *err_name = NULL; if (mode >= PSD_BITMAP && mode <= PSD_LAB) return psd_color_mode_names[mode]; g_free (err_name); err_name = g_strdup_printf ("UNKNOWN (%d)", mode); return err_name; } static void psd_to_gimp_color_map (guchar *map256) { guchar *tmpmap; gint i; tmpmap = g_malloc (3 * 256); for (i = 0; i < 256; ++i) { tmpmap[i*3 ] = map256[i]; tmpmap[i*3+1] = map256[i+256]; tmpmap[i*3+2] = map256[i+512]; } memcpy (map256, tmpmap, 3 * 256); g_free (tmpmap); } static GimpImageType get_gimp_image_type (GimpImageBaseType image_base_type, gboolean alpha) { GimpImageType image_type; switch (image_base_type) { case GIMP_GRAY: image_type = (alpha) ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE; break; case GIMP_INDEXED: image_type = (alpha) ? GIMP_INDEXEDA_IMAGE : GIMP_INDEXED_IMAGE; break; case GIMP_RGB: image_type = (alpha) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE; break; default: image_type = -1; break; } return image_type; } static voidpf zzalloc (voidpf opaque, uInt items, uInt size) { /* overflow check missing */ return g_malloc (items * size); } static void zzfree (voidpf opaque, voidpf address) { g_free (address); } static gint read_channel_data (PSDchannel *channel, guint16 bps, guint16 compression, const guint16 *rle_pack_len, FILE *f, guint32 comp_len, GError **error) { gchar *raw_data; gchar *src; guint32 readline_len; gint i, j; if (bps == 1) readline_len = ((channel->columns + 7) / 8); else readline_len = (channel->columns * bps / 8); IFDBG(3) g_debug ("raw data size %d x %d = %d", readline_len, channel->rows, readline_len * channel->rows); /* sanity check, int overflow check (avoid divisions by zero) */ if ((channel->rows == 0) || (channel->columns == 0) || (channel->rows > G_MAXINT32 / channel->columns / MAX (bps / 8, 1))) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unsupported or invalid channel size")); return -1; } raw_data = g_malloc (readline_len * channel->rows); switch (compression) { case PSD_COMP_RAW: if (fread (raw_data, readline_len, channel->rows, f) < 1) { psd_set_error (feof (f), errno, error); return -1; } break; case PSD_COMP_RLE: for (i = 0; i < channel->rows; ++i) { src = gegl_scratch_alloc (rle_pack_len[i]); /* FIXME check for over-run if (ftell (f) + rle_pack_len[i] > block_end) { psd_set_error (TRUE, errno, error); return -1; } */ if (fread (src, rle_pack_len[i], 1, f) < 1) { psd_set_error (feof (f), errno, error); gegl_scratch_free (src); return -1; } /* FIXME check for errors returned from decode packbits */ decode_packbits (src, raw_data + i * readline_len, rle_pack_len[i], readline_len); gegl_scratch_free (src); } break; case PSD_COMP_ZIP: case PSD_COMP_ZIP_PRED: { z_stream zs; src = g_malloc (comp_len); if (fread (src, comp_len, 1, f) < 1) { psd_set_error (feof (f), errno, error); g_free (src); return -1; } zs.next_in = (guchar*) src; zs.avail_in = comp_len; zs.next_out = (guchar*) raw_data; zs.avail_out = readline_len * channel->rows; zs.zalloc = zzalloc; zs.zfree = zzfree; if (inflateInit (&zs) == Z_OK && inflate (&zs, Z_FINISH) == Z_STREAM_END) { inflateEnd (&zs); } else { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to decompress data")); g_free (src); return -1; } g_free (src); break; } } /* Convert channel data to GIMP format */ switch (bps) { case 32: { guint32 *data = (guint32*) raw_data; channel->data = raw_data; raw_data = NULL; for (i = 0; i < channel->rows * channel->columns; ++i) data[i] = GUINT32_FROM_BE (data[i]); if (compression == PSD_COMP_ZIP_PRED) { for (i = 0; i < channel->rows; ++i) for (j = 1; j < channel->columns; ++j) data[i * channel->columns + j] += data[i * channel->columns + j - 1]; } break; } case 16: { guint16 *data = (guint16*) raw_data; channel->data = raw_data; raw_data = NULL; for (i = 0; i < channel->rows * channel->columns; ++i) data[i] = GUINT16_FROM_BE (data[i]); if (compression == PSD_COMP_ZIP_PRED) { for (i = 0; i < channel->rows; ++i) for (j = 1; j < channel->columns; ++j) data[i * channel->columns + j] += data[i * channel->columns + j - 1]; } break; } case 8: channel->data = raw_data; raw_data = NULL; if (compression == PSD_COMP_ZIP_PRED) { for (i = 0; i < channel->rows; ++i) for (j = 1; j < channel->columns; ++j) channel->data[i * channel->columns + j] += channel->data[i * channel->columns + j - 1]; } break; case 1: channel->data = (gchar *) g_malloc (channel->rows * channel->columns); convert_1_bit (raw_data, channel->data, channel->rows, channel->columns); break; default: return -1; break; } g_free (raw_data); return 1; } static void convert_1_bit (const gchar *src, gchar *dst, guint32 rows, guint32 columns) { /* Convert bits to bytes left to right by row. Rows are padded out to a byte boundary. */ guint32 row_pos = 0; gint i, j; IFDBG(3) g_debug ("Start 1 bit conversion"); for (i = 0; i < rows * ((columns + 7) / 8); ++i) { guchar mask = 0x80; for (j = 0; j < 8 && row_pos < columns; ++j) { *dst = (*src & mask) ? 0 : 1; IFDBG(3) g_debug ("byte %d, bit %d, offset %d, src %d, dst %d", i , j, row_pos, *src, *dst); dst++; mask >>= 1; row_pos++; } if (row_pos >= columns) row_pos = 0; src++; } IFDBG(3) g_debug ("End 1 bit conversion"); } static const Babl* get_layer_format (PSDimage *img_a, gboolean alpha) { const Babl *format = NULL; switch (get_gimp_image_type (img_a->base_type, alpha)) { case GIMP_GRAY_IMAGE: switch (img_a->bps) { case 32: format = babl_format ("Y' u32"); break; case 16: format = babl_format ("Y' u16"); break; case 8: case 1: format = babl_format ("Y' u8"); break; default: return NULL; break; } break; case GIMP_GRAYA_IMAGE: switch (img_a->bps) { case 32: format = babl_format ("Y'A u32"); break; case 16: format = babl_format ("Y'A u16"); break; case 8: case 1: format = babl_format ("Y'A u8"); break; default: return NULL; break; } break; case GIMP_RGB_IMAGE: switch (img_a->bps) { case 32: format = babl_format ("R'G'B' u32"); break; case 16: format = babl_format ("R'G'B' u16"); break; case 8: case 1: format = babl_format (img_a->color_mode == PSD_CMYK ? "R'G'B' float" : "R'G'B' u8"); break; default: return NULL; break; } break; case GIMP_RGBA_IMAGE: switch (img_a->bps) { case 32: format = babl_format ("R'G'B'A u32"); break; case 16: format = babl_format ("R'G'B'A u16"); break; case 8: case 1: format = babl_format (img_a->color_mode == PSD_CMYK ? "R'G'B'A float" : "R'G'B'A u8"); break; default: return NULL; break; } break; default: return NULL; break; } return format; } static const Babl* get_channel_format (PSDimage *img_a) { const Babl *format = NULL; switch (img_a->bps) { case 32: format = babl_format ("Y u32"); break; case 16: format = babl_format ("Y u16"); break; case 8: case 1: /* see gimp_image_get_channel_format() */ format = babl_format ("Y' u8"); break; default: break; } return format; } static const Babl* get_mask_format (PSDimage *img_a) { const Babl *format = NULL; switch (img_a->bps) { case 32: format = babl_format ("Y u32"); break; case 16: format = babl_format ("Y u16"); break; case 8: case 1: format = babl_format ("Y u8"); break; default: break; } return format; }