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
我在運行時
,用於spritekit過濾它提到的文檔的地方必須有一個inputImage的和outputImage參數 - 這是你的過濾器的情況下? – LearnCocos2D
https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKEffectNode_Ref/Reference/Reference.html#//apple_ref/occ/cl/SKEffectNode。 「啓用效果後,效果節點會將其子圖像呈現給圖像,將濾鏡應用於該圖像,然後將濾鏡圖像混合到父級的幀緩衝區中。」看來輸入和輸出已經被處理了。沒有? – mabounassif
此外,「核心圖像過濾器必須具有一個inputImage參數並生成一個outputImage參數,默認值爲nil,如果該值爲nil且啓用了效果節點,則不會進行過濾,但其子項仍然呈現在一個單獨的通行證中,並與父母的幀緩衝區混合「。默認設置應該至少呈現不是這種情況的孩子。 – mabounassif