From 3d752ad6da033ab0fad65e96b3b7fe44fd5f2fc5 Mon Sep 17 00:00:00 2001 From: "Gun.io Whitespace Robot" Date: Wed, 26 Oct 2011 20:05:41 -0400 Subject: [PATCH] Remove whitespace [Gun.io WhitespaceBot] --- README.rdoc | 34 +-- lib/fleximage/aviary_controller.rb | 38 +-- lib/fleximage/blank.rb | 20 +- lib/fleximage/helper.rb | 16 +- lib/fleximage/image_proxy.rb | 22 +- lib/fleximage/legacy_view.rb | 26 +- lib/fleximage/model.rb | 258 ++++++++-------- lib/fleximage/operator/background.rb | 20 +- lib/fleximage/operator/base.rb | 74 ++--- lib/fleximage/operator/border.rb | 20 +- lib/fleximage/operator/crop.rb | 8 +- lib/fleximage/operator/image_overlay.rb | 44 +-- lib/fleximage/operator/resize.rb | 34 +-- lib/fleximage/operator/shadow.rb | 32 +- lib/fleximage/operator/text.rb | 10 +- lib/fleximage/operator/trim.rb | 4 +- lib/fleximage/operator/unsharp_mask.rb | 6 +- lib/fleximage/view.rb | 24 +- tasks/fleximage_tasks.rake | 54 ++-- test/mock_file.rb | 8 +- test/rails_root/app/models/abstract.rb | 2 +- test/rails_root/config/environment.rb | 6 +- .../config/initializers/inflections.rb | 2 +- test/rails_root/public/.htaccess | 6 +- test/rails_root/public/index.html | 54 ++-- .../rails_root/public/javascripts/controls.js | 122 ++++---- .../rails_root/public/javascripts/dragdrop.js | 288 +++++++++--------- test/rails_root/public/javascripts/effects.js | 250 +++++++-------- test/test_helper.rb | 36 +-- test/unit/abstract_test.rb | 8 +- test/unit/basic_model_test.rb | 10 +- test/unit/blank_test.rb | 8 +- test/unit/default_image_path_option_test.rb | 2 +- test/unit/file_upload_from_local_test.rb | 6 +- test/unit/file_upload_from_strings_test.rb | 6 +- test/unit/file_upload_from_url_test.rb | 6 +- test/unit/file_upload_to_db_test.rb | 10 +- test/unit/i18n_messages_test.rb | 16 +- test/unit/image_directory_option_test.rb | 2 +- test/unit/image_proxy_test.rb | 2 +- test/unit/image_storage_format_option_test.rb | 6 +- test/unit/magic_columns_test.rb | 8 +- test/unit/minimum_image_size_test.rb | 8 +- test/unit/operator_base_test.rb | 54 ++-- test/unit/operator_resize_test.rb | 6 +- test/unit/preprocess_image_option_test.rb | 8 +- test/unit/require_image_option_test.rb | 6 +- test/unit/temp_image_test.rb | 6 +- ...tion_date_based_directories_option_test.rb | 2 +- 49 files changed, 849 insertions(+), 849 deletions(-) diff --git a/README.rdoc b/README.rdoc index eab90e9..5b3bb3a 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,14 +1,14 @@ == Installation Gem: (Recommended) - + gem install fleximage - + # in config/environment.rb config.gem 'fleximage' Plugin: - + ./script/plugin install git://github.com/Squeegy/fleximage.git @@ -49,21 +49,21 @@ Fleximage uses a simple templating engine that allows you to re-render images ex == 1. Installation Gem: (Recommended) - + gem install fleximage - + # in config/environment.rb config.gem 'fleximage' Plugin: - + ./script/plugin install git://github.com/Squeegy/fleximage.git == 2. Activating your model You need to let your model know it should be Fleximage-friendly. Lets say you have a model for photos. - + # app/models/photo.rb class Photo < ActiveRecord::Base acts_as_fleximage :image_directory => 'public/images/uploaded_photos' @@ -77,9 +77,9 @@ There are many other options for your model. Refer to the Fleximage::Model: == 3. The upload form Your users need a way to upload their images into your site. Here is how we might render a form to create a photo record. - + # app/views/photos/new.html.erb - + <% form_for @photo, :html => { :multipart => true } do |f| %>

Name
@@ -101,7 +101,7 @@ Your users need a way to upload their images into your site. Here is how we mig <%= f.submit "Create" %>

<% end %> - + *NOTE*: The ":html => { :multipart => true }" is *VERY* *IMPORTANT*. Without this snippet your browser will not send binary data to the server. If things aren't working, check to make sure you have this in your form declaration. The relevant bit of our form code is: @@ -119,7 +119,7 @@ Right along side the upload field is a simple text field, which maps to the "ima You can have just one of these fields, or both. The model will know how to do the right thing either way. When the user submits the form, all you have to do is assign the form contents to your object in standard Rails fashion, and the image is uploaded and saved for you. Creating a new photo may look like this in your controller: - + # app/controllers/photos_controller.rb def create @photo = Photo.new(params[:photo]) @@ -137,10 +137,10 @@ When the user submits the form, all you have to do is assign the form contents t Rails 2 has amazing support for format driven responses. Given a photo object, by default it would have an HTML view that describes information about that photo. With Fleximage, the JPG or (GIF or PNG) view can be the image data itself. A photo HTML view may look like this: - + # app/views/photos/show.html.erb # http://mysite.com/photos/123 - +

<%= image_tag formatted_photo_path(@photo, :jpg) %>

