Skip to content

Commit

Permalink
Merge pull request #2674 from tvdeyen/webp-quality
Browse files Browse the repository at this point in the history
Allow quality setting for webp images
  • Loading branch information
tvdeyen authored Jan 8, 2024
2 parents b068ac6 + 1cec42a commit ca79aa5
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 15 deletions.
9 changes: 7 additions & 2 deletions app/models/alchemy/picture_variant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class PictureVariant

ANIMATED_IMAGE_FORMATS = %w[gif webp]
TRANSPARENT_IMAGE_FORMATS = %w[gif webp png]
ENCODABLE_IMAGE_FORMATS = %w[jpg jpeg webp]

attr_reader :picture, :render_format

Expand Down Expand Up @@ -95,8 +96,8 @@ def encoded_image(image, options = {})

convert_format = render_format.sub("jpeg", "jpg") != picture.image_file_format.sub("jpeg", "jpg")

if render_format =~ /jpe?g/ && (convert_format || options[:quality])
quality = options[:quality] || Config.get(:output_image_jpg_quality)
if encodable_image? && (convert_format || options[:quality])
quality = options[:quality] || Config.get(:output_image_quality)
encoding_options << "-quality #{quality}"
end

Expand All @@ -115,5 +116,9 @@ def encoded_image(image, options = {})

image
end

def encodable_image?
render_format.in?(ENCODABLE_IMAGE_FORMATS)
end
end
end
21 changes: 11 additions & 10 deletions config/alchemy/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ items_per_page: 15
#
# ==== Global Options:
#
# output_image_jpg_quality [Integer] # If image gets rendered as JPG this is the quality setting for it. (Default 85)
# output_image_quality [Integer] # If image gets rendered as JPG or WebP this is the quality setting for it. (Default 85)
# preprocess_image_resize [String] # Use this option to resize images to the given size when they are uploaded to the image library. Downsizing example: '1000x1000>' (Default nil)
# image_output_format [String] # The global image output format setting. (Default +original+)
#
# NOTE: You can always override the output format in the settings of your ingredients in elements.yml, I.E. {format: 'gif'}
#
output_image_jpg_quality: 85
output_image_quality: 85
preprocess_image_resize:
image_output_format: original

Expand Down Expand Up @@ -133,7 +133,8 @@ mailer:
mail_from: your.mail@your-domain.com
mail_to: your.mail@your-domain.com
subject: A new contact form message
fields: [salutation, firstname, lastname, address, zip, city, phone, email, message]
fields:
[salutation, firstname, lastname, address, zip, city, phone, email, message]
validate_fields: [lastname, email]

# === User roles
Expand Down Expand Up @@ -166,14 +167,14 @@ uploader:
file_size_limit: 100
allowed_filetypes:
alchemy/attachments:
- '*'
- "*"
alchemy/pictures:
- jpg
- jpeg
- gif
- png
- svg
- webp
- jpg
- jpeg
- gif
- png
- svg
- webp

# === Link Target Options
#
Expand Down
26 changes: 24 additions & 2 deletions lib/alchemy/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class << self
#
def get(name)
check_deprecation(name)
show[name.to_s]
key = check_replacement(name)
show[key.to_s]
end

alias_method :parameter, :get
Expand All @@ -27,13 +28,20 @@ def show
@config ||= merge_configs!(alchemy_config, main_app_config, env_specific_config)
end

# A list of deprecated configurations
# A list of deprecated configuration values
# a value of nil means there is no new default
# any not nil value is the new default
def deprecated_configs
{}
end

# A list of replaced configuration keys
def replaced_config_keys
{
output_image_quality: :output_image_jpg_quality
}
end

private

# Alchemy default configuration
Expand Down Expand Up @@ -87,6 +95,20 @@ def check_deprecation(name)
end
end
end

def check_replacement(name)
if replaced_config_keys.key?(name.to_sym)
old_key = replaced_config_keys[name.to_sym]
if show[old_key.to_s]
Alchemy::Deprecation.warn("Using #{old_key} configuration is deprecated and will be removed in Alchemy #{Alchemy::Deprecation.deprecation_horizon}. Please use #{name} instead.")
old_key
else
name
end
else
name
end
end
end
end
end
37 changes: 37 additions & 0 deletions spec/libraries/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,43 @@ module Alchemy
end
end
end

context "if config has been replaced" do
context "with a new default" do
before do
expect(described_class).to receive(:replaced_config_keys).at_least(:once) do
{foo: :bar}
end
end

context "and config uses old key" do
before do
expect(described_class).to receive(:show).at_least(:once) do
{"bar" => :baz}
end
end

it "warns about new key and returns old value" do
expect(Alchemy::Deprecation).to \
receive(:warn).with("Using bar configuration is deprecated and will be removed in Alchemy #{Alchemy::Deprecation.deprecation_horizon}. Please use foo instead.")
expect(Config.get(:foo)).to eq(:baz)
end
end

context "and config uses new key" do
before do
expect(described_class).to receive(:show).at_least(:once) do
{"foo" => :bar}
end
end

it "warns about new key and returns old value" do
expect(Alchemy::Deprecation).to_not receive(:warn)
expect(Config.get(:foo)).to eq(:bar)
end
end
end
end
end

describe ".main_app_config" do
Expand Down
86 changes: 85 additions & 1 deletion spec/models/alchemy/picture_variant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
it "does not flatten the image." do
step = subject.steps[0]
expect(step.name).to eq(:encode)
expect(step.arguments).to eq(["webp", ""])
expect(step.arguments).to eq(["webp", "-quality 85"])
end
end
end
Expand Down Expand Up @@ -317,6 +317,90 @@
end
end
end

context "and image has webp format" do
let(:image_file) do
File.new(File.expand_path("../../fixtures/image5.webp", __dir__))
end

let(:alchemy_picture) do
build_stubbed(:alchemy_picture, image_file: image_file, image_file_format: "webp")
end

let(:options) do
{format: format}
end

it "converts the picture into #{format}" do
step = subject.steps[0]
expect(step.name).to eq(:encode)
expect(step.arguments).to eq([format, "-quality 85"])
end

context "and quality is passed in options" do
let(:options) do
{format: format, quality: "30"}
end

it "sets the quality as well" do
step = subject.steps[0]
expect(step.name).to eq(:encode)
expect(step.arguments).to eq([format, "-quality 30"])
end
end
end
end
end

context "when webp format is requested" do
let(:options) do
{format: "webp"}
end

context "and the image file format is not WebP" do
it "converts image into webp and sets the default quality" do
step = subject.steps[0]
expect(step.name).to eq(:encode)
expect(step.arguments).to eq(["webp", "-quality 85"])
end

context "but quality is passed" do
let(:options) do
{format: "webp", quality: "30"}
end

it "converts with given quality" do
step = subject.steps[0]
expect(step.name).to eq(:encode)
expect(step.arguments).to eq(["webp", "-quality 30"])
end
end
end

context "and image already has webp format" do
let(:image_file) do
File.new(File.expand_path("../../fixtures/image5.webp", __dir__))
end

let(:alchemy_picture) do
build_stubbed(:alchemy_picture, image_file: image_file, image_file_format: "webp")
end

it "does not convert the picture format" do
expect(subject).to_not respond_to(:steps)
end

context "and quality is passed in options" do
let(:options) do
{format: "webp", quality: "30"}
end

it "converts to given quality" do
step = subject.steps[0]
expect(step.name).to eq(:encode)
expect(step.arguments).to eq(["webp", "-quality 30"])
end
end
end
end
end

0 comments on commit ca79aa5

Please sign in to comment.