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.

This section describes the interfaces presented when compressors invoke your callback functions. These application-defined functions may be called by compressor components during a compression or decompression operation.

You identify a callback function to an Image Compression Manager function by specifying a pointer to a callback function structure. These structures contain two fields: a pointer to the callback function and a reference constant value. There is one callback function structure for each type of callback function. See the individual function descriptions in the sections that follow for descriptions of the structures.

Changing Sequence-Compression Parameters

This section describes the functions that allow your application to manipulate the parameters that control sequence compression and to get information about memory that the compressor has allocated. You can use these functions during the sequence-compression process. Your application establishes the default value for most of these parameters with the CompressSequenceBegin function. Some of these functions deal with parameter values that cannot be set when starting a sequence.

You can determine the location of the previous image buffer used by the Image Compression Manager by calling the GetCSequencePrevBuffer function.

You can set a number of compression parameters. Use the SetCSequenceFlushProc function to assign a data-unloading function to the operation. You can set the rate at which the Image Compression Manager inserts key frames into the compressed sequence by calling the SetCSequenceKeyFrameRate function. You can set the frame against which the compressor compares a frame when performing temporal compression by calling the SetCSequencePrev function. Finally, you can control the quality of the compressed image by calling the SetCSequenceQuality function.

Changing Sequence-Decompression Parameters

This section discusses the functions that enable your application to manipulate the parameters that control sequence decompression and to get information about memory that the decompressor has allocated. Your application establishes the default value for most of these parameters with the DecompressSequenceBegin function. Some of these functions deal with parameter values that cannot be set when starting a sequence.

You can determine the buffers used by a decompressor component when it decompresses a sequence. Use the GetDSequenceImageBuffer function to determine the location of the image buffer. Use the GetDSequenceScreenBuffer function to determine the location of the screen buffer.

You can control a number of the parameters that affect a decompression operation (note that changing these parameters may temporarily affect performance). Use the SetDSequenceAccuracy function to control the accuracy of the decompression. Use the SetDSequenceDataProc function to assign a data-loading function to the operation. Use the SetDSequenceMask function to set the clipping region for the resulting image. You can establish a blend matte for the operation by calling the SetDSequenceMatte function. You can alter the spatial characteristics of the resulting image by calling the SetDSequenceMatrix function. Your application can establish the size and location of the operation’s source rectangle by calling the SetDSequenceSrcRect function. Finally, you can set the transfer mode used by the decompressor when it draws to the screen by calling the SetDSequenceTransferMode function.

Working With Images

This section discusses the functions that allow your application to compress and decompress single-frame images stored as pixel maps (of data type PixMap ). See Working With Sequences for information on compressing and decompressing sequences of images. See Working With Pictures and PICT Files for information on compressing and manipulating single-frame images stored as pictures or picture files (in PICT format).

The Image Compression Manager provides two sets of functions for compressing and decompressing images. If you do not need to assert a lot of control over the compression operation, you can use the CompressImage and DecompressImage functions to work with compressed images. If you need more control over the compression parameters, you can use the FCompressImage and FDecompressImage functions.

You can convert a compressed image from one compression format to another by calling the ConvertImage function.

You can alter the spatial characteristics of a compressed image by calling the TrimImage function.

You can work with an image’s color table with the SetImageDescriptionCTable and GetImageDescriptionCTable functions.

Working With Sequences

This section describes the functions that enable your application to compress and decompress sequences of images. Each image in the sequence is referred to as a frame. Note that the sequence carries no time information. The Movie Toolbox manages all temporal aspects of displaying the sequence. Consequently, your application can focus on the order of images in the sequence.

To process a sequence of frames, your program first begins the sequence (by issuing either the CompressSequenceBegin or DecompressSequenceBegin functions). You then process each frame in the sequence (use CompressSequenceFrame to compress a frame; use DecompressSequenceFrame to decompress a frame). When you are done, close the sequence by issuing the CDSequenceEnd function. You can check on the status of the current operation by calling the CDSequenceBusy function.

Note that the Image Compression Manager provides a rich set of functions that allow your application to control many of the parameters that govern sequence processing. You set default values for most of these parameters when you start the sequence. These additional functions allow you to modify those parameters while you are processing a sequence. See Changing Sequence-Compression Parameters for information on functions that affect sequence compression. See Changing Sequence-Decompression Parameters for information on functions that affect sequence decompression.

Working With Pictures and PICT Files

This section describes the functions that let your application compress and decompress single-frame images stored as pictures and PICT files. See Working With Images for information on compressing and manipulating single-frame images stored as pixel map structures. See Working With Sequences for information on compressing and decompressing sequences of images.

As with image compression, the Image Compression Manager provides two sets of functions for working with compressed pictures. If you do not need to control the compression parameters, use the CompressPicture or CompressPictureFile functions. If you need more control over the operation, use the FCompressPicture or FCompressPictureFile functions.

