paper_cropper 0.0.2

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: 765ec5c7bbb8a9db019e7c04a976c98a61d0b5ce
4
+ data.tar.gz: db472297bc0ae0fe57f463d113141514198fefaa
5
+ SHA512:
6
+ metadata.gz: 8005e706ae466fb0029f9c34aee3fe5929fbee660b7bd9486347267c1ad657a84717e3204fc2caf83338f709a57b2784659a3acdab82f9938f516a61ebe7f68e
7
+ data.tar.gz: 81906bd23691a56d4617c5ebe2981efc16b9995c37315eca45adae02ced0d7a3137e8bea97dc2e0f03b669e789da56db4df93c5fcf6e62aabffa9d7a2eaebdb0
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # PaperCropper gem
2
+
3
+ PaperCropper gem is a gem for cropping images using [cropper js](https://github.com/fengyuanchen/cropperjs) and [Paperclip](https://github.com/thoughtbot/paperclip)
4
+
5
+ All examples are based on a `cover` attachment
6
+
7
+ ## migrations
8
+
9
+ ```ruby
10
+ create_table :gallery_albums do |t|
11
+ t.attachment :cover # paperclip required
12
+ t.crop_attachment :cover # add extra columns for crop
13
+ end
14
+ ```
15
+
16
+ ## model
17
+
18
+ ```ruby
19
+ # aspect 1:1
20
+ crop_attached_file :cover
21
+
22
+ # aspect 16:4
23
+ crop_attached_file :cover, aspect: '16:4'
24
+
25
+ # free (without aspect restriction)
26
+ crop_attached_file :cover, aspect: false
27
+ ```
28
+
29
+ ## controler
30
+ Take care of permitted params. Add the following fields to ```permitted``` strong attributes:
31
+
32
+ ```ruby
33
+ :cover_crop_x, :cover_crop_y, :cover_crop_width, :cover_crop_height
34
+ ```
35
+
36
+ ## javascripts
37
+
38
+ ~~~
39
+ //= require cropper
40
+ //= require paper_cropper
41
+
42
+ // Crop
43
+ $('.crop-image-container').each(function(){
44
+ papercropper = new PaperCropper(this, {})
45
+ });
46
+ ~~~
47
+
48
+ ## scss
49
+
50
+ ~~~
51
+ @import "cropper";
52
+ @import "paper_cropper";
53
+ ~~~
54
+
55
+ The paper_cropper is not required, is only for a small changes. The only thing required from 'paper_cropper' is this rule:
56
+
57
+ ~~~
58
+ /* Limit image width to avoid overflow the container */
59
+ .crop-image-container img.crop-image {
60
+ max-width: 100%; /* This rule is very important, please do not ignore this! */
61
+ }
62
+ ~~~
63
+
64
+ ---------------------------------------------
65
+
66
+ ## helpers
67
+
68
+ helper, with twitter bootstrap classes, custom formatted, and other things
69
+
70
+ ~~~
71
+ <%= form_for ..... %>
72
+ <%= f.tws_cropper_box :cover %>
73
+ <% end %>
74
+ ~~~
75
+
76
+ **custom (without helper)**
77
+
78
+ if you do not want to use helper, you can do what you want, for example you could make the file selector ".crop-image-file-input" below the picture "crop-image-wrapper"
79
+
80
+ the most important thing is to keep the "crop-image ..." classes and "crop-image-container" and "crop-image-wrapper" containers
81
+
82
+ for example:
83
+
84
+ ~~~
85
+ <!-- [required] Main container (you need to supply this in JS constructor) -->
86
+ <div class="crop-image-container">
87
+ <!-- [required] Hidden input for save the crop values -->
88
+ <input class="crop-image-value-x" type="hidden" name="cover_crop_x" value="">
89
+ <input class="crop-image-value-y" type="hidden" name="cover_crop_y" value="">
90
+ <input class="crop-image-value-width" type="hidden" name="cover_crop_width" value="">
91
+ <input class="crop-image-value-height" type="hidden" name="cover_crop_height" value="">
92
+
93
+ <!-- [required] Wrap the image or canvas element with a block element (container) -->
94
+ <div class="crop-image-wrapper">
95
+ <!-- [required] Image to crop -->
96
+ <img class="crop-image" src="">
97
+ </div>
98
+
99
+ <!-- [required] File input for change the image -->
100
+ <input class="crop-image-file-input" type="file">
101
+
102
+ <!-- [optional] Buttons -->
103
+ <button class="crop-image-btn-zoom-in" type="button">Zoom in</button>
104
+ <button class="crop-image-btn-zoom-out" type="button">Zoom out</button>
105
+ <button class="crop-image-btn-move-left" type="button">Move left</button>
106
+ <button class="crop-image-btn-move-right" type="button">Move right</button>
107
+ <button class="crop-image-btn-move-up" type="button">Move up</button>
108
+ <button class="crop-image-btn-move-down" type="button">Move down</button>
109
+ </div>
110
+ ~~~
111
+
112
+ # License
113
+
114
+ PaperCropper is Copyright © 2016 CodiTramuntana SL. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
115
+
116
+ # About CodiTramuntana
117
+
118
+ ![coditramuntana](http://www.coditramuntana.com/assets/ic_logo_medium.png)
119
+
120
+ PaperCropper is maintained by [CodiTramuntana](http://www.coditramuntana.com).
121
+ PaperCropper is the mix of [cropper js](https://github.com/fengyuanchen/cropperjs) and
122
+ [Paperclip](https://github.com/thoughtbot/paperclip) and some glue code to make things
123
+ easier.
124
+
125
+ The names and logos for CodiTramuntana are trademarks of CodiTramuntana SL.
126
+
127
+ We love open source software!
@@ -0,0 +1,149 @@
1
+ /**
2
+ * PaperCropper
3
+ *
4
+ * @param container
5
+ * Main container of objects
6
+ * @param options
7
+ * Extra options
8
+ *
9
+ * Example, important all classes used for crop starts with "crop-image*"
10
+ * The buttons, classes 'crop-image-btn-*' are optional
11
+ *
12
+ <!-- Main container (you need to supply this in constructor) -->
13
+ <div class="crop-image-container">
14
+ <!-- Hidden input for save the crop values -->
15
+ <input class="crop-image-value-x" type="hidden" name="cover_crop_x" value="">
16
+ <input class="crop-image-value-y" type="hidden" name="cover_crop_y" value="">
17
+ <input class="crop-image-value-width" type="hidden" name="cover_crop_width" value="">
18
+ <input class="crop-image-value-height" type="hidden" name="cover_crop_height" value="">
19
+
20
+ <!-- File input for change the image -->
21
+ <input class="crop-image-file-input" type="file">
22
+
23
+ <hr>
24
+
25
+ <!-- Wrap the image or canvas element with a block element (container) -->
26
+ <div class="crop-image-wrapper">
27
+ <img class="crop-image" src="">
28
+ </div>
29
+
30
+ <hr>
31
+
32
+ <button class="crop-image-btn-zoom-in" type="button">Zoom in</button>
33
+ <button class="crop-image-btn-zoom-out" type="button">Zoom out</button>
34
+ <button class="crop-image-btn-move-left" type="button">Move left</button>
35
+ <button class="crop-image-btn-move-right" type="button">Move right</button>
36
+ <button class="crop-image-btn-move-up" type="button">Move up</button>
37
+ <button class="crop-image-btn-move-down" type="button">Move down</button>
38
+ </div>
39
+
40
+ */
41
+ function PaperCropper(container, opt) {
42
+ var that = this;
43
+ this.container = $(container);
44
+ this.image = $(container).find('.crop-image');
45
+ this.inputX = $(container).find('.crop-image-value-x');
46
+ this.inputY = $(container).find('.crop-image-value-y');
47
+ this.inputWidth = $(container).find('.crop-image-value-width');
48
+ this.inputHeight = $(container).find('.crop-image-value-height');
49
+
50
+ var aspect = $(container).attr('data-crop-image-range');
51
+ if( isNaN(aspect) ) {
52
+ this.aspect = null;
53
+ } else {
54
+ this.aspect = parseFloat(aspect);
55
+ }
56
+
57
+ this.init();
58
+ }
59
+
60
+ /** Check if browswer support it */
61
+ PaperCropper.isSupported = function() {
62
+ return (typeof FileReader !== "undefined");
63
+ }
64
+
65
+ /** Initializes all */
66
+ PaperCropper.prototype.init = function() {
67
+ var fileInput = this.container.find('input.crop-image-file-input');
68
+ var that = this;
69
+
70
+ // file input change
71
+ fileInput.change(function(event){
72
+ that.fileInputChange(event);
73
+ });
74
+
75
+ // cropper
76
+ this.cropper = new Cropper(this.image[0], {
77
+ aspectRatio: this.aspect,
78
+ crop: function(event){
79
+ that.cropperCrop(event);
80
+ },
81
+ built: function() {
82
+ console.log('cropper build')
83
+ that.cropperBuild();
84
+ }
85
+ });
86
+
87
+
88
+ // buttons
89
+ this.container.find('.crop-image-btn-zoom-in').click(function(){
90
+ that.cropper.zoom(0.1);
91
+ });
92
+ this.container.find('.crop-image-btn-zoom-out').click(function(){
93
+ that.cropper.zoom(-0.1);
94
+ });
95
+ this.container.find('.crop-image-btn-move-left').click(function(){
96
+ that.cropper.move(-10,0);
97
+ });
98
+ this.container.find('.crop-image-btn-move-right').click(function(){
99
+ that.cropper.move(10,0);
100
+ });
101
+ this.container.find('.crop-image-btn-move-up').click(function(){
102
+ that.cropper.move(0,-10);
103
+ });
104
+ this.container.find('.crop-image-btn-move-down').click(function(){
105
+ that.cropper.move(0,10);
106
+ });
107
+ }
108
+
109
+ /** Callback method used when cropper are full loaded */
110
+ PaperCropper.prototype.cropperBuild = function() {
111
+ // set initial values
112
+ this.setCropperData(this.inputX.val(), this.inputY.val(), this.inputWidth.val(), this.inputHeight.val());
113
+ }
114
+
115
+ /** Callback method used when the user changes the crop */
116
+ PaperCropper.prototype.cropperCrop = function (event) {
117
+ console.log('crop:',event.detail)
118
+ console.log('crop crop data:',this.cropper.getData())
119
+ this.inputX.val(parseInt(event.detail.x));
120
+ this.inputY.val(parseInt(event.detail.y));
121
+ this.inputWidth.val(parseInt(event.detail.width));
122
+ this.inputHeight.val(parseInt(event.detail.height));
123
+ }
124
+
125
+ /** Callback method used when the user changes the file */
126
+ PaperCropper.prototype.fileInputChange = function (event) {
127
+ var input = event.target;
128
+ var that = this;
129
+ if (input.files && input.files[0]) {
130
+ var reader = new FileReader();
131
+ reader.onload = function (e) {
132
+ that.cropper.replace(e.target.result);
133
+ }
134
+ reader.readAsDataURL(input.files[0]);
135
+ }
136
+ }
137
+
138
+ /** Set the cropper data */
139
+ PaperCropper.prototype.setCropperData = function (x, y, width, height) {
140
+ this.cropper.setData({
141
+ 'x': parseInt(x),
142
+ 'y': parseInt(y),
143
+ 'width': parseInt(width),
144
+ 'height': parseInt(height),
145
+ 'rotate': 0,
146
+ 'scaleX': 1,
147
+ 'scaleY': 1,
148
+ });
149
+ }
@@ -0,0 +1,7 @@
1
+ /* Limit image width to avoid overflow the container */
2
+ .crop-image-container img.crop-image {
3
+ max-width: 100%; /* This rule is very important, please do not ignore this! */
4
+ }
5
+ .crop-image-container div.crop-image-wrapper {
6
+ max-height: 300px;
7
+ }
@@ -0,0 +1,4 @@
1
+ module PaperCropper
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,66 @@
1
+ module PaperCropper
2
+ module FormHelpers
3
+
4
+ # Create a new cropper box with all buttons and classe. This will be use the
5
+ # twitter bootstrap classes
6
+ # @param attachment_name [Symbol] Name of the attachment to crop
7
+ def tws_cropper_box attachment_name
8
+ obj = self.object
9
+ form_helper = self
10
+ aspect_ratio = obj.send "#{attachment_name}_aspect"
11
+
12
+ out = "<div class='crop-image-container' data-crop-image-range='#{aspect_ratio}'>"
13
+
14
+ out << form_helper.hidden_field(:"#{attachment_name}_crop_x", class: 'crop-image-value-x')
15
+ out << form_helper.hidden_field(:"#{attachment_name}_crop_y", class: 'crop-image-value-y')
16
+ out << form_helper.hidden_field(:"#{attachment_name}_crop_width", class: 'crop-image-value-width')
17
+ out << form_helper.hidden_field(:"#{attachment_name}_crop_height", class: 'crop-image-value-height')
18
+
19
+ out << form_helper.file_field(attachment_name, class: 'crop-image-file-input', label_col: "col-sm-3", control_col: "col-sm-9")
20
+
21
+ out << '<hr>'
22
+
23
+ image_src = obj.send("#{attachment_name}?") ? obj.send(attachment_name).url : ''
24
+ out << '<div class="crop-image-wrapper">'
25
+ out << "<img class='crop-image' class='crop-image' src='#{image_src}'>"
26
+ out << '</div>'
27
+
28
+ out << '<hr>'
29
+
30
+ out << '<div class="btn-group pull-left" role="group">'
31
+ out << "<button type='button' class='crop-image-btn-zoom-in btn btn-default'>&#43;</button>"
32
+ out << "<button type='button' class='crop-image-btn-zoom-out btn btn-default'>&#45;</button>"
33
+ out << '</div>'
34
+
35
+ out << '<div class="btn-group pull-right" role="group">'
36
+ out << "<button type='button' class='crop-image-btn-move-left btn btn-default'>left</button>"
37
+ out << "<button type='button' class='crop-image-btn-move-right btn btn-default'>right</button>"
38
+ out << "<button type='button' class='crop-image-btn-move-up btn btn-default'>up</button>"
39
+ out << "<button type='button' class='crop-image-btn-move-down btn btn-default'>down</button>"
40
+ out << '</div>'
41
+
42
+ out << '</div>'
43
+
44
+ out.html_safe
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+
51
+ # ActionView::Helpers::FormBuilder support
52
+ # #########################################################################
53
+ if defined? ActionView::Helpers::FormBuilder
54
+ ActionView::Helpers::FormBuilder.class_eval do
55
+ include PaperCropper::FormHelpers
56
+ end
57
+ end
58
+
59
+
60
+ # BootstrapForm::FormBuilder support
61
+ # #########################################################################
62
+ # if defined? BootstrapForm::FormBuilder
63
+ # BootstrapForm::FormBuilder.class_eval do
64
+ # include PaperCropper::FormHelpers
65
+ # end
66
+ # end
@@ -0,0 +1,6 @@
1
+ module PaperCropper
2
+ # Paperclip log wrapper
3
+ def self.log(text)
4
+ Paperclip.log(text)
5
+ end
6
+ end
@@ -0,0 +1,129 @@
1
+ module PaperCropper
2
+ module ModelExtension
3
+ # Class methods
4
+ # #########################################################################
5
+ # Initializes attachment cropping in your model
6
+ #
7
+ # crop_attached_file :avatar
8
+ #
9
+ # You can also define an initial aspect ratio for the crop and preview box through opts[:aspect]
10
+ #
11
+ # crop_attached_file :avatar, :aspect => "4:3"
12
+ #
13
+ # Or unlock it
14
+ #
15
+ # crop_attached_file :avatar, :aspect => false
16
+ #
17
+ # @param attachment_name [Symbol] Name of the desired attachment to crop
18
+ # @param opts [Hash]
19
+ # @option opts [Range, String, FalseClass] :aspect
20
+ module ClassMethods
21
+ def crop_attached_file(attachment_name, opts = {})
22
+ opts = opts.dup
23
+
24
+ include PaperCropper::ModelExtension::InstanceMethods
25
+
26
+ aspect = normalize_aspect opts[:aspect]
27
+ send :define_method, :"#{attachment_name}_aspect" do
28
+ aspect.first.to_f / aspect.last.to_f if aspect
29
+ end
30
+
31
+ if respond_to? :attachment_definitions
32
+ # for Paperclip <= 3.4
33
+ definitions = attachment_definitions
34
+ else
35
+ # for Paperclip >= 3.5
36
+ definitions = Paperclip::Tasks::Attachments.instance.definitions_for(self)
37
+ end
38
+ processors = definitions[attachment_name][:processors] ||= []
39
+ unless processors.include? :paper_cropper
40
+ processors << :paper_cropper
41
+ end
42
+
43
+ after_save :"reprocess_to_crop_#{attachment_name}_attachment"
44
+ after_update {
45
+ if send(:attachment_changed?, attachment_name)
46
+ self.update_column(:"#{attachment_name}_updated_at", Time.now)
47
+ end
48
+ }
49
+ end
50
+
51
+ # Returns a valid and normalized value for aspect ratio
52
+ # It will return 1.. if aspect is nil or a invalid string
53
+ # @param aspect [Range, String, FalseClass]
54
+ #
55
+ # @return [Range]
56
+ def normalize_aspect(aspect)
57
+ if aspect.kind_of?(String) && aspect =~ PaperCropper::RegExp::ASPECT
58
+ Range.new *aspect.split(':').map(&:to_i)
59
+ elsif aspect.kind_of?(Range)
60
+ return aspect.first.to_i..aspect.last.to_i
61
+ elsif aspect == false
62
+ return aspect
63
+ else
64
+ 1..1
65
+ end
66
+ end
67
+ end
68
+
69
+ # Instance methods
70
+ # #########################################################################
71
+ module InstanceMethods
72
+ # Asks if the attachment received a crop process
73
+ # @param attachment_name [Symbol]
74
+ #
75
+ # @return [Boolean]
76
+ def cropping?(attachment_name)
77
+ !self.send(:"#{attachment_name}_crop_x").blank? &&
78
+ !self.send(:"#{attachment_name}_crop_y").blank? &&
79
+ !self.send(:"#{attachment_name}_crop_width").blank? &&
80
+ !self.send(:"#{attachment_name}_crop_height").blank?
81
+ end
82
+
83
+ def attachment_changed?(attachment_name)
84
+ ["#{attachment_name}_name", "#{attachment_name}_content_type",
85
+ "#{attachment_name}_file_size", "#{attachment_name}_updated_at",
86
+ "#{attachment_name}_crop_x", "#{attachment_name}_crop_y",
87
+ "#{attachment_name}_crop_width",
88
+ "#{attachment_name}_crop_height"
89
+ ].any? { |attr|
90
+ method= "#{attr}_changed?".to_sym
91
+ if respond_to?(method)
92
+ self.send(method)
93
+ end
94
+ }
95
+ end
96
+
97
+ # Uses method missing to responding the model callback for reprocess the image
98
+ def method_missing(method, *args)
99
+ if method.to_s =~ PaperCropper::RegExp::CALLBACK
100
+ reprocess_cropped_attachment(
101
+ method.to_s.scan(PaperCropper::RegExp::CALLBACK).flatten.first.to_sym
102
+ )
103
+ else
104
+ super
105
+ end
106
+ end
107
+
108
+ private
109
+ # Saves the attachment if the crop attributes are present
110
+ # @param attachment_name [Symbol]
111
+ def reprocess_cropped_attachment(attachment_name)
112
+ if cropping?(attachment_name)
113
+ attachment_instance = send(attachment_name)
114
+ attachment_instance.assign(attachment_instance)
115
+ attachment_instance.save
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+
123
+ # ActiveRercord support
124
+ # #########################################################################
125
+ if defined? ActiveRecord::Base
126
+ ActiveRecord::Base.class_eval do
127
+ extend PaperCropper::ModelExtension::ClassMethods
128
+ end
129
+ end
@@ -0,0 +1,6 @@
1
+ module PaperCropper
2
+ module RegExp
3
+ ASPECT = /^([1-9]{1}\d*):([1-9]{1}\d*)$/
4
+ CALLBACK = /reprocess_to_crop_(\S{1,})_attachment/
5
+ end
6
+ end
@@ -0,0 +1,76 @@
1
+ # Custom migration data type
2
+ # Based on papercli schema.rb from: https://github.com/thoughtbot/paperclip => /lib/paperclip/schema.rb
3
+ module PaperCropper
4
+ module Schema
5
+ COLUMNS = {
6
+ crop_x: :integer,
7
+ crop_y: :integer,
8
+ crop_width: :integer,
9
+ crop_height: :integer
10
+ }
11
+
12
+ #
13
+ # #########################################################################
14
+ module Statements
15
+ def add_crop_attachment(table_name, *attachment_names)
16
+ raise ArgumentError, "Please specify attachment name in your add_attachment call in your migration." if attachment_names.empty?
17
+
18
+ options = attachment_names.extract_options!
19
+
20
+ attachment_names.each do |attachment_name|
21
+ COLUMNS.each_pair do |column_name, column_type|
22
+ column_options = options.merge(options[column_name.to_sym] || {})
23
+ add_column(table_name, "#{attachment_name}_#{column_name}", column_type, column_options)
24
+ end
25
+ end
26
+ end
27
+
28
+ def remove_crop_attachment(table_name, *attachment_names)
29
+ raise ArgumentError, "Please specify attachment name in your remove_attachment call in your migration." if attachment_names.empty?
30
+
31
+ attachment_names.each do |attachment_name|
32
+ COLUMNS.keys.each do |column_name|
33
+ remove_column(table_name, "#{attachment_name}_#{column_name}")
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ #
40
+ # #########################################################################
41
+ module TableDefinition
42
+ def crop_attachment(*attachment_names)
43
+ options = attachment_names.extract_options!
44
+ attachment_names.each do |attachment_name|
45
+ COLUMNS.each_pair do |column_name, column_type|
46
+ column_options = options.merge(options[column_name.to_sym] || {})
47
+ column("#{attachment_name}_#{column_name}", column_type, column_options)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ #
54
+ # #########################################################################
55
+ module CommandRecorder
56
+ def add_attachment(*args)
57
+ record(:add_attachment, args)
58
+ end
59
+
60
+ private
61
+
62
+ def invert_add_attachment(args)
63
+ [:remove_attachment, args]
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+
70
+
71
+ # ActiveRecord support
72
+ # #########################################################################
73
+ ActiveRecord::ConnectionAdapters::Table.send :include, PaperCropper::Schema::TableDefinition
74
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, PaperCropper::Schema::TableDefinition
75
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, PaperCropper::Schema::Statements
76
+ ActiveRecord::Migration::CommandRecorder.send :include, PaperCropper::Schema::CommandRecorder
@@ -0,0 +1,12 @@
1
+ module PaperCropper
2
+ # Changelog based on Semantic Versioning: http://semver.org
3
+ # REMEMBER: Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.
4
+
5
+ # 0.0.2 PATCH
6
+ #- Added ActiveRecord extensions to force attachment updated_at field to be setted
7
+ # on every attachment change.
8
+
9
+ unless defined?(PaperCropper::VERSION)
10
+ VERSION = "0.0.2".freeze
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ require 'paper_cropper/engine'
2
+ require 'paper_cropper/schema'
3
+ require 'paper_cropper/reg_exp'
4
+ require 'paper_cropper/model_extension'
5
+ require 'paper_cropper/helpers'
6
+ require 'paper_cropper/logger'
7
+ require 'paperclip_processors/paper_cropper'
@@ -0,0 +1,31 @@
1
+ require "paperclip"
2
+
3
+ module Paperclip
4
+ class PaperCropper < Thumbnail
5
+ def transformation_command
6
+ if crop_command
7
+ crop_command + super.join(' ').sub(/ -crop \S+/, '').split(' ')
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ def crop_command
14
+ target = @attachment.instance
15
+
16
+ if target.cropping?(@attachment.name)
17
+ begin
18
+ x = Integer(target.send :"#{@attachment.name}_crop_x")
19
+ y = Integer(target.send :"#{@attachment.name}_crop_y")
20
+ w = Integer(target.send :"#{@attachment.name}_crop_width")
21
+ h = Integer(target.send :"#{@attachment.name}_crop_height")
22
+ ["-crop", "#{w}x#{h}+#{x}+#{y}"]
23
+ rescue Exception => e
24
+ ::PaperCropper.log("[paper_cropper] #{@attachment.name} crop w/h/x/y were non-integer. Error: #{e.to_s}")
25
+ return
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+ end
Binary file