carrierwave-crop-on-fly 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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