Psd文件解析出来的图层对象Layer,无法序列化

场景:首次解析出psd源文件,得到psdImage对象,layer对象列表,将其序列化字节码,存储至数据库中。而后所有的操作,都是基于单图层对象,所以希望从数据库中读取出layer的序列化字节码能够将其反序列化为源layer类对象,进行操作。要不然的话,每次都得解析,遍历图层列表,定位到某一层进行操作,影响性能和效率。如果对象支持序列化,和反序列化源对象还原的话,我就可以将其存储数据库中了。现该api不支持此场景,只能操作一次,解析加载一次遍历操作。比如,多人操作同一psd文件,你就必须加载解析多次,如果对象支持序列化存储,只需解析一次存储对象序列化字节码,后面所有的操作都只需读取字节码反序列化源对象,进行其操作即可,然后再组装还原反序列化为psdImage源对象即可。

获取 Outlook for iOS

@xielong
目前,API中不提供所请求的支持。 我已经在我们的问题跟踪系统中创建了一个ID为PSDNET-850的票证,以进一步调查提供请求的支持的可能性。 该线程已与问题联系在一起,因此一旦支持可用,您可能会收到通知。

收到,非常感谢

获取 Outlook for iOS

@xielong

随时欢迎你

您好,请问下问题跟踪系统中的,问题单,大概何时可以得到解决?因我们这边产品比较紧急,所以想确认下具体的时间,一切都得以解决的话,我们就要开始走付费购买以及付费技术支持等商务合同事宜了。

@jsczxielong

Now we support serialization only simple data of layer, so serialization/deserialization can work only for simple layers(without effects or any other dependencies from image global resources).

The following code example will make bytes from layer and move it to other PsdImage:

            string src1 = "testFile1.psd";
            string src2 = "testFile2.psd";
            string output2 = "out_testFile2.psd";

            using (var image1 = (PsdImage)Image.Load(src1))
            {
                byte[] layerBytes;
                using (MemoryStream layerMem = new MemoryStream())
                {
                    image1.Layers[1].Save(layerMem, new PsdOptions());
                    layerBytes = layerMem.ToArray();
                }

                using (var image2 = (PsdImage)Image.Load(src2))
                {
                    using (MemoryStream layerMem = new MemoryStream(layerBytes))
                    {
                        Layer copiedLayer = new Layer(layerMem);
                        image2.AddLayer(copiedLayer);
                    }

                    image2.Save(output2);
                }
            }

image.png (24.3 KB)
实际没看到有此方法

请问是,最aspose-psd.jar(20.9)这版本?

groupLayer序列化还是有问题,请问下,此问题可以解决修复?
image.png (9.8 KB)

@jsczxielong

请共享有效的示例代码和重现此问题的实际源文件。 我们将尽力对此进行调查,以进一步为您提供帮助。

您好,单图层也可实际序列化、反序列化。现最大的问题,就是,是否有支持:PsdImage image =(PsdImage) Image.load(sourceFileName,loadOptions);对整个PsdImage序列化、反序列化?我们的场景,就是希望,只load一次源psd文件,而后序列化成byte[]字节持久化存储,下次再进行图层编辑时,只需反序列化原对象即可。因为现最大的性能消耗,主要就是loadPsd源文件,非常吃性能。

如若官方团队,loadpsd到输出png整个过程,时间性能上可以缩小到3~5秒内,那实际应用倒也是可以接受。但实际的运行效果下来,就最标准的loadpsd到存储 png图片就需要将近10秒左右。
1.代码:
public static void main(String[] args) throws FileNotFoundException
{

    License license = new License();
    String licFileDir = "E:\\mysite\\openproj\\Aspose.PSD-for-Java\\Examples\\src\\main\\resources\\Lic\\Aspose.Total.Product.Family.lic";
    license.setLicense(licFileDir);

    long startTime = System.currentTimeMillis();    //获取开始时间

    String dataDir = "E:\\mysite\\openproj\\Aspose.PSD-for-Java\\Examples\\src\\main\\resources\\PSD\\";
    Cache.setCacheFolder(dataDir);
    // Set cache on disk.
    Cache.setCacheType(CacheType.CacheInMemoryOnly);
    // The default cache max value is 0, which means that there is no upper limit
    Cache.setMaxMemoryForCache(1073741824); // 1 gigabyte
    // We do not recommend that you change the following property because it may greatly affect performance
    Cache.setExactReallocateOnly(false);

    String sourceFileName = dataDir+ "nvwang.psd";
    String exportPath = dataDir+ "nvwangBakNew1.png";
    PsdLoadOptions loadOptions = new PsdLoadOptions();
    PsdImage image =(PsdImage) Image.load(sourceFileName,loadOptions);
    PngOptions options = new PngOptions();
    options.setCompressionLevel(Compression.NONE.getValue());
    options.setColorType(PngColorType.TruecolorWithAlpha);
    image.save(exportPath,options);
    long endTime = System.currentTimeMillis();    //获取结束时间

    System.out.println("程序运行时间:" + (endTime - startTime)/1000 + "s");    //输出程序运行时间
}

