Redaction Deletes and Shifts Text

Upon selecting text as part of a redaction, applying the redaction deletes the selected text rather than just covering it. The adjacent text is pulled from the right to replace deleted area. The redaction should cover the area rather than replace it.

@ccavallaro

Thanks for contacting support.

Would you please share your sample PDF document along with sample code snippet. We will test the scenario in our environment and address it accordingly.

if (status == GdPictureStatus.OK)
{
if (roilist.Count > 0)
{
Document pdfDocument = new Document(currentDocument);

                            foreach (RegionOfInterest r in roilist)
                            {
                                try
                                {
                                    double heightHalfPoint = (int)Math.Round(r.Height * 72, 0) / 2;
                                    double widthHalfPoint = (int)Math.Round(r.Width * 72, 0) / 2;

                                    double llx = (int)Math.Round(r.Left * 72, 0) - widthHalfPoint;
                                    double lly = (int)Math.Round(r.Top * 72, 0) + heightHalfPoint;
                                    double urx = (int)Math.Round(r.Left * 72, 0) + widthHalfPoint;
                                    double ury = (int)Math.Round(r.Top * 72, 0) - heightHalfPoint;

                                    double maxheight = (int)(r.PageHeight);// * 72);
                                    double maxwidth = (int)(r.Width * 72);

                                    lly = maxheight - lly;
                                    ury = maxheight - ury;

                                    RedactionAnnotation annot = new RedactionAnnotation(pdfDocument.Pages[r.PageNumber], new Aspose.Pdf.Rectangle(llx, lly, urx, ury));

                                    annot.FillColor = Aspose.Pdf.Color.Black;
                                    annot.BorderColor = Aspose.Pdf.Color.Black;
                                    annot.Color = Aspose.Pdf.Color.Black;

                                    pdfDocument.Pages[r.PageNumber].Annotations.Add(annot);

                                    annot.Redact();
                                }
                                catch (Exception ex)
                                {
                                    //Logger.Error(ex);
                                    e.message = SendErrorMessage("Unable to process redaction in the given document");
                                    break;
                                }
                            }
                            pdfDocument.Save(updatedDocument);
                            pdfDocument.Dispose();

                            e.docuVieware.Close();
                            ogdPicture.Dispose();

                            status = e.docuVieware.LoadFromStream(new FileStream(updatedDocument, FileMode.Open, FileAccess.ReadWrite, FileShare.Delete, 8, FileOptions.DeleteOnClose), true);
                            

                            if (status != GdPictureStatus.OK)
                            {
                                e.message = SendErrorMessage("Unable to load redacted document");
                            }

                            if (status != GdPictureStatus.OK)
                            {
                                e.message = SendErrorMessage("Unable to load the latest page");
                            }

                        }
                    }

@ccavallaro

Thanks for sharing sample code snippet.

As requested earlier, would you also share your sample PDF document with us. This would help us testing the scenario in our environment and address it accordingly.

Hello here is file that would have the problem?

@ccavallaro

Thanks for sharing sample PDF document.

We have tried to run your code snippet with your document but it contained some missing values and objects. However, we have tested the scenario using following code snippet and Aspose.PDF for .NET 19.2 in our environment and were unable to notice the issue you have mentioned.

TextFragmentAbsorber absorber = new TextFragmentAbsorber("Contributor");
Document pdf = new Document(dataDir + "Flatten.pdf");
pdf.Pages.Accept(absorber);
foreach(TextFragment tf in absorber.TextFragments)
{
 RedactionAnnotation ra = new RedactionAnnotation(tf.Page, tf.Rectangle);
 ra.FillColor = Aspose.Pdf.Color.FromRgb(System.Drawing.Color.Black);
 ra.BorderColor = Aspose.Pdf.Color.Black;
 tf.Page.Annotations.Add(ra);
 ra.Color = Aspose.Pdf.Color.Black;
 ra.Redact();
}     
pdf.Save(dataDir + "redacted.pdf");

Redacted.pdf (43.2 KB)

For your kind reference, an output PDF file is also attached. Would you please make sure to use latest version of the API and in case issue still persists, please share a code snippet which can be run and able to replicate the issue. We will again test the scenario in our environment and address it accordingly.

Thanks for the reply,

However, I wanted to show you exactly what is happening when we redact.

This sounds very similar to the issue that was reported in the below ticket: Not sure if this was resolved or not

@ccavallaro

Thanks for sharing more details.

