Transparency and semi-transparency support in Aspose.PDF for .NET for PDF operators

Can someone please shed some light on the current level of support in Aspose.PDF for .NET with regard to use of transparency and semi-transparency in PDF operators like references to XImage, XObject and use of operators from the Aspose.Pdf.Operators namespace? Please do not suggest replacement solutions, the question is specifically about PDF operators. For example, PDF standard allows definition of ExtGState for a graphics state parameter dictionary, image soft masks (SMask), CA/ca/AIS keys in a graphics state parameter dictionary to support alpha constant for stroking and non-stroking operations, but non of these seem to be supported in Aspose.PDF for .NET on the API level at all?

If this question is to be turned into a requirement specification, then the requirement specification is as follows:

(a) it should be possible to draw semi-transparent shapes (such as polygons, rectangles, circles, or ellipses) using shape-drawing operators from the Aspose.Pdf.Operators namespace, in combination with CA/ca alpha setting from the ExtGState dictionary or similar, and an example of doing so shall be provided together with Aspose.PDF for .NET user-facing documentation;

(b) using Aspose.Pdf.Operators.Do operator, it should be possible to draw XImage objects that contain transparent image areas / transparent background (example is a .PNG image with transparency - note this is just a conceptual example to illustrate the business need, I know XImage in Aspose.PDF does not support .PNG and do not expect such support to be added in connection with this request), in combination with a soft mask (SMask) or similar technology natively offered by PDF standard, and an example of doing so shall be provided together with Aspose.PDF for .NET user-facing documentation.

@AlexeyM

Could you please ZIP and attach your input and expected output PDF files for each use case? We will then provide you more information about your query. Thanks for your cooperation.

Thank you for your prompt reply Tahir! In fact, I have difficulty attaching an example code, because the query is about ExtGState API support in Aspose.PDF for .NET that appears to be completely missing. So it is a challenge to attach a code example for an API that is simply not there. For the same reason, I cannot attach example produced PDF files, because I am using Aspose.PDF API to produce PDF files, and it does not let me perform the intended action.

Here is, however, how I would need to add e.g. a rectanglular shape using PDF operator and Aspose.PDF for .NET API:

    page.Contents.Add(new Aspose.Pdf.Operators.Re(0, 0, 100, 100));
    page.Contents.Add(new Aspose.Pdf.Operators.FillStroke());

And here you can read how you typically add an image using PDF operator:

Please let me know if you need additional input from my side.

@AlexeyM

Thanks for sharing further details. We need to perform an investigation against your shared requirements. For the purpse, an enhancement request has been generated in our issue management system under the ticket ID PDFNET-51120. We will further investigate its feasibility and let you know as soon as the ticket is resolved. Please be patient and spare us some time.

We are sorry for the inconvenience.

Hi, as a workaround, we were able to resolve this with the following code:

    private int _transparencyResourceIndex = 0;
    internal struct TransparencyResourceRef
    {
        public Artifact artifact;
        public int index;
    }
    private Dictionary<float, TransparencyResourceRef> _transparencyResourceMap = new Dictionary<float, TransparencyResourceRef>();

    private string GetTransparencyResourceName(float opacity)
    {
        if (_transparencyResourceMap.ContainsKey(opacity))
        {
            return $"GS{_transparencyResourceMap[opacity].index}";
        }

        var opacityArtifact = new Artifact(Artifact.ArtifactType.Undefined, Artifact.ArtifactSubtype.Undefined);
        opacityArtifact.Opacity = opacity;
        _page.Artifacts.Add(opacityArtifact);

        _transparencyResourceMap.Add(opacity, new TransparencyResourceRef
        {
            artifact = opacityArtifact,
            index = _transparencyResourceIndex
        });

        return $"GS{_transparencyResourceIndex++}";
    }

    private Random _rng = new Random();

    private void DrawFilledRectangle(Layer layer, Box3 box, Vector3 color)
    {
        layer.Contents.Add(new global::Aspose.Pdf.Operators.GSave());
        layer.Contents.Add(new global::Aspose.Pdf.Operators.GS(GetTransparencyResourceName(_rng.NextSingle())));
        layer.Contents.Add(new global::Aspose.Pdf.Operators.SetRGBColor(color.X, color.Y, color.Z));
        layer.Contents.Add(new global::Aspose.Pdf.Operators.MoveTo(box.Min.X, box.Min.Y));
        layer.Contents.Add(new global::Aspose.Pdf.Operators.LineTo(box.Min.X, box.Max.Y));
        layer.Contents.Add(new global::Aspose.Pdf.Operators.LineTo(box.Max.X, box.Max.Y));
        layer.Contents.Add(new global::Aspose.Pdf.Operators.LineTo(box.Max.X, box.Min.Y));
        layer.Contents.Add(new global::Aspose.Pdf.Operators.Fill());
        layer.Contents.Add(new global::Aspose.Pdf.Operators.GRestore());
    }

Note that the GS operator with the transparency resource index should work for all drawing operator that follow.

The result (don’t mind the page title):
image.png (24.9 KB)

@firat

It is nice to know that you were able to sort your issue out. We will definitely include this shared information in our investigation against the logged ticket and update you here once the ticket is resolved.

In addition to semi-transparent background fix that Firat has mentioned, image transparency (like in .png) can be handled / worked around using a collection of Re operators followed by Clip and EndPath operators to specify the image mask in the form of a clipping path.

@AlexeyM

Thanks for sharing more details. We have recorded provided information under the logged ticket so that it can be honored during investigation.