1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Michael Natterer
3624c93209 file-psd: minor cleanup, mostly whitespace, reducing the diff to master 2013-10-30 23:21:09 +01:00
Simon Lui
beb298fbfd plug-in: Fix stuff for rebase from 'soc-2013-psd'. 2013-10-30 23:21:09 +01:00
Simon Lui
d688887e38 plug-ins: Remove warning put in by last commit and fix psd-save.c 2013-10-30 23:21:09 +01:00
Simon Lui
feee5bd75a plug-ins: Support > 8 bit psd files properly. 2013-10-30 23:21:09 +01:00
Simon Lui
505090d2ee plug-ins: Preliminary 16, 32 bit color PSD proper loading support. 2013-10-30 23:21:08 +01:00
Simon Lui
bf5c9e3e98 file-psd: Fix errors with GEGL code. 2013-10-30 23:21:08 +01:00
Simon Lui
bc5ebbe276 file-psd: Port remaining deprecated code to GEGL in psd-save.c 2013-10-30 23:21:08 +01:00
Simon Lui
fce974e1d3 Converted most deprecated operations in all but psd-save.c to use GEGL. 2013-10-30 23:21:08 +01:00
Simon Lui
d77c0833a2 Added part of the code to read text, and layer effects basic reading is implemented
There is code held back for now due to the unstable effects it brings to the build.
Will be withheld until it can be made stable.
2013-10-30 23:21:08 +01:00
Simon Lui
4dd45e0c26 file-psd: More cleanup of documentation and formatting of code. Image resource
1077 now loaded to ensure channel compatibility with PS CS3+ psds. Slight
changes to "PSDchannelData" struct also to support that. Debug mode enabled
also for the time being in code.
2013-10-30 23:21:08 +01:00
Simon Lui
33a0e20451 plug-ins: Initial branch creation and updated documentation. 2013-10-30 23:21:08 +01:00
7 changed files with 1131 additions and 387 deletions

View File

@@ -64,6 +64,7 @@ LDADD = \
$(libgimpbase) \
$(JPEG_LIBS) \
$(GTK_LIBS) \
$(GEGL_LIBS) \
$(EXIF_LIBS) \
$(IPTCDATA_LIBS) \
$(RT_LIBS) \

View File