As requested earlier, would you please share missing part of your code snippet i.e. Definition of RegionOfInterest as it could help us generating the similar case you are experiencing in your environment. OR you can please share Rectangle value with us so that we can test the scenario in our environment and address it accordingly.

    /// <summary>
    /// Creates black redaction rectangle
    /// </summary>
    /// <param name="e"></param>
    public static void RedactPdf(CustomActionEventArgs e)
    {
        if (!string.IsNullOrWhiteSpace(e.args.ToString()))
        {
            RedactionObject _redactionObject = JsonConvert.DeserializeObject<RedactionObject>(e.args.ToString());

            string cacheFolderPath = _redactionObject.CacheFolder.Replace("$","\\");

            List<RedactionDetails> redactiondetails = _redactionObject.RedactionList;

            if(!string.IsNullOrWhiteSpace(cacheFolderPath) && Directory.Exists(cacheFolderPath) && redactiondetails!= null && redactiondetails.Count > 0 )
            {
                string guid = Guid.NewGuid().ToString();

                string currentDocument = System.IO.Path.Combine(cacheFolderPath, guid + ".pdf");

                string nguid = Guid.NewGuid().ToString();

                string updatedDocument = System.IO.Path.Combine(cacheFolderPath, nguid + ".pdf");

                Aspose.Pdf.License lic = new Aspose.Pdf.License();

                lic.SetLicense("Aspose.Pdf.lic");

                lic.Embedded = true;

                GdPicturePDF ogdPicture = new GdPicturePDF();

                AnnotationManager am = new AnnotationManager();

                GdPictureStatus status = e.docuVieware.GetNativePDF(out ogdPicture);

                List<RegionOfInterest> roilist = new List<RegionOfInterest>();

                if (status == GdPictureStatus.OK)
                {
                    status = am.InitFromGdPicturePDF(ogdPicture);

                    if (status == GdPictureStatus.OK)
                    {
                        if (redactiondetails != null && redactiondetails.Count > 0)
                        {
                            List<int> selectedPageNumbers = redactiondetails.Select(x => x.pageNo).Distinct().ToList();

                            foreach (int page in selectedPageNumbers)
                            {
                                ogdPicture.SelectPage(page);
                                am.SelectPage(page);

                                List<string> annotGuidList = redactiondetails.Where(x => x.pageNo == page).Select(x => x.id).ToList();

                                GdPicture14.Annotations.Annotation[] annotListByPage = am.GetOrderedAnnotations();

                                foreach (string id in annotGuidList)
                                {
                                    GdPicture14.Annotations.Annotation temp = annotListByPage.Where(x => x.Guid == id).Select(x => x).FirstOrDefault();

                                    if (temp != null)
                                    {
                                        RegionOfInterest roi = new RegionOfInterest();

                                        roi.PageNumber = page;
                                        roi.Left = temp.Left;
                                        roi.Top = temp.Top;
                                        roi.Height = temp.Height;
                                        roi.Width = temp.Width;
                                        roi.PageWidth = ogdPicture.GetPageWidth();
                                        roi.PageHeight = ogdPicture.GetPageHeight();
                                        roilist.Add(roi);
                                    }

                                }
                            }

                            foreach (RedactionDetails item in redactiondetails)
                            {
                                bool result = DeleteAnnotation(am, item.id, item.pageNo);

                                if (!result)
                                {
                                    redactiondetails.Remove(item);//SendErrorMessage("Cannot delete annotation");
                                    break;
                                }
                            }
                        }
                    }

                    status = ogdPicture.SaveToFile(currentDocument);

                    if (status == GdPictureStatus.OK)
                    {
                        if (roilist.Count > 0)
                        {
                            Document pdfDocument = new Document(currentDocument);

                            foreach (RegionOfInterest r in roilist)
                            {
                                try
                                {
                                    double heightHalfPoint = (int)Math.Round(r.Height * 72, 0) / 2;
                                    double widthHalfPoint = (int)Math.Round(r.Width * 72, 0) / 2;

                                    double llx = (int)Math.Round(r.Left * 72, 0) - widthHalfPoint;
                                    double lly = (int)Math.Round(r.Top * 72, 0) + heightHalfPoint;
                                    double urx = (int)Math.Round(r.Left * 72, 0) + widthHalfPoint;
                                    double ury = (int)Math.Round(r.Top * 72, 0) - heightHalfPoint;

                                    double maxheight = (int)(r.PageHeight);// * 72);
                                    double maxwidth = (int)(r.Width * 72);

                                    lly = maxheight - lly;
                                    ury = maxheight - ury;

                                    RedactionAnnotation annot = new RedactionAnnotation(pdfDocument.Pages[r.PageNumber], new Aspose.Pdf.Rectangle(llx, lly, urx, ury));

                                    annot.FillColor = Aspose.Pdf.Color.Black;
                                    annot.BorderColor = Aspose.Pdf.Color.Black;
                                    annot.Color = Aspose.Pdf.Color.Black;

                                    pdfDocument.Pages[r.PageNumber].Annotations.Add(annot);

                                    annot.Redact();
                                }
                                catch (Exception ex)
                                {
                                    //Logger.Error(ex);
                                    e.message = SendErrorMessage("Unable to process redaction in the given document");
                                    break;
                                }
                            }
                            pdfDocument.Save(updatedDocument);
                            pdfDocument.Dispose();

                            e.docuVieware.Close();
                            ogdPicture.Dispose();

                            status = e.docuVieware.LoadFromStream(new FileStream(updatedDocument, FileMode.Open, FileAccess.ReadWrite, FileShare.Delete, 8, FileOptions.DeleteOnClose), true);
                            

                            if (status != GdPictureStatus.OK)
                            {
                                e.message = SendErrorMessage("Unable to load redacted document");
                            }

                            if (status != GdPictureStatus.OK)
                            {
                                e.message = SendErrorMessage("Unable to load the latest page");
                            }

                        }
                    }
                }
            }
            else
            {
                e.message = SendErrorMessage("Nothing to redact");
            }
        }
        else
        {
            e.message = SendErrorMessage("Unable to redact document");
        }

    }


public class RegionOfInterest
{
    public int PageNumber { get; set; }
    public double Left { get; set; }
    public double Top { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double PageHeight { get; set; }
    public double PageWidth { get; set; }
}

@ccavallaro

Thanks for sharing sample code snippet.

We have again tested the scenario in our environment and were unable to replicate issue. However, we have noticed that the PDF you shared was generated using quite old version of the API whereas it is always recommended to use latest version. We were unable to replicate the formatting issue using Aspose.PDF for .NET 19.2. Would you please try using latest version of the API and in case you still face any issue, please let us know.

PS: In case issue still persists, please share sample values for above class which you used along with respective source PDF document.