Core Image Programming Guide Part2

Create, Set Up, and Apply Filters

Listing 2-5 shows how to create, set up, and apply a hue filter. You use the filterWithName: method to create a filter whose type is specified by the name argument. The hue adjust filter is named CIHueAdjust. You can obtain a list of filter names by following the instructions in “Getting a List of Filters and Attributes” or you can look up a filter name in Core Image Filter Reference. The input values for a filter are undefined when you first create it, which is why you either need to call the setDefaults method to set the default values or supply values for all input parameters at the time you create the filter by calling the methodfilterWithName:keysAndValues:.

If you don’t know the input parameters for a filter, you can get an array of them using the method inputKeys. (Or, you can look up the input parameters for most of the built-in filters in Core Image Filter Reference.) Set a value for each input parameter whose default value you want to change by calling the method setValue:forKey:.

Listing 2-5 sets two input parameters—the input image and the input angle. Filters, except for generator filters, require an input image. Some require two or more images or textures. The input angle for the hue adjustment filter refers to the location of the hue in the HSV and HLS color spaces. This is an angular measurement that can vary from 0.0 to 2 pi. A value of 0 indicates the color red; the color green corresponds to 2/3 pi radians, and the color blue is 4/3 pi radians.

The last line in Listing 2-5 requests the value that corresponds to the outputImage key. When you request the output image, Core Image evaluates the input parameters and stores the calculations necessary to produce the resulting image. The image is not actually rendered. You can apply another filter and continue the process of applying filters until you want to render the result.

Listing 2-5  Creating, setting up, and applying a hue filter

hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];
[hueAdjust setDefaults];
[hueAdjust setValue: myCIImage forKey: @"inputImage"];
[hueAdjust setValue: [NSNumber numberWithFloat: 2.094]
                    forKey: @"inputAngle"];
result = [hueAdjust valueForKey: @"outputImage"];

If you use one of the Core Image draw methods to render the output image from Listing 2-5, you’ll see what’s shown in Figure 2-2. Next you’ll see how to apply two more filters to the image—gloom (CIGloom) and bump distortion (CIBumpDistortion).

The gloom filter does just that—makes an image gloomy by dulling its highlights. Notice that the code in Listing 2-6 is very similar to that shown in Listing 2-5. It creates a filter and sets default values for the gloom filter. This time, the input image is the output image from the hue adjustment filter. It’s that easy to chain filters together!

Figure 2-2  The image after applying the color controls filter The image after applying the color controls filter

The gloom filter has two input parameters. Rather than use the default values, which you could do, the code sets the input radius to25 and the input intensity to 0.75. The input radius specifies the extent of the effect, and can vary from 0 to 100 with a default value of 10. Recall that you can find the minimum, maximum, and default values for a filter programmatically by retrieving the attribute dictionary for the filter.

The input intensity is a scalar value that specifies a linear blend between the filter output and the original image. The minimum is 0.0, the maximum is 1.0, and the default value is 1.0.

Listing 2-6  Creating, setting up, and applying a gloom filter

gloom = [CIFilter filterWithName:@"CIGloom"];
[gloom setDefaults];
[gloom setValue: result forKey: @"inputImage"];
[gloom setValue: [NSNumber numberWithFloat: 25]
                    forKey: @"inputRadius"];
[gloom setValue: [NSNumber numberWithFloat: 0.75]
                    forKey: @"inputIntensity"];
result = [gloom valueForKey: @"outputImage"];

The code requests the output image but does not draw the image. You’ll see how to draw the image in the next section. Figure 2-3shows what the image would look like if you drew it at this point after processing it with both the hue adjustment and gloom filters.

Figure 2-3  The image after applying the hue adjustment and gloom filters The image after applying the hue adjustment and gloom filters

The bump distortion filter (CIBumpDistortion) creates a bulge in an image that originates at a specified point. Listing 2-7 shows how to create, set up, and apply this filter to the output image from the previous filter, the gloom filter. By now you should be an expert. First, create the filter by providing its name. Then, set the defaults and set the input image to the previous result. The bump distortion takes three parameters: a location that specifies the center of the effect, the radius of the effect, and the input scale. The input scale specifies the direction and the amount of the effect. The default value is –0.5. The range is –10.0 through 10.0. A value of 0 specifies no effect. A negative value creates an outward bump; a positive value creates an inward bump.

Listing 2-7  Creating, setting up, and applying the bump distortion filter

bumpDistortion = [CIFilter filterWithName:@"CIBumpDistortion"];
[bumpDistortion setDefaults];
[bumpDistortion setValue: result forKey: @"inputImage"];
[bumpDistortion setValue: [CIVector vectorWithX:200 Y:150  ]
                    forKey: @"inputCenter"];
[bumpDistortion setValue: [NSNumber numberWithFloat: 100]
                    forKey: @"inputRadius"];
