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.
Mac/Gamma_Table_FxPlug.m
/* |
File: Gamma_Table_FxPlug.m |
Abstract: This is the header for the Gamma Table example FxPlug. This |
class calls helper functions which can be called from |
both an FxPlug and an After Effects plug-in. |
NOTE: To use this code you need to have both the FxPlug |
SDK and the After Effects SDK installed. The FxPlug SDK |
can be downloaded from: |
<http://connect.apple.com> |
and choosing "Downloads" then choosing "Applications." |
The After Effects SDK can be downloaded from Adobe's |
web site at: |
<http://www.adobe.com/devnet/aftereffects/> |
Version: 1.0 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by |
Apple 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 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. |
Copyright (C) 2007 Apple Inc. All Rights Reserved. |
*/ |
#import "Gamma_Table_FxPlug.h" |
#include "GammaHelper.h" |
#include "FxHelpers.h" |
#import <FxPlug/FxPlugSDK.h> |
#include <OpenGL/gl.h> |
#include <OpenGL/glext.h> |
#include <OpenGL/glu.h> |
// Set DO_HARDWARE to 1 to try out hardware acceleration |
// Set DO_HARDWARE to 0 to use software-only rendering |
#define DO_HARDWARE 0 |
#if DO_HARDWARE |
//--------------------------------------------------------- |
// gammaARBFragmentProgram |
// |
// ARB fragment program, stored as a C string. |
//--------------------------------------------------------- |
static const char *gammaARBFragmentProgram = |
"!!ARBfp1.0\n" |
"TEMP inSample;\n" |
"TEX inSample, fragment.texcoord[0], texture[0], RECT;\n" |
"POW result.color.r, inSample.r, program.local [ 0 ].r;\n" |
"POW result.color.g, inSample.g, program.local [ 0 ].g;\n" |
"POW result.color.b, inSample.b, program.local [ 0 ].b;\n" |
"MOV result.color.a, inSample.a;\nEND"; |
#endif // DO_HARDWARE |
@implementation Gamma_Table_FxPlug |
//--------------------------------------------------------- |
// initWithAPIManager: |
// |
// This method is called when a plug-in is first loaded, and |
// is a good point to conduct any checks for anti-piracy or |
// system compatibility. Returning NULL means that a plug-in |
// chooses not to be accessible for some reason. |
//--------------------------------------------------------- |
- (id)initWithAPIManager:(id)apiManager; |
{ |
const GLubyte *extensions = glGetString( GL_EXTENSIONS ); |
BOOL cardSupportsARB = strstr( (const char *)extensions, |
"GL_ARB_fragment_program" ) != NULL; |
_apiManager = apiManager; |
_cachedBright = -1; |
_cachedLUT = NULL; |
_lutDepth = 0; |
#if DO_HARDWARE |
if ( cardSupportsARB ) |
{ |
GLint isUnderNativeLimits; |
glGenProgramsARB( 1, &_programID ); |
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, _programID ); |
glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, |
GL_PROGRAM_FORMAT_ASCII_ARB, |
strlen( gammaARBFragmentProgram ), |
gammaARBFragmentProgram ); |
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, _programID ); |
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, |
GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, |
&isUnderNativeLimits ); |
_canDoHardware = ( isUnderNativeLimits == 1 ); |
} |
#else // if !DO_HARDWARE |
_canDoHardware = NO; |
#endif // DO_HARDWARE |
_gammaTable = AllocateAndInitGammaTable (NULL); |
return self; |
} |
//--------------------------------------------------------- |
// dealloc |
// |
// Override of standard NSObject dealloc. Called when plug-in |
// instance is deallocated. |
//--------------------------------------------------------- |
- (void)dealloc |
{ |
if (_programID != 0) |
{ |
glDeleteProgramsARB( 1, &_programID ); |
} |
if (_gammaTable != NULL) |
{ |
FXHFreeHandle (NULL, _gammaTable); |
} |
[super dealloc]; |
} |
//--------------------------------------------------------- |
// variesOverTime |
// |
// This method should return YES if the plug-in's output can |
// vary over time even when all of its parameter values remain |
// constant. |
//--------------------------------------------------------- |
- (BOOL)variesOverTime |
{ |
return NO; |
} |
//--------------------------------------------------------- |
// addParameters |
// |
// This method is where a plug-in defines its list of parameters. |
//--------------------------------------------------------- |
- (BOOL)addParameters |
{ |
id parmsApi; |
parmsApi = [_apiManager apiForProtocol:@protocol(FxParameterCreationAPI)]; |
if ( parmsApi != NULL ) |
{ |
SetupGammaParameters (parmsApi); |
return YES; |
} |
else |
return NO; |
} |
//--------------------------------------------------------- |
// parameterChanged: |
// |
// This method will be called whenever a parameter value has changed. |
// This provides a plug-in an opportunity to respond by changing the |
// value or state of some other parameter. |
//--------------------------------------------------------- |
- (BOOL)parameterChanged:(UInt32)parmId |
{ |
return YES; |
} |
- (NSDictionary*)properties |
{ |
return [NSDictionary dictionaryWithObjectsAndKeys: |
[NSNumber numberWithBool:NO], kFxPropertyKey_SupportsRowBytes, |
[NSNumber numberWithBool:NO], kFxPropertyKey_SupportsR408, |
[NSNumber numberWithBool:NO], kFxPropertyKey_SupportsR4fl, |
[NSNumber numberWithBool:YES], kFxPropertyKey_PixelIndependent, |
[NSNumber numberWithBool:NO], kFxPropertyKey_MayRemapTime, |
[NSNumber numberWithBool:YES], kFxPropertyKey_PreservesAlpha, |
nil]; |
} |
//--------------------------------------------------------- |
// getOutputWidth:height:withInput:withInfo: |
// |
// This is where a filter defines the width and height of |
// its output, given a description of its input. |
//--------------------------------------------------------- |
- (BOOL)getOutputWidth:(UInt32 *)width |
height:(UInt32 *)height |
withInput:(FxImageInfo)inputInfo |
withInfo:(FxRenderInfo)renderInfo |
{ |
if ( width != NULL && height != NULL ) |
{ |
*width = inputInfo.width; |
*height = inputInfo.height; |
return YES; |
} |
else |
return NO; |
} |
//--------------------------------------------------------- |
// renderOutput:withInput:withInfo: |
// |
// This method renders the plug-in's output into the given |
// destination, using the given FxImage object as its image |
// input, with the given render options. The plug-in may |
// retrieve parameters as needed here, using the appropriate |
// host APIs. The output image will either be an FxBitmap |
// or an FxTexture, depending on the plug-in's capabilities, |
// as declared in the frameSetup:hardware:software: method. |
//--------------------------------------------------------- |
- (BOOL)renderOutput:(FxImage *)outputImage |
withInput:(FxImage *)inputImage |
withInfo:(FxRenderInfo)renderInfo |
{ |
BOOL retval = YES; |
id parmsApi; |
parmsApi = [_apiManager apiForProtocol:@protocol(FxParameterRetrievalAPI)]; |
if ( parmsApi != NULL ) |
{ |
// Call our helper method to get a floating point parameter. Note |
// that this same method can also be called from an After Effects |
// plug-in |
double gamma = GetFloatParam (parmsApi, kGammaParamID, |
&renderInfo.frame); |
if ( [inputImage imageType] == kFxImageType_TEXTURE ) |
{ |
// If hardware rendering is turned on, render in hardware |
double left, right, top, bottom; |
double tLeft, tRight, tTop, tBottom; |
FxTexture *inTex = (FxTexture *)inputImage; |
FxTexture *outTex = (FxTexture *)outputImage; |
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); |
[inTex getTextureCoords:&tLeft |
right:&tRight |
bottom:&tBottom |
top:&tTop]; |
[outTex getTextureCoords:&left |
right:&right |
bottom:&bottom |
top:&top]; |
glEnable( GL_FRAGMENT_PROGRAM_ARB ); |
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, _programID ); |
// Don't affect alpha! |
glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 0, |
1.0 / gamma, 1.0 / gamma, |
1.0 / gamma, 1.0 ); |
[inTex bind]; |
[inTex enable]; |
glBegin(GL_QUADS); |
{ |
glTexCoord2f( tLeft, tBottom ); |
glVertex2f( left, bottom ); |
glTexCoord2f( tRight, tBottom ); |
glVertex2f( right, bottom ); |
glTexCoord2f( tRight, tTop ); |
glVertex2f( right, top ); |
glTexCoord2f( tLeft, tTop ); |
glVertex2f( left, top ); |
} |
glEnd(); |
glDisable( GL_FRAGMENT_PROGRAM_ARB ); |
[inTex disable]; |
glBindTexture (GL_TEXTURE_RECTANGLE_EXT, 0); |
} |
else if ( [inputImage imageType] == kFxImageType_BITMAP ) |
{ |
// Use software rendering |
FxBitmap *inMap = (FxBitmap *)inputImage; |
FxBitmap *outMap = (FxBitmap *)outputImage; |
switch( [outputImage depth] ) |
{ |
case 8: |
{ |
// Call the generic function which regenerates the gamma lookup |
// table. This same method can be called from an After Effects |
// plug-in |
PF_Fixed desiredGamma = (PF_Fixed)(gamma * 65536.0); |
RegenerateTableIfNecessary (*(Gamma_Table**)_gammaTable, |
desiredGamma); |
// Get the pointers to the input and output images pixels |
UInt8 *inData = (UInt8 *)[inMap dataPtr]; |
UInt8 *outData = (UInt8 *)[outMap dataPtr]; |
UInt32 y; |
UInt32 outHeight = [outMap height]; |
UInt32 outWidth = [outMap width]; |
PF_Err err = PF_Err_NONE; |
GammaInfo gammaInfo = { |
(*(Gamma_Table**)_gammaTable)->lut |
}; |
// Now we iterate over the pixels and call our generic function |
// for applying the gamma to each pixel. Note that the GammaFunc |
// function is called by both the FxPlug and the After Effects |
// plug-in, eliminating the need to write it twice! |
for ( y = 0; (y < outHeight) && (err == PF_Err_NONE); ++y ) |
{ |
UInt32 x; |
for ( x = 0; (x < outWidth) && (err == PF_Err_NONE); ++x ) |
{ |
err = GammaFunc ((A_long)(&gammaInfo), |
(A_long)x, |
(A_long)y, |
(PF_Pixel*)inData, |
(PF_Pixel*)outData); |
inData += 4; |
outData += 4; |
} |
} |
if (err != PF_Err_NONE) |
{ |
retval = NO; |
} |
break; |
} |
case 16: |
{ |
// NOTE: You would normally have to write this, too! |
retval = NO; |
break; |
} |
case 32: |
{ |
// NOTE: You would normally have to write this, too! |
retval = NO; |
break; |
} |
} |
} |
else |
retval = NO; |
} |
else |
retval = NO; |
return retval; |
} |
//--------------------------------------------------------- |
// frameSetup:inputInfo:hardware:software: |
// |
// This method will be called before the host app sets up a |
// render. A plug-in can indicate here whether it supports |
// CPU (software) rendering, GPU (hardware) rendering, or |
// both. |
//--------------------------------------------------------- |
- (BOOL)frameSetup:(FxRenderInfo)renderInfo |
inputInfo:(FxImageInfo)inputInfo |
hardware:(BOOL *)canRenderHardware |
software:(BOOL *)canRenderSoftware |
{ |
*canRenderSoftware = YES; |
*canRenderHardware = _canDoHardware; |
return YES; |
} |
//--------------------------------------------------------- |
// frameCleanup |
// |
// This method is called when the host app is done with a frame. |
// A plug-in may release any per-frame retained objects |
// at this point. |
//--------------------------------------------------------- |
- (BOOL)frameCleanup |
{ |
return YES; |
} |
@end |
Copyright © 2008 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2008-06-02