2.实际运行效果:
image.png (25.7 KB)

3.源文件:
nvwangcopy.zip (118.8 KB)

所以,我们就想到了,是否有支持PsdImage整个对象的序列化、反充列化,以及Layer图层的序列化、反序列化。从而达到间接提升性能。

能否请您解释一下。 该API支持从MemoryStream加载PSD和将PSD保存到MemoryStream。 如果要将PSD保留为字节数组,可以将PSD保存为流,然后从Stream中将其另存为字节数组到持久性存储中。 同样,如果要加载字节数组,可以将字节数组转换为MemoryStream,然后加载它。 如果这不是您想要的,请解释一下您希望Aspose.PSD为您提供的内容。

恩,可否提供示例代码。谢谢

获取 Outlook for iOS

你好,实际我们这边验证了。可以序列化,但是无法反序列化为原对象。
1.源代码:
public static void main(String[] args) throws FileNotFoundException {
License license = new License();
String licFileDir = “E:\mysite\openproj\Aspose.PSD-for-Java\Examples\src\main\resources\Lic\Aspose.Total.Product.Family.lic”;
license.setLicense(licFileDir);

    String dataDir = "E:\\mysite\\openproj\\Aspose.PSD-for-Java\\Examples\\src\\main\\resources\\PSD\\";

    String sourceFileName = dataDir + "6d006ea3baa81d8cba9f25ce56a2c970.psd";
    String exportPath = dataDir + "nvwangNewITextPortion.png";

    PsdLoadOptions loadOptions = new PsdLoadOptions();

    PsdImage image1 =(PsdImage) Image.load(sourceFileName,loadOptions);

    byte[] layerBytes;
    MemoryStream layerMem = new MemoryStream();
    OutputStream dstStream = layerMem.toOutputStream();
    image1.save(dstStream, new PsdOptions());
    layerBytes = layerMem.toArray();
    //layerMem = new MemoryStream(layerBytes);
    InputStream inputStream = new ByteArrayInputStream(layerBytes);
    PsdImage image = new PsdImage(inputStream);

    for(int i=0; i < image.getLayers().length; i++ )
    {
        Layer layer = (Layer) image.getLayers()[i];
        System.out.println(i + "DisplayName:" + layer.getDisplayName() + "name:" + layer.getName());

        if (i == 10 && image.getLayers()[i] instanceof TextLayer)
        {
            TextLayer textLayer = (TextLayer)image.getLayers()[i];
            //IText textData = textLayer.getTextData();
            //System.out.println("textData producePortion text:"+textData.producePortion().getText());
            //方案一.直接获取producePortion对象修改文本:报错Line break '\r' character can be only in the end of text
            //textData.producePortion().setText("靠你就是我的你的");
            //方案二.创建新ITextPortion
            //ITextStyle defaultStyle = textData.producePortion().getStyle();
            //defaultStyle.setFillColor(textLayer.getTextColor());
            //defaultStyle.setFontSize(textLayer.getFont().getSize());
            //ITextParagraph defaultParagraph = textData.producePortion().getParagraph();

            /*textData.getItems()[1].getStyle().setStrikethrough(true);
            ITextPortion[] newTextPortions = textData.producePortions(new String[] {
                            "E=mc",  "2\r",  "Bold",  "Italic\r",  "Lowercasetext" },
                    textData.producePortion().getStyle(), textData.producePortion().getParagraph());
            newTextPortions[0].getStyle().setUnderline(true); // edit text style of "E=mc"
            newTextPortions[1].getStyle().setFontBaseline(FontBaseline.Superscript); // edit text style of "2\r"
            newTextPortions[2].getStyle().setFauxBold(true); // edit text style of "Bold"
            newTextPortions[3].getStyle().setFauxItalic(true); // edit text style of "Italic\r"
            newTextPortions[3].getStyle().setBaselineShift(-25); // edit text style of "Italic\r"
            newTextPortions[4].getStyle().setFontCaps(FontCaps.SmallCaps); // edit text style of "Lowercasetext"
            for (ITextPortion newTextPortion : newTextPortions)
            {
                textData.addPortion(newTextPortion);
            }
            textData.updateLayerData();*/

            Point leftTopCoordinate = new Point();
            leftTopCoordinate.setX(textLayer.getLeft());
            leftTopCoordinate.setY(textLayer.getTop());
            textLayer.updateText("我的你的", leftTopCoordinate, textLayer.getFont().getSize(), textLayer.getTextColor());

        }
    }
    PngOptions options = new PngOptions();
    options.setColorType(PngColorType.TruecolorWithAlpha);

    image.save(exportPath,options);
}

