I'm drawing a path on a PDF page using PDFsharp. I add all points to an XGraphicsPath path and then draw the path on an XGraphics. However, the XGraphicsPath always closes my path (so it always connects the end point to the begin point). Is it possible to not connect the end points so that I have an "open" path? I coundn't find this functionality in the documentation of PDFsharp.
Thanks in advance!
I haven't tried it myself, but it seems you have to do nothing special to get an open path:
http://pdfsharp.net/wiki/Graphics-sample.ashx#Stroke_an_open_path_12
You do not show any code so no-one else can try your code.
I know you asked this 3 years ago but I have been using GDI+ and PDFSharp some lately and I had this exact problem so maybe I can help someone.
I had a loop drawing a bunch of polylines in GDI+. I decided to try to optimize this by changing a loop of DrawLines calls every time my control was being drawn into a one-time loop of GraphicsPath.AddLines(PointF[]) calls.
As soon as I made this change, calling DrawPath would draw all my lines (which used to be separated) as one long continuous path from start to end.
I added a GraphicsPath.StartFigure() call before the addlines and it broke apart all my polylines and drew them the way I intended.
GraphicsPath myShapes;
for (int i = 0; i < PLineCount; i++)
{
PointF[] points = new PointF[PLineCount];
for (int ii = 0; ii < PLinePointCount; ii++)
{
points[ii] = new PointF(X, Y);
}
myShapes.StartFigure(); // This is what I added to break the line segments apart.
myShapes.AddLines(points);
}
This code won't run as written, you have to add code to provide the numbers of points in the polylines, and the X,Y coordinates of each point. Whether you have predefined shapes or you want to randomly generate them is up to you.
I have verified XGraphics has StartFigure just like GDI+ so I think it likely this will solve your issue.
Here's images of the undesirable version, and the one that was fixed by adding StartFigure before each shape.
GraphicsPath screenshots :
Related
I was able to successfully use the following code to highlight text in an existing PDF:
private static void highlightDiff(PdfStamper stamper, Rectangle rectangle, int page)
{
float[] quadPoints = { rectangle.Left, rectangle.Bottom, rectangle.Right, rectangle.Bottom, rectangle.Left, rectangle.Top, retangle.Right, rectangle.Top };
PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rectangle, null, PdfAnnotation.MARKUP_HIGHLIGHT, quadPoints);
highlight.Color = BaseColor.RED;
stamper.AddAnnotation(highlight, page);
}
The problem is I'm highlighting characters at a time and my guess is a new layer is added every time I call this function because the resulting file size is significantly larger after the program has completed running.
I tried to add the following lines at the end of the function and maybe it's just me but it seemed to have sped up the time it takes the PDF to load when I go to view it but the size of the file still remains exceedingly large.
stamper.FreeTextFlattening = true;
I may try to make my code more efficient and decrease the number of calls I make (if the characters I'm highlighting are next to each other, find the combined rectangle and call) but was wondering if there was another way around this. Thanks in advance!
Each time you execute highlightDiff you add a new highlight annotation to the PDF. Inside the PDF such an annotation is an object like this:
1 0 obj
<<
/Rect[204.68 705.11 211.2 716.11]
/Subtype/Highlight
/Contents()
/QuadPoints[204.68 716.11 211.2 716.11 204.68 705.11 211.2 705.11]
/C[1 0 0]
/P 2 0 R
>>
Furthermore there needs to be a reference to this object from the page description plus an entry in the internal cross references.
Thus, each such call makes the PDF grow by nearly 200 bytes. If you highlight many such individual characters, the file indeed will grow considerably.
I may try to make my code more efficient and decrease the number of calls I make (if the characters I'm highlighting are next to each other, find the combined rectangle and call) but was wondering if there was another way around this.
If you indeed want your highlighting to be done using highlighting annotations, there is not way around this.
If you on the other hand would also accept highlighting rectangles to be drawn in the regular page content, you may see less file size growth using that approach. Even then, though, first combining neighboring rectangles would reduce file size (and PDF viewer resource requirements) considerably.
I'm trying to rotate a polygon in windows forms using C# and below is code written .
Please tell me what wrong in the code, there is no output on windows form.
Before and after rotation polygons not visible.
public void RotatePolygon(PaintEventArgs e)
{
pp[0] = new Point(624, 414);
pp[1] = new Point(614, 416);
pp[2] = new Point(626, 404);
e.Graphics.DrawPolygon(myPen2, pp);
System.Drawing.Drawing2D.Matrix myMatrix1 = new System.Drawing.Drawing2D.Matrix();
myMatrix.Rotate(45, MatrixOrder.Append);
myMatrix.TransformPoints(pp);
e.Graphics.Transform = myMatrix1;
e.Graphics.DrawPolygon(myPen, pp);
}
Thanks
You code does not compile if left unmodified. There are two matrices used - one declared in your method (myMatrix1) attached to the graphics object and one declared outside your method (myMatrix without the 1) used to explicitly transform the point array.
I tried the code with the required changes and it works flawless - I used myMatrix1 for both transformations and the effective rotation angle was, as expected, twice the one specified. So I guess you are using two transformation that cancel if the transformed points end where they began.
There could be this problems:
[1] your pens have no color/thickness (where do you define them?)
[2] your polygone is to big, so you only see the inside of it but not the border. --> Test Graphics.FillPolygon-Methode so you will see if [2] is right
You're both transforming the points and changing the transform matrix for the Graphics object - you need to do one or the other.
You also need to think about the fact that the rotate is going to be happing about (0,0) rather than about some part of the object - you may well need a translate in there too.
Bear in mind that TransformPoints just manipulates some numbers in an array - which you can easily inspect with the debugger - this will be a more effective technique than displaying an invisible object and wondering where it went.
Starting with a much smaller rotation angle (10 deg, perhaps?) may also help with the problem of losing the object - it will be easier to work out what's happening if you haven't moved so far.
I've a image like this (white background and black text). If there is not noise (as you can see: the top and bottom of number line has many noise), Tesseract can recognize number very good.
But when has noise, Tesseract try to recognize it as number and add more number to result. It is really bad. How can I make Tesseract Ignore Noise? I can't make a preprocessing image to make it more contrast or sharp text. This doesn't help anything.
If some tool can to hightlight only string line. It can be really good input to Tesseract. Please help me. Thanks everybody.
You should try eroding and dilating:
The most basic morphological operations are two: Erosion and Dilation.
They have a wide array of uses, i.e. :
Removing noise
...
you could try to down sample your binary image and sample it up again (pyrDown and PyrUp) or you could try to smooth your image with an gaussian blur. And, as already suggested, erode and dilate your image.
I see 3 solutions for your problem:
As already sugested - try using erode and dilate or some kind of blur. It's the simplest solution.
Find all contours (findContours function) and then delete all contours with area less then some value (try different values, you should find correct one quite fast). Note that the value may not be constant - for example you can try to use 80% of average contour area (just add all contours areas, divide it by number of contours and multiply by 0.8).
Find all contours. Create one dimension array of integers, with length equal to your image height. Fill array with zeros. Now for each contour:
I. Find the top and the bottom point (points with the biggest and the smallest value of y coordinate). Let's name this points T and B.
II. Add one to all elements of array which index is between B.y and T.y. (so if B = (1, 4) and T = (3, 11) then add one to array[4], array[5], array[6] ..., array[11]).
Find the biggest element of array. Let's name this value v. All contours for which B.y <= v <= T.y should be letters, other contours - noise.
you can easily remove these noises by using image processing techniques(Morphological operations like erode and dilate) you can choose opencv for this operations.
Do connected component labeling....that is blob counting....all dose noises can never match the size of the numbers....with morphological techniques the numbers also get modified...label the image...count the number of pixels in each labeled region and set a threshold (which you can easily set as you will only have numbers and noises)...cvblob is the library written in C++ available at code googles...
I had similar problem: small noises was cause of tesseract fails. I cannot use open-cv, because I was developing some feature on android, and open-cv was unwanted because of it large size. I don't know if this solution is good, but here is what I did.
I found all black regions in image (points of each region I added to own region set). Then, I check if count of point in this region is bigger than some threshold, like 10, 25 and 50. If true, I make white all points of that region.
I'm working on a text extraction system from PDF files using iTextSharp. I have already created a class that implements ITextExtractionStrategy and implemented methods like RenderText(), GetResultantText() etc. I have studied LocationTextExtractionStrategy class provided by iTextSharp itself as well.
The problem I'm facing is that for a particular PDF document, the RenderText() method reports the horizontal position of a few text chunks incorrectly. This happens for around 15-20 chunks out of a total of 700+ text chunks available on the page. I'm using the following simple code to get text position in RenderText():
Vector curBaselineStart = renderInfo.GetBaseline().GetStartPoint();
LineSegment segment = renderInfo.GetBaseline();
TextChunk location = new TextChunk(renderInfo.GetText(), segment.GetStartPoint(), segment.GetEndPoint(), renderInfo.GetSingleSpaceWidth());
chunks.Add(location);
After collecting all the text chunks, I try to draw them on a bitmap, using Graphics class and the following simple loop:
for (int k = 0; k < chunks.Count; k++)
{
var ch = chunks[k];
g.DrawString(ch.text, fnt, Brushes.Black, ch.startLocation[Vector.I1], bmp.Height - ch.startLocation[Vector.I2], StringFormat.GenericTypographic);
}
The problem happens with the X (horizontal) dimension only for these few text chunks. They appear slightly towards the left than their actual position. Was wondering if there's something wrong with my code here.
Shujaat
Finally figured this out. In PDF, computing actual text positions is more complicated than simply getting the baseline co-ordinates. You need to incorporate character and word spacing, horizontal and vertical scaling and some other factors too. I did some correspondance with iText guys and they have now incorporated a new method in TextRenderInfo class that provides actual character-by-character positions by taking care of all of the above factors.
I have an dynamic List of Point, new Point can be added at any time. I want to draw lines to connect them using different color. Color is based on the index of those points. Here is the code:
private List<Point> _points;
private static Pen pen1 = new Pen(Color.Red, 10);
private static Pen pen2 = new Pen(Color.Yellow, 10);
private static Pen pen3 = new Pen(Color.Blue, 10);
private static Pen pen4 = new Pen(Color.Green, 10);
private void Init()
{
// use fixed 80 for simpicity
_points = new List<Point>(80);
for (int i = 0; i < 80; i++)
{
_points.Add(new Point(30 + i * 10, 30));
}
}
private void DrawLinesNormal(PaintEventArgs e)
{
for (int i = 0; i < _points.Count-1; i++)
{
if (i < 20)
e.Graphics.DrawLine(pen1, _points[i], _points[i + 1]);
else if (i < 40)
e.Graphics.DrawLine(pen2, _points[i], _points[i + 1]);
else if (i < 60)
e.Graphics.DrawLine(pen3, _points[i], _points[i + 1]);
else
e.Graphics.DrawLine(pen4, _points[i], _points[i + 1]);
}
}
I find this method is not fast enough when I have new points coming in at a high speed. Is there any way to make it faster? I did some research and someone said using GraphicsPath could be faster, but how?
[UPDATE] I collect some possible optimizations:
Using GrahpicsPath, Original Question
Change Graphics quality ( such as SmoothingMode/PixelOffsetMode...), also call SetClip to specify the only necessary region to render.
You won't be able to squeeze much more speed out of that code without losing quality or changing to a faster renderer (GDI, OpenGL, DirectX). But GDI will often be quite a bit faster (maybe 2x), and DirectX/OpenGL can be much faster (maybe 10x), depending on what you're drawing.
The idea of using a Path is that you batch many (in your example, 20) lines into a single method call, rather than calling DrawLine 20 times. This will only benefit you if you can arrange the incoming data into the correct list-of-points format for the drawing routine. Otherwise, you will have to copy the points into the correct data structure and this will waste a lot of the time that you are gaining by batching into a path. In the case of DrawPath, you may have to create a GraphicsPath from an array of points, which may result in no time saved. But if you have to draw the same path more than once, you can cache it, and you may then see a net benefit.
If new points are added to the list, but old ones are not removed (i.e. you are always just adding new lines to the display) then you would be able to use an offscreen bitmap to store the lines rendered so far. That way each time a point is added, you draw one line, rather than drawing all 80 lines every time.
It all depends on exactly what you're trying to do.
Doesn't really help to improve performance, but i would put the pens also into a list and writing all this lines in this way:
int ratio = _points.Count / _pens.Count;
for (int i = 0; i < _points.Count - 1; i++)
{
e.Graphics.DrawLine(_pens[i / ratio], _points[i], _points[i + 1]);
}
This is about as fast as you're going to get with System.Drawing. You might see a bit of gain using Graphics.DrawLines(), but you'd need to format your data differently to get the advantage of drawing a bunch of lines at once with the same pen. I seriously doubt GraphicsPath will be faster.
One sure way to improve speed is to reduce the quality of the output. Set Graphics.InterpolationMode to InterpolationMode.Low, Graphics.CompositingQuality to CompositingQuality.HighSpeed, Graphics.SmoothingMode to SmoothingMode.HighSpeed, Graphics.PixelOffsetMode to PixelOffsetMode.HighSpeed and Graphics.CompositingMode to CompositingMode.SourceCopy.
I remember a speed test once where someone compared Graphics to P/Invoke into GDI routines, and was quite surprised by the much faster P/Invoke speeds. You might check that out. I'll see if I can find that comparison... Apparently this was for the Compact Framework, so it likely doesn't hold for a PC.
The other way to go is to use Direct2D, which can be faster yet than GDI, if you have the right hardware.
Too late, but possibly somebody still need a solution.
I've created small library GLGDI+ with similiar (but not full/equal) GDI+ syntax, which run upon OpenTK: http://code.google.com/p/glgdiplus/
I'm not sure about stability, it has some issues with DrawString (problem with TextPrint from OpenTK). But if you need performance boost for your utility (like level editor in my case) it can be solution.
You might wanna look into the Brush object, and it's true that you won't get near real-time performance out of a GDI+ program, but you can easily maintain a decent fps as long as the geometry and number of objects stay within reasonable bounds. As for line drawing, I don't see why not.
But if you reach the point where you doing what you think is optimal, and all that is, drawing lines.. you should consider a different graphics stack, and if you like .NET but have issues with unmanaged APIs like OpenGL and DirectX, go with WPF or Silverlight, it's quite powerful.
Anyway, you could try setting up a System.Drawing.Drawing2D.GraphicsPath and then using a System.Drawing.Drawing2D.PathGradientBrush to a apply the colors this way. That's a single buffered draw call and if you can't get enough performance out of that. You'll have to go with something other entirely than GDI+
Not GDI(+) at all, but a completely different way to tackle this could be to work with a block of memory, draw your lines into there, convert it to a Bitmap object to instantly paint where you need to show your lines.
Of course this hinges in the extreme on fast ways to
draw lines of given color in the memory representation of choice and
convert that to the Bitmap to show.
Not in the .NET Framework, I think, but perhaps in a third party library? Isn't there a bitmap writer of sorts in Silverlight for stuff like this? (Not into Silverlight myself that much yet...)
At least it might be an out of the box way to approach this. Hope it helps.
I think you have to dispose pen object and e.Graphics object after drawing.
One more thing it is better if you write your drawLine code inside onPaint().
just override onPaint() method it support better drawing and fast too.