X-Git-Url: https://projects.mako.cc/source/selectricity-live/blobdiff_plain/a38724bea6c09b479a93948b6ef4ef61edd24f39..e75d29998f5348be83dde4b6fd8f5aa437c2dc74:/vendor/plugins/attachment_fu/vendor/red_artisan/core_image/processor.rb diff --git a/vendor/plugins/attachment_fu/vendor/red_artisan/core_image/processor.rb b/vendor/plugins/attachment_fu/vendor/red_artisan/core_image/processor.rb new file mode 100644 index 0000000..965e70c --- /dev/null +++ b/vendor/plugins/attachment_fu/vendor/red_artisan/core_image/processor.rb @@ -0,0 +1,123 @@ +require 'rubygems' +require 'osx/cocoa' +require 'active_support' + +require 'red_artisan/core_image/filters/scale' +require 'red_artisan/core_image/filters/color' +require 'red_artisan/core_image/filters/watermark' +require 'red_artisan/core_image/filters/quality' +require 'red_artisan/core_image/filters/perspective' +require 'red_artisan/core_image/filters/effects' + +# Generic image processor for scaling images based on CoreImage via RubyCocoa. +# +# Example usage: +# +# p = Processor.new OSX::CIImage.from(path_to_image) +# p.resize(640, 480) +# p.render do |result| +# result.save('resized.jpg', OSX::NSJPEGFileType) +# end +# +# This will resize the image to the given dimensions exactly, if you'd like to ensure that aspect ratio is preserved: +# +# p = Processor.new OSX::CIImage.from(path_to_image) +# p.fit(640) +# p.render do |result| +# result.save('resized.jpg', OSX::NSJPEGFileType) +# end +# +# fit(size) will attempt its best to resize the image so that the longest width/height (depending on image orientation) will match +# the given size. The second axis will be calculated automatically based on the aspect ratio. +# +# Scaling is performed by first clamping the image so that its external bounds become infinite, this helps when scaling so that any +# rounding discrepencies in dimensions don't affect the resultant image. We then perform a Lanczos transform on the image which scales +# it to the target size. We then crop the image to the traget dimensions. +# +# If you are generating smaller images such as thumbnails where high quality rendering isn't as important, an additional method is +# available: +# +# p = Processor.new OSX::CIImage.from(path_to_image) +# p.thumbnail(100, 100) +# p.render do |result| +# result.save('resized.jpg', OSX::NSJPEGFileType) +# end +# +# This will perform a straight affine transform and scale the X and Y boundaries to the requested size. Generally, this will be faster +# than a lanczos scale transform, but with a scaling quality trade. +# +# More than welcome to intregrate any patches, improvements - feel free to mail me with ideas. +# +# Thanks to +# * Satoshi Nakagawa for working out that OCObjWrapper needs inclusion when aliasing method_missing on existing OSX::* classes. +# * Vasantha Crabb for general help and inspiration with Cocoa +# * Ben Schwarz for example image data and collaboration during performance testing +# +# Copyright (c) Marcus Crafter released under the MIT license +# +module RedArtisan + module CoreImage + class Processor + + def initialize(original) + if original.respond_to? :to_str + @original = OSX::CIImage.from(original.to_str) + else + @original = original + end + end + + def render(&block) + raise "unprocessed image: #{@original}" unless @target + block.call @target + end + + include Filters::Scale, Filters::Color, Filters::Watermark, Filters::Quality, Filters::Perspective, Filters::Effects + + private + + def create_core_image_context(width, height) + output = OSX::NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(nil, width, height, 8, 4, true, false, OSX::NSDeviceRGBColorSpace, 0, 0) + context = OSX::NSGraphicsContext.graphicsContextWithBitmapImageRep(output) + OSX::NSGraphicsContext.setCurrentContext(context) + @ci_context = context.CIContext + end + + def vector(x, y, w, h) + OSX::CIVector.vectorWithX_Y_Z_W(x, y, w, h) + end + end + end +end + +module OSX + class CIImage + include OCObjWrapper + + def method_missing_with_filter_processing(sym, *args, &block) + f = OSX::CIFilter.filterWithName("CI#{sym.to_s.camelize}") + return method_missing_without_filter_processing(sym, *args, &block) unless f + + f.setDefaults if f.respond_to? :setDefaults + f.setValue_forKey(self, 'inputImage') + options = args.last.is_a?(Hash) ? args.last : {} + options.each { |k, v| f.setValue_forKey(v, k.to_s) } + + block.call f.valueForKey('outputImage') + end + + alias_method_chain :method_missing, :filter_processing + + def save(target, format = OSX::NSJPEGFileType, properties = nil) + bitmapRep = OSX::NSBitmapImageRep.alloc.initWithCIImage(self) + blob = bitmapRep.representationUsingType_properties(format, properties) + blob.writeToFile_atomically(target, false) + end + + def self.from(filepath) + raise Errno::ENOENT, "No such file or directory - #{filepath}" unless File.exists?(filepath) + OSX::CIImage.imageWithContentsOfURL(OSX::NSURL.fileURLWithPath(filepath)) + end + end +end +