Generate srcset images for a variety of resolutions from OCaml
1(* Copyright (c) 2024, Anil Madhavapeddy <anil@recoil.org>
2
3 Permission to use, copy, modify, and/or distribute this software for
4 any purpose with or without fee is hereby granted, provided that the
5 above copyright notice and this permission notice appear in all
6 copies.
7
8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
9 WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
11 AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
13 OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 PERFORMANCE OF THIS SOFTWARE. *)
16
17(** Command-line image processing operations for srcsetter.
18
19 This module provides the core image processing pipeline including
20 file discovery, image conversion, and progress reporting.
21
22 {1 High-Level Pipeline}
23
24 The simplest way to use this module is via {!run}, which executes
25 the complete pipeline:
26
27 {[
28 Srcsetter_cmd.run
29 ~proc_mgr:(Eio.Stdenv.process_mgr env)
30 ~src_dir:Eio.Path.(fs / "images/originals")
31 ~dst_dir:Eio.Path.(fs / "images/output")
32 ()
33 ]}
34
35 {1 Configuration} *)
36
37(** Configuration for the image processing pipeline. *)
38type ('a, 'b) config = {
39 dummy : bool; (** When true, skip actual image conversion (dry run) *)
40 preserve : bool; (** When true, skip conversion if destination exists *)
41 proc_mgr : 'a Eio.Process.mgr; (** Eio process manager for running ImageMagick *)
42 src_dir : 'b Eio.Path.t; (** Source directory containing original images *)
43 dst_dir : 'b Eio.Path.t; (** Destination directory for generated images *)
44 img_widths : int list; (** List of target widths for responsive variants *)
45 img_exts : string list; (** File extensions to process (e.g., ["jpg"; "png"]) *)
46 idx_file : string; (** Name of the JSON index file to generate *)
47 max_fibers : int; (** Maximum concurrent conversion operations *)
48}
49
50(** {1 File Operations} *)
51
52val file_seq :
53 filter:(string -> bool) ->
54 ([> Eio.Fs.dir_ty ] as 'a) Eio.Path.t ->
55 'a Eio.Path.t Seq.t
56(** [file_seq ~filter path] recursively enumerates files in [path].
57
58 Returns a sequence of file paths where [filter filename] is true.
59 Directories are traversed depth-first. *)
60
61val iter_seq_p : ?max_fibers:int -> ('a -> unit) -> 'a Seq.t -> unit
62(** [iter_seq_p ?max_fibers fn seq] iterates [fn] over [seq] in parallel.
63
64 @param max_fibers Optional limit on concurrent fibers. Must be positive.
65 @raise Invalid_argument if [max_fibers] is not positive. *)
66
67(** {1 Image Operations} *)
68
69val dims : ('a, 'b) config -> 'b Eio.Path.t -> int * int
70(** [dims cfg path] returns the [(width, height)] dimensions of an image.
71
72 Uses ImageMagick's [identify] command to read image metadata. *)
73
74val convert : ('a, 'b) config -> string * string * int -> unit
75(** [convert cfg (src, dst, size)] converts an image to WebP format.
76
77 Creates the destination directory if needed, then uses ImageMagick
78 to resize and convert the image with auto-orientation.
79
80 @param src Source filename relative to [cfg.src_dir]
81 @param dst Destination filename relative to [cfg.dst_dir]
82 @param size Target width in pixels *)
83
84val convert_pdf :
85 ('a, 'b) config ->
86 size:string ->
87 dst:'b Eio.Path.t ->
88 src:'b Eio.Path.t ->
89 unit
90(** [convert_pdf cfg ~size ~dst ~src] converts a PDF's first page to an image.
91
92 Renders at 300 DPI, crops the top half, and resizes to the target width. *)
93
94(** {1 Pipeline Execution} *)
95
96val run :
97 proc_mgr:'a Eio.Process.mgr ->
98 src_dir:'b Eio.Path.t ->
99 dst_dir:'b Eio.Path.t ->
100 ?idx_file:string ->
101 ?img_widths:int list ->
102 ?img_exts:string list ->
103 ?max_fibers:int ->
104 ?dummy:bool ->
105 ?preserve:bool ->
106 unit ->
107 Srcsetter.t list
108(** [run ~proc_mgr ~src_dir ~dst_dir ()] runs the full srcsetter pipeline.
109
110 Scans [src_dir] for images, converts them to WebP format at multiple
111 responsive sizes, and writes an index file to [dst_dir].
112
113 @param proc_mgr Eio process manager for running ImageMagick
114 @param src_dir Source directory containing original images
115 @param dst_dir Destination directory for generated images
116 @param idx_file Name of the index file (default ["index.json"])
117 @param img_widths List of target widths (default common responsive breakpoints)
118 @param img_exts List of extensions to process (default common image formats)
119 @param max_fibers Maximum concurrent operations (default 8)
120 @param dummy When true, skip actual conversions (default false)
121 @param preserve When true, skip existing files (default true)
122 @return List of {!Srcsetter.t} entries describing generated images *)