Copy stamp annotation

Hi, 

I have tried to create a stampAnnotation with a image. Then I've tried create feature to copy the annotation by selected annotation and create a copy of it in new location.

But the Stream properties in StampAnnotation class is internal, so I cannot set the stream for the copy annotation.

How can I perform this feature?

Thank and regards,

TH


16 Replies

MM Manikandan Manickavasagam Syncfusion Team September 11, 2024 03:44 AM UTC

Hi Thanh,


Currently, we do not provide any API to access the stream of a selected stamp annotation, nor do we offer support for copying the selected annotation directly. However, we have checked with some competitors regarding the feature of copying selected annotations. Could you please confirm whether you are specifically looking for the ability to copy a selected annotation, or if you are mainly interested in obtaining the stream of the selected stamp annotation? Your confirmation will greatly help us in analyzing this requirement further.


Regards,
Manikandan M



TH Thanh Hai Dang September 11, 2024 03:48 AM UTC

Hi Manikandan, 

I am mainly interested in obtaining the stream of the selected stamp annotation. Then I can be make a workaround to create a new stamp annotation with this stream and another annotation bounds. 

Thanks and regards,

TH



MM Manikandan Manickavasagam Syncfusion Team September 12, 2024 03:03 AM UTC

Hi Thanh


You can obtain the stream of a selected annotation using the PDF library, which is another control of Syncfusion. The Syncfusion.Maui.PdfViewer already includes the PDF library package, so there's no need for an additional download.


Here's a code snippet to demonstrate how you can achieve this:


 

Stream[] copiedStream;

RectF copiedAnnotationBound;

 

public MainPage()

{

    InitializeComponent();

    Stream document = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("OutlineViewIssue.pdfSuc.pdf");

    pdfViewer.LoadDocument(document);

    pdfViewer.AnnotationSelected += PdfViewer_AnnotationSelected;

}

 

private void PdfViewer_AnnotationSelected(object? sender, AnnotationEventArgs e)

{

    int pageNumber = e.Annotation.PageNumber;

 

    Stream mainStream = new MemoryStream();

    pdfViewer.SaveDocument(outputStream: mainStream);

    PdfLoadedDocument pdfLoadedDocument = new PdfLoadedDocument(mainStream);

    if (pdfLoadedDocument.Pages[pageNumber - 1] is PdfLoadedPage page)

    {

        foreach (var annotation in page.Annotations)

        {

            if (annotation is PdfLoadedRubberStampAnnotation stampAnnotation && (e.Annotation.Name == stampAnnotation.Name))

            {

                copiedStream = stampAnnotation.GetImages();

                copiedAnnotationBound = new RectF(stampAnnotation.Bounds.X, stampAnnotation.Bounds.Y, stampAnnotation.Bounds.Width, stampAnnotation.Bounds.Height);

            }

        }

    }

}

 

private void Add_Clicked(object sender, EventArgs e)

{

    AddStampAnnotation();

}

 

StampAnnotation CreateApprovedStandardStamp()

{

    int pageNumber = 1;

    RectF bounds = new RectF(50, 50, 200, 100);

    Stream imageStream = this.GetType().Assembly.GetManifestResourceStream("OutlineViewIssue.Resources.Images.dotnet_bot.png");

    StampAnnotation customStamp = new StampAnnotation(imageStream, pageNumber, bounds);

    customStamp.Name = "copy";

    return customStamp;

}

 

void AddStampAnnotation()

{

    StampAnnotation stampAnnotation = CreateApprovedStandardStamp();

    pdfViewer.AddAnnotation(stampAnnotation);

}

 

private void Copy_Button_Clicked(object sender, EventArgs e)

{

    if (copiedStream[0] != null)

    {

        StampAnnotation annotation = new StampAnnotation(copiedStream[0], pdfViewer.PageNumber + 1, copiedAnnotationBound);

        pdfViewer.AddAnnotation(annotation);

    }

}

 


Explanation of the Code

  1. Loading the Document: In the MainPage constructor, the PDF document is loaded using the LoadDocument method of pdfViewer. The AnnotationSelected event is subscribed to handle when an annotation is selected.


  1. Handling Annotation Selection: The PdfViewer_AnnotationSelected method is triggered when an annotation is selected. This method saves the current document into a MemoryStream, then loads it into a PdfLoadedDocument. It iterates through the annotations on the selected page to find the matching stamp annotation by name. Once found, it retrieves the stream of the selected annotation's images (GetImages()) and stores the annotation's bounds in copiedAnnotationBound.


  1. Creating and Adding a Stamp Annotation: The CreateApprovedStandardStamp method creates a new stamp annotation with specified bounds and an image stream from a resource. The AddStampAnnotation method adds this newly created annotation to the pdfViewer.


  1. Copying and Adding an Annotation: The Copy_Button_Clicked method checks if the copiedStream is not null, then creates a new stamp annotation using the copied stream and bounds. It adds this copied annotation to the pdfViewer.


