carrierwave-crop-on-fly 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a4b2b20f10b010c98b7c72ce473beddc9fd9fbab
4
+ data.tar.gz: 4568c7d682db0640d53151093ccc37ef6494f1d1
5
+ SHA512:
6
+ metadata.gz: e4195a367c327aef9ed2c66bd7f5aa9a59564bf40584c6815de72dadf6eb545d026d51a9ad36d6b7e0142c145be2b255c0067ea0513fde64497f8a55ccc1ef92
7
+ data.tar.gz: 0e5fbcfc2ec2988ee9d0308dfcdb27b3d3276c200a44a28dbeb93fd05d9a0d243a9857f5c8c07169d958dea6a35830f56e3bc905a3ea787874ef5479e95fb3d5
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 evg2108
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # CarrierWave-Fly-Crop
2
+
3
+ CarrierWave extension for on fly specifying crop area with preview and cropping images before they saved.
4
+
5
+ this gem based on [carrierwave-crop](https://github.com/kirtithorat/carrierwave-crop)
6
+
7
+ ## Installation
8
+
9
+ Install the latest stable release:
10
+
11
+ $[sudo] gem install carrierwave-fly-crop
12
+
13
+ In Rails, add it to your Gemfile:
14
+
15
+ gem 'carrierwave-fly-crop'
16
+
17
+ Also you must add mini_magick gem
18
+
19
+ gem 'mini_magick'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Finally, restart the server to apply the changes.
26
+
27
+ ## Getting Started
28
+
29
+ Add the required files in assets
30
+
31
+ In .js file
32
+
33
+ //= require jquery
34
+ //= require jcrop_init
35
+
36
+ In .css file
37
+
38
+ *= require jquery.jcrop
39
+ *= require jcrop_fix
40
+
41
+ ## Usage
42
+
43
+ Open your model file and add the CarrierWave uploader:
44
+
45
+ class User < ActiveRecord::Base
46
+ mount_uploader :avatar, AvatarUploader
47
+ end
48
+
49
+ In the CarrierWave uploader:
50
+
51
+ class BaseUploader < CarrierWave::Uploader::Base
52
+ include CarrierWave::MiniMagick
53
+ process crop: [100, 100]
54
+ end
55
+
56
+ In the view:
57
+
58
+ <%= form_for @user do |f| %>
59
+ <%= f.file_field :avatar %>
60
+ <%= f.cropbox :avatar, width: 300, height: 300 %>
61
+ <%= f.previewbox :avatar %>
62
+ <%= f.submit 'Crop' %>
63
+ <% end %>
64
+
65
+ ### Credits and resources
66
+ * [CarrierWave](https://github.com/carrierwaveuploader/carrierwave)
67
+ * [Deep Liquid's JCrop](http://deepliquid.com/content/Jcrop.html)
@@ -0,0 +1,145 @@
1
+ //= require jquery.jcrop.js
2
+ //= require_self
3
+
4
+ document.jcrop = (function() {
5
+ var exports = { };
6
+
7
+ var centerSelection = function(input_image_sizes, output_image_sizes) {
8
+ var x_offset = 0;
9
+ var y_offset = 0;
10
+ var orig_w = input_image_sizes[0];
11
+ var orig_h = input_image_sizes[1];
12
+
13
+ var ratio = output_image_sizes[0] / output_image_sizes[1];
14
+ var current_image_ratio = orig_w / orig_h;
15
+
16
+ var width = orig_w;
17
+ var height = orig_h;
18
+ if (ratio < current_image_ratio) {
19
+ width = orig_h * ratio;
20
+ x_offset = (orig_w - width) / 2;
21
+ } else if (ratio > current_image_ratio) {
22
+ height = orig_w * ratio;
23
+ y_offset = (orig_h - height) / 2
24
+ }
25
+
26
+ return { aspect_ratio: ratio, position_and_size: [x_offset, y_offset, width, height] }
27
+ };
28
+
29
+ var readURL = function(input)
30
+ {
31
+ if (input.files && input.files[0]) {
32
+ var reader = new FileReader();
33
+
34
+ reader.onload = function(e){
35
+ if (!document.jcrop.options.image_loaded) {
36
+ document.jcrop.options.image_loaded = true;
37
+ document.jcrop.options.cropbox_image.on('load', function () {
38
+ document.jcrop.options.current_image_width = this.width;
39
+ document.jcrop.options.current_image_height = this.height;
40
+
41
+ var selection = centerSelection([document.jcrop.options.current_image_width, document.jcrop.options.current_image_height],
42
+ [document.jcrop.options.output_width, document.jcrop.options.output_height]);
43
+
44
+ var data = document.jcrop.options.cropbox_image.data('Jcrop');
45
+ if (data) { data.destroy(); }
46
+
47
+ document.jcrop.options.cropbox_image.Jcrop({
48
+ aspectRatio: selection.aspect_ratio,
49
+ setSelect: selection.position_and_size,
50
+ onChange: showPreview,
51
+ onSelect: showPreview,
52
+ boxWidth: 300, boxHeight: 300
53
+ });
54
+ });
55
+ }
56
+
57
+ document.jcrop.options.cropbox_image.attr('src', e.target.result);
58
+ if (document.jcrop.options.previewbox_image.length > 0) { document.jcrop.options.previewbox_image.attr('src', e.target.result); }
59
+ };
60
+ reader.readAsDataURL(input.files[0]);
61
+ }
62
+ };
63
+
64
+ var showPreview = function(coords) {
65
+ if (document.jcrop.options.crop_x.length > 0) { document.jcrop.options.crop_x.val(coords.x); }
66
+ if (document.jcrop.options.crop_y.length > 0) { document.jcrop.options.crop_y.val(coords.y); }
67
+ if (document.jcrop.options.crop_w.length > 0) { document.jcrop.options.crop_w.val(coords.w); }
68
+ if (document.jcrop.options.crop_h.length > 0) { document.jcrop.options.crop_h.val(coords.h); }
69
+
70
+ if (document.jcrop.options.previewbox_image.length > 0) {
71
+ var original_picture_height = document.jcrop.options.current_image_height;
72
+ var original_picture_width = document.jcrop.options.current_image_width;
73
+
74
+ var preview_height = document.jcrop.options.output_height;
75
+ var preview_width = document.jcrop.options.output_width;
76
+
77
+ var imaginary_picture_height = (original_picture_height * preview_height) / coords.h;
78
+ var imaginary_picture_width = (original_picture_width * preview_width) / coords.w;
79
+
80
+ var imaginary_picture_x_shift = imaginary_picture_width * coords.x / (original_picture_width);
81
+ var imaginary_picture_y_shift = imaginary_picture_height * coords.y / (original_picture_height);
82
+
83
+ document.jcrop.options.previewbox_image.css({
84
+ width: Math.round(imaginary_picture_width) + 'px',
85
+ height: Math.round(imaginary_picture_height) + 'px',
86
+ marginLeft: '-' + Math.round(imaginary_picture_x_shift) + 'px',
87
+ marginTop: '-' + Math.round(imaginary_picture_y_shift) + 'px'
88
+ });
89
+ }
90
+ };
91
+
92
+ var init_options = function(options) {
93
+ options = options || {};
94
+
95
+ options.file_input_id = options.file_input_id ? '#' + options.file_input_id : '#file_input_cropper';
96
+ options.file_input = $(options.file_input_id);
97
+ if (options.file_input.length == 0) { throw "element '" + options.file_input_id + "' not found"; }
98
+
99
+ options.cropbox_image_id = options.cropbox_image_id || options.file_input_id + '_cropbox';
100
+ options.cropbox_image = $(options.cropbox_image_id);
101
+ if (options.cropbox_image.length == 0) { throw "element '" + options.cropbox_image_id + "' not found"; }
102
+
103
+ options.previewbox_image_id = options.previewbox_image_id || options.file_input_id + '_previewbox';
104
+ options.previewbox_image = $(options.previewbox_image_id);
105
+ if (options.previewbox_image.length == 0) { console.info("element '" + options.previewbox_image_id + "' not found"); }
106
+
107
+ options.crop_x_id = options.crop_x_id || options.file_input_id + '_crop_x';
108
+ options.crop_x = $(options.crop_x_id);
109
+ if (options.crop_x.length == 0) { console.warn("element '" + options.crop_x_id + "' not found. You can not send horizontal offset data to the server"); }
110
+
111
+ options.crop_y_id = options.crop_y_id || options.file_input_id + '_crop_y';
112
+ options.crop_y = $(options.crop_y_id);
113
+ if (options.crop_y.length == 0) { console.warn("element '" + options.crop_y_id + "' not found. You can not send vertical offset data to the server"); }
114
+
115
+ options.crop_w_id = options.crop_w_id || options.file_input_id + '_crop_w';
116
+ options.crop_w = $(options.crop_w_id);
117
+ if (options.crop_w.length == 0) { console.warn("element '" + options.crop_w_id + "' not found. You can not send width data to the server"); }
118
+
119
+ options.crop_h_id = options.crop_h_id || options.file_input_id + '_crop_h';
120
+ options.crop_h = $(options.crop_h_id);
121
+ if (options.crop_h.length == 0) { console.warn("element '" + options.crop_h_id + "' not found. You can not send height data to the server"); }
122
+
123
+ options.output_width = options.output_width || options.cropbox_image.data('output-width') || 100;
124
+ options.output_height = options.output_height || options.cropbox_image.data('output-height') || 100;
125
+
126
+ document.jcrop.options = options;
127
+
128
+ return options;
129
+ };
130
+
131
+ exports.init = function(options) {
132
+ init_options(options);
133
+
134
+ var file_input = $(document.jcrop.options.file_input_id);
135
+
136
+ if (file_input.length > 0) {
137
+ file_input.change(function(){
138
+ if (document.jcrop.options.after_change) { document.jcrop.options.after_change(); }
139
+ readURL(this);
140
+ });
141
+ }
142
+ };
143
+
144
+ return exports;
145
+ })();
@@ -0,0 +1,3 @@
1
+ .jcrop-keymgr {
2
+ opacity: 0;
3
+ }
@@ -0,0 +1 @@
1
+ require 'carrierwave/crop/all'
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ require 'carrierwave/crop/version'
4
+ require 'carrierwave/crop/error'
5
+
6
+ if defined? Rails
7
+ require 'carrierwave/crop/engine'
8
+ require 'carrierwave/crop/helpers'
9
+ require 'carrierwave/crop/uploader_additions'
10
+ require 'carrierwave/crop/uploaded_file_additions'
11
+ require 'carrierwave/crop/extension_crop_data'
12
+ require 'carrierwave/crop/railtie'
13
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Crop
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Crop
5
+ class MissingProcessorError < StandardError; end
6
+ class ProcessingError < StandardError; end
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ module CarrierWave
2
+ module Crop
3
+ module ExtensionCropData
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before :cache, :remember_crop_data
8
+
9
+ attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
10
+ end
11
+
12
+ private
13
+
14
+ def remember_crop_data(file)
15
+ self.crop_x = file.file.crop_x
16
+ self.crop_y = file.file.crop_y
17
+ self.crop_w = file.file.crop_w
18
+ self.crop_h = file.file.crop_h
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+
25
+ if defined? CarrierWave::Uploader::Base
26
+ CarrierWave::Uploader::Base.class_eval do
27
+ include ::CarrierWave::Crop::ExtensionCropData
28
+ end
29
+ end
@@ -0,0 +1,84 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Crop
5
+ module Helpers
6
+
7
+ # Form helper to render the preview of a cropped attachment.
8
+ # Loads the actual image. Previewbox has no constraints on dimensions, image is renedred at full size.
9
+ # By default box size is 100x100. Size can be customized by setting the :width and :height option.
10
+ # If you override one of width/height you must override both.
11
+ #
12
+ # previewbox :avatar
13
+ # previewbox :avatar, width: 200, height: 200
14
+ #
15
+ # @param attachment [Symbol] attachment name
16
+ # @param opts [Hash] specify version or width and height options
17
+ def previewbox(attachment, opts = {})
18
+ attachment = attachment.to_sym
19
+ attachment_instance = self.object.send(attachment)
20
+
21
+ if(attachment_instance.is_a? CarrierWave::Uploader::Base)
22
+ model_name = self.object.class.name.demodulize.underscore
23
+ width, height = 100, 100
24
+ if(opts[:width] && opts[:height])
25
+ width, height = opts[:width].round, opts[:height].round
26
+ elsif (sizes = find_output_sizes(attachment_instance))
27
+ width, height = *sizes
28
+ end
29
+ wrapper_attributes = {id: "#{model_name}_#{attachment}_previewbox_wrapper", style: "width:#{width}px; height:#{height}px; overflow:hidden", class: 'previewbox_wrapper'}
30
+
31
+ preview_image = @template.image_tag(attachment_instance.url, id: "#{model_name}_#{attachment}_previewbox")
32
+ @template.content_tag(:div, preview_image, wrapper_attributes)
33
+ end
34
+ end
35
+
36
+ def find_output_sizes(attachment_instance)
37
+ attachment_instance.class.processors.reverse.find{ |a| a[0].to_s.include?('crop') }.try(:[], 1)
38
+ end
39
+
40
+ # Form helper to render the actual cropping box of an attachment.
41
+ # Loads the actual image. Cropbox has no constraints on dimensions, image is renedred at full size.
42
+ # Box size can be restricted by setting the :width and :height option. If you override one of width/height you must override both.
43
+ #
44
+ # cropbox :avatar
45
+ # cropbox :avatar, width: 550, height: 600
46
+ #
47
+ # @param attachment [Symbol] attachment name
48
+ # @param opts [Hash] specify version or width and height options
49
+ def cropbox(attachment, opts = {})
50
+ attachment = attachment.to_sym
51
+ attachment_instance = self.object.send(attachment)
52
+
53
+ if(attachment_instance.is_a? CarrierWave::Uploader::Base)
54
+ model_name = self.object.class.name.demodulize.underscore
55
+
56
+ output = ActiveSupport::SafeBuffer.new
57
+ [:crop_x ,:crop_y, :crop_w, :crop_h].each do |attribute|
58
+ output << @template.hidden_field_tag("#{model_name}[#{attachment}][#{attribute}]", nil, id: "#{model_name}_#{attachment}_#{attribute}")
59
+ end
60
+
61
+ wrapper_attributes = {id: "#{model_name}_#{attachment}_cropbox_wrapper", class: 'cropbox_wrapper'}
62
+ if(opts[:width] && opts[:height])
63
+ wrapper_attributes.merge!(style: "width:#{opts[:width].round}px; height:#{opts[:height].round}px; overflow:hidden")
64
+ end
65
+
66
+ width, height = 100, 100
67
+ if (sizes = find_output_sizes(attachment_instance))
68
+ width, height = *sizes
69
+ end
70
+
71
+ output << @template.image_tag(attachment_instance.url, id: "#{model_name}_#{attachment}_cropbox", data: { output_width: width, output_height: height })
72
+
73
+ @template.content_tag(:div, output, wrapper_attributes)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ if defined? ActionView::Helpers::FormBuilder
81
+ ActionView::Helpers::FormBuilder.class_eval do
82
+ include CarrierWave::Crop::Helpers
83
+ end
84
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Crop
5
+ class Railtie < Rails::Railtie
6
+ initializer 'carrierwave.crop' do
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ class ActionDispatch::Http::UploadedFile
2
+ attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
3
+
4
+ alias_method :old_initialize, :initialize
5
+
6
+ def initialize(hash)
7
+ parameters = hash.with_indifferent_access
8
+ @crop_x = parameters[:crop_x]
9
+ @crop_y = parameters[:crop_y]
10
+ @crop_w = parameters[:crop_w]
11
+ @crop_h = parameters[:crop_h]
12
+
13
+ old_initialize(hash)
14
+ end
15
+ end
@@ -0,0 +1,67 @@
1
+ module CarrierWave
2
+ module Crop
3
+ module UploaderAdditions
4
+ # Performs cropping.
5
+ #
6
+ # Resizes the original image to 600x600 and then performs cropping
7
+ # process crop: [600, 600]
8
+ def crop(width = nil, height = nil)
9
+ if self.respond_to? "resize_to_limit"
10
+ begin
11
+ manipulate! do |img|
12
+ if crop_w.present? && crop_h.present?
13
+ w = crop_w
14
+ h = crop_h
15
+ else
16
+ orig_w = img['width']
17
+ orig_h = img['height']
18
+
19
+ ratio = width.to_f / height
20
+ orig_ratio = orig_w / orig_h
21
+
22
+ w = h = [orig_w, orig_h].min
23
+ if ratio < orig_ratio
24
+ w = orig_h * ratio
25
+ elsif ratio > orig_ratio
26
+ h = orig_w * ratio
27
+ end
28
+ end
29
+
30
+ if crop_x.blank? && crop_y.blank?
31
+ img.combine_options do |op|
32
+ op.crop "#{w.to_i}x#{h.to_i}+0+0"
33
+ op.gravity 'Center'
34
+ end
35
+ else
36
+ img.crop("#{w.to_i}x#{h.to_i}+#{crop_x.to_i}+#{crop_y.to_i}")
37
+ end
38
+ img.resize("#{width}x#{height}")
39
+ img
40
+ end
41
+
42
+ rescue Exception => e
43
+ raise CarrierWave::Crop::ProcessingError, "Failed to crop - #{e.message}"
44
+ end
45
+
46
+ else
47
+ raise CarrierWave::Crop::MissingProcessorError, "Failed to crop #{attachment}. Add mini_magick."
48
+ end
49
+ end
50
+
51
+ # Checks if the attachment received cropping attributes
52
+ # @param attachment [Symbol] Name of the attribute to be croppedv
53
+ #
54
+ # @return [Boolean]
55
+ # def cropping?
56
+ # crop_x.present? && crop_y.present? && crop_w.present? && crop_h.present?
57
+ # end
58
+
59
+ end ## End of UploaderAdditions
60
+ end ## End of Crop
61
+ end ## End of CarrierWave
62
+
63
+ if defined? CarrierWave::Uploader::Base
64
+ CarrierWave::Uploader::Base.class_eval do
65
+ include CarrierWave::Crop::UploaderAdditions
66
+ end
67
+ end