[bumpDistortion setValue: [NSNumber numberWithFloat:  3.0]
                    forKey: @"inputScale"];
result = [bumpDistortion valueForKey: @"outputImage"];

Draw the Result

Drawing the result triggers the processor-intensive operations (GPU or CPU). Core Image provides two methods for drawing:

The following code renders the hue-adjusted, gloom-filtered, bump-distorted image from the previous section:

[myCIContext  drawImage: result
                atPoint: CGPointZero
               fromRect: contextRect];

Figure 2-4 shows the rendered image. In this case, Core Image draws the image at (0,0), which is CGPointZero, and draws into the entire context destination.

Figure 2-4  The image after applying the hue adjustment, gloom, and bump distortion filters The image after applying the hue adjustment, gloom, and bump distortion filters
4. Using Transition Effects
 

Transitions are typically used between images in a slide show or to switch from one scene to another in video. These effects are rendered over time and require that you set up a timer. This section shows how to set up and apply the copy machine transition filter—CICopyMachine—to two still images. The copy machine transition creates a light bar similar to what you see in a copy machine. The light bar sweeps across the initial image to reveal the target image. Figure 2-5 shows what this filter looks like before, partway through, and after the transition from an image of ski boots to an image of a skier.

Figure 2-5  A copy machine transition from ski boots to a skier A copy machine transition from ski boots to a skier

Transition filters require the following tasks:

  1. Create Core Image images (CIImage objects) to use for the transition.

  2. Set up and schedule a timer.

  3. Create a CIContext object.

  4. Create a CIFilter object for the filter to apply to the image.

  5. Set the default values for the filter.

  6. Set the filter parameters.

  7. Set the source and the target images to process.

  8. Calculate the time.

  9. Apply the filter.

  10. Draw the result.

  11. Repeat steps 8–10 until the transition is complete.

You’ll notice that many of these tasks are the same as those required to process an image using a filter other than a transition filter. What’s different is the need to set up a timer and to repeatedly draw the effect at various time intervals throughout the transition.

The awakeFromNib method, shown in Listing 2-8, gets two images (boots.jpg and skier.jpg) and sets them as the source and target images. Using the NSTimer class, a timer is set to repeat every 1/30 second. Note the variables thumbnailWidth andthumbnailHeight. These are used to constrain the rendered images to the view set up in Interface Builder.



You set up a transition filter just as you’d set up any other filter. Listing 2-9 uses the method filterWithName: to create the filter. It then calls setDefaults to initialize all input parameters. The code sets the extent to correspond with the thumbnail width and height that is declared in the awakeFromNib: method shown in Listing 2-8.

The routine uses the thumbnail variables to specify the center of the effect. For this example, the center of the effect is the center of the image, but it doesn’t have to be.

Listing 2-9  Setting up the transition filter

 



The drawRect: routine for the copy machine transition effect is shown in Listing 2-10. This routine sets up a rectangle that’s the same size as the view and then sets up a floating-point value for the rendering time. If the CIContext object hasn’t already been created, the routine creates one. If the transition is not yet set up, the routine calls the setupTransition method (see Listing 2-9). Finally, the routine calls the drawImage:atPoint:fromRect: method, passing the image that should be shown for the rendering time. The imageForTransition: method, shown in Listing 2-11, applies the filter and returns the appropriate image for the rendering time.

Listing 2-10  The drawRect: method for the copy machine transition effect

 



The imageForTransition: method figures out, based on the rendering time, which image is the source image and which one is the target image. It’s set up to allow a transition to repeatedly loop. If your application applies a transition that doesn’t loop, it would not need the if-else construction shown in Listing 2-11.

The routine sets the inputTime value based on the rendering time passed to the imageForTransition: method. It applies the transition, passing the output image from the transition to the crop filter (CICrop). Cropping ensures the output image fits in the view rectangle. The routine returns the cropped transition image to the drawRect: method, which then draws the image.

Listing 2-11  Applying the transition filter

 
- (CIImage *)imageForTransition: (float)t
{
    CIFilter  *crop;
    if(fmodf(t, 2.0) < 1.0f)
    {
        [transition setValue: sourceImage  forKey: @"inputImage"];
        [transition setValue: targetImage  forKey: @"inputTargetImage"];
    }
    else
    {
        [transition setValue: targetImage  forKey: @"inputImage"];
        [transition setValue: sourceImage  forKey: @"inputTargetImage"];
    }
    [transition setValue: [NSNumber numberWithFloat:
                            0.5*(1-cos(fmodf(t, 1.0f) * M_PI))]
                forKey: @"inputTime"];
    crop = [CIFilter filterWithName: @"CICrop"
                    keysAndValues: @"inputImage",
                            [transition valueForKey: @"outputImage"],
                    @"inputRectangle", [CIVector vectorWithX: 0  Y: 0
                                        Z: thumbnailWidth
                                        W: thumbnailHeight],
                    nil];
    return [crop valueForKey: @"outputImage"];
}
 

