2

I need to resize an image, but the image quality cannot be affected by this, the images will be from like 10x10 to 1000x1000, it will have some major congestions and some empty times it has to scale both up and down "potentially losing some image quality." is OK but it has to be at minimum, everything with raster graphics indeed NO libraries or other external binaries please

user302823
  • 361
  • 1
  • 3
  • 13
  • You're doing it wrong. Use a vector graphics format, and this wouldn't be an issue. – Stefan Kendall Apr 21 '10 at 19:23
  • possible duplicate of http://stackoverflow.com/questions/87753/resizing-an-image-without-losing-any-quality – Jon Seigel Apr 21 '10 at 19:25
  • @oidfrosty what you want (especially at this scale and in any half-way useful quality) is probably not going to be achievable without libraries or other external binaries. Image enhancement is a huge field of research. – Pekka Apr 21 '10 at 19:25
  • well since this is one of my first jobs I'd love to learn as much as I can doing it, so I want to keep "external work" at minimum @Stefan Kendall I don't really know how "everything with raster graphics" made you think I'm actually able to do with vectors? – user302823 Apr 21 '10 at 20:07

3 Answers3

4

Here is a link showing you how to resize an image:

http://snippets.dzone.com/posts/show/4336

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
0

Whenever you resize images you're going to have some loss of quality - there's no way around that, but you can help minimize it by using the highest quality options in for the graphics context.

Here's what I use using plain GDI+ functions:

public static Bitmap ResizeImage(Bitmap bmp, int width, int height, 
                                 InterpolationMode mode = InterpolationMode.HighQualityBicubic)                                         
{
    Bitmap bmpOut = null;

    try
    {                                
        decimal ratio;
        int newWidth = 0;
        int newHeight = 0;

        // If the image is smaller than a thumbnail just return original size
        if (bmp.Width < width && bmp.Height < height)
        {
            newWidth = bmp.Width;
            newHeight = bmp.Height;
        }
        else
        {
            if (bmp.Width == bmp.Height)
            {
                if (height > width)
                {
                    newHeight = height;
                    newWidth = height;
                }
                else
                {
                    newHeight = width;
                    newWidth = width;                         
                }
            }
            else if (bmp.Width >= bmp.Height)
            {
                ratio = (decimal) width/bmp.Width;
                newWidth = width;
                decimal lnTemp = bmp.Height*ratio;
                newHeight = (int) lnTemp;
            }
            else
            {
                ratio = (decimal) height/bmp.Height;
                newHeight = height;
                decimal lnTemp = bmp.Width*ratio;
                newWidth = (int) lnTemp;
            }
        }

        //bmpOut = new Bitmap(bmp, new Size( newWidth, newHeight));                     
        bmpOut = new Bitmap(newWidth, newHeight);                
        bmpOut.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);

        Graphics g = Graphics.FromImage(bmpOut);
        g.InterpolationMode = mode;

        g.SmoothingMode = SmoothingMode.HighQuality;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

        g.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
        g.DrawImage(bmp, 0, 0, newWidth, newHeight);                
    }
    catch
    {
        return null;
    }

    return bmpOut;
}

This resizes an image to the largest of either the width or the height - you can vary that algorithm to fit your resizing needs.

If you want to work with files you can add another helper that wraps the code above:

public static bool ResizeImage(string filename, string outputFilename, 
                                int width, int height, 
                                InterpolationMode mode = InterpolationMode.HighQualityBicubic)
{

    using (var bmpOut = ResizeImage(filename, width, height, mode) )
    {
        var imageFormat = GetImageFormatFromFilename(filename);
        if (imageFormat == ImageFormat.Emf)
            imageFormat = bmpOut.RawFormat; 

        bmpOut.Save(outputFilename, imageFormat);
    }

    return true;
}

GDI+ in general is not the best solution for high quality image manipulation - it's decent but if you need the highest quality, better performance and thread safety in Web apps you need to look at other options.

Bertrand LeRoy had a great article on Image Resizing some time ago that offers some alternatives using core .NET frameworks. http://weblogs.asp.net/bleroy/state-of-net-image-resizing-how-does-imageresizer-do

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134
-2

What you need is for your images to be scalable. I'd recommend using an XML format to store your images, since XML is very scalable. For example:

<Image Width="640" Height="480">
  <Pixel X="0" Y="0">
    <Red>20</Red>
    <Green>80</Green>
    <Blue>0</Blue>
    <Alpha>255</Alpha>
  </Pixel>
  <Pixel X="1" Y="0">
    ...

If you're worried about memory, I bet this will compress really well :-).

Robert Fraser
  • 10,649
  • 8
  • 69
  • 93
  • 3
    Is...is this sarcasm? If so, brilliant! If not, maybe you need a thesaurus... :-) – NickAldwin Apr 21 '10 at 22:23
  • @oidfrosty -- This certainly isn't a complete solution, but if you stored your images like this, you could implement a technique like the one above by using XSLT + XPath, which would be more readable & extensible than a C# solution. In fact, most image processing tasks (such as cropping, resizing, levels, etc.) cold be reduced to XSLT. – Robert Fraser Apr 24 '10 at 20:53
  • @NickAldwin - I don't joke around when it comes to XML. – Robert Fraser Apr 24 '10 at 20:54