According to this post (Removing Watermark from PDF iTextSharp) , #mkl code works fine for ExGstate graphical watermarks but I have tested this code to remove watermark from some files which have Text based watermarks behind PDF contents (like this file : http://s000.tinyupload.com/index.php?file_id=05961025831018336372)
I have tried multiple solutions that found in this site but get no success.
Can anyone help to remove this watermark types by changing above #mkl solution?
thanks
Just like in the case of the question the OP references (Removing Watermark from PDF iTextSharp), you can remove the watermark from your sample file by building upon the PdfContentStreamEditor class presented in my answer to that question.
In contrast to the solution in that other answer, though, we do not want to hide vector graphics based on some transparency value but instead the writing "Archive of SID" from this:
First we have to select a criterion to recognize the background text by. Let's use the fact that the writing is by far the largest here. Using this criterion makes the task at hand essentially the iTextSharp/C# pendant to this iText/Java solution.
There is a problem, though: As mentioned in that answer:
The gs().getFontSize() used in the second sample may not be what you expect it to be as sometimes the coordinate system has been stretched by the current transformation matrix and the text matrix. The code can be extended to consider these effects.
Exactly this is happening here: A font size of 1 is used and that small text then is stretched by means of the text matrix:
/NxF0 1 Tf
49.516754 49.477234 -49.477234 49.516754 176.690933 217.316086 Tm
Thus, we need to take the text matrix into account. Unfortunately the text matrix is a private member. Thus, we will also need some reflection magic.
Thus, a possible background remover for that file looks like this:
class BigTextRemover : PdfContentStreamEditor
{
protected override void Write(PdfContentStreamProcessor processor, PdfLiteral operatorLit, List<PdfObject> operands)
{
if (TEXT_SHOWING_OPERATORS.Contains(operatorLit.ToString()))
{
Vector fontSizeVector = new Vector(0, Gs().FontSize, 0);
Matrix textMatrix = (Matrix) textMatrixField.GetValue(this);
Matrix curentTransformationMatrix = Gs().GetCtm();
Vector transformedVector = fontSizeVector.Cross(textMatrix).Cross(curentTransformationMatrix);
float transformedFontSize = transformedVector.Length;
if (transformedFontSize > 40)
return;
}
base.Write(processor, operatorLit, operands);
}
System.Reflection.FieldInfo textMatrixField = typeof(PdfContentStreamProcessor).GetField("textMatrix", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
List<string> TEXT_SHOWING_OPERATORS = new List<string>{"Tj", "'", "\"", "TJ"};
}
The 40 has been chosen with that text matrix in mind.
Applying it like this
[Test]
public void testRemoveBigText()
{
string source = #"sid-1.pdf";
string dest = #"sid-1-noBigText.pdf";
using (PdfReader pdfReader = new PdfReader(source))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(dest, FileMode.Create, FileAccess.Write)))
{
PdfContentStreamEditor editor = new BigTextRemover();
for (int i = 1; i <= pdfReader.NumberOfPages; i++)
{
editor.EditPage(pdfStamper, i);
}
}
}
to your sample file results in:
Related
I am using iText 7.2.1.
I am trying to add some small icons (drawn by code) in my text. I find if small icons are added into my text, it's hard to have uniform line space.
If all elements of a paragraph are texts, I can just set SetFixedLeading() then no matter how big the font sizes are, my lines have always the same height.
But when I add some small icons inside my paragraph, SetFixedLeading() no longer works.
What I want is like the "Line spacing" option in Microsoft Word. If I give it a fixed value, it treats embedding images and texts equally so I always get fixed line spacing.
The following is my code:
using iText.Kernel.Colors;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Layout;
using iText.Kernel.Pdf.Xobject;
using iText.Layout.Element;
using iText.Kernel.Geom;
using iText.Kernel.Font;
using iText.IO.Font;
namespace iTextTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var writer = new PdfWriter("test.pdf");
var pdf_doc = new PdfDocument(writer);
var doc = new Document(pdf_doc, iText.Kernel.Geom.PageSize.DEFAULT, false);
// Make a text of various sizes
var mixed_paragraph = new Paragraph();
for (int i = 0; i < 100; i ++)
{
var style = new Style();
var size = (Math.Sin(i) + 2) * 10;
style.SetFontSize((float)size);
mixed_paragraph.Add(new Text("A").AddStyle(style));
}
// Make a 20x20 icon
var bounds = new iText.Kernel.Geom.Rectangle(0, 0, 20, 20);
var xobj = new PdfFormXObject(bounds);
var pdf_canvas = new PdfCanvas(xobj, pdf_doc);
pdf_canvas.SetFillColor(ColorConstants.RED);
pdf_canvas.Rectangle(0, 0, 20, 20);
pdf_canvas.Fill();
var icon = new iText.Layout.Element.Image(xobj);
mixed_paragraph.Add(icon);
// Fixed leading
mixed_paragraph.SetFixedLeading(10);
doc.Add(mixed_paragraph);
doc.Close();
pdf_doc.Close();
writer.Close();
MessageBox.Show("OK");
}
}
}
This is what it looks like. The second line is right but the third line has more space than fixed leading 10.
I need this because, in my case, I need some small rectanglular icons that each contain two lines of integers and other info.
These icons have bigger height than my text (or else it's hard to read), but theoretically they can still fit because my text has enough spacing.
Unfortunately, my line spaces become uneven. Fixed leading seems not affecting non-text images, so lines with icons have wider line spaces.
I have been considering a workaround: add empty spaces in text and put icons at these fixed positions. It's still hard. I don't know how to get these positions.
anyone could tell me why this generate a black only animated gif?
the code also output each in memory generated gif to show that they are different
public static void Test()
{
Image<Rgba32> img = null;
Image<Rgba32> gif = null;
TextGraphicsOptions textGraphicsOptions = new TextGraphicsOptions(true);
SolidBrush<Rgba32> brushYellow = new SolidBrush<Rgba32>(Rgba32.Yellow);
FontCollection fonts = new FontCollection();
fonts.Install(fontLocation);
Font font = fonts.CreateFont("Liberation Mono", PngFontHeight, FontStyle.Regular);
gif = new Image<Rgba32>(400, 400);
for (int i = 0; i < 10;++i)
{
img = new Image<Rgba32>(400, 400);
img.Mutate(x => x.Fill(Rgba32.Black));
img.Mutate(x => x.DrawText(textGraphicsOptions, i.ToString(), font, brushYellow, new PointF(1,1)));
gif.Frames.AddFrame(img.Frames[0]);
using (FileStream fs = File.Create(Path.Join(Program.workingDirectory, string.Format("Test-{0}.gif", i))))
{
img.SaveAsGif(fs);
}
img.Dispose();
}
using (FileStream fs = File.Create(Path.Join(Program.workingDirectory, "Test.gif")))
{
gif.SaveAsGif(fs);
}
}
if I code it to load each individual physical file using this code it make the animated gif as expected.
I want to create the animated gif in memory only.
When you create an Image<>...
gif = new Image<Rgba32>(400, 400);
...gif.Frames[0] is a "transparent black" frame (each pixel's RGBA value is #00000000). The additional frames you create in your for loop and add with...
gif.Frames.AddFrame(img.Frames[0]);
...become gif.Frames[1] through gif.Frames[10], for a total of 11 frames.
The GIF encoder uses GifColorTableMode to decide if a color table is generated for each frame or the color table for the first frame is used for all frames. The combination of the default value, GifColorTableMode.Global, plus that first transparent frame results in an 11-frame .gif file with only one color, that same "transparent black". This is why your yellow text doesn't appear and every frame looks the same.
To solve this, at some point before you save the file you need to remove that initial transparent frame so it doesn't influence color table calculations and because it's not part of your animation, anyways...
gif.Frames.RemoveFrame(0);
You may also want to change to GifColorTableMode.Local so your .gif file contains color tables reflecting all of the colors rendered...
gif.MetaData.GetFormatMetaData(GifFormat.Instance).ColorTableMode = GifColorTableMode.Local;
...although your 10 frames each use almost the same set of colors so if file size is a greater concern than color representation you might leave that property alone. Generating your 400 × 400 animation with GifColorTableMode.Global produces a 9,835-byte file whereas GifColorTableMode.Local produces a 16,703-byte file; 70% bigger but I can't tell the difference between them.
Related issue on GitHub
By the way, since I found this along the way, if you wanted to change the duration of the animated frames you would do so using another GetFormatMetaData() method similar to the one shown above...
GifFrameMetaData frameMetaData = img.MetaData.GetFormatMetaData(GifFormat.Instance);
frameMetaData.FrameDelay = 100;// 1 second
When attempting to render Chinese (or other symbolic) text. SkiSharp will render boxes instead of the correct Chinese characters. Obviously the font that Skia is using by default doesn't support those characters. So we have to assign our own SKTypeface using a font that does support those characters.
My initial strategy was to simply include the necessary fonts to render those characters, which worked fine. However when supporting multiple different symbolic languages with their own fonts, the application size grows dramatically (about 15 mb per font).
So thinking about this a bit more... The default platform fonts seems to support any of these symbolic characters just fine. What I mean by this, is that the font that is used by default renders Buttons, labels and titles perfectly.
So my current thought is, why can't I just pass, whatever font that is into a SKTypeface for my control?
The problem is that I don't know how to get ahold of whatever that fall-back or default font is in order to create a new SKTypeface with it.
My Question
How can I create an SKTypeface from the same font that is rendering these buttons, labels and titles just fine?
note: if you need anything from me to help you understand the problem
or solve the problem just let me know.
You should be able to use SKFontManager.MatchCharacter or one of its overloads in order to:
Use the system fallback to find a typeface for the given character.
Below is an example based on SkiaSharp WindowsSample's TextSample:
public class TextSample : SampleBase
{
// ...
protected override void OnDrawSample(SKCanvas canvas, int width, int height)
{
canvas.DrawColor(SKColors.White);
const string text = "象形字";
var x = width / 2f;
// in my case the line below returns typeface with FamilyName `Yu Gothic UI`
var typeface = SKFontManager.Default.MatchCharacter(text[0]);
using (var paint = new SKPaint())
{
paint.TextSize = 64.0f;
paint.IsAntialias = true;
paint.Color = (SKColor)0xFF4281A4;
paint.IsStroke = false;
paint.Typeface = typeface; // use typeface for the first one
paint.TextAlign = SKTextAlign.Center;
canvas.DrawText(text, x, 64.0f, paint);
}
using (var paint = new SKPaint())
{
// no typeface here
paint.TextSize = 64.0f;
paint.IsAntialias = true;
paint.Color = (SKColor)0xFF9CAFB7;
paint.IsStroke = true;
paint.StrokeWidth = 3;
paint.TextAlign = SKTextAlign.Center;
canvas.DrawText(text, x, 144.0f, paint);
}
}
}
And below is the output
I have a problem with regards on the page orientation of the paper size.
I have a pdf file which contains portrait and landscape page.
this code works perfectly.
string FileLocation = "c:\\Temp\\SomeFile.pdf";
string WatermarkLocation = "c:\\Temp\\watermark.gif";
Document document = new Document();
PdfReader pdfReader = new PdfReader(FileLocation);
PdfStamper stamp = new PdfStamper(pdfReader, new FileStream(FileLocation.Replace(".pdf","[temp][file].pdf"), FileMode.Create));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(WatermarkLocation);
img.SetAbsolutePosition(250,300); // set the position in the document where you want the watermark to appear (0,0 = bottom left corner of the page)
PdfContentByte waterMark;
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
waterMark = stamp.GetUnderContent(page);
waterMark.AddImage(img);
}
stamp.FormFlattening = true;
stamp.Close();
// now delete the original file and rename the temp file to the original file
File.Delete(FileLocation);
File.Move(FileLocation.Replace(".pdf", "[temp][file].pdf"), FileLocation);
since I'm using absolute value to set the image position.
img.SetAbsolutePosition(250,300);
How can T set the image position if the page is landscape or portrait?
note: One pdf with landscape and portrait page orientation.
Is there by chance that I can use if statement?
if (//paper is landscape)
{
//code here
}
else
{
//code here
}
What do you want to achieve?
Normally, iText takes into account the value of the page rotation. This means that when a page is rotated, the coordinates will be rotated too.
If you want to overrule this, you can add this line:
stamper.RotateContents = false;
This is explained in Chapter 6 of my book. You can try this example to see the difference:
No rotation, text added normally: hello1.pdf
Rotation, text added normally ( = rotated): hello2.pdf
Rotation, text added with rotation ignored: hello3.pdf
Of course, this assumes that a rotation was defined for the pages. Sometimes, landscape is mimicked by defining a different page size instead of defining a rotation.
In that case, you should also read Chapter 6 because it explains how to get the MediaBox of a document. see the example PageInformation that introduces methods such as GetPageSize(), GetRotation() and GetPageSizeWithRotation().
This is all documented, but if it doesn't answer your question, please clarify. As demonstrated in the example, the rotation is taken into account by default when adding new content, so maybe I misunderstood the question.
I am developing a barcode generating web application using asp.net/c# ,I was wondering if it is better to use barcode library or a barcode font will be just enough.I have come across some samples but when using barcode font I found there is an asterisk(*) in front of the each code used for generating barcode.And I dint find any free barcode libraries. I want to generate code 39 or 93. Please help me decide
try jquery-barcode
Its a javascript library to generate bar codes. Check out this question for other alternatives.
Here is an extension method I am using that doesn't require you to install the font:
public static Image GetBarCode(this string data, int fontSizeEm)
{
data = "*" + data + "*";
Image img = null;
Graphics drawing = null;
try
{
using (var pfc = new PrivateFontCollection())
{
pfc.AddFontFile(#"{{PATH TO YOUR FONT FILE}}");
using (var myfont = new Font(pfc.Families[0], fontSizeEm))
{
img = new Bitmap(1, 1);
drawing = Graphics.FromImage(img);
var textSize = drawing.MeasureString(data, myfont);
img.Dispose();
drawing.Dispose();
img = new Bitmap((int) textSize.Width, (int) textSize.Height);
drawing = Graphics.FromImage(img);
drawing.DrawString(data, myfont, new SolidBrush(Color.Black), 0, 0);
}
drawing.Save();
}
return img;
}
catch
{
//Handle exception
return null;
}
finally
{
if(drawing!= null)
drawing.Dispose();
}
}
In my experience, libraries that generate barcodes via graphic primitives like rectangles are far superior to barcode fonts. Reasons:
Fonts are much larger, often orders of magnitude, and take much longer to transmit. This is especially problematic on serial connections.
The barcodes fonts produce are often less accurate as printers may try to anti-alias the bars.
Fonts are subject to things like styles, word-wrapping, font substitution, and other effects that make them difficult to control.
There are plenty of free barcode image libraries. If you didn't find any you did not look very well.
Barcode 3 of 9 requires guard bars at the start and end of the code so the scanner knows where the code starts and ends. When printing the legend for a code 3 of 9, these guard bars are traditionally shown as asterisks. These asterisks are only for humans reading the legend, they are not part of the code and in fact an asterisk is not a legal code 3 of 9 character. If you remove the guard bars the scanner would not be able to read the barcode.