Solved

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

Posted on 2006-07-19
10
614 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
 
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

AJAX ModalPopupExtender has a required property "TargetControlID" which may seem to be very confusing to new users. It means the server control that will be extended by the ModalPopup, for instance, if when you click a button, a ModalPopup displays,…
I recently went through the process of creating a Calendar Control of events with the basis of using a database to keep track of the dates that are selectable, one requirement was to have the selected date pop-up in a simple lightbox.  At first this…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

758 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now