MVC3 resize image without losing quality? - asp.net-mvc-3

Hello everybody I would like to ask how can I resize an image without losing quality?
Here is my controller method
var fileName = DateTime.Now.ToString("MM.dd.yyyy HH.mm.ss") + Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/uploads/"), fileName);
file.SaveAs(path);
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath("~/uploads/") + fileName);
System.Drawing.Image thumb = img.GetThumbnailImage(97, 114, null, IntPtr.Zero);
img.Dispose();
thumb.Save(Server.MapPath("~/uploads/") + fileName);

There are some really good image resizing libraries out there - I would use one of those. I'm using ImageResizing on one of my projects and the results have been pretty good. Bertrand LeRoy has done some benchmarking of some of the main libraries, which you might find useful.

Related

iText Image and transparency

I'm trying to add a PNG image to an existing pdf, but the transparency is converted to black color.
PdfReader reader = new PdfReader(pdfPath);
File f = new File(pdfPath);
String result = f.getParent() + File.separator + UUID.randomUUID().toString() + ".pdf";
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(result));
Image image = Image.getInstance(ImageIO.read(new File(imagePath)), null);
PdfImage stream = new PdfImage(image, null, null);
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(30, 300);
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image);
stamper.close();
reader.close();
How can I keep transparency?
First this: I am violating the policy at iText Software by answering this question. You are using an old version of iText, and the policy dictates that voluntary support on iText 5 or earlier has stopped. You should either use iText 7, or you should get a support contract if you still want support for an old iText version.
However, I am curious. I want to know where you found this clunky code (or why you decided to write this code):
Image image = Image.getInstance(ImageIO.read(new File(imagePath)), null);
PdfImage stream = new PdfImage(image, null, null);
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(30, 300);
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image);
You don't need ImageIO and you don't need to create a PdfImage, nor do you need to add that image to the body of a PDF file. The code you are using is code specialists would use for a very particular purpose. If you know that particular purpose, please explain.
If adding an image at an absolute position is all you want to do (that's a general purpose, not a particular purpose), your code should be as simple as this:
Image image = Image.getInstance(imagePath);
image.setAbsolutePosition(30, 300);
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image);
In this case, you don't have to worry about the image mask; iText will take care of that for you.
Please also explain why you're using an outdated version of iText instead of iText 7. If you want your application to be future-proof, you should upgrade to iText 7 now (to avoid wasting time later).

Why is Wicket not showing correct image on the WebPage?

I have a folder with images: IMG1.jpg, IMG2.jpg, IMG3.jpg, IMG4.jpg.
I do:
BufferedImage _img = null;
_img = ImageIO.read(new File(PATH_TO_IMAGE + "\\IMG"+Id+".jpg")); //where id is the number.
Then the rest...
BufferedDynamicImageResource bufferedDynamicImage = new BufferedDynamicImageResource();
bufferedDynamicImage.setImage(_img);
Image ci = new Image("myImg", bufferedDynamicImage);
add(ci);
And what I get in the end is that although Wicket knows the exact path to some image (which is shown in Log.file) most time it gets random image from my folder. What could be the reason for this?
Following my comment, what about
Image ci = new Image("myImg");
ci.add(AttributeModifier.replace("src", Model.of(PATH_TO_IMAGE + "\\IMG" + Id + ".jpg")));
add(ci);
This changes the src-attribute of your img-tag according to your desired logic, prevents browser-caching where undesired but enables caching where possible.

Rendering smallest possible image size with MVC3 vs Webforms Library