Each time the timer that you set up fires, the display must be updated. Listing 2-12 shows a timerFired: routine that does just that.

Listing 2-12  Using the timer to update the display

 


Finally, Listing 2-13 shows the housekeeping that needs to be performed if your application switches the source and target images, as the example does.

Listing 2-13  Setting source and target images

 



5. Imaging Dynamical Systems
 
A dynamical system is one whose state changes over time using a calculation that is based on the current state of the system. Complex phenomena—fluid dynamics, stellar formation, saxophone multiphonics, self-organizing systems, and so forth—are typically modeled using iterative functions whose output is presented in graphical format. Imaging dynamical systems requires a way to feed the output of the system back to the input. Imaging these types of systems is not quite as simple as chaining a lot of filters together, as shown in“Processing an Image.” Rather, there needs to be a way to accumulate image output so that it can affect the next iteration. Core Image provides the CIImageAccumulator class for just this purpose. An image accumulator object enables feedback-based image processing for such things as the iterative painting operations required by fluid dynamics simulations.

The code in this section shows how to use a CIImageAccumulator object, but not for anything as complex as modeling dynamical systems. Instead, you’ll see how to use an image accumulator to implement a simple painting application called MicroPaint. A user drags the mouse on a canvas to apply paint. A simple button press sprays a dab of paint. A color well lets the user change color. The user can create output similar to that shown in Figure 2-6.

Figure 2-6  Output from MicroPaint Output from MicroPaint

The “image” starts as a blank canvas. MicroPaint uses an image accumulator to collect the paint applied by the user. When the user clicks Clear, MicroPaint resets the image accumulator to a white canvas. The three essential tasks for using an image accumulator for the MicroPaint application are:

  1. “Create and Initialize an Image Accumulator Object”

  2. “Set Up and Apply a Filter to the Image Accumulator”

  3. “Create a CIContext Object and Draw the Image”

The interface file for the MicroPaint application is shown in Listing 2-14. 

Listing 2-14  The interface for the MicroPaintView



Create and Initialize an Image Accumulator Object

The canvas routine shown in Listing 2-15 creates and initializes an image accumulator object. The bounds of the image accumulator object are set to the bounds of the view, using a 32 bit-per-pixel, fixed-point pixel format (kCIFormatARGB8). The routine also sets up and initializes a constant color generator filter (CIConstantColorGenerator) with the color white. Then it uses the output of the constant color filter to initialize the image accumulator image. The canvas routine sets a blank (white) canvas the first time the application launches and anytime the user clicks the clear button. Otherwise, the routine returns the current image accumulator.

Listing 2-15  Creating and initializing an image accumulator



 

Set Up and Apply a Filter to the Image Accumulator

MicroPaint provides its own filter—a dab filter—that applies paint to the canvas. The filter calculates where and how much paint to apply based upon the location of the mouse (or pen), the brush size and brush spacing (constants defined by the application), and the pressure, which can vary if the user paints with a pressure-sensitive device.

The dab filter is part of the MicroPaint application bundle. Its implementation isn’t discussed here. If you want to create and use your own filters, see “Creating Custom Filters.”

The deposit:pressure: method shown in Listing 2-16 is called whenever there is a mouse-down or mouse-dragged event. A detailed explanation for each numbered line of code appears following the listing.

Listing 2-16  Setting up and applying the dab filter to the accumulated image

 



Here’s what the code does:

  1. Creates a filter for the dab filter.

    Note:  The dab filter is a custom filter created by the application. The process for using custom filters is the same as for using Core Image filters. You create a CIFilter object using the name assigned to the filter, set the input values, and obtain the output image. If you package your filter as an image unit, you must first load it. See “Loading Image Units” for details.

     

  2. Sets the input values for the dab filter.

  3. Sets the image accumulator image as the input image to the dab filter.

  4. Calculates the dirty rectangle, which is based on the location of the mouse and the brush size set by the application.

  5. Sets the image accumulator image to the output of the dab filter, but only in the area specified by the dirty rectangle.

  6. Sets the display to be updated, which calls the drawRect: routine for the view.

Create a CIContext Object and Draw the Image

The drawRect: method shown in Listing 2-17 is called when the deposit:pressure: method sets the display for updating. A detailed explanation for each numbered line of code appears following the listing.

Listing 2-17  The drawRect routine for the Mouse Paint application

 



Here’s what the code does:

  1. Creates a Core Image context by calling the NSGraphicsContext method CIContext. You need to create the context only once; always reuse the CIContext object when you can.

  2. Draws the image returned by the CIImageAccumulator object at the origin (0,0), using the full size of the view.

转载于:https://www.cnblogs.com/pengyingh/articles/2339954.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值