Rendering an image to a pdf is blurry - c#

I must be doing something wrong. I have tried rendering an image to a PDF to both a pdfContext in iOS and a PDF using PDFSharp. When I do it, it's blurry compared to when I open it up in Photoshop or Microsoft's picture preview. So maybe I don't understand what is going on with the image itself. Here is what I know:
Image size is 90 x 20 (w x h). The resolution is 264 ppi.
To draw it in PDFSharp, I do:
XImage image = XImage.FromGdiPlusImage(Properties.Resources.logo);
gphx.DrawImage(image, leftStartDefault, 50, image.PointWidth, image.PointHeight);
I have also tried image.PixelWidth, image.PixelHeight in the above code. Both produce the same blurry result.
In iOS, I do
UIImage *logo = [UIImage imageNamed:#"logo.png"];
[logo drawInRect:CGRectMake(self.frame.size.width - 90 - 60, 20, 90, 20)];
Both produce blurry results. I'm not sure why. I don't know if it's something I am missing with how to choose the size to draw. If I need to ask for a different resolution/size image from our graphics artist, or if it's the way I make the drawing call. If I draw the image at half the size, it is clearer.
e.g.
gphx.DrawImage(image, leftStartDefault, 50, 45, 10);
Any thoughts? thanks.

I realize this is old and perhaps no longer an issue, but I had the same problem.
I found this thread on the PDFSharp forums which was of some use.
As far as I can tell, x pixels on an image in paint does not transfer the same way to y pixels in an image on a pdf (at least in my case). Having an image of 100x100px in paint would apply the same image to the pdf at approximately 153x153px. I have absolutely no idea why this happens, but once I figured out the the factor by which the image size was increased, it became a simple matter to "resize" the image for printing on the pdf.
Like so:
gfx.DrawImage(logo, 0, 0, ApplyTransform(logo.PointWidth), ApplyTransform(logo.PointHeight));
private static double ApplyTransform(double previous)
{
return previous * .6538;
}
EDIT: Upon further research, I believe this is caused by pdf documents not having the concept of pixels in the first place.

Probably, the PDF rasterizing libraries use different, than Photoshop, Windows Viewer ... algorithms of image interpolation, which incorrectly applies for the resulted view. Also they have used different ICC profiles, it also affects the rendering.

Related

Winforms: Capture part of PDF image to OCR

This is a C# winforms question.
The process I am trying to achieve is the following:
Using AxAcroPDFLib I'm loading a pdf file to the form
I want the user to be able to specify a square on that PDF and create a bmp from it
That bmp will then be loaded to a OCR to become text
What is my issue:
Step 1 and 3 are easy to do, the problem is how to allow the user to draw a square on top of the AxAcroPDFLib for a screenshot.
I already got different ways to draw squares on native winform components, but AxAcroPDFLib does not support mouse down, up, move, etc and paint events.
There is the option to convert the PDF to bitmap and display it on a picturebox and deal with events for drawing the square. Problem with that approach is that my PDF's are usually more than two pages, and I would like to avoid the conversion pdf to bmp due to changes to image quality that will impact on OCR.
I came to think that maybe something that works as the windows snippingtool would do the the job. My application would get the screenshot, temporarily save the image on disk (must be a file for OCR), I would then pass it to the OCR and done. Hard part, I could not think on how to take the screenshot of part of the PDF.
Do anyone here have any suggestion to different components or workarounds to deal with the requirement above? I am using Adobe just because it is simple, but maybe there are other components better suited to handle my requirements? I googled but haven't found any free ones, trying to avoid paid options.
Thanks
At some point in this process, the PDF is going to have to be rasterized in order to be passed to the OCR, so I don't totally understand your objection to converting it to a bitmap. If you're okay with Snipping Tool's behavior, then you must be OK with the quality of the PDF control's PDF->screen rasterization. If that resolution is acceptable, why not just capture the control's content to a Bitmap and let the user draw the selection marquee over that Bitmap?
Here is code I'm using to capture a control's contents to a Bitmap in Windows Forms. One caveat is that this is really a screen capture, so any windows or controls that overlap the control's visible area will be captured in the image.
using (Bitmap b = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(b))
{
Point p1 = myControl.PointToScreen(new Point(0, 0));
g.CopyFromScreen(p1.X, p1.Y, 0, 0, size);
}
// do stuff here with your Bitmap
}

Remove Black Border From Scanned Image c#

