Working with the Image Compression Manager

This chapter describes how to use the Gestalt Manager to determine what version of the Image Compression Manager is available. Included is a brief discussion of the information about compressors and compressed data that can be obtained from the Image Compression Manager.

The chapter also describes the various functions you can use to

Getting Information About Compressors and Compressed Data

Use the Gestalt environmental selector gestaltCompressionMgr to determine whether the Image Compression Manager is available. Gestalt returns a 32-bit value indicating the version of the Image Compression Manager that is installed. This return value is formatted in the same way as the value returned by the CodecManagerVersion function, and it contains the version number specified as an integer value.

#define gestaltCompressionMgr 'icmp'

The Image Compression Manager provides a number of functions that allow your application to obtain information about the facilities available for image compression or about compressed images. Your application may use some of these functions to select a specific compressor or decompressor for a given operation or to determine how much memory to allocate to receive a decompressed image. In addition, your application may use some of these functions to determine the capabilities of the components that are available on the user’s computer system. You can then condition the options your program makes available to the user based on the user’s system configuration.

Getting Information About Compressor Components

This section describes the functions that allow your application to gather information about the Image Compression Manager and the installed compressor components.

You can use the CodecManagerVersion function to retrieve the version number associated with the Image Compression Manager that is installed on a particular computer.

You can use the FindCodec, GetCodecInfo, and GetCodecNameList functions to locate and retrieve information about the compressor components that are available on a computer.

Getting Information About Compressed Data

This section describes the functions that enable your application to collect information about compressed images and images that are about to be compressed. Your application may use some of these functions in preparation for compressing or decompressing an image or sequence.

You can use the GetCompressionTime function to determine how long it will take for a compressor to compress a specified image. Similarly, you can use the GetMaxCompressionSize function to find out how large the compressed image may be after the compression operation.

You can use the GetCompressedImageSize to determine the size of a compressed image that does not have a complete image description.

The GetSimilarity function allows you to determine how similar two images are. This information is useful when you are performing temporal compression on an image sequence.

Compressing Images

The Image Compression Manager provides a rich set of functions that allow applications to compress images. Some of these functions present a straightforward interface that is suitable for applications that need little control over the compression operation. Others permit applications to control the parameters that govern the compression operation.

This section describes the basic steps that your application follows when compressing a single frame of image data. Following this discussion, Listing 5-1 shows a sample function that compresses an image.

First, determine the parameters for the compression operation. Typically, the user specifies these parameters in a user dialog box you may supply via the standard compression dialog component. Your application may choose to give the user the ability to specify such parameters as the compression algorithm, image quality, and so on.

Your application may give the user the option to specify a compression algorithm based on an important performance characteristic. For example, the user may be most concerned with size, speed, or quality. The Image Compression Manager allows your application to choose the compressor component that meets the specified criterion.

To determine the maximum size of the resulting compressed image, your application should then call the Image Compression Manager’s GetMaxCompressionSize function. You provide the specified compression parameters to this function. In response, the Image Compression Manager invokes the appropriate compressor component to determine the maximum number of bytes required to store the compressed image. Your application should then reserve sufficient memory to accommodate the compressed image or use a data-unloading function to spool the compressed data to disk (see Spooling Compressed Data for more information about data-unloading functions).

Once the user has specified the compression parameters and your application has established an appropriate environment for the operation, call the CompressImage (or FCompressImage) function to compress the image. Use the CompressImage function if your application does not need to control all the parameters governing compression. If your application needs access to other compression parameters, use the FCompressImage function.

The Image Compression Manager manages the compression operation and invokes the appropriate compressor. The manager returns the compressed image and its associated image description structure to your application. Note that the image description structure contains a field indicating the size of the resulting image.

Listing 5-1  Compressing and decompressing an image

#include <Types.h>
#include <Traps.h>
#include <Memory.h>
#include <Errors.h>
#include <FixMath.h>
#include "Movies.h"
#include "ImageCompression.h"
#include "StdCompression.h"
 
