I am working on fixing a problem in a program (ReportGenerator) which seems to be an issue with the printed report, either being extremely poor quality or much too large.
This project involves the use of two threads that synchronize the task of preparing the pages for preview and printing them. The start points for these two threads are preventing me from using PrintPageEventArg (an input of PrintDocument_PrintPage) at the proper time in order to use e.graphics that can improve the print quality. To try and work around this issue I created a graphic from a bitmap (graphics.FromImage(bitmap)) but this creates its own problems. In order to use this event I must change the start points for the threads causing even further problems. I have a limited time and I cannot take the time to completely re-write this project. Are there any suggestions as to what I may be able to try in order to find a workaround?
This is a general overview of the project, including the threads and my methods:
Print Show Dialog -> ok
Print_Document_BeginPrint -> Thread begins here
3.Create a graphic from bitmap(graphics.FromImage(bitmap))
From here if I could use PrintPageEventArg my issues would be solved but I am not that lucky
Alternatively I could create a bitmap and draw a prepared graphic on it (graphics.Draw(..bitmap...)) saving this image on the system and then restoring it in PrintDocument_PrintPage ,This method allows me to use PrintPageEventArg but only after I restore the previously created graphics and print them.
I have asked questions related to this problem before on these links.
how to improve printed text quality after using "graphics.DrawString"?
save an image as a bitmap without losing quality
Any help would be greatly appreciated. Thanks in advance.
Confusing.
Why don't you draw into the Graphics created from printer HDC? If you draw into a bitmap Graphics first, the bitmap needs to be of high resulition (e.g. 300-dpi) to get better printing quality. But printing could be slow due to sending large amount of image to printer.
Related
In one of my windows application, I am in need of a module where we want to detect the coverage of the page being printed.
Right now, I am using Print Queue Watch library for detecting the printing job events.
But is there a way to detect how much part of the page being printed.?
Thanks in advance.
Since you progammed your application in C# using WinForms, I assume you used a PrintDocument and your printing takes place in a PrintPage event using PrintPageEventArgs.Graphics.
If this is the case, it should be possible to refractor the code which prints into a seperate method, which takes a an instance of Graphics as parameter (and probably additional parameters, like page size and so on).
Then, you could create a (white) Bitmap object with sufficient size (and the same aspect ratio as your paper), and supply it to the method described above. Then, you can go and count the pixels which have been colored and thus, caculate the percentage of the page which the printer would have printed on.
Keep in mind that you probably have to respect the margin around the printing area and different paper sizes for your calculation.
If the refractoring of the code prooves to heavy, you could create a wrapper for the Graphics object, which "duplicates" all draw calls to a Bitmap while printing, and then continue with counting the pixels.
(This answer assumes you want to monitor your application, not other applications on the system)
I know one way to do that. You need to create a Print Processor. The print processor is a driver that can change or read data before it is sent to the Print Monitor (This is the driver that emit things in proprietary format to the printer port).
See here a global view of the printing architecture http://technet.microsoft.com/en-us/library/cc976755.aspx.
Here is a description of what a Printer Processor does: https://serverfault.com/questions/304536/what-is-the-reason-for-choosing-a-different-print-processor.
How to change the print processor by using PowerShell: http://blogs.technet.com/b/chad/archive/2012/10/31/tip-52-mixing-the-old-and-new-setting-a-printer-s-print-processor-using-powershell-wmi-and-setprinter-exe.aspx
And here is a sample on how to do it (i.e., to create a print processor): http://code.msdn.microsoft.com/windowshardware/Genprint-4a71134f.
To make it work you will need to redirect GdiPlayPageEMF to a bitmap on memory, then you can count its pixels before it is send to the handle of the printer. You can search about GdiPlayPageEMF on Google, there will be interesting results on how to do this kind of thing.
Also, there are a lot of good info about printing here http://www.undocprint.org/winspool/spool_files#reading_job_data.
I hope this helps.
I face one critical Performance problem in my Direct2D application. I make use of Direct2D to draw my graph using PathGeometry to get better performance and to achieve the clean rendering in Windows 8.1.
While creating the DeviceResources, i create the PathGeometry using the Factory interface. Then i set the Graph points to draw my graph in the output surface. Finally rendered ImageSource will be used as the source for my Image element in the XAML.
I just followed the below sample link to achieve my scenario.
http://code.msdn.microsoft.com/windowsapps/XAML-SurfaceImageSource-58f7e4d5
The above sample helped me a lot to get the ImageSource output from the Direct2D and finally used across the XAML/C# app.
Lets come to my problem. I use more than 24 graphs in the single Page of my Windows Store application. This graph allows the user to manipulate in Left and Right position and also allows to scale to the particular zoom level.
Hence whenever user tries to manipulate the graph , i just set the Translation and Scaling matrix to the TransformedPathGeometry instead of creating the new one for each and every time.
ID2D1TransformedGeometry *m_pTransformedGeometry;
pFactory->CreateTransformedGeometry(graphgeometry, combinedMatrix, &m_pTransformedGeometry);
Finally i draw the TransformedGeometry using the DrawGeometry method.
I checked my application using the Performance analysis tool in the VisualStudio2013. I could see that in the particular peek level, It takes more than 80% of running time to call the m_d2deviceContext->EndDraw() method. I attached the below screen shot to get more idea in this performance output.
Is there any way to increase this performance considerably ?
Could you please anyone help me in this ?
Regards,
David C
THere is a difference between slow performance and time spend.
If your draw method does more work than other parts, can mean that this method is slow but it also can mean that your other parts don't need a lot of cpu.
88.2% tells you only that you spend more time drawing that stuff than doing other stuff.
Use an timer to determine if your draw is slow.
"i just set the Translation and Scaling matrix to the
TransformedPathGeometry instead of creating the new one for each and
every time."
I hope you use world transform? Else you overwrite the pointer without releasing it before, providing a memory leak. You cannot change the matrix of a geometry directly, you have to recreate it each time, or if you can, you apply the transform to the entire world.
I am currently working in Windows Form Apps and am making what will essentially be a map editor for a game. The way i have gone about this is by having a central TabControl where each TabPage contains a custom PictureBox control and all the other UI controls are around this central TabControl. The PictureBox uses its Paint event to draw everything that is placed on the map, and therefore draws multiple images of many sizes, rotations and scales etc to the single PictureBox. This has all gone well so far. The TabPage is essentially used as a view window for the PictureBox and is of size (1280x720).
The problem is with the scale to which the maps are being produced. The avg (and also maximum) map size on screen is around 19200x10800px and can be made up of hundreds of items at any one point. When drawing just a backdrop image of size 19200x10800px the PictureBox starts to flicker when it redraws and makes the program unusable. As the map is so big you are able to pan around them and this is where the flickering really shows. Also i do not want to use a 19200x10800px image source if possible for the sake of file sizes and the scaled image quality isn't an issue at all.
I have done heaps of reading on why this might be and feel like I have tried everything up until this point. So far ive tried:
Having the background image only 1920x1080 and scaling it up by 10x
Starting with a 1920x1080 image, programatically resizing it and drawing this image
Slicing the background into multiple segments (i tried many different amounts) and drawing only the ones that the view window can see (tried this for both a small(1080p) and large(10800p) images)
Using graphics clipping so that only the things on screen would be drawn
Used Double Buffering on both the picturebox and the form that the picturebox is on
Converting the image at initialisation to an "optimised bitmap" with faster formatting and then drawing the bitmap
I've probably tried a couple other things along with minor optimisations but its taken me so long ive forgotten the rest. From what i've read its most likely something to do with the control redrawing too slowly for some sort of performance reason or a limitation with picturebox's, however exactly what is going on i cannot tell due to lack of experience with form apps controls.
Currently to draw the background in the Paint event i have either:
g.DrawImage(image, new Rectangle(0, 0, (int)(image.Size.Width * levelScale), (int)(image.Size.Height * levelScale)));
or
g.ScaleTransform(levelScale, levelScale);
g.DrawImage(image, new Rectangle(0, 0, (int)(image.Size.Width), (int)(image.Size.Height)));
Where g is the Graphics object.
Have I hit the limit of Win form apps capabilities or is there something i may be missing?
Any and all help appreciated,
Thanks in advance.
Just for formality I though id answer my own question just in case anyone else would like to know the outcome.
Based off the overwhelming consensus that winforms was just not made to do the things I was trying to do with it I decided I had to move to some other platform. Suggested to me was WPF, DirectX and OpenGL but after some extensive searching around I found what I think is the optimal solution.
In order to utilise the power of DirectX hardware acceleration MS has made it so that you can embed XNA graphics devices into a winforms application. Essentially you can create custom controls that run in the normal winform style that have access to a much higher caliber of graphics control. In this manner (with a bit of extra work) I have replaced the picturebox I was using with a custom graphics control which handles all of the drawing. This has worked very well, and on the up side i havent had to take too much of a hit to my development time.
For those looking for more info refer to this question which has further links that should help. Once again thanks to all those who gave their advice!
This is a quoted answer from the URL at the bottom. There are code examples at the link at the bottom. Hope this is helpful; not sure if you tried this yet and maybe it'll help you get a little more juice out of the existing picturebox control. As explain in the other answers, it sounds like you will be forced to a more powerful solution in the near future regardless (DirectX/OpenGL or WPF)
** Partial quote from http://social.msdn.microsoft.com/Forums/en-US/68ecd1f6-2eeb-45ce-a881-24c62145ab0e/c-picturebox-problems
"I'd guess the real problem is that it takes too long to redraw the images. GDI+ is pretty slow, it doesn't use any video hardware acceleration. To speed it up, be sure to avoid rescaling the drawing and to use the Format32PArgb format. It is about 10 times faster than any other format. Load the images into a Bitmap with the right format first."
If you have a LOT of items (Maybe realized as controls), forget about the standard event mechanism of Windows Forms. Some time ago, i've written a logic gate editor/simulator which supported lots of thousands of gates in the editor and was really fast. There, I've used the canvas and draw the gates as custom "images" instead of putting them as controls. You'll have to write a custom GetUnderlyingGate function which resolves the current gate / tile (Is your editor a tilemap editor?) from a coordinate array. Also, there were some visible area optimizations.
Maybe, when i'm back home, I'll upload some sourcecode and notify you.
I'm developing a C# software that is able to show previews for files. Basically, there is a tree at the left that shows the disk filesystem entries, and a panel on the right that will show a preview of files selected in the tree, in a resizable panel that contains a docked PictureBox. Initially I only show preview for image files.
This software is designed for game developers, so I need to support all the image formats, I will use the great ImageMagick library for this purpose. The key is that some image files could be big, very big so, I have several questions, about performance and memory consumption.
Do I need to thread the load of the picture? Always, or only if the picture is very big?
Would be a correct if I load the picture directly in the Picturebox, or should I calculate a smaller size image (like a thumbnail or something similar), save it to disk, and then, show it?
Someone knows where can I download big picture files to test my preview with really very large files.
Imo always thread a work like this, there is little point in trying to decide what is big; for images that of are talking about I would of thought most would be enough that under the wrong conditions (computer is spending resources on other processes, not just yours) it could cause a perceivable pause in the UI thread.
Without knowing more, I would just test your implementation when it does the basic stuff and make a judgement call. There is also the question of required quality and desktop resolution of the user - so perhaps this should be configurable in some way.
Imo there could be no better place than PolyCount, specifically look in these forums:
http://www.polycount.com/forum/forumdisplay.php?f=42 &
http://www.polycount.com/forum/forumdisplay.php?f=60
I'm creating a cad viewer which deals with very large image files and I am trying to optimise it for as high a framerate and low a memory footprint as possible.
It uses GDI+ for rendering onto a panel.
It's current flaw is with image rendering. Some of the files I'm using reference images which are particularly big (8000x8000 pixels). I've optimised the memory usage by only loading them when they become visible and disposing of them when they're not. This reduces the chance of the program running out of memory but prevents the images from being loaded and unloaded too often; however rendering the images themselves (context.DrawImage) still carries a very large overhead.
I'm now exploring ways of blitting the images into a smaller buffer of some sort, rendering this (generally much smaller) buffer, and then refreshing/rebuilding it when the zoom level changes significantly.
The problem is, I can't find any provision for this in GDI whatsoever. Can anyone suggest how I could achieve it?
I don't think GDI is designed for such high-speed updates of images. If you are trying to scroll the image, and tracking the mouse with each move, try to shift sections of the image and fill in the space opened up by the shift. Essentially reuse the tricks that programmers used when smoothly scrolling/panning graphics at a time when CPU's are slow and RAM is small.
If you're creating a new graphics application that needs a high framerate and are looking for suggestions, then I suggest abandoning GDI+ and using WPF. WPF uses hardware acceleration and supports retained-mode graphics; this has much better performance for less work than GDI+.
If there is some limitation that forbids WPF, please explain it in your question. This is relevant because such limitations can also impact GDI+ drawing.
GDI Binned in favour of Direct3D as 3D elements came into the equation anyway. Images turned into single thumbnails and larger tiles that are loaded in/out as required.
I faced a similar problem when developing my own GIS application. The best solution I found for this (even when using WPF) is to tile big images and display only the portions that are visible. This is being said, I would switch to WPF not only for the reasons given in the above answers but also for the good imaging support offered. See this link for more information