morandi 0.100.0 → 0.102.0
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +32 -2
- data/lib/morandi/image_processor.rb +4 -4
- data/lib/morandi/operation/image_border.rb +3 -4
- data/lib/morandi/profiled_pixbuf.rb +6 -5
- data/lib/morandi/srgb_conversion.rb +6 -5
- data/lib/morandi/version.rb +1 -1
- data/lib/morandi/vips_image_processor.rb +5 -5
- data/lib/morandi.rb +4 -2
- metadata +4 -23
- data/lib/gdk_pixbuf_cairo.so +0 -0
- data/lib/morandi_native.so +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c3e931b14e93f648cfbd847e686181be4d0f40add004ff52c31b126063fc46c6
|
|
4
|
+
data.tar.gz: 53f1e57062bcf23d20649ee8c2abb59d8050e21be64f125e54c77f40e0f35e7f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3271063861dccf057107b0abbfe915318d9f09ddf887f70a24082979a459d33203b0b8ed80e770552e41d1f46e94f7255d437ffac404aa48ecabc886448e7838
|
|
7
|
+
data.tar.gz: abe64371cc9809ebab22d421a8c92d82fb5d29c2733b872388885409b578daeeaa1efc5ef58e91d18bcb26a605feb828ab32c170a0d88aad0c81269baff677d2
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.102.0] 07.09.2026
|
|
8
|
+
### Fixed
|
|
9
|
+
- Unnecessary `.so` files are no longer shipped with the gem
|
|
10
|
+
- Rubocop on CI
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
- Obsolete dependency on colorscore
|
|
14
|
+
|
|
15
|
+
## [0.101.0] 28.01.2026
|
|
16
|
+
### Added
|
|
17
|
+
- [BREAKING] introduced automated cleanup of srgb files after processing
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
- [BREAKING] support for custom srgb file path
|
|
21
|
+
|
|
7
22
|
## [0.100.0] 17.01.2024
|
|
8
23
|
### Added
|
|
9
24
|
- Vips image processor (resizing)
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Library of simple image manipulations - replicating the behaviour of morandi-js.
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
Install `liblcms2-utils` to provide the `jpgicc` command used by `Morandi::ProfiledPixbuf`.
|
|
7
|
+
Install `liblcms2-utils` to provide the `jpgicc` command used by `Morandi::ProfiledPixbuf`.
|
|
8
8
|
|
|
9
9
|
Add this line to your application's Gemfile:
|
|
10
10
|
|
|
@@ -36,4 +36,34 @@ For the detailed documentation of options see `lib/morandi.rb`
|
|
|
36
36
|
|
|
37
37
|
### Development
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Development happens inside a docker image, with a Makefile provided as a simple CLI.
|
|
40
|
+
|
|
41
|
+
#### Build the image and run the container
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
make
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Above launches `guard`, which automatically runs tests when any file changes.
|
|
48
|
+
|
|
49
|
+
#### Run the full test suite manually from the guard prompt
|
|
50
|
+
```bash
|
|
51
|
+
all
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### Run an individual test
|
|
55
|
+
|
|
56
|
+
Add the `focus: true` annotation to an example or describe block.
|
|
57
|
+
|
|
58
|
+
#### Open a bash shell in the container
|
|
59
|
+
|
|
60
|
+
Useful, for example, to run rubocop:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
make shell
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> [!NOTE]
|
|
67
|
+
> The image builds and the gem works on ARM platform, but a few specs fail with tiny rendering output mismatches.
|
|
68
|
+
>
|
|
69
|
+
> CI uses AMD64 and is a source of truth for the specs
|
|
@@ -126,7 +126,7 @@ module Morandi
|
|
|
126
126
|
@pb = MorandiNative::PixbufUtils.brightness(@pb, brighten)
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
if options['gamma'] && not_equal_to_one(options['gamma'])
|
|
129
|
+
if options['gamma'] && not_equal_to_one?(options['gamma'])
|
|
130
130
|
@pb = MorandiNative::PixbufUtils.gamma(@pb,
|
|
131
131
|
options['gamma'])
|
|
132
132
|
end
|
|
@@ -197,7 +197,7 @@ module Morandi
|
|
|
197
197
|
# can't crop, won't crop
|
|
198
198
|
return if @width.nil? && @height.nil? && crop.nil?
|
|
199
199
|
|
|
200
|
-
crop = crop.map { |s| (s.to_f * @scale).floor } if crop && not_equal_to_one(@scale)
|
|
200
|
+
crop = crop.map { |s| (s.to_f * @scale).floor } if crop && not_equal_to_one?(@scale)
|
|
201
201
|
|
|
202
202
|
crop ||= Morandi::CropUtils.autocrop_coords(@pb.width, @pb.height, @width, @height)
|
|
203
203
|
|
|
@@ -226,7 +226,7 @@ module Morandi
|
|
|
226
226
|
colour ||= 'black'
|
|
227
227
|
|
|
228
228
|
crop = options['crop']
|
|
229
|
-
crop = crop.map { |s| (s.to_f * @scale).floor } if crop && not_equal_to_one(@scale)
|
|
229
|
+
crop = crop.map { |s| (s.to_f * @scale).floor } if crop && not_equal_to_one?(@scale)
|
|
230
230
|
|
|
231
231
|
op = Morandi::Operation::ImageBorder.new_from_hash(
|
|
232
232
|
'style' => style,
|
|
@@ -243,7 +243,7 @@ module Morandi
|
|
|
243
243
|
|
|
244
244
|
private
|
|
245
245
|
|
|
246
|
-
def not_equal_to_one(float)
|
|
246
|
+
def not_equal_to_one?(float)
|
|
247
247
|
(float - 1.0).abs >= Float::EPSILON
|
|
248
248
|
end
|
|
249
249
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'colorscore'
|
|
4
3
|
require 'morandi/image_operation'
|
|
5
4
|
|
|
6
5
|
module Morandi
|
|
@@ -16,7 +15,7 @@ module Morandi
|
|
|
16
15
|
return pixbuf unless %w[square retro].include? @style
|
|
17
16
|
|
|
18
17
|
create_pixbuf_from_image_surface(:rgb24, pixbuf.width, pixbuf.height) do |cr|
|
|
19
|
-
if @crop && (
|
|
18
|
+
if @crop && (@crop[0].negative? || @crop[1].negative?)
|
|
20
19
|
img_width = size[0]
|
|
21
20
|
img_height = size[1]
|
|
22
21
|
else
|
|
@@ -38,7 +37,7 @@ module Morandi
|
|
|
38
37
|
# Should be less than 1
|
|
39
38
|
pb_scale = (longest_side - (border_width * 2)) / longest_side
|
|
40
39
|
|
|
41
|
-
if @crop && (
|
|
40
|
+
if @crop && (@crop[0].negative? || @crop[1].negative?)
|
|
42
41
|
x -= @crop[0]
|
|
43
42
|
y -= @crop[1]
|
|
44
43
|
end
|
|
@@ -77,7 +76,7 @@ module Morandi
|
|
|
77
76
|
|
|
78
77
|
def draw_background(cr, img_height, img_width)
|
|
79
78
|
cr.save do
|
|
80
|
-
cr.translate(-@crop[0], -@crop[1]) if @crop && (
|
|
79
|
+
cr.translate(-@crop[0], -@crop[1]) if @crop && (@crop[0].negative? || @crop[1].negative?)
|
|
81
80
|
|
|
82
81
|
cr.save do
|
|
83
82
|
cr.set_operator :source
|
|
@@ -8,22 +8,23 @@ module Morandi
|
|
|
8
8
|
# It attempts to load an image using jpegicc/littlecms to ensure that it is sRGB.
|
|
9
9
|
# NOTE: pixbuf supports colour profiles, but it requires an explicit icc-profile option to embed it when saving file
|
|
10
10
|
class ProfiledPixbuf < GdkPixbuf::Pixbuf
|
|
11
|
-
def initialize(path,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
path = srgb_path(path) || path
|
|
11
|
+
def initialize(path, _local_options, max_size_px = nil)
|
|
12
|
+
srgb_converted_file_path = srgb_path(path)
|
|
13
|
+
path = srgb_converted_file_path || path
|
|
15
14
|
|
|
16
15
|
if max_size_px
|
|
17
16
|
super(file: path, width: max_size_px, height: max_size_px)
|
|
18
17
|
else
|
|
19
18
|
super(file: path)
|
|
20
19
|
end
|
|
20
|
+
ensure
|
|
21
|
+
FileUtils.rm_f(srgb_converted_file_path) if srgb_converted_file_path
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
private
|
|
24
25
|
|
|
25
26
|
def srgb_path(original_path)
|
|
26
|
-
Morandi::SrgbConversion.perform(original_path
|
|
27
|
+
Morandi::SrgbConversion.perform(original_path)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
end
|
|
@@ -7,15 +7,16 @@ module Morandi
|
|
|
7
7
|
class SrgbConversion
|
|
8
8
|
# Performs a conversion to srgb colour space if possible
|
|
9
9
|
# Returns a path to converted file on success or nil on failure
|
|
10
|
-
def self.perform(path
|
|
10
|
+
def self.perform(path)
|
|
11
11
|
return unless suitable_for_jpegicc?(path)
|
|
12
12
|
|
|
13
|
-
icc_file_path =
|
|
14
|
-
return icc_file_path if valid_jpeg?(icc_file_path)
|
|
15
|
-
|
|
13
|
+
icc_file_path = default_icc_path(path)
|
|
16
14
|
system('jpgicc', '-q97', path, icc_file_path, out: '/dev/null', err: '/dev/null')
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
unless valid_jpeg?(icc_file_path)
|
|
17
|
+
FileUtils.rm_f(icc_file_path) # jpgicc likes to leave an empty file after failing
|
|
18
|
+
return
|
|
19
|
+
end
|
|
19
20
|
|
|
20
21
|
icc_file_path
|
|
21
22
|
end
|
data/lib/morandi/version.rb
CHANGED
|
@@ -55,7 +55,7 @@ module Morandi
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def process!
|
|
58
|
-
source_file_path =
|
|
58
|
+
source_file_path = @path
|
|
59
59
|
begin
|
|
60
60
|
@img = Vips::Image.new_from_file(source_file_path)
|
|
61
61
|
rescue Vips::Error => e
|
|
@@ -68,7 +68,7 @@ module Morandi
|
|
|
68
68
|
end
|
|
69
69
|
if @size_limit_on_load_px
|
|
70
70
|
@scale = @size_limit_on_load_px.to_f / [@img.width, @img.height].max
|
|
71
|
-
@img = @img.resize(@scale) if not_equal_to_one(@scale)
|
|
71
|
+
@img = @img.resize(@scale) if not_equal_to_one?(@scale)
|
|
72
72
|
else
|
|
73
73
|
@scale = 1.0
|
|
74
74
|
end
|
|
@@ -113,7 +113,7 @@ module Morandi
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def apply_gamma!
|
|
116
|
-
return unless @options['gamma'] && not_equal_to_one(@options['gamma'])
|
|
116
|
+
return unless @options['gamma'] && not_equal_to_one?(@options['gamma'])
|
|
117
117
|
|
|
118
118
|
@img = @img.gamma(exponent: @options['gamma'])
|
|
119
119
|
end
|
|
@@ -152,7 +152,7 @@ module Morandi
|
|
|
152
152
|
# can't crop, won't crop
|
|
153
153
|
return if @output_width.nil? && @output_height.nil? && crop.nil?
|
|
154
154
|
|
|
155
|
-
crop = crop.map { |s| (s.to_f * @scale).floor } if crop && not_equal_to_one(@scale)
|
|
155
|
+
crop = crop.map { |s| (s.to_f * @scale).floor } if crop && not_equal_to_one?(@scale)
|
|
156
156
|
crop ||= Morandi::CropUtils.autocrop_coords(@img.width, @img.height, @output_width, @output_height)
|
|
157
157
|
@img = Morandi::CropUtils.apply_crop_vips(@img, crop[0], crop[1], crop[2], crop[3])
|
|
158
158
|
end
|
|
@@ -183,7 +183,7 @@ module Morandi
|
|
|
183
183
|
@img = @img.linear(1.0, colour_filter_modifier)
|
|
184
184
|
end
|
|
185
185
|
|
|
186
|
-
def not_equal_to_one(float)
|
|
186
|
+
def not_equal_to_one?(float)
|
|
187
187
|
(float - 1.0).abs >= Float::EPSILON
|
|
188
188
|
end
|
|
189
189
|
|
data/lib/morandi.rb
CHANGED
|
@@ -43,7 +43,6 @@ module Morandi
|
|
|
43
43
|
# size of the longer edge (ignoring shorter dimension!)
|
|
44
44
|
# @param target_path [String] target location for image
|
|
45
45
|
# @param local_options [Hash] Hash of options other than desired transformations
|
|
46
|
-
# @option local_options [String] 'path.icc' A path to store the input after converting to sRGB colour space
|
|
47
46
|
# @option local_options [String] 'processor' ('pixbuf') Name of the image processing library ('pixbuf', 'vips')
|
|
48
47
|
# NOTE: vips processor only handles subset of operations,
|
|
49
48
|
# see `Morandi::VipsImageProcessor.supports?` for details
|
|
@@ -58,7 +57,10 @@ module Morandi
|
|
|
58
57
|
cache_max = 0
|
|
59
58
|
concurrency = 2 # Hardcoding to 2 for now to maintain some balance between resource usage and performance
|
|
60
59
|
VipsImageProcessor.with_global_options(cache_max: cache_max, concurrency: concurrency) do
|
|
61
|
-
|
|
60
|
+
srgb_converted_file_path = Morandi::SrgbConversion.perform(source)
|
|
61
|
+
VipsImageProcessor.new(srgb_converted_file_path || source, options).write_to_jpeg(target_path)
|
|
62
|
+
ensure
|
|
63
|
+
FileUtils.rm_f(srgb_converted_file_path) if srgb_converted_file_path
|
|
62
64
|
end
|
|
63
65
|
else
|
|
64
66
|
ImageProcessor.new(source, options, local_options).tap(&:result).write_to_jpeg(target_path)
|
metadata
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: morandi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.102.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- |+
|
|
8
8
|
Geoff Youngs
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
autorequire:
|
|
12
11
|
bindir: bin
|
|
13
12
|
cert_chain: []
|
|
14
|
-
date:
|
|
13
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
15
14
|
dependencies:
|
|
16
15
|
- !ruby/object:Gem::Dependency
|
|
17
16
|
name: atk
|
|
@@ -41,20 +40,6 @@ dependencies:
|
|
|
41
40
|
- - "~>"
|
|
42
41
|
- !ruby/object:Gem::Version
|
|
43
42
|
version: '1.0'
|
|
44
|
-
- !ruby/object:Gem::Dependency
|
|
45
|
-
name: colorscore
|
|
46
|
-
requirement: !ruby/object:Gem::Requirement
|
|
47
|
-
requirements:
|
|
48
|
-
- - "~>"
|
|
49
|
-
- !ruby/object:Gem::Version
|
|
50
|
-
version: '0.0'
|
|
51
|
-
type: :runtime
|
|
52
|
-
prerelease: false
|
|
53
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
54
|
-
requirements:
|
|
55
|
-
- - "~>"
|
|
56
|
-
- !ruby/object:Gem::Version
|
|
57
|
-
version: '0.0'
|
|
58
43
|
- !ruby/object:Gem::Dependency
|
|
59
44
|
name: gdk_pixbuf2
|
|
60
45
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -116,8 +101,8 @@ email:
|
|
|
116
101
|
- git@intersect-uk.co.uk
|
|
117
102
|
executables: []
|
|
118
103
|
extensions:
|
|
119
|
-
- ext/morandi_native/extconf.rb
|
|
120
104
|
- ext/gdk_pixbuf_cairo/extconf.rb
|
|
105
|
+
- ext/morandi_native/extconf.rb
|
|
121
106
|
extra_rdoc_files: []
|
|
122
107
|
files:
|
|
123
108
|
- CHANGELOG.md
|
|
@@ -132,7 +117,6 @@ files:
|
|
|
132
117
|
- ext/morandi_native/morandi_native.c
|
|
133
118
|
- ext/morandi_native/rotate.h
|
|
134
119
|
- ext/morandi_native/tint.h
|
|
135
|
-
- lib/gdk_pixbuf_cairo.so
|
|
136
120
|
- lib/morandi.rb
|
|
137
121
|
- lib/morandi/cairo_ext.rb
|
|
138
122
|
- lib/morandi/crop_utils.rb
|
|
@@ -149,14 +133,12 @@ files:
|
|
|
149
133
|
- lib/morandi/srgb_conversion.rb
|
|
150
134
|
- lib/morandi/version.rb
|
|
151
135
|
- lib/morandi/vips_image_processor.rb
|
|
152
|
-
- lib/morandi_native.so
|
|
153
136
|
homepage: https://github.com/livelink/morandi-rb
|
|
154
137
|
licenses:
|
|
155
138
|
- MIT
|
|
156
139
|
metadata:
|
|
157
140
|
source_code_uri: https://github.com/livelink/morandi-rb
|
|
158
141
|
rubygems_mfa_required: 'true'
|
|
159
|
-
post_install_message:
|
|
160
142
|
rdoc_options: []
|
|
161
143
|
require_paths:
|
|
162
144
|
- lib
|
|
@@ -171,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
171
153
|
- !ruby/object:Gem::Version
|
|
172
154
|
version: '0'
|
|
173
155
|
requirements: []
|
|
174
|
-
rubygems_version:
|
|
175
|
-
signing_key:
|
|
156
|
+
rubygems_version: 4.0.4
|
|
176
157
|
specification_version: 4
|
|
177
158
|
summary: Simple Image Edits
|
|
178
159
|
test_files: []
|
data/lib/gdk_pixbuf_cairo.so
DELETED
|
Binary file
|
data/lib/morandi_native.so
DELETED
|
Binary file
|