From 3a9cb7b0fb1da71f1c051340bf746f29ab39cd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 4 Oct 2022 11:00:07 +0200 Subject: [PATCH] resources/images: Fix 2 animated GIF resize issues * Fix resize of animated GIF when target != GIF * Avoid processing all GIF frames if targetFormat != GIF Fixes #10354 --- resources/image_test.go | 4 +- resources/images/config.go | 1 + resources/images/image.go | 37 +++++++++++------- ..._52213_100x0_resize_q75_bgffffff_box_1.jpg | Bin 0 -> 2154 bytes ...6bf1d31f82e1_52213_200x0_resize_box_1.gif} | Bin ...6bf1d31f82e1_52213_512x0_resize_box_1.gif} | Bin ...0641110a1a73_10820_100x0_resize_box_1.gif} | Bin ...0641110a1a73_10820_220x0_resize_box_1.gif} | Bin 8 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_100x0_resize_q75_bgffffff_box_1.jpg rename resources/testdata/golden/{giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box.gif => giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box_1.gif} (100%) rename resources/testdata/golden/{giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box.gif => giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box_1.gif} (100%) rename resources/testdata/golden/{gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box.gif => gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box_1.gif} (100%) rename resources/testdata/golden/{gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box.gif => gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box_1.gif} (100%) diff --git a/resources/image_test.go b/resources/image_test.go index 111ce66db2b..75a20f156b6 100644 --- a/resources/image_test.go +++ b/resources/image_test.go @@ -620,6 +620,8 @@ func TestImageOperationsGolden(t *testing.T) { // Note, if you're enabling this on a MacOS M1 (ARM) you need to run the test with GOARCH=amd64. // GOARCH=amd64 go test -timeout 30s -run "^TestImageOperationsGolden$" ./resources -v + // The above will print out a folder. + // Replace testdata/golden with resources/_gen/images in that folder. devMode := false testImages := []string{"sunset.jpg", "gohugoio8.png", "gohugoio24.png"} @@ -663,7 +665,7 @@ func TestImageOperationsGolden(t *testing.T) { // Animated GIF orig = fetchImageForSpec(spec, c, "giphy.gif") - for _, resizeSpec := range []string{"200x", "512x"} { + for _, resizeSpec := range []string{"200x", "512x", "100x jpg"} { resized, err := orig.Resize(resizeSpec) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() diff --git a/resources/images/config.go b/resources/images/config.go index 62b5c72d8cf..6f562ff8ece 100644 --- a/resources/images/config.go +++ b/resources/images/config.go @@ -60,6 +60,7 @@ var ( imageFormatsVersions = map[Format]int{ PNG: 3, // Fix transparency issue with 32 bit images. WEBP: 2, // Fix transparency issue with 32 bit images. + GIF: 1, // Fix resize issue with animated GIFs when target != GIF. } // Increment to mark all processed images as stale. Only use when absolutely needed. diff --git a/resources/images/image.go b/resources/images/image.go index 4ffbaa2295a..9dc8ed408c3 100644 --- a/resources/images/image.go +++ b/resources/images/image.go @@ -247,7 +247,7 @@ func (p *ImageProcessor) ApplyFiltersFromConfig(src image.Image, conf ImageConfi return nil, fmt.Errorf("unsupported action: %q", conf.Action) } - img, err := p.Filter(src, filters...) + img, err := p.doFilter(src, conf.TargetFormat, filters...) if err != nil { return nil, err } @@ -256,25 +256,34 @@ func (p *ImageProcessor) ApplyFiltersFromConfig(src image.Image, conf ImageConfi } func (p *ImageProcessor) Filter(src image.Image, filters ...gift.Filter) (image.Image, error) { + return p.doFilter(src, 0, filters...) +} + +func (p *ImageProcessor) doFilter(src image.Image, targetFormat Format, filters ...gift.Filter) (image.Image, error) { filter := gift.New(filters...) - if giph, ok := src.(Giphy); ok && len(giph.GIF().Image) > 1 { + if giph, ok := src.(Giphy); ok { g := giph.GIF() - var bounds image.Rectangle - firstFrame := g.Image[0] - tmp := image.NewNRGBA(firstFrame.Bounds()) - for i := range g.Image { - gift.New().DrawAt(tmp, g.Image[i], g.Image[i].Bounds().Min, gift.OverOperator) - bounds = filter.Bounds(tmp.Bounds()) - dst := image.NewPaletted(bounds, g.Image[i].Palette) - filter.Draw(dst, tmp) - g.Image[i] = dst + if len(g.Image) < 2 || (targetFormat == 0 || targetFormat != GIF) { + src = g.Image[0] + } else { + var bounds image.Rectangle + firstFrame := g.Image[0] + tmp := image.NewNRGBA(firstFrame.Bounds()) + for i := range g.Image { + gift.New().DrawAt(tmp, g.Image[i], g.Image[i].Bounds().Min, gift.OverOperator) + bounds = filter.Bounds(tmp.Bounds()) + dst := image.NewPaletted(bounds, g.Image[i].Palette) + filter.Draw(dst, tmp) + g.Image[i] = dst + } + g.Config.Width = bounds.Dx() + g.Config.Height = bounds.Dy() + + return giph, nil } - g.Config.Width = bounds.Dx() - g.Config.Height = bounds.Dy() - return giph, nil } bounds := filter.Bounds(src.Bounds()) diff --git a/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_100x0_resize_q75_bgffffff_box_1.jpg b/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_100x0_resize_q75_bgffffff_box_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c55e5d3adbd02e720b766f7453073459d6e1aa35 GIT binary patch literal 2154 zcmbW$dpy(oAHebN?wd({N-)YR4`>uVE9I+~gW<{L>ABNG!7 zEqzP61=X5tY(fR0P$(5;6`ZOnj!MuZQ2*~)tOw9Y;4p9)0wMxnGzfwQEjEF~004r4 z{utmt0|G;!FgOBo|lFtUZOcI6_7AsA|WmI$e1 zCvCv8Iwp0Ey^klLl+@SY@N4xp=o@S_G%+y`2@_?aG z2o$mG0fEDpf}o)=f)QNJ))m1GSxuzIBQbVaB54Ck$Cx#V^*-LAq^@f+s5iAt`a|^3 zKned!^cUza&!QYqfq<4C41xx>0-xjt;y9)M)k8180mtzo5Be*HoUe?01q}nuZJu>$ zv{qAPcW(=*k=-~~*WD`)ywabZFqMGyX&r%kGh18|!>^ab$lO$1-#Oljx5K(nC~MNt z8M})B--oA46$Ig!^Lf#MgYN{Yq`0U=gX($6Rh!*d5p>GSv&CACl;tSu=o+EWk;Spo zkw-4<%Of)EE>s+<#?h-G)`w=tsyKBtY{itB#9t*_IXq#L2((p~|H0t+y*$GebSC`` z*y@|--cyYCElzhT`-4&rMCakYK0yJDf~*!+0*vG1vgj!byN9s z@>5Y^@4zKFUz_PP&vyx#?;(&DG`eM$`UjPFmL9MU)NA%heXa2WMJqaPmp8XL0wS+f zHJjG>M(uvzk0%KALKy%SdW>T6wX9G4?L|#r8-sc8sE0UZBL?HT9a!#!hkJo<0SSBc3*jNGlp+*;(M*!I9lmf zTg{e-9fP#|2CH!UmkC?L1(`-~r~@y|1jS}Q@V_I!S8e3D^ETxfQV1}5}B$$-@FK|AZxV9=gkLN#D zN~^|=WhLUq$VP2|gCwH(*`B+Vo)Ki2Y)D#Fb4;YC&6mT&!R(N^xWS!PZj%p+C8ekR zOxq^v8qRY!4DdvkcAztD5irHa8x9Q%YCWOJgv#i^=s<(u^bztWQYYiu*^|%)eB-Lv zAn-2pFzRP_p4)`nBA0&b(Zed2FW!BT0Wo6cx3R~c>b1VRS!BrhjW^Dwe+x)Sa?>IXtrz9;w(?lZX-yid^xB@OHj& zA|~`zR?qd5{8S>9mc+mv;buCBZX8{y)Fuh&5qRwIcMsuM9FpwTYY*CPs8loQ#2@eK z6x3Wv<1c-=iFNB_PuRH~eKrblCf_ZAy5(FJ>jiJi^LJ*e6u|>N9OGe)3|5HZ`ziN; zEYNn0%W??Q;aX|nU>-K!Z#0Xw7xBSdlzOGirAc)%3u1TQGWB@e(k}f1osY>CCIY&*e&IAAp1@Hq2TzcrC>*p6zH0t* zd#ql-nq7@SnfCUq)-2ul9#xq_d2}U#a;+ZQf5Eog-MDS2EdaHzadVAh#Z#W*NfIW# zO4n{zhK?ilYB0c9(|$!=xFA>rP;d$Pc4UD<_s*TNvfym{AnX1eFpawEiD#xg9vpeU zys+D?(X>`Y=l)>k@CD>hoW3~40Qg(rx)~<@Y!l0{G8oThy6bXvl5I+AZPCpTB&5Lt`_4^t%-i zZC}+nkw1Vl=lM1dSEp(Y_jN_Vn%LdpYo@3boPMWIY3iw5dVX;}DrIb|zwt`bv1bR3uISzV;2G)y+idLkywcMxu&CG8m(QtA Wfg)=&+~Q}-D_w11n17zuV(;&Rq@LXX literal 0 HcmV?d00001 diff --git a/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box.gif b/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box_1.gif similarity index 100% rename from resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box.gif rename to resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box_1.gif diff --git a/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box.gif b/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box_1.gif similarity index 100% rename from resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box.gif rename to resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box_1.gif diff --git a/resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box.gif b/resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box_1.gif similarity index 100% rename from resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box.gif rename to resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box_1.gif diff --git a/resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box.gif b/resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box_1.gif similarity index 100% rename from resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box.gif rename to resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box_1.gif