Aspose.PSD for .NET 19.9 - Release Notes

** 

Key Summary Category
PSDNET-160 Wrong layer name extracted Feature
PSDNET-175 Getting text properties from a different portion of text inside PSD TextLayer Feature
PSDNET-190 Support for Add layer group Feature
PSDNET-192 Support of Scale Property for Gradient Fill Layer Feature
PSDNET-162 Adjusting Brightness Enhancement
PSDNET-174 IndexOutOfRangeException on saving PSD image as JPEG Bug
PSDNET-180 Updating text layer text throws an exception Bug
PSDNET-182 Saving PSD image after RotateFlip operation produces a corrupted file which could not be open Bug

Public API Changes

Added APIs:

  • M:Aspose.PSD.FileFormats.Psd.Layers.LayerGroup.AddLayerGroup(System.String,System.Int32)
  • T:Aspose.PSD.FileFormats.Psd.Layers.Text.IText
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.Items
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.Text
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.ProducePortion
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.AddPortion(Aspose.PSD.FileFormats.Psd.Layers.Text.ITextPortion)
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.InsertPortion(Aspose.PSD.FileFormats.Psd.Layers.Text.ITextPortion,System.Int32)
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.RemovePortion(System.Int32)
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.IText.UpdateLayerData
  • T:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.Justification
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.FirstLineIndent
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.StartIndent
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.EndIndent
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.SpaceBefore
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.SpaceAfter
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.AutoHyphenate
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.HyphenatedWordSize
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.PreHyphen
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.PostHyphen
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.ConsecutiveHyphens
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.Zone
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.WordSpacing
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.LetterSpacing
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.GlyphSpacing
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.AutoLeading
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.LeadingType
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.Hanging
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.Burasagari
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.KinsokuOrder
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.EveryLineComposer
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.Apply(Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph)
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph.IsEqual(Aspose.PSD.FileFormats.Psd.Layers.Text.ITextParagraph)
  • T:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextPortion
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextPortion.Text
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextPortion.Style
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextPortion.Paragraph
  • T:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.FontSize
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.AutoLeading
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.Leading
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.Tracking
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.Kerning
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.FillColor
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.StrokeColor
  • P:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.HindiNumbers
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.Apply(Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle)
  • M:Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle.IsEqual(Aspose.PSD.FileFormats.Psd.Layers.Text.ITextStyle)
  • P:Aspose.PSD.FileFormats.Psd.Layers.TextLayer.TextData
  • P:Aspose.PSD.FileFormats.Psd.Layers.FillSettings.IGradientFillSettings.Scale
  • P:Aspose.PSD.FileFormats.Psd.Layers.LayerResources.GdFlResource.Scale
  • P:Aspose.PSD.FileFormats.Psd.Layers.FillSettings.GradientFillSettings.Scale

Removed APIs:

  • None

Usage examples:

PSDNET-160. Wrong layer name extracted

To display the layer name properly use the DisplayName property. A setter is now added for this property and the property can be modified. When Photoshop is saving layer name using the Name property the Korean characters are stored as byte 63'?' in ASCII.  Use the DisplayName property because the Name property does not support Korean characters.

             // make changes in layer names and save it

            using (var image = (PsdImage)Image.Load("layers with names.psd"))

            {

                for (int i = 0; i < image.Layers.Length; i++)

                {

                    var layer = image.Layers[i];

                    // set new value into DisplayName property

                    layer.DisplayName += "_changed";

                }

                image.Save("output.psd");

            }

