images_golden_integration_test.go - hugo - [fork] hugo port for 9front
HTML git clone https://git.drkhsh.at/hugo.git
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
images_golden_integration_test.go (14647B)
---
1 // Copyright 2024 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package images_test
15
16 import (
17 _ "image/jpeg"
18 "strings"
19 "testing"
20
21 "github.com/gohugoio/hugo/resources/images/imagetesting"
22 )
23
24 // Note, if you're enabling writeGoldenFiles on a MacOS ARM 64 you need to run the test with GOARCH=amd64, e.g.
25 func TestImagesGoldenFiltersMisc(t *testing.T) {
26 t.Parallel()
27
28 if imagetesting.SkipGoldenTests {
29 t.Skip("Skip golden test on this architecture")
30 }
31
32 // Will be used as the base folder for generated images.
33 name := "filters/misc"
34
35 files := `
36 -- hugo.toml --
37 -- assets/rotate270.jpg --
38 sourcefilename: ../testdata/exif/orientation6.jpg
39 -- assets/sunset.jpg --
40 sourcefilename: ../testdata/sunset.jpg
41 -- assets/gopher.png --
42 sourcefilename: ../testdata/gopher-hero8.png
43 -- layouts/index.html --
44 Home.
45 {{ $sunset := (resources.Get "sunset.jpg").Resize "x300" }}
46 {{ $sunsetGrayscale := $sunset.Filter (images.Grayscale) }}
47 {{ $gopher := (resources.Get "gopher.png").Resize "x80" }}
48 {{ $overlayFilter := images.Overlay $gopher 20 20 }}
49
50 {{ $textOpts := dict
51 "color" "#fbfaf5"
52 "linespacing" 8
53 "size" 40
54 "x" 25
55 "y" 190
56 }}
57
58 {{/* These are sorted. */}}
59 {{ template "filters" (dict "name" "brightness-40.jpg" "img" $sunset "filters" (images.Brightness 40)) }}
60 {{ template "filters" (dict "name" "contrast-50.jpg" "img" $sunset "filters" (images.Contrast 50)) }}
61 {{ template "filters" (dict "name" "dither-default.jpg" "img" $sunset "filters" (images.Dither)) }}
62 {{ template "filters" (dict "name" "gamma-1.667.jpg" "img" $sunset "filters" (images.Gamma 1.667)) }}
63 {{ template "filters" (dict "name" "gaussianblur-5.jpg" "img" $sunset "filters" (images.GaussianBlur 5)) }}
64 {{ template "filters" (dict "name" "grayscale.jpg" "img" $sunset "filters" (images.Grayscale)) }}
65 {{ template "filters" (dict "name" "grayscale+colorize-180-50-20.jpg" "img" $sunset "filters" (slice images.Grayscale (images.Colorize 180 50 20))) }}
66 {{ template "filters" (dict "name" "colorbalance-180-50-20.jpg" "img" $sunset "filters" (images.ColorBalance 180 50 20)) }}
67 {{ template "filters" (dict "name" "hue--15.jpg" "img" $sunset "filters" (images.Hue -15)) }}
68 {{ template "filters" (dict "name" "invert.jpg" "img" $sunset "filters" (images.Invert)) }}
69 {{ template "filters" (dict "name" "opacity-0.65.jpg" "img" $sunset "filters" (images.Opacity 0.65)) }}
70 {{ template "filters" (dict "name" "overlay-20-20.jpg" "img" $sunset "filters" ($overlayFilter)) }}
71 {{ template "filters" (dict "name" "padding-20-40-#976941.jpg" "img" $sunset "filters" (images.Padding 20 40 "#976941" )) }}
72 {{ template "filters" (dict "name" "pixelate-10.jpg" "img" $sunset "filters" (images.Pixelate 10)) }}
73 {{ template "filters" (dict "name" "rotate270.jpg" "img" (resources.Get "rotate270.jpg") "filters" images.AutoOrient) }}
74 {{ template "filters" (dict "name" "saturation-65.jpg" "img" $sunset "filters" (images.Saturation 65)) }}
75 {{ template "filters" (dict "name" "sepia-80.jpg" "img" $sunsetGrayscale "filters" (images.Sepia 80)) }}
76 {{ template "filters" (dict "name" "sigmoid-0.6--4.jpg" "img" $sunset "filters" (images.Sigmoid 0.6 -4 )) }}
77 {{ template "filters" (dict "name" "text.jpg" "img" $sunset "filters" (images.Text "Hugo Rocks!" $textOpts )) }}
78 {{ template "filters" (dict "name" "unsharpmask.jpg" "img" $sunset "filters" (images.UnsharpMask 10 0.4 0.03)) }}
79
80
81 {{ define "filters"}}
82 {{ if lt (len (path.Ext .name)) 4 }}
83 {{ errorf "No extension in %q" .name }}
84 {{ end }}
85 {{ $img := .img.Filter .filters }}
86 {{ $name := printf "images/%s" .name }}
87 {{ with $img | resources.Copy $name }}
88 {{ .Publish }}
89 {{ end }}
90 {{ end }}
91 `
92
93 opts := imagetesting.DefaultGoldenOpts
94 opts.T = t
95 opts.Name = name
96 opts.Files = files
97
98 imagetesting.RunGolden(opts)
99 }
100
101 func TestImagesGoldenFiltersMask(t *testing.T) {
102 t.Parallel()
103
104 if imagetesting.SkipGoldenTests {
105 t.Skip("Skip golden test on this architecture")
106 }
107
108 // Will be used as the base folder for generated images.
109 name := "filters/mask"
110
111 files := `
112 -- hugo.toml --
113 [imaging]
114 bgColor = '#ebcc34'
115 hint = 'photo'
116 quality = 75
117 resampleFilter = 'Lanczos'
118 -- assets/sunset.jpg --
119 sourcefilename: ../testdata/sunset.jpg
120 -- assets/mask.png --
121 sourcefilename: ../testdata/mask.png
122
123 -- layouts/index.html --
124 Home.
125 {{ $sunset := resources.Get "sunset.jpg" }}
126 {{ $mask := resources.Get "mask.png" }}
127
128 {{ template "mask" (dict "name" "transparant.png" "base" $sunset "mask" $mask) }}
129 {{ template "mask" (dict "name" "yellow.jpg" "base" $sunset "mask" $mask) }}
130 {{ template "mask" (dict "name" "wide.jpg" "base" $sunset "mask" $mask "spec" "resize 600x200") }}
131 {{/* This looks a little odd, but is correct and the recommended way to do this.
132 This will 1. Scale the image to x300, 2. Apply the mask, 3. Create the final image with background color #323ea.
133 It's possible to have multiple images.Process filters in the chain, but for the options for the final image (target format, bgGolor etc.),
134 the last entry will win.
135 */}}
136 {{ template "mask" (dict "name" "blue.jpg" "base" $sunset "mask" $mask "spec" "resize x300 #323ea8") }}
137
138 {{ define "mask"}}
139 {{ $ext := path.Ext .name }}
140 {{ if lt (len (path.Ext .name)) 4 }}
141 {{ errorf "No extension in %q" .name }}
142 {{ end }}
143 {{ $format := strings.TrimPrefix "." $ext }}
144 {{ $spec := .spec | default (printf "resize x300 %s" $format) }}
145 {{ $filters := slice (images.Process $spec) (images.Mask .mask) }}
146 {{ $name := printf "images/%s" .name }}
147 {{ $img := .base.Filter $filters }}
148 {{ with $img | resources.Copy $name }}
149 {{ .Publish }}
150 {{ end }}
151 {{ end }}
152 `
153
154 opts := imagetesting.DefaultGoldenOpts
155 opts.T = t
156 opts.Name = name
157 opts.Files = files
158
159 imagetesting.RunGolden(opts)
160 }
161
162 // Issue 13272, 13273.
163 func TestImagesGoldenFiltersMaskCacheIssues(t *testing.T) {
164 if imagetesting.SkipGoldenTests {
165 t.Skip("Skip golden test on this architecture")
166 }
167
168 // Will be used as the base folder for generated images.
169 name := "filters/mask2"
170
171 files := `
172 -- hugo.toml --
173 [caches]
174 [caches.images]
175 dir = ':cacheDir/golden_images'
176 maxAge = "30s"
177 [imaging]
178 bgColor = '#33ff44'
179 hint = 'photo'
180 quality = 75
181 resampleFilter = 'Lanczos'
182 -- assets/sunset.jpg --
183 sourcefilename: ../testdata/sunset.jpg
184 -- assets/mask.png --
185 sourcefilename: ../testdata/mask.png
186
187 -- layouts/index.html --
188 Home.
189 {{ $sunset := resources.Get "sunset.jpg" }}
190 {{ $mask := resources.Get "mask.png" }}
191
192
193 {{ template "mask" (dict "name" "green.jpg" "base" $sunset "mask" $mask) }}
194
195 {{ define "mask"}}
196 {{ $ext := path.Ext .name }}
197 {{ if lt (len (path.Ext .name)) 4 }}
198 {{ errorf "No extension in %q" .name }}
199 {{ end }}
200 {{ $format := strings.TrimPrefix "." $ext }}
201 {{ $spec := .spec | default (printf "resize x300 %s" $format) }}
202 {{ $filters := slice (images.Process $spec) (images.Mask .mask) }}
203 {{ $name := printf "images/%s" .name }}
204 {{ $img := .base.Filter $filters }}
205 {{ with $img | resources.Copy $name }}
206 {{ .Publish }}
207 {{ end }}
208 {{ end }}
209 `
210
211 tempDir := t.TempDir()
212
213 opts := imagetesting.DefaultGoldenOpts
214 opts.WorkingDir = tempDir
215 opts.T = t
216 opts.Name = name
217 opts.Files = files
218 opts.SkipAssertions = true
219
220 imagetesting.RunGolden(opts)
221
222 files = strings.Replace(files, "#33ff44", "#a83269", -1)
223 files = strings.Replace(files, "green", "pink", -1)
224 files = strings.Replace(files, "mask.png", "mask2.png", -1)
225 opts.Files = files
226 opts.SkipAssertions = false
227 opts.Rebuild = true
228
229 imagetesting.RunGolden(opts)
230 }
231
232 func TestImagesGoldenFiltersText(t *testing.T) {
233 t.Parallel()
234
235 if imagetesting.SkipGoldenTests {
236 t.Skip("Skip golden test on this architecture")
237 }
238
239 // Will be used as the base folder for generated images.
240 name := "filters/text"
241
242 files := `
243 -- hugo.toml --
244 -- assets/sunset.jpg --
245 sourcefilename: ../testdata/sunset.jpg
246
247 -- layouts/index.html --
248 Home.
249 {{ $sunset := resources.Get "sunset.jpg" }}
250 {{ $textOpts := dict
251 "color" "#fbfaf5"
252 "linespacing" 8
253 "size" 28
254 "x" (div $sunset.Width 2 | int)
255 "y" (div $sunset.Height 2 | int)
256 "alignx" "center"
257 }}
258
259 {{ $text := "Pariatur deserunt sunt nisi sunt tempor quis eu. Sint et nulla enim officia sunt cupidatat. Eu amet ipsum qui velit cillum cillum ad Lorem in non ad aute." }}
260 {{ template "filters" (dict "name" "text_alignx-center.jpg" "img" $sunset "filters" (images.Text $text $textOpts )) }}
261 {{ $textOpts = (dict "alignx" "right") | merge $textOpts }}
262 {{ template "filters" (dict "name" "text_alignx-right.jpg" "img" $sunset "filters" (images.Text $text $textOpts )) }}
263 {{ $textOpts = (dict "alignx" "left") | merge $textOpts }}
264 {{ template "filters" (dict "name" "text_alignx-left.jpg" "img" $sunset "filters" (images.Text $text $textOpts )) }}
265 {{ $textOpts = (dict "alignx" "center" "aligny" "center") | merge $textOpts }}
266 {{ $text = "Est exercitation deserunt exercitation nostrud magna. Eiusmod anim deserunt sit elit dolore ea incididunt nisi. Ea ullamco excepteur voluptate occaecat duis pariatur proident cupidatat. Eu id esse qui consectetur commodo ad ex esse cupidatat velit duis cupidatat. Aliquip irure tempor consequat non amet in mollit ipsum officia tempor laborum." }}
267 {{ template "filters" (dict "name" "text_alignx-center_aligny-center.jpg" "img" $sunset "filters" (images.Text $text $textOpts )) }}
268 {{ $textOpts = (dict "alignx" "center" "aligny" "bottom") | merge $textOpts }}
269 {{ template "filters" (dict "name" "text_alignx-center_aligny-bottom.jpg" "img" $sunset "filters" (images.Text $text $textOpts )) }}
270
271 {{ define "filters"}}
272 {{ if lt (len (path.Ext .name)) 4 }}
273 {{ errorf "No extension in %q" .name }}
274 {{ end }}
275 {{ $img := .img.Filter .filters }}
276 {{ $name := printf "images/%s" .name }}
277 {{ with $img | resources.Copy $name }}
278 {{ .Publish }}
279 {{ end }}
280 {{ end }}
281 `
282
283 opts := imagetesting.DefaultGoldenOpts
284 opts.T = t
285 opts.Name = name
286 opts.Files = files
287 // opts.WriteFiles = true
288 // opts.DevMode = true
289
290 imagetesting.RunGolden(opts)
291 }
292
293 func TestImagesGoldenProcessMisc(t *testing.T) {
294 t.Parallel()
295
296 if imagetesting.SkipGoldenTests {
297 t.Skip("Skip golden test on this architecture")
298 }
299
300 // Will be used as the base folder for generated images.
301 name := "process/misc"
302
303 files := `
304 -- hugo.toml --
305 -- assets/giphy.gif --
306 sourcefilename: ../testdata/giphy.gif
307 -- assets/sunset.jpg --
308 sourcefilename: ../testdata/sunset.jpg
309 -- assets/gopher.png --
310 sourcefilename: ../testdata/gopher-hero8.png
311 -- layouts/index.html --
312 Home.
313 {{ $sunset := resources.Get "sunset.jpg" }}
314 {{ $sunsetGrayscale := $sunset.Filter (images.Grayscale) }}
315 {{ $gopher := resources.Get "gopher.png" }}
316 {{ $giphy := resources.Get "giphy.gif" }}
317
318
319 {{/* These are sorted. The end file name will be created from the spec + extension, so make sure these are unique. */}}
320 {{ template "process" (dict "spec" "crop 500x200 smart" "img" $sunset) }}
321 {{ template "process" (dict "spec" "fill 500x200 smart" "img" $sunset) }}
322 {{ template "process" (dict "spec" "fit 500x200 smart" "img" $sunset) }}
323 {{ template "process" (dict "spec" "resize 100x100 gif" "img" $giphy) }}
324 {{ template "process" (dict "spec" "resize 100x100 r180" "img" $gopher) }}
325 {{ template "process" (dict "spec" "resize 300x300 jpg #b31280" "img" $gopher) }}
326
327 {{ define "process"}}
328 {{ $img := .img.Process .spec }}
329 {{ $ext := path.Ext $img.RelPermalink }}
330 {{ $name := printf "images/%s%s" (.spec | anchorize) $ext }}
331 {{ with $img | resources.Copy $name }}
332 {{ .Publish }}
333 {{ end }}
334 {{ end }}
335 `
336
337 opts := imagetesting.DefaultGoldenOpts
338 opts.T = t
339 opts.Name = name
340 opts.Files = files
341
342 imagetesting.RunGolden(opts)
343 }
344
345 func TestImagesGoldenMethods(t *testing.T) {
346 t.Parallel()
347
348 if imagetesting.SkipGoldenTests {
349 t.Skip("Skip golden test on this architecture")
350 }
351
352 // Will be used as the base folder for generated images.
353 name := "methods"
354
355 files := `
356 -- hugo.toml --
357 [imaging]
358 bgColor = '#ebcc34'
359 hint = 'photo'
360 quality = 75
361 resampleFilter = 'MitchellNetravali'
362 -- assets/sunset.jpg --
363 sourcefilename: ../testdata/sunset.jpg
364 -- assets/gopher.png --
365 sourcefilename: ../testdata/gopher-hero8.png
366
367 -- layouts/index.html --
368 Home.
369 {{ $sunset := resources.Get "sunset.jpg" }}
370 {{ $gopher := resources.Get "gopher.png" }}
371
372
373 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "resize" "spec" "300x" ) }}
374 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "resize" "spec" "x200" ) }}
375 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "fill" "spec" "90x120 left" ) }}
376 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "fill" "spec" "90x120 right" ) }}
377 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "fit" "spec" "200x200" ) }}
378 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "crop" "spec" "200x200" ) }}
379 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "crop" "spec" "350x400 center" ) }}
380 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "crop" "spec" "350x400 smart" ) }}
381 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "crop" "spec" "350x400 center r90" ) }}
382 {{ template "invoke" (dict "copyFormat" "jpg" "base" $sunset "method" "crop" "spec" "350x400 center q20" ) }}
383 {{ template "invoke" (dict "copyFormat" "png" "base" $gopher "method" "resize" "spec" "100x" ) }}
384 {{ template "invoke" (dict "copyFormat" "png" "base" $gopher "method" "resize" "spec" "100x #fc03ec" ) }}
385 {{ template "invoke" (dict "copyFormat" "jpg" "base" $gopher "method" "resize" "spec" "100x #03fc56 jpg" ) }}
386
387 {{ define "invoke"}}
388 {{ $spec := .spec }}
389 {{ $name := printf "images/%s-%s-%s.%s" .method ((trim .base.Name "/") | lower | anchorize) ($spec | anchorize) .copyFormat }}
390 {{ $img := ""}}
391 {{ if eq .method "resize" }}
392 {{ $img = .base.Resize $spec }}
393 {{ else if eq .method "fill" }}
394 {{ $img = .base.Fill $spec }}
395 {{ else if eq .method "fit" }}
396 {{ $img = .base.Fit $spec }}
397 {{ else if eq .method "crop" }}
398 {{ $img = .base.Crop $spec }}
399 {{ else }}
400 {{ errorf "Unknown method %q" .method }}
401 {{ end }}
402 {{ with $img | resources.Copy $name }}
403 {{ .Publish }}
404 {{ end }}
405 {{ end }}
406 `
407
408 opts := imagetesting.DefaultGoldenOpts
409 opts.T = t
410 opts.Name = name
411 opts.Files = files
412
413 imagetesting.RunGolden(opts)
414 }