@@ -75,11 +75,40 @@
PSD_ALPHA_ID = 1053, Loaded * 0x041d - Alpha IDs *
PSD_URL_LIST_UNI = 1054, * 0x041e - URL list - unicode *
PSD_VERSION_INFO = 1057, * 0x0421 - Version info *
PSD_EXIF_DATA = 1058, Loaded * 0x0422 - Exif data block *
PSD_EXIF_DATA = 1058, Loaded * 0x0422 - Exif data block 1 *
PSD_EXIF_DATA_3 = 1059 * 0X0423 - Exif data block 3 (?) *
PSD_XMP_DATA = 1060, Loaded * 0x0424 - XMP data block *
PSD_CAPTION_DIGEST = 1061, * 0x0425 - Caption digest *
PSD_PRINT_SCALE = 1062, * 0x0426 - Print scale *
PSD_PIXEL_AR = 1064, * 0x0428 - Pixel aspect ratio *
PSD_LAYER_COMPS = 1065, * 0x0429 - Layer comps *
PSD_ALT_DUOTONE_COLOR = 1066, * 0x042A - Alternative Duotone colors *
PSD_ALT_SPOT_COLOR = 1067, * 0x042B - Alternative Spot colors *
PSD_LAYER_SELECT_ID = 1069, * 0x042D - Layer selection ID *
PSD_HDR_TONING_INFO = 1070, * 0x042E - HDR toning information *
PSD_PRINT_INFO_SCALE = 1071, * 0x042F - Print scale *
PSD_LAYER_GROUP_E_ID = 1072, * 0x0430 - Layer group(s) enabled ID *
PSD_COLOR_SAMPLER_NEW = 1073, * 0x0431 - Color sampler resource for ps CS3 and higher PSD files *
PSD_MEASURE_SCALE = 1074, * 0x0432 - Measurement scale *
PSD_TIMELINE_INFO = 1075, * 0x0433 - Timeline information *
PSD_SHEET_DISCLOSE = 1076, * 0x0434 - Sheet discloser *
PSD_DISPLAY_INFO_NEW = 1077, Loaded * 0x0435 - DisplayInfo structure for ps CS3 and higher PSD files *
PSD_ONION_SKINS = 1078, * 0x0436 - Onion skins *
PSD_COUNT_INFO = 1080, * 0x0438 - Count information*
PSD_PRINT_INFO = 1082, * 0x043A - Print information added in ps CS5*
PSD_PRINT_STYLE = 1083, * 0x043B - Print style *
PSD_MAC_NSPRINTINFO = 1084, * 0x043C - Mac NSPrintInfo*
PSD_WIN_DEVMODE = 1085, * 0x043D - Windows DEVMODE *
PSD_AUTO_SAVE_PATH = 1086, * 0x043E - Auto save file path *
PSD_AUTO_SAVE_FORMAT = 1087, * 0x043F - Auto save format *
PSD_PATH_INFO_FIRST = 2000, Loaded * 0x07d0 - First path info block *
PSD_PATH_INFO_LAST = 2998, Loaded * 0x0bb6 - Last path info block *
PSD_CLIPPING_PATH = 2999, * 0x0bb7 - Name of clipping path *
PSD_PLUGIN_R_FIRST = 4000, * 0x0FA0 - First plugin resource *
PSD_PLUGIN_R_LAST = 4999, * 0x1387 - Last plugin resource *
PSD_IMAGEREADY_VARS = 7000, PS Only * 0x1B58 - Imageready variables *
PSD_IMAGEREADY_DATA = 7001, PS Only * 0x1B59 - Imageready data sets *
PSD_LIGHTROOM_WORK = 8000, PS Only * 0x1F40 - Lightroom workflow *
PSD_PRINT_FLAGS_2 = 10000 * 0x2710 - Print flags *
*/
@@ -193,6 +222,12 @@ static gint load_resource_1058 (const PSDimageres *res_a,
FILE *f,
GError **error);
static gint load_resource_1077 (const PSDimageres *res_a,
const gint32 image_id,
PSDimage *img_a,
FILE *f,
GError **error);
static gint load_resource_2000 (const PSDimageres *res_a,
const gint32 image_id,
FILE *f,
@@ -254,7 +289,7 @@ load_image_resource (PSDimageres *res_a,
return -1;
}
/* Process image resource blocks */
/* Process image resource blocks */
if (memcmp (res_a->type, "8BIM", 4) != 0 &&
memcmp (res_a->type, "MeSa", 4) !=0)
{
@@ -349,6 +384,10 @@ load_image_resource (PSDimageres *res_a,
case PSD_XMP_DATA:
break;
case PSD_DISPLAY_INFO_NEW:
load_resource_1077 (res_a, image_id, img_a, f, error);
break;
default:
if (res_a->id >= 2000 &&
res_a->id < 2999)
@@ -390,14 +429,14 @@ load_thumbnail_resource (PSDimageres *res_a,
return -1;
}
/* Process image resource blocks */
if (res_a->id == PSD_THUMB_RES
|| res_a->id == PSD_THUMB_RES2)
{
/* Load thumbnails from standard file load */
load_resource_1033 (res_a, image_id, f, error);
rtn = 1;
}
/* Process image resource blocks */
if (res_a->id == PSD_THUMB_RES
|| res_a->id == PSD_THUMB_RES2)
{
/* Load thumbnails from standard file load */
load_resource_1033 (res_a, image_id, f, error);
rtn = 1;
}
/* Image blocks are null padded to even length */
if (res_a->data_len % 2 == 0)
@@ -439,7 +478,7 @@ load_resource_unknown (const PSDimageres *res_a,
}
name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
res_a->type, res_a->id);
res_a->type, res_a->id);
IFDBG(2) g_debug ("Parasite name: %s", name);
parasite = gimp_parasite_new (name, 0, res_a->data_len, data);
@@ -474,7 +513,7 @@ load_resource_ps_only (const PSDimageres *res_a,
}
name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
res_a->type, res_a->id);
res_a->type, res_a->id);
IFDBG(2) g_debug ("Parasite name: %s", name);
parasite = gimp_parasite_new (name, 0, res_a->data_len, data);
@@ -519,12 +558,12 @@ load_resource_1005 (const PSDimageres *res_a,
res_info.heightUnit = GINT16_FROM_BE (res_info.heightUnit);
IFDBG(3) g_debug ("Resolution: %d, %d, %d, %d, %d, %d",
res_info.hRes,
res_info.hResUnit,
res_info.widthUnit,
res_info.vRes,
res_info.vResUnit,
res_info.heightUnit);
res_info.hRes,
res_info.hResUnit,
res_info.widthUnit,
res_info.vRes,
res_info.vResUnit,
res_info.heightUnit);
/* Resolution always recorded as pixels / inch in a fixed point implied
decimal int32 with 16 bits before point and 16 after (i.e. cast as
@@ -535,14 +574,14 @@ load_resource_1005 (const PSDimageres *res_a,
/* GIMP only has one display unit so use ps horizontal resolution unit */
switch (res_info.hResUnit)
{
case PSD_RES_INCH:
image_unit = GIMP_UNIT_INCH;
break;
case PSD_RES_CM:
image_unit = GIMP_UNIT_MM;
break;
default:
image_unit = GIMP_UNIT_INCH;
case PSD_RES_INCH:
image_unit = GIMP_UNIT_INCH;
break;
case PSD_RES_CM:
image_unit = GIMP_UNIT_MM;
break;
default:
image_unit = GIMP_UNIT_INCH;
}
gimp_image_set_unit (image_id, image_unit);
@@ -681,13 +720,13 @@ load_resource_1007 (const PSDimageres *res_a,
gimp_rgb_set_alpha (&gimp_rgb, 1.0);
IFDBG(2) g_debug ("PS cSpace: %d, col: %d %d %d %d, opacity: %d, kind: %d",
dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
dsp_info.kind);
dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
dsp_info.kind);
IFDBG(2) g_debug ("cSpace: %d, col: %g %g %g, opacity: %d, kind: %d",
dsp_info.colorSpace, gimp_rgb.r * 255 , gimp_rgb.g * 255,
gimp_rgb.b * 255, dsp_info.opacity, dsp_info.kind);
dsp_info.colorSpace, gimp_rgb.r * 255 , gimp_rgb.g * 255,
gimp_rgb.b * 255, dsp_info.opacity, dsp_info.kind);
img_a->alpha_display_info[cidx] = g_malloc (sizeof (PSDchanneldata));
img_a->alpha_display_info[cidx]->gimp_color = gimp_rgb;
@@ -748,8 +787,8 @@ load_resource_1022 (const PSDimageres *res_a,
img_a->quick_mask_id = GUINT16_FROM_BE (img_a->quick_mask_id);
IFDBG(3) g_debug ("Quick mask channel: %d, empty: %d",
img_a->quick_mask_id,
quick_mask_empty);
img_a->quick_mask_id,
quick_mask_empty);
return 0;
}
@@ -913,8 +952,8 @@ load_resource_1033 (const PSDimageres *res_a,
struct jpeg_error_mgr jerr;
ThumbnailInfo thumb_info;
GimpDrawable *drawable;
GimpPixelRgn pixel_rgn;
GeglBuffer *buffer;
const Babl *format;
gint32 layer_id;
guchar *buf;
guchar *rgb_buf;
@@ -948,9 +987,9 @@ load_resource_1033 (const PSDimageres *res_a,
IFDBG(2) g_debug ("\nThumbnail:\n"
"\tFormat: %d\n"
"\tDimensions: %d x %d\n",
thumb_info.format,
thumb_info.width,
thumb_info.height);
thumb_info.format,
thumb_info.width,
thumb_info.height);
if (thumb_info.format != 1)
{
@@ -995,9 +1034,8 @@ load_resource_1033 (const PSDimageres *res_a,
cinfo.output_width,
cinfo.output_height,
GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE);
drawable = gimp_drawable_get (layer_id);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
drawable->width, drawable->height, TRUE, FALSE);
buffer = gimp_drawable_get_buffer (layer_id);
format = babl_format ("R'G'B'A u8");
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
@@ -1011,7 +1049,7 @@ load_resource_1033 (const PSDimageres *res_a,
guchar *dst = rgb_buf;
guchar *src = buf;
for (i = 0; i < drawable->width * drawable->height; ++i)
for (i = 0; i < gegl_buffer_get_width (buffer) * gegl_buffer_get_height (buffer); ++i)
{
guchar r, g, b;
@@ -1023,8 +1061,8 @@ load_resource_1033 (const PSDimageres *res_a,
*(dst++) = r;
}
}
gimp_pixel_rgn_set_rect (&pixel_rgn, rgb_buf ? rgb_buf : buf,
0, 0, drawable->width, drawable->height);
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)),
0, format, rgb_buf ? rgb_buf : buf, GEGL_AUTO_ROWSTRIDE);
}
/* Step 7: Finish decompression */
@@ -1046,7 +1084,7 @@ load_resource_1033 (const PSDimageres *res_a,
* jerr.num_warnings is nonzero).
*/
gimp_image_insert_layer (image_id, layer_id, -1, 0);
gimp_drawable_detach (drawable);
g_object_unref (buffer);
return 0;
}
@@ -1232,6 +1270,118 @@ load_resource_1058 (const PSDimageres *res_a,
return 0;
}
static gint
load_resource_1077 (const PSDimageres *res_a,
const gint32 image_id,
PSDimage *img_a,
FILE *f,
GError **error)
{
/* Load alpha channel display info */
DisplayInfoNew dsp_info;
CMColor ps_color;
GimpRGB gimp_rgb;
GimpHSV gimp_hsv;
GimpCMYK gimp_cmyk;
gint16 tot_rec;
gint cidx;
IFDBG(2) g_debug ("Process image resource block 1077: Display Info New");
/* For now, skip first 4 bytes since intention is unclear. Seems to be
a version number that is always one, but who knows. */
fseek (f, 4, SEEK_CUR);
tot_rec = res_a->data_len / 13;
if (tot_rec == 0)
return 0;
img_a->alpha_display_info = g_new (PSDchanneldata *, tot_rec);
img_a->alpha_display_count = tot_rec;
for (cidx = 0; cidx < tot_rec; ++cidx)
{
if (fread (&dsp_info.colorSpace, 2, 1, f) < 1
|| fread (&dsp_info.color, 8, 1, f) < 1
|| fread (&dsp_info.opacity, 2, 1, f) < 1
|| fread (&dsp_info.mode, 1, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
dsp_info.colorSpace = GINT16_FROM_BE (dsp_info.colorSpace);
ps_color.cmyk.cyan = GUINT16_FROM_BE (dsp_info.color[0]);
ps_color.cmyk.magenta = GUINT16_FROM_BE (dsp_info.color[1]);
ps_color.cmyk.yellow = GUINT16_FROM_BE (dsp_info.color[2]);
ps_color.cmyk.black = GUINT16_FROM_BE (dsp_info.color[3]);
dsp_info.opacity = GINT16_FROM_BE (dsp_info.opacity);
switch (dsp_info.colorSpace)
{
case PSD_CS_RGB:
gimp_rgb_set (&gimp_rgb, ps_color.rgb.red / 65535.0,
ps_color.rgb.green / 65535.0,
ps_color.rgb.blue / 65535.0);
break;
case PSD_CS_HSB:
gimp_hsv_set (&gimp_hsv, ps_color.hsv.hue / 65535.0,
ps_color.hsv.saturation / 65535.0,
ps_color.hsv.value / 65535.0);
gimp_hsv_to_rgb (&gimp_hsv, &gimp_rgb);
break;
case PSD_CS_CMYK:
gimp_cmyk_set (&gimp_cmyk, 1.0 - ps_color.cmyk.cyan / 65535.0,
1.0 - ps_color.cmyk.magenta / 65535.0,
1.0 - ps_color.cmyk.yellow / 65535.0,
1.0 - ps_color.cmyk.black / 65535.0);
gimp_cmyk_to_rgb (&gimp_cmyk, &gimp_rgb);
break;
case PSD_CS_GRAYSCALE:
gimp_rgb_set (&gimp_rgb, ps_color.gray.gray / 10000.0,
ps_color.gray.gray / 10000.0,
ps_color.gray.gray / 10000.0);
break;
case PSD_CS_FOCOLTONE:
case PSD_CS_TRUMATCH:
case PSD_CS_HKS:
case PSD_CS_LAB:
case PSD_CS_PANTONE:
case PSD_CS_TOYO:
case PSD_CS_DIC:
case PSD_CS_ANPA:
default:
if (CONVERSION_WARNINGS)
g_message ("Unsupported color space: %d",
dsp_info.colorSpace);
gimp_rgb_set (&gimp_rgb, 1.0, 0.0, 0.0);
}
gimp_rgb_set_alpha (&gimp_rgb, 1.0);
IFDBG(2) g_debug ("PS cSpace: %d, col: %d %d %d %d, opacity: %d, kind: %d",
dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
dsp_info.kind);
IFDBG(2) g_debug ("cSpace: %d, col: %g %g %g, opacity: %d, kind: %d",
dsp_info.colorSpace, gimp_rgb.r * 255 , gimp_rgb.g * 255,
gimp_rgb.b * 255, dsp_info.opacity, dsp_info.kind);
img_a->alpha_display_info[cidx] = g_malloc (sizeof (PSDchanneldata));
img_a->alpha_display_info[cidx]->gimp_color = gimp_rgb;
img_a->alpha_display_info[cidx]->opacity = dsp_info.opacity;
img_a->alpha_display_info[cidx]->ps_mode = dsp_info.mode;
img_a->alpha_display_info[cidx]->ps_cspace = dsp_info.colorSpace;
img_a->alpha_display_info[cidx]->ps_color = ps_color;
}
return 0;
}
static gint
load_resource_2000 (const PSDimageres *res_a,
const gint32 image_id,
@@ -1377,11 +1527,11 @@ load_resource_2000 (const PSDimageres *res_a,
|| type == PSD_PATH_OP_UNLNK)
{
if (fread (&y[0], 4, 1, f) < 1
|| fread (&x[0], 4, 1, f) < 1
|| fread (&y[1], 4, 1, f) < 1
|| fread (&x[1], 4, 1, f) < 1
|| fread (&y[2], 4, 1, f) < 1
|| fread (&x[2], 4, 1, f) < 1)
|| fread (&x[0], 4, 1, f) < 1
|| fread (&y[1], 4, 1, f) < 1
|| fread (&x[1], 4, 1, f) < 1
|| fread (&y[2], 4, 1, f) < 1
|| fread (&x[2], 4, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
@@ -1429,5 +1579,5 @@ load_resource_2000 (const PSDimageres *res_a,
path_rec--;
}
return 0;
return 0;
}

View File

@@ -22,7 +22,7 @@
All layer resources not otherwise handled, including unknown types
are dropped with a warning.
* Adjustment layer IDs *
* Adjustment layer IDs *
PSD_LADJ_LEVEL "levl" Drop Layer * Adjustment layer - levels (PS4) *
PSD_LADJ_CURVE "curv" Drop Layer * Adjustment layer - curves (PS4) *
PSD_LADJ_BRIGHTNESS "brit" Drop Layer * Adjustment layer - brightness contrast (PS4) *
@@ -38,21 +38,23 @@
PSD_LADJ_INVERT "nvrt" Drop Layer * Adjustment layer - invert (PS4) *
PSD_LADJ_THRESHOLD "thrs" Drop Layer * Adjustment layer - threshold (PS4) *
PSD_LADJ_POSTERIZE "post" Drop Layer * Adjustment layer - posterize (PS4) *
PSD_LADJ_VIBRANCE "vibA" - * Adjustment layer - vibrance (PS10) *
PSD_LADJ_COLOR_LOOKUP "clrL" - * Adjustment layer - color lookup (PS13) *
* Fill Layer IDs *
* Fill Layer IDs *
PSD_LFIL_SOLID "SoCo" - * Solid color sheet setting (PS6) *
PSD_LFIL_PATTERN "PtFl" - * Pattern fill setting (PS6) *
PSD_LFIL_GRADIENT "GdFl" - * Gradient fill setting (PS6) *
* Effects Layer IDs *
* Effects Layer IDs *
PSD_LFX_FX "lrFX" - * Effects layer info (PS5) *
PSD_LFX_FX2 "lfx2" - * Object based effects layer info (PS6) *
* Type Tool Layers *
* Type Tool Layers *
PSD_LTYP_TYPE "tySh" - * Type tool layer (PS5) *
PSD_LTYP_TYPE2 "TySh" - * Type tool object setting (PS6) *
* Layer Properties *
* Layer Properties *
PSD_LPRP_UNICODE "luni" Loaded * Unicode layer name (PS5) *
PSD_LPRP_SOURCE "lnsr" Loaded * Layer name source setting (PS6) *
PSD_LPRP_ID "lyid" Loaded * Layer ID (PS5) *
@@ -63,13 +65,13 @@
PSD_LPRP_COLOR "lclr" - * Sheet color setting (PS6) *
PSD_LPRP_REF_POINT "fxrp" - * Reference point (PS6) *
* Vector mask *
* Vector mask *
PSD_LMSK_VMASK "vmsk" - * Vector mask setting (PS6) *
* Parasites *
* Parasites *
PSD_LPAR_ANNOTATE "Anno" - * Annotation (PS6) *
* Other *
* Other *
PSD_LOTH_PATTERN "Patt" - * Patterns (PS6) *
PSD_LOTH_GRADIENT "grdm" - * Gradient settings (PS6) *
PSD_LOTH_SECTION "lsct" Loaded * Section divider setting (PS6) (Layer Groups) *
@@ -78,14 +80,42 @@
PSD_LOTH_PATT_DATA "shpa" - * Pattern data (PS6) *
PSD_LOTH_META_DATA "shmd" - * Meta data setting (PS6) *
PSD_LOTH_LAYER_DATA "layr" - * Layer data (PS6) *
PSD_LOTH_CONTENT_GEN "CgEd" - * Content generator extra data (PS12) *
PSD_LOTH_TEXT_ENGINE "Txt2" - * Text engine data (PS10) *
PSD_LOTH_PATH_NAME "pths" - * Unicode path name (PS13) *
PSD_LOTH_ANIMATION_FX "anFX" - * Animation effects (PS13) *
PSD_LOTH_FILTER_MASK "FMsk" - * Filter mask (PS10) *
PSD_LOTH_VECTOR_STROKE "vscg" - * Vector stroke data (PS13) *
PSD_LOTH_ALIGN_RENDER "sn2P" - * Aligned rendering flag (?) *
PSD_LOTH_USER_MASK "LMsk" - * User mask (?) *
* Effects layer resource IDs *
* Effects layer resource IDs *
PSD_LFX_COMMON "cmnS" - * Effects layer - common state (PS5) *
PSD_LFX_DROP_SDW "dsdw" - * Effects layer - drop shadow (PS5) *
PSD_LFX_INNER_SDW "isdw" - * Effects layer - inner shadow (PS5) *
PSD_LFX_OUTER_GLW "oglw" - * Effects layer - outer glow (PS5) *
PSD_LFX_INNER_GLW "iglw" - * Effects layer - inner glow (PS5) *
PSD_LFX_BEVEL "bevl" - * Effects layer - bevel (PS5) *
* New stuff temporarily until I can get them sorted out *
* Placed Layer *
PSD_LPL_PLACE_LAYER "plLd" - * Placed layer (?) *
PSD_LPL_PLACE_LAYER_NEW "SoLd" - * Placed layer (PS10) *
* Linked Layer *
PSD_LLL_LINKED_LAYER "lnkD" - * Linked layer (?) *
PSD_LLL_LINKED_LAYER_2 "lnk2" - * Linked layer 2nd key *
PSD_LLL_LINKED_LAYER_3 "lnk3" - * Linked layer 3rd key *
* Merged Transparency *
PSD_LMT_MERGE_TRANS "Mtrn" - * Merged transperency save flag (?) *
PSD_LMT_MERGE_TRANS_16 "Mt16" - * Merged transperency save flag 2 *
PSD_LMT_MERGE_TRANS_32 "Mt32" - * Merged transperency save flag 3 *
* Filter Effects *
PSD_LFFX_FILTER_FX "FXid" - * Filter effects (?) *
PSD_LFFX_FILTER_FX_2 "FEid" - * Filter effects 2 *
*/
#include "config.h"
@@ -143,6 +173,10 @@ static gint load_resource_lsct (const PSDlayerres *res_a,
FILE *f,
GError **error);
static gint load_resource_lrfx (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f,
GError **error);
/* Public Functions */
gint
@@ -161,7 +195,7 @@ get_layer_resource_header (PSDlayerres *res_a,
res_a->data_start = ftell (f);
IFDBG(2) g_debug ("Sig: %.4s, key: %.4s, start: %d, len: %d",
res_a->sig, res_a->key, res_a->data_start, res_a->data_len);
res_a->sig, res_a->key, res_a->data_start, res_a->data_len);
return 0;
}
@@ -179,7 +213,7 @@ load_layer_resource (PSDlayerres *res_a,
return -1;
}
/* Process layer resource blocks */
/* Process layer resource blocks */
if (memcmp (res_a->sig, "8BIM", 4) != 0)
{
IFDBG(1) g_debug ("Unknown layer resource signature %.4s", res_a->sig);
@@ -201,30 +235,32 @@ load_layer_resource (PSDlayerres *res_a,
|| memcmp (res_a->key, PSD_LADJ_THRESHOLD, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_INVERT, 4) == 0
|| memcmp (res_a->key, PSD_LADJ_POSTERIZE, 4) == 0)
load_resource_ladj (res_a, lyr_a, f, error);
load_resource_ladj (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LFIL_SOLID, 4) == 0
|| memcmp (res_a->key, PSD_LFIL_PATTERN, 4) == 0
|| memcmp (res_a->key, PSD_LFIL_GRADIENT, 4) == 0)
load_resource_lfil (res_a, lyr_a, f, error);
|| memcmp (res_a->key, PSD_LFIL_PATTERN, 4) == 0
|| memcmp (res_a->key, PSD_LFIL_GRADIENT, 4) == 0)
load_resource_lfil (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0
|| memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
load_resource_lfx (res_a, lyr_a, f, error);
|| memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
load_resource_lfx (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LTYP_TYPE, 4) == 0
|| memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
load_resource_ltyp (res_a, lyr_a, f, error);
|| memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
load_resource_ltyp (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LPRP_UNICODE, 4) == 0)
load_resource_luni (res_a, lyr_a, f, error);
load_resource_luni (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LPRP_ID, 4) == 0)
load_resource_lyid (res_a, lyr_a, f, error);
load_resource_lyid (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LOTH_SECTION, 4) == 0)
load_resource_lsct (res_a, lyr_a, f, error);
load_resource_lsct (res_a, lyr_a, f, error);
else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0)
load_resource_lrfx (res_a, lyr_a, f, error);
else
load_resource_unknown (res_a, lyr_a, f, error);
}
@@ -329,18 +365,15 @@ load_resource_ltyp (const PSDlayerres *res_a,
gint16 version;
gint16 text_desc_vers;
gint32 desc_version;
gint32 read_len;
gint32 write_len;
guint64 t_xx;
guint64 t_xy;
guint64 t_yx;
guint64 t_yy;
guint64 t_tx;
guint64 t_ty;
gdouble transform_xx;
gdouble transform_xy;
gdouble transform_yx;
gdouble transform_yy;
gdouble transform_tx;
gdouble transform_ty;
gchar *classID;
static gboolean msg_flag = FALSE;
@@ -374,31 +407,30 @@ load_resource_ltyp (const PSDlayerres *res_a,
version = GINT16_FROM_BE (version);
text_desc_vers = GINT16_FROM_BE (text_desc_vers);
desc_version = GINT32_FROM_BE (desc_version);
// t_xx = GUINT64_FROM_BE (t_xx);
// t_xy = GUINT64_FROM_BE (t_xy);
// t_yx = GUINT64_FROM_BE (t_yx);
// t_yy = GUINT64_FROM_BE (t_yy);
// t_tx = GUINT64_FROM_BE (t_tx);
// t_ty = GUINT64_FROM_BE (t_ty);
// t_xx = GUINT64_FROM_BE (t_xx);
// t_xy = GUINT64_FROM_BE (t_xy);
// t_yx = GUINT64_FROM_BE (t_yx);
// t_yy = GUINT64_FROM_BE (t_yy);
// t_tx = GUINT64_FROM_BE (t_tx);
// t_ty = GUINT64_FROM_BE (t_ty);
transform_xx = t_xx >> 11;
transform_xy = t_xy >> 11;
transform_yx = t_yx >> 11;
transform_yy = t_yy >> 11;
transform_tx = t_tx >> 11;
transform_ty = t_ty >> 11;
lyr_a->text.xx = t_xx >> 11;
lyr_a->text.xy = t_xy >> 11;
lyr_a->text.yx = t_yx >> 11;
lyr_a->text.yy = t_yy >> 11;
lyr_a->text.tx = t_tx >> 11;
lyr_a->text.ty = t_ty >> 11;
IFDBG(2) g_debug ("Version: %d, Text desc. vers.: %d, Desc. vers.: %d",
version, text_desc_vers, desc_version);
IFDBG(2) g_debug ("Transform\n\txx: %f\n\txy: %f\n\tyx: %f"
"\n\tyy: %f\n\ttx: %f\n\tty: %f",
transform_xx, transform_xy, transform_yx,
transform_yy, transform_tx, transform_ty);
// classID = fread_unicode_string (&read_len, &write_len, 4, f);
// IFDBG(2) g_debug ("Unicode name: %s", classID);
lyr_a->text.xx, lyr_a->text.xy, lyr_a->text.yx,
lyr_a->text.yy, lyr_a->text.tx, lyr_a->text.ty);
classID = fread_unicode_string (&read_len, &write_len, 4, f, error);
IFDBG(2) g_debug ("Unicode name: %s", classID);
}
return 0;
@@ -472,3 +504,342 @@ load_resource_lsct (const PSDlayerres *res_a,
return 0;
}
static gint
load_resource_lrfx (const PSDlayerres *res_a,
PSDlayer *lyr_a,
FILE *f,
GError **error)
{
gint16 version;
gint16 count;
gchar signature[4];
gchar effectname[4];
gint i;
IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key);
if (fread (&version, 2, 1, f) < 1
|| fread (&count, 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
for (i = 0; i < count; i++)
{
if (fread (&signature, 4, 1, f) < 1
|| fread(&effectname, 4, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
if (memcmp (signature, "8BIM", 4) != 0)
{
IFDBG(1) g_debug ("Unknown layer resource signature %.4s", signature);
}
else
{
if (memcmp (effectname, "cmnS", 4) == 0)
{
gint32 size;
gint32 ver;
gchar visible;
gint16 unused;
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&visible, 1, 1, f) < 1
|| fread(&unused, 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
else if (memcmp (effectname, "dsdw", 4) == 0
|| memcmp (effectname, "isdw", 4) == 0)
{
gint32 size;
gint32 ver;
gint32 blur;
gint32 intensity;
gint32 angle;
gint32 distance;
gint16 color[5];
gint32 blendsig;
gint32 effect;
gchar effecton;
gchar anglefx;
gchar opacity;
gint16 natcolor[5];
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&blur, 4, 1, f) < 1
|| fread(&intensity, 4, 1, f) < 1
|| fread(&angle, 4, 1, f) < 1
|| fread(&distance, 4, 1, f) < 1
|| fread(&color[0], 2, 1, f) < 1
|| fread(&color[1], 2, 1, f) < 1
|| fread(&color[2], 2, 1, f) < 1
|| fread(&color[3], 2, 1, f) < 1
|| fread(&color[4], 2, 1, f) < 1
|| fread(&blendsig, 4, 1, f) < 1
|| fread(&effect, 4, 1, f) < 1
|| fread(&effecton, 1, 1, f) < 1
|| fread(&anglefx, 1, 1, f) < 1
|| fread(&opacity, 1, 1, f) < 1
|| fread(&natcolor[0], 2, 1, f) < 1
|| fread(&natcolor[1], 2, 1, f) < 1
|| fread(&natcolor[2], 2, 1, f) < 1
|| fread(&natcolor[3], 2, 1, f) < 1
|| fread(&natcolor[4], 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
else if (memcmp (effectname, "oglw", 4) == 0)
{
gint32 size;
gint32 ver;
gint32 blur;
gint32 intensity;
gint16 color[5];
gint32 blendsig;
gint32 effect;
gchar effecton;
gchar opacity;
gint16 natcolor[5];
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&blur, 4, 1, f) < 1
|| fread(&intensity, 4, 1, f) < 1
|| fread(&color[0], 2, 1, f) < 1
|| fread(&color[1], 2, 1, f) < 1
|| fread(&color[2], 2, 1, f) < 1
|| fread(&color[3], 2, 1, f) < 1
|| fread(&color[4], 2, 1, f) < 1
|| fread(&blendsig, 4, 1, f) < 1
|| fread(&effect, 4, 1, f) < 1
|| fread(&effecton, 1, 1, f) < 1
|| fread(&opacity, 1, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
if (ver == 42)
{
if (fread(&natcolor[0], 2, 1, f) < 1
|| fread(&natcolor[1], 2, 1, f) < 1
|| fread(&natcolor[2], 2, 1, f) < 1
|| fread(&natcolor[3], 2, 1, f) < 1
|| fread(&natcolor[4], 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
}
else if (memcmp (effectname, "iglw", 4) == 0)
{
gint32 size;
gint32 ver;
gint32 blur;
gint32 intensity;
gint32 angle;
gint32 distance;
gint16 color[5];
gint32 blendsig;
gint32 effect;
gchar effecton;
gchar anglefx;
gchar opacity;
gint16 natcolor[5];
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&blur, 4, 1, f) < 1
|| fread(&intensity, 4, 1, f) < 1
|| fread(&angle, 4, 1, f) < 1
|| fread(&distance, 4, 1, f) < 1
|| fread(&color[0], 2, 1, f) < 1
|| fread(&color[1], 2, 1, f) < 1
|| fread(&color[2], 2, 1, f) < 1
|| fread(&color[3], 2, 1, f) < 1
|| fread(&color[4], 2, 1, f) < 1
|| fread(&blendsig, 4, 1, f) < 1
|| fread(&effect, 4, 1, f) < 1
|| fread(&effecton, 1, 1, f) < 1
|| fread(&anglefx, 1, 1, f) < 1
|| fread(&opacity, 1, 1, f) < 1
|| fread(&natcolor[0], 2, 1, f) < 1
|| fread(&natcolor[1], 2, 1, f) < 1
|| fread(&natcolor[2], 2, 1, f) < 1
|| fread(&natcolor[3], 2, 1, f) < 1
|| fread(&natcolor[4], 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
else if (memcmp (effectname, "oglw", 4) == 0)
{
gint32 size;
gint32 ver;
gint32 blur;
gint32 intensity;
gint16 color[5];
gint32 blendsig;
gint32 effect;
gchar effecton;
gchar opacity;
gchar invert;
gint16 natcolor[5];
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&blur, 4, 1, f) < 1
|| fread(&intensity, 4, 1, f) < 1
|| fread(&color[0], 2, 1, f) < 1
|| fread(&color[1], 2, 1, f) < 1
|| fread(&color[2], 2, 1, f) < 1
|| fread(&color[3], 2, 1, f) < 1
|| fread(&color[4], 2, 1, f) < 1
|| fread(&blendsig, 4, 1, f) < 1
|| fread(&effect, 4, 1, f) < 1
|| fread(&effecton, 1, 1, f) < 1
|| fread(&opacity, 1, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
if (ver == 43)
{
if (fread (&invert, 1, 1, f) < 1
|| fread(&natcolor[0], 2, 1, f) < 1
|| fread(&natcolor[0], 2, 1, f) < 1
|| fread(&natcolor[1], 2, 1, f) < 1
|| fread(&natcolor[2], 2, 1, f) < 1
|| fread(&natcolor[3], 2, 1, f) < 1
|| fread(&natcolor[4], 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
}
else if (memcmp (effectname, "bevl", 4) == 0)
{
gint32 size;
gint32 ver;
gint32 angle;
gint32 strength;
gint32 blur;
gint32 highlightsig;
gint32 highlighteffect;
gint32 shadowsig;
gint32 shadoweffect;
gint16 highlightcolor[5];
gint16 shadowcolor[5];
gchar style;
gchar highlightopacity;
gchar shadowopacity;
gchar enabled;
gchar global;
gchar direction;
gint16 highlightnatcolor[5];
gint16 shadownatcolor[5];
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&angle, 4, 1, f) < 1
|| fread(&strength, 4, 1, f) < 1
|| fread(&blur, 4, 1, f) < 1
|| fread(&highlightsig, 4, 1, f) < 1
|| fread(&highlighteffect, 4, 1, f) < 1
|| fread(&shadowsig, 4, 1, f) < 1
|| fread(&highlightcolor[0], 2, 1, f) < 1
|| fread(&shadoweffect, 4, 1, f) < 1
|| fread(&highlightcolor[1], 2, 1, f) < 1
|| fread(&highlightcolor[2], 2, 1, f) < 1
|| fread(&highlightcolor[3], 2, 1, f) < 1
|| fread(&highlightcolor[4], 2, 1, f) < 1
|| fread(&shadowcolor[0], 2, 1, f) < 1
|| fread(&shadowcolor[1], 2, 1, f) < 1
|| fread(&shadowcolor[2], 2, 1, f) < 1
|| fread(&shadowcolor[3], 2, 1, f) < 1
|| fread(&shadowcolor[4], 2, 1, f) < 1
|| fread(&style, 1, 1, f) < 1
|| fread(&highlightopacity, 1, 1, f) < 1
|| fread(&shadowopacity, 1, 1, f) < 1
|| fread(&enabled, 1, 1, f) < 1
|| fread(&global, 1, 1, f) < 1
|| fread(&direction, 1, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
if (ver == 78)
{
if (fread(&highlightnatcolor[0], 2, 1, f) < 1
|| fread(&highlightnatcolor[0], 2, 1, f) < 1
|| fread(&highlightnatcolor[1], 2, 1, f) < 1
|| fread(&highlightnatcolor[2], 2, 1, f) < 1
|| fread(&highlightnatcolor[3], 2, 1, f) < 1
|| fread(&highlightnatcolor[4], 2, 1, f) < 1
|| fread(&shadownatcolor[0], 2, 1, f) < 1
|| fread(&shadownatcolor[0], 2, 1, f) < 1
|| fread(&shadownatcolor[1], 2, 1, f) < 1
|| fread(&shadownatcolor[2], 2, 1, f) < 1
|| fread(&shadownatcolor[3], 2, 1, f) < 1
|| fread(&shadownatcolor[4], 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
}
else if (memcmp (effectname, "sofi", 4) == 0)
{
gint32 size;
gint32 ver;
gint32 key;
gint16 color[5];
gchar opacity;
gchar enabled;
gint16 natcolor[5];
if (fread (&size, 4, 1, f) < 1
|| fread(&ver, 4, 1, f) < 1
|| fread(&key, 4, 1, f) < 1
|| fread(&color[0], 2, 1, f) < 1
|| fread(&color[1], 2, 1, f) < 1
|| fread(&color[2], 2, 1, f) < 1
|| fread(&color[3], 2, 1, f) < 1
|| fread(&color[4], 2, 1, f) < 1
|| fread(&opacity, 1, 1, f) < 1
|| fread(&enabled, 1, 1, f) < 1
|| fread(&natcolor[0], 2, 1, f) < 1
|| fread(&natcolor[1], 2, 1, f) < 1
|| fread(&natcolor[2], 2, 1, f) < 1
|| fread(&natcolor[3], 2, 1, f) < 1
|| fread(&natcolor[4], 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
}
else
{
IFDBG(1) g_debug ("Unknown layer effect signature %.4s", effectname);
}
}
}
return 0;
}

View File

@@ -97,15 +97,13 @@ static gint read_channel_data (PSDchannel *channel,
FILE *f,
GError **error);
static void convert_16_bit (const gchar *src,
gchar *dst,
guint32 len);
static void convert_1_bit (const gchar *src,
gchar *dst,
guint32 rows,
guint32 columns);
static const Babl* get_pixel_format (PSDimage *img_a);
/* Main file load function */
gint32
@@ -326,16 +324,15 @@ read_header_block (PSDimage *img_a,
return -1;
}
/* Warnings for format conversions */
/* 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");
if (CONVERSION_WARNINGS)
g_message (_("Warning:\n"
"The image you are loading has 16 bits per channel. GIMP "
"can only handle 8 bit, so it will be converted for you. "
"Information will be lost because of this conversion."));
break;
case 8:
@@ -484,6 +481,7 @@ read_layer_block (PSDimage *img_a,
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);
@@ -525,6 +523,7 @@ read_layer_block (PSDimage *img_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 */
@@ -544,6 +543,7 @@ read_layer_block (PSDimage *img_a,
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);
@@ -590,6 +590,7 @@ read_layer_block (PSDimage *img_a,
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
@@ -630,6 +631,7 @@ read_layer_block (PSDimage *img_a,
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
@@ -802,9 +804,11 @@ read_layer_block (PSDimage *img_a,
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)
@@ -818,6 +822,7 @@ read_layer_block (PSDimage *img_a,
4, f, error);
if (*error)
return NULL;
block_rem -= read_len;
IFDBG(3) g_debug ("Remaining length %d", block_rem);
@@ -827,8 +832,13 @@ read_layer_block (PSDimage *img_a,
{
if (get_layer_resource_header (&res_a, f, error) < 0)
return NULL;
block_rem -= 12;
//Round up to the nearest even byte
while (res_a.data_len % 4 != 0)
res_a.data_len++;
if (res_a.data_len > block_rem)
{
IFDBG(1) g_debug ("Unexpected end of layer resource data");
@@ -902,6 +912,7 @@ create_gimp_image (PSDimage *img_a,
const gchar *filename)
{
gint32 image_id = -1;
GimpPrecision precision;
switch (img_a->color_mode)
{
@@ -926,10 +937,32 @@ create_gimp_image (PSDimage *img_a,
break;
}
switch (img_a->bps)
{
case 32:
precision = GIMP_PRECISION_U32_LINEAR;
break;
case 16:
precision = GIMP_PRECISION_U16_LINEAR;
break;
case 8:
case 1:
precision = GIMP_PRECISION_U8_LINEAR;
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 (img_a->columns, img_a->rows, img_a->base_type);
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);
@@ -1025,6 +1058,7 @@ add_layers (const gint32 image_id,
guint16 layer_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 */
@@ -1045,8 +1079,7 @@ add_layers (const gint32 image_id,
gboolean user_mask;
gboolean empty;
gboolean empty_mask;
GimpDrawable *drawable;
GimpPixelRgn pixel_rgn;
GeglBuffer *buffer;
GimpImageType image_type;
GimpLayerModeEffects layer_mode;
@@ -1092,25 +1125,25 @@ add_layers (const gint32 image_id,
}
else
{
if (lyr_a[lidx]->group_type != 0)
{
if (lyr_a[lidx]->group_type == 3)
{
/* the </Layer group> marker layers are used to
assemble the layer structure in a single pass */
layer_id = gimp_layer_group_new (image_id);
}
else /* group-type == 1 || group_type == 2 */
{
layer_id = g_array_index (parent_group_stack, gint32,
parent_group_stack->len-1);
/* 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);
}
}
if (lyr_a[lidx]->group_type != 0)
{
if (lyr_a[lidx]->group_type == 3)
{
/* the </Layer group> marker layers are used to
assemble the layer structure in a single pass */
layer_id = gimp_layer_group_new (image_id);
}
else /* group-type == 1 || group_type == 2 */
{
layer_id = g_array_index (parent_group_stack, gint32,
parent_group_stack->len-1);
/* 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);
}
}
/* Empty layer */
if (lyr_a[lidx]->bottom - lyr_a[lidx]->top == 0
@@ -1228,7 +1261,7 @@ add_layers (const gint32 image_id,
g_free (rle_pack_len);
break;
case PSD_COMP_ZIP: /* ? */
case PSD_COMP_ZIP: /* ? */
case PSD_COMP_ZIP_PRED:
default:
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
@@ -1292,20 +1325,15 @@ add_layers (const gint32 image_id,
else
{
IFDBG(2) g_debug ("End group layer id %d.", layer_id);
drawable = gimp_drawable_get (layer_id);
layer_mode = psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode);
gimp_layer_set_mode (layer_id, layer_mode);
gimp_layer_set_opacity (layer_id,
lyr_a[lidx]->opacity * 100 / 255);
gimp_item_set_name (drawable->drawable_id, lyr_a[lidx]->name);
gimp_item_set_name (layer_id, lyr_a[lidx]->name);
g_free (lyr_a[lidx]->name);
gimp_item_set_visible (drawable->drawable_id,
lyr_a[lidx]->layer_flags.visible);
gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
if (lyr_a[lidx]->id)
gimp_item_set_tattoo (drawable->drawable_id,
lyr_a[lidx]->id);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
}
}
else if (empty)
@@ -1317,15 +1345,12 @@ add_layers (const gint32 image_id,
image_type, 0, GIMP_NORMAL_MODE);
g_free (lyr_a[lidx]->name);
gimp_image_insert_layer (image_id, layer_id, parent_group_id, -1);
drawable = gimp_drawable_get (layer_id);
gimp_drawable_fill (drawable->drawable_id, GIMP_TRANSPARENT_FILL);
gimp_item_set_visible (drawable->drawable_id, lyr_a[lidx]->layer_flags.visible);
gimp_drawable_fill (layer_id, GIMP_TRANSPARENT_FILL);
gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
if (lyr_a[lidx]->id)
gimp_item_set_tattoo (drawable->drawable_id, lyr_a[lidx]->id);
gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
if (lyr_a[lidx]->layer_flags.irrelevant)
gimp_item_set_visible (drawable->drawable_id, FALSE);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
gimp_item_set_visible (layer_id, FALSE);
}
else
{
@@ -1338,12 +1363,16 @@ add_layers (const gint32 image_id,
image_type = get_gimp_image_type (img_a->base_type, alpha);
IFDBG(3) g_debug ("Layer type %d", image_type);
layer_size = l_w * l_h;
pixels = g_malloc (layer_size * layer_channels);
bps = img_a->bps / 8;
if (bps == 0)
bps++;
pixels = g_malloc (layer_size * layer_channels * bps);
for (cidx = 0; cidx < layer_channels; ++cidx)
{
IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]);
for (i = 0; i < layer_size; ++i)
pixels[(i * layer_channels) + cidx] = lyr_chn[channel_idx[cidx]]->data[i];
memcpy (&pixels[((i * layer_channels) + cidx) * bps],
&lyr_chn[channel_idx[cidx]]->data[i * bps], bps);
g_free (lyr_chn[channel_idx[cidx]]->data);
}
@@ -1356,16 +1385,13 @@ add_layers (const gint32 image_id,
gimp_image_insert_layer (image_id, layer_id, parent_group_id, -1);
gimp_layer_set_offsets (layer_id, l_x, l_y);
gimp_layer_set_lock_alpha (layer_id, lyr_a[lidx]->layer_flags.trans_prot);
drawable = gimp_drawable_get (layer_id);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
drawable->width, drawable->height, TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, pixels,
0, 0, drawable->width, drawable->height);
gimp_item_set_visible (drawable->drawable_id, lyr_a[lidx]->layer_flags.visible);
buffer = gimp_drawable_get_buffer (layer_id);
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)),
0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
if (lyr_a[lidx]->id)
gimp_item_set_tattoo (drawable->drawable_id, lyr_a[lidx]->id);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
g_object_unref (buffer);
g_free (pixels);
}
@@ -1463,12 +1489,10 @@ add_layers (const gint32 image_id,
IFDBG(3) g_debug ("New layer mask %d", mask_id);
gimp_layer_add_mask (layer_id, mask_id);
drawable = gimp_drawable_get (mask_id);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0 , 0,
drawable->width, drawable->height, TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, pixels, lm_x, lm_y, lm_w, lm_h);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
buffer = gimp_drawable_get_buffer (mask_id);
gegl_buffer_set (buffer, GEGL_RECTANGLE (lm_x, lm_y, lm_w, lm_h), 0,
get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
g_object_unref (buffer);
gimp_layer_set_apply_mask (layer_id,
! lyr_a[lidx]->layer_mask.mask_flags.disabled);
g_free (pixels);
@@ -1500,6 +1524,7 @@ add_merged_image (const gint32 image_id,
guint16 base_channels;
guint16 extra_channels;
guint16 total_channels;
guint16 bps;
guint16 *rle_pack_len[MAX_CHANNELS];
guint32 alpha_id;
gint32 layer_size;
@@ -1514,13 +1539,15 @@ add_merged_image (const gint32 image_id,
gint offset;
gint i;
gboolean alpha_visible;
GimpDrawable *drawable;
GimpPixelRgn pixel_rgn;
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->color_mode == PSD_BITMAP ||
img_a->color_mode == PSD_GRAYSCALE ||
@@ -1626,12 +1653,13 @@ add_merged_image (const gint32 image_id,
image_type = get_gimp_image_type (img_a->base_type, img_a->transparency);
layer_size = img_a->columns * img_a->rows;
pixels = g_malloc (layer_size * base_channels);
pixels = g_malloc (layer_size * base_channels * bps);
for (cidx = 0; cidx < base_channels; ++cidx)
{
for (i = 0; i < layer_size; ++i)
{
pixels[(i * base_channels) + cidx] = chn_a[cidx].data[i];
memcpy (&pixels[((i * base_channels) + cidx) * bps],
&chn_a[cidx].data[i * bps], bps);
}
g_free (chn_a[cidx].data);
}
@@ -1643,13 +1671,10 @@ add_merged_image (const gint32 image_id,
image_type,
100, GIMP_NORMAL_MODE);
gimp_image_insert_layer (image_id, layer_id, -1, 0);
drawable = gimp_drawable_get (layer_id);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
drawable->width, drawable->height, TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, pixels,
0, 0, drawable->width, drawable->height);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
buffer = gimp_drawable_get_buffer (layer_id);
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)),
0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
g_object_unref (buffer);
g_free (pixels);
}
else
@@ -1734,18 +1759,14 @@ add_merged_image (const gint32 image_id,
alpha_opacity, &alpha_rgb);
gimp_image_insert_channel (image_id, channel_id, -1, 0);
g_free (alpha_name);
drawable = gimp_drawable_get (channel_id);
buffer = gimp_drawable_get_buffer (channel_id);
if (alpha_id)
gimp_item_set_tattoo (drawable->drawable_id, alpha_id);
gimp_item_set_visible (drawable->drawable_id, alpha_visible);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
drawable->width, drawable->height,
TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, pixels,
0, 0, drawable->width,
drawable->height);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
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_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
g_object_unref (buffer);
g_free (chn_a[cidx].data);
}
@@ -1928,20 +1949,21 @@ read_channel_data (PSDchannel *channel,
/* Convert channel data to GIMP format */
switch (bps)
{
case 32:
case 16:
channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
convert_16_bit (raw_data, channel->data, (channel->rows * channel->columns) << 1);
break;
case 8:
channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
memcpy (channel->data, raw_data, (channel->rows * channel->columns));
channel->data = (gchar *) g_malloc (channel->rows * channel->columns * bps / 8 );
memcpy (channel->data, raw_data, (channel->rows * channel->columns * bps / 8));
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);
@@ -1949,27 +1971,6 @@ read_channel_data (PSDchannel *channel,
return 1;
}
static void
convert_16_bit (const gchar *src,
gchar *dst,
guint32 len)
{
/* Convert 16 bit to 8 bit dropping low byte
*/
gint i;
IFDBG(3) g_debug ("Start 16 bit conversion");
for (i = 0; i < len >> 1; ++i)
{
*dst = *src;
dst++;
src += 2;
}
IFDBG(3) g_debug ("End 16 bit conversion");
}
static void
convert_1_bit (const gchar *src,
gchar *dst,
@@ -2002,3 +2003,108 @@ convert_1_bit (const gchar *src,
}
IFDBG(3) g_debug ("End 1 bit conversion");
}
static const Babl*
get_pixel_format (PSDimage *img_a)
{
const Babl *format;
switch (get_gimp_image_type (img_a->base_type, img_a->transparency))
{
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 ("YA u32");
break;
case 16:
format = babl_format ("YA u16");
break;
case 8:
case 1:
format = babl_format ("YA u8");
break;
default:
return NULL;
break;
}
break;
case GIMP_RGB_IMAGE:
case GIMP_INDEXED_IMAGE:
switch (img_a->bps)
{
case 32:
format = babl_format ("RGB u32");
break;
case 16:
format = babl_format ("RGB u16");
break;
case 8:
case 1:
format = babl_format ("RGB u8");
break;
default:
return NULL;
break;
}
break;
case GIMP_RGBA_IMAGE:
case GIMP_INDEXEDA_IMAGE:
switch (img_a->bps)
{
case 32:
format = babl_format ("RGBA u32");
break;
case 16:
format = babl_format ("RGBA u16");
break;
case 8:
case 1:
format = babl_format ("RGBA u8");
break;
default:
return NULL;
break;
}
break;
default:
return NULL;
break;
}
return format;
}

View File

@@ -86,12 +86,11 @@
#define DEBUG FALSE
/* 1: Normal debuggin, 2: Deep debuggin */
#define DEBUG_LEVEL 1
#define DEBUG_LEVEL 2
#define IFDBG if (DEBUG)
#define IF_DEEP_DBG if (DEBUG && DEBUG_LEVEL == 2)
#define PSD_UNIT_INCH 1
#define PSD_UNIT_CM 2
@@ -101,7 +100,6 @@
/* Local types etc
*/
typedef struct PsdLayerDimension
{
gint left;
@@ -110,7 +108,6 @@ typedef struct PsdLayerDimension
gint32 height;
} PSD_Layer_Dimension;
typedef struct PsdImageData
{
gboolean compression;
@@ -134,64 +131,80 @@ typedef struct PsdImageData
static PSD_Image_Data PSDImageData;
/* Declare some local functions.
*/
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
static void query (void);
static void psd_lmode_layer (gint32 idLayer,
gchar *psdMode);
static void reshuffle_cmap_write (guchar *mapGimp);
static void save_header (FILE *fd,
gint32 image_id);
static void save_color_mode_data (FILE *fd,
gint32 image_id);
static void save_resources (FILE *fd,
gint32 image_id);
static void save_layer_and_mask (FILE *fd,
gint32 image_id);
static void save_data (FILE *fd,
gint32 image_id);
static gint save_image (const gchar *filename,
gint32 image_id,
GError **error);
static void xfwrite (FILE *fd,
gconstpointer buf,
glong len,
const gchar *why);
static void write_pascalstring (FILE *fd,
const gchar *val,
gint padding,
const gchar *why);
static void write_string (FILE *fd,
const gchar *val,
const gchar *why);
static void write_gchar (FILE *fd,
guchar val,
const gchar *why);
static void write_gint16 (FILE *fd,
gint16 val,
const gchar *why);
static void write_gint32 (FILE *fd,
gint32 val,
const gchar *why);
static void write_datablock_luni (FILE *fd,
const gchar *val,
const gchar *why);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
static void write_pixel_data (FILE *fd,
gint32 drawableID,
glong *ChanLenPosition,
gint32 rowlenOffset);
static void psd_lmode_layer (gint32 idLayer,
gchar *psdMode);
static gint32 create_merged_image (gint32 imageID);
static void reshuffle_cmap_write (guchar *mapGimp);
static void save_header (FILE *fd,
gint32 image_id);
static void save_color_mode_data (FILE *fd,
gint32 image_id);
static void save_resources (FILE *fd,
gint32 image_id);
static void save_layer_and_mask (FILE *fd,
gint32 image_id);
static void save_data (FILE *fd,
gint32 image_id);
static gint save_image (const gchar *filename,
gint32 image_id,
GError **error);
static void xfwrite (FILE *fd,
gconstpointer buf,
glong len,
const gchar *why);
static void write_pascalstring (FILE *fd,
const gchar *val,
gint padding,
const gchar *why);
static void write_string (FILE *fd,
const gchar *val,
const gchar *why);
static void write_gchar (FILE *fd,
guchar val,
const gchar *why);
static void write_gint16 (FILE *fd,
gint16 val,
const gchar *why);
static void write_gint32 (FILE *fd,
gint32 val,
const gchar *why);
static void write_datablock_luni (FILE *fd,
const gchar *val,
const gchar *why);
static void write_pixel_data (FILE *fd,
gint32 drawableID,
glong *ChanLenPosition,
gint32 rowlenOffset);
static gint32 create_merged_image (gint32 imageID);
static const Babl* get_pixel_format (gint32 drawableID);
const GimpPlugInInfo PLUG_IN_INFO =
{
@@ -235,7 +248,6 @@ query (void)
gimp_register_save_handler (SAVE_PROC, "psd", "");
}
static void
run (const gchar *name,
gint nparams,
@@ -411,7 +423,6 @@ psd_lmode_layer (gint32 idLayer,
}
}
static void
write_string (FILE *fd,
const gchar *val,
@@ -421,7 +432,6 @@ write_string (FILE *fd,
xfwrite (fd, val, strlen (val), why);
}
static void
write_pascalstring (FILE *fd,
const gchar *val,
@@ -459,7 +469,6 @@ write_pascalstring (FILE *fd,
write_gchar (fd, 0, why);
}
static void
xfwrite (FILE *fd,
gconstpointer buf,
@@ -476,7 +485,6 @@ xfwrite (FILE *fd,
}
}
static void
write_gchar (FILE *fd,
guchar val,
@@ -497,7 +505,6 @@ write_gchar (FILE *fd,
fseek (fd, pos + 1, SEEK_SET);
}
static void
write_gint16 (FILE *fd,
gint16 val,
@@ -517,9 +524,6 @@ write_gint16 (FILE *fd,
}
}
static void
write_gint32 (FILE *fd,
gint32 val,
@@ -539,7 +543,6 @@ write_gint32 (FILE *fd,
}
}
static void
write_datablock_luni (FILE *fd,
const gchar *val,
@@ -581,7 +584,6 @@ write_datablock_luni (FILE *fd,
}
}
static gint32
pack_pb_line (guchar *start,
gint32 length,
@@ -666,7 +668,6 @@ gimpBaseTypeToPsdMode (GimpImageBaseType gimpBaseType)
}
}
static gint
nChansLayer (gint gimpBaseType,
gint hasAlpha,
@@ -691,7 +692,6 @@ nChansLayer (gint gimpBaseType,
}
}
static void
reshuffle_cmap_write (guchar *mapGimp)
{
@@ -715,7 +715,6 @@ reshuffle_cmap_write (guchar *mapGimp)
g_free (mapPSD);
}
static void
save_header (FILE *fd,
gint32 image_id)
@@ -736,13 +735,10 @@ save_header (FILE *fd,
"channels");
write_gint32 (fd, PSDImageData.image_height, "rows");
write_gint32 (fd, PSDImageData.image_width, "columns");
write_gint16 (fd, 8, "depth"); /* Apparently GIMP only supports 8 bit deep
PSD images. */
write_gint16 (fd, 8, "depth"); /* Saving can only be done in 8 bits at the moment. */
write_gint16 (fd, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode");
}
static void
save_color_mode_data (FILE *fd,
gint32 image_id)
@@ -800,8 +796,6 @@ save_color_mode_data (FILE *fd,
}
}
static void
save_resources (FILE *fd,
gint32 image_id)
@@ -1031,8 +1025,6 @@ save_resources (FILE *fd,
fseek (fd, eof_pos, SEEK_SET);
}
static int
get_compress_channel_data (guchar *channel_data,
gint32 channel_cols,
@@ -1062,7 +1054,6 @@ get_compress_channel_data (guchar *channel_data,
return len;
}
static void
save_layer_and_mask (FILE *fd,
gint32 image_id)
@@ -1284,32 +1275,26 @@ save_layer_and_mask (FILE *fd,
fseek (fd, eof_pos, SEEK_SET);
}
static void
write_pixel_data (FILE *fd,
gint32 drawableID,
glong *ChanLenPosition,
gint32 ltable_offset)
{
GimpPixelRgn region; /* Image region */
guchar *data; /* Temporary copy of pixel data */
gint32 tile_height = gimp_tile_height();
GimpDrawable *drawable = gimp_drawable_get (drawableID);
gint32 height = drawable->height;
gint32 width = drawable->width;
gint32 bytes = drawable->bpp;
gint32 colors = bytes; /* fixed up down below */
gint32 y;
gint32 len; /* Length of compressed data */
gint16 *LengthsTable; /* Lengths of every compressed row */
guchar *rledata; /* Compressed data from a region */
glong length_table_pos; /* position in file of the length table */
int i, j;
GeglBuffer *buffer = gimp_drawable_get_buffer (drawableID);
const Babl *format = get_pixel_format (drawableID);
gint32 tile_height = gimp_tile_height();
gint32 height = gegl_buffer_get_height (buffer);
gint32 width = gegl_buffer_get_width (buffer);
gint32 bytes = babl_format_get_bytes_per_pixel (format);
gint32 colors = bytes; /* fixed up down below */
gint32 y;
gint32 len; /* Length of compressed data */
gint16 *LengthsTable; /* Lengths of every compressed row */
guchar *rledata; /* Compressed data from a region */
guchar *data; /* Temporary copy of pixel data */
glong length_table_pos; /* position in file of the length table */
int i, j;
IFDBG printf (" Function: write_pixel_data, drw %d, lto %d\n",
drawableID, ltable_offset);
@@ -1318,17 +1303,12 @@ write_pixel_data (FILE *fd,
!gimp_drawable_is_indexed (drawableID))
colors -= 1;
gimp_tile_cache_ntiles (2* (drawable->width / gimp_tile_width () + 1));
LengthsTable = g_new (gint16, height);
rledata = g_new (guchar, (MIN (height, tile_height) *
(width + 10 + (width / 100))));
data = g_new (guchar, MIN(height, tile_height) * width * bytes);
gimp_pixel_rgn_init (&region, drawable, 0, 0,
width, height, FALSE, FALSE);
for (i = 0; i < bytes; i++)
{
gint chan;
@@ -1374,8 +1354,8 @@ write_pixel_data (FILE *fd,
for (y = 0; y < height; y += tile_height)
{
int tlen;
gimp_pixel_rgn_get_rect (&region, data, 0, y,
width, MIN(height - y, tile_height));
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, y, width, MIN (height - y, tile_height)),
0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
tlen = get_compress_channel_data (&data[chan],
width,
MIN(height - y, tile_height),
@@ -1409,12 +1389,9 @@ write_pixel_data (FILE *fd,
if (maskID != -1)
{
GimpDrawable *mdrawable = gimp_drawable_get (maskID);
GeglBuffer *mbuffer = gimp_drawable_get_buffer (maskID);
len = 0;
gimp_pixel_rgn_init (&region, mdrawable, 0, 0,
width, height, FALSE, FALSE);
if (ChanLenPosition)
{
write_gint16 (fd, 1, "Compression type (RLE)");
@@ -1442,8 +1419,8 @@ write_pixel_data (FILE *fd,
for (y = 0; y < height; y += tile_height)
{
int tlen;
gimp_pixel_rgn_get_rect (&region, data, 0, y,
width, MIN(height - y, tile_height));
gegl_buffer_get (mbuffer, GEGL_RECTANGLE (0, y, width, MIN (height - y, tile_height)),
0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
tlen = get_compress_channel_data (&data[0],
width,
MIN(height - y, tile_height),
@@ -1473,19 +1450,17 @@ write_pixel_data (FILE *fd,
fseek (fd, 0, SEEK_END);
IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", ftell(fd));
gimp_drawable_detach (mdrawable);
g_object_unref (mbuffer);
}
}
gimp_drawable_detach (drawable);
g_object_unref (buffer);
g_free (data);
g_free (rledata);
g_free (LengthsTable);
}
static void
save_data (FILE *fd,
gint32 image_id)
@@ -1541,50 +1516,50 @@ create_merged_image (gint32 image_id)
if (gimp_image_base_type (image_id) != GIMP_INDEXED)
{
GimpDrawable *drawable = gimp_drawable_get (projection);
GimpPixelRgn region;
gboolean transparency_found = FALSE;
gpointer pr;
GeglBuffer *buffer = gimp_drawable_get_buffer (projection);
const Babl *format = get_pixel_format (projection);
gboolean transparency_found = FALSE;
gint bpp = babl_format_get_bytes_per_pixel (format);
gint n_components = babl_format_get_n_components (format);
gint width = gegl_buffer_get_width (buffer);
gint height = gegl_buffer_get_height (buffer);
GeglBufferIterator *iter = gegl_buffer_iterator_new (buffer, GEGL_RECTANGLE (0, 0, width, height),
0, format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
gimp_pixel_rgn_init (&region, drawable,
0, 0, drawable->width, drawable->height,
TRUE, FALSE);
while (gegl_buffer_iterator_next (iter))
{
guchar *data = iter->data[0];
gint y;
for (pr = gimp_pixel_rgns_register (1, &region);
pr != NULL;
pr = gimp_pixel_rgns_process (pr))
{
guchar *data = region.data;
gint y;
for (y = 0; y < iter->roi->height; y++)
{
guchar *d = data;
gint x;
for (y = 0; y < region.h; y++)
{
guchar *d = data;
gint x;
for (x = 0; x < iter->roi->width; x++)
{
gint32 alpha = d[bpp - 1];
for (x = 0; x < region.w; x++)
{
guint32 alpha = d[region.bpp - 1];
if (alpha < 255)
{
gint i;
if (alpha < 255)
{
gint i;
transparency_found = TRUE;
transparency_found = TRUE;
/* blend against white, photoshop does this. */
for (i = 0; i < bpp - 1; i++)
d[i] = ((guint32) d[i] * alpha) / 255 + 255 - alpha;
}
/* blend against white, photoshop does this. */
for (i = 0; i < region.bpp - 1; i++)
d[i] = ((guint32) d[i] * alpha) / 255 + 255 - alpha;
}
}
d += region.bpp;
}
d += bpp;
}
data += region.rowstride;
}
}
data += n_components;
}
gimp_drawable_detach (drawable);
g_object_unref (buffer);
if (! transparency_found)
gimp_layer_flatten (projection);
@@ -1628,18 +1603,16 @@ get_image_data (FILE *fd,
PSDImageData.layersDim = g_new (PSD_Layer_Dimension, PSDImageData.nLayers);
}
static gint
save_image (const gchar *filename,
gint32 image_id,
GError **error)
{
FILE *fd;
gint32 *layers;
gint nlayers;
gint i;
GimpDrawable *drawable;
FILE *fd;
gint32 *layers;
gint nlayers;
gint i;
GeglBuffer *buffer;
IFDBG printf (" Function: save_image\n");
@@ -1658,8 +1631,8 @@ save_image (const gchar *filename,
layers = gimp_image_get_layers (image_id, &nlayers);
for (i = 0; i < nlayers; i++)
{
drawable = gimp_drawable_get (layers[i]);
if (drawable->width > 30000 || drawable->height > 30000)
buffer = gimp_drawable_get_buffer (layers[i]);
if (gegl_buffer_get_width (buffer) > 30000 || gegl_buffer_get_height (buffer) > 30000)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Unable to save '%s'. The PSD file format does not "
@@ -1669,6 +1642,7 @@ save_image (const gchar *filename,
g_free (layers);
return FALSE;
}
g_object_unref (buffer);
}
g_free (layers);
@@ -1713,3 +1687,36 @@ save_image (const gchar *filename,
fclose (fd);
return TRUE;
}
static const Babl*
get_pixel_format (gint32 drawableID)
{
const Babl *format;
switch (gimp_drawable_type (drawableID))
{
case GIMP_GRAY_IMAGE:
format = babl_format ("Y u8");
break;
case GIMP_GRAYA_IMAGE:
format = babl_format ("YA u8");
break;
case GIMP_RGB_IMAGE:
case GIMP_INDEXED_IMAGE:
format = babl_format ("RGB u8");
break;
case GIMP_RGBA_IMAGE:
case GIMP_INDEXEDA_IMAGE:
format = babl_format ("RGBA u8");
break;
default:
return NULL;
break;
}
return format;
}

View File

@@ -182,6 +182,7 @@ run (const gchar *name,
run_mode = param[0].data.d_int32;
INIT_I18N ();
gegl_init (NULL, NULL);
*nreturn_vals = 1;
*return_vals = values;

View File

@@ -31,7 +31,7 @@
/* Set to the level of debugging output you want, 0 for none.
* Setting higher than 2 will result in a very large amount of debug
* output being produced. */
#define PSD_DEBUG 0
#define PSD_DEBUG 3
#define IFDBG(level) if (PSD_DEBUG >= level)
/* Set to FALSE to suppress pop-up warnings about lossy file conversions */
@@ -83,6 +83,8 @@
#define PSD_LADJ_INVERT "nvrt" /* Adjustment layer - invert (PS4) */
#define PSD_LADJ_THRESHOLD "thrs" /* Adjustment layer - threshold (PS4) */
#define PSD_LADJ_POSTERIZE "post" /* Adjustment layer - posterize (PS4) */
#define PSD_LADJ_VIBRANCE "vibA" /* Adjustment layer - vibrance (PS10) */
#define PSD_LADJ_COLOR_LOOKUP "clrL" /* Adjustment layer - color lookup (PS13) */
/* Fill Layer IDs */
#define PSD_LFIL_SOLID "SoCo" /* Solid color sheet setting (PS6) */
@@ -117,12 +119,22 @@
/* Other */
#define PSD_LOTH_SECTION "lsct" /* Section divider setting - Layer groups (PS6) */
#define PSD_LOTH_PATTERN "Patt" /* Patterns (PS6) */
#define PSD_LOTH_PATTERN_2 "Pat2" /* Patterns 2nd key (PS6) */
#define PSD_LOTH_PATTERN_3 "Pat3" /* Patterns 3rd key (PS6) */
#define PSD_LOTH_GRADIENT "grdm" /* Gradient settings (PS6) */
#define PSD_LOTH_RESTRICT "brst" /* Channel blending restriction setting (PS6) */
#define PSD_LOTH_FOREIGN_FX "ffxi" /* Foreign effect ID (PS6) */
#define PSD_LOTH_PATT_DATA "shpa" /* Pattern data (PS6) */
#define PSD_LOTH_META_DATA "shmd" /* Meta data setting (PS6) */
#define PSD_LOTH_LAYER_DATA "layr" /* Layer data (PS6) */
#define PSD_LOTH_CONTENT_GEN "CgEd" /* Content generator extra data (PS12) */
#define PSD_LOTH_TEXT_ENGINE "Txt2" /* Text engine data (PS10) */
#define PSD_LOTH_PATH_NAME "pths" /* Unicode path name (PS13) */
#define PSD_LOTH_ANIMATION_FX "anFX" /* Animation effects (PS13) */
#define PSD_LOTH_FILTER_MASK "FMsk" /* Filter mask (PS10) */
#define PSD_LOTH_VECTOR_STROKE "vscg" /* Vector stroke data (PS13) */
#define PSD_LOTH_ALIGN_RENDER "sn2P" /* Aligned rendering flag (?) */
#define PSD_LOTH_USER_MASK "LMsk" /* User mask (?) */
/* Effects layer resource IDs */
#define PSD_LFX_COMMON "cmnS" /* Effects layer - common state (PS5) */
@@ -132,6 +144,24 @@
#define PSD_LFX_INNER_GLW "iglw" /* Effects layer - inner glow (PS5) */
#define PSD_LFX_BEVEL "bevl" /* Effects layer - bevel (PS5) */
/* Placed Layer */
#define PSD_LPL_PLACE_LAYER "plLd" /* Placed layer (?) */
#define PSD_LPL_PLACE_LAYER_NEW "SoLd" /* Placed layer (PS10) */
/* Linked Layer */
#define PSD_LLL_LINKED_LAYER "lnkD" /* Linked layer (?) */
#define PSD_LLL_LINKED_LAYER_2 "lnk2" /* Linked layer 2nd key */
#define PSD_LLL_LINKED_LAYER_3 "lnk3" /* Linked layer 3rd key */
/* Merged Transparency */
#define PSD_LMT_MERGE_TRANS "Mtrn" /* Merged transperency save flag (?) */
#define PSD_LMT_MERGE_TRANS_16 "Mt16" /* Merged transperency save flag 2 */
#define PSD_LMT_MERGE_TRANS_32 "Mt32" /* Merged transperency save flag 3 */
/* Filter Effects */
#define PSD_LFFX_FILTER_FX "FXid" /* Filter effects (?) */
#define PSD_LFFX_FILTER_FX_2 "FEid" /* Filter effects 2 */
/* PSD spec enums */
/* Image color modes */
@@ -169,7 +199,7 @@ typedef enum {
PSD_PS2_COLOR_TAB = 1003, /* 0x03eb - Obsolete - ps 2.0 indexed color table */
PSD_RESN_INFO = 1005, /* 0x03ed - ResolutionInfo structure */
PSD_ALPHA_NAMES = 1006, /* 0x03ee - Alpha channel names */
PSD_DISPLAY_INFO = 1007, /* 0x03ef - DisplayInfo structure */
PSD_DISPLAY_INFO = 1007, /* 0x03ef - Superceded by PSD_DISPLAY_INFO_NEW for ps CS3 and higher - DisplayInfo structure */
PSD_CAPTION = 1008, /* 0x03f0 - Optional - Caption string */
PSD_BORDER_INFO = 1009, /* 0x03f1 - Border info */
PSD_BACKGROUND_COL = 1010, /* 0x03f2 - Background color */
@@ -198,8 +228,8 @@ typedef enum {
PSD_COPYRIGHT_FLG = 1034, /* 0x040a - Copyright flag */
PSD_URL = 1035, /* 0x040b - URL string */
PSD_THUMB_RES2 = 1036, /* 0x040c - Thumbnail resource */
PSD_GLOBAL_ANGLE = 1037, /* 0x040d - Global angle */
PSD_COLOR_SAMPLER = 1038, /* 0x040e - Color samplers resource */
PSD_GLOBAL_ANGLE = 1037, /* 0x040d - Superceded by PSD_NEW_COLOR_SAMPLER for ps CS3 and higher - Global angle */
PSD_COLOR_SAMPLER = 1038, /* 0x040e - Superceded by PSD_NEW_COLOR_SAMPLER for ps CS3 and higher - Color samplers resource */
PSD_ICC_PROFILE = 1039, /* 0x040f - ICC Profile */
PSD_WATERMARK = 1040, /* 0x0410 - Watermark */
PSD_ICC_UNTAGGED = 1041, /* 0x0411 - Do not use ICC profile flag */
@@ -216,11 +246,40 @@ typedef enum {
PSD_ALPHA_ID = 1053, /* 0x041d - Alpha IDs */
PSD_URL_LIST_UNI = 1054, /* 0x041e - URL list - unicode */
PSD_VERSION_INFO = 1057, /* 0x0421 - Version info */
PSD_EXIF_DATA = 1058, /* 0x0422 - Exif data block */
PSD_EXIF_DATA = 1058, /* 0x0422 - Exif data block 1 */
PSD_EXIF_DATA_3 = 1059, /* 0X0423 - Exif data block 3 (?) */
PSD_XMP_DATA = 1060, /* 0x0424 - XMP data block */
PSD_CAPTION_DIGEST = 1061, /* 0x0425 - Caption digest */
PSD_PRINT_SCALE = 1062, /* 0x0426 - Print scale */
PSD_PIXEL_AR = 1064, /* 0x0428 - Pixel aspect ratio */
PSD_LAYER_COMPS = 1065, /* 0x0429 - Layer comps */
PSD_ALT_DUOTONE_COLOR = 1066, /* 0x042A - Alternative Duotone colors */
PSD_ALT_SPOT_COLOR = 1067, /* 0x042B - Alternative Spot colors */
PSD_LAYER_SELECT_ID = 1069, /* 0x042D - Layer selection ID */
PSD_HDR_TONING_INFO = 1070, /* 0x042E - HDR toning information */
PSD_PRINT_INFO_SCALE = 1071, /* 0x042F - Print scale */
PSD_LAYER_GROUP_E_ID = 1072, /* 0x0430 - Layer group(s) enabled ID */
PSD_COLOR_SAMPLER_NEW = 1073, /* 0x0431 - Color sampler resource for ps CS3 and higher PSD files */
PSD_MEASURE_SCALE = 1074, /* 0x0432 - Measurement scale */
PSD_TIMELINE_INFO = 1075, /* 0x0433 - Timeline information */
PSD_SHEET_DISCLOSE = 1076, /* 0x0434 - Sheet discloser */
PSD_DISPLAY_INFO_NEW = 1077, /* 0x0435 - DisplayInfo structure for ps CS3 and higher PSD files */
PSD_ONION_SKINS = 1078, /* 0x0436 - Onion skins */
PSD_COUNT_INFO = 1080, /* 0x0438 - Count information*/
PSD_PRINT_INFO = 1082, /* 0x043A - Print information added in ps CS5*/
PSD_PRINT_STYLE = 1083, /* 0x043B - Print style */
PSD_MAC_NSPRINTINFO = 1084, /* 0x043C - Mac NSPrintInfo*/
PSD_WIN_DEVMODE = 1085, /* 0x043D - Windows DEVMODE */
PSD_AUTO_SAVE_PATH = 1086, /* 0x043E - Auto save file path */
PSD_AUTO_SAVE_FORMAT = 1087, /* 0x043F - Auto save format */
PSD_PATH_INFO_FIRST = 2000, /* 0x07d0 - First path info block */
PSD_PATH_INFO_LAST = 2998, /* 0x0bb6 - Last path info block */
PSD_CLIPPING_PATH = 2999, /* 0x0bb7 - Name of clipping path */
PSD_PLUGIN_R_FIRST = 4000, /* 0x0FA0 - First plugin resource */
PSD_PLUGIN_R_LAST = 4999, /* 0x1387 - Last plugin resource */
PSD_IMAGEREADY_VARS = 7000, /* 0x1B58 - Imageready variables */
PSD_IMAGEREADY_DATA = 7001, /* 0x1B59 - Imageready data sets */
PSD_LIGHTROOM_WORK = 8000, /* 0x1F40 - Lightroom workflow */
PSD_PRINT_FLAGS_2 = 10000 /* 0x2710 - Print flags */
} PSDImageResID;
@@ -306,7 +365,7 @@ typedef struct
guint16 red;
guint16 green;
guint16 blue;
}CMRGBColor;
} CMRGBColor;
/* HSV Color Value
A color value expressed in the HSV color space is composed of hue,
@@ -321,7 +380,7 @@ typedef struct
guint16 hue;
guint16 saturation;
guint16 value;
}CMHSVColor;
} CMHSVColor;
/* CMYK Color Value
A color value expressed in the CMYK color space is composed of cyan, magenta,
@@ -336,7 +395,7 @@ typedef struct
guint16 magenta;
guint16 yellow;
guint16 black;
}CMCMYKColor;
} CMCMYKColor;
/* L*a*b* Color Value
The first three values in the color data are, respectively, the colors
@@ -363,17 +422,16 @@ typedef struct
} CMGrayColor ;
/* The color union is defined by the CMColor type definition.
*/
*/
typedef union
{
CMRGBColor rgb;
CMHSVColor hsv;
CMLabColor Lab;
CMCMYKColor cmyk;
CMGrayColor gray;
CMRGBColor rgb;
CMHSVColor hsv;
CMLabColor Lab;
CMCMYKColor cmyk;
CMGrayColor gray;
} CMColor;
/* Image resolution data */
typedef struct {
Fixed hRes; /* Horizontal resolution pixels/inch */
@@ -410,15 +468,24 @@ typedef struct {
gint16 planes; /* Number of planes (always 1) */
} ThumbnailInfo;
/* Channel display info data */
/* Channel display info data for Adobe Photoshop CS2 and lower */
typedef struct {
gint16 colorSpace; /* Color space from PSDColorSpace */
gint16 colorSpace; /* Color space from PSDColorSpace */
guint16 color[4]; /* 4 * 16 bit color components */
gint16 opacity; /* Opacity 0 to 100 */
gchar kind; /* Selected = 0, Protected = 1 */
gchar padding; /* Padding */
} DisplayInfo;
/* Channel display info data for Adobe Photoshop CS3 and higher to support floating point colors */
typedef struct {
gint16 colorSpace; /* Color space from PSDColorSpace */
guint16 color[4]; /* 4 * 16 bit color components */
gint16 opacity; /* Opacity 0 to 100 */
gchar kind; /* Selected = 0, Protected = 1 */
gchar mode; /* Alpha = 0, Inverted alpha = 1, Spot = 2 */
} DisplayInfoNew;
/* PSD Channel length info data structure */
typedef struct
{
@@ -444,6 +511,33 @@ typedef struct
gboolean invert; /* Invert mask on blending */
} MaskFlags;
/* PSD Slices */
typedef struct
{
gint32 id; /* ID */
gint32 groupid; /* Group ID */
gint32 origin; /* Origin */
gint32 associatedid; /* Associated Layer ID */
gchar *name; /* Name */
gint32 type; /* Type */
gint32 left; /* Position coordinates */
gint32 top;
gint32 right;
gint32 bottom;
gchar *url; /* URL */
gchar *target; /* Target */
gchar *message; /* Message */
gchar *alttag; /* Alt Tag */
gchar html; /* Boolean for if cell text is HTML */
gchar *celltext; /* Cell text */
gint32 horizontal; /* Horizontal alignment */
gint32 vertical; /* Vertical alignment */
gchar alpha; /* Alpha */
gchar red; /* Red */
gchar green; /* Green */
gchar blue; /* Blue */
} PSDSlice;
/* PSD Layer mask data (length 20) */
typedef struct
{
@@ -467,6 +561,18 @@ typedef struct
gint32 right; /* Layer right */
} LayerMaskExtra;
/* PSD text reading */
typedef struct
{
gdouble xx; /* Transform information */
gdouble xy;
gdouble yx;
gdouble yy;
gdouble tx;
gdouble ty;
gchar *info; /* Text information */
} PSDText;
/* PSD Layer data structure */
typedef struct
{
@@ -489,6 +595,7 @@ typedef struct
LayerMask layer_mask; /* Layer mask data */
LayerMaskExtra layer_mask_extra; /* Layer mask extra data */
LayerFlags layer_flags; /* Layer flags */
PSDText text; /* PSD text */
guint32 id; /* Layer ID (Tattoo) */
guchar group_type; /* 0 -> not a group; 1 -> open folder; 2 -> closed folder; 3 -> end of group */
} PSDlayer;
@@ -508,6 +615,7 @@ typedef struct
{
GimpRGB gimp_color; /* Gimp RGB color */
gint16 opacity; /* Opacity */
guchar ps_mode; /* PS mode flag */
guchar ps_kind; /* PS type flag */
gint16 ps_cspace; /* PS color space */
CMColor ps_color; /* PS color */
@@ -539,7 +647,7 @@ typedef struct
gboolean transparency; /* Image has merged transparency alpha channel */
guint32 rows; /* Number of rows: 1 - 30000 */
guint32 columns; /* Number of columns: 1 - 30000 */
guint16 bps; /* Bits per channel: 1, 8 or 16 */
guint16 bps; /* Bits per sample: 1, 8, 16, or 32 */
guint16 color_mode; /* Image color mode: {PSDColorMode} */
GimpImageBaseType base_type; /* Image base color mode: (GIMP) */
guint16 comp_mode; /* Merged image compression mode */