I am in the process of moving a webforms app to MVC3. Ironically enough, everything is cool beans except one thing - images are served from a handler, specifically the Microsoft Generated Image Handler. It works really well - on average a 450kb photo gets output at roughly 20kb.
The actual photo on disk weighs in at 417kb, so i am getting a great reduction.
Moving over to MVC3 i would like to drop the handler and use a controller action. However i seem to be unable to achieve the same kind of file size reduction when rendering the image. I walked through the source and took an exact copy of their image transform code yet i am only achieving 230~kb, which is still a lot bigger than what the ms handler is outputting - 16kb.
You can see an example of both the controller and the handler here
I have walked through the handler source code and cannot see anything that is compressing the image further. If you examine both images you can see a difference - the handler rendered image is less clear, more grainy looking, but still what i would consider satisfactory for my needs.
Can anyone give me any pointers here? is output compression somehow being used? or am i overlooking something very obvious?
The code below is used in my home controller to render the image, and is an exact copy of the FitImage method in the Image Transform class that the handler uses ...
public ActionResult MvcImage()
{
var file = Server.MapPath("~/Content/test.jpg");
var img = System.Drawing.Image.FromFile(file);
var sizedImg = MsScale(img);
var newFile = Server.MapPath("~/App_Data/test.jpg");
if (System.IO.File.Exists(newFile))
{
System.IO.File.Delete(newFile);
}
sizedImg.Save(newFile);
return File(newFile, "image/jpeg");
}
private Image MsScale(Image img)
{
var scaled_height = 267;
var scaled_width = 400;
int resizeWidth = 400;
int resizeHeight = 267;
if (img.Height == 0)
{
resizeWidth = img.Width;
resizeHeight = scaled_height;
}
else if (img.Width == 0)
{
resizeWidth = scaled_width;
resizeHeight = img.Height;
}
else
{
if (((float)img.Width / (float)img.Width < img.Height / (float)img.Height))
{
resizeWidth = img.Width;
resizeHeight = scaled_height;
}
else
{
resizeWidth = scaled_width;
resizeHeight = img.Height;
}
}
Bitmap newimage = new Bitmap(resizeWidth, resizeHeight);
Graphics gra = Graphics.FromImage(newimage);
SetupGraphics(gra);
gra.DrawImage(img, 0, 0, resizeWidth, resizeHeight);
return newimage;
}
private void SetupGraphics(Graphics graphics)
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighSpeed;
}
If you don't set the quality on the encoder, it uses 100 by default. You'll never get a good size reduction by using 100 due to the way image formats like JPEG work. I've got a VB.net code example of how to set the quality parameter that you should be able to adapt.
80L here is the quality setting. 80 still gives you a fairly high quality image, but at DRASTIC size reduction over 100.
Dim graphic As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(newImage)
graphic.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
graphic.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality
graphic.PixelOffsetMode = Drawing.Drawing2D.PixelOffsetMode.HighQuality
graphic.CompositingQuality = Drawing.Drawing2D.CompositingQuality.HighQuality
graphic.DrawImage(sourceImage, 0, 0, width, height)
' now encode and send the new image
' This is the important part
Dim info() As Drawing.Imaging.ImageCodecInfo = Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
Dim encoderParameters As New Drawing.Imaging.EncoderParameters(1)
encoderParameters.Param(0) = New Drawing.Imaging.EncoderParameter(Drawing.Imaging.Encoder.Quality, 80L)
ms = New System.IO.MemoryStream
newImage.Save(ms, info(1), encoderParameters)
When you save or otherwise write the image after setting the encoder parameters, it'll output it using the JPEG encoder (in this case) set to quality 80. That will get you the size savings you're looking for.
I believe it's defaulting to PNG format also, although Tridus' solution solves that also.
However, I highly suggest using this MVC-friendly library instead, as it avoids all the image resizing pitfalls and doesn't leak memory. It's very lightweight, free, and fully supported.

Adding text to existing pdf which is closed using itextsharp

Hi
I am creating PDF using itextsharp. Now my requirement is to add more text to the existing pdf. Is it possible if so then how can I do that?
Thanks Dipa
Yes, with certain limitations.
It is difficult, but not impossible, to determine what is already on an existing page.
If all you want to do is add "page X of Y" to the bottom left corner of all your pages, that's easy.
PdfReader reader = new PdfReader( inPath );
PdfStamper stamper = new PdfStamper( reader, new FileOutputStream( outPath ) );
BaseFont font = BaseFont.createFont(); // Helvetica, WinAnsiEncoding
for (int i = 0; i < reader.getNumberOfPages(); ++i) {
PdfContentByte overContent = stamper.getOverContent( i + 1 );
overContent.saveState();
overContent.beginText();
overContent.setFontAndSize( font, 10.0f );
overContent.setTextMatrix( xLoc, yLoc );
overContent.showText( "Page " + (i + 1) + " of " + reader.getNumberOfPages() );
overContent.endText();
overContent.restoreState();
}
stamper.close();
A big watermark isn't much more difficult. Adding things to a PDF at one or more predetermined locations is quite doable.
At the other end of the spectrum is "change text within existing paragraphs and reflow them". That's all but impossible. It would be much easier to rebuild the original PDF with the new data.
In fact, if at all possible, just rebuild them. You did it once, do it again.

Image Processing In c#,.net

I want to create a small application that allows me to insert an image on top of another image.And also i want to insert some text as well.
So can someone points me out where to start.Is there any open source libraries that allows me to do this task?.
I am after a solution that can be implemented in C#,Visual Studio .net.
Thanks.
You need to use the Graphics class.
For example:
using(var oldImage = Bitmap.FromFile(path))
using(var newImage = new Bitmap(250, 250))
using(var graphics = Graphics.FromImage(newImage)) {
graphics.DrawImage(oldImage, 10, 15);
graphics.DrawString("Hello, world!", SystemFonts.DefaultFont, Brushes.Red, 0, 0);
newImage.Save(path);
}
Try ImageMagick.Net. Lotsa stuff in there.
You should be OK using System.Drawing.Graphics if you don't need anything too fancy.

Resources