我正在尝试创建一个 SKEffectNode,它将使黑色背景上的任何绿色像素变为透明。出于测试目的,当我弄清楚这些东西时,我想确保以下代码不会在 SKEffectNode 的子树中变得透明。以下代码实际上阻止了孩子被绘制,并吐出以下错误:
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 的开发文档中)。
- (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
在运行时我仍然有同样的错误