Cool Effects with Core Image!

posted by crafterm, 31 December 2007

In a previous article I described how to use Core Image as the backend image processor for Attachment Fu in your Rails applications. In that particular article we looked at supporting image scaling and thumbnails to be compatible with the other Attachment Fu backends such as RMagick and ImageScience.

With Core Image available however, we have an entire range of post processing filters available to use at our fingertips. In this article we’ll step through a few of these additional filter options that you can use to post process your images with.

Here’s a few examples of what we can do with Core Image post file upload. All of the following examples use the following input image taken in Berlin while at RailsConf EU (also used in the performance measurements article):

Greyscale or Sepia

A scaled version of the source image is cool, but how about an automatic greyscale or sepia version of the image:

Greyscale

Sepia

Code Fragment

module RedArtisan
  module CoreImage
    module Filters
      module Color

        def greyscale(color = nil, intensity = 1.00)
          create_core_image_context(@original.extent.size.width, @original.extent.size.height)

          color = OSX::CIColor.colorWithString("1.0 1.0 1.0 1.0") unless color

          @original.color_monochrome :inputColor => color, :inputIntensity => intensity do |greyscale|
            @target = greyscale
          end
        end

        def sepia(intensity = 1.00)
          create_core_image_context(@original.extent.size.width, @original.extent.size.height)

          @original.sepia_tone :inputIntensity => intensity do |sepia|
            @target = sepia
          end
        end

      end
    end
  end
end

Exposure and Noise Control

Another option for us is to automatically adjust exposure and noise parameters upon upload to brighten images up, or remove unwanted noise from lower quality images:

1 F-Stop

2 F-Stops

Noise Removal

Code Fragment

module RedArtisan
  module CoreImage
    module Filters
      module Quality

        def reduce_noise(level = 0.02, sharpness = 0.4)
          create_core_image_context(@original.extent.size.width, @original.extent.size.height)

          @original.noise_reduction :inputNoiseLevel => level, :inputSharpness => sharpness do |noise_reduced|
            @target = noise_reduced
          end
        end

        def adjust_exposure(input_ev = 0.5)
          create_core_image_context(@original.extent.size.width, @original.extent.size.height)

          @original.exposure_adjust :inputEV => input_ev do |adjusted|
            @target = adjusted
          end          
        end

      end
    end
  end
end

Watermarking

Sometimes we’d like to automatically add a watermark to our images, either with a single watermark image, or as a tiled watermark image:

Single Watermark

Tiled Watermark

Code Fragment

module RedArtisan
  module CoreImage
    module Filters
      module Watermark

        def watermark(watermark_image, tile = false, strength = 0.1)
          create_core_image_context(@original.extent.size.width, @original.extent.size.height)

          if watermark_image.respond_to? :to_str
            watermark_image = OSX::CIImage.from(watermark_image.to_str)
          end

          if tile
            tile_transform = OSX::NSAffineTransform.transform
            tile_transform.scaleXBy_yBy 1.0, 1.0

            watermark_image.affine_tile :inputTransform => tile_transform do |tiled|
              tiled.crop :inputRectangle => vector(0, 0, @original.extent.size.width, @original.extent.size.height) do |tiled_watermark|
                watermark_image = tiled_watermark
              end
            end
          end

          @original.dissolve_transition :inputTargetImage => watermark_image, :inputTime => strength do |watermarked|
            @target = watermarked
          end
        end

      end
    end
  end
end

Funky Effects

We can also use cool and funky effects used in applications like Photobooth, here’s an example using the edge colouring algorithm:

Edges

Core Fragment

module RedArtisan
  module CoreImage
    module Filters
      module Effects

        def edges(intensity = 1.00)
          create_core_image_context(@original.extent.size.width, @original.extent.size.height)

          @original.edges :inputIntensity => intensity do |edged|
            @target = edged
          end
        end

      end
    end
  end
end

The sign artwork works particularly well with this algorithm.

Core Image Processor

All of the code above is also available as a usable image processor via git.

Some examples of using the processor:

require 'red_artisan/core_image/processor'

# generate some test output images for various effects

processor = RedArtisan::CoreImage::Processor.new('berlin.jpg')

grey = processor.greyscale
grey.save 'results/berlin-grey.jpg'

sepia = processor.sepia
sepia.save 'results/berlin-sepia.jpg'

watermarked = processor.watermark('watermark_image.png')
watermarked.save 'results/berlin-watermarked.jpg'

watermarked = processor.watermark('watermark_image.png', true)
watermarked.save 'results/berlin-watermarked-tiled.jpg'

noise_reduced = processor.reduce_noise
noise_reduced.save 'results/berlin-noise-reduced.jpg'

exposure_adjusted = processor.adjust_exposure
exposure_adjusted.save 'results/berlin-exposure-adjusted-half-stop.jpg'

exposure_adjusted = processor.adjust_exposure(2.0)
exposure_adjusted.save 'results/berlin-exposure-adjusted-two-stops.jpg'

edge = processor.edges
edge.save 'results/berlin-edge.jpg'

Summary

The above shows us only a fraction of what can be done with the 100+ filters Core Image provides by default. There’s many other filters that let you create all sorts of effects with single and multiple images combined. Enjoy!