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.