Rendition with layer effects

Is it possible to create a rendition of a layer with the layer effects applied?

@Harbs yes. It’s possible.

If you want to open file with Layer effects please check the following code:
PsdLoadOptions loadOpt = new PsdLoadOptions();
// For the Applying of effects
loadOpt.setLoadEffectsResource(true);
// For the Applying of Warp Transform
loadOpt.setAllowWarpRepaint(true);

If you want create effects from scratch, please check the following example:

try (PsdImage image = (PsdImage)Image.load(inputFilePath)) {
IGradientColorPoint[] gradientColorPoints = new IGradientColorPoint[] {
new GradientColorPoint(Color.getRed(), 0, 50),
new GradientColorPoint(Color.getGreen(), 1024, 50),
new GradientColorPoint(Color.getBlue(), 2048, 50)
};

        GradientTransparencyPoint gp1 = new GradientTransparencyPoint();
        gp1.setOpacity(128);
        gp1.setMedianPointLocation(50);
        gp1.setLocation(0);

        GradientTransparencyPoint gp2 = new GradientTransparencyPoint();
        gp2.setOpacity(176);
        gp2.setMedianPointLocation(50);
        gp2.setLocation(2048);
        IGradientTransparencyPoint[] gradientTransparencyPoints = new IGradientTransparencyPoint[] {
                gp1,
                gp2
        };

        StrokeEffect stroke =  image.getLayers()[1].getBlendingOptions().addStroke(FillType.Gradient);
        GradientFillSettings gradientFill = (GradientFillSettings)stroke.getFillSettings();
        gradientFill.setColorPoints(gradientColorPoints);
        gradientFill.setTransparencyPoints(gradientTransparencyPoints);

        InnerShadowEffect innerShadow = image.getLayers()[2].getBlendingOptions().addInnerShadow();
        innerShadow.setAngle(60);
        innerShadow.setColor(Color.getYellow());

        DropShadowEffect dropShadow = image.getLayers()[3].getBlendingOptions().addDropShadow();
        dropShadow.setAngle(30);
        dropShadow.setColor(Color.getViolet());

        GradientOverlayEffect gradient = image.getLayers()[4].getBlendingOptions().addGradientOverlay();
        gradient.getSettings().setColorPoints(gradientColorPoints);
        gradient.getSettings().setTransparencyPoints(gradientTransparencyPoints);

        ColorOverlayEffect colorFill = image.getLayers()[5].getBlendingOptions().addColorOverlay();
        colorFill.setColor(Color.getAzure());
        colorFill.setOpacity((byte)120);

        PatternOverlayEffect patternFill = image.getLayers()[6].getBlendingOptions().addPatternOverlay();
        patternFill.getSettings().setPatternData(new int[] {
                Color.getRed().toArgb(), Color.getTransparent().toArgb(),
                Color.getTransparent().toArgb(), Color.getRed().toArgb()
        });
        patternFill.getSettings().setPatternWidth(2);
        patternFill.getSettings().setPatternHeight(2);

        OuterGlowEffect outerGlow = image.getLayers()[7].getBlendingOptions().addOuterGlow();
        outerGlow.setSize(10);
        ColorFillSettings fillSettings = new ColorFillSettings();
        fillSettings.setColor(Color.getCrimson());
        outerGlow.setFillColor(fillSettings);
    }

Hi, the original question above was posted on my behalf by the user above (same license) and I’m now replying with more info.

I tried the suggested code and I couldn’t get it to work. The layer is exported but not the effects.

Here is what I have:

