Solved

Resize Images Using GDI ---- Error with Gif Files

Posted on 2006-07-19
10
616 Views
Last Modified: 2008-01-09
Hello. I found this excellent article and class about resizing images using GDI. Here is the code:

using System;
using System.Drawing;
using System.IO;

namespace ImageHelper
{
    public class ImageResize
    {
        private double m_width, m_height;
        private bool m_use_aspect = true;
        private bool m_use_percentage = false;
        private string m_image_path;
        private Image m_src_image, m_dst_image;
        private ImageResize m_cache;
        private Graphics m_graphics;

        public string File
        {
            get { return m_image_path; }
            set { m_image_path = value; }
        }

        public Image Image
        {
            get { return m_src_image; }
            set { m_src_image = value; }
        }

        public bool PreserveAspectRatio
        {
            get { return m_use_aspect; }
            set { m_use_aspect = value; }
        }

        public bool UsePercentages
        {
            get { return m_use_percentage; }
            set { m_use_percentage = value; }
        }

        public double Width
        {
            get { return m_width; }
            set { m_width = value; }
        }

        public double Height
        {
            get { return m_height; }
            set { m_height = value; }
        }

        protected virtual bool IsSameSrcImage(ImageResize other)
        {
            if (other != null)
            {
                return (File == other.File
                    && Image == other.Image);
            }

            return false;
        }

        protected virtual bool IsSameDstImage(ImageResize other)
        {
            if (other != null)
            {
                return (Width == other.Width
                    && Height == other.Height
                    && UsePercentages == other.UsePercentages
                    && PreserveAspectRatio == other.PreserveAspectRatio);
            }

            return false;
        }

        public virtual Image GetThumbnail()
        {
            // Flag whether a new image is required
            bool recalculate = false;
            double new_width = Width;
            double new_height = Height;

            // Is there a cached source image available? If not,
            // load the image if a filename was specified; otherwise
            // use the image in the Image property
            if (!IsSameSrcImage(m_cache))
            {
                if (m_image_path.Length > 0)
                {
                    // Load via stream rather than Image.FromFile to release the file
                    // handle immediately
                    if (m_src_image != null)
                        m_src_image.Dispose();
                        // Wrap the FileStream in a "using" directive, to ensure the handle
                        // gets closed when the object goes out of scope
                        using (Stream stream = new FileStream(m_image_path, FileMode.Open))
                            m_src_image = Image.FromStream(stream);

                        recalculate = true;
                   
                }
            }

            // Check whether the required destination image properties have
            // changed
            if (!IsSameDstImage(m_cache))
            {
                // Yes, so we need to recalculate.
                // If you opted to specify width and height as percentages of the original
                // image's width and height, compute these now
                if (UsePercentages)
                {
                    if (Width != 0)
                    {
                        new_width = (double)m_src_image.Width * Width / 100;

                        if (PreserveAspectRatio)
                        {
                            new_height = new_width * m_src_image.Height / (double)m_src_image.Width;
                        }
                    }

                    if (Height != 0)
                    {
                        new_height = (double)m_src_image.Height * Height / 100;

                        if (PreserveAspectRatio)
                        {
                            new_width = new_height * m_src_image.Width / (double)m_src_image.Height;
                        }
                    }
                }
                else
                {
                    // If you specified an aspect ratio and absolute width or height, then calculate this
                    // now; if you accidentally specified both a width and height, ignore the
                    // PreserveAspectRatio flag
                    if (PreserveAspectRatio)
                    {
                        if (Width != 0 && Height == 0)
                        {
                            new_height = (Width / (double)m_src_image.Width) * m_src_image.Height;
                        }
                        else if (Height != 0 && Width == 0)
                        {
                            new_width = (Height / (double)m_src_image.Height) * m_src_image.Width;
                        }
                    }
                }

                recalculate = true;
            }

            if (recalculate)
            {
                // Calculate the new image
                if (m_dst_image != null)
                {
                    m_dst_image.Dispose();
                    m_graphics.Dispose();
                }

                Bitmap bitmap = new Bitmap((int)new_width, (int)new_height, m_src_image.PixelFormat);
                m_graphics = Graphics.FromImage(bitmap);
                m_graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                m_graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                m_graphics.DrawImage(m_src_image, 0, 0, bitmap.Width, bitmap.Height);
                m_dst_image = bitmap;

                // Cache the image and its associated settings
                m_cache = this.MemberwiseClone() as ImageResize;
            }

            return m_dst_image;

        }