PSDNET-175. Getting text properties from a different portion of text inside PSD TextLayer

            const double Tolerance = 0.0001;

            var filePath = "ThreeColorsParagraphs.psd";

            var outputPath = "ThreeColorsParagraph_out.psd";

            using (var im = (PsdImage)Image.Load(filePath))

            {

                for (int i = 0; i < im.Layers.Length; i++)

                {

                    var layer = im.Layers[i] as TextLayer;

                    if (layer != null)

                    {

                        var portions = layer.TextData.Items;

                        if (portions.Length != 4)

                        {

                            throw new Exception();

                        }

                        // Checking text of every portion

                        if (portions[0].Text != "Old " ||

                            portions[1].Text != "color" ||

                            portions[2].Text != " text\r" ||

                            portions[3].Text != "Second paragraph\r")

                        {

                            throw new Exception();

                        }

                        // Checking paragraphs data

                        // Paragraphs have different justification

                        if (

                            portions[0].Paragraph.Justification != 0 ||

                            portions[1].Paragraph.Justification != 0 ||

                            portions[2].Paragraph.Justification != 0 ||

                            portions[3].Paragraph.Justification != 2)

                        {

                            throw new Exception();

                        }

                        // All other properties of first and second paragraph are equal

                        for (int j = 0; j < portions.Length; j++)

                        {

                            var paragraph = portions[j].Paragraph;

                            if (Math.Abs(paragraph.AutoLeading - 1.2) > Tolerance ||

                                paragraph.AutoHyphenate != false ||

                                paragraph.Burasagari != false ||

                                paragraph.ConsecutiveHyphens != 8 ||

                                Math.Abs(paragraph.StartIndent) > Tolerance ||

                                Math.Abs(paragraph.EndIndent) > Tolerance ||

                                paragraph.EveryLineComposer != false ||

                                Math.Abs(paragraph.FirstLineIndent) > Tolerance ||

                                paragraph.GlyphSpacing.Length != 3 ||

                                Math.Abs(paragraph.GlyphSpacing[0] - 1) > Tolerance ||

                                Math.Abs(paragraph.GlyphSpacing[1] - 1) > Tolerance ||

                                Math.Abs(paragraph.GlyphSpacing[2] - 1) > Tolerance ||

                                paragraph.Hanging != false ||

                                paragraph.HyphenatedWordSize != 6 ||

                                paragraph.KinsokuOrder != 0 ||

                                paragraph.LetterSpacing.Length != 3 ||

                                Math.Abs(paragraph.LetterSpacing[0]) > Tolerance ||

                                Math.Abs(paragraph.LetterSpacing[1]) > Tolerance ||

                                Math.Abs(paragraph.LetterSpacing[2]) > Tolerance ||

                                paragraph.LeadingType != LeadingMode.Auto ||

                                paragraph.PreHyphen != 2 ||

                                paragraph.PostHyphen != 2 ||

                                Math.Abs(paragraph.SpaceBefore) > Tolerance ||

                                Math.Abs(paragraph.SpaceAfter) > Tolerance ||

                                paragraph.WordSpacing.Length != 3 ||

                                Math.Abs(paragraph.WordSpacing[0] - 0.8) > Tolerance ||

                                Math.Abs(paragraph.WordSpacing[1] - 1.0) > Tolerance ||

                                Math.Abs(paragraph.WordSpacing[2] - 1.33) > Tolerance ||

                                Math.Abs(paragraph.Zone - 36.0) > Tolerance)

                            {

                                throw new Exception();

                            }

                        }

                        // Checking style data

                        // Styles have different colors and font size

                        if (Math.Abs(portions[0].Style.FontSize - 12) > Tolerance ||

                            Math.Abs(portions[1].Style.FontSize - 12) > Tolerance ||

                            Math.Abs(portions[2].Style.FontSize - 12) > Tolerance ||

                            Math.Abs(portions[3].Style.FontSize - 10) > Tolerance)

                        {

                            throw new Exception();

                        }

                        if (portions[0].Style.FillColor != Color.FromArgb(255, 145, 0, 0) ||

                            portions[1].Style.FillColor != Color.FromArgb(255, 201, 128, 2) ||

                            portions[2].Style.FillColor != Color.FromArgb(255, 18, 143, 4) ||

                            portions[3].Style.FillColor != Color.FromArgb(255, 145, 42, 100))

                        {

                            throw new Exception();

                        }

                        for (int j = 0; j < portions.Length; j++)

                        {

                            var style = portions[j].Style;

                            if (style.AutoLeading != false ||

                                style.HindiNumbers != false ||

                                style.Kerning != 0 ||

                                style.Leading != 0 ||

                                style.StrokeColor != Color.FromArgb(255, 175, 90, 163) ||

                                style.Tracking != 50)

                            {

                                throw new Exception();

                            }

                        }

                        // Example of text editing

                        portions[0].Text = "Hello ";

                        portions[1].Text = "World";

                        // Example of text portions removing

                        layer.TextData.RemovePortion(3);

                        layer.TextData.RemovePortion(2);

                        // Example of adding new text portion

                        var createdPortion = layer.TextData.ProducePortion();

                        createdPortion.Text = "!!!\r";

                        layer.TextData.AddPortion(createdPortion);

                        portions = layer.TextData.Items;

                        // Example of paragraph and style editing for portions

                        // Set right justification

                        portions[0].Paragraph.Justification = 1;

                        portions[1].Paragraph.Justification = 1;

                        portions[2].Paragraph.Justification = 1;

                        // Different colors for each style. The will be changed, but rendering is not fully supported

                        portions[0].Style.FillColor = Color.Aquamarine;

                        portions[1].Style.FillColor = Color.Violet;

                        portions[2].Style.FillColor = Color.LightBlue;

                        // Different font. The will be changed, but rendering is not fully supported

                        portions[0].Style.FontSize = 6;

                        portions[1].Style.FontSize = 8;

                        portions[2].Style.FontSize = 10;

                        layer.TextData.UpdateLayerData();

                        im.Save(outputPath, new PsdOptions(im));

                        break;

                    }

                }

            }