private static void saveLayerToPng(int layerIndex, boolean addEffectManually) {
	boolean applyEffects = true;
	File psdFile = new File("psds/effects/text-shape-font-effects.psd");
	PsdLoadOptions loadOptions = null;
	File outputImage = new File("layer_" + layerIndex + ".png");

	if (applyEffects) {
		loadOptions = new PsdLoadOptions();
		loadOptions.setLoadEffectsResource(true);
		loadOptions.setAllowWarpRepaint(true);
		System.out.println("Setting load effects to true");
	}

	FileInputStream inputFileStream = null;

	try {
		inputFileStream = new FileInputStream(psdFile);
	} catch (FileNotFoundException e) {
		System.err.println("File <" + psdFile.getPath() + "> does not exist");
		System.exit(1);
	} catch (SecurityException e) {
		System.err.println("File <" + psdFile.getPath() + "> cannot be read");
		System.exit(1);
	}

	Image image = Image.load(inputFileStream, loadOptions);
	PsdImage psdImage = (PsdImage) image;
	List<Layer> normalizedLayers = TaskUtils.normalizeLayers(psdImage.getLayers());

	Layer layer = normalizedLayers.get(layerIndex);

	if (addEffectManually) {
		DropShadowEffect dropShadow = layer.getBlendingOptions().addDropShadow();
		dropShadow.setAngle(144);
		dropShadow.setColor(Color.getViolet());
	}

	PngOptions pngOptions = new PngOptions();
	pngOptions.setColorType(PngColorType.TruecolorWithAlpha);

	try {
		FileOutputStream outputFileStream = new FileOutputStream(outputImage);
		layer.save(outputFileStream, pngOptions);
		System.out.println("Saved layer to " + outputImage.getPath());
	} catch (Exception e) {
		// throw new TaskException("Failed to output image to file: " +
		// outputImage.getPath(), e);

		System.err.println("Failed to output image to file: " + outputImage.getPath());
		System.exit(1);
	}
}
public static List<Layer> normalizeLayers(Layer[] layers) {
	int depth = 0;
	List<Layer> result = new ArrayList<>();
	for (Layer layer : layers) {
		if (layer instanceof SectionDividerLayer) {
			depth++;
		} else if (layer instanceof LayerGroup) {
			depth--;
		}
		if (depth == 0) {
			result.add(layer);
		}
	}
	Collections.reverse(result);
	return result;
}
saveLayerToPng(1, false);
saveLayerToPng(2, false);
saveLayerToPng(3, true);
saveLayerToPng(4, true);

PSD attached:
text-shape-font-effects.psd.zip (382.7 KB)

@Harbs
I have opened three tickets in our internal issue tracking system according to this task and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PSDNET-1958,PSDNET-1959,PSDJAVA-598

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

This issue it’s a API Limitation that exists at this moment. Layers contain only its’ pixeldata. So it’s impossible to export Layer with the Effects in this way layer.save(outputFileStream, pngOptions); But this API feature is frequently requested, so I created tasks to improve API.

At this moment to make export of layer with Layer Effects you need to make all layers invisible except exporting one and then save whole Image to PNG with needed layer.

Please check the following code:

    private static void ExportLayerWithEffect(PsdImage image, int layerToExportIndex) {
        Layer[] layers = image.getLayers();
        boolean[] layerStates = new boolean[layers.length];

        for (int i = 0; i < layers.length; i++) {
            layerStates[i] = layers[i].isVisible();
            layers[i].setVisible(false);
        }

        layers[layerToExportIndex].setVisible(true);

        PngOptions pngOpt = new PngOptions();
        pngOpt.setColorType(PngColorType.TruecolorWithAlpha);

        image.save("SomePath.png");

        for (int i = 0; i < layers.length; i++) {
            layers[i].setVisible(layerStates[i]);
        }
    }
1 Like

Hi, I have applied your example and the layers are exported but the effects do not show in the export. Can you confirm with the PSD above? Here is my export code based on your example:

public class Main {
	public static void main(String[] args) {
		boolean testing = true;
		checkLicense();

		if (testing) {
			saveLayerToPng(1, false);
			saveLayerToPng(2, false);
			saveLayerToPng(3, false);
			saveLayerToPng(4, false);
			return;
		}
	}