        ~ImageResize()
        {
            // Free resources
            if (m_dst_image != null)
            {
                m_dst_image.Dispose();
                m_graphics.Dispose();
            }

            if (m_src_image != null)
                m_src_image.Dispose();
        }
    }
}

This works great with Jpeg images:

Dim o As New ImageHelper.ImageResize
o.File = myFilePath
o.Height = 500
o.GetThumbnail.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)

but when I try to use this on a Gif, I get an error ("A Graphics object cannot be created from an image that has an indexed pixel format")

Dim o As New ImageHelper.ImageResize
o.File = myFilePath
o.Height = 500
o.GetThumbnail.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif)

Does anyone know how I can fix the class to work with Gifs? I'm only good with VB.net so I don't know how to modify the C# class. Thanks.
0
Comment
Question by:Skytide
  • 5
  • 3
10 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 17141549
I always have to ask, how would you do it with VB.NET?

Bob
0
 

Author Comment

by:Skytide
ID: 17141561
On the flip side, I don't really need to fix the code to handle Gifs, if someone has a good way to resize Gif files without making it looked very dithered. I tried to use the GetThumbnailImage method and someone elses resize method, but they all create bad quality Gifs.

I also found an article on color quantization (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/colorquant.asp), but I still don't know what to do. Am I suppose to extract the palette from the original gif and apply it to the resized one? Please help. Thanks.
0
 

Author Comment

by:Skytide
ID: 17141583
Bob. Yeah, I wish I knew the anser to doing it with VB.net. I tried a C# to VB.net converter, but it didn't work. However, I figured out how to use C# and VB.net classes in my project. But like the comment above, I don't really need to fix the C# class. I just need a way to resize Gifs well. (Although I'd prefer a fix, since it will mean less coding :-p ). Thanks.
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 
LVL 96

Expert Comment

by:Bob Learned
ID: 17141638
I don't work with GIFs, all JPEGs and PNG files, since they the same file size and better color rendering.

Bob
0
 

Author Comment

by:Skytide
ID: 17141866
Ok, so I experimented a little with the C# code and figured out where the error is occuring:

m_graphics = Graphics.FromImage(bitmap);

I put a try, catch statement and decided (from other articles I have found) to redraw the image:

                try
                {
                    m_graphics = Graphics.FromImage(bitmap);
                }
                catch
                {
                    Bitmap bmpNew = new Bitmap(m_src_image.Width, m_src_image.Height);
                    m_graphics = Graphics.FromImage(bmpNew);
                    m_graphics.DrawImage(m_src_image, new Rectangle(0, 0, m_src_image.Width, m_src_image.Height), 0, 0, m_src_image.Width, m_src_image.Height, GraphicsUnit.Pixel);
                }

This resizes my gif, BUT my gif file is completely black. Any ideas?
0
 

Author Comment

by:Skytide
ID: 17142196
I figured out an alternative.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 17142273
Awesome!!!  What did you finally find?  

Bob
0
 

Author Comment

by:Skytide
ID: 17142560
Well as far as the gif goes, I can do some smoothing to make it a little better. Otherwise (according to online stuff), I'll have to use some unsafe code to make the Gif Palette. Most of my users will be using Jpegs anyways....

I still used the Try/Catch statement to work with the Gif image. My C# code was wrong though (since I'm a VB person....). But I figured it out:

catch
                {
                    Bitmap bmpNew = new Bitmap(bitmap.Width, bitmap.Height);
                    m_graphics = Graphics.FromImage(bmpNew);
                    m_graphics.DrawImage(m_src_image, new Rectangle(0, 0, m_src_image.Width, m_src_image.Height), 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel);
                    m_graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    m_graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                    m_graphics.DrawImage(m_src_image, 0, 0, bitmap.Width, bitmap.Height);
                    m_dst_image = bmpNew;
                }

0
 
LVL 1

Accepted Solution

by:
GhostMod earned 0 total points
ID: 17168441
Closed, 500 points refunded.

GhostMod
Community Support Moderator
0

Featured Post

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have developed many web applications with asp & asp.net and to add and use a dropdownlist was always a very simple task, but with the new asp.net, setting the value is a bit tricky and its not similar to the old traditional method. So in this a…
This article discusses the ASP.NET AJAX ModalPopupExtender control. In this article we will show how to use the ModalPopupExtender control, how to display/show/call the ASP.NET AJAX ModalPopupExtender control from javascript, how to show/display/cal…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question