#define kMgrChoose 0
PicHandle GetQTCompressedPict (PixMapHandle myPixMap);
 
PicHandle GetQTCompressedPict( PixMapHandle myPixMap )
{
    long                            maxCompressedSize = 0; 
    Handle                          compressedDataH = nil; 
    Ptr                             compressedDataP; 
    ImageDescriptionHandle          imageDescH = nil;
    OSErr                           theErr;
    PicHandle                       myPic = nil;
    Rect                            bounds = (**myPixMap).bounds; 
    CodecType                       theCodecType = 'jpeg';
    CodecComponent                  theCodec = (CodecComponent)anyCodec;
    CodecQ                          spatialQuality = codecNormalQuality; 
    short                           depth = 0;/* let ICM choose depth */ 
            
    theErr = GetMaxCompressionSize( myPixMap, &bounds, depth,
                                            spatialQuality, theCodecType, 
                                            (CompressorComponent)theCodec, 
                                             &maxCompressedSize); 
    if ( theErr ) return nil;
    
    imageDescH = (ImageDescriptionHandle)NewHandle(4);
    compressedDataH = NewHandle(maxCompressedSize);
    if ( compressedDataH != nil && imageDescH != nil )
    {
        MoveHHi(compressedDataH);
        HLock(compressedDataH);
        compressedDataP = StripAddress(*compressedDataH);
    
        theErr = CompressImage( myPixMap,
                        &bounds,
                        spatialQuality,
                        theCodecType,
                        imageDescH,
                        compressedDataP);
        
        if ( theErr == noErr )
        {                       
            ClipRect(&bounds);
            myPic = OpenPicture(&bounds);
            theErr = DecompressImage( compressedDataP,
                                        imageDescH, 
                                        myPixMap, 
                                        &bounds, 
                                        &bounds, 
                                        srcCopy, 
                                        nil ); 
            ClosePicture();
        }
        if ( theErr
                || GetHandleSize((Handle)myPic) == sizeof(Picture) )
        {
            KillPicture(myPic);
            myPic = nil;
        }
    }
    if (imageDescH) DisposeHandle( (Handle)imageDescH);
    if (compressedDataH) DisposeHandle( compressedDataH);
    return myPic;
}

Spooling Compressed Data

During compression and decompression operations it may be necessary to spool the image data to or from storage other than computer memory. If your application uses the Image Compression Manager functions that handle picture files, the Image Compression Manager manages this spooling for you. However, if you use the functions that work with pixel maps or sequences and your application cannot store the image data in memory, it is your application’s responsibility to spool the data.

The Image Compression Manager provides a mechanism that allows the compressors and decompressors to invoke spooling functions provided by your application. There are two kinds of data-spooling functions: data-loading functions and data-unloading functions. Decompressors call data-loading functions during image decompression. The data-loading function is responsible for providing compressed image data to the decompressor. The decompressor then decompresses the data and writes the resulting image to the appropriate location. See Application-Defined Functions for a detailed description of the calling sequence used by the decompressor component when it invokes your data-loading function.

Compressors call data-unloading functions during image compression. The data-unloading function must remove the compressed image data from memory. The compressor can then compress more of the image and write the compressed image data into the available buffer space. See Application-Defined Functions for a detailed description of the calling sequence used by the compressor component when it invokes your data-unloading function.

When compressing sequences, your application assigns a data-unloading function by calling the SetCSequenceFlushProc function. When decompressing sequences, you assign a data-loading function by calling the SetDSequenceDataProc function.

When your application assigns a spooling function to an image or sequence operation, you must also specify a data buffer and the size of that buffer. The codecMinimumDataSize value specifies the smallest data buffer you may allocate for image data spooling.

#define codecMinimumDataSize 32768  /* minimum data size */

Application-Defined Functions

This section describes four callback functions that you may provide to compressor components and an application-defined function that specifies alignment behavior.

The Image Compression Manager defines four callback functions that applications may provide to compressors or decompressors. These callbacks are data-loading functions, data-unloading functions, completion functions, and progress functions.