locked
Correct direction (size) of image thumbnail RRS feed

  • Question

  • Hello.
    I am doing a little image viewer. I have a listView controll, and put there an  image thumbnails. To get the thumbnails from images, i have this code:

            Image thumbnail(System.String pathToFile)
            {
                    Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                    Bitmap myBitmap = new Bitmap(pathToFile);
                    Image myThumbnail = myBitmap.GetThumbnailImage(120, 90, myCallback, IntPtr.Zero);
                    return myThumbnail;
            }
    
            /////////////////////////////////////
            
            public bool ThumbnailCallback()
            {
                return false;
            }

    Image thumbnails are placed in listView as large icons with resolution 120 x 90 pix.
    All is OK, if the image is horizontal, but when it is vertical, the thumbnail is stretched. What I have to do to fix this? And is there any reason to write down any text on thumbnails like this (like information about resolution, or filesize)?
    Wednesday, May 20, 2009 1:19 PM

Answers

  • This is because the height and width must be multiplied by an identical factor to maintain the proportion width / height.  I think the following code will do what you want given allowEnlarge = false and pad = true (but feel free to experiment with other parameters).

            /// <summary>
            /// Generates a thumbnail that fits in specified bounds while maintaining the proportions
            /// of the original image.
            /// </summary>
            /// <param name="fileName">The path and filename of the original image.</param>
            /// <param name="bounds">The maximum width and height for the returned image.</param>
            /// <param name="allowEnlarge">If true, the original image may be enlarged or reduced.
            ///   If false, the original image may only be reduced.</param>
            /// <param name="pad">If true, the thumbnail is centered in an image that has exactly
            ///   the specified bounds. If false, the returned image has equal or lesser bounds than
            ///   those specified.</param>
            /// <returns>The thumbnail image.</returns>
            private static Image GenerateThumbnail(string fileName, Size bounds, bool allowEnlarge, bool pad)
            {
                using (Bitmap bmp = new Bitmap(fileName))
                {
                    Size targetSize;
    
                    double hFit = (double) bounds.Height / bmp.Height;
                    double wFit = (double) bounds.Width / bmp.Width;
    
                    double factor = Math.Min(hFit, wFit);
                    if (!allowEnlarge)
                    {
                        factor = Math.Min(factor, 1.0);
                    }
    
                    targetSize = new Size((int)(bmp.Width * factor), (int)(bmp.Height * factor));
    
                    if (pad)
                    {
                        using (Image thumbnail = bmp.GetThumbnailImage(targetSize.Width, targetSize.Height, null, IntPtr.Zero))
                        {
                            Bitmap centeredBitmap = new Bitmap(bounds.Width, bounds.Height);
                            using (Graphics g = Graphics.FromImage(centeredBitmap))
                            {
                                g.DrawImage(thumbnail,
                                    (centeredBitmap.Width - thumbnail.Width) / 2, (centeredBitmap.Height - thumbnail.Height) / 2,
                                    thumbnail.Width, thumbnail.Height);
                            }
                            return centeredBitmap;
                        }
                    }
                    else
                    {
                        return bmp.GetThumbnailImage(targetSize.Width, targetSize.Height, null, IntPtr.Zero);
                    }
                }
            }


    > And is there any reason to write down any text on thumbnails like this (like information about resolution, or filesize)?

    Not sure what you mean.  I suppose this would depend on your application.
    • Proposed as answer by Jason Kresowaty Thursday, May 21, 2009 11:35 PM
    • Marked as answer by Ajgor64 Friday, May 22, 2009 1:35 AM
    Thursday, May 21, 2009 1:00 AM

All replies

  • This is because the height and width must be multiplied by an identical factor to maintain the proportion width / height.  I think the following code will do what you want given allowEnlarge = false and pad = true (but feel free to experiment with other parameters).

            /// <summary>
            /// Generates a thumbnail that fits in specified bounds while maintaining the proportions
            /// of the original image.
            /// </summary>
            /// <param name="fileName">The path and filename of the original image.</param>
            /// <param name="bounds">The maximum width and height for the returned image.</param>
            /// <param name="allowEnlarge">If true, the original image may be enlarged or reduced.
            ///   If false, the original image may only be reduced.</param>
            /// <param name="pad">If true, the thumbnail is centered in an image that has exactly
            ///   the specified bounds. If false, the returned image has equal or lesser bounds than
            ///   those specified.</param>
            /// <returns>The thumbnail image.</returns>
            private static Image GenerateThumbnail(string fileName, Size bounds, bool allowEnlarge, bool pad)
            {
                using (Bitmap bmp = new Bitmap(fileName))
                {
                    Size targetSize;
    
                    double hFit = (double) bounds.Height / bmp.Height;
                    double wFit = (double) bounds.Width / bmp.Width;
    
                    double factor = Math.Min(hFit, wFit);
                    if (!allowEnlarge)
                    {
                        factor = Math.Min(factor, 1.0);
                    }
    
                    targetSize = new Size((int)(bmp.Width * factor), (int)(bmp.Height * factor));
    
                    if (pad)
                    {
                        using (Image thumbnail = bmp.GetThumbnailImage(targetSize.Width, targetSize.Height, null, IntPtr.Zero))
                        {
                            Bitmap centeredBitmap = new Bitmap(bounds.Width, bounds.Height);
                            using (Graphics g = Graphics.FromImage(centeredBitmap))
                            {
                                g.DrawImage(thumbnail,
                                    (centeredBitmap.Width - thumbnail.Width) / 2, (centeredBitmap.Height - thumbnail.Height) / 2,
                                    thumbnail.Width, thumbnail.Height);
                            }
                            return centeredBitmap;
                        }
                    }
                    else
                    {
                        return bmp.GetThumbnailImage(targetSize.Width, targetSize.Height, null, IntPtr.Zero);
                    }
                }
            }


    > And is there any reason to write down any text on thumbnails like this (like information about resolution, or filesize)?

    Not sure what you mean.  I suppose this would depend on your application.
    • Proposed as answer by Jason Kresowaty Thursday, May 21, 2009 11:35 PM
    • Marked as answer by Ajgor64 Friday, May 22, 2009 1:35 AM
    Thursday, May 21, 2009 1:00 AM
  • Woow...
    This is EXACTLY, what I need :)
    The class Graphics is, what I was searching for. My second question was - how can I write info about original image on the thumbnail (resolution etc). Now I can write everything using Graphics.DrawString method :)
    Thank You Very Much for helping :)


    • Proposed as answer by gb_007 Wednesday, July 8, 2009 11:43 AM
    Thursday, May 21, 2009 10:08 AM