Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
PixOps.c
/*  | 
File: PixOps.c  | 
Description:  | 
Routines for simple graphics file creation and manipulation.  | 
Copyright:  | 
Copyright (c) 2003 Apple Computer, Inc. All rights reserved.  | 
Disclaimer:  | 
IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.  | 
        ("Apple") in consideration of your agreement to the following terms, and your | 
use, installation, modification or redistribution of this Apple software  | 
constitutes acceptance of these terms. If you do not agree with these terms,  | 
please do not use, install, modify or redistribute this Apple software.  | 
In consideration of your agreement to abide by the following terms, and subject  | 
to these terms, Apple grants you a personal, non-exclusive license, under AppleĆs  | 
copyrights in this original Apple software (the "Apple Software"), to use,  | 
reproduce, modify and redistribute the Apple Software, with or without  | 
modifications, in source and/or binary forms; provided that if you redistribute  | 
the Apple Software in its entirety and without modifications, you must retain  | 
this notice and the following text and disclaimers in all such redistributions of  | 
the Apple Software. Neither the name, trademarks, service marks or logos of  | 
Apple Computer, Inc. may be used to endorse or promote products derived from the  | 
Apple Software without specific prior written permission from Apple. Except as  | 
expressly stated in this notice, no other rights or licenses, express or implied,  | 
are granted by Apple herein, including but not limited to any patent rights that  | 
may be infringed by your derivative works or by other works in which the Apple  | 
Software may be incorporated.  | 
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO  | 
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED  | 
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR  | 
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN  | 
COMBINATION WITH YOUR PRODUCTS.  | 
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR  | 
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE  | 
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  | 
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION  | 
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT  | 
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN  | 
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
Change History (most recent first):  | 
Wed, Feb 16, 2001 -- created  | 
Wed, Apr 02, 2001 -- added unicode only routines  | 
Wed, Aug 27, 2003 -- morphed to work in TextNameTool sample  | 
*/  | 
#include <ApplicationServices/ApplicationServices.h>  | 
#include <QuickTime/ImageCompression.h>  | 
#include <QuickTime/QuickTimeComponents.h>  | 
#include "PixOps.h"  | 
OSStatus SaveAsJPG(GWorldPtr gworld, char* filepath, int jpgquality) { | 
GraphicsExportComponent theExportComponent;  | 
OSStatus err, result;  | 
Handle dataHandle;  | 
FILE* dataFile;  | 
CodecQ spatialQuality;  | 
    switch (jpgquality) { | 
case minQuality: spatialQuality = codecMinQuality; break;  | 
case lowQuality: spatialQuality = codecLowQuality; break;  | 
case normalQuality: spatialQuality = codecNormalQuality; break;  | 
case highQuality: spatialQuality = codecHighQuality; break;  | 
case maxQuality: spatialQuality = codecMaxQuality; break;  | 
default: return paramErr;  | 
}  | 
/* find the exporter */  | 
result = paramErr;  | 
err = OpenADefaultComponent( GraphicsExporterComponentType, kQTFileTypeJPEG, &theExportComponent );  | 
    if (err == noErr) { | 
err = GraphicsExportSetInputGWorld(theExportComponent, gworld);  | 
        if (err == noErr) { | 
/* perform the export */  | 
result = memFullErr;  | 
dataHandle = NewHandle(0);  | 
            if (dataHandle != NULL) { | 
err = GraphicsExportSetOutputHandle( theExportComponent, dataHandle);  | 
                if (err == noErr) { | 
err = GraphicsExportSetCompressionQuality( theExportComponent, spatialQuality );  | 
                    if (err == noErr) { | 
err = GraphicsExportDoExport( theExportComponent, NULL );  | 
                        if (err == noErr) { | 
/* write the file */  | 
result = fnfErr;  | 
dataFile = fopen(filepath, "w+");  | 
                            if (dataFile != NULL) { | 
HLock(dataHandle);  | 
fwrite(*dataHandle, GetHandleSize(dataHandle), 1, dataFile);  | 
fclose(dataFile);  | 
result = noErr;  | 
}  | 
}  | 
}  | 
}  | 
DisposeHandle(dataHandle);  | 
}  | 
}  | 
CloseComponent( theExportComponent );  | 
}  | 
return result;  | 
}  | 
OSStatus SaveAsPNG(GWorldPtr gworld, char* filepath) { | 
GraphicsExportComponent theExportComponent;  | 
OSStatus err, result;  | 
Handle dataHandle;  | 
FILE* dataFile;  | 
/* find the exporter */  | 
result = paramErr;  | 
err = OpenADefaultComponent( GraphicsExporterComponentType, kQTFileTypePNG, &theExportComponent );  | 
    if (err == noErr) { | 
err = GraphicsExportSetInputGWorld(theExportComponent, gworld);  | 
        if (err == noErr) { | 
/* perform the export */  | 
result = memFullErr;  | 
dataHandle = NewHandle(0);  | 
            if (dataHandle != NULL) { | 
err = GraphicsExportSetOutputHandle( theExportComponent, dataHandle);  | 
                if (err == noErr) { | 
err = GraphicsExportSetDepth( theExportComponent, 4); /* 40 for grayscale */  | 
                    if (err == noErr) { | 
err = GraphicsExportDoExport( theExportComponent, NULL );  | 
                        if (err == noErr) { | 
/* write the file */  | 
result = fnfErr;  | 
dataFile = fopen(filepath, "w+");  | 
                            if (dataFile != NULL) { | 
HLock(dataHandle);  | 
fwrite(*dataHandle, GetHandleSize(dataHandle), 1, dataFile);  | 
fclose(dataFile);  | 
result = noErr;  | 
}  | 
}  | 
}  | 
}  | 
DisposeHandle(dataHandle);  | 
}  | 
}  | 
CloseComponent( theExportComponent );  | 
}  | 
return result;  | 
}  | 
GWorldPtr MakeGWorld(Rect *bounds) { | 
GWorldPtr result;  | 
result = NULL;  | 
if (NewGWorld(&result, sizeof(PixelDataType) * 8, bounds, NULL, NULL, 0) != noErr) result = NULL;  | 
if (result != NULL) LockPixels(GetGWorldPixMap(result));  | 
return result;  | 
}  | 
GWorldPtr MakeGSubWorld(GWorldPtr sourceWorld, Rect *bounds) { | 
Rect r;  | 
GWorldPtr sub;  | 
r = *bounds;  | 
OffsetRect(&r, -r.left, -r.top);  | 
sub = MakeGWorld(&r);  | 
    if (sub != NULL) { | 
SetGWorld(sub, NULL);  | 
CopyBits(GetPortBitMapForCopyBits(sourceWorld),  | 
GetPortBitMapForCopyBits(sub), bounds, &r, srcCopy, NULL);  | 
}  | 
return sub;  | 
}  | 
GWorldPtr MakeGrayscaleGWorld(Rect *bounds) { | 
GWorldPtr result;  | 
CTabHandle theClut;  | 
result = NULL;  | 
theClut = GetCTable(40);  | 
    if (theClut != NULL) { | 
        if (NewGWorld(&result, 8, bounds, theClut, NULL, 0) == noErr) { | 
LockPixels(GetGWorldPixMap(result));  | 
} else result = NULL;  | 
DisposeCTable(theClut);  | 
}  | 
return result;  | 
}  | 
void UnmakeGWorld(GWorldPtr theWorld) { | 
UnlockPixels(GetGWorldPixMap(theWorld));  | 
DisposeGWorld(theWorld);  | 
}  | 
Rect *DiscoverGWorldUsedBounds(GWorldPtr newWorld, Rect *boundingBox, Rect *r) { | 
PixMapHandle thePix;  | 
unsigned char *baseAddr;  | 
long rowBytes;  | 
PixelDataType zeroElt, *rover;  | 
Boolean isEmpty;  | 
long x, y;  | 
Rect box;  | 
thePix = GetGWorldPixMap(newWorld);  | 
baseAddr = (unsigned char*) GetPixBaseAddr(thePix);  | 
rowBytes = GetPixRowBytes(thePix);  | 
zeroElt = * (PixelDataType*) baseAddr;  | 
box = *boundingBox;  | 
/* down from top */  | 
    for ( y = box.top; y < box.bottom ; y++) { | 
        for (isEmpty=true, rover = (PixelDataType*) (baseAddr + y*rowBytes), x=box.left; x<box.right; x++, rover++) { | 
            if ( *rover != zeroElt ) { isEmpty = false; break; } | 
}  | 
if (! isEmpty) break;  | 
}  | 
if (y == box.bottom) return NULL;  | 
box.top = y;  | 
/* up from bottom */  | 
    for ( y = box.bottom; y > box.top ; y--) { | 
        for (isEmpty=true, rover = (PixelDataType*) (baseAddr + (y-1)*rowBytes), x=box.left; x<box.right; x++, rover++) { | 
            if ( *rover != zeroElt ) { isEmpty = false; break; } | 
}  | 
if (! isEmpty) break;  | 
}  | 
box.bottom = y;  | 
/* from left to right */  | 
    for ( x = box.left; x < box.right ; x++) { | 
        for (isEmpty=true, y=box.top; y<box.bottom; y++) { | 
rover = ((PixelDataType*) (baseAddr + y*rowBytes)) + x;  | 
            if ( *rover != zeroElt ) { isEmpty = false; break; } | 
}  | 
if (! isEmpty) break;  | 
}  | 
box.left = x;  | 
/* from right to left */  | 
    for ( x = box.right; x > box.left ; x--) { | 
        for (isEmpty=true, y=box.top; y<box.bottom; y++) { | 
rover = ((PixelDataType*) (baseAddr + y*rowBytes)) + (x-1);  | 
            if ( *rover != zeroElt ) { isEmpty = false; break; } | 
}  | 
if (! isEmpty) break;  | 
}  | 
box.right = x;  | 
/* return the bounding box */  | 
*r = box;  | 
return r;  | 
}  | 
OSStatus GetGraphicsFileBounds(char* filepath, short *width, short *height) { | 
ComponentInstance gi;  | 
OSStatus err, result;  | 
Rect naturalBounds;  | 
FILE* theFile;  | 
long theFileSize;  | 
void* fileData;  | 
PointerDataRef pdr;  | 
/* look for the file */  | 
result = fnfErr;  | 
theFile = fopen(filepath, "r");  | 
    if (theFile) { | 
fseek(theFile, 0, SEEK_END);  | 
theFileSize = ftell(theFile);  | 
fseek(theFile, 0, SEEK_SET);  | 
/* read it into a buffer, make a dataref to the buffer */  | 
result = memFullErr;  | 
fileData = malloc(theFileSize);  | 
        if (fileData != NULL) { | 
fread(fileData, theFileSize, 1, theFile);  | 
pdr = (PointerDataRef) NewHandle(sizeof(PointerDataRefRecord));  | 
            if (pdr != NULL) { | 
(**pdr).data = fileData;  | 
(**pdr).dataLength = theFileSize;  | 
/* identify the file format */  | 
result = paramErr;  | 
err = GetGraphicsImporterForDataRef( (Handle) pdr, PointerDataHandlerSubType, &gi);  | 
                if (err == noErr) { | 
err = GraphicsImportGetNaturalBounds(gi, &naturalBounds);  | 
                    if (err == noErr) { | 
*width = naturalBounds.right - naturalBounds.left;  | 
*height = naturalBounds.bottom - naturalBounds.top;  | 
result = noErr;  | 
}  | 
CloseComponent( gi );  | 
}  | 
DisposeHandle((Handle) pdr);  | 
}  | 
free(fileData);  | 
}  | 
fclose(theFile);  | 
}  | 
/* done */  | 
return result;  | 
}  | 
OSStatus LoadGraphicsFile(char* filepath, GWorldPtr *theWorld, Rect *r) { | 
ComponentInstance gi;  | 
OSStatus err, result;  | 
Rect naturalBounds;  | 
FILE* theFile;  | 
long theFileSize;  | 
void* fileData;  | 
PointerDataRef pdr;  | 
/* look for the file */  | 
result = fnfErr;  | 
theFile = fopen(filepath, "r");  | 
    if (theFile) { | 
fseek(theFile, 0, SEEK_END);  | 
theFileSize = ftell(theFile);  | 
fseek(theFile, 0, SEEK_SET);  | 
/* read it into a buffer, make a dataref to the buffer */  | 
result = memFullErr;  | 
fileData = malloc(theFileSize);  | 
        if (fileData != NULL) { | 
fread(fileData, theFileSize, 1, theFile);  | 
pdr = (PointerDataRef) NewHandle(sizeof(PointerDataRefRecord));  | 
            if (pdr != NULL) { | 
(**pdr).data = fileData;  | 
(**pdr).dataLength = theFileSize;  | 
/* identify the file format */  | 
result = paramErr;  | 
err = GetGraphicsImporterForDataRef( (Handle) pdr, PointerDataHandlerSubType, &gi);  | 
                if (err == noErr) { | 
err = GraphicsImportGetNaturalBounds(gi, &naturalBounds);  | 
                    if (err == noErr) { | 
GWorldPtr localGWorld;  | 
OffsetRect(&naturalBounds, -naturalBounds.left, -naturalBounds.top);  | 
                        if ((localGWorld = MakeGWorld(&naturalBounds)) != NULL) { | 
err = GraphicsImportSetGWorld( gi, localGWorld, GetGWorldDevice(localGWorld));  | 
                            if (err == noErr) { | 
err = GraphicsImportDraw(gi);  | 
                                if (err == noErr) { | 
*r = naturalBounds;  | 
*theWorld = localGWorld;  | 
result = noErr;  | 
}  | 
}  | 
                            if (err != noErr) { | 
UnmakeGWorld(localGWorld);  | 
result = err;  | 
}  | 
}  | 
}  | 
CloseComponent( gi );  | 
}  | 
DisposeHandle((Handle) pdr);  | 
}  | 
free(fileData);  | 
}  | 
fclose(theFile);  | 
}  | 
/* done */  | 
return result;  | 
}  | 
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-27