Note: In this sample, the copied stamp annotation is added to the next page of the selected annotation's page number. You can adjust the code to add the copied annotation to your desired location.


Please review the attached sample and let us know if this meets your requirement or if further modifications are needed.

Regards,
Manikandan M


Attachment: CopyStream_f9d0ab76.zip


TH Thanh Hai Dang September 16, 2024 07:08 PM UTC

Hi  Manikandan M,

I used your algorithm to get image stream from a Stamp Annotation. But sometimes the  PdfViewer_AnnotationSelected() function works properly, sometimes it doesn't work because there is no  PdfLoadedRubberStampAnnotation or the page doesn't contain any annotations.

How can I resolve this issue?
Thanks and regards



MM Manikandan Manickavasagam Syncfusion Team September 17, 2024 05:16 PM UTC

Hi Thanh,


We provided a workaround to copy the selected stamp annotation in the PDF. This workaround copies only the stream of the selected stamp annotation. As you mentioned, the workaround sometimes does not work, particularly when there is no annotation on the page or no PdfLoadedRubberStampAnnotation is found.


If a page contains no annotations, you cannot select any annotation, including stamp annotations, so copying the stream is not possible. Regarding the absence of PdfLoadedRubberStampAnnotation, when you select the stamp annotation, the AnnotationSelected event saves the current PDF stream and loads it into the PdfLoadedDocument to retrieve the selected annotation's stream. Stamp annotations that are already added will be under PdfLoadedRubberStampAnnotation, and their stream should be accessible.


To investigate this issue further, could you please provide the following information:


  • Does this issue occur in our sample provided in our last update? If yes, please share the exact steps to reproduce it.

  • If the issue doesn't occur with our sample, please provide detailed reproduction steps or modify the provided sample to replicate the issue.


This will help us analyze the problem more effectively and suggest appropriate solutions.


Regards,

Manikandan M



TH Thanh Hai Dang September 23, 2024 11:50 AM UTC

Hi  Manikandan M, 

I got this bug when I design a button to add image to PDF file as a stamp annotation. 

I created a button to select an image that will be added to stamp annotation and executed the tap event to determine position for the annotation.

To reproduce this bug please follow the steps:

  1. Click button and select an image path.
  2. Tap to the SfPdfViewer on the out of page area.
  3. Click button and select image again.
  4. Tap to the SfPdfViewer page, a stamp annotation added.
When the annotation selected, there isn't any PdfLoadedRubberStampAnnotation ​is found.
P/s: I can only select the annotation and can't move or edit its size.

Please suggest to me an appropriate solution.
Many thanks and best 


BS Bharathi Selvam Syncfusion Team September 24, 2024 04:53 PM UTC

Hi Thanh,

We are preparing a sample to reproduce the issue based on the replication steps you have provided. We will provide you the details on September 25, 2024

Regards,

Bharathi S




MM Manikandan Manickavasagam Syncfusion Team September 26, 2024 04:38 AM UTC

Hi Thanh,

We have attempted to replicate the issue using our sample, but we were unable to reproduce the problem: "PdfLoadedRubberStampAnnotation not found in the PdfLoadedStream."

In our updated sample (which was previously shared with you), we replaced the "Add" button with a "Create" button. This button retrieves the image stream, creates the stamp, and triggers the "Tapped" event, which adds the created stamp at the tapped position.

From your update, it seems there is no PdfLoadedRubberStampAnnotation in the selected annotation. To retrieve PdfLoadedRubberStampAnnotation, you must reload the PDF viewer stream into the PdfLoadedDocument. Only by doing this can you access PdfLoadedRubberStampAnnotation.
Here is the code snippet for that

 

private void PdfViewer_AnnotationSelected(object? sender, AnnotationEventArgs e)

