Solved

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

Posted on 2006-07-19
10
617 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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Lots of people ask this question on how to extend the “MembershipProvider” to make use of custom authentication like using existing database or make use of some other way of authentication. Many blogs show you how to extend the membership provider c…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

808 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