morandi 0.12.0 → 0.99.03

Sign up to get free protection for your applications and to get access to all the features.
data/lib/morandi/utils.rb DELETED
@@ -1,136 +0,0 @@
1
- require 'gdk_pixbuf2'
2
-
3
- module Morandi
4
- module Utils
5
- module_function
6
- def autocrop_coords(iw, ih, width, height)
7
- return nil unless width
8
- aspect = width.to_f / height.to_f
9
- iaspect = iw.to_f / ih.to_f
10
-
11
- if ih > iw
12
- # Portrait image
13
- # Check whether the aspect ratio is greater or smaller
14
- # ie. where constraints will hit
15
- aspect = height.to_f / width.to_f
16
- end
17
-
18
- # Landscape
19
- if aspect > iaspect
20
- # Width constraint - aspect-rect wider
21
- crop_width = iw
22
- crop_height = (crop_width / aspect).to_i
23
- else
24
- # Height constraint - aspect-rect wider
25
- crop_height = ih
26
- crop_width = (crop_height * aspect).to_i
27
- end
28
-
29
- [
30
- ((iw - crop_width)>>1),
31
- ((ih - crop_height)>>1),
32
- crop_width,
33
- crop_height
34
- ].map { |i| i.to_i }
35
- end
36
-
37
- def constrain(val,min,max)
38
- if val < min
39
- min
40
- elsif val > max
41
- max
42
- else
43
- val
44
- end
45
- end
46
-
47
- def apply_crop(pixbuf, x, y, w, h, fill_col = 0xffffffff)
48
- if (x < 0) or (y < 0) || ((x+w) > pixbuf.width) || ((y+h) > pixbuf.height)
49
- #tw, th = [w-x,w].max, [h-y,h].max
50
- base_pixbuf = GdkPixbuf::Pixbuf.new(
51
- colorspace: GdkPixbuf::Colorspace::RGB,
52
- has_alpha: false,
53
- bits_per_sample: 8,
54
- width: w,
55
- height: h
56
- )
57
- base_pixbuf.fill!(fill_col)
58
- dest_x = [x, 0].min
59
- dest_y = [y, 0].min
60
- #src_x = [x,0].max
61
- #src_y = [y,0].max
62
- dest_x = [-x,0].max
63
- dest_y = [-y,0].max
64
-
65
- #if x < 0
66
- #else
67
- #end
68
- #if y < 0
69
- # dest_h = [h-dest_y, pixbuf.height, base_pixbuf.height-dest_y].min
70
- #else
71
- # dest_h = [h,pixbuf.height].min
72
- #end
73
- # dest_w = [w-dest_x, pixbuf.width, base_pixbuf.width-dest_x].min
74
-
75
- offset_x = [x,0].max
76
- offset_y = [y,0].max
77
- copy_w = [w, pixbuf.width - offset_x].min
78
- copy_h = [h, pixbuf.height - offset_y].min
79
-
80
- paste_x = [x, 0].min * -1
81
- paste_y = [y, 0].min * -1
82
-
83
- if copy_w + paste_x > base_pixbuf.width
84
- copy_w = base_pixbuf.width - paste_x
85
- end
86
- if copy_h + paste_y > base_pixbuf.height
87
- copy_h = base_pixbuf.height - paste_y
88
- end
89
- base_pixbuf.composite! pixbuf, {
90
- dest_x: paste_x,
91
- dest_y: paste_y,
92
- dest_width: copy_w,
93
- dest_height: copy_h,
94
- offset_x: paste_x - offset_x,
95
- offset_y: paste_y - offset_y,
96
- scale_x: 1,
97
- scale_y: 1,
98
- interpolation_type: :hyper,
99
- overall_alpha: 255
100
- }
101
- pixbuf = base_pixbuf
102
- else
103
- x = constrain(x, 0, pixbuf.width)
104
- y = constrain(y, 0, pixbuf.height)
105
- w = constrain(w, 1, pixbuf.width - x)
106
- h = constrain(h, 1, pixbuf.height - y)
107
- #p [pixbuf, x, y, w, h]
108
- pixbuf = pixbuf.subpixbuf(x, y, w, h)
109
- end
110
- pixbuf
111
- end
112
- end
113
- end
114
-
115
- class GdkPixbuf::Pixbuf
116
- unless defined?(::GdkPixbuf::Pixbuf::InterpType)
117
- InterpType = GdkPixbuf::InterpType
118
- end
119
-
120
- def scale_max(max_size, interp = GdkPixbuf::Pixbuf::InterpType::BILINEAR, max_scale = 1.0)
121
- mul = (max_size / [width,height].max.to_f)
122
- mul = [max_scale = 1.0,mul].min
123
- scale(width * mul, height * mul, interp)
124
- end
125
- end
126
-
127
- class Cairo::ImageSurface
128
- def to_pixbuf
129
- loader = GdkPixbuf::PixbufLoader.new
130
- io = StringIO.new
131
- write_to_png(io)
132
- io.rewind
133
- loader.last_write(io.read)
134
- loader.pixbuf
135
- end
136
- end
data/morandi.gemspec DELETED
@@ -1,33 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'morandi/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "morandi"
8
- spec.version = Morandi::VERSION
9
- spec.authors = ["Geoff Youngs\n\n\n"]
10
- spec.email = ["git@intersect-uk.co.uk"]
11
- spec.summary = %q{Simple Image Edits}
12
- spec.description = %q{Apply simple edits to images}
13
- spec.homepage = ""
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.add_dependency "gtk2"
22
- spec.add_dependency "gdk_pixbuf2", "~> 3.4.0"
23
- spec.add_dependency "cairo"
24
- spec.add_dependency "pixbufutils"
25
- spec.add_dependency "redeye"
26
- spec.add_dependency "pango"
27
- spec.add_dependency "colorscore"
28
-
29
- spec.add_development_dependency "bundler"
30
- spec.add_development_dependency "pry"
31
- spec.add_development_dependency "rake"
32
- spec.add_development_dependency "rspec"
33
- end
Binary file
data/sample/sample.jpg DELETED
Binary file
data/spec/morandi_spec.rb DELETED
@@ -1,208 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'fileutils'
4
- require 'morandi'
5
-
6
- RSpec.describe Morandi, '#process' do
7
- context 'in command mode' do
8
- it 'should create ouptut' do
9
- Morandi.process('sample/sample.jpg', {}, out = 'sample/out_plain.jpg')
10
- expect(File.exist?(out))
11
- end
12
-
13
- context "with a big image and a bigger cropped area to fill" do
14
- it 'should create ouptut' do
15
- settings = {
16
- "crop"=>"0,477,15839,18804",
17
- "angle"=>90,
18
- "fx"=>"colour",
19
- "straighten"=>0.0,
20
- "gamma"=>0.98,
21
- "redeye"=>[]
22
- }
23
-
24
- Morandi.process('sample/100_mb_image.jpg', settings, out = 'sample/out_100_mb_image.jpg')
25
- expect(File.exist?(out))
26
- end
27
- end
28
-
29
- it 'should do rotation of images' do
30
- original = GdkPixbuf::Pixbuf.get_file_info('sample/sample.jpg')
31
- Morandi.process('sample/sample.jpg', {
32
- 'angle' => 90
33
- }, out = 'sample/out_rotate90.jpg')
34
- expect(File.exist?(out))
35
- _, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
36
- expect(original[1]).to eq(height)
37
- expect(original[2]).to eq(width)
38
- end
39
-
40
- it 'should accept pixbufs as an argument' do
41
- pixbuf = GdkPixbuf::Pixbuf.new(file: 'sample/sample.jpg')
42
- pro = Morandi::ImageProcessor.new(pixbuf, {}, {})
43
- pro.process!
44
- expect(pixbuf.width).to eq(pro.result.width)
45
- end
46
-
47
- it 'should do cropping of images' do
48
- Morandi.process('sample/sample.jpg', {
49
- 'crop' => [10, 10, 300, 300]
50
- }, out = 'sample/out_crop.jpg')
51
- expect(File.exist?(out))
52
- _, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
53
- expect(width).to eq(300)
54
- expect(height).to eq(300)
55
- end
56
-
57
- it 'should use user supplied path.icc' do
58
- src = 'sample/sample.jpg'
59
- icc = '/tmp/this-is-secure-thing.jpg'
60
- default_icc = Morandi::ImageProcessor.default_icc_path(src)
61
- out = 'sample/out_icc.jpg'
62
- FileUtils.rm_f(default_icc)
63
- Morandi.process(src, {}, out, 'path.icc' => icc)
64
- expect(File).to exist(icc)
65
- expect(File).not_to exist(default_icc)
66
- end
67
-
68
- it 'should ignore user supplied path.icc' do
69
- src = 'sample/sample.jpg'
70
- icc = '/tmp/this-is-insecure-thing.jpg'
71
- default_icc = Morandi::ImageProcessor.default_icc_path(src)
72
- FileUtils.rm_f(icc)
73
- FileUtils.rm_f(default_icc)
74
- out = 'sample/out_icc.jpg'
75
- Morandi.process(src, { 'path.icc' => icc, 'output.max' => 200 }, out)
76
- expect(File).not_to exist(icc)
77
- expect(File).to exist(default_icc)
78
- end
79
-
80
- it 'should do cropping of images with a string' do
81
- Morandi.process('sample/sample.jpg', {
82
- 'crop' => '10,10,300,300'
83
- }, out = 'sample/out_crop.jpg')
84
- expect(File.exist?(out))
85
- _, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
86
- expect(width).to eq(300)
87
- expect(height).to eq(300)
88
- end
89
-
90
- it 'should reduce the size of images' do
91
- Morandi.process('sample/sample.jpg', {
92
- 'output.max' => 200
93
- }, out = 'sample/out_reduce.jpg')
94
- expect(File.exist?(out))
95
- _, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
96
- expect(width).to be <= 200
97
- expect(height).to be <= 200
98
- end
99
-
100
- it 'should reduce the straighten images' do
101
- Morandi.process('sample/sample.jpg', {
102
- 'straighten' => 5
103
- }, out = 'sample/out_straighten.jpg')
104
- expect(File.exist?(out))
105
- info, _, _ = GdkPixbuf::Pixbuf.get_file_info(out)
106
- expect(info.name).to eq('jpeg')
107
- end
108
-
109
- it 'should reduce the gamma correct images' do
110
- Morandi.process('sample/sample.jpg', {
111
- 'gamma' => 1.2
112
- }, out = 'sample/out_gamma.jpg')
113
- expect(File.exist?(out))
114
- info, _, _ = GdkPixbuf::Pixbuf.get_file_info(out)
115
- expect(info.name).to eq('jpeg')
116
- end
117
-
118
- it 'should reduce the size of images' do
119
- Morandi.process('sample/sample.jpg', {
120
- 'fx' => 'sepia'
121
- }, out = 'sample/out_sepia.jpg')
122
- expect(File.exist?(out))
123
- info, _, _ = GdkPixbuf::Pixbuf.get_file_info(out)
124
- expect(info.name).to eq('jpeg')
125
- end
126
-
127
- it 'should output at the specified size' do
128
- Morandi.process('sample/sample.jpg', {
129
- 'output.width' => 300,
130
- 'output.height' => 200,
131
- 'image.auto-crop' => true,
132
- 'output.limit' => true
133
- }, out = 'sample/out_at_size.jpg')
134
- expect(File.exist?(out))
135
- info, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
136
- expect(info.name).to eq('jpeg')
137
- expect(width).to be <= 300
138
- expect(height).to be <= 200
139
- end
140
-
141
- it 'should blur the image' do
142
- Morandi.process('sample/sample.jpg', {
143
- 'sharpen' => -3
144
- }, out = 'sample/out_blur.jpg')
145
- expect(File.exist?(out))
146
- end
147
-
148
- it 'should apply a border and maintain the target size' do
149
- Morandi.process('sample/sample.jpg', {
150
- 'border-style' => 'square',
151
- 'background-style' => 'dominant',
152
- 'border-size-mm' => 5,
153
- 'output.width' => 800,
154
- 'output.height' => 650
155
- }, out = 'sample/out_border.jpg')
156
- expect(File.exist?(out))
157
-
158
- info, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
159
- expect(info.name).to eq('jpeg')
160
- expect(width).to eq 800
161
- expect(height).to eq 650
162
- end
163
-
164
- it 'should apply multiple transformations' do
165
- Morandi.process('sample/sample.jpg', {
166
- 'brighten' => 5,
167
- 'contrast' => 5,
168
- 'sharpen' => 2,
169
- 'fx' => 'greyscale',
170
- 'border-style' => 'solid',
171
- 'background-style' => '#00FF00',
172
- 'crop' => [50, 0, 750, 650],
173
- 'output.width' => 300,
174
- 'output.height' => 260,
175
- 'output.limit' => true
176
- }, out = 'sample/out_various.jpg')
177
- expect(File.exist?(out))
178
-
179
- info, width, height = GdkPixbuf::Pixbuf.get_file_info(out)
180
- expect(info.name).to eq('jpeg')
181
- expect(width).to eq 300
182
- expect(height).to eq 260
183
- end
184
- end
185
-
186
- context 'with increasing quality settings' do
187
- let(:max_quality_file_size) do
188
- Morandi.process('sample/sample.jpg', { 'quality' => 100 }, 'sample/out-100.jpg')
189
- File.size('sample/out-100.jpg')
190
- end
191
-
192
- let(:default_of_97_quality) do
193
- Morandi.process('sample/sample.jpg', {}, 'sample/out-97.jpg')
194
- File.size('sample/out-97.jpg')
195
- end
196
-
197
- let(:quality_of_40_by_options_args) do
198
- Morandi.process('sample/sample.jpg', { 'quality' => 40 }, 'sample/out-40.jpg')
199
- File.size('sample/out-40.jpg')
200
- end
201
-
202
- # Sort the output files' sizes and expect them to match to quality order
203
- it 'creates files of increasing size' do
204
- created_file_sizes = [default_of_97_quality, max_quality_file_size, quality_of_40_by_options_args].sort
205
- expect(created_file_sizes).to eq([quality_of_40_by_options_args, default_of_97_quality, max_quality_file_size])
206
- end
207
- end
208
- end
data/spec/spec_helper.rb DELETED
@@ -1,19 +0,0 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper"` to ensure that it is only
4
- # loaded once.
5
- #
6
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
-
8
- require "pry"
9
-
10
- RSpec.configure do |config|
11
- config.run_all_when_everything_filtered = true
12
- config.filter_run :focus
13
-
14
- # Run specs in random order to surface order dependencies. If you find an
15
- # order dependency and want to debug it, you can fix the order by providing
16
- # the seed, which is printed after each run.
17
- # --seed 1234
18
- config.order = 'random'
19
- end