home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / Rhapsody / Graphics / Morph-2.0a / Morpher_bak.m < prev    next >
Encoding:
Text File  |  1997-12-29  |  6.7 KB  |  201 lines

  1. // Morpher.m 
  2. //
  3. // created by Martin Wennerberg on Sun 08-Sep-1996
  4. //
  5. // when        who    modification
  6.  
  7. #import "Morpher.h"
  8. #import "MorphLine.h"
  9. #import <AppKit/AppKit.h>
  10. #import "algebra.h"
  11. #import "NSBitmapImageRep_editing.h"
  12.  
  13. #define SMALL_FLOAT    0.00001
  14.  
  15. static struct RGBA mixRGBA(struct RGBA a, struct RGBA b, float d)
  16. {
  17.     struct RGBA    res;
  18.  
  19.     res.r = a.r + (b.r - a.r) * d;
  20.     res.g = a.g + (b.g - a.g) * d;
  21.     res.b = a.b + (b.b - a.b) * d;
  22.     res.a = a.a + (b.a - a.a) * d;
  23.  
  24.     return res;
  25. }
  26.  
  27. static inline NSPoint transform (NSPoint p, NSAffineTransformStruct m)
  28. {
  29.     NSPoint res;
  30.     
  31.     res.x = p.x * m.m11 + p.y * m.m21 + m.tX;
  32.     res.y = p.x * m.m12 + p.y * m.m22 + m.tY;
  33.  
  34.     return res;
  35. }
  36.  
  37. static NSArray *copyObjectsInArray(NSArray *source)
  38. {
  39.     NSMutableArray *dest = [NSMutableArray arrayWithCapacity:[source count]];
  40.     NSEnumerator   *sourceEnum = [source objectEnumerator];
  41.     MorphLine        *sourceObj;
  42.  
  43.     while ((sourceObj = [sourceEnum nextObject]))
  44.         [dest addObject:[[sourceObj copy] autorelease]];
  45.     return dest;
  46. }
  47.  
  48. @implementation Morpher
  49. - initWithFirstBitmap:(NSBitmapImageRep *)im0 lastBitmap:(NSBitmapImageRep *)im1
  50. {
  51.     self = [super init];
  52.     if (!self)
  53.         return nil;
  54.  
  55.     firstBitmap = [im0 retain];
  56.     lastBitmap  = [im1 retain];
  57.     
  58.     return self;
  59. }
  60.  
  61. - (void)calcMorphBitmap:(NSBitmapImageRep *) bitmap
  62.                 atDelta:(float) delta
  63.              morphLines:(NSArray *) lines
  64. {
  65.     MorphLine    *morphLine;
  66.     NSAffineTransformStruct    *trans0;    // transformation from 0 to delta
  67.     NSAffineTransformStruct *trans1;    // transformation from 1 to delta
  68.     NSPoint         dp;                    // destination point
  69.     NSPoint         p0;                    // source point at 0
  70.     NSPoint         p1;                    // source point at 1
  71.     struct RGBA         RGBA0, RGBA1;        // color at 0 and 1
  72.     struct RGBA         rgba;                // destination color (this is what we're trying to calculate)
  73.     int             lineCount;
  74.     int             i;
  75.     float         dissolveDelta;
  76.     struct LineCoords      *PdQd;
  77.     struct LineCoords      *destLineCoordinates;
  78.     NSPoint          D;        /* Displacement */
  79.     float         weight, weightsum;
  80.     NSPoint         DSUM0, DSUM1;    /* Displacement sum for the to images */
  81.     float         dist;
  82.     float         dissolveStartSum, dissolveEndSum;
  83.     float         dissolveStartDelta, dissolveEndDelta;
  84.     NSArray        *morphLines;
  85.  
  86.     morphLines = copyObjectsInArray(lines);
  87.     lineCount = [morphLines count];
  88.     
  89.     trans0 = (NSAffineTransformStruct *) alloca (lineCount * sizeof(NSAffineTransformStruct));
  90.     trans1 = (NSAffineTransformStruct *) alloca (lineCount * sizeof(NSAffineTransformStruct));
  91.     destLineCoordinates = (struct LineCoords *) alloca (lineCount * sizeof(struct LineCoords));
  92.  
  93.     [self fillTransMatrixes:trans0 withDeltaFrom:delta to:0 morphLines:morphLines];
  94.     [self fillTransMatrixes:trans1 withDeltaFrom:delta to:1 morphLines:morphLines];
  95.     [self fillDestLineCoordinates:destLineCoordinates delta:delta morphLines:morphLines];
  96.  
  97.     // Loop through all pixels in the destination bitmap and set them to the morphed colors
  98.     for (dp.y = 0; dp.y < 1; dp.y += 1.0 / [bitmap size].height)
  99.     {
  100.         progress = dp.y / [bitmap size].height;
  101.  
  102.         for (dp.x = 0; dp.x < 1; dp.x += 1.0 / [bitmap size].width)
  103.         {
  104.             /* Calc the SourcePoints p0 and p1 */
  105.             D = NSZeroPoint;
  106.             weightsum = 0.0;
  107.             DSUM0 = NSZeroPoint;
  108.             DSUM1 = NSZeroPoint;
  109.             dissolveStartSum = 0.0;
  110.             dissolveEndSum = 0.0;
  111.  
  112.             for (i = 0; i < lineCount; ++i)
  113.             {
  114.                 morphLine = [morphLines objectAtIndex:i];
  115.                 PdQd = &destLineCoordinates[i];
  116.                 
  117.                 /* calculate the source points to sample */
  118.                 p0 = transform (dp, trans0[i]);
  119.                 p1 = transform (dp, trans1[i]);
  120.  
  121.                 /* calculate the weight */
  122.                 D = pt_sub (p0, dp);
  123.                 dist = line_dist_to_point (PdQd->start, PdQd->end, dp);
  124.                 weight = pow (pt_dist2(PdQd->start, PdQd->end) / (morphLine->control + dist), morphLine->range);
  125.                 DSUM0 = pt_sum (DSUM0, pt_scale (D, weight, weight));
  126.                 weightsum += weight;
  127.  
  128.                 D = pt_sub (p1, dp);
  129.                 DSUM1 = pt_sum (DSUM1, pt_scale (D, weight, weight));
  130.  
  131.                 dissolveStartSum += morphLine->dissolveStartDelta * weight;
  132.                 dissolveEndSum += morphLine->dissolveEndDelta * weight;
  133.             }
  134.             /* average (by weight) the source points */
  135.             p0 = pt_sum(dp, pt_scale(DSUM0, 1.0 / weightsum, 1.0 / weightsum));
  136.             p1 = pt_sum(dp, pt_scale(DSUM1, 1.0 / weightsum, 1.0 / weightsum));
  137.  
  138.             dissolveStartDelta = dissolveStartSum / weightsum;
  139.             dissolveEndDelta = dissolveEndSum / weightsum;
  140.  
  141.             /* make sure 0 <= dissolveDelta <= 1 */
  142.             if (ABS(dissolveEndDelta - dissolveStartDelta) <= SMALL_FLOAT )
  143.                     if (dissolveStartDelta == 0.0)
  144.                             dissolveDelta = 1.0;
  145.                     else if (delta <= dissolveStartDelta)
  146.                             dissolveDelta = 0.0;
  147.                     else dissolveDelta = 11.0;
  148.             else if (delta <= dissolveStartDelta)
  149.                     dissolveDelta = 0.0;
  150.             else
  151.             {
  152.                     dissolveDelta = (delta - dissolveStartDelta) / (dissolveEndDelta - dissolveStartDelta);
  153.                     dissolveDelta = MIN (dissolveDelta, 1.0);
  154.                     dissolveDelta = MAX (dissolveDelta, 0.0);
  155.             }
  156.  
  157.             RGBA0 = [firstBitmap RGBAAtPoint:pt_scale (p0, [firstBitmap size].width, [firstBitmap size].height)];
  158.             RGBA1  = [lastBitmap  RGBAAtPoint:pt_scale ( p1,  [lastBitmap size].width, [lastBitmap size].height)];
  159.             rgba = mixRGBA (RGBA0, RGBA1, dissolveDelta);
  160.             [bitmap setRGBA:rgba atPoint:pt_scale ( dp,  [bitmap size].width, [bitmap size].height)];
  161.         }
  162.     }
  163.     progress = 1.0;
  164. }
  165.  
  166. - (void) fillTransMatrixes:(NSAffineTransformStruct *) matrixes
  167.              withDeltaFrom:(float) beforeDelta
  168.                         to:(float) afterDelta
  169.                 morphLines:(NSArray *)lines
  170. {
  171.     int                         i;
  172.     MorphLine                *line;
  173.  
  174.     for (i = 0; i < [lines count]; ++i)
  175.     {
  176.         line = [lines objectAtIndex:i];
  177.         matrixes[i] = [[line transformFromDelta:beforeDelta toDelta:afterDelta] transformStruct];
  178.     }
  179. }
  180.  
  181. - (void) fillDestLineCoordinates:(struct LineCoords *)lines
  182.                        delta:(float)delta
  183.                       morphLines:(NSArray *)morphLines
  184. {
  185.     int    i;
  186.     MorphLine    *morphLine;
  187.  
  188.     for (i = 0; i < [morphLines count]; ++i)
  189.     {
  190.         morphLine = [morphLines objectAtIndex:i];
  191.         lines[i].start = [morphLine startPointAtDelta:delta];
  192.         lines[i].end = [morphLine endPointAtDelta:delta]; 
  193.     }
  194. }
  195.  
  196. - (float) progress
  197. {
  198.     return progress;
  199. }
  200. @end
  201.