Last active
July 1, 2022 06:43
-
-
Save SheffieldKevin/9873485 to your computer and use it in GitHub Desktop.
Code to demonstrate that the backside image option for the CIPageCurlTransition filter doesn't work.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// main.m | |
// pagecurlbacksidetest | |
// | |
// Created by Kevin Meaney on 30/03/2014. | |
@import Foundation; | |
@import QuartzCore; | |
size_t const kWidth = 600; | |
size_t const kHeight = 400; | |
size_t const kBitsPerComponent = 8; | |
size_t const kBytesPerPixel = 4; | |
CGRect kBoundsRect = { 0.0, 0.0, kWidth, kHeight }; | |
CGRect innerRect = { kWidth / 4.0, kHeight / 4.0, kWidth / 2.0, kHeight / 2.0 }; | |
CGPoint trianglePoint1 = { 100, 350 }; | |
CGPoint trianglePoint2 = { 300, 50 }; | |
CGPoint trianglePoint3 = { 500, 350 }; | |
CGBitmapInfo const bitmapInfo = (CGBitmapInfo)kCGImageAlphaPremultipliedFirst; | |
CGContextRef CreateMyContext() | |
{ | |
CGColorSpaceRef colorSpace; | |
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); | |
CGContextRef context = CGBitmapContextCreate(NULL, kWidth, kHeight, | |
kBitsPerComponent, | |
kWidth * kBytesPerPixel, | |
colorSpace, | |
bitmapInfo); | |
CGColorSpaceRelease(colorSpace); | |
return context; | |
} | |
CGImageRef DrawFillOvalAndCreateImage(CGContextRef context) | |
{ | |
// Draw red oval on a blue background. | |
CGColorRef redColor = CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0); | |
CGColorRef blueColor = CGColorCreateGenericRGB(0.0, 0.0, 1.0, 1.0); | |
CGContextSetFillColorWithColor(context, blueColor); | |
CGContextFillRect(context, kBoundsRect); | |
CGContextSetFillColorWithColor(context, redColor); | |
CGContextFillEllipseInRect(context, innerRect); | |
CGColorRelease(redColor); | |
CGColorRelease(blueColor); | |
CGImageRef image = CGBitmapContextCreateImage(context); | |
return image; | |
} | |
CGImageRef DrawFillRectAndCreateImage(CGContextRef context) | |
{ | |
// Draw green oval on a red background. | |
CGColorRef redColor = CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0); | |
CGColorRef greenColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 1.0); | |
CGContextSetFillColorWithColor(context, redColor); | |
CGContextFillRect(context, kBoundsRect); | |
CGContextSetFillColorWithColor(context, greenColor); | |
CGContextFillRect(context, innerRect); | |
CGColorRelease(redColor); | |
CGColorRelease(greenColor); | |
CGImageRef image = CGBitmapContextCreateImage(context); | |
return image; | |
} | |
CGImageRef DrawFillTriangleAndCreateImage(CGContextRef context) | |
{ | |
// Draw blue triangle on a green bacgkround. | |
CGColorRef blueColor = CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0); | |
CGColorRef greenColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 1.0); | |
CGContextSetFillColorWithColor(context, greenColor); | |
CGContextFillRect(context, kBoundsRect); | |
CGContextSetFillColorWithColor(context, blueColor); | |
CGContextBeginPath(context); | |
CGContextMoveToPoint(context, trianglePoint1.x, trianglePoint1.y); | |
CGContextAddLineToPoint(context, trianglePoint2.x, trianglePoint2.y); | |
CGContextAddLineToPoint(context, trianglePoint3.x, trianglePoint3.y); | |
CGContextClosePath(context); | |
CGContextFillPath(context); | |
CGColorRelease(blueColor); | |
CGColorRelease(greenColor); | |
CGImageRef image = CGBitmapContextCreateImage(context); | |
return image; | |
} | |
void SaveCGImageToAPNGFile(CGImageRef theImage, NSString *path) | |
{ | |
NSString *expandedPath = [path stringByExpandingTildeInPath]; | |
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:expandedPath]; | |
CGImageDestinationRef exporter = CGImageDestinationCreateWithURL( | |
(__bridge CFURLRef)fileURL, | |
kUTTypePNG, 1, NULL); | |
CGImageDestinationAddImage(exporter, theImage, nil); | |
CGImageDestinationFinalize(exporter); | |
CFRelease(exporter); | |
} | |
void SaveCGBitmapContextToAPNGFile(CGContextRef context, NSString *path) | |
{ | |
CGImageRef image = CGBitmapContextCreateImage(context); | |
SaveCGImageToAPNGFile(image, path); | |
CGImageRelease(image); | |
} | |
int main(int argc, const char * argv[]) | |
{ | |
if (argc < 2) | |
{ | |
printf("Please provide a path to where you want to save public.png image."); | |
return 1; | |
} | |
@autoreleasepool | |
{ | |
// Create the context and the images. | |
CGContextRef myContext = CreateMyContext(); | |
CGImageRef sourceImage = DrawFillOvalAndCreateImage(myContext); | |
CGImageRef destinationImage = DrawFillRectAndCreateImage(myContext); | |
CGImageRef backsideImage = DrawFillTriangleAndCreateImage(myContext); | |
// Set up the radial gradient and crop filters for the inputShadingImage | |
CGFloat diam = 300.0; | |
CGFloat radius = diam * 0.5; | |
CIFilter *radialGradientFilter = [CIFilter filterWithName:@"CIRadialGradient"]; | |
[radialGradientFilter setDefaults]; | |
CIVector *centerVector = [CIVector vectorWithX:radius Y:radius]; | |
[radialGradientFilter setValue:centerVector forKey:@"inputCenter"]; | |
// inner circle is 4% of the size of the outer one. | |
[radialGradientFilter setValue:@(radius * 0.04) forKey:@"inputRadius0"]; | |
[radialGradientFilter setValue:@(radius) forKey:@"inputRadius1"]; | |
CIColor *color0 = [CIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.3]; | |
[radialGradientFilter setValue:color0 forKey:@"inputColor0"]; | |
CIColor *color1 = [CIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7]; | |
[radialGradientFilter setValue:color1 forKey:@"inputColor1"]; | |
CIFilter *cropFilter = [CIFilter filterWithName:@"CICrop"]; | |
[cropFilter setDefaults]; | |
CIVector *extentVector; | |
extentVector = [CIVector vectorWithX:0.0 Y:0.0 Z:diam W:diam]; | |
[cropFilter setValue:extentVector forKey:@"inputRectangle"]; | |
[cropFilter setValue:[radialGradientFilter valueForKeyPath:@"outputImage"] | |
forKey:@"inputImage"]; | |
// OK, the radial gradient fill and crop filters have been setup so that | |
// we have generated a shading input image for the CIPageCurlTransition | |
// filter. | |
CIFilter *pageCurlFilter = [CIFilter filterWithName:@"CIPageCurlTransition"]; | |
[pageCurlFilter setDefaults]; | |
[pageCurlFilter setValue:@(0.5) forKey:@"inputTime"]; | |
CIImage *inputImage = [CIImage imageWithCGImage:sourceImage]; | |
[pageCurlFilter setValue:inputImage forKey:@"inputImage"]; | |
CIImage *inputTargetImage = [CIImage imageWithCGImage:destinationImage]; | |
[pageCurlFilter setValue:inputTargetImage forKey:@"inputTargetImage"]; | |
CIImage *inputBacksideImage = [CIImage imageWithCGImage:backsideImage]; | |
[pageCurlFilter setValue:inputBacksideImage forKey:@"inputBacksideImage"]; | |
CIImage *inputShadingImage = [cropFilter valueForKeyPath:@"outputImage"]; | |
[pageCurlFilter setValue:inputShadingImage forKey:@"inputShadingImage"]; | |
// [pageCurlFilter setValue:inputShadingImage forKey:@"inputBacksideImage"]; | |
CIVector *fullExtentVector; | |
fullExtentVector = [CIVector vectorWithX:0.0 Y:0.0 Z:kWidth W:kHeight]; | |
[pageCurlFilter setValue:fullExtentVector forKey:@"inputExtent"]; | |
[pageCurlFilter setValue:@(-2.7) forKey:@"inputAngle"]; | |
[pageCurlFilter setValue:@(120) forKey:@"inputRadius"]; | |
// So the page Filter has been setup. Now we want to create a CIContext | |
// and draw the output CIImage from the pageCurlFilter using the CIContext | |
// into myContext and CGContextRef context. | |
CIContext *ciContext = [CIContext contextWithCGContext:myContext options:nil]; | |
[ciContext drawImage:[pageCurlFilter valueForKey:@"outputImage"] | |
inRect:kBoundsRect | |
fromRect:kBoundsRect]; | |
// Now need to save the image to disk. | |
const char * filePath = argv[1]; | |
SaveCGBitmapContextToAPNGFile(myContext, @(filePath)); | |
CGContextRelease(myContext); | |
CGImageRelease(sourceImage); | |
CGImageRelease(destinationImage); | |
CGImageRelease(backsideImage); | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
true