morandi 0.12.0 → 0.99.03

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.
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