ftp.nice.ch/pub/next/graphics/movie/Morph2a.s.tar.gz#/Morph2/Morpher_bak.m

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.