@@ -53,8 +53,11 @@ def generate(site)
5353 # Counting the number of files generated
5454 file_count = 0
5555
56- # Iterate through every image in each of the image folders and create a webp image
57- # if one has not been created already for that image.
56+ # Collection of tasks to be processed
57+ # Each task is a hash with all necessary info to process the file
58+ tasks = [ ]
59+
60+ # Iterate through every image in each of the image folders and collect files to process
5861 for imgdir in @config [ 'img_dir' ]
5962 imgdir_source = File . join ( site . source , imgdir )
6063 imgdir_destination = File . join ( site . dest , imgdir )
@@ -83,28 +86,88 @@ def generate(site)
8386 FileUtils ::mkdir_p ( imgdir_destination + imgfile_relative_path )
8487 outfile_fullpath_webp = File . join ( imgdir_destination + imgfile_relative_path , outfile_filename )
8588
86- # Check if the file already has a webp alternative?
87- # If we're force rebuilding all webp files then ignore the check
88- # also check the modified time on the files to ensure that the webp file
89- # is newer than the source file, if not then regenerate
90- if @config [ 'regenerate' ] || !File . file? ( outfile_fullpath_webp ) ||
91- File . mtime ( outfile_fullpath_webp ) <= File . mtime ( imgfile )
92- Jekyll . logger . info "WebP:" , "Change to source image file #{ imgfile } detected, regenerating WebP"
93-
94- # Generate the file
95- WebpExec . run ( @config [ 'quality' ] , @config [ 'flags' ] , imgfile , outfile_fullpath_webp , @config [ 'webp_path' ] )
96- file_count += 1
97- end
98- if File . file? ( outfile_fullpath_webp )
99- # Keep the webp file from being cleaned by Jekyll
100- site . static_files << WebpFile . new ( site ,
101- site . dest ,
102- File . join ( imgdir , imgfile_relative_path ) ,
103- outfile_filename )
104- end
89+ # Add to tasks list
90+ tasks << {
91+ 'imgfile' => imgfile ,
92+ 'outfile_fullpath_webp' => outfile_fullpath_webp ,
93+ 'imgdir' => imgdir ,
94+ 'imgfile_relative_path' => imgfile_relative_path ,
95+ 'outfile_filename' => outfile_filename
96+ }
10597 end # dir.foreach
10698 end # img_dir
10799
100+
101+ # Define the work block
102+ mutex = Mutex . new
103+
104+ process_file = Proc . new do |task |
105+ imgfile = task [ 'imgfile' ]
106+ outfile_fullpath_webp = task [ 'outfile_fullpath_webp' ]
107+ imgdir = task [ 'imgdir' ]
108+ imgfile_relative_path = task [ 'imgfile_relative_path' ]
109+ outfile_filename = task [ 'outfile_filename' ]
110+
111+ # Check if the file already has a webp alternative?
112+ # If we're force rebuilding all webp files then ignore the check
113+ # also check the modified time on the files to ensure that the webp file
114+ # is newer than the source file, if not then regenerate
115+ if @config [ 'regenerate' ] || !File . file? ( outfile_fullpath_webp ) ||
116+ File . mtime ( outfile_fullpath_webp ) <= File . mtime ( imgfile )
117+ Jekyll . logger . info "WebP:" , "Change to source image file #{ imgfile } detected, regenerating WebP"
118+
119+ # Generate the file
120+ WebpExec . run ( @config [ 'quality' ] , @config [ 'flags' ] , imgfile , outfile_fullpath_webp , @config [ 'webp_path' ] )
121+
122+ # Thread-safe increment
123+ if @config [ 'threads' ] && @config [ 'threads' ] > 1
124+ mutex . synchronize { file_count += 1 }
125+ else
126+ file_count += 1
127+ end
128+ end
129+
130+ if File . file? ( outfile_fullpath_webp )
131+ # Keep the webp file from being cleaned by Jekyll
132+ if @config [ 'threads' ] && @config [ 'threads' ] > 1
133+ mutex . synchronize do
134+ site . static_files << WebpFile . new ( site , site . dest , File . join ( imgdir , imgfile_relative_path ) , outfile_filename )
135+ end
136+ else
137+ site . static_files << WebpFile . new ( site , site . dest , File . join ( imgdir , imgfile_relative_path ) , outfile_filename )
138+ end
139+ end
140+ end
141+
142+ # Execute tasks
143+ thread_count = @config [ 'threads' ] . to_i
144+
145+ if thread_count > 1
146+ Jekyll . logger . info "WebP:" , "Parallel processing enabled with #{ thread_count } threads"
147+ queue = Queue . new
148+ tasks . each { |t | queue << t }
149+
150+ workers = ( 1 ..thread_count ) . map do
151+ Thread . new do
152+ begin
153+ while !queue . empty?
154+ # Non-blocking pop; rescue if empty
155+ task = queue . pop ( true ) rescue nil
156+ process_file . call ( task ) if task
157+ end
158+ rescue ThreadError
159+ # Queue empty
160+ end
161+ end
162+ end
163+ workers . each ( &:join )
164+ else
165+ # Sequential execution
166+ tasks . each do |task |
167+ process_file . call ( task )
168+ end
169+ end
170+
108171 Jekyll . logger . info "WebP:" , "Generator Complete: #{ file_count } file(s) generated"
109172
110173 end #function generate
0 commit comments