-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #323 from joyofrails/feat/optimize-images
Optimize images
- Loading branch information
Showing
58 changed files
with
192 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+5.84 KB
app/assets/images/app-icons/noun-tears-of-joy-3555562-80ffea-7960F8.webp
Binary file not shown.
Binary file added
BIN
+86.7 KB
...ssets/images/articles/add-your-rails-app-to-the-home-screen/chrome-devtools-manifest.webp
Binary file not shown.
Binary file modified
BIN
-11.8 MB
(0.99%)
app/assets/images/articles/add-your-rails-app-to-the-home-screen/hot-air-balloon.webp
Binary file not shown.
Binary file added
BIN
+3.18 KB
...ets/images/articles/add-your-rails-app-to-the-home-screen/icon-192-maskable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.39 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/icon-192-maskable.webp
Binary file not shown.
Binary file added
BIN
+3.97 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+3.02 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/icon-192.webp
Binary file not shown.
Binary file added
BIN
+14.6 KB
...ets/images/articles/add-your-rails-app-to-the-home-screen/icon-512-maskable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+6.06 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/icon-512-maskable.webp
Binary file not shown.
Binary file added
BIN
+18 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+7.68 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/icon-512.webp
Binary file not shown.
Binary file added
BIN
+37.6 KB
...ages/articles/add-your-rails-app-to-the-home-screen/install-prompt-edge-opt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+19.2 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/install-prompt-safari.webp
Binary file not shown.
Binary file added
BIN
+37.3 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/launchpad-opt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+19.5 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/localhost-address-bar.webp
Binary file not shown.
Binary file added
BIN
+47.7 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/maskable-icons.webp
Binary file not shown.
Binary file added
BIN
+40.7 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/pwa-campfire.webp
Binary file not shown.
Binary file added
BIN
+53 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/pwa-discourse.webp
Binary file not shown.
Binary file added
BIN
+85.8 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/pwa-feedbin.webp
Binary file not shown.
Binary file added
BIN
+49.8 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/pwa-hatchbox.webp
Binary file not shown.
Binary file added
BIN
+92.8 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/ruby-app-icon-archived.webp
Binary file not shown.
Binary file modified
BIN
-108 KB
(48%)
app/assets/images/articles/add-your-rails-app-to-the-home-screen/ruby-app-icon.webp
Binary file not shown.
Binary file added
BIN
+88.1 KB
app/assets/images/articles/add-your-rails-app-to-the-home-screen/standalone.webp
Binary file not shown.
Binary file modified
BIN
-69.8 KB
(44%)
app/assets/images/articles/custom-color-schemes-with-ruby-on-rails/rainbows.webp
Binary file not shown.
Binary file modified
BIN
-42.5 KB
(54%)
app/assets/images/articles/custom-color-schemes-with-ruby-on-rails/screenshot.webp
Binary file not shown.
Binary file modified
BIN
+8.83 KB
(120%)
app/assets/images/articles/how-to-render-css-dynamically-in-rails/style-rainbow.webp
Binary file not shown.
Binary file added
BIN
+48.7 KB
app/assets/images/articles/introducing-joy-of-rails/screenshot-opt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
-112 KB
(31%)
app/assets/images/articles/mastering-custom-configuration-in-rails/ice-cream.webp
Binary file not shown.
Binary file modified
BIN
-71 KB
(45%)
app/assets/images/articles/web-push-notifications-from-rails/airplane.webp
Binary file not shown.
Binary file added
BIN
+7.73 KB
...sets/images/articles/web-push-notifications-from-rails/push-notifications-high-level.webp
Binary file not shown.
Binary file modified
BIN
-39.1 KB
(71%)
app/assets/images/articles/what-you-need-to-know-about-sqlite/feather.webp
Binary file not shown.
Binary file added
BIN
+18.1 KB
app/assets/images/articles/what-you-need-to-know-about-sqlite/mountain-range.webp
Binary file not shown.
Binary file added
BIN
+20.1 KB
app/assets/images/articles/what-you-need-to-know-about-sqlite/scaling.webp
Binary file not shown.
Binary file added
BIN
+63.4 KB
app/assets/images/meta/deployment/hatchbox/conversation-bundler-config.webp
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+56.2 KB
app/assets/images/meta/deployment/hatchbox/conversation-systemd-2.webp
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
module Content | ||
class Image < ApplicationComponent | ||
attr_reader :src, :alt, :title, :attributes | ||
|
||
def initialize(src, alt: "", title: "", **attributes) | ||
@src = src | ||
@alt = alt.presence || File.basename(src, ".*").humanize | ||
@title = title | ||
@attributes = attributes | ||
end | ||
|
||
def view_template | ||
figure do | ||
img(alt:, loading: "lazy", **image_attributes, **attributes) | ||
figcaption { title } if title.present? | ||
end | ||
end | ||
|
||
private | ||
|
||
def asset_path(*) = helpers.asset_path(*) | ||
|
||
def image_attributes | ||
if webp_src? | ||
{ | ||
src: asset_path(webp_src) | ||
} | ||
elsif optimized_src? | ||
{ | ||
src: asset_path(optimized_src) | ||
} | ||
else | ||
{ | ||
src: asset_path(src) | ||
} | ||
end | ||
end | ||
|
||
def webp_src? = File.exist? Rails.root.join("app", "assets", "images", webp_src) | ||
|
||
def webp_src = "#{dirname}/#{basename}.webp" | ||
|
||
def optimized_src? = File.exist? Rails.root.join("app", "assets", "images", optimized_src) | ||
|
||
def optimized_src = "#{dirname}/#{basename}-opt.#{ext}" | ||
|
||
def ext = File.extname(src) | ||
|
||
def basename = File.basename(src, ".*") | ||
|
||
def dirname = File.dirname(src) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,127 @@ | ||
#!/usr/bin/env ruby | ||
|
||
# ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) | ||
|
||
# bundle_binstub = File.expand_path("bundle", __dir__) | ||
|
||
# if File.file?(bundle_binstub) | ||
# if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") | ||
# load(bundle_binstub) | ||
# else | ||
# abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. | ||
# Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") | ||
# end | ||
# end | ||
|
||
# require "rubygems" | ||
# require "bundler/setup" | ||
|
||
require "fastimage" | ||
|
||
force = false | ||
|
||
class ImageFile | ||
def exists? | ||
File.exist?(file) | ||
end | ||
|
||
attr_reader :file | ||
def initialize(file) | ||
@file = file | ||
end | ||
|
||
def to_s = file | ||
|
||
def to_str = file | ||
|
||
def as(*suffixes) | ||
ext = suffixes.pop | ||
ImageFile.new("#{dirname}/#{([basename] + suffixes).join("-")}.#{ext}") | ||
end | ||
|
||
def as_webp = as("webp") | ||
|
||
def as_opt_jpg = as("opt", "jpg") | ||
|
||
def ext = File.extname(file) | ||
|
||
def basename = File.basename(file, ".*") | ||
|
||
def dirname = File.dirname(file) | ||
end | ||
|
||
module Cmd | ||
def self.run(cmd) | ||
puts cmd | ||
system cmd | ||
end | ||
|
||
def self.webp(img, force: false, quality: 90, tries: 0) | ||
dest = img.as_webp.to_s | ||
|
||
if force || !File.exist?(dest) | ||
cmd = "magick #{img}" | ||
|
||
opts = ["-define webp:method=6", "-quality #{quality}"] | ||
|
||
# Resize if width is specified and image is larger | ||
opts << "-resize 1200x" if FastImage.size(img.to_s)[0] > 1200 | ||
|
||
# Lossless compression for images < 96kB | ||
if File.size?(img) && File.size(img) < 98_304 # 96kB | ||
opts << "-define webp:lossless=true" | ||
end | ||
|
||
opts << dest | ||
|
||
run "#{cmd} #{opts.join(" ")}" | ||
|
||
if File.size(dest) > 131_072 && # 128kB | ||
tries < 8 | ||
webp(img, force: true, quality: quality - 5, tries: tries + 1) | ||
end | ||
end | ||
end | ||
|
||
def self.jpg(img, force: false, quality: 90, tries: 0) | ||
dest = img.as_opt_jpg.to_s | ||
if force || !File.exist?(dest) | ||
run "magick #{img} -strip -interlace Plane -quality #{quality}% #{dest}" | ||
|
||
if File.size(dest) > 131_072 && # 128kB | ||
tries < 8 | ||
jpg(img, force: true, quality: quality - 5, tries: tries + 1) | ||
end | ||
end | ||
end | ||
end | ||
|
||
ARGV.each do |file| | ||
basename = File.basename(file, ".*") | ||
dir = File.dirname(file) | ||
Dir.glob(file).each do |file| | ||
img = ImageFile.new(file) | ||
next unless %w[.jpg .jpeg .png].include?(img.ext) | ||
next if img.to_s.include?("-opt.jpg") | ||
Cmd.webp img, force: force | ||
end | ||
|
||
Dir.glob(file).each do |file| | ||
img = ImageFile.new(file) | ||
next unless %w[.jpg .jpeg].include?(img.ext) | ||
next if img.to_s.include?("-opt.jpg") | ||
next if File.size(img) < 32_768 # 32kB | ||
Cmd.jpg img, force: force | ||
end | ||
|
||
webp = "#{dir}/#{basename}.webp" | ||
Dir.glob(file).each do |file| | ||
img = ImageFile.new(file) | ||
|
||
cmd = "magick #{file} -quality 50 -define webp:lossless=true -resize 960x480 #{webp}" | ||
files = [img.as_webp.to_s, img.as_opt_jpg.to_s].filter { |f| File.exist?(f) } | ||
|
||
puts cmd | ||
system cmd | ||
smallest = files.min { |a, b| File.size(a) <=> File.size(b) } | ||
files.each do |f| | ||
if f != smallest || File.size(f) > File.size(img.to_s) | ||
File.delete(f) | ||
end | ||
end | ||
end | ||
end |