Resalta las palabras en un pdf usando itextsharp, sin mostrar la palabra resaltada en el navegador

Las palabras resaltadas no se muestran en el navegador utilizando itextsharp.

Adobe

enter image description here

Navegador

enter image description here

CÓDIGO

List MatchesFound = strategy.GetTextLocations(splitText[i].Trim(), StringComparison.CurrentCultureIgnoreCase); foreach (Rectangle rect in MatchesFound) { float[] quad = { rect.Left - 3.0f, rect.Bottom, rect.Right, rect.Bottom, rect.Left - 3.0f, rect.Top + 1.0f, rect.Right, rect.Top + 1.0f }; //Create our hightlight PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rect, null, PdfAnnotation.MARKUP_HIGHLIGHT, quad); //Set the color highlight.Color = BaseColor.YELLOW; //Add the annotation stamper.AddAnnotation(highlight, pageno); } 

Amablemente ayúdame a resolver este problema.

Código Updaetd

  private void highlightPDF() { //Create a simple test file string outputFile = Server.MapPath("~/pdf/16193037V_Dhana-FI_NK-QA_Completed.pdf"); string filename = "HL" + Convert.ToString(Session["Filename"]) + ".pdf"; Session["Filename"] = "HL" + Convert.ToString(Session["Filename"]); //Create a new file from our test file with highlighting string highLightFile = Server.MapPath("~/pdf/" + filename); //Bind a reader and stamper to our test PDF PdfReader reader = new PdfReader(outputFile); iTextSharp.text.pdf.PdfContentByte canvas; int pageno = Convert.ToInt16(txtPageno.Text); using (FileStream fs = new FileStream(highLightFile, FileMode.Create, FileAccess.Write, FileShare.None)) { using (PdfStamper stamper = new PdfStamper(reader, fs)) { canvas = stamper.GetUnderContent(pageno); myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy(); strategy.UndercontentCharacterSpacing = canvas.CharacterSpacing; strategy.UndercontentHorizontalScaling = canvas.HorizontalScaling; string currentText = PdfTextExtractor.GetTextFromPage(reader, pageno, strategy); string text = txtHighlight.Text.Replace("\r\n", "").Replace("\\n", "\n").Replace(" ", " "); string[] splitText = text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < splitText.Length; i++) { List MatchesFound = strategy.GetTextLocations(splitText[i].Trim(), StringComparison.CurrentCultureIgnoreCase); foreach (Rectangle rect in MatchesFound) { canvas.SaveState(); canvas.SetColorFill(BaseColor.YELLOW); canvas.Rectangle(rect); canvas.Fill(); canvas.RestoreState(); } } } } reader.Close(); } 

No está resaltando el texto. Pasé el texto y la página no para resaltar el texto.

Ante todo…

¿Por qué el código del OP (actualizado) no funciona?

En realidad hay dos factores.

En primer lugar , hay un problema en el código del OP, para agregar un rectángulo a una ruta que usa

 canvas.Rectangle(rect); 

Desafortunadamente, esto no es lo que espera: la clase Rectangle tiene múltiples propiedades más allá de las simples coordenadas de un rectángulo, la información más importante sobre los bordes seleccionados, los colores de borde y un color interior, y PdfContentByte.Rectangle(Rectangle) dibuja un rectángulo de acuerdo con esas propiedades .

Sin embargo, en el caso que nos ocupa, rect se usa solo para transportar las coordenadas de un rectángulo, por lo que todas esas propiedades adicionales son false o null . Por lo tanto, canvas.Rectangle(rect) no hace nada!

En cambio, el OP debería usar

 canvas.Rectangle(rect.Left, rect.Bottom, rect.Width, rect.Height); 

aquí.

Además , @Bruno mencionó en su respuesta

Tenga en cuenta que no verá el rectángulo amarillo si lo agrega bajo una forma opaca (por ejemplo, debajo de una imagen).

Lamentablemente, este es el caso aquí: el documento en realidad es un documento escaneado, cada página es una imagen de llenado de página debajo de la cual se dibuja el texto equivalente (probablemente después de OCR) para permitir la copia y pegado de texto.

Por lo tanto, cualquiera que sea el código de OP que dibuje en UnderContent , estará oculto por esa misma imagen.

Por lo tanto, probemos algo diferente …

Cómo hacer que funcione

@Bruno en su respuesta también indicó una solución para tal caso:

En ese caso, puede agregar un rectángulo transparente sobre el contenido existente.

Siguiendo este consejo, reemplazamos

 canvas = stamper.GetUnderContent(pageno); 

por

 canvas = stamper.GetOverContent(pageno); PdfGState state = new PdfGState(); state.FillOpacity = .3f; canvas.SetGState(state); 

Seleccionando la palabra “soporte” en la página del tercer documento que obtenemos:

usando una opacidad de .3

El amarillo es bastante pálido aquí.

Usando un valor de Opacity de .6 vez de eso obtenemos

usando una opacidad de .6

Ahora el amarillo es más intenso pero el texto comienza a palidecer.

Para tareas como esta, prefiero usar el modo de fusión Oscurecer . Esto se puede hacer mediante el uso de

 state.BlendMode = new PdfName("Darken"); 

en lugar de state.FillOpacity = .3f . Esto resulta en

usando el modo de fusión Oscurecimiento

Esta IMO se ve mejor.

Cómo lo hizo el cliente

El OP comentó

El cliente ha dado un pdf. En eso, resaltaron texto, el texto resaltado se muestra en el navegador

El PDF del cliente realmente usa anotaciones, al igual que el OP en su código original, pero en contraste cada una de las anotaciones del cliente contiene una secuencia de aparición que las anotaciones resaltadas generadas por iText no lo hacen.

Proporcionar una apariencia es opcional y los visualizadores de PDF deberían generar una apariencia si no se proporciona ninguno. Obviamente, sin embargo, hay numerosos lectores de PDF que dependen de las apariencias que trae el PDF.

Por cierto, las apariciones en el PDF del cliente realmente usan el modo de mezcla Multiplicar . Para los colores blanco y negro subyacentes, Darken y Multiply tienen el mismo resultado.

Haciéndolo funcionar con anotaciones

En un comentario, el OP se preguntaba

Por favor, una duda más, si el usuario destacó erróneamente, ¿cómo eliminar el color amarillo (o cambiar de amarillo a blanco)? Cambié el amarillo al blanco pero no funciona. canvas.SetColorFill (BaseColor.WHITE);

Deshacer un cambio en el contenido de la página generalmente es más difícil que deshacer la adición de una anotación. Por lo tanto, hagamos que el código original del OP también funcione, es decir, agreguemos una secuencia de aparición a las anotaciones de resaltado.

Como el OP informó en otro comentario, su primer bash de agregar una secuencia de aparición falló:

 PdfAppearance appearance = PdfAppearance.CreateAppearance(stamper.Writer, rect.Width, rect.Height); appearance.Rectangle(rect.Left, rect.Bottom, rect.Width, rect.Height); appearance.SetColorFill(BaseColor.WHITE); appearance.Fill(); highlight.SetAppearance( PdfAnnotation.APPEARANCE_NORMAL, appearance ); stamper.AddAnnotation(highlight, pageno); 

pero no está funcionando.

Los problemas en su bash son:

  • El origen de la plantilla de apariencia se encuentra en la esquina inferior izquierda del área de anotación, no de la página. Para colorear el área en cuestión, por lo tanto, el rectángulo debe tener su parte inferior izquierda en (0, 0).
  • Estrictamente hablando, el color debe establecerse antes de comenzar la construcción del camino.
  • Se debe usar un color diferente al blanco para resaltar.
  • Se debe usar transparencia o un modo de renderizado apropiado para permitir que brille el texto original marcado .

Por lo tanto, el siguiente código muestra cómo hacerlo.

 private void highlightPDFAnnotation(string outputFile, string highLightFile, int pageno, string[] splitText) { PdfReader reader = new PdfReader(outputFile); iTextSharp.text.pdf.PdfContentByte canvas; using (FileStream fs = new FileStream(highLightFile, FileMode.Create, FileAccess.Write, FileShare.None)) { using (PdfStamper stamper = new PdfStamper(reader, fs)) { myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy(); strategy.UndercontentHorizontalScaling = 100; string currentText = PdfTextExtractor.GetTextFromPage(reader, pageno, strategy); for (int i = 0; i < splitText.Length; i++) { List MatchesFound = strategy.GetTextLocations(splitText[i].Trim(), StringComparison.CurrentCultureIgnoreCase); foreach (Rectangle rect in MatchesFound) { float[] quad = { rect.Left - 3.0f, rect.Bottom, rect.Right, rect.Bottom, rect.Left - 3.0f, rect.Top + 1.0f, rect.Right, rect.Top + 1.0f }; //Create our hightlight PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rect, null, PdfAnnotation.MARKUP_HIGHLIGHT, quad); //Set the color highlight.Color = BaseColor.YELLOW; PdfAppearance appearance = PdfAppearance.CreateAppearance(stamper.Writer, rect.Width, rect.Height); PdfGState state = new PdfGState(); state.BlendMode = new PdfName("Multiply"); appearance.SetGState(state); appearance.Rectangle(0, 0, rect.Width, rect.Height); appearance.SetColorFill(BaseColor.YELLOW); appearance.Fill(); highlight.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, appearance); //Add the annotation stamper.AddAnnotation(highlight, pageno); } } } } reader.Close(); } 

Estas anotaciones también son mostradas por Chrome y, como anotaciones, pueden eliminarse fácilmente.

Está utilizando una anotación de marcado para resaltar texto. ¡Eso es genial! No hay nada malo con su código, ni con iText. Sin embargo, no todos los lectores de PDF admiten esa funcionalidad.

Si desea ver texto resaltado en cada visor de PDF, una solución (subóptima) podría ser agregar un rectángulo amarillo a la secuencia de contenido bajo el contenido existente (suponiendo que el contenido existente no sea opaco).

Esto se demuestra en el ejemplo de HighLightByAddingContent :

 public void manipulatePdf(String src, String dest) throws IOException, DocumentException { PdfReader reader = new PdfReader(src); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest)); PdfContentByte canvas = stamper.getUnderContent(1); canvas.saveState(); canvas.setColorFill(BaseColor.YELLOW); canvas.rectangle(36, 786, 66, 16); canvas.fill(); canvas.restreState(); stamper.close(); reader.close(); } 

En este ejemplo, tomamos un archivo llamado hello.pdf y agregamos un rectángulo amarillo, con el archivo hello_highlighted.pdf como resultado.

Tenga en cuenta que no verá el rectángulo amarillo si lo agrega bajo una forma opaca (por ejemplo, debajo de una imagen). En ese caso, puede agregar un rectángulo transparente sobre el contenido existente.

Actualización: mi ejemplo fue escrito en Java. No debería ser un problema para un desarrollador transferir esto a C #. Solo se trata de cambiar algunas minúsculas a mayúsculas. Ejemplo: stamper.GetUnderContent(1) lugar de stamper.getUnderContent(1) , canvas.SaveState() lugar de canvas.saveState() , y así sucesivamente.