2014-02-23 107 views
1

我試圖創建一個SKEffectNode,它將在黑色背景上變成透明的任何綠色像素。出於測試的目的,當我想出這些東西時,我想確保下面的代碼不會在SKEffectNode的子樹內變成任何透明的東西。下面的代碼實際上防止被抽出的孩子和它吐出了以下錯誤:在SKEffectNode中設置自定義CIColorCube過濾器

CIColorCube inputCubeData is not of the expected length.

這是創建該SKEffectNode

- (SKEffectNode *) newVeil 
{ 
    SKEffectNode *node = [[SKEffectNode alloc] init]; 

    node.shouldEnableEffects = YES; 
    node.filter = [self createFilter]; 

    SKSpriteNode *darkness = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:self.view.frame.size]; 
    node.position = self.view.center; 
    [node addChild:darkness]; 

    return node; 
} 

這方法我怎麼設置過濾器(最多,或者我敢說所有這些代碼都在Apple's dev documents)。

- (CIFilter *) createFilter 
{ 
    // Allocate memory 
    const unsigned int size = 64; 
    float *cubeData = (float *)malloc (size * size * size * sizeof (float) * 4); 
    float *c = cubeData; 
    rgb rgbInput; 
    hsv hsvOutput; 

    // Populate cube with a simple gradient going from 0 to 1 
    for (int z = 0; z < size; z++){ 
     rgbInput.b = ((double)z)/(size-1); // Blue value 
     for (int y = 0; y < size; y++){ 
      rgbInput.g = ((double)y)/(size-1); // Green value 
      for (int x = 0; x < size; x ++){ 
       rgbInput.r = ((double)x)/(size-1); // Red value 
       // Convert RGB to HSV 
       // You can find publicly available rgbToHSV functions on the Internet 
       hsvOutput = rgb2hsv(rgbInput); 
       // Use the hue value to determine which to make transparent 
       // The minimum and maximum hue angle depends on 
       // the color you want to remove 
       float alpha = (hsvOutput.h > 120 && hsvOutput.h < 100) ? 0.0f: 1.0f; 
       // Calculate premultiplied alpha values for the cube 
       c[0] = rgbInput.b * alpha; 
       c[1] = rgbInput.g * alpha; 
       c[2] = rgbInput.r * alpha; 
       c[3] = alpha; 
       c += 4; // advance our pointer into memory for the next color value 
      } 
     } 
    } 
    // Create memory with the cube data 
    NSData *data = [NSData dataWithBytesNoCopy:cubeData 
             length:size 
            freeWhenDone:YES]; 

    CIFilter *colorCube = [CIFilter filterWithName:@"CIColorCube"]; 
    [colorCube setValue:@(size) forKey:@"inputCubeDimension"]; 
    // Set data for cube 
    [colorCube setValue:data forKey:@"inputCubeData"]; 

    return colorCube; 
} 

我只是不能發現問題。 CoreImage沒有太多的經驗。任何人?

更新1

我嘗試導出整個CIFilter到它自己的類。

// PMColorCube.h 

#import <CoreImage/CoreImage.h> 

@interface PMColorCube : CIFilter{ 
    CIImage *inputImage; 
} 
@property (retain, nonatomic) CIImage *inputImage; 
@end 



// PMColorCube.m 

#import "PMColorCube.h" 

typedef struct { 
    double r;  // percent 
    double g;  // percent 
    double b;  // percent 
} rgb; 

typedef struct { 
    double h;  // angle in degrees 
    double s;  // percent 
    double v;  // percent 
} hsv; 

static hsv  rgb2hsv(rgb in); 

@implementation PMColorCube 
@synthesize inputImage; 

hsv rgb2hsv(rgb in) 
{ 
    hsv   out; 
    double  min, max, delta; 

    min = in.r < in.g ? in.r : in.g; 
    min = min < in.b ? min : in.b; 

    max = in.r > in.g ? in.r : in.g; 
    max = max > in.b ? max : in.b; 

    out.v = max;        // v 
    delta = max - min; 
    if(max > 0.0) { 
     out.s = (delta/max);     // s 
    } else { 
     // r = g = b = 0      // s = 0, v is undefined 
     out.s = 0.0; 
     out.h = NAN;       // its now undefined 
     return out; 
    } 
    if(in.r >= max)       // > is bogus, just keeps compilor happy 
     out.h = (in.g - in.b)/delta;  // between yellow & magenta 
    else 
     if(in.g >= max) 
      out.h = 2.0 + (in.b - in.r)/delta; // between cyan & yellow 
     else 
      out.h = 4.0 + (in.r - in.g)/delta; // between magenta & cyan 

    out.h *= 60.0;        // degrees 

    if(out.h < 0.0) 
     out.h += 360.0; 

    return out; 
} 

- (CIImage *) outputImage 
{ 
    const unsigned int size = 64; 
    float *cubeData = (float *)malloc (size * size * size * sizeof (float) * 4); 
    float *c = cubeData; 
    rgb rgbInput; 
    hsv hsvOutput; 

    // Populate cube with a simple gradient going from 0 to 1 
    for (int z = 0; z < size; z++){ 
     rgbInput.b = ((double)z)/(size-1); // Blue value 
     for (int y = 0; y < size; y++){ 
      rgbInput.g = ((double)y)/(size-1); // Green value 
      for (int x = 0; x < size; x ++){ 
       rgbInput.r = ((double)x)/(size-1); // Red value 
       // Convert RGB to HSV 
       // You can find publicly available rgbToHSV functions on the Internet 
       hsvOutput = rgb2hsv(rgbInput); 
       // Use the hue value to determine which to make transparent 
       // The minimum and maximum hue angle depends on 
       // the color you want to remove 
       float alpha = (hsvOutput.h > 120 && hsvOutput.h < 100) ? 0.0f: 1.0f; 
       // Calculate premultiplied alpha values for the cube 
       c[0] = rgbInput.b * alpha; 
       c[1] = rgbInput.g * alpha; 
       c[2] = rgbInput.r * alpha; 
       c[3] = alpha; 
       c += 4; // advance our pointer into memory for the next color value 
      } 
     } 
    } 
    // Create memory with the cube data 
    NSData *data = [NSData dataWithBytesNoCopy:cubeData 
             length:size 
            freeWhenDone:YES]; 

    CIFilter *colorCube = [CIFilter filterWithName:@"CIColorCube"]; 
    [colorCube setValue:@(size) forKey:@"inputCubeDimension"]; 
    // Set data for cube 
    [colorCube setValue:data forKey:@"inputCubeData"]; 

    [colorCube setValue:self.inputImage forKey:kCIInputImageKey]; 
    CIImage *result = [colorCube valueForKey:kCIOutputImageKey]; 

    return result; 
} 
@end 

我在運行時

+0

,用於spritekit過濾它提到的文檔的地方必須有一個inputImage的和outputImage參數 - 這是你的過濾器的情況下? – LearnCocos2D

+0

https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKEffectNode_Ref/Reference/Reference.html#//apple_ref/occ/cl/SKEffectNode。 「啓用效果後,效果節點會將其子圖像呈現給圖像,將濾鏡應用於該圖像,然後將濾鏡圖像混合到父級的幀緩衝區中。」看來輸入和輸出已經被處理了。沒有? – mabounassif

+1

此外,「核心圖像過濾器必須具有一個inputImage參數並生成一個outputImage參數,默認值爲nil,如果該值爲nil且啓用了效果節點,則不會進行過濾,但其子項仍然呈現在一個單獨的通行證中,並與父母的幀緩衝區混合「。默認設置應該至少呈現不是這種情況的孩子。 – mabounassif

回答

2

尷尬,因爲它聽起來仍然有同樣的錯誤。創建NSData時我在類方法中傳遞的大小與實際大小不符。固定它像這樣:

// Create memory with the cube data 
    NSData *data = [NSData dataWithBytesNoCopy:cubeData 
             length:size * size * size * sizeof (float) * 4 
            freeWhenDone:YES];