{

    int pageNumber = e.Annotation.PageNumber;

           

    Stream mainStream = new MemoryStream();

   pdfViewer.SaveDocument(outputStream: mainStream);

    PdfLoadedDocument pdfLoadedDocument = new PdfLoadedDocument(mainStream);

    if (pdfLoadedDocument.Pages[pageNumber-1] is PdfLoadedPage page)

    {

        foreach (var annotation in page.Annotations)

        {

            if (annotation is PdfLoadedRubberStampAnnotation stampAnnotation && (e.Annotation.Name==stampAnnotation.Name))

            {

                copiedStream = (stampAnnotation).GetImages();

                copiedAnnotationBound = new RectF(stampAnnotation.Bounds.X, stampAnnotation.Bounds.Y, stampAnnotation.Bounds.Width, stampAnnotation.Bounds.Height);

            }

        }

    }

 

}

 



Please confirm if you have followed the highlighted steps. If not, kindly try them and let us know if the issue is resolved. For your reference we have attached the modified the sample in the attachment.

Regards,

Manikandan M


Attachment: CopyStream_90521c95.zip


TH Thanh Hai Dang September 26, 2024 05:03 AM UTC

Hi  Manikandan M,

I've tried to replicate the issue, and the reason is the SaveDocument() method throw exceptions:

"The index can't be less then zero or greater then Count. (Parameter 'index')"

   at Syncfusion.Pdf.Primitives.PdfArray.get_Item(Int32 index)
   at Syncfusion.Pdf.Parsing.PdfLoadedPageCollection.GetParentNode(Int32 kidStartIndex, PdfArray kids, Int32 lowIndex, Int32 pageIndex, PdfDictionary& node, Int32& localIndex, Boolean& isParentFetched)
   at Syncfusion.Pdf.Parsing.PdfLoadedPageCollection.GetParent(Int32 index, Int32& localIndex, Boolean zeroValid, Boolean enableFastFetching)
   at Syncfusion.Pdf.Parsing.PdfLoadedPageCollection.GetPage(Int32 index)
   at Syncfusion.Pdf.Parsing.PdfLoadedPageCollection.get_Item(Int32 index)
   at Syncfusion.Maui.PdfViewer.AnnotationsLoader.SaveAnnotations(CancellationToken cancellationToken)
   at Syncfusion.Maui.PdfViewer.AnnotationsLoader.Save(Stream outputStream, CancellationToken cancellationToken)
   at Syncfusion.Maui.PdfViewer.SfPdfViewer.SaveDocument(Stream outputStream)
   at RocketPDF.LibShareService.Services.PdfAnnotationService.ExtractImageFromStampAnnotation(SfPdfViewer pdfViewer, StampAnnotation stampAnnotation)

Here is my code:

Where the stampAnnotation is the selected annotation.