The Image Compression Manager automatically expands compressed pictures when you display them. Use the DrawPictureFile function to display the contents of a picture file. If you want to alter the spatial characteristics of the image, use the DrawTrimmedPicture or DrawTrimmedPictureFile functions.

You can work with an image’s control information by calling the GetPictureFileHeader function.

Decompressing Images

Working With Pictures discusses how applications can display compressed images that are stored as pictures by calling the DrawPicture function. The Image Compression Manager also provides functions that allow your application to display single-frame compressed images. As with image compression, your application can choose to specify all the parameters that govern the operation, or it can leave many of these choices to the Image Compression Manager.

This section describes the steps your application must follow to decompress an image into a pixel map.

First, your application determines where to display the decompressed image. Your application must specify the destination graphics port to the Image Compression Manager. In addition, you may indicate that only a portion of the source image is to be displayed. You describe the desired portion of the image by specifying a rectangle in the coordinate system of the source image. You can determine the size of the source image by examining the image description structure associated with the image (see The Image Description Structure for more information about image description structures).

Your application may also specify that the image is to be mapped into the destination graphics port. The Image Compression Manager provides two mechanisms for mapping images during decompression. The DecompressImage function accepts a second rectangle as a parameter. During decompression the Image Compression Manager maps the desired image to the destination rectangle, scaling the resulting image as appropriate to fit the destination rectangle. The FDecompressImage function allows your application to specify a mapping matrix for the operation. Currently, the Image Compression Manager supports only scaling and translation matrix operations.

Your application can invoke further effects by specifying a mask region or blend matte for the image. Mask regions and mattes control which pixels in the source image are drawn to the destination. Mask regions define the part of the source image that is displayed. During decompression the Image Compression Manager displays only those pixels in the source image that correspond to bits in the mask that are set to 1. Mask regions must be defined in the destination coordinate system.

Blend mattes contain several bits per pixel and are defined in the coordinate system of the source image. Mattes provide a mechanism for mixing two images. The Image Compression Manager displays the weighted average of the source and destination based on the corresponding pixel in the matte.

Decompress the image by calling the Image Compression Manager’s DecompressImage or FDecompressImage function. Your application must provide an image description structure along with the other parameters governing the operation. Use the DecompressImage function for simple decompression operations. If your application needs greater control, use the FDecompressImage function. See Working With Images for detailed descriptions of these functions.

The Image Compression Manager manages the decompression operation and invokes the appropriate decompressor component. The manager returns the decompressed image to the location specified by your application.

Image Transcoding Functions

A transcoder translates an image compressed in one format into a different compression format. A transcoder can use an algorithm that directly translates from one format into another, which is often faster and more accurate than decompression and recompression. If your application requests decompression of an image, but no decompressor for the image can be found, QuickTime will search for a transcoder that can be used to convert the image into a format for which a decompressor is available. The transcoder functions directly available to your application are:

The Image Description Structure

An image description structure contains information that defines the characteristics of a compressed image or sequence. Data in the image description structure indicates the type of compression that was used, the size of the image when displayed, the resolution at which the image was captured, and so on. One image description structure may be associated with one or more compressed frames.

The ImageDescription data type defines the layout of an image description structure. In addition, an image description structure may contain additional data in extensions and custom color tables. The Image Compression Manager provides functions that allow you to get and set the data in image description structure extensions and custom color tables.

struct ImageDescription {
    long idSize;            /* total size of this structure */
    CodecType cType;        /* compressor creator type */
    long resvd1;            /* reserved--must be set to 0 */
    short resvd2;           /* reserved--must be set to 0 */
    short dataRefIndex;     /* reserved--must be set to 0 */
    short version;          /* version of compressed data */
    short revisionLevel;    /* compressor that created data */
    long vendor;            /* compressor developer that created data */
    CodecQ temporalQuality;     
                            /* degree of temporal compression */ 
    CodecQ spatialQuality;      
                            /* degree of spatial compression */ 
    short width;            /* width of source image in pixels */
    short height;           /* height of source image in pixels */
    Fixed hRes;             /* horizontal resolution of source image */
    Fixed vRes;             /* vertical resolution of source image */
    long dataSize;          /* size in bytes of compressed data */
    short frameCount;       /* number of frames in image data */
    Str31 name;             /* name of compression algorithm */
    short depth;            /* pixel depth of source image */
    short clutID;           /* ID number of the color table for image */
};
typedef struct ImageDescription ImageDescription;
typedef ImageDescription *ImageDescriptionPtr, **ImageDescriptionHandle;

Field

Description

idSize

Defines the total size of this image description structure with extra data including color lookup tables and other per sequence data.

cType

Indicates the type of compressor component that created this compressed image data. The value of this field indicates the compression algorithm supported by the component. The Codec data type defines a field in the compressor name list structure that identifies the compression method employed by a given compressor component. Apple Computer's Developer Technical Support group assigns these values so that they remain unique. These values correspond, in turn, to text strings that can identify the compression method to the user. See the description of GetCodecNameList for a list of valid values.

resvd1

Reserved for Apple. This field must be set to 0.

resvd2

