|
|
[Home](Home) | [Contents](Contents) | [Previous - Drawing in a Bitmap Context](DrawingInABitmapContext) | [Next - Image Metadata](ImageMetadata)
|
|
|
|
|
|
## This is kind of panning out more as a reference document than a using document.
|
|
|
|
|
|
### Tracking down errors
|
|
|
|
|
|
When something goes wrong with the interpretation of the json or plist data when creating or rendering a image filter chain object then smig will often return a terse error message. When this happens it is likely that there will be useful information in the MovingImages' log file. The [Introduction to using MovingImages debugging section describes how to view the log file](UsingMovingImages#debugging).
|
|
|
When something goes wrong with the interpretation of the json or plist data when creating or rendering a image filter chain object then smig will return a terse error message. When this happens there will be useful information in MovingImages' log file. The [Introduction to using MovingImages debugging section describes how to view the log file](UsingMovingImages#debugging).
|
|
|
|
|
|
### Getting a list of the CoreImage filters
|
|
|
|
... | ... | @@ -16,7 +14,7 @@ To get the list of filters that belong to particular category: |
|
|
|
|
|
smig getproperty -type imagefilterchain -property imagefilters -filtercategory CICategoryDistortionEffect
|
|
|
|
|
|
All the filters belong to more than one category. The list of categories, from Apple's documentation are:
|
|
|
All the filters belong to more than one category. The list of categories, [from Apple's documentation are](https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_concepts/ci_concepts.html):
|
|
|
|
|
|
CICategoryBlur
|
|
|
CICategoryColorAdjustment
|
... | ... | @@ -33,7 +31,7 @@ CICategoryTransition |
|
|
|
|
|
### Getting the attributes of a CoreImage filter
|
|
|
|
|
|
To be able to create a property list or a json object that you use to setup a core image filter in a filter chain, you need to know what the list of keys are for each filter and what their expected range of values is. To get the filter description you can get the "imagefilterattribute" property from the "imagefilterchain" type. The information can be returned in one of 3 ways. Either as a json string (see the example below) or saved to a json or a plist file (-jsonfile, -plistfile). If saving to a file then after the (-jsonfile, -plistfile) option you need to provide a file path.
|
|
|
To be able to create a property list dictionary or json object that you use to setup a core image filter in a filter chain, you need to know what the list of keys are for each filter are and for each key what the range of allowed values is that can be assigned to the filter. To get the filter description you can get the "imagefilterattribute" property from the "imagefilterchain" type. The information can be returned in one of 3 ways. Either as a json string (see the example below) or saved to a json or a plist file (-jsonfile, -plistfile). If saving to a file then after the (-jsonfile, -plistfile) option you need to provide a file path.
|
|
|
|
|
|
The following shows you how to get the properties about the CIDroste filter as a json string.
|
|
|
|
... | ... | @@ -41,15 +39,19 @@ The following shows you how to get the properties about the CIDroste filter as a |
|
|
|
|
|
This returns the non human friendly version of the json string. To quickly view the human friendly version, copy the result and paste it into either: [JSONLint](http://jsonlint.com) or [JSON Editor online](http://jsoneditoronline.org).
|
|
|
|
|
|
Alternatively you can save the result to a file as a json object or a plist dictionary. You do this by replacing the "-jsonstring" switch with a "-jsonfile" or "-propertyfile" option on the command line followed by a path to a file.
|
|
|
|
|
|
In the case of the "-jsonfile" option the text saved to the json file will be in a more human readable form than that returned using the "-jsonstring" option.
|
|
|
|
|
|
### Setting up the properties for a filter
|
|
|
|
|
|
All but a few of the core image filters require inputs. All the numerical inputs for the filters have default values that means for a quick and dirty test of a filter you don't need to assign these values. Other input types like images, require an input as they don't have a default, and input types like CIVector and CIColor have default values, but the default values need to be overridden.
|
|
|
All but a few of the core image filters require inputs. All the numerical inputs for the filters have default values which means for a quick and dirty test of a filter you don't need to assign these values. Other input types like the CIImage class, are required as they don't have a default, and input types like CIVector and CIColor have default values, but the default values need to be overridden.
|
|
|
|
|
|
Each filter in a filter chain, is described by the filter name, a render destination, a name identifier and a list of properties to be assigned. The filter name is the core image name of the filter to be created, and the name identifier is used to chain together filters in a filter chain. Filters later in the chain can reference earlier filters by their name identifier and assign any of their input images to the output image of an earlier filter.
|
|
|
Each filter in a filter chain, is described by the filter name, a name identifier and a list of properties to be assigned. The filter name is the core image name of the filter to be created, and the name identifier is used to identify the filter when chaining filters together to build a filter chain. Filters later in the chain can reference earlier filters by their name identifier and assign any of their input images to the output image of an earlier filter.
|
|
|
|
|
|
{
|
|
|
"cifiltername": "CIUnsharpMask",
|
|
|
"mifiltername" : "com.yvs.renderingfilterchain.example.unsharpmask"
|
|
|
"mifiltername" : "com.yvs.documentation.renderingfilterchain.unsharpmask"
|
|
|
"cifilterproperties": [
|
|
|
{
|
|
|
"cifilterkey": "inputRadius",
|
... | ... | @@ -69,7 +71,7 @@ Each filter in a filter chain, is described by the filter name, a render destina |
|
|
]
|
|
|
}
|
|
|
|
|
|
In the above json example, the core image filter to be created is a Core Image Unsharp Mask filter. The filter is given the identifier "com.yvs.renderingfilterchain.example.unsharpmask" and the filter takes three inputs. These are the input radius, which takes a numeric value, input intensity which also takes a numeric value and an input image which takes a dictionary/json object which describes where to get the image from.
|
|
|
In the above json example, the core image filter to be created is a Core Image Unsharp Mask filter. The filter is given the identifier "com.yvs.documentation.renderingfilterchain.unsharpmask" and the filter takes three inputs. These are the input radius, which takes a numeric value, the input intensity which also takes a numeric value and an input image which takes a dictionary/json object which describes how to obtain the image.
|
|
|
|
|
|
When an input is an image, then the input value is a way to obtain the image and is a json object. The image can be sourced as the output image of a previous filter in the filter chain and if that was the case then the key in the object would be "cifilterindex" and the value is an index to an earlier filter in the filter chain or a key "mifiltername" and the value would be a string which is the name identifier of the earlier filter. If the image is sourced from a bitmap context then the key in the object would be "objectreference" as in the above example which refers to a base object with reference 0. The image can also come from an image importer object in which case the "objectreference" key is also used but that a "imageindex" key should also be supplied specifying the index of the image in the image file. If "imageindex" is not specified and the object reference refers to an image importer object then "imageindex" defaults to 0.
|
|
|
|
... | ... | @@ -109,7 +111,7 @@ In the following example the json object represents the information needed for c |
|
|
|
|
|
### Chaining filters together
|
|
|
|
|
|
The following json object is everything needed to define the filter chain managed by a "imagefilterchain" base object. The render destination is specified using the "cirenderdestination" key. The value for the "cifilterlist" key is a list of filter objects each one describing one filter in the filter list. The order of the filters in this list is important, for a few reasons. The outputImage of the last filter in the filter chain is the the one that renders to the render destination. Since you can refer to an earlier filter in the filter chain by its filter index "cifilterindex" then the order needs to be correct or even if you refer to filters by the name identifier you can only refer to filters earlier in the list of filters.
|
|
|
The following json object is everything needed to define the filter chain managed by a "imagefilterchain" base object. The render destination is specified using the "cirenderdestination" key. The value for the "cifilterlist" key is a list of filter objects each one describing one filter in the filter list. The order of the filters in this list is important, for a few reasons. The outputImage of the last filter in the filter chain is the the one that renders to the render destination. Since you can refer to an earlier filter in the filter chain by its filter index "cifilterindex" then the order needs to be correct or alternatively if you refer to filters by their name identifier you can only refer to filters earlier in the list of filters.
|
|
|
|
|
|
{
|
|
|
"cirenderdestination": {
|
... | ... | @@ -233,15 +235,15 @@ The following json object is everything needed to define the filter chain manage |
|
|
]
|
|
|
}
|
|
|
|
|
|
The filter graph for the above filter chain:
|
|
|
The filter graph for the above filter chain looks like:
|
|
|
|
|
|
![Filter Graph](../raw/master/wiki-images/FilterGraph.jpg "The filter graph for the above json object filter chain representation.")
|
|
|
|
|
|
The radial gradient filter generates an image that has infinite extent. To produce a usable image it is followed by the crop filter. The result of the two filters is:
|
|
|
I'm going to show what the output looks like at each of the stages of the above filter chain so you can see how the final result is built up from the intermediate steps. The radial gradient filter generates an image that has infinite extent. To produce a usable image it is followed by the crop filter. The result of the two filters is:
|
|
|
|
|
|
![CIRadialGradient CICrop](../raw/master/wiki-images/ShadedSphere.jpg "An image produced by using Core Image's radial gradient and crop filters.")
|
|
|
|
|
|
I'm going to step through the different parts of this filter chain. So the input mask image provided to the CIHeightFieldFromMask filter is below, followed by the output image of the CIHeightFieldFromMask filter:
|
|
|
The input mask image provided to the CIHeightFieldFromMask filter is below, followed by the output image of the CIHeightFieldFromMask filter:
|
|
|
|
|
|
![Mask Image](../raw/master/coreimage/images/embossmask/MovingImagesMaskSmall.png "An image used as input for demonstrating the height field and shaded material filters.") ![Generated height field image](../raw/master/wiki-images/HeightField.jpg "The height field image generated by the CIHeightFieldFromMask filter applied to the mask.")
|
|
|
|
... | ... | |