	private static void saveLayerToPng(int layerIndex, boolean addEffectManually) {
		boolean applyEffects = true;
		File psdFile = new File("psds/effects/text-shape-font-effects.psd");
		PsdLoadOptions loadOptions = null;
		File outputImage = new File("layer_" + layerIndex + ".png");

		if (applyEffects) {
			loadOptions = new PsdLoadOptions();
			loadOptions.setLoadEffectsResource(true);
			loadOptions.setAllowWarpRepaint(true);
			System.out.println("Setting load effects to true");
		}

		FileInputStream inputFileStream = null;

		try {
			inputFileStream = new FileInputStream(psdFile);
		} catch (FileNotFoundException e) {
			System.err.println("File <" + psdFile.getPath() + "> does not exist");
			System.exit(1);
		} catch (SecurityException e) {
			System.err.println("File <" + psdFile.getPath() + "> cannot be read");
			System.exit(1);
		}

		Image image = Image.load(inputFileStream, loadOptions);
		// Image image = Image.load(inputFileStream);
		PsdImage psdImage = (PsdImage) image;
		PngOptions pngOptions = new PngOptions();
		pngOptions.setColorType(PngColorType.TruecolorWithAlpha);

		// output with effects
		Layer[] layers = psdImage.getLayers();
		boolean[] layerStates = new boolean[layers.length];

		for (int i = 0; i < layers.length; i++) {
			layerStates[i] = layers[i].isVisible();
			layers[i].setVisible(false);
		}

		layers[layerIndex].setVisible(true);

		try {
			FileOutputStream outputFileStream = new FileOutputStream(outputImage);
			psdImage.save(outputFileStream, pngOptions);
			// psdImage.save(outputFileStream);
			System.out.println("Saved layer to " + outputImage.getPath());
		} catch (Exception e) {
			// throw new TaskException("Failed to output image to file: " +
			// outputImage.getPath(), e);

			System.err.println("Failed to output image to file: " + outputImage.getPath());
			System.exit(1);
		}
	}
}

You may have to adjust the code to work with your test program. I am only getting the normal layer with no effects applied.

layer_1.jpg (62.9 KB)

layer_2.png (3.4 KB)

layer_3.png (1023 Bytes)

layer_4.png (4.8 KB)

@velara1 I need time to make investigation. Then I’ll text you back.

1 Like

@valera1 I’ve checked your code and you outputs file. The Shadow effect was applied for them, but without opaque font it’s hard to see the shadows.

The main Issues that I found:

  1. Font differs from input one. You’ll need to install missed font to give Aspose.PSD ability to render it correctly.
  2. Shadows has slightly difference.
    TextLayerWithBackground (2.8 KB)

I cannot view that file:

Sorry, this file is private. Only visible to topic owner and staff members.

I sent you the file.

2 Likes

Are you able to get this PSD to work? I might be missing something or it might be multiple of the same effects are not supported.

drop-shadow-multiple.jpg (162.3 KB)

drop-shadow-multiple.zip (1008.9 KB)

When a layer is exported to an image this way, are the layer effects recreated or are they snapshots stored in the PSD layer data?

@Harbs
@velara1 I’ve checked your file, so I can confirm that Aspose.PSD has issues with rendering or reading multiple effects.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PSDJAVA-608,PSDNET-2003

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

@velara1 when you use ReadOnlyMode, Aspose.PSD takes pixel-perfect saved preview of file. If you open file without ReadOnlyMode, then according to LoadEffectsResource property effects will be rerendered or ignored.

OK. Then the ReadOnlyMode is saving the composite image embedded in the PSD correct? That won’t have the effects on the layers.

So the effects are created by the rendering engine. If it’s not, then we are simply attempting to get the layer image with effects applied (no editing is needed).

If you are taking feature requests on this topic:

  • layer.png() or layer.save() saves the image with effects
  • flag if the effects are ignored or not supported yet
  • layer.save() or psdImage.save() trims the transparent pixel edges (autocrop) but optionally or only as much as the minimum of the layer width and height

Ideally, the Autocrop or trim feature would not completely trim all the whitespace area of a layer. If it is a psdImage composite it would trim the excess areas not part of the layer. Or if it is exported a text layer, if the original text layer is 100x100 normally it may have transparency around it already. That white space is part of the margins. So you don’t want to trim all of that white space. But when effects are applied, like a drop shadow and you have to use the psdImage.save() method the layer content size maybe less than 100x100 if you trim all the transparent pixels. So the final layer size will be less than the artboard size but not less than the layer size. I hope that makes sense.

@Harbs
@velara1 I’ve checked readonlymode with this file and created new bug.

After the investigation of feature-request, I’ll create related task and them to this forum issue. Maybe it’s better to create separate forum topic for it.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PSDNET-2004

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

1 Like

FYI We are using the Java version

@velara1 sure. These bugs will be fixed on Java too. I specified .NET issues and missed the Java version of bugs to ensure correct forum notifications. These issues are presented in whole Aspose.PSD Family. The notifications of .NET versions will be sent sooner.

1 Like