Example3.c

/*
    File:       Example3.c
 
    Contains:   Compression of PICT Files
 
                The following sample code is again similar to the previous example except
                that it better deals with custom color tables, and demonstrates the use
                of extended procs and saving/restoring compression settings state.
 
    Written by:     
 
    Copyright:  Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/17/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                12/4/94     khs             changed the format of the file to the new look and feel
 
*/
// INCLUDE FILES
#include <menus.h>
#include <fonts.h>
#include <osevents.h>
#include <components.h>
#include <quicktimecomponents.h>
 
 
// FUNCTION PROTOTYPES
pascal Boolean Example3FilterProc(DialogPtr theDialog,
                                  EventRecord* theEvent,
                                  short* itemHit,
                                  long refcon);
pascal short Example3HookProc(DialogPtr theDialog,
                              short itemHit,
                              void* params,
                              long refcon);
void Example3(void);
 
 
// FUNCTIONS
void Example3(void)
{
    ComponentResult result;
    Point where;
    ComponentInstance ci;
    short sref;
    SFTypeList typeList;
    SFReply reply;
    short firstFile = true;
 
    //  Open the Standard Compression Dialog component.
 
    ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
    if (ci)
    {
 
        //  Tell SFGetFilePreview to center on the best monitor.
 
        where.h = where.v = -2;
 
        //  Show only 'PICT' files in the file list.
 
        typeList[0] = 'PICT';
 
        //  Keep asking the user for files until they cancel.
 
        reply.good = true;
        while (reply.good)
        {
 
            //  Ask user to select PICT file to be compressed.
 
            SFGetFilePreview(where, "\p", nil, 1, typeList, nil, &reply);
            if (reply.good)
            {
 
                //  If they selected a file, open that file.
 
                result = FSOpen(reply.fName, reply.vRefNum, &sref);
                if (!result)
                {
 
                    //  If the file opened successfully, set the picture file to
                    //  be the test image shown in the dialog.  Passing nil for srcRect
                    //  means use the entire image.  Passing 0 for testFlags means
                    //  to use the default system method of displaying the test image
                    //  which is currently a combination of cropping and scaling.
 
                    SCSetTestImagePictFile(ci, sref, nil, 0);
 
                    //  If this is the first picture file being compressed do one-time
                    //  setup of defaults and extended procs described below.
 
                    if (firstFile)
                    {
 
                        //  Select defaults for the picture file.  Subsequent
                        //  picture files will only have defaults chosen for
                        //  them if the user presses the custom ÒDefaultsÓ button
                        //  in the compression dialog.
 
                        result = SCDefaultPictFileSettings(ci, sref, false);
                        if (!result)
                        {
 
                            //  Prepare and set the extended procs to be used by the
                            //  compression dialog.  The filterProc is used to handle
                            //  any events which the compression dialog doesn't know about.
                            //  for
 
                            SCExtendedProcs xprocs;
 
                            //  The filterProc is used to handle any events which the
                            //  compression dialog doesn't know about.  For example,
                            //  the filterProc would handle update events for application
                            //  windows uncovered by the movable modal compression dialog.
                            //  The previous two examples don't supply a filterProc because
                            //  they are not full applications with other windows and a menu
                            //  bar.  However, all applications using the compression dialog
                            //  should provide a filterProc to handle updates for their windows.
                            //
                            //  It is also possible to use the filterProc for update handling, etc.
                            //  without using the custom button. Set the hookProc to nil and
                            //  customName to "\p" and the custom button will not be displayed.
 
                            xprocs.filterProc = NewSCModalFilterProc(Example3FilterProc);
 
                            //  The hookProc handles clicks in the custom button and responds
                            //  accordingly.  In our example, it will change the current settings
                            //  to the defaults for the test image.
 
                            xprocs.hookProc = NewSCModalHookProc(Example3HookProc);
 
                            //  In this example, we pass the component instance of the
                            //  compression dialog in as a refcon.  This value will then
                            //  be available in our filter and hook procs to access the
                            //  the compression dialog component.  This refcon could be
                            //  any value that is useful to the filter and/or hook procs.
 
                            xprocs.refcon = (long)ci;
 
                            //  Copy the string for our custom button into the extended
                            //  procs structure.
 
                            BlockMove("\pDefaults", xprocs.customName, 9);
 
                            //  Set the current extended procs to be our procs.
                            //
                            //  We could clear out the extended procs at any time
                            //  by calling SCSetInfo(ci,scExtendedProcsType,nil);
 
                            result = SCSetInfo(ci, scExtendedProcsType, &xprocs);
                        }
 
                        firstFile = false;
                    }
                    else
                    {
 
                        //  If this is not the first pass, we probably want to clear out
                        //  the color table chosen as the default in the first pass because
                        //  it's most likely not appropriate for the current picture.  We could
                        //  do this by calling SCSetInfo(ci,scColorTableType,nil) which would
                        //  remove any custom color table completely.  The picture would then
                        //  be compressed using the standard Macintosh color tables.
                        //
                        //  A better thing to do would be to keep the current defaults but
                        //  set a new color table appropriate for the picture.  Unfortunately,
                        //  there isn't a call to just get the default color table from the
                        //  picture file.  That means saving the current settings, getting the
                        //  default settings including a new color table, then restoring
                        //  the previous settings while leaving the new color table.
 
                        Handle h;
 
                        //  Get a handle containing the current spatial compression settings.
                        //  If we were dealing with sequences of images, this handle would also
                        //  contain temporal and data rate settings.  The handle only includes
                        //  information useful across reboots.  It does not include information
                        //  such as the current test image, color table, window position, etc.
                        //  The handle is created for us but we must dispose it.
 
                        result = SCGetInfo(ci, scSettingsStateType, &h);
                        if (!result)
                        {
 
                            //  Get default settings based on the picture file we are compressing.
                            //  This includes the color table we will be interested in.
 
                            result = SCDefaultPictFileSettings(ci, sref, false);
                            if (!result)
 
                            //  Restore the compression settings while leaving the color
                            //  table set to the one from the current picture file.
 
                                result = SCSetInfo(ci, scSettingsStateType, &h);
 
                            //  We have to throw away the handle created by SCGetInfo.
 
                            DisposeHandle(h);
                        }
                    }
 
                    //  If no errors have occured continue.
 
                    if (!result)
                    {
 
                        //  Display the compress dialog to the user and request compression
                        //  settings from them.  Note that the result code returned could
                        //  include scUserCancelled.
 
                        result = SCRequestImageSettings(ci);
                        if (!result)
                        {
 
                            //  Compress the picture file with the settings chosen by the user.
                            //  The settings include any custom color table found in the source
                            //  picture if still appropriate for the depth chosen by the user.
                            //
                            //  Again note that we are able to pass the source file ref for both the
                            //  source and destination picture files.  In this case, the picture
                            //  file will be compressed in place.  It would probably be better to
                            //  ask the user for a name to save the compressed file as, rather than
                            //  compressing it in place.
 
                            result = SCCompressPictureFile(ci, sref, sref);
                        }
                    }
 
                    //  Close the source picture file.
 
                    FSClose(sref);
                }
            }
        }
 
        //  Close the Standard Compression Dialog component.
 
        CloseComponent(ci);
    }
}
 
 
pascal Boolean Example3FilterProc(DialogPtr theDialog,
                                  EventRecord* theEvent,
                                  short* itemHit,
                                  long refcon)
{
#pragma unused (itemHit, refcon)
 
    if (theEvent->what == updateEvt)
    {
        if ((WindowPtr)theEvent->message != theDialog)
        {
            // handle updates for application windows
        }
    }
    return (false);
}
 
 
pascal short Example3HookProc(DialogPtr theDialog,
                              short itemHit,
                              void* params,
                              long refcon)
{
#pragma unused (theDialog)
 
    //  Check to see if the item clicked in is our custom button.
 
    if (itemHit == scCustomItem)
    {
 
        //  Let Standard Compression select some defaults for our picture file.
 
        SCDefaultPictFileSettings(params, *(short*)refcon, false);
 
        //  Note that we could set test image in here if we wanted.
    }
 
    //  Always return the itemHit.
 
    return (itemHit);
}
 
 
// MAIN FUNCTION
void main(void)
{
    InitGraf(&qd.thePort);
    InitFonts();
    FlushEvents(everyEvent, 0);
    InitWindows();
    InitMenus();
    InitDialogs(nil);
    InitCursor();
    MaxApplZone();
 
    Example3();
}