@@ -169,7 +169,7 @@ The filename of the template should look like this: action_name.jpg.flexi '20x20' image.border :size => 10, :color => 'green' image.text 'I like Cheese' - image.unsharp_mask + image.unsharp_mask image.shadow end @@ -221,7 +221,7 @@ You don't want to render JPGs? That's fine. Just link to the format you want ( # app/views/photos/show.html.erb <%= image_tag photo_path(@photo, :gif) %> - + # app/views/photos/show.gif.flexi @photo.operate do |image| @photo.resize '150x150', :crop => true @@ -232,7 +232,7 @@ The Fleximage template engine will automatically detect the format that is being == Converting/Upgrading your master image store Are you upgrading your live app to the new file store creation date based format? Did you start out with PNG image storage, and later realize you need to store with the more space economic JPG instead? Not problem, Fleximage provides some rake tasks to help you out. - + Each conversion rake task requires that you tell it the class for which that you are changing the file store. For example, if you want to change to the new creation date based storage structure, for the class +Photo+, you can run a rake task like this: rake fleximage:convert:to_nested FLEXIMAGE_CLASS=Photo diff --git a/lib/fleximage/aviary_controller.rb b/lib/fleximage/aviary_controller.rb index 532c2f0..aa745a2 100644 --- a/lib/fleximage/aviary_controller.rb +++ b/lib/fleximage/aviary_controller.rb @@ -1,75 +1,75 @@ module Fleximage - + module AviaryController def self.api_key(value = nil) value ? @api_key = value : @api_key end - + def self.api_key=(value = nil) api_key value end - + # Include acts_as_fleximage class method def self.included(base) #:nodoc: base.extend(ClassMethods) end - + module ClassMethods - + # Invoke this method to enable this controller to allow editing of images via Aviary def editable_in_aviary(model_class, options = {}) unless options.has_key?(:secret) raise ArgumentError, ":secret key in options is required.\nExample: editable_in_aviary(Photo, :secret => \"My-deep-dark-secret\")" end - + # Don't verify authenticity for aviary callback - protect_from_forgery :except => :aviary_image_update - + protect_from_forgery :except => :aviary_image_update + # Include the necesary instance methods include Fleximage::AviaryController::InstanceMethods - + # Add before_filter to secure aviary actions before_filter :aviary_image_security, :only => [:aviary_image, :aviary_image_update] - + # Allow the view access to the image hash generation method helper_method :aviary_image_hash - + # Save the Fleximage model class model_class = model_class.constantize if model_class.is_a?(String) dsl_accessor :aviary_model_class, :default => model_class dsl_accessor :aviary_secret, :default => options[:secret] end - + end - + module InstanceMethods - + # Deliver the master image to aviary def aviary_image render :text => @model.load_image.to_blob, :content_type => Mime::Type.lookup_by_extension(self.class.aviary_model_class.image_storage_format.to_s) end - + # Aviary posts the edited image back to the controller here def aviary_image_update @model.image_file_url = params[:imageurl] @model.save render :text => 'Image Updated From Aviary' end - + protected def aviary_image_hash(model) Digest::SHA1.hexdigest("fleximage-aviary-#{model.id}-#{model.created_at}-#{self.class.aviary_secret}") end - + def aviary_image_security @model = self.class.aviary_model_class.find(params[:id]) unless aviary_image_hash(@model) == params[:key] render :text => '

403 Not Authorized

', :status => '403' end end - + end end - + end \ No newline at end of file diff --git a/lib/fleximage/blank.rb b/lib/fleximage/blank.rb index 1be44f5..0e432a2 100644 --- a/lib/fleximage/blank.rb +++ b/lib/fleximage/blank.rb @@ -1,5 +1,5 @@ module Fleximage - + # The +Blank+ class allows easy creation of dynamic images for views which depends models that # do not store images. For example, perhaps you want a rendering of a text label, or a comment, # or some other type of data that is not inherently image based. @@ -8,27 +8,27 @@ module Fleximage # a new Fleximage::Blank object right in your view. # # Usage: - # + # # Fleximage::Blank.new(size, options = {}).operate { |image| ... } # # Use the following keys in the +options+ hash: # # * color: the color the image will be. Can be a named color or a Magick::Pixel object. - # + # # Example: # # # app/views/comments/show.png.flexi # Fleximage::Blank.new('400x150')).operate do |image| # # Start with a chat bubble image as the background # image.image_overlay('public/images/comment_bubble.png') - # + # # # Assuming that the user model acts_as_fleximage, this will draw the users image. # image.image_overlay(@comment.user.file_path, # :size => '50x50', # :alignment => :top_left, # :offset => '10x10' # ) - # + # # # Add the author name text # image.text(@comment.author, # :alignment => :top_left, @@ -40,9 +40,9 @@ module Fleximage # :opacity => 0.5, # } # ) - # + # # # Add the comment body text - # image.text(@comment.body, + # image.text(@comment.body, # :alignment => :top_left, # :offset => '10x90', # :color => color(128, 128, 128), @@ -52,10 +52,10 @@ module Fleximage class Blank include Fleximage::Model acts_as_fleximage - + def initialize(size, options = {}) width, height = Fleximage::Operator::Base.size_to_xy(size) - + @uploaded_image = Magick::Image.new(width, height) do self.colorspace = Magick::RGBColorspace self.depth = 8 @@ -63,7 +63,7 @@ def initialize(size, options = {}) self.format = 'PNG' self.background_color = options[:color] || 'none' end - + @output_image = @uploaded_image end end diff --git a/lib/fleximage/helper.rb b/lib/fleximage/helper.rb index 8672692..8241395 100644 --- a/lib/fleximage/helper.rb +++ b/lib/fleximage/helper.rb @@ -1,6 +1,6 @@ module Fleximage module Helper - + # Creates an image tag that links directly to image data. Recommended for displays of a # temporary upload that is not saved to a record in the databse yet. def embedded_image_tag(model, options = {}) @@ -9,20 +9,20 @@ def embedded_image_tag(model, options = {}) mime = Mime::Type.lookup_by_extension(format.to_s).to_s image = model.output_image(:format => format) data = Base64.encode64(image) - + options = { :alt => model.class.to_s }.merge(options) - + result = image_tag("data:#{mime};base64,#{data}", options) result.gsub(%r{src=".*/images/data:}, 'src="data:') - + rescue Fleximage::Model::MasterImageNotFound => e nil end - + # Creates a link that opens an image for editing in Aviary. # # Options: - # + # # * image_url: url to the master image used by Aviary for editing. Defauls to url_for(:action => 'aviary_image', :id => model, :only_path => false) # * post_url: url where Aviary will post the updated image. Defauls to url_for(:action => 'aviary_image_update', :id => model, :only_path => false) # @@ -33,9 +33,9 @@ def link_to_edit_in_aviary(text, model, options = {}) post_url = options.delete(:image_update_url) || url_for(:action => 'aviary_image_update', :id => model, :only_path => false, :key => key) api_key = Fleximage::AviaryController.api_key url = "http://aviary.com/flash/aviary/index.aspx?tid=1&phoenix&apil=#{api_key}&loadurl=#{CGI.escape image_url}&posturl=#{CGI.escape post_url}" - + link_to text, url, { :target => 'aviary' }.merge(options) end - + end end diff --git a/lib/fleximage/image_proxy.rb b/lib/fleximage/image_proxy.rb index 2721ce6..ff00837 100644 --- a/lib/fleximage/image_proxy.rb +++ b/lib/fleximage/image_proxy.rb @@ -1,5 +1,5 @@ module Fleximage - + # An instance of this class is yielded when Model#operate is called. It enables image operators # to be called to transform the image. You should never need to directly deal with this class. # You simply call image operators on this object when inside an Model#operate block @@ -10,13 +10,13 @@ module Fleximage # # In this example, +image+ is an instance of ImageProxy class ImageProxy - + class OperatorNotFound < NameError #:nodoc: end - + # The image to be manipulated by operators. attr_accessor :image - + # Create a new image operator proxy. def initialize(image, model_obj) @image = image @@ -32,24 +32,24 @@ def width def height @image.rows end - + # A call to an unknown method will look for an Operator by that method's name. # If it finds one, it will execute that operator. def method_missing(method_name, *args) # Find the operator class class_name = method_name.to_s.camelcase operator_class = "Fleximage::Operator::#{class_name}".constantize - + # Define a method for this operator so future calls to this operation are faster self.class.module_eval <<-EOF def #{method_name}(*args) @image = execute_operator(#{operator_class}, *args) end EOF - + # Call the method that was just defined to perform its functionality. send(method_name, *args) - + rescue NameError => e if e.to_s =~ /uninitialized constant Fleximage::Operator::#{class_name}/ raise OperatorNotFound, "No operator Fleximage::Operator::#{class_name} found for the method \"#{method_name}\"" @@ -57,13 +57,13 @@ def #{method_name}(*args) raise e end end - + private # Instantiate and execute the requested image Operator. def execute_operator(operator_class, *args) operator_class.new(self, @image, @model).execute(*args) end - + end - + end \ No newline at end of file diff --git a/lib/fleximage/legacy_view.rb b/lib/fleximage/legacy_view.rb index 1a2a7aa..4c36611 100644 --- a/lib/fleximage/legacy_view.rb +++ b/lib/fleximage/legacy_view.rb @@ -1,18 +1,18 @@ module Fleximage - + # Renders a .flexi template class LegacyView #:nodoc: class TemplateDidNotReturnImage < RuntimeError #:nodoc: end - + def initialize(view) @view = view end - + def render(template, local_assigns = {}) # process the view result = @view.instance_eval do - + # Shorthand color creation def color(*args) if args.size == 1 && args.first.is_a?(String) @@ -21,40 +21,40 @@ def color(*args) Magick::Pixel.new(*args) end end - + # inject assigns into instance variables assigns.each do |key, value| instance_variable_set "@#{key}", value end - + # inject local assigns into reader methods local_assigns.each do |key, value| class << self; self; end.send(:define_method, key) { value } end - + #execute the template eval(template) end - + # Raise an error if object returned from template is not an image record unless result.class.include?(Fleximage::Model::InstanceMethods) raise TemplateDidNotReturnImage, ".flexi template was expected to return a model instance that acts_as_fleximage, but got an instance of <#{result.class}> instead." end - + # Figure out the proper format requested_format = (@view.params[:format] || :jpg).to_sym raise 'Image must be requested with an image type format. jpg, gif and png only are supported.' unless [:jpg, :gif, :png].include?(requested_format) - + # Set proper content type @view.controller.headers["Content-Type"] = Mime::Type.lookup_by_extension(requested_format.to_s).to_s - + # get rendered result rendered_image = result.output_image(:format => requested_format) - + # Return image data return rendered_image ensure - + # ensure garbage collection happens after every flex image render rendered_image.dispose! GC.start diff --git a/lib/fleximage/model.rb b/lib/fleximage/model.rb index a1c96e7..8527a9c 100644 --- a/lib/fleximage/model.rb +++ b/lib/fleximage/model.rb @@ -1,40 +1,40 @@ module Fleximage - + # Container for Fleximage model method inclusion modules module Model - + class MasterImageNotFound < RuntimeError #:nodoc: end - + # Include acts_as_fleximage class method def self.included(base) #:nodoc: base.extend(ClassMethods) end - + # Provides class methods for Fleximage for use in model classes. The only class method is # acts_as_fleximage which integrates Fleximage functionality into a model class. # # The following class level accessors also get inserted. # - # * +image_directory+: (String, no default) Where the master images are stored, directory path relative to your + # * +image_directory+: (String, no default) Where the master images are stored, directory path relative to your # app root. - # * s3_bucket: Name of the bucket on Amazon S3 where your master images are stored. To use this you must + # * s3_bucket: Name of the bucket on Amazon S3 where your master images are stored. To use this you must # call establish_connection! on the aws/s3 gem form your app's initilization to authenticate with your # S3 account. # * +use_creation_date_based_directories+: (Boolean, default +true+) If true, master images will be stored in # directories based on creation date. For example: "#{image_directory}/2007/11/24/123.png" for an # image with an id of 123 and a creation date of November 24, 2007. Turing this off would cause the path - # to be "#{image_directory}/123.png" instead. This helps keep the OS from having directories that are too + # to be "#{image_directory}/123.png" instead. This helps keep the OS from having directories that are too # full. - # * +image_storage_format+: (:png or :jpg, default :png) The format of your master images. Using :png will give - # you the best quality, since the master images as stored as lossless version of the original upload. :jpg - # will apply lossy compression, but the master image file sizes will be much smaller. If storage space is a + # * +image_storage_format+: (:png or :jpg, default :png) The format of your master images. Using :png will give + # you the best quality, since the master images as stored as lossless version of the original upload. :jpg + # will apply lossy compression, but the master image file sizes will be much smaller. If storage space is a # concern, us :jpg. # * +require_image+: (Boolean, default +true+) The model will raise a validation error if no image is uploaded # with the record. Setting to false allows record to be saved with no images. - # * +missing_image_message+: (String, default "is required") Validation message to display when no image was uploaded for + # * +missing_image_message+: (String, default "is required") Validation message to display when no image was uploaded for # a record. - # * +invalid_image_message+: (String default "was not a readable image") Validation message when an image is uploaded, but is not an + # * +invalid_image_message+: (String default "was not a readable image") Validation message when an image is uploaded, but is not an # image format that can be read by RMagick. # * +output_image_jpg_quality+: (Integer, default 85) When rendering JPGs, this represents the amount of # compression. Valid values are 0-100, where 0 is very small and very ugly, and 100 is near lossless but @@ -45,13 +45,13 @@ def self.included(base) #:nodoc: # :color => :transparent
, where :size defines the dimensions of the default image, and :color # defines the fill. :color can be a named color as a string ('red'), :transparent, or a Magick::Pixel object. # * +preprocess_image+: (Block, no default) Call this class method just like you would call +operate+ in a view. - # The image transoformation in the provided block will be run on every uploaded image before its saved as the + # The image transoformation in the provided block will be run on every uploaded image before its saved as the # master image. # # Example: # # class Photo < ActiveRecord::Base - # acts_as_fleximage do + # acts_as_fleximage do # image_directory 'public/images/uploaded' # use_creation_date_based_directories true # image_storage_format :png @@ -61,32 +61,32 @@ def self.included(base) #:nodoc: # default_image_path 'public/images/no_photo_yet.png' # default_image nil # output_image_jpg_quality 85 - # + # # preprocess_image do |image| # image.resize '1024x768' # end # end - # + # # # normal model methods... # end module ClassMethods - - # Use this method to include Fleximage functionality in your model. It takes an - # options hash with a single required key, :+image_directory+. This key should + + # Use this method to include Fleximage functionality in your model. It takes an + # options hash with a single required key, :+image_directory+. This key should # point to the directory you want your images stored on your server. Or # configure with a nice looking block. def acts_as_fleximage(options = {}) - + # Include the necesary instance methods include Fleximage::Model::InstanceMethods - + # Call this class method just like you would call +operate+ in a view. - # The image transoformation in the provided block will be run on every uploaded image before its saved as the + # The image transoformation in the provided block will be run on every uploaded image before its saved as the # master image. def self.preprocess_image(&block) preprocess_image_operation(block) end - + # Internal method to ask this class if it stores image in the DB. def self.db_store? return false if s3_store? @@ -98,52 +98,52 @@ def self.db_store? false end end - + def self.s3_store? !!s3_bucket end - + def self.file_store? !db_store? && !s3_store? end - + def self.has_store? respond_to?(:columns) && (db_store? || s3_store? || image_directory) end - + # validation callback validate :validate_image if respond_to?(:validate) - + # The filename of the temp image. Used for storing of good images when validation fails # and the form needs to be redisplayed. attr_reader :image_file_temp - + # Setter for jpg compression quality at the instance level attr_accessor :jpg_compression_quality - + # Where images get stored dsl_accessor :image_directory - + # Amazon S3 bucket where the master images are stored dsl_accessor :s3_bucket - + # Put uploads from different days into different subdirectories dsl_accessor :use_creation_date_based_directories, :default => true - + # The format are master images are stored in dsl_accessor :image_storage_format, :default => Proc.new { :png } - + # Require a valid image. Defaults to true. Set to false if its ok to have no image for dsl_accessor :require_image, :default => true - - + + def self.translate_error_message(name, fallback, options = {}) translation = I18n.translate "activerecord.errors.models.#{self.model_name.underscore}.#{name}", options if translation.match /translation missing:/ I18n.translate "activerecord.errors.messages.#{name}", options.merge({ :default => fallback }) end end - + # Missing image message #dsl_accessor :missing_image_message, :default => 'is required' def self.missing_image_message(str = nil) @@ -153,13 +153,13 @@ def self.missing_image_message(str = nil) else translate_error_message("missing_image", "is required") end - + else @missing_image_message = str end end - - + + # Invalid image message #dsl_accessor :invalid_image_message, :default => 'was not a readable image' def self.invalid_image_message(str = nil) @@ -173,7 +173,7 @@ def self.invalid_image_message(str = nil) @invalid_image_message = str end end - + # Image too small message # Should include {{minimum}} def self.image_too_small_message(str = nil) @@ -189,36 +189,36 @@ def self.image_too_small_message(str = nil) @image_too_small_message = str end end - + # Sets the quality of rendered JPGs dsl_accessor :output_image_jpg_quality, :default => 85 - + # Set a default image to use when no image has been assigned to this record dsl_accessor :default_image_path - + # Set a default image based on a a size and fill dsl_accessor :default_image - + # A block that processes an image before it gets saved as the master image of a record. # Can be helpful to resize potentially huge images to something more manageable. Set via # the "preprocess_image { |image| ... }" class method. dsl_accessor :preprocess_image_operation - + # Set a minimum size ([x, y] e.g. 200, '800x600', [800, 600]) # Set '0x600' to just enforce y size or # '800x0' to just validate x size. dsl_accessor :validates_image_size - + # Image related save and destroy callbacks if respond_to?(:before_save) after_destroy :delete_image_file before_save :pre_save after_save :post_save end - + # execute configuration block yield if block_given? - + # Create S3 bucket if it's not present if s3_bucket begin @@ -227,10 +227,10 @@ def self.image_too_small_message(str = nil) AWS::S3::Bucket.create(s3_bucket) end end - + # set the image directory from passed options image_directory options[:image_directory] if options[:image_directory] - + # Require the declaration of a master image storage directory if respond_to?(:validate) && !image_directory && !db_store? && !s3_store? && !default_image && !default_image_path raise "No place to put images! Declare this via the :image_directory => 'path/to/directory' option\n"+ @@ -239,31 +239,31 @@ def self.image_too_small_message(str = nil) "Or set a default image to show with :default_image or :default_image_path" end end - + def image_file_exists(file) # File must be a valid object return false if file.nil? - + # Get the size of the file. file.size works for form-uploaded images, file.stat.size works # for file object created by File.open('foo.jpg', 'rb'). It must have a size > 0. return false if (file.respond_to?(:size) ? file.size : file.stat.size) <= 0 - + # object must respond to the read method to fetch its contents. return false if !file.respond_to?(:read) - + # file validation passed, return true true end end - + # Provides methods that every model instance that acts_as_fleximage needs. module InstanceMethods - + # Returns the path to the master image file for this record. - # + # # @some_image.directory_path #=> /var/www/myapp/uploaded_images # - # If this model has a created_at field, it will use a directory + # If this model has a created_at field, it will use a directory # structure based on the creation date, to prevent hitting the OS imposed # limit on the number files in a directory. # @@ -271,21 +271,21 @@ module InstanceMethods def directory_path directory = self.class.image_directory raise 'No image directory was defined, cannot generate path' unless directory - + # base directory directory = "#{RAILS_ROOT}/#{directory}" unless /^\// =~ directory - + # specific creation date based directory suffix. creation = self[:created_at] || self[:created_on] - if self.class.use_creation_date_based_directories && creation + if self.class.use_creation_date_based_directories && creation "#{directory}/#{creation.year}/#{creation.month}/#{creation.day}" else directory end end - + # Returns the path to the master image file for this record. - # + # # @some_image.file_path #=> /var/www/myapp/uploaded_images/123.png def file_path "#{directory_path}/#{id}.#{extension}" @@ -305,16 +305,16 @@ def extension self.class.image_storage_format end end - + def url_format extension.to_sym end - # Sets the image file for this record to an uploaded file. This can - # be called directly, or passively like from an ActiveRecord mass + # Sets the image file for this record to an uploaded file. This can + # be called directly, or passively like from an ActiveRecord mass # assignment. - # - # Rails will automatically call this method for you, in most of the + # + # Rails will automatically call this method for you, in most of the # situations you would expect it to. # # # via mass assignment, the most common form you'll probably use @@ -324,31 +324,31 @@ def url_format # # via explicit assignment hash # Photo.new(:image_file => params[:photo][:image_file]) # Photo.create(:image_file => params[:photo][:image_file]) - # + # # # Direct Assignment, usually not needed # photo = Photo.new # photo.image_file = params[:photo][:image_file] - # + # # # via an association proxy # p = Product.find(1) # p.images.create(params[:photo]) def image_file=(file) if self.class.image_file_exists(file) - + # Create RMagick Image object from uploaded file if file.path @uploaded_image = Magick::Image.read(file.path).first else @uploaded_image = Magick::Image.from_blob(file.read).first end - + # Sanitize image data @uploaded_image.colorspace = Magick::RGBColorspace @uploaded_image.density = '72' - + # Save meta data to database set_magic_attributes(file) - + # Success, make sure everything is valid @invalid_image = false save_temp_image(file) unless @dont_save_temp @@ -370,10 +370,10 @@ def image_file=(file) def image_file has_image? end - + # Assign the image via a URL, which will make the plugin go # and fetch the image at the provided URL. The image will be stored - # locally as a master image for that record from then on. This is + # locally as a master image for that record from then on. This is # intended to be used along side the image upload to allow people the # choice to upload from their local machine, or pull from the internet. # @@ -382,25 +382,25 @@ def image_file_url=(file_url) @image_file_url = file_url if file_url =~ %r{^(https?|ftp)://} file = open(file_url) - + # Force a URL based file to have an original_filename eval <<-CODE def file.original_filename "#{file_url}" end CODE - + self.image_file = file - + elsif file_url.empty? # Nothing to process, move along - + else # invalid URL, raise invalid image validation error @invalid_image = true end end - + # Set the image for this record by reading in file data as a string. # # data = File.read('my_image_file.jpg') @@ -428,7 +428,7 @@ def image_file_temp=(file_name) if !@uploaded_image && file_name && file_name.present? && file_name !~ %r{\.\./} @image_file_temp = file_name file_path = "#{RAILS_ROOT}/tmp/fleximage/#{file_name}" - + @dont_save_temp = true if File.exists?(file_path) File.open(file_path, 'rb') do |f| @@ -444,12 +444,12 @@ def image_file_temp=(file_name) def image_file_url @image_file_url end - + # Return true if this record has an image. def has_image? @uploaded_image || @output_image || has_saved_image? end - + def has_saved_image? if self.class.db_store? !!image_file_data @@ -459,11 +459,11 @@ def has_saved_image? File.exists?(file_path) end end - - # Call from a .flexi view template. This enables the rendering of operators + + # Call from a .flexi view template. This enables the rendering of operators # so that you can transform your image. This is the method that is the foundation # of .flexi views. Every view should consist of image manipulation code inside a - # block passed to this method. + # block passed to this method. # # # app/views/photos/thumb.jpg.flexi # @photo.operate do |image| @@ -485,42 +485,42 @@ def operate!(&block) save end - # Load the image from disk/DB, or return the cached and potentially + # Load the image from disk/DB, or return the cached and potentially # processed output image. def load_image #:nodoc: @output_image ||= @uploaded_image - + # Return the current image if we have loaded it already return @output_image if @output_image - + # Load the image from disk if self.class.db_store? # Load the image from the database column if image_file_data && image_file_data.present? @output_image = Magick::Image.from_blob(image_file_data).first end - + elsif self.class.s3_store? # Load image from S3 filename = "#{id}.#{self.class.image_storage_format}" bucket = self.class.s3_bucket - + if AWS::S3::S3Object.exists?(filename, bucket) @output_image = Magick::Image.from_blob(AWS::S3::S3Object.value(filename, bucket)).first end - + else # Load the image from the disk @output_image = Magick::Image.read(file_path).first - + end - + if @output_image @output_image else master_image_not_found end - + rescue Magick::ImageMagickError => e if e.to_s =~ /unable to open (file|image)/ master_image_not_found @@ -528,7 +528,7 @@ def load_image #:nodoc: raise e end end - + # Convert the current output image to a jpg, and return it in binary form. options support a # :format key that can be :jpg, :gif or :png def output_image(options = {}) #:nodoc: @@ -544,12 +544,12 @@ def output_image(options = {}) #:nodoc: ensure GC.start end - - # Delete the image file for this record. This is automatically ran after this record gets + + # Delete the image file for this record. This is automatically ran after this record gets # destroyed, but you can call it manually if you want to remove the image from the record. def delete_image_file return unless self.class.has_store? - + if self.class.db_store? update_attribute :image_file_data, nil unless frozen? elsif self.class.s3_store? @@ -557,69 +557,69 @@ def delete_image_file else File.delete(file_path) if File.exists?(file_path) end - + clear_magic_attributes - + self end - + # Execute image presence and validity validations. def validate_image #:nodoc: field_name = (@image_file_url && @image_file_url.present?) ? :image_file_url : :image_file - + # Could not read the file as an image if @invalid_image errors.add field_name, self.class.invalid_image_message - + # no image uploaded and one is required elsif self.class.require_image && !has_image? errors.add field_name, self.class.missing_image_message - + # Image does not meet minimum size elsif self.class.validates_image_size && !@uploaded_image.nil? x, y = Fleximage::Operator::Base.size_to_xy(self.class.validates_image_size) - + if @uploaded_image.columns < x || @uploaded_image.rows < y errors.add field_name, self.class.image_too_small_message end - + end end - + private # Perform pre save tasks. Preprocess the image, and write it to DB. def pre_save if @uploaded_image # perform preprocessing perform_preprocess_operation - + # Convert to storage format @uploaded_image.format = self.class.image_storage_format.to_s.upcase unless respond_to?(:image_format) - + # Write image data to the DB field if self.class.db_store? self.image_file_data = @uploaded_image.to_blob end end end - + # Write image to file system/S3 and cleanup garbage. def post_save if @uploaded_image if self.class.file_store? # Make sure target directory exists FileUtils.mkdir_p(directory_path) - + # Write master image file @uploaded_image.write(file_path) - + elsif self.class.s3_store? blob = StringIO.new(@uploaded_image.to_blob) AWS::S3::S3Object.store("#{id}.#{self.class.image_storage_format}", blob, self.class.s3_bucket) - + end end - + # Cleanup temp files delete_temp_image @@ -628,7 +628,7 @@ def post_save GC.start end end - + # Preprocess this image before saving def perform_preprocess_operation if self.class.preprocess_image_operation @@ -637,7 +637,7 @@ def perform_preprocess_operation @uploaded_image = @output_image end end - + def clear_magic_attributes unless frozen? self.image_filename = nil if respond_to?(:image_filename=) @@ -646,7 +646,7 @@ def clear_magic_attributes self.image_format = nil if respond_to?(:image_format=) end end - + # If any magic column names exists fill them with image meta data. def set_magic_attributes(file = nil) if file && self.respond_to?(:image_filename=) @@ -658,7 +658,7 @@ def set_magic_attributes(file = nil) self.image_height = @uploaded_image.rows if self.respond_to?(:image_height=) self.image_format = @uploaded_image.format if self.respond_to?(:image_format=) end - + # Save the image in the rails tmp directory def save_temp_image(file) file_name = file.respond_to?(:original_filename) ? file.original_filename : file.path @@ -670,42 +670,42 @@ def save_temp_image(file) f.write file.read end end - + # Delete the temp image after its no longer needed def delete_temp_image FileUtils.rm_rf "#{RAILS_ROOT}/tmp/fleximage/#{@image_file_temp}" end - + # Load the default image, or raise an expection def master_image_not_found # Load the default image from a path if self.class.default_image_path @output_image = Magick::Image.read("#{RAILS_ROOT}/#{self.class.default_image_path}").first - + # Or create a default image elsif self.class.default_image x, y = Fleximage::Operator::Base.size_to_xy(self.class.default_image[:size]) color = self.class.default_image[:color] - + @output_image = Magick::Image.new(x, y) do self.background_color = color if color && color != :transparent end - + # No default, not master image, so raise exception else message = "Master image was not found for this record" - + if !self.class.db_store? message << "\nExpected image to be at:" message << "\n #{file_path}" end - + raise MasterImageNotFound, message end ensure GC.start end end - + end end diff --git a/lib/fleximage/operator/background.rb b/lib/fleximage/operator/background.rb index 445e3d8..8aa1ed0 100644 --- a/lib/fleximage/operator/background.rb +++ b/lib/fleximage/operator/background.rb @@ -8,28 +8,28 @@ module Operator # * +color+: the color of the background image. # Use an RMagick named color or use the +color+ method in Fleximage::Controller, or a # Magick::Pixel object. - # - # * +size+: The size of the background image, in Fleximage *size* format. + # + # * +size+: The size of the background image, in Fleximage *size* format. # By default the background image is the same size as the foreground image - # - # * +alignment+: A symbol that tells Fleximage where to put the foreground image on + # + # * +alignment+: A symbol that tells Fleximage where to put the foreground image on # top of the background image. Can be any of the following: # :center, :top, :top_right, :right, :bottom_right, :bottom, :bottom_left, :left, :top_left. # Default is :+center+ - # - # * +offset+: the number of pixels to offset the foreground image from it's :+alignment+ anchor, in FlexImage + # + # * +offset+: the number of pixels to offset the foreground image from it's :+alignment+ anchor, in FlexImage # *size* format. Useful to give a bit a space between your image and the edge of the background, for instance. # *NOTE:* Due to some unexpected (buggy?) RMagick behaviour :+offset+ will work strangely # if :+alignment+ is set to a corner non-corner value, such as :+top+ or :+center+. Using :+offset+ in # these cases will force the overlay into a corner anyway. - # - # * +blending+: The blending mode governs how the foreground image gets composited onto the background. You can + # + # * +blending+: The blending mode governs how the foreground image gets composited onto the background. You can # get some funky effects with modes like :+copy_cyan+ or :+screen+. For a full list of blending # modes checkout the RMagick documentation (http://www.simplesystems.org/RMagick/doc/constants.html#CompositeOperator). # To use a blend mode remove the +CompositeOp+ form the name and "unserscorize" the rest. For instance, # +MultiplyCompositeOp+ becomes :+multiply+, and +CopyBlackCompositeOp+ becomes :+copy_black+. - class Background < Operator::Base + class Background < Operator::Base def operate(options = {}) options = options.symbolize_keys @@ -40,7 +40,7 @@ def operate(options = {}) width, height = options.key?(:size) ? size_to_xy(options[:size]) : [@image.columns, @image.rows] #create the background image onto which we will composite the foreground image - bg = Magick::Image.new(width, height) do + bg = Magick::Image.new(width, height) do self.background_color = color self.format = 'PNG' end diff --git a/lib/fleximage/operator/base.rb b/lib/fleximage/operator/base.rb index 7ae904f..970cb61 100644 --- a/lib/fleximage/operator/base.rb +++ b/lib/fleximage/operator/base.rb @@ -1,21 +1,21 @@ module Fleximage module Operator - + class BadOperatorResult < Exception #:nodoc: end - + class OperationNotImplemented < Exception #:nodoc: end - + # The Operator::Base class is what all other Operator classes inherit from. - # To write your own Operator class, simply inherit from this class, and - # implement your own operate methods, with your own arguments. Just + # To write your own Operator class, simply inherit from this class, and + # implement your own operate methods, with your own arguments. Just # return a new RMagick image object that represents the new image, and # the model will be updated automatically. # # You have access to a few instance variables in the operate method: # - # * @image : The current image from the model. Use this is a starting + # * @image : The current image from the model. Use this is a starting # point for all transformations. # * @model : The model instance that this image transformation is happenining # in. Use it to get data out of your model for display in your image. @@ -26,47 +26,47 @@ def initialize(proxy, image, model_obj) #:nodoc: @image = image @model = model_obj end - + # Start the operation def execute(*args) #:nodoc: # Get the result of the Operators #operate method result = operate(*args) - + # Ensure that the result is an RMagick:Image object unless result.is_a?(Magick::Image) raise BadOperatorResult, "expected #{self.class}#operate to return an instance of Magick::Image. \n"+ "Got instance of #{result.class} instead." end - + # Save the result to the operator proxy @proxy.image = result end - + # Perform the operation. Override this method in your Operator::Base subclasses # in order to write your own image operators. def operate(*args) raise OperationNotImplemented, "Override this method in your own subclass." end - + # --- # - SUPPORT METHODS # --- - + # Allows access to size conversion globally. See size_to_xy for a more detailed explanation def self.size_to_xy(size) - case + case when size.is_a?(Array) && size.size == 2 # [320, 240] size - + when size.to_s.include?('x') # "320x240" size.split('x').collect(&:to_i) - + else # Anything else, convert the object to an integer and assume square dimensions [size.to_i, size.to_i] - + end end - + # This method will return a valid color Magick::Pixel object. It will also auto adjust # for the bit depth of your ImageMagick configuration. # @@ -83,7 +83,7 @@ def self.color(*args) if args.size == 1 && args.first.is_a?(String) args.first else - + # adjust color to proper bit depth if Magick::QuantumDepth != 8 max = case Magick::QuantumDepth @@ -92,23 +92,23 @@ def self.color(*args) when 32 4_294_967_295 end - + args.map! do |value| (value.to_f/255 * max).to_i end end - + # create the pixel Magick::Pixel.new(*args) end end - + def color(*args) self.class.color(*args) end - + # Converts a size object to an [x,y] array. Acceptible formats are: - # + # # * 10 # * "10" # * "10x20" @@ -120,8 +120,8 @@ def color(*args) def size_to_xy(size) self.class.size_to_xy size end - - # Scale the image, respecting aspect ratio. + + # Scale the image, respecting aspect ratio. # Operation will happen in the main @image unless you supply the +img+ argument # to operate on instead. def scale(size, img = @image) @@ -131,24 +131,24 @@ def scale(size, img = @image) _img.resize!(cols, rows) end end - + # Scale to the desired size and crop edges off to get the exact dimensions needed. # Operation will happen in the main @image unless you supply the +img+ argument # to operate on instead. def scale_and_crop(size, img = @image) img.crop_resized!(*size_to_xy(size)) end - - # Resize the image, with no respect to aspect ratio. + + # Resize the image, with no respect to aspect ratio. # Operation will happen in the main @image unless you supply the +img+ argument # to operate on instead. def stretch(size, img = @image) img.resize!(*size_to_xy(size)) end - + # Convert a symbol to an RMagick blending mode. - # - # The blending mode governs how the overlay gets composited onto the image. You can + # + # The blending mode governs how the overlay gets composited onto the image. You can # get some funky effects with modes like :+copy_cyan+ or :+screen+. For a full list of blending # modes checkout the RMagick documentation (http://www.simplesystems.org/RMagick/doc/constants.html#CompositeOperator). # To use a blend mode remove the +CompositeOp+ form the name and "unserscorize" the rest. For instance, @@ -158,20 +158,20 @@ def symbol_to_blending_mode(mode) rescue NameError raise ArgumentError, ":#{mode} is not a valid blending mode." end - + def symbol_to_gravity(gravity_name) gravity = GRAVITIES[gravity_name] - + if gravity gravity else raise ArgumentError, ":#{gravity_name} is not a valid gravity name.\n\nValid names are :center, :top, :top_right, :right, :bottom_right, :bottom, :bottom_left, :left, :top_left" end end - - + + end # Base - + # Conversion table for mapping alignment symbols to their equivalent RMagick gravity constants. GRAVITIES = { :center => Magick::CenterGravity, @@ -184,6 +184,6 @@ def symbol_to_gravity(gravity_name) :left => Magick::WestGravity, :top_left => Magick::NorthWestGravity, } unless defined?(GRAVITIES) - + end # Operator end # Fleximage \ No newline at end of file diff --git a/lib/fleximage/operator/border.rb b/lib/fleximage/operator/border.rb index 80a6680..75163f3 100644 --- a/lib/fleximage/operator/border.rb +++ b/lib/fleximage/operator/border.rb @@ -1,28 +1,28 @@ module Fleximage module Operator - + # Add a border to the outside of the image # # image.border(options = {}) - # + # # Use the following keys in the +options+ hash: # # * +size+: Width of the border on each side. You can use a 2 dimensional value ('5x10') if you want - # different widths for the sides and top borders, but a single integer will apply the same border on + # different widths for the sides and top borders, but a single integer will apply the same border on # all sides. - # - # * +color+: the color of the border. Use an RMagick named color or use the +color+ method in + # + # * +color+: the color of the border. Use an RMagick named color or use the +color+ method in # FlexImage::Controller, or a Magick::Pixel object. - # + # # Example: - # + # # @photo.operate do |image| # # Defaults # image.border( # :size => 10, # :color => 'white' # or color(255, 255, 255) # ) - # + # # # Big, pink and wide # image.border( # :size => '200x100', @@ -37,7 +37,7 @@ def operate(options = {}) :color => 'white' } options = options.is_a?(Hash) ? defaults.update(options) : defaults - + # Get border size options[:size] = size_to_xy(options[:size]) @@ -45,6 +45,6 @@ def operate(options = {}) @image.border!(options[:size][0], options[:size][1], options[:color]) end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/crop.rb b/lib/fleximage/operator/crop.rb index f55377a..3ff44aa 100644 --- a/lib/fleximage/operator/crop.rb +++ b/lib/fleximage/operator/crop.rb @@ -1,9 +1,9 @@ module Fleximage module Operator - + # Crops the image without doing any resizing first. The operation crops from the :+from+ coordinate, # and returns an image of size :+size+ down and right from there. - # + # # image.crop(options = {}) # # Use the following keys in the +options+ hash: @@ -12,7 +12,7 @@ module Operator # Choose from GRAVITITES constant defined in base.rb. # * +from+: coorinates for the upper left corner of resulting image. # * +size+: The size of the resulting image, going down and to the right of the :+from+ coordinate. - # + # # size and from options are *required*. # # Example: @@ -53,6 +53,6 @@ def operate(options = {}) @image.crop!(symbol_to_gravity(options[:gravity]), options[:from][0], options[:from][1], options[:size][0], options[:size][1], true) end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/image_overlay.rb b/lib/fleximage/operator/image_overlay.rb index 058b40d..5186060 100644 --- a/lib/fleximage/operator/image_overlay.rb +++ b/lib/fleximage/operator/image_overlay.rb @@ -1,46 +1,46 @@ module Fleximage module Operator - + # Adds an overlay to the base image. It's useful for things like attaching a logo, # watermark, or even a border to the image. It will work best with a 24-bit PNG with # alpha channel since it will properly deal with partial transparency. - # + # # image.resize(image_overlay_path, options = {}) - # + # # +image_overlay_path+ is the path, relative to +RAILS_ROOT+ where the image you want superimposed # can be found. - # + # # Use the following keys in the +options+ hash: - # - # * +size+: The size of the overlayed image, as '123x456' or [123, 456]. + # + # * +size+: The size of the overlayed image, as '123x456' or [123, 456]. # By default the overlay is not resized before compositing. # Use this options if you want to resize the overlay, perhaps to have a small # logo on thumbnails and a big logo on full size images. Other than just numerical dimensions, the - # size parameter takes 2 special values :+scale_to_fit+ and :+stretch_to_fit+. :+scale_to_fit+ will - # make the overlay fit as + # size parameter takes 2 special values :+scale_to_fit+ and :+stretch_to_fit+. :+scale_to_fit+ will + # make the overlay fit as # much as it can inside the image without changing the aspect ratio. :+stretch_to_fit+ # will make the overlay the exact same size as the image but with a distorted aspect ratio to make # it fit. :+stretch_to_fit+ is designed to add border to images. - # + # # * +alignment+: A symbol that tells Fleximage where to put the overlay. Can be any of the following: # :center, :top, :top_right, :right, :bottom_right, :bottom, :bottom_left, :left, :top_left. # Default is :+center+ - # - # * +offset+: the number of pixels to offset the overlay from it's :+alignment+ anchor, in - # '123x456' or [123, 456] format. Useful to give a bit a space between your logo + # + # * +offset+: the number of pixels to offset the overlay from it's :+alignment+ anchor, in + # '123x456' or [123, 456] format. Useful to give a bit a space between your logo # and the edge of the image, for instance. # *NOTE:* Due to some unexpected (buggy?) RMagick behaviour :+offset+ will work strangely # if :+alignment+ is set to a non-corner value, such as :+top+ or :+center+. Using :+offset+ in # these cases will force the overlay into a corner anyway. - # - # * +blending+: The blending mode governs how the overlay gets composited onto the image. You can + # + # * +blending+: The blending mode governs how the overlay gets composited onto the image. You can # get some funky effects with modes like :+copy_cyan+ or :+screen+. For a full list of blending # modes checkout the RMagick documentation (http://www.simplesystems.org/RMagick/doc/constants.html#CompositeOperator). # To use a blend mode remove the +CompositeOp+ form the name and "unserscorize" the rest. For instance, # +MultiplyCompositeOp+ becomes :+multiply+, and +CopyBlackCompositeOp+ becomes :+copy_black+. # # Example: - # + # # @photo.operate do |image| # image.image_overlay('images/my_logo_with_alpha.png', # :size => '25x25', @@ -51,10 +51,10 @@ module Operator class ImageOverlay < Operator::Base def operate(image_overlay_path, options = {}) options = options.symbolize_keys - + #load overlay overlay = Magick::Image.read(image_overlay_path).first - + #resize overlay if options[:size] if options[:size] == :scale_to_fit || options[:size] == :stretch_to_fit @@ -62,24 +62,24 @@ def operate(image_overlay_path, options = {}) else x, y = size_to_xy(options[:size]) end - + method = options[:size] == :stretch_to_fit ? :stretch : :scale send(method, [x, y], overlay) end - + #prepare arguments for composite! args = [] args << overlay #overlay image args << symbol_to_gravity(options[:alignment] || :center) #gravity args += size_to_xy(options[:offset]) if options[:offset] #offset args << symbol_to_blending_mode(options[:blending] || :over) #compositing mode - + #composite @image.composite!(*args) - + return @image end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/resize.rb b/lib/fleximage/operator/resize.rb index 6040eac..bac85e3 100644 --- a/lib/fleximage/operator/resize.rb +++ b/lib/fleximage/operator/resize.rb @@ -1,44 +1,44 @@ module Fleximage module Operator - + # Resize this image, constraining proportions. Options allow cropping, stretching, upsampling and # padding. - # + # # image.resize(size, options = {}) - # + # # +size+ is size of the output image after the resize operation. Accepts either '123x456' # format or [123, 456] format. # # Use the following keys in the +options+ hash: - # - # * +crop+: pass true to this option to make the ouput image exactly + # + # * +crop+: pass true to this option to make the ouput image exactly # the same dimensions as +size+. The default behaviour will resize the image without # cropping any part meaning the image will be no bigger than the +size+. When :crop - # is true the final image is resized to fit as much as possible in the frame, and then crops it + # is true the final image is resized to fit as much as possible in the frame, and then crops it # to make it exactly the dimensions declared by the +size+ argument. - # - # * +upsample+: By default the image will never display larger than its original dimensions, + # + # * +upsample+: By default the image will never display larger than its original dimensions, # no matter how large the +size+ argument is. Pass +true+ to use this option to allow # upsampling, disabling the default behaviour. # # * +padding+: This option will pad the space around your image with a solid color to make it exactly the requested - # size. Pass +true+, for the default of +white+, or give it a text or pixel color like "red" or - # color(255, 127, 0). This is like the opposite of the +crop+ option. Instead of trimming the - # image to make it exactly the requested size, it will make sure the entire image is visible, but adds space + # size. Pass +true+, for the default of +white+, or give it a text or pixel color like "red" or + # color(255, 127, 0). This is like the opposite of the +crop+ option. Instead of trimming the + # image to make it exactly the requested size, it will make sure the entire image is visible, but adds space # around the edges to make it the right dimensions. # # * +stretch+: Set this option to true and the image will not preserve its aspect ratio. The final image will # stretch to fit the requested +size+. The resulting image is exactly the size you ask for. - # + # # Example: - # + # # @photo.operate do |image| # image.resize '200x200', :crop => true # end class Resize < Operator::Base def operate(size, options = {}) options = options.symbolize_keys - + # Find dimensions x, y = size_to_xy(size) @@ -69,7 +69,7 @@ def operate(size, options = {}) # get color padding_color = 'white' if padding_color == true - # get original x and y. This makes it play nice if the requested size is larger + # get original x and y. This makes it play nice if the requested size is larger # than the image and upsampling is not allowed. x, y = size_to_xy(size) @@ -83,10 +83,10 @@ def operate(size, options = {}) # crop to remove possible extra pixel @image.crop!(0, 0, x, y, true) end - + return @image end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/shadow.rb b/lib/fleximage/operator/shadow.rb index deca029..7c69745 100644 --- a/lib/fleximage/operator/shadow.rb +++ b/lib/fleximage/operator/shadow.rb @@ -1,30 +1,30 @@ module Fleximage module Operator - + # Add a drop shadow to the image. # # image.shadow(options = {}) - # + # # Use the following keys in the +options+ hash: # # * +offset+: distance of the dropsahdow form the image, in FlexImage *size* format. Positive # number move it down and right, negative numbers move it up and left. - # + # # * +blur+: how blurry the shadow is. Roughly corresponds to distance in pixels of the blur. - # - # * +background+: a color for the background of the image. What the shadow fades into. + # + # * +background+: a color for the background of the image. What the shadow fades into. # Use an RMagick named color or use the +color+ method in FlexImage::Controller, or a # Magick::Pixel object. - # + # # * +color+: color of the shadow itself. # Use an RMagick named color or use the +color+ method in FlexImage::Controller, or a # Magick::Pixel object. - # + # # * +opacity+: opacity of the shadow. A value between 0.0 and 1.0, where 1 is opaque and 0 is # transparent. - # + # # Example: - # + # # @photo.operate do |image| # # Default settings # image.shadow( @@ -32,9 +32,9 @@ module Operator # :background => 'white', # or color(255, 255, 255) # :blur => 8, # :offset => '2x2', - # :opacity => 0.75 + # :opacity => 0.75 # ) - # + # # # Huge, red shadow # image.shadow( # :color => color(255, 0, 0), @@ -73,15 +73,15 @@ def operate(options = {}) # apply shadow @image = shadow.composite( - @image, - symbol_to_gravity(:top_left), - (shadow.columns - @image.columns) / 2 - options[:offset][0], - (shadow.rows - @image.rows) / 2 - options[:offset][1], + @image, + symbol_to_gravity(:top_left), + (shadow.columns - @image.columns) / 2 - options[:offset][0], + (shadow.rows - @image.rows) / 2 - options[:offset][1], symbol_to_blending_mode(:over) ) @image.trim! end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/text.rb b/lib/fleximage/operator/text.rb index 26ba496..70dd601 100644 --- a/lib/fleximage/operator/text.rb +++ b/lib/fleximage/operator/text.rb @@ -1,12 +1,12 @@ module Fleximage module Operator - + # Draw text on the image. Customize size, position, color, dropshadow, and font. - # + # # image.text(string_to_write, options = {}) # # Use the following keys in the +options+ hash: - # + # # * alignment: symbol like in ImageOverlay # * offset: size string # * antialias: true or false @@ -66,7 +66,7 @@ def operate(string_to_write, options = {}) text.pointsize = options[:font_size].to_i text.rotation = options[:rotate] text.font_weight = options[:font_weight] if options[:font_weight] - + if options[:stroke][:width] > 0 text.stroke_width = options[:stroke][:width] text.stroke = options[:stroke][:color] @@ -99,6 +99,6 @@ def operate(string_to_write, options = {}) @image.composite!(temp_image, 0, 0, symbol_to_blending_mode(:over)) end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/trim.rb b/lib/fleximage/operator/trim.rb index 857a320..6def64e 100644 --- a/lib/fleximage/operator/trim.rb +++ b/lib/fleximage/operator/trim.rb @@ -1,6 +1,6 @@ module Fleximage module Operator - + # Trim off all the pixels around the image border that have the same color. # # image.trim @@ -9,6 +9,6 @@ def operate() @image.trim!(true) end end - + end end \ No newline at end of file diff --git a/lib/fleximage/operator/unsharp_mask.rb b/lib/fleximage/operator/unsharp_mask.rb index 5aa8c80..e9c539e 100644 --- a/lib/fleximage/operator/unsharp_mask.rb +++ b/lib/fleximage/operator/unsharp_mask.rb @@ -1,8 +1,8 @@ module Fleximage module Operator - + # Sharpen an image using an unsharp mask filter. - # + # # image.unsharp_mask(options = {}) # # Use the following keys in the +options+ hash: @@ -31,6 +31,6 @@ def operate(options = {}) @image = @image.unsharp_mask(options[:radius], options[:sigma], options[:amount], options[:threshold]) end end - + end end \ No newline at end of file diff --git a/lib/fleximage/view.rb b/lib/fleximage/view.rb index 6a86f82..4ee8f1b 100644 --- a/lib/fleximage/view.rb +++ b/lib/fleximage/view.rb @@ -1,10 +1,10 @@ module Fleximage - + # Renders a .flexi template class View < ActionView::TemplateHandler #:nodoc: class TemplateDidNotReturnImage < RuntimeError #:nodoc: end - + def self.call(template) "Fleximage::View.new(self).render(template)" end @@ -12,44 +12,44 @@ def self.call(template) def initialize(action_view) @view = action_view end - + def render(template) # process the view result = @view.instance_eval do - + # Shorthand color creation def color(*args) Fleximage::Operator::Base.color(*args) end - + #execute the template eval(template.source) end - + # Raise an error if object returned from template is not an image record unless result.class.include?(Fleximage::Model::InstanceMethods) - raise TemplateDidNotReturnImage, + raise TemplateDidNotReturnImage, ".flexi template was expected to return a model instance that acts_as_fleximage, but got an instance of <#{result.class}> instead." end - + # Figure out the proper format requested_format = (@view.params[:format] || :jpg).to_sym unless [:jpg, :gif, :png].include?(requested_format) raise 'Image must be requested with an image type format. jpg, gif and png only are supported.' end - + # Set proper content type @view.controller.response.content_type = Mime::Type.lookup_by_extension(requested_format.to_s).to_s - + # Set proper caching headers if defined?(Rails) && Rails.env == 'production' @view.controller.response.headers['Cache-Control'] = 'public, max-age=86400' end - + # return rendered result return result.output_image(:format => requested_format) ensure - + # ensure garbage collection happens after every flex image render GC.start end diff --git a/tasks/fleximage_tasks.rake b/tasks/fleximage_tasks.rake index a88ea2c..4945d28 100644 --- a/tasks/fleximage_tasks.rake +++ b/tasks/fleximage_tasks.rake @@ -1,11 +1,11 @@ namespace :fleximage do - + # Find the model class def model_class raise 'You must specify a FLEXIMAGE_CLASS=MyClass' unless ENV['FLEXIMAGE_CLASS'] @model_class ||= ENV['FLEXIMAGE_CLASS'].camelcase.constantize end - + desc "Populate width and height magic columns from the current image store. Useful when migrating from on old installation." task :dimensions => :environment do model_class.find(:all).each do |obj| @@ -16,19 +16,19 @@ namespace :fleximage do end end end - + namespace :convert do - + def convert_directory_format(to_format) model_class.find(:all).each do |obj| - + # Get the creation date creation = obj[:created_at] || obj[:created_on] - + # Generate both types of file paths flat_path = "#{RAILS_ROOT}/#{model_class.image_directory}/#{obj.id}.#{model_class.image_storage_format}" - nested_path = "#{RAILS_ROOT}/#{model_class.image_directory}/#{creation.year}/#{creation.month}/#{creation.day}/#{obj.id}.#{model_class.image_storage_format}" - + nested_path = "#{RAILS_ROOT}/#{model_class.image_directory}/#{creation.year}/#{creation.month}/#{creation.day}/#{obj.id}.#{model_class.image_storage_format}" + # Assign old path and new path based on desired directory format if to_format == :nested old_path = flat_path @@ -37,7 +37,7 @@ namespace :fleximage do old_path = nested_path new_path = flat_path end - + # Move the files if old_path != new_path && File.exists?(old_path) FileUtils.mkdir_p(File.dirname(new_path)) @@ -46,10 +46,10 @@ namespace :fleximage do end end end - + def convert_image_format(to_format) model_class.find(:all).each do |obj| - + # convert DB stored images if model_class.db_store? if obj.image_file_data && obj.image_file_data.any? @@ -62,16 +62,16 @@ namespace :fleximage do puts "Could not convert image for #{model_class} with id #{obj.id}\n #{e.class} #{e}\n" end end - + # Convert file system stored images - else + else # Generate both types of file paths png_path = obj.file_path.gsub(/\.jpg$/, '.png') jpg_path = obj.file_path.gsub(/\.png$/, '.jpg') - + # Output stub output = (to_format == :jpg) ? 'PNG -> JPG' : 'JPG -> PNG' - + # Assign old path and new path based on desired image format if to_format == :jpg old_path = png_path @@ -80,47 +80,47 @@ namespace :fleximage do old_path = jpg_path new_path = png_path end - + # Perform conversion if File.exists?(old_path) image = Magick::Image.read(old_path).first image.format = to_format.to_s.upcase image.write(new_path) File.delete(old_path) - + puts "#{output} : Image #{obj.id}" end end end end - + def ensure_db_store col = model_class.columns.find {|c| c.name == 'image_file_data'} unless col && col.type == :binary raise "No image_file_data field of type :binary for this model!" end end - + desc "Convert a flat images/123.png style image store to a images/2007/11/12/123.png style. Requires FLEXIMAGE_CLASS=ModelName" task :to_nested => :environment do convert_directory_format :nested end - + desc "Convert a nested images/2007/11/12/123.png style image store to a images/123.png style. Requires FLEXIMAGE_CLASS=ModelName" task :to_flat => :environment do convert_directory_format :flat end - + desc "Convert master images stored as JPGs to PNGs" task :to_png => :environment do convert_image_format :png end - + desc "Convert master images stored as PNGs to JPGs" task :to_jpg => :environment do convert_image_format :jpg end - + desc "Convert master image storage to use the database. Loads all file-stored images into the database." task :to_db => :environment do ensure_db_store @@ -132,10 +132,10 @@ namespace :fleximage do end end end - + puts "--- All images successfully moved to the database. Check to make sure the transfer worked cleanly before deleting your file system image store." end - + desc "Convert master image storage to use the file system. Loads all database images into files." task :to_filestore => :environment do ensure_db_store @@ -146,9 +146,9 @@ namespace :fleximage do end end end - + puts "--- All images successfully moved to the file system. Remember to remove your image_file_data field from your models database table." end - + end end diff --git a/test/mock_file.rb b/test/mock_file.rb index 17dea65..6ef212b 100644 --- a/test/mock_file.rb +++ b/test/mock_file.rb @@ -4,18 +4,18 @@ class MockFile def initialize(path) @path = path end - + def size 1 end - + def original_filename @path.split('/').last end - + def read File.open(@path) { |f| f.read } end - + def rewind; end end \ No newline at end of file diff --git a/test/rails_root/app/models/abstract.rb b/test/rails_root/app/models/abstract.rb index 00360b1..ea5f807 100644 --- a/test/rails_root/app/models/abstract.rb +++ b/test/rails_root/app/models/abstract.rb @@ -1,6 +1,6 @@ class Abstract < ActiveRecord::Base set_table_name :photo_dbs - + acts_as_fleximage do require_image false default_image :size => '320x240', :color => 'red' diff --git a/test/rails_root/config/environment.rb b/test/rails_root/config/environment.rb index 166187f..9bed49d 100644 --- a/test/rails_root/config/environment.rb +++ b/test/rails_root/config/environment.rb @@ -20,7 +20,7 @@ # To use Rails without a database, you must remove the Active Record framework # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] - # Only load the plugins named here, in the order given. By default, all plugins + # Only load the plugins named here, in the order given. By default, all plugins # in vendor/plugins are loaded in alphabetical order. # :all can be used as a placeholder for all plugins not explicitly named # config.plugins = [ :exception_notification, :ssl_requirement, :all ] @@ -34,7 +34,7 @@ # Your secret key for verifying cookie session data integrity. # If you change this key, all old sessions will become invalid! - # Make sure the secret is at least 30 characters and all random, + # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. config.action_controller.session = { :session_key => '_rails_root_session', @@ -56,7 +56,7 @@ # Make Active Record use UTC-base instead of local time # config.active_record.default_timezone = :utc - + config.log_level = :debug config.cache_classes = false config.whiny_nils = true diff --git a/test/rails_root/config/initializers/inflections.rb b/test/rails_root/config/initializers/inflections.rb index 09158b8..5261cd1 100644 --- a/test/rails_root/config/initializers/inflections.rb +++ b/test/rails_root/config/initializers/inflections.rb @@ -1,6 +1,6 @@ # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format +# Add new inflection rules using the following format # (all these examples are active by default): # Inflector.inflections do |inflect| # inflect.plural /^(ox)$/i, '\1en' diff --git a/test/rails_root/public/.htaccess b/test/rails_root/public/.htaccess index d9d211c..1d37bd9 100644 --- a/test/rails_root/public/.htaccess +++ b/test/rails_root/public/.htaccess @@ -5,14 +5,14 @@ Options +FollowSymLinks +ExecCGI # If you don't want Rails to look in certain directories, # use the following rewrite rules so that Apache won't rewrite certain requests -# +# # Example: # RewriteCond %{REQUEST_URI} ^/notrails.* # RewriteRule .* - [L] # Redirect all requests not available on the filesystem to Rails # By default the cgi dispatcher is used which is very slow -# +# # For better performance replace the dispatcher with the fastcgi one # # Example: @@ -33,7 +33,7 @@ RewriteRule ^(.*)$ dispatch.cgi [QSA,L] # In case Rails experiences terminal errors # Instead of displaying this message you can supply a file here which will be rendered instead -# +# # Example: # ErrorDocument 500 /500.html diff --git a/test/rails_root/public/index.html b/test/rails_root/public/index.html index 84b7b57..be32234 100644 --- a/test/rails_root/public/index.html +++ b/test/rails_root/public/index.html @@ -14,20 +14,20 @@ font-size: 13px; color: #333; } - + h1 { font-size: 28px; color: #000; } - + a {color: #03c} a:hover { background-color: #03c; color: white; text-decoration: none; } - - + + #page { background-color: #f0f0f0; width: 750px; @@ -35,7 +35,7 @@ margin-left: auto; margin-right: auto; } - + #content { float: left; background-color: white; @@ -44,7 +44,7 @@ padding: 25px; width: 500px; } - + #sidebar { float: right; width: 175px; @@ -53,7 +53,7 @@ #footer { clear: both; } - + #header, #about, #getting-started { padding-left: 75px; @@ -73,14 +73,14 @@ font-weight: normal; font-size: 16px; } - - + + #about h3 { margin: 0; margin-bottom: 10px; font-size: 14px; } - + #about-content { background-color: #ffd; border: 1px solid #fc0; @@ -99,7 +99,7 @@ } #about-content td.name {color: #555} #about-content td.value {color: #000} - + #about-content.failure { background-color: #fcc; border: 1px solid #f00; @@ -108,8 +108,8 @@ margin: 0; padding: 10px; } - - + + #getting-started { border-top: 1px solid #ccc; margin-top: 25px; @@ -145,8 +145,8 @@ color: #555; font-size: 13px; } - - + + #search { margin: 0; padding-top: 10px; @@ -158,8 +158,8 @@ margin: 2px; } #search-text {width: 170px} - - + + #sidebar ul { margin-left: 0; padding-left: 0; @@ -176,7 +176,7 @@ #sidebar ul.links li { margin-bottom: 5px; } - + @@ -189,11 +189,11 @@ onComplete: function() {new Effect.BlindDown('about-content', {duration: 0.25})} }); } else { - new Effect[Element.visible('about-content') ? + new Effect[Element.visible('about-content') ? 'BlindUp' : 'BlindDown']('about-content', {duration: 0.25}); } } - + window.onload = function() { $('search-text').value = ''; $('search').onsubmit = function() { @@ -213,7 +213,7 @@ the Rails site - +
  • Join the community

  • - +
  • Browse the documentation