2.运行结果:
nvwangNewITextPortion.jpg (1.5 MB)

3.实际期望(源psd文本层文字有替换):
nvwangNewITextPortion1.jpg (1.5 MB)

4.psd源文件"
nvwangJy.zip (2.6 MB)

@jsczxielong

对不起,我没有明白你的意思吗? 您能解释一下它的意思吗?可以序列化但不能反序列化。

0.场景需求:PsdImage对象-》((PsdImage) Image.load(sourceFileName,loadOptions),存储为byte[],转存new String(bytes, “UTF-8”),持久化存储,然后再String->byte[]->PsdImage,进行图层的操作(文本层文字替换、图片层图片替换等)。
1.源代码:

public static void main(String[] args) throws FileNotFoundException 
{
    License license = new License();
    String licFileDir = "E:\\mysite\\openproj\\Aspose.PSD-for-Java\\Examples\\src\\main\\resources\\Lic\\Aspose.Total.Product.Family.lic";
    license.setLicense(licFileDir);
    String dataDir = "E:\\mysite\\openproj\\Aspose.PSD-for-Java\\Examples\\src\\main\\resources\\PSD\\";
    String sourceFileName = dataDir + "nvwangJy.psd";
    String exportPath = dataDir + "nvwangNewTextUpdateResult.png";
    PsdLoadOptions loadOptions = new PsdLoadOptions();
    //Try this
    //loadOptions. setLoadEffectsResource(true);
    PsdImage image1 =(PsdImage) Image.load(sourceFileName,loadOptions);

    byte[] layerBytes;
    MemoryStream layerMem = new MemoryStream();
    OutputStream dstStream = layerMem.toOutputStream();
    image1.save(dstStream, new PsdOptions());
    layerBytes = layerMem.toArray();
    //layerMem = new MemoryStream(layerBytes);
    InputStream inputStream = new ByteArrayInputStream(layerBytes);
    PsdImage image = new PsdImage(inputStream);

    for(int i=0; i < image.getLayers().length; i++ )
    {
        Layer layer = (Layer) image.getLayers()[i];
        System.out.println(i + "DisplayName:" + layer.getDisplayName() + "name:" + layer.getName());
        if (i == 11 && image.getLayers()[i] instanceof TextLayer)
        {
            TextLayer textLayer = (TextLayer)image.getLayers()[i];
            Point leftTopCoordinate = new Point();
            leftTopCoordinate.setX(textLayer.getLeft());
            leftTopCoordinate.setY(textLayer.getTop());
            textLayer.updateText("靠你就是我\r我的\r你的", leftTopCoordinate, ((TextLayer)textLayer).getFont().getSize(), ((TextLayer)textLayer).getTextColor());
        }
    }
    PngOptions options = new PngOptions();
    options.setColorType(PngColorType.TruecolorWithAlpha);

    image.save(exportPath,options);
}
  1. 期望结果:
    nvwangNewTextUpdateExpect.jpg (277.6 KB)

3.实际结果:
nvwangNewTextUpdateResult.jpg (306.7 KB)

PS:看清需求,希望一步到位解决,给出实际效果的源代码示例。谢谢,关乎购买服务商务合同签订。
目前我们产品待实现的需求,仅剩此问题,加文本层文字支持多行\r不限长度内容替换了。忘这两个问题优先紧急处理,谢谢。

@jsczxielong

我已经通过以下线程分享了针对同一问题的反馈。 这是API中的问题,我们将尽快与您分享反馈。

收到,非常感谢,期待答案。刚也验证过了,换行通过如上textData.getItems()方式的确可以了。现问题就只在于loadPsd源文件对象PsdImage->byte[]->PsdImage这块了。加油,敬请期待。

对于序列化,我已经添加了新票证,请按照有关更新的主题进行操作。