public Stream? ExtractImageFromStampAnnotation(SfPdfViewer pdfViewer, StampAnnotation? stampAnnotation)
{
if (stampAnnotation == null)
{
return null;
}

try
{
using Stream mainStream = new MemoryStream();
pdfViewer.SaveDocument(outputStream: mainStream);
var pdfLoadedDocument = new PdfLoadedDocument(mainStream);
var pageNumber = stampAnnotation.PageNumber;
if (pdfLoadedDocument.Pages[pageNumber - 1] is PdfLoadedPage page)
{
foreach (var annotation in page.Annotations)
{
if (annotation is PdfLoadedRubberStampAnnotation pdfLoadedRubberStampAnnotation && (stampAnnotation.Name == pdfLoadedRubberStampAnnotation.Name))
{
return pdfLoadedRubberStampAnnotation.GetImages()?.FirstOrDefault();
}
}
}
}
catch (Exception ex)
{
//ignore
}


return null

;


TH Thanh Hai Dang September 26, 2024 08:50 AM UTC

Hi Manikandan M,

I found another issue with this approach, the stream which got PdfLoadedRubberStamptAnnotation, has some change with the base stream that used to create annotation.

I write some code to create StampAnnotation:


            var newAnnotation = new StampAnnotation(stream, stampAnnotation.PageNumber, stampAnnotation.Bounds)
            {
                Name = stampAnnotation.Name,
                Opacity = stampAnnotation.Opacity,
            };
            var newStream = ExtractImageFromStampAnnotation(pdfViewer, newAnnotation);

The 'stream' has length is  4207, and the image created from it has resolution is 150. While the properties in 'newStream' are 5463 and 96.

Please help me to explain this issue? Or how can I keep image resolution after creating new annotation?

Thanks and best regards,

TH



BS Bharathi Selvam Syncfusion Team September 30, 2024 06:30 PM UTC

Hi Thanh,

Issue

Response

I've tried to replicate the issue, and the reason is the SaveDocument() method throw exceptions:

"The index can't be less then zero or greater then Count. (Parameter 'index')"

 

 We were unable to reproduce the reported exception and selecting the annotation is working fine on our end.

 

Please share the following details to analyze and investigate this issue further and assist you with a better solution:

  • Modified sample.

  • Platform details

  • Any other specific information that could help us to replicate this issue.

 I found another issue with this approach, the stream which got PdfLoadedRubberStamptAnnotation, has some change with the base stream that used to create annotation.

 

We are able to replicate the issue “Length of the stream got from PdfLoadedRubberStamptAnnotation is differ from the initial stream  “. We are currently in the process of validating the issue and will update you with further details by October 4,2024.


Regards,

Bharathi S



TH Thanh Hai Dang October 1, 2024 03:28 PM UTC

Hi Bharathi, 

I've found the reason for the exceptions  "The index can't be less then zero or greater then Count. (Parameter 'index')". Because I tap the area out of page, the pageNumber is -1, then I try to add annotation to the page number -1. 

Thank you for your efforts.

I 've just compiled the problems I encountered when using Annotation with SfPdfViewer in the thread https://www.syncfusion.com/forums/194610/some-issues-with-annotation-and-redact.

Please take a look!

Thanks again and regards,

TH



MA ManojKumar Arumugasamy Syncfusion Team October 2, 2024 01:13 PM UTC

Hi Thanh,

Issue

Response

I've found the reason for the exceptions  "The index can't be less then zero or greater then Count. (Parameter 'index')". Because I tap the area out of page, the pageNumber is -1, then I try to add annotation to the page number -1.

Thank you for your efforts.

 

Thank you for clarifying that the issue was not with the application. I appreciate your understanding that it happened because of tapping outside the page, which resulted in a page number of -1.

If you have any more questions or need assistance, don’t hesitate to reach out.

 

I found another issue with this approach, the stream which got PdfLoadedRubberStamptAnnotation, has some change with the base stream that used to create annotation.

 

From <https://forumassist.syncfusion.com/194359>  

 

We will provide an update by October 4, 2024 as already promised.

I 've just compiled the problems I encountered when using Annotation with SfPdfViewer in the thread  https://www.syncfusion.com/forums/194610/some-issues-with-annotation-and-redact.

Please take a look!

We will update the details on this ticket itself, please follow up on the same ticket.

 

 

 

Regards,

Manoj Kumar



BS Bharathi Selvam Syncfusion Team October 4, 2024 03:29 PM UTC

Hi Thanh,

Sorry for the inconvenience caused. We are still validating the reported issue “Length of the stream got from PdfLoadedRubberStamptAnnotation is differ from the initial stream ” and are prioritizing it with high importance. We will provide you with further details by October 08, 2024.

Regards,

Bharathi S



BS Bharathi Selvam Syncfusion Team October 8, 2024 06:20 PM UTC

Hi Thanh,

We are still validating the reported issue “Length of the stream got from PdfLoadedRubberStamptAnnotation is differ from the initial stream ” and are prioritizing it with high importance. We will provide you with further details by October 10, 2024.

Regards,

Bharathi S



BS Bharathi Selvam Syncfusion Team October 10, 2024 06:03 PM UTC

Hi Thanh,

The difference in image size when inserting and extracting an image from a PDF can be due to several factors:

Here are the primary reasons:

1.Compression: When an image is inserted into a PDF, it may be compressed to reduce the overall file size of the PDF. Common compression algorithms include JPEG compression for images, which can significantly reduce the file size but also alter the image data.

2.Format Conversion: The image format might change during the insertion or extraction process. For example, an image inserted as a PNG might be extracted as a JPEG, which uses lossy compression and can result in a different file size.

3.Metadata: The original image might contain metadata (such as EXIF data) that is not preserved when the image is embedded in the PDF or when it is extracted. This can lead to differences in file size.

4.Color Space Conversion: The color space of the image might be converted when it is inserted into the PDF. For example, an RGB image might be converted to CMYK, which can affect the file size.

5.Resolution Changes: The resolution of the image might be altered during the insertion process.

6.PDF Encoding: The way the PDF encodes the image data can also affect the file size. Different encoding methods can result in different file sizes for the same image.

Because of these factors, it's normal that the image size and properties change during the process. As this is the expected behavior, we are unable to proceed further in preserving the exact original size and resolution after extraction.

Regards,

Bharathi S




Loader.
Up arrow icon