MyNameIsKo
MyNameIsKo

Reputation: 2301

How do I use an image transition filter in Xcode?

Having followed a tutorial on Ray Wenderlich's site with success, I decided to try and manipulate what I learned and apply it towards a CITransition, particularly CIDissolveTransition. However, I can't seem to get the image to appear even after cross-referencing what I've learned against Apple's own filter documentation (which, I gotta say, are dated and incredibly difficult to adapt outside of their own convoluted examples). Here is what I have so far:

NSURL *url = [NSURL fileURLWithPath:imagePath];
NSURL *url2 = [NSURL fileURLWithPath:image2Path];
CIContext *context;
CIFilter *filter;
CIImage *beginImage, *targetImage;
UIImageView *mainImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[self addSubview:mainImage];

beginImage = [CIImage imageWithContentsOfURL:url];
targetImage = [CIImage imageWithContentsOfURL:url2];

if(context == nil)
{
  NSLog(@"Creating Context");
  context = [CIContext contextWithOptions:nil];
}
if(filter == nil) {
  NSLog(@"Creating filter");
  filter = [CIFilter filterWithName:@"CIDissolveTransition" keysAndValues:@"inputImage",   beginImage, @"inputTargetImage", targetImage, @"inputTime", [NSNumber numberWithFloat:0.5], nil];
}

CIImage *outputImage = [filter outputImage];

CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *newImg = [UIImage imageWithCGImage:cgimg];

[mainImage setImage:newImg];

All I've been getting is a black screen where mainImage should be displaying. The ultimate goal is to be able to cycle through a sequence of images with this dissolve effect using a slider (which I am only assuming will work), but I can't even get this static image to display. Any help will be greatly appreciated.

Upvotes: 1

Views: 2944

Answers (3)

Will Loew-Blosser
Will Loew-Blosser

Reputation: 278

The Apple WWDC 2014 session "Advances in Core Image" listed 115 CIFilters available in iOS. The CIDissolveTransition is listed as supported as of 2014. See session 514 https://developer.apple.com/videos/play/wwdc2014/514/ Try it again !

Upvotes: 1

MyNameIsKo
MyNameIsKo

Reputation: 2301

As Jay mentioned in his answer, iOS doesn't support transitions. However, I found and edited a script that grabs the pixel values of two images and returns a cross of the two based on a percentage. Here's the method:

- (UIImage*)morphImage:(UIImage*)img1
             withImage:(UIImage*)img2
             withValue:(float)val
{  
CGImageRef sourceImage = img1.CGImage;
CGImageRef sourceImage2 = img2.CGImage;

CFDataRef theData;
theData = CGDataProviderCopyData(CGImageGetDataProvider(sourceImage));
CFDataRef theData2;
theData2 = CGDataProviderCopyData(CGImageGetDataProvider(sourceImage2));

UInt8 *pixelData = (UInt8 *) CFDataGetBytePtr(theData);
UInt8 *pixelData2 = (UInt8 *) CFDataGetBytePtr(theData2);

int dataLength = CFDataGetLength(theData);

//color byte increments
int red = 0;
int green = 1;
int blue = 2;
//temporary rgb values for both images
int r1, g1, b1, r2, g2, b2;
//fake slider value
for (int index = 0; index < dataLength; index += 4) {
r1 = pixelData[index + red];
g1 = pixelData[index + green];
b1 = pixelData[index + blue];
r2 = pixelData2[index + red];
g2 = pixelData2[index + green];
b2 = pixelData2[index + blue];

pixelData[index + red] += (r2 - r1) * val;
pixelData[index + green] += (g2 - g1) * val;
pixelData[index + blue] += (b2 - b1) * val;
}

CGContextRef context;
context = CGBitmapContextCreate(pixelData,
                              CGImageGetWidth(sourceImage),
                              CGImageGetHeight(sourceImage),
                              8,
                              CGImageGetBytesPerRow(sourceImage),
                              CGImageGetColorSpace(sourceImage),
                              kCGImageAlphaPremultipliedLast);

CGImageRef newCGImage = CGBitmapContextCreateImage(context);
UIImage *newImage = [UIImage imageWithCGImage:newCGImage];

CGContextRelease(context);
CFRelease(theData);
CGImageRelease(newCGImage);

return newImage;

}

I haven't tested it on a device, but it runs pretty smooth on the simulator when cycling through 6 to 10 200x200 images using a slider. I imagine it could be more efficient by extracting the image pixel data beforehand.

Upvotes: 0

Jay Wardell
Jay Wardell

Reputation: 2290

Your call to filterWithName:keysAndValues: is returning nil because iOS doesn't know how to make a CIDossolveTransition filter. Core Image for iOS doesn't support all the filters that Core image for Mac OS does. See this answer

You can read Apple's Core image Filter reference and see which filters are supported in iOS, but the bad news is that transitions didn't make the cut for iOS 5. The only filter available in iOS 5 that deals with compositing is CISourceOverCompositing, which probably isn't very interesting to you.

Upvotes: 6

Related Questions