Reserved for Apple. This field must be set to 0.

dataRefIndex

Reserved for Apple. This field must be set to 0.

version

Indicates the version of the compressed data. The contents of this field should indicate the version of the compression algorithm that was used to create the compressed data. By examining this field, decompressors that support many versions of an algorithm can determine the proper way to decompress the image.

revisionLevel

Indicates the version of the compressor that created the compressed image. Developers of compressors and decompressors assign these version numbers.

vendor

Identifies the developer of the compressor that created the compressed image.

temporalQuality

Indicates the degree of temporal compression performed on the image data associated with this description. This field is valid only for sequences.

spatialQuality

Indicates the degree of spatial compression performed on the image data associated with this description. This field is valid for sequences and still images.

width

Contains the width of the source image, in pixels.

height

Contains the height of the source image, in pixels.

hRes

Contains the horizontal resolution of the source image, in dots per inch.

vRes

Contains the vertical resolution of the source image, in dots per inch.

dataSize

Indicates the size of the compressed image, in bytes. This field is valid only for still images. Set this field to 0 if the size is unknown.

frameCount

Contains the number of frames in the image data associated with this description.

name

Indicates the compression algorithm used to create the compressed data. This algorithm is stored in Pascal string format. It always takes up 32 bytes no matter how long the string is. The 32 bytes consist of 31 bytes plus one length byte. The value of this field should correspond to the compressor type specified by the cType field, as well as to the value of the typeName field in the appropriate compressor name structure returned by the GetCodecNameList function. Applications may use the contents of this field to indicate the type of compression used for the associated image.

depth

Contains the pixel depth specified for the compressed image. Values of 1, 2, 4, 8, 16, 24, and 32 indicate the depth of color images. Values of 34, 36, and 40 indicate 2-bit, 4-bit, and 8-bit grayscale, respectively, for grayscale images.

clutID

Contains the ID of the color table for the compressed image, or other special values. If this field is set to 0, then a custom color table is defined for the compressed image. You can use the GetImageDescriptionCTable function to retrieve the color table. If this field is set to -1, the image does not use a color table.

See Compression Quality Constants for a list of available values for the temporalQuality and spatialQuality fields.

Compression Quality Constants

Compressor components may allow applications to assert some control over the image quality that results from a compression or decompression operation. For example, the CompressSequenceBegin function provides the spatialQuality and temporalQuality parameters so that applications can indicate the level of image accuracy desired within individual frames and across adjacent frames in a sequence, respectively. These quality values become a property of the compressed data and are stored in the image description structure (described on The Image Description Structure ) associated with the image or sequence.

For a given compression operation, your application can determine the quality that the component supports by issuing the GetCompressionTime function.

The CodecQ data type defines a field that identifies the quality characteristics of a given image or sequence. Note that individual components may not implement all the quality levels shown here. In addition, components may implement other quality levels in the range from codecMinQuality to codecMaxQuality. Relative quality should scale within the defined value range. Values above codecLosslessQuality are reserved for use by individual components.

/* compression quality values */
#define codecMinQuality         0x000L      /* minimum valid value */
#define codecLowQuality         0x100L      /* low-quality reproduction */
#define codecNormalQuality              
                                0x200L      /* normal-quality repro */ 
#define codecHighQuality        
                                0x300L      /* high-quality repro */ 
#define codecMaxQuality         0x3FFL      /* maximum-quality repro */
#define codecLosslessQuality        
                                0x400L      /* lossless-quality repro */ 
typedef unsigned long CodecQ;

Field

Description

codecMinQuality

Specifies the minimum valid value for a CodecQ field.

codecLowQuality

Specifies low-quality image reproduction. This value should correspond to the lowest image quality that still results in acceptable display characteristics.

codecNormalQuality

Specifies image reproduction of normal quality.

codecHighQuality

Specifies high-quality image reproduction. This value should correspond to the highest image quality that can be achieved with reasonable performance.

codecMaxQuality

Specifies the maximum standard value for a CodecQ field.

codecLosslessQuality

Specifies lossless compression or decompression. This special value is valid only for components that can support lossless compression or decompression.

The Compressor Name List Structure

The compressor name list structure contains a list of compressor name structures. (A compressor name structure identifies a compressor or decompressor component.) The data structure contains name and type information for the component. The GetCodecNameList function returns an array of these structures, formatted into a compressor name list structure. The CodecNameSpecList data type defines a compressor name list structure.

/* compressor name list structure */
struct CodecNameSpecList {
    short count;        /* how many compressor name structures */
    CodecNameSpec list[1];          
                        /* array of compressor name structures */
};
typedef struct CodecNameSpecList CodecNameSpecList;
typedef CodecNameSpecList *CodecNameSpecListPtr;

Field

Description

count

Indicates the number of compressor name structures contained in the list array that follows.

list

Contains an array of compressor name structures. Each structure corresponds to one compressor component or type that meets the selection criteria your application specifies when it issues the GetCodecNameList function. The count field indicates the number of structures stored in this array.