Centered Windows-Like Thumbnail Images?

VagabondSW

Well-known member
Joined
Feb 19, 2005
Messages
66
I have a ListView displaying thumbnails created from the original images using the System.Drawing.Image.GetThumbnailImage method.
Code:
System.Drawing.Bitmap thumbnail = getThumbnail(original, imgList.ImageSize.Width, imgList.ImageSize.Height);
I implemented some private methods that preserve the image proportions in the thumbnail, just like the Windows Thubmnail view. However, unlike the Windows Thumbnails, my thumbnails are top-justified, rather than centered. Here is a cropped screenshot comparing the Windows Thumbnails (top) to my thumbnails (bottom):

[Broken External Image]:http://home.san.rr.com/vagabondia/images/tmp/sample_v2.gif

In fact, it appears as if my 96h x 96w Bitmap is not part of my image despite my use of the Graphics.DrawImage method. The 96h x 96w dimension is determined by the ImageList.ImageSize height and width, respectively. However, passing those dimensions directly to the Image.GetThumbnailImage method causes non-square images to be distorted. So, I attempt to preserve the aspect ratio of the original image in the thumbnail.
Code:
private Bitmap getThumbnail(System.Drawing.Image img, int imgWidth, int imgHeight)
{
  decimal aspectRatio = getAspectRatio(img.Height, img.Width);
  int thumbWidth = imgWidth;
  int thumbHeight = imgHeight;

  if (img.Width > img.Height && img.Width != img.Height)
    thumbHeight = Convert.ToInt32(imgHeight * aspectRatio);
  else
    thumbWidth = Convert.ToInt32(imgWidth * aspectRatio);

  Image.GetThumbnailImageAbort thumbCallback = new Image.GetThumbnailImageAbort(thumbnailCallback);
  Image thumb = (Bitmap) img.GetThumbnailImage(thumbWidth, thumbHeight, thumbCallback, IntPtr.Zero);

  return thumb;
}
My getAspectRatio method is a simple one line routine that returns a decimal.
Code:
private decimal getAspectRatio(int imgHeight, int imgWidth)
{
  decimal aspectRatio = (decimal) System.Math.Min(imgHeight, imgWidth) / System.Math.Max(imgHeight, imgWidth);
  return aspectRatio;
}
The real problem seems to be when I attempt to draw my proportional thumbnail onto a blank Bitmap with the same dimensions as the ImageList.ImageSize. This step does not appear to be happening correctly, or it is not producing the desired Windows-like thumbnail result.
Code:
private Bitmap preserveAspectRatio(int imgHeight, int imgWidth, System.Drawing.Image img)
{
  Bitmap bmpImage = new Bitmap(imgWidth, imgHeight);
  int xoffset = 0;
  int yoffset = 0;

  if (img.Width > img.Height)
    yoffset = getOffset(bmpImage.Height, img.Width);
  else
    xoffset = getOffset(bmpImage.Width, img.Height) + img.Height;

  Graphics grafix = Graphics.FromImage(bmpImage);
  grafix.DrawImage(img, xoffset, yoffset, img.Width, img.Height);
  return bmpImage;
}
My getOffset method is a simple one line routine that returns an integer.
Code:
private int getOffset(int max, int actual)
{
  int offset = (max - actual) / 2;
  return offset;
}
I thought my preserveAspectRatio routine would draw my proportional thumbnail onto the square bitmap to create a centered proportional image, just like the Windows Thumbnail view. Apparently, there is something Im not doing correctly.

Any help or suggestions would be greatly appreciated.
 
PreserveAspectRatio(100, 50, someimagethatis200by100):
bmpImage is 100x50.
yoffset = GetOffset(50, 200) or 75.
And then draws the 200x100 image onto the 100x50 bitmap at 0,75... so
the image is clipped...

PreserveAspectRatio(400, 200, someimagethatis100by50):
bmpImage is 400x200.
yoffset = GetOffset(200, 100) thats 50.
And then draws the image onto the 200x100 bitmap at 0, 50

First of all:
grafix.DrawImage(img, xoffset, yoffset, img.Width, img.Height);
is the same as
grafix.DrawImage(img, xoffset, yoffset);

if (img.Width > img.Height && img.Width != img.Height)
is the same as
if (img.Width > img.Height)

On a more conceptual note, why arent you changing the size of the image when you scale it?
If you are just trying to center the picture in the middle without scaling it, then you should just do GetOffset for both the widths and the heights:
xoffset = getOffset(bmpWidth, imgWidth)
yoffset = getOffset(bmpHeight, imgHeight)
 
Thanks for the reply. When I went back to work (where I can only use Visual Basic.NET) and started implementing this code, I realized how bass-ackwards I was on tracking images and their respective sizes. Right now, Im back on the data layer, but should be returning to the images later in the week.

Speaking of that, you wouldnt happen to know how to handle multipage tiffs, would you? I only need to display and print existing multipage tiff files. I dont need to create them or change the existing ones in any way.

Any tips are greatly appreciated.
 
Back
Top