Persits Software, Inc. Knowledge Base Articles

HOWTO: Create fixed-size thumbnail while preserving aspect ratio

Problem Description

This article describes how to use AspJpeg to create a thumbnail of pre-set dimensions while preserving the orientation and aspect ratio of the original image, as follows:

   

Solution

In many web applications such as online photo albums, there is a need to convert all images to fixed-size (usually square) thumbnails. To preserve the aspect ratio and orientation of the original image in a square thumbnail, landscape-oriented images need to have margins added on the top and bottom, and portrait-oriented images on the left and right.

AspJpeg can add margins to thumbnails by means of "negative cropping", i.e. using the Crop method with some or all of the coordinates being outside the coordinate space of the thumbnail. Negative cropping is described here.

The color of the margin areas is black by default and can be changed via the property objJpeg.Canvas.Brush.Color.

The following code snippet creates a square 200x200 thumbnail of an arbitrary image with white margins. The thumbnail dimensions are specified via the variables DesiredWidth and DesiredHeight. In this particular example, these are set to the same number (200 pixels) but they can be arbitrary numbers not necessarily equal to each other.

VB Script:

Set Jpeg = Server.CreateObject("Persits.Jpeg")

Jpeg.Open "c:\path\image.jpg"

Jpeg.PreserveAspectRatio = True

DesiredWidth = 200
DesiredHeight = 200

If Jpeg.OriginalWidth / DesiredWidth > Jpeg.OriginalHeight / DesiredHeight Then
   Jpeg.Width = DesiredWidth

   dy = Int((DesiredHeight - Jpeg.Height) / 2)
   dy1 = DesiredHeight - Jpeg.Height - dy
   dx = 0
   dx1 = 0
Else
   Jpeg.Height = DesiredHeight

   dx = Int((DesiredWidth - Jpeg.Width) / 2)
   dx1 = DesiredWidth - Jpeg.Width - dx
   dy = 0
   dy1 = 0
End If

' Apply negative cropping with white background
Jpeg.Canvas.Brush.Color = &HFFFFFF
Jpeg.Crop -dx, -dy, Jpeg.Width + dx1, Jpeg.Height + dy1

Jpeg.SaveUnique "c:\path\out.jpg"

C#:

IASPJpeg objJpeg = new ASPJpeg();
objJpeg.Open( @"c:\path\image.jpg" );

objJpeg.PreserveAspectRatio = 1;

int DesiredWidth = 200;
int DesiredHeight = 200;

int dx, dy, dx1, dy1;

if( objJpeg.OriginalWidth / DesiredWidth > objJpeg.OriginalHeight / DesiredHeight )
{
   objJpeg.Width = DesiredWidth;

   dy = (DesiredHeight - objJpeg.Height) / 2;
   dy1 = DesiredHeight - objJpeg.Height - dy;
   dx = 0;
   dx1 = 0;
}
else
{
   objJpeg.Height = DesiredHeight;

   dx = (DesiredWidth - objJpeg.Width) / 2;
   dx1 = DesiredWidth - objJpeg.Width - dx;
   dy = 0;
   dy1 = 0;
}

// Apply negative cropping with white background
objJpeg.Canvas.Brush.Color = 0xFF0000;
objJpeg.Crop( -dx, -dy, objJpeg.Width + dx1, objJpeg.Height + dy1 );

objJpeg.SaveUnique( @"c:\path\out.jpg" );

The margins can also be made fully transparent by using PNG as the output format and adding an alpha channel to the image. The following lines of code should be added after the call to the Crop method if you want your thumbnails to have transparent margins:

VB Script:

...

Set Alpha = Server.CreateObject("Persits.Jpeg")
Alpha.New DesiredWidth, DesiredHeight, 0 ' fully transparent
Alpha.Canvas.Brush.Color = &HFFFFFF ' fully opaque
Alpha.Canvas.Pen.Color = &HFFFFFF ' fully opaque
Alpha.Canvas.DrawBar dx, dy, Jpeg.Width - dx1, Jpeg.Height - dy1
Alpha.ToGrayscale(0)
Jpeg.SetAlpha Alpha, False
Jpeg.PNGOutput = true

Jpeg.SaveUnique "c:path\out.png"

C#:

...

IASPJpeg objAlpha = new ASPJpeg();
objAlpha.New( DesiredWidth, DesiredHeight, 0 ); // fully transparent
objAlpha.Canvas.Brush.Color = 0xFFFFFF; // fully opaque
objAlpha.Canvas.Pen.Color = 0xFFFFFF; // fully opaque
objAlpha.Canvas.DrawBar( dx, dy, objJpeg.Width - dx1, objJpeg.Height - dy1 );
objAlpha.ToGrayscale(0);
objJpeg.SetAlpha( (ASPJpeg)objAlpha, false );
objJpeg.PNGOutput = 1;

objJpeg.SaveUnique( @"c:\path\out.png" );

The PNG format and alpha channel are described here.