I have an application that scan Images from scanner but some scanners put a black border around the saved image.
How can I remove that black border?
Thanks so much for your participation.
I’ve had good luck in the past process images using the Magick.NET library. It’s available on Codeplex or you can install it using NuGet in Visual Studio. Documentation for the library is a little sparse, but it’s served me well in the past.
Depending upon the exact nature of the images you’re dealing with, you might be able to do something as simple as crop off the edges where the border is and then add a white (or whatever color; I just assumed that you were scanning text documents or something) border to bring the image back up to a standardized size. If having a standardized size doesn’t matter, then of course you can just leave the image cropped. If that sounds like a viable solution, here’s some code that should accomplish what you need:
using (MagickImage image = new MagickImage(#"path_to_original"))
{
int width = image.Width, height = image.Height;
image.Crop(width - 800, height - 800);
//if the image needs to be brought back up to a standarized size
image.BorderColor = new ColorRGB(System.Drawing.Color.White);
image.Border(100, 100);
image.Write(#"path_to_cropped_image_with_no_more_black_border_around_it");
}
You will, of course need to add your own values for just how much width you need to crop off/add back in.

How to control Excel's scaling of bitmaps

I have a bitmap image and I want to put it in excel. I used this code I found here:
xlWorkSheet.Shapes.AddPicture("C:\\filesystem\\mb2.bmp",
msoFalse, msoCTrue, 0, 0, 518, 390);
But the resulting image is 1.333 times wider and higher. OK, so I can just multiply the dimensions by 0.75 and I get an image in excel with the desired dimensions.
xlWorkSheet.Shapes.AddPicture("C:\\filesystem\\mb2.bmp",
msoFalse, msoCTrue, 0, 0, (float)(518*0.75), (float)(390*0.75));
But that number 0.75 sitting there hard-coded really bothers me. Especially since I've seen this question in which the op's ratio is 0.76. Knowing that this code needs to run on any number of systems with different displays, I want to know how to get the ratio programmatically.
Somewhat also related to this question which has to do with copy-paste without code.
If you are talking about printing, the display is irrelevant.
The dimensions of the image need to be relative to the paper size. The size values in the AddPicture method are in points and are only loosely related to pixels. Points are units if measure that make sense to your printer. The application translates points to pixels for you so you don't need to worry about that.
You can use the InchesToPoints or CentimetersToPoints methods of the Application object to size your image to paper size.

How can I resize an image in C# while retaining high quality?

I found an article on image processing from here: http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing Everything works fine.
I want to keep the high quality when resizing the image. I think if I can increase the DPI value I can achieve this. Does anyone know if this is possible? And if so, how can I implement it in C#?
For starters, it's worth pointing out that there are two general categories of images; vector [e.g. SVG, WMF, Adobe Illustrator and Corel Draw Graphics] and bitmap (also called raster) images [e.g. Bitmap, JPEG and PNG Images].
Vector images are formed from a series of mathematical equations and/or calculations. Bitmap images, on the other hand, are made up of individual dots (pixels) each corresponding to a particular feature on the object the image is taken of.
If it should happen that you want to resize an image, the first thing to consider is if it is a bitmap or vector image. By virtue of the fact that vector images are obtained from calculations, they can be perfectly resized without losing any detail. The case is different for bitmap images. Since each pixel is independent of the other, when you desire to resize it, you are simply increasing or decreasing the source to target pixel ratio.
So in order to double the size of a vector image, simply multiply the target dimensions by two and everything comes out all right. If you should apply the same effect on a bitmap, you are actually increasing each source pixel to cover four pixels (two rows of two horizontal pixels).
Of course, by applying interpolation and filtering, the computer can "smooth" out the edges of the target pixels so they seem to blend into each other and give the appearance of a reasonably resized image but this output is never the same as resizing a vector image; vector images resize perfectly.
You also mentioned DPI in your question. DPI is essentially the number of pixels that correspond to an inch when the image is printed not when it is viewed on a screen. Therefore by increasing the DPI of the image, you do not increase the size of the image on the screen. You only increase the quality of print [which needless to say depends on the maximum resolution of the printer].
If you really desire to resize the image and the image is a bitmap, as a rule of thumb, do not increase the size beyond 200% of the original image's size else you'll lose the quality.
You can see this answer for code to resize bitmap images.
To see a sample vector image, go to this link.
Note Try zooming in and out of the image to see how well it resizes.
A typical bitmap are the StackOverflow sprites. They do not keep their quality resized.
Further Reading
Vector Graphics: http://en.wikipedia.org/wiki/Vector_image
Bitmap Graphics: http://en.wikipedia.org/wiki/Bitmap_image
Simply If the original image is smaller then the re-sized image then there is hardly anything you can do. Rest is a research problem.
This would only be possible if it's a vector graphic. Look into SVG. Otherwise, I think you might need Silverlight or Flex for that part.
What you're asking isn't really possible. You can't enlarge an image while maintaining the same quality.
If you think about an image as a mapped array of pixels (literally, a "bit-map"), this makes sense. The image is saved with a fixed amount of data, and that's all you have to work with when you resize it. Any examples to the contrary (like TV shows, as suggested by one of the comments) are purely fictional.
The best that you can do is set the InterpolationMode property of the Graphics object you're using to do the resizing to "HighQualityBicubic", which is the highest quality smoothing algorithm supported by GDI+ and in fact by every major graphics package on the market. It's the best that even Adobe Photoshop has to offer. Essentially, interpolation means that the computer is calculating the approximate value of the new pixels you're adding to make the image larger from the relative values of neighboring pixels. It's a "best guess" method, but it's the best compromise we've come up with yet.
At the very least, the resulting images won't have "jaggies" or rough, pixelated lines.
Sample code:
Graphics g;
g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// ... insert the rest of your code here
Beyond that, it's worth noting that GDI+ (which the .NET Framework uses internally for graphics routines) works best with image sizes that are multiples of 16. So if it all possible, you should try and make the width and height of your resized images a multiple of 16. This will preserve as much of the original image quality as possible.
The ideal solution is to switch to vector graphics that can be resized at will. Instead of pixel information, they contain mathematical information used to draw or "render" the image. Read more on Wikipedia.
let's try metadata in GDI+, may be it can suit your request

How to serve high-resolution imagery in a low-resolution form using C#

Trying to use 300dpi tif images for display on the web. At the moment, when the user uploads an image, I am dynamically creating a thumbnail. If a page is created referencing the high-res image with a width of 500x500px, can I use the same functionality to convert to a gif/jpg on the fly. What is the impending resolution of the jpg that would be created?
EDIT:
To further explain the usage, the user uploads 300dpi images which are approx 3000x3000 pixels. The user is using these images to create a catalog page which will be used for pdf printing. When they are creating the page, we only need 72dpi images to display to the screen, but for print, need the 300dpi images. Obviously they do not want to add a 3000x3000px image to the page, so it needs to be resized to the correct viewing area, e.g. 500x500px etc.
This boils down to a simple image resize. The discussion of DPIs is just ancillary data to calculate the scale factor.
As #Guffa said, you should do this at the time of the upload so that you can just serve static images in your viewer.
This will be a load on the server:
Load the full image. This will be about 27 MB of memory for your 3000x3000 images.
Resize. Lot's of math done lazily (still CPU intensive).
Compress. More CPU + Cost of writing to your drive.
Since you are already taking the time to generate a thumbnail, you can amortize that cost and this cost by not having to repeat Step 1 above (see the code).
After an image is uplaoded, I would recommend spinning off a thread to do this work. It's a load on the web server for sure, but you're only other option is to devote a second machine to performing the work. It will have to be done eventually.
Here is some code to do the job. The important lines are these:
OutputAsJpeg(Resize(big, 300.0, 72.0), new FileStream("ScreenView.jpg"));
OutputAsJpeg(Resize(big, bigSize, 64.0), new FileStream("Thumbnail.jpg"));
We can resize the big image however we need. In the first line we just scale it down by a fixed scale (72.0 / 300.0). On the second line, we force the image to have a final max dimension of 64 (scale factor = 64.0 / 3000.0).
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
BitmapSource Resize(BitmapSource original,
double originalScale,
double newScale) {
double s = newScale / originalScale;
return new TransformedBitmap(original, new ScaleTransform(s, s));
}
void OutputAsJpeg(BitmapSource src, Stream out) {
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(src));
encoder.Save(out);
}
// Load up your bitmap from the file system or whatever,
// then dump it out to a smaller version and a thumbnail.
// Assumes thumbnails have a max dimension of 64
BitmapSource big = new BitmapImage(new Uri("BigPage0.png",
UriKind. RelativeOrAbsolute));
double bigSize = Math.Max(big.PixelWidth, big.PixelHeight);
OutputAsJpeg(Resize(big, 300.0, 72.0), new FileStream("ScreenView.jpg"));
OutputAsJpeg(Resize(big, bigSize, 64.0), new FileStream("Thumbnail.jpg"));
If I understand what you want - you're trying to make a gif or jpg thumbnail of a very high resolution tif, for web display - if not, I apologize in advance....
If you want the thumbnail to be 500x500px, that is the resolution of the jpg/gif you'll want to create - 500x500, or at least 500x<500 or <500x500 (to fit in the box, unless you want distorted images).
For display on the web, the DPI does not matter. Just use the pixel resolution you wish directly.
Technically the JPG/GIF is created at 72-DPI by the Image classes in .NET. But the DPI really doesn't have any meaning to the browser - it just uses the dimensions 500x500.
When displaying an image on a web, the dpi (or more correctly ppi) setting is irrelevant. It's only the size in pixels that is relevant.
You can convert an image on the fly, but it is very work intensive for the server to do that every time the image is displayed. You should create the sizes that you need when the user uploads the image.

Categories

Resources