PSDNET-190. Support for Add layer group

             // -Group 1

            // --Layer 1

            // --Group 2

            // ---Layer 2

            // ---Layer 3

            // --Layer 4

            string dataDir = "psdnet190_test.psd";

            var createOptions = new PsdOptions();

            createOptions.Source = new FileCreateSource(dataDir, false);

            createOptions.Palette = new PsdColorPalette(new Color[] { Color.Green });

            using (var psdImage = (PsdImage)Image.Create(createOptions, 500, 500))

            {

                LayerGroup group1 = psdImage.AddLayerGroup("Group 1", 0, true);

                Layer layer1 = new Layer(psdImage);

                layer1.Name = "Layer 1";

                group1.AddLayer(layer1);

                LayerGroup group2 = group1.AddLayerGroup("Group 2", 1);

                Layer layer2 = new Layer(psdImage);

                layer2.Name = "Layer 2";

                group2.AddLayer(layer2);

                Layer layer3 = new Layer(psdImage);

                layer3.Name = "Layer 3";

                group2.AddLayer(layer3);

                Layer layer4 = new Layer(psdImage);

                layer4.Name = "Layer 4";

                group1.AddLayer(layer4);

                psdImage.Save();

            }

PSDNET-192. Support of Scale Property for Gradient Fill Layer

            using (var image = (PsdImage)Image.Load("FillLayerGradient.psd"))

            {

                // getting a fill layer

                FillLayer fillLayer = null;

                foreach (var layer in image.Layers)

                {

                    fillLayer = layer as FillLayer;

                    if (fillLayer != null)

                    {

                        break;

                    }

                }

                var settings = fillLayer.FillSettings as IGradientFillSettings;

                // update scale value

                settings.Scale = 200;

                fillLayer.Update(); // Updates pixels data

                image.Save("scaledImage.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });

            }

PSDNET-174. IndexOutOfRangeException on saving PSD image as JPEG

         using (var image = Aspose.PSD.Image.Load("SamplePSD.psd"))

        {

            image.Save("sampleJPG.jpg", new JpegOptions());

        }

PSDNET-180. Updating text layer text throws an exception

           // Updating text layer text throws exception

            string filePath = "FlipVertical.psd";

            string outputPath = "FlipVertical_changed.psd";

            var newText = "Test";

            using (var image = Image.Load(filePath))

            {

                var psdImage = image as PsdImage;

                if (image == null)

                {

                    return;

                }

                var layers = psdImage.Layers;

                for (var index = layers.Length - 1; index >= 0; index--)

                {

                    var layer = layers[index] as TextLayer;

                    if (layer == null)

                    {

                        continue;

                    }

                    layer.UpdateText(newText);

                }

                var imageOptions = new PsdOptions(psdImage);

                psdImage.Save(outputPath, imageOptions);

            }

PSDNET-182. Saving PSD image after RotateFlip operation produces a corrupted file which could not be open

 string sourceFileName = "1.psd";

RotateFlipType flipType = RotateFlipType.Rotate270FlipXY;

string outFileNamePsd = "RotateFlipTest2617.psd";

using (PsdImage image = (PsdImage)Image.Load(sourceFileName))

{

    image.RotateFlip(flipType);

    image.Save(outFileNamePsd);

}

// Should be executed without exceptions

using (PsdImage image = (PsdImage)Image.Load(outFileNamePsd)) 

{

    // Do nothing

}