This is Morpher_bak.m in view mode; [Download] [Up]
// Morpher.m
//
// created by Martin Wennerberg on Sun 08-Sep-1996
//
// when who modification
#import "Morpher.h"
#import "MorphLine.h"
#import <AppKit/AppKit.h>
#import "algebra.h"
#import "NSBitmapImageRep_editing.h"
#define SMALL_FLOAT 0.00001
static struct RGBA mixRGBA(struct RGBA a, struct RGBA b, float d)
{
struct RGBA res;
res.r = a.r + (b.r - a.r) * d;
res.g = a.g + (b.g - a.g) * d;
res.b = a.b + (b.b - a.b) * d;
res.a = a.a + (b.a - a.a) * d;
return res;
}
static inline NSPoint transform (NSPoint p, NSAffineTransformStruct m)
{
NSPoint res;
res.x = p.x * m.m11 + p.y * m.m21 + m.tX;
res.y = p.x * m.m12 + p.y * m.m22 + m.tY;
return res;
}
static NSArray *copyObjectsInArray(NSArray *source)
{
NSMutableArray *dest = [NSMutableArray arrayWithCapacity:[source count]];
NSEnumerator *sourceEnum = [source objectEnumerator];
MorphLine *sourceObj;
while ((sourceObj = [sourceEnum nextObject]))
[dest addObject:[[sourceObj copy] autorelease]];
return dest;
}
@implementation Morpher
- initWithFirstBitmap:(NSBitmapImageRep *)im0 lastBitmap:(NSBitmapImageRep *)im1
{
self = [super init];
if (!self)
return nil;
firstBitmap = [im0 retain];
lastBitmap = [im1 retain];
return self;
}
- (void)calcMorphBitmap:(NSBitmapImageRep *) bitmap
atDelta:(float) delta
morphLines:(NSArray *) lines
{
MorphLine *morphLine;
NSAffineTransformStruct *trans0; // transformation from 0 to delta
NSAffineTransformStruct *trans1; // transformation from 1 to delta
NSPoint dp; // destination point
NSPoint p0; // source point at 0
NSPoint p1; // source point at 1
struct RGBA RGBA0, RGBA1; // color at 0 and 1
struct RGBA rgba; // destination color (this is what we're trying to calculate)
int lineCount;
int i;
float dissolveDelta;
struct LineCoords *PdQd;
struct LineCoords *destLineCoordinates;
NSPoint D; /* Displacement */
float weight, weightsum;
NSPoint DSUM0, DSUM1; /* Displacement sum for the to images */
float dist;
float dissolveStartSum, dissolveEndSum;
float dissolveStartDelta, dissolveEndDelta;
NSArray *morphLines;
morphLines = copyObjectsInArray(lines);
lineCount = [morphLines count];
trans0 = (NSAffineTransformStruct *) alloca (lineCount * sizeof(NSAffineTransformStruct));
trans1 = (NSAffineTransformStruct *) alloca (lineCount * sizeof(NSAffineTransformStruct));
destLineCoordinates = (struct LineCoords *) alloca (lineCount * sizeof(struct LineCoords));
[self fillTransMatrixes:trans0 withDeltaFrom:delta to:0 morphLines:morphLines];
[self fillTransMatrixes:trans1 withDeltaFrom:delta to:1 morphLines:morphLines];
[self fillDestLineCoordinates:destLineCoordinates delta:delta morphLines:morphLines];
// Loop through all pixels in the destination bitmap and set them to the morphed colors
for (dp.y = 0; dp.y < 1; dp.y += 1.0 / [bitmap size].height)
{
progress = dp.y / [bitmap size].height;
for (dp.x = 0; dp.x < 1; dp.x += 1.0 / [bitmap size].width)
{
/* Calc the SourcePoints p0 and p1 */
D = NSZeroPoint;
weightsum = 0.0;
DSUM0 = NSZeroPoint;
DSUM1 = NSZeroPoint;
dissolveStartSum = 0.0;
dissolveEndSum = 0.0;
for (i = 0; i < lineCount; ++i)
{
morphLine = [morphLines objectAtIndex:i];
PdQd = &destLineCoordinates[i];
/* calculate the source points to sample */
p0 = transform (dp, trans0[i]);
p1 = transform (dp, trans1[i]);
/* calculate the weight */
D = pt_sub (p0, dp);
dist = line_dist_to_point (PdQd->start, PdQd->end, dp);
weight = pow (pt_dist2(PdQd->start, PdQd->end) / (morphLine->control + dist), morphLine->range);
DSUM0 = pt_sum (DSUM0, pt_scale (D, weight, weight));
weightsum += weight;
D = pt_sub (p1, dp);
DSUM1 = pt_sum (DSUM1, pt_scale (D, weight, weight));
dissolveStartSum += morphLine->dissolveStartDelta * weight;
dissolveEndSum += morphLine->dissolveEndDelta * weight;
}
/* average (by weight) the source points */
p0 = pt_sum(dp, pt_scale(DSUM0, 1.0 / weightsum, 1.0 / weightsum));
p1 = pt_sum(dp, pt_scale(DSUM1, 1.0 / weightsum, 1.0 / weightsum));
dissolveStartDelta = dissolveStartSum / weightsum;
dissolveEndDelta = dissolveEndSum / weightsum;
/* make sure 0 <= dissolveDelta <= 1 */
if (ABS(dissolveEndDelta - dissolveStartDelta) <= SMALL_FLOAT )
if (dissolveStartDelta == 0.0)
dissolveDelta = 1.0;
else if (delta <= dissolveStartDelta)
dissolveDelta = 0.0;
else dissolveDelta = 11.0;
else if (delta <= dissolveStartDelta)
dissolveDelta = 0.0;
else
{
dissolveDelta = (delta - dissolveStartDelta) / (dissolveEndDelta - dissolveStartDelta);
dissolveDelta = MIN (dissolveDelta, 1.0);
dissolveDelta = MAX (dissolveDelta, 0.0);
}
RGBA0 = [firstBitmap RGBAAtPoint:pt_scale (p0, [firstBitmap size].width, [firstBitmap size].height)];
RGBA1 = [lastBitmap RGBAAtPoint:pt_scale ( p1, [lastBitmap size].width, [lastBitmap size].height)];
rgba = mixRGBA (RGBA0, RGBA1, dissolveDelta);
[bitmap setRGBA:rgba atPoint:pt_scale ( dp, [bitmap size].width, [bitmap size].height)];
}
}
progress = 1.0;
}
- (void) fillTransMatrixes:(NSAffineTransformStruct *) matrixes
withDeltaFrom:(float) beforeDelta
to:(float) afterDelta
morphLines:(NSArray *)lines
{
int i;
MorphLine *line;
for (i = 0; i < [lines count]; ++i)
{
line = [lines objectAtIndex:i];
matrixes[i] = [[line transformFromDelta:beforeDelta toDelta:afterDelta] transformStruct];
}
}
- (void) fillDestLineCoordinates:(struct LineCoords *)lines
delta:(float)delta
morphLines:(NSArray *)morphLines
{
int i;
MorphLine *morphLine;
for (i = 0; i < [morphLines count]; ++i)
{
morphLine = [morphLines objectAtIndex:i];
lines[i].start = [morphLine startPointAtDelta:delta];
lines[i].end = [morphLine endPointAtDelta:delta];
}
}
- (float) progress
{
return progress;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.