这个答案的所有功劳都归Nghia Tran所有。如果你看到这个,谢谢!
结果,一直以来只有一个答案。Nghia Tran写了一篇文章
here
他解决了我确切的用例。
他很乐意提供一个扩展来生成
CIFilter
从一个查找图像,我将粘贴到下面,为将来的开发人员保留这个答案。
您需要导入
CIFilter+LUT.h
如果你用的是斯威夫特。
下面是一个演示如何在GPU上使用它的片段
斯威夫特4
.这离优化还很远,应该缓存上下文等,但这是一个很好的起点。
static func applyFilter(with lookupImage: UIImage, to image: UIImage) -> UIImage? {
guard let cgInputImage = image.cgImage else {
return nil
}
guard let glContext = EAGLContext(api: .openGLES2) else {
return nil
}
let ciContext = CIContext(eaglContext: glContext)
guard let lookupFilter = CIFilter(lookupImage: lookupImage, dimension: 64) else {
return nil
}
lookupFilter.setValue(CIImage(cgImage: cgInputImage),
forKey: "inputImage")
guard let output = lookupFilter.outputImage else {
return nil
}
guard let cgOutputImage = ciContext.createCGImage(output, from: output.extent) else {
return nil
}
return UIImage(cgImage: cgOutputImage)
}
cifilter+lut.h过滤
#import <CoreImage/CoreImage.h>
@import UIKit.UIImage;
@class CIFilter;
@interface CIFilter (LUT)
+(CIFilter *) filterWithLookupImage:(UIImage *)image dimension:(NSInteger) n;
@end
C滤波器+LUT.M
#import "CIFilter+LUT.h"
#import <CoreImage/CoreImage.h>
#import <OpenGLES/EAGL.h>
@implementation CIFilter (LUT)
+(CIFilter *)filterWithLookupImage:(UIImage *)image dimension:(NSInteger)n {
NSInteger width = CGImageGetWidth(image.CGImage);
NSInteger height = CGImageGetHeight(image.CGImage);
NSInteger rowNum = height / n;
NSInteger columnNum = width / n;
if ((width % n != 0) || (height % n != 0) || (rowNum * columnNum != n)) {
NSLog(@"Invalid colorLUT");
return nil;
}
unsigned char *bitmap = [self createRGBABitmapFromImage:image.CGImage];
if (bitmap == NULL) {
return nil;
}
NSInteger size = n * n * n * sizeof(float) * 4;
float *data = malloc(size);
int bitmapOffest = 0;
int z = 0;
for (int row = 0; row < rowNum; row++) {
for (int y = 0; y < n; y++) {
int tmp = z;
for (int col = 0; col < columnNum; col++) {
for (int x = 0; x < n; x++) {
float r = (unsigned int)bitmap[bitmapOffest];
float g = (unsigned int)bitmap[bitmapOffest + 1];
float b = (unsigned int)bitmap[bitmapOffest + 2];
float a = (unsigned int)bitmap[bitmapOffest + 3];
NSInteger dataOffset = (z*n*n + y*n + x) * 4;
data[dataOffset] = r / 255.0;
data[dataOffset + 1] = g / 255.0;
data[dataOffset + 2] = b / 255.0;
data[dataOffset + 3] = a / 255.0;
bitmapOffest += 4;
}
z++;
}
z = tmp;
}
z += columnNum;
}
free(bitmap);
CIFilter *filter = [CIFilter filterWithName:@"CIColorCube"];
[filter setValue:[NSData dataWithBytesNoCopy:data length:size freeWhenDone:YES] forKey:@"inputCubeData"];
[filter setValue:[NSNumber numberWithInteger:n] forKey:@"inputCubeDimension"];
return filter;
}
+ (unsigned char *)createRGBABitmapFromImage:(CGImageRef)image {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
unsigned char *bitmap;
NSInteger bitmapSize;
NSInteger bytesPerRow;
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
bytesPerRow = (width * 4);
bitmapSize = (bytesPerRow * height);
bitmap = malloc(bitmapSize);
if (bitmap == NULL) {
return NULL;
}
colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL) {
free(bitmap);
return NULL;
}
context = CGBitmapContextCreate (bitmap, width, height, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (context == NULL) {
free (bitmap);
}
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
CGContextRelease(context);
return bitmap;
}
@end