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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ca1f4a637e59ee90de4f309dfecc40eae27b103f416ea301af36e8bd04c555f
4
- data.tar.gz: 8ebeda3024e6275ea7e8b75c8357339523a59a24987e1ebd07142cba445edce7
3
+ metadata.gz: c3e931b14e93f648cfbd847e686181be4d0f40add004ff52c31b126063fc46c6
4
+ data.tar.gz: 53f1e57062bcf23d20649ee8c2abb59d8050e21be64f125e54c77f40e0f35e7f
5
5
  SHA512:
6
- metadata.gz: 55308d1a2ae4626a81bf1faa9a6ae0535f816d777e31d25266e36e563bdc1dc60c55ef588ade477ce113a13bd20f80aefd046a52c1e4aaccffdc103e48d75cac
7
- data.tar.gz: c10ab8cbe21121d50a2c0a10cdb6c0fefe595962d11cf936adeaef78e8291bd4688b37bb464577c7f455d8aa02e04def65d46930a86fb3cbf9c1aed4e9abf972
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`. Also ensure that your host system has `imagemagick` installed, which is required by the `colorscore` gem.
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
- Since this gem depends on the `liblcms2-utils` library, which can be awkward to install on some operating systems, we also provide a development docker image. A Makefile is also provided as a simple CLI. To build the image and run the container, type `make` from the project root. The container itself runs `guard` as its main process. Running the container via `make` will drop you into the guard prompt, which will run the test suite whenever any of the source code or tests are changed. The tests can be kicked-off manually via the `all` command at the guard prompt. Individual test can be run using the `focus: true` annotation on an example or describe block. If you need to access a bash shell in the container (for example, to run rubocop), use the command `make shell`.
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 && ((@crop[0]).negative? || (@crop[1]).negative?)
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 && ((@crop[0]).negative? || (@crop[1]).negative?)
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 && ((@crop[0]).negative? || (@crop[1]).negative?)
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, local_options, max_size_px = nil)
12
- @local_options = local_options
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, target_path: @local_options['path.icc'])
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, target_path: nil)
10
+ def self.perform(path)
11
11
  return unless suitable_for_jpegicc?(path)
12
12
 
13
- icc_file_path = target_path || default_icc_path(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
- return unless valid_jpeg?(icc_file_path)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Morandi
4
- VERSION = '0.100.0'
4
+ VERSION = '0.102.0'
5
5
  end
@@ -55,7 +55,7 @@ module Morandi
55
55
  end
56
56
 
57
57
  def process!
58
- source_file_path = Morandi::SrgbConversion.perform(@path) || @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
- VipsImageProcessor.new(source, options).write_to_jpeg(target_path)
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.100.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: 2025-01-17 00:00:00.000000000 Z
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: 3.1.2
175
- signing_key:
156
+ rubygems_version: 4.0.4
176
157
  specification_version: 4
177
158
  summary: Simple Image Edits
178
159
  test_files: []
Binary file
Binary file