himg 0.0.8 → 0.0.10
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 +12 -0
- data/Cargo.lock +54 -13
- data/Cargo.toml +4 -0
- data/README.md +2 -0
- data/ext/himg/Cargo.toml +7 -6
- data/ext/himg/examples/file.rs +1 -0
- data/ext/himg/src/html_to_image.rs +24 -9
- data/ext/himg/src/lib.rs +24 -3
- data/ext/himg/src/options.rs +2 -0
- data/lib/himg/cli.rb +1 -0
- data/lib/himg/version.rb +1 -1
- data/lib/himg.rb +5 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d65ada02141e4fdd397d4c58def4e7fd658202563a2bbc31b548801b08198d4b
|
4
|
+
data.tar.gz: b7c9cc37243b8f790dfb977a6d6e5c215104e4a6a0f03cbc63308191d7ba7e73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d21cb8a714e462c08b36a000275eb9b4c840ab2bb049f8c7bcacb5b978a4404f36d0431b867b019fee864130b1895ef026b81257d6ce0199dec0adef8ecf5578
|
7
|
+
data.tar.gz: a96a262c6dc6e4a42bb8b6bcdacb47f24203d3e5d74673880b6851f76a01421e373c2a3e074f2cbb697e58c69b1e9eb1a3284824853821601c3e694c5bd127a3
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
3
|
|
4
|
+
## [0.0.10] - 2025-08-01
|
5
|
+
|
6
|
+
- Fixed himg require from native extension
|
7
|
+
- Catch rust panics and wrap with ruby Error
|
8
|
+
- GpuNotFound error extending Himg::Error
|
9
|
+
|
10
|
+
## [0.0.9] - 2025-07-31
|
11
|
+
|
12
|
+
- Returned to CPU-only rendering by default
|
13
|
+
- Added `gpu` option to enable GPU rendering
|
14
|
+
- Updated to latest blitz to fix blue/green colour swap on images
|
15
|
+
|
4
16
|
## [0.0.8] - 2025-07-31
|
5
17
|
|
6
18
|
- Return to GPU rendering by default: quality is low with CPU rendering.
|
data/Cargo.lock
CHANGED
@@ -89,6 +89,18 @@ dependencies = [
|
|
89
89
|
"wgpu",
|
90
90
|
]
|
91
91
|
|
92
|
+
[[package]]
|
93
|
+
name = "anyrender_vello_cpu"
|
94
|
+
version = "0.5.1"
|
95
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
96
|
+
checksum = "e83dfa407bbe89c99cf990a933aeab4e1d499c38a465c3f316066a1dd3eb5614"
|
97
|
+
dependencies = [
|
98
|
+
"anyrender",
|
99
|
+
"kurbo",
|
100
|
+
"peniko",
|
101
|
+
"vello_cpu",
|
102
|
+
]
|
103
|
+
|
92
104
|
[[package]]
|
93
105
|
name = "app_units"
|
94
106
|
version = "0.7.8"
|
@@ -211,9 +223,9 @@ dependencies = [
|
|
211
223
|
|
212
224
|
[[package]]
|
213
225
|
name = "blitz-dom"
|
214
|
-
version = "0.1.0-rc.
|
226
|
+
version = "0.1.0-rc.2"
|
215
227
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
216
|
-
checksum = "
|
228
|
+
checksum = "145a503f45b2284a75ca1e715dbbef4d1ccf1eeace85330e29a2ae12a01d1263"
|
217
229
|
dependencies = [
|
218
230
|
"accesskit",
|
219
231
|
"app_units",
|
@@ -223,6 +235,7 @@ dependencies = [
|
|
223
235
|
"color",
|
224
236
|
"cursor-icon",
|
225
237
|
"euclid",
|
238
|
+
"fastrand",
|
226
239
|
"html-escape",
|
227
240
|
"image",
|
228
241
|
"keyboard-types",
|
@@ -248,9 +261,9 @@ dependencies = [
|
|
248
261
|
|
249
262
|
[[package]]
|
250
263
|
name = "blitz-html"
|
251
|
-
version = "0.1.0-rc.
|
264
|
+
version = "0.1.0-rc.2"
|
252
265
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
253
|
-
checksum = "
|
266
|
+
checksum = "52d34dae2ab4e90c0ccfa6470be7e455f897ae702c85d248fccdc807e375426d"
|
254
267
|
dependencies = [
|
255
268
|
"blitz-dom",
|
256
269
|
"blitz-traits",
|
@@ -260,9 +273,9 @@ dependencies = [
|
|
260
273
|
|
261
274
|
[[package]]
|
262
275
|
name = "blitz-net"
|
263
|
-
version = "0.1.0-rc.
|
276
|
+
version = "0.1.0-rc.2"
|
264
277
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
265
|
-
checksum = "
|
278
|
+
checksum = "e2a5ebc8993e3985097716262d4d496c18d3324727109e3c865071776dfe38b1"
|
266
279
|
dependencies = [
|
267
280
|
"blitz-traits",
|
268
281
|
"data-url",
|
@@ -272,9 +285,9 @@ dependencies = [
|
|
272
285
|
|
273
286
|
[[package]]
|
274
287
|
name = "blitz-paint"
|
275
|
-
version = "0.1.0-rc.
|
288
|
+
version = "0.1.0-rc.2"
|
276
289
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
277
|
-
checksum = "
|
290
|
+
checksum = "9d62c7953382622298402412535db1796aaa83c71600bfc77fa7627a39aa722d"
|
278
291
|
dependencies = [
|
279
292
|
"anyrender",
|
280
293
|
"anyrender_svg",
|
@@ -293,15 +306,16 @@ dependencies = [
|
|
293
306
|
|
294
307
|
[[package]]
|
295
308
|
name = "blitz-traits"
|
296
|
-
version = "0.1.0-rc.
|
309
|
+
version = "0.1.0-rc.2"
|
297
310
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
298
|
-
checksum = "
|
311
|
+
checksum = "4cb0235930120526087ce9d69fa2d6828e3fb078c61dde43231acec7968376bf"
|
299
312
|
dependencies = [
|
300
313
|
"bitflags 2.9.1",
|
301
314
|
"bytes",
|
302
315
|
"cursor-icon",
|
303
316
|
"http",
|
304
317
|
"keyboard-types",
|
318
|
+
"serde",
|
305
319
|
"smol_str",
|
306
320
|
"url",
|
307
321
|
]
|
@@ -412,6 +426,9 @@ name = "color"
|
|
412
426
|
version = "0.3.1"
|
413
427
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
414
428
|
checksum = "7ae467d04a8a8aea5d9a49018a6ade2e4221d92968e8ce55a48c0b1164e5f698"
|
429
|
+
dependencies = [
|
430
|
+
"bytemuck",
|
431
|
+
]
|
415
432
|
|
416
433
|
[[package]]
|
417
434
|
name = "color_quant"
|
@@ -1077,10 +1094,11 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
|
1077
1094
|
|
1078
1095
|
[[package]]
|
1079
1096
|
name = "himg"
|
1080
|
-
version = "0.0.
|
1097
|
+
version = "0.0.10"
|
1081
1098
|
dependencies = [
|
1082
1099
|
"anyrender",
|
1083
1100
|
"anyrender_vello",
|
1101
|
+
"anyrender_vello_cpu",
|
1084
1102
|
"blitz-dom",
|
1085
1103
|
"blitz-html",
|
1086
1104
|
"blitz-net",
|
@@ -2065,6 +2083,7 @@ version = "0.4.0"
|
|
2065
2083
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
2066
2084
|
checksum = "1f9529efd019889b2a205193c14ffb6e2839b54ed9d2720674f10f4b04d87ac9"
|
2067
2085
|
dependencies = [
|
2086
|
+
"bytemuck",
|
2068
2087
|
"color",
|
2069
2088
|
"kurbo",
|
2070
2089
|
"smallvec",
|
@@ -2951,9 +2970,9 @@ checksum = "500f379645e8a87fd03fe88607a5edcb0d8e4e423baa74ba52db198a06a0c261"
|
|
2951
2970
|
|
2952
2971
|
[[package]]
|
2953
2972
|
name = "stylo_taffy"
|
2954
|
-
version = "0.1.0-rc.
|
2973
|
+
version = "0.1.0-rc.2"
|
2955
2974
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
2956
|
-
checksum = "
|
2975
|
+
checksum = "dce8876a33e0f3b16916b2b4da1cdbb64b9985d5ae61033d23024d95e45569ac"
|
2957
2976
|
dependencies = [
|
2958
2977
|
"stylo",
|
2959
2978
|
"taffy",
|
@@ -3539,6 +3558,28 @@ dependencies = [
|
|
3539
3558
|
"wgpu",
|
3540
3559
|
]
|
3541
3560
|
|
3561
|
+
[[package]]
|
3562
|
+
name = "vello_common"
|
3563
|
+
version = "0.0.1"
|
3564
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
3565
|
+
checksum = "6b5e49f2836e87b6bd3d8f70324696f22b5f7dfdc836caeab463fff05957c1b1"
|
3566
|
+
dependencies = [
|
3567
|
+
"bytemuck",
|
3568
|
+
"peniko",
|
3569
|
+
"png",
|
3570
|
+
"skrifa",
|
3571
|
+
"smallvec",
|
3572
|
+
]
|
3573
|
+
|
3574
|
+
[[package]]
|
3575
|
+
name = "vello_cpu"
|
3576
|
+
version = "0.0.1"
|
3577
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
3578
|
+
checksum = "a45e0a6b777abb4354e15146ecf95bac03aada7a85024fd47762f56095b32896"
|
3579
|
+
dependencies = [
|
3580
|
+
"vello_common",
|
3581
|
+
]
|
3582
|
+
|
3542
3583
|
[[package]]
|
3543
3584
|
name = "vello_encoding"
|
3544
3585
|
version = "0.5.0"
|
data/Cargo.toml
CHANGED
data/README.md
CHANGED
@@ -67,6 +67,7 @@ bundle add himg
|
|
67
67
|
|base_url | Where relative paths are relative to for linked resources (stylesheets, images, fonts, etc) | string | nil |
|
68
68
|
|disable_fetch | Disables fetching linked resources from disk and network| bool | false |
|
69
69
|
|fetch_timeout | Timeout in seconds for fetching resources | float | 10.0 |
|
70
|
+
|gpu | Use GPU renderer instead of CPU renderer | bool | false |
|
70
71
|
|
71
72
|
|
72
73
|
### Passing options to a Rails view template
|
@@ -217,6 +218,7 @@ To play nicely with Rails a template handler is registered, which Rails' `defaul
|
|
217
218
|
- http://localhost:3000/users/jamedjo.himg will also render the same png
|
218
219
|
- http://localhost:3000/users/jamedjo will render an HTML page with opengraph meta tags
|
219
220
|
6. To install this gem onto your local machine, run `bundle exec rake install`.
|
221
|
+
7. To simulate a headless server environment without a GPU, use `WGPU_BACKEND=empty bundle exec rspec`
|
220
222
|
|
221
223
|
### Run cargo example directly generate image in Rust
|
222
224
|
|
data/ext/himg/Cargo.toml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[package]
|
2
2
|
name = "himg"
|
3
3
|
description = "ruby bindings to expose a blitz html->png pipeline"
|
4
|
-
version = "0.0.
|
4
|
+
version = "0.0.10"
|
5
5
|
edition = "2024"
|
6
6
|
authors = ["James Edwards-Jones <git@jamedjo.co.uk>"]
|
7
7
|
license = "MIT"
|
@@ -14,13 +14,14 @@ crate-type = ["cdylib", "rlib"]
|
|
14
14
|
[dependencies]
|
15
15
|
magnus = { version = "0.7.1" }
|
16
16
|
rb-sys = { version = "0.9", features = ["stable-api-compiled-fallback"] }
|
17
|
-
blitz-traits = { version = "0.1.0-rc.
|
18
|
-
blitz-dom = { version = "0.1.0-rc.
|
19
|
-
blitz-net = { version = "0.1.0-rc.
|
20
|
-
blitz-paint = { version = "0.1.0-rc.
|
17
|
+
blitz-traits = { version = "0.1.0-rc.2" }
|
18
|
+
blitz-dom = { version = "0.1.0-rc.2" }
|
19
|
+
blitz-net = { version = "0.1.0-rc.2" }
|
20
|
+
blitz-paint = { version = "0.1.0-rc.2" }
|
21
21
|
anyrender = { version = "0.5.0" }
|
22
22
|
anyrender_vello = { version = "0.5.0" }
|
23
|
-
|
23
|
+
anyrender_vello_cpu = { version = "0.5.1" }
|
24
|
+
blitz-html = { version = "0.1.0-rc.2" }
|
24
25
|
tokio = { version = "1.46", features = ["rt-multi-thread", "macros"] }
|
25
26
|
png = "0.17"
|
26
27
|
openssl = { version = "0.10", features = ["vendored"] }
|
data/ext/himg/examples/file.rs
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
use blitz_html::HtmlDocument;
|
2
2
|
use blitz_dom::DocumentConfig;
|
3
3
|
use anyrender_vello::VelloImageRenderer;
|
4
|
+
use anyrender_vello_cpu::VelloCpuImageRenderer;
|
4
5
|
use anyrender::render_to_buffer;
|
5
6
|
use blitz_paint::paint_scene;
|
6
7
|
use blitz_traits::shell::{Viewport};
|
@@ -79,17 +80,31 @@ pub async fn html_to_image(
|
|
79
80
|
}
|
80
81
|
|
81
82
|
// Render document to RGBA buffer
|
82
|
-
let buffer =
|
83
|
-
|
84
|
-
scene
|
85
|
-
|
86
|
-
|
83
|
+
let buffer = if options.gpu {
|
84
|
+
render_to_buffer::<VelloImageRenderer, _>(
|
85
|
+
|scene| paint_scene(
|
86
|
+
scene,
|
87
|
+
document.as_ref(),
|
88
|
+
render_size.hidpi_scale,
|
89
|
+
render_size.scaled_width(),
|
90
|
+
render_size.scaled_height(),
|
91
|
+
),
|
87
92
|
render_size.scaled_width(),
|
88
93
|
render_size.scaled_height(),
|
89
|
-
)
|
90
|
-
|
91
|
-
|
92
|
-
|
94
|
+
)
|
95
|
+
} else {
|
96
|
+
render_to_buffer::<VelloCpuImageRenderer, _>(
|
97
|
+
|scene| paint_scene(
|
98
|
+
scene,
|
99
|
+
document.as_ref(),
|
100
|
+
render_size.hidpi_scale,
|
101
|
+
render_size.scaled_width(),
|
102
|
+
render_size.scaled_height(),
|
103
|
+
),
|
104
|
+
render_size.scaled_width(),
|
105
|
+
render_size.scaled_height(),
|
106
|
+
)
|
107
|
+
};
|
93
108
|
|
94
109
|
logger.log("Rendered to buffer");
|
95
110
|
|
data/ext/himg/src/lib.rs
CHANGED
@@ -34,6 +34,7 @@ impl Options {
|
|
34
34
|
base_url: hash.lookup("base_url")?,
|
35
35
|
disable_fetch: hash.lookup2("disable_fetch", defaults.disable_fetch)?,
|
36
36
|
fetch_timeout: hash.lookup2("fetch_timeout", defaults.fetch_timeout)?,
|
37
|
+
gpu: hash.lookup2("gpu", defaults.gpu)?,
|
37
38
|
color_scheme: defaults.color_scheme,
|
38
39
|
};
|
39
40
|
|
@@ -44,10 +45,30 @@ impl Options {
|
|
44
45
|
pub fn render_blocking_rb(ruby: &Ruby, html: String, options: Option<RHash>) -> Result<RString, Error> {
|
45
46
|
let options = Options::from_ruby(options)?;
|
46
47
|
let exception_class = ExceptionClass::from_value(magnus::eval("Himg::Error").unwrap()).unwrap();
|
48
|
+
let gpu_not_found_class = ExceptionClass::from_value(magnus::eval("Himg::GpuNotFound").unwrap()).unwrap();
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
51
|
+
render_blocking(html, options)
|
52
|
+
}));
|
53
|
+
|
54
|
+
match result {
|
55
|
+
Ok(Ok(data)) => Ok(ruby.str_from_slice(&data)),
|
56
|
+
Ok(Err(e)) => Err(Error::new(exception_class, format!("{}", e))),
|
57
|
+
Err(panic) => {
|
58
|
+
let msg = if let Some(s) = panic.downcast_ref::<String>() {
|
59
|
+
s.clone()
|
60
|
+
} else if let Some(s) = panic.downcast_ref::<&str>() {
|
61
|
+
s.to_string()
|
62
|
+
} else {
|
63
|
+
"Unknown panic".to_string()
|
64
|
+
};
|
65
|
+
|
66
|
+
if msg.contains("No compatible device found") {
|
67
|
+
Err(Error::new(gpu_not_found_class, msg))
|
68
|
+
} else {
|
69
|
+
Err(Error::new(exception_class, format!("Panic: {}", msg)))
|
70
|
+
}
|
71
|
+
}
|
51
72
|
}
|
52
73
|
}
|
53
74
|
|
data/ext/himg/src/options.rs
CHANGED
@@ -8,6 +8,7 @@ pub struct Options {
|
|
8
8
|
pub color_scheme: ColorScheme,
|
9
9
|
pub disable_fetch: bool,
|
10
10
|
pub fetch_timeout: f64,
|
11
|
+
pub gpu: bool,
|
11
12
|
pub base_url: Option<String>,
|
12
13
|
pub truncate: bool,
|
13
14
|
pub verbose: bool,
|
@@ -26,6 +27,7 @@ impl Options {
|
|
26
27
|
base_url: None,
|
27
28
|
disable_fetch: false,
|
28
29
|
fetch_timeout: 10.0,
|
30
|
+
gpu: false,
|
29
31
|
color_scheme: ColorScheme::Light,
|
30
32
|
}
|
31
33
|
}
|
data/lib/himg/cli.rb
CHANGED
@@ -12,6 +12,7 @@ module Himg
|
|
12
12
|
option :verbose, type: :boolean, desc: "Enables detailed logging for debugging and profiling.", default: false
|
13
13
|
option :disable_fetch, type: :boolean, desc: "Skip fetching file/http resources (stylesheets, images, fonts, etc)", default: false
|
14
14
|
option :fetch_timeout, type: :numeric, desc: "Timeout in seconds for fetching resources", default: 10
|
15
|
+
option :gpu, type: :boolean, desc: "Use GPU renderer instead of CPU renderer", default: false
|
15
16
|
option :http_headers, desc: "HTTP Headers to use when fetching remote resource"
|
16
17
|
option :base_url, desc: "Base URL used to resolve relative URLs"
|
17
18
|
|
data/lib/himg/version.rb
CHANGED
data/lib/himg.rb
CHANGED
@@ -8,7 +8,7 @@ require "himg/railtie" if defined?(Rails::Railtie)
|
|
8
8
|
# Fall back to loading the non-versioned extension if version-specific loading fails.
|
9
9
|
begin
|
10
10
|
RUBY_VERSION =~ /(\d+\.\d+)/
|
11
|
-
require "
|
11
|
+
require "himg/#{Regexp.last_match(1)}/himg"
|
12
12
|
rescue LoadError
|
13
13
|
require "himg/himg"
|
14
14
|
end
|
@@ -17,10 +17,11 @@ end
|
|
17
17
|
#
|
18
18
|
# Converts HTML to an Image for a minimal subset of HTML and CSS
|
19
19
|
module Himg
|
20
|
-
RENDER_OPTIONS = %i[width height truncate verbose].freeze
|
20
|
+
RENDER_OPTIONS = %i[width height truncate verbose base_url disable_fetch fetch_timeout gpu].freeze
|
21
21
|
class Error < StandardError; end
|
22
|
+
class GpuNotFound < Error; end
|
22
23
|
|
23
|
-
def self.render(html, width: 720, height: 405, truncate: true, verbose: false, base_url: nil, disable_fetch: false, fetch_timeout: 10)
|
24
|
-
render_to_string(html, "width" => width.to_i, "height" => height.to_i, "truncate" => truncate, "verbose" => verbose, "base_url" => BaseUrl.new(base_url).to_s, "disable_fetch" => disable_fetch, "fetch_timeout" => fetch_timeout.to_f)
|
24
|
+
def self.render(html, width: 720, height: 405, truncate: true, verbose: false, base_url: nil, disable_fetch: false, fetch_timeout: 10, gpu: false)
|
25
|
+
render_to_string(html, "width" => width.to_i, "height" => height.to_i, "truncate" => truncate, "verbose" => verbose, "base_url" => BaseUrl.new(base_url).to_s, "disable_fetch" => disable_fetch, "fetch_timeout" => fetch_timeout.to_f, "gpu" => gpu)
|
25
26
|
end
|
26
27
|
end
|