Recipe 10.9. Resizing and Compressing JPEG Files


Problem

Your digital camera's pictures are great, but they're way too big to send attached to your family emails. You want to shrink them to a manageable size, but you also want to control the compression so there's no compromise in the resulting quality of the images.

Solution

Sample code folder: Chapter 10\CompressImages

The CompressJPEG class presented in this recipe wraps all the code required to compress JPEG pictures to any desired absolute or relative size. It lets you set the compression factor so you get a good balance between file size and quality in the resulting JPEG images.

Discussion

Before presenting the CompressJPEG class itself, let's see how it's called. The following code shows how a large picture named Family.jpg is compressed to 25 percent of its starting size using a compression-factor setting of 70 percent. A CompressJPEG object is created, and its SizePercent and QualityPercent properties are set to 25 and 70, respectively. The Load() method loads the original JPEG image, and the Save() method then saves the compressed and resized image to a new JPEG file:

 Dim imageConverter As New CompressJPEG imageConverter.SizePercent = 25 imageConverter.QualityPercent = 70 imageConverter.Load("Family.jpg") imageConverter.Save("SmallerFamily.jpg") 

Both the SizePercent and QualityPercent properties affect the final number of bytes in the output file, and it's important to understand the difference between these two settings. SizePercent refers to the physical dimensions of the image; that is, how many pixels wide and high it will be after compression. JPEG compression is not a lossless compression technique, and the QualityPercent setting controls how much of the original information content of the picture is retained. A low setting results in graininess and blockiness in the image, whereas a high value for this setting retains the detail and quality of the original image. Typically, a setting of around 75 to 85 provides good compression with little or no noticeable loss of image quality. If you don't set the QualityPercent property, it defaults to a very reasonable value of 85. If you don't set the SizePercent property, the output image retains the same dimensions as the original.

The following code is for the CompressJPEG class itself. In addition to the properties and methods described so far, there are two more properties you might find handy: instead of setting SizePercent, which resizes the picture to a percentage of its original size, you can set the Width or Height properties to define the compressed file's dimensions. If you set one of these properties, the other is calculated to retain the proportions of the original image. Here's the code for the CompressJPEG class:

 Imports System.Drawing.Imaging Public Class CompressJPEG    Private SourceImage As Image    Private UseQualityPercent As Double    Private UseSizePercent As Double    Private UseWidth As Integer    Private UseHeight As Integer    Public Sub Load(ByVal filePath As String)       ' ----- Assign the user-specified file.       SourceImage = Image.FromFile(filePath)    End Sub    Public Sub Save(ByVal outputFile As String)       ' ----- Save the file, making adjustments as requested.       Dim wide As Integer       Dim tall As Integer       Dim newImage As Bitmap       Dim canvas As Graphics       Dim codecs( ) As ImageCodecInfo       Dim jpegCodec As ImageCodecInfo       Dim scanCodec As ImageCodecInfo       Dim qualityParam As EncoderParameters       ' ----- Don't bother if there is no image.       If IsNothing(SourceImage) = True Then Return       ' ----- Use default values if needed.       If UseQualityPercent = 0 Then UseQualityPercent = 85       ' ----- Calculate the new dimensions.       If (UseWidth <> 0) And (UseHeight = 0) Then          ' ----- Proportional to the width.          wide = UseWidth          tall = CInt(UseWidth * _             SourceImage.Height / SourceImage.Width)       ElseIf (UseWidth = 0) And (UseHeight <> 0) Then          ' ----- Proportional to the height.          wide = CInt(UseHeight * _             SourceImage.Width / SourceImage.Height)          tall = UseHeight       ElseIf (UseWidth <> 0) And (UseHeight <> 0) Then          ' ----- User-specified size.          wide = UseWidth          tall = UseHeight       ElseIf (UseSizePercent <> 0) Then          ' ----- Percent scale.          wide = CInt(SourceImage.Width * _             UseSizePercent / 100)          tall = CInt(SourceImage.Height * _             UseSizePercent / 100)       Else          ' ----- Retain the size.          wide = SourceImage.Width          tall = SourceImage.Height       End If       ' ----- Redraw the image to the new size.       newImage = New Bitmap(wide, tall)       canvas = Graphics.FromImage(newImage)       canvas.DrawImage(SourceImage, 0, 0, wide, tall)       canvas.Dispose( )       ' ----- Locate the processor for JPEG images.       codecs = ImageCodecInfo.GetImageEncoders       jpegCodec = codecs(0)       qualityParam = New EncoderParameters       For Each scanCodec In codecs          If (scanCodec.MimeType = "image/jpeg") Then             ' ----- Found the one we're looking for.             jpegCodec = scanCodec             Exit For          End If       Next scanCodec       ' ----- Prepare the quality reduction.       qualityParam.Param(0) = New EncoderParameter( _          Encoder.Quality, CInt(UseQualityPercent))       ' ----- Adjust   and save the new image in one command.       newImage.Save(  outputFile, jpegCodec, qualityParam)       SourceImage = Nothing    End Sub    Public Property QualityPercent( ) As Double       Get          Return UseQualityPercent       End Get       Set(ByVal Value As Double)          Select Case Value             Case Is < 1                UseQualityPercent = 1             Case Is > 100                UseQualityPercent = 100             Case Else                UseQualityPercent = Value          End Select       End Set    End Property    Public Property SizePercent( ) As Double       Get          Return UseSizePercent       End Get       Set(ByVal Value As Double)          Select Case Value             Case Is < 1                UseSizePercent = 1             Case Is > 400                UseSizePercent = 400             Case Else                UseSizePercent = Value          End Select       End Set    End Property    Public Property Width( ) As Integer       Get          If (UseWidth > 0) Then             Return UseWidth          Else             If (SourceImage.Width > 0) Then                Return CInt(SourceImage.Width * _                   UseSizePercent / 100)             End If          End If       End Get       Set(ByVal Value As Integer)          UseWidth = Value       End Set    End Property    Public Property Height( ) As Integer       Get          Return UseHeight       End Get       Set(ByVal Value As Integer)          UseHeight = Value       End Set    End Property End Class 

Figure 10-11 shows an image after compression from the original, much larger file. This compressed file is less than 19 KB in size, reduced from an original of over 1.25 MB!

Figure 10-11. Compressed and reduced images can be made much smaller, without noticeable loss of quality





Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net