diff --git a/.github/DrawCard.png b/.github/DrawCard.png index 2002539..a9a0b13 100644 Binary files a/.github/DrawCard.png and b/.github/DrawCard.png differ diff --git a/.github/DrawTitle.png b/.github/DrawTitle.png index 4192a9d..95aa823 100644 Binary files a/.github/DrawTitle.png and b/.github/DrawTitle.png differ diff --git a/.github/DrawTitleWithText.png b/.github/DrawTitleWithText.png index db75ad8..ce5d85f 100644 Binary files a/.github/DrawTitleWithText.png and b/.github/DrawTitleWithText.png differ diff --git a/card.go b/card.go index fdf710a..2c859e6 100644 --- a/card.go +++ b/card.go @@ -5,10 +5,8 @@ import ( "errors" "image" "math/rand" - "strings" "github.com/FloatTech/gg" - "github.com/FloatTech/imgfactory" ) var ( @@ -28,24 +26,18 @@ func (c *Card) DrawTextCard() (imgForCard image.Image, err error) { return nil, ErrNilTextFont } // 正文数据 - textString := "" - if c.IsTextSplitPerElement { - textString = strings.Join(c.Text, "\n") - } else { - textString = strings.Join(c.Text, " ") - } - textImg, err := imgfactory.RenderTextWith(textString, c.TextFontData, width-80, 38) + texts, err := Truncate(c.TextFontData, c.Text, float64(width)-80, 38) if err != nil { return } - textHigh := textImg.Bounds().Dy() + textHigh := float64(len(texts)+1) * 38 * 72 / 96 * 1.5 // 计算图片高度 imgHigh := c.Height if imgHigh == 0 { if c.CanTitleShown { - imgHigh = 30 + 100 + textHigh + 20 + imgHigh = 30 + 100 + int(textHigh) + 20 } else { - imgHigh = 20 + textHigh + 20 + imgHigh = 20 + int(textHigh) + 20 } } // 创建画布 @@ -56,11 +48,21 @@ func (c *Card) DrawTextCard() (imgForCard image.Image, err error) { canvas.SetRGBA255(rand.Intn(45)+165, rand.Intn(45)+165, rand.Intn(45)+165, 255) canvas.Fill() } else { - banner, err := imgfactory.LoadFirstFrame(c.BackgroundImage, width, imgHigh) + banner, err := gg.LoadImage(c.BackgroundImage) if err == nil { - canvas.DrawImage(imgfactory.Size(banner.Image(), width, imgHigh).Image(), 0, 0) + if float64(banner.Bounds().Dy())/float64(banner.Bounds().Dx()) < float64(canvas.H())/float64(canvas.W()) { + sc := float64(canvas.H()) / float64(banner.Bounds().Dy()) + canvas.ScaleAbout(sc, sc, float64(canvas.W())/2, float64(canvas.H())/2) + canvas.DrawImageAnchored(banner, canvas.W()/2, canvas.H()/2, 0.5, 0.5) + } else { + sc := float64(canvas.W()) / float64(banner.Bounds().Dx()) + canvas.Scale(sc, sc) + canvas.DrawImage(banner, 0, 0) + } + canvas.Identity() } } + y := 0.0 // 标题 if c.CanTitleShown { if c.TitleFontData == nil { @@ -87,10 +89,18 @@ func (c *Card) DrawTextCard() (imgForCard image.Image, err error) { canvas.SetRGB(0, 0, 0) canvas.Fill() // 内容 - canvas.DrawImage(textImg, 10, 130) + y = 130 + 38*72/96*1.5 } else { // 内容 - canvas.DrawImage(textImg, 10, 20) + y = 20 + 38*72/96*1.5 + } + err = canvas.ParseFontFace(c.TextFontData, 38) + if err != nil { + return + } + for _, s := range texts { + canvas.DrawStringAnchored(s, 10, y, 0, 0.5) + y += canvas.FontHeight() * 1.5 } // 制图 imgForCard = canvas.Image() diff --git a/go.mod b/go.mod index fb4f9d3..5c94ca5 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,12 @@ go 1.19 require ( github.com/FloatTech/gg v1.1.2 - github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9 github.com/disintegration/imaging v1.6.2 github.com/stretchr/testify v1.8.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect github.com/fumiama/imgsz v0.0.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 4e978c3..43ab5f9 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,10 @@ github.com/FloatTech/gg v1.1.2 h1:YolgOYg3uDHc1+g0bLtt6QuRA/pvLn+b9IBCIhOOX88= github.com/FloatTech/gg v1.1.2/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI= -github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9 h1:Havq0z/N79KeD50L7ms+Hv8F4Sw98Dt8lXM8jECp04o= -github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= -github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU= -github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM= github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak= github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= diff --git a/title.go b/title.go index aba806a..5f66faa 100644 --- a/title.go +++ b/title.go @@ -4,7 +4,6 @@ import ( "image" "github.com/FloatTech/gg" - "github.com/FloatTech/imgfactory" ) // DrawTitle 绘制标题 @@ -24,7 +23,7 @@ func (t *Title) DrawTitle() (imgs image.Image, err error) { canvas.SetRGBA255(0, 0, 0, 153) canvas.Fill() - fontsize1, fontsize2 := 108.0+t.TitleFontOffsetPoint, 54.0+t.TextFontOffsetPoint + fontsize1, fontsize2, fontsize3 := 108.0+t.TitleFontOffsetPoint, 72+t.TextFontOffsetPoint, 54.0+t.TextFontOffsetPoint // 加载size为108的字体 err = canvas.ParseFontFace(t.TitleFontData, fontsize1) if err != nil { @@ -33,37 +32,35 @@ func (t *Title) DrawTitle() (imgs image.Image, err error) { // 绘制标题 canvas.SetRGBA255(250, 250, 250, 255) - stringwight, _ := canvas.MeasureString(t.LeftTitle) - canvas.DrawStringAnchored(t.LeftTitle, (220-(fontsize1+fontsize2)*72/96)*0.33+stringwight/2+t.OffsetX, 30+40+(220-(fontsize1+fontsize2)*72/96)*0.33+fontsize1*72/96*0.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.LeftTitle, (220-fontsize1-fontsize3)/3+t.OffsetX, 30+40+(220-fontsize1-fontsize3)/3+fontsize1/2+t.OffsetY, 0, 0.5) // 加载size为54的字体 - err = canvas.ParseFontFace(t.TextFontData, fontsize2) + err = canvas.ParseFontFace(t.TextFontData, fontsize3) if err != nil { return } canvas.SetRGBA255(250, 250, 250, 255) // 绘制副标题 - stringwight, _ = canvas.MeasureString(t.LeftSubtitle) - canvas.DrawStringAnchored(t.LeftSubtitle, 3+(220-(fontsize1+fontsize2)*72/96)*0.33+stringwight/2+t.OffsetX, 30+40+(220-(fontsize1+fontsize2)*72/96)*0.66+fontsize1*72/96+fontsize2*72/96*0.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.LeftSubtitle, 3+(220-fontsize1-fontsize3)/3+t.OffsetX, 30+40+(220-fontsize1-fontsize3)/3*2+fontsize1+fontsize3/2+t.OffsetY, 0, 0.5) - // 加载icon并绘制 - var icon *imgfactory.Factory - icon, err = imgfactory.LoadFirstFrame(t.ImagePath, 220, 220) + // 加载icon并绘制 高限制220 + var icon image.Image + icon, err = gg.LoadImage(t.ImagePath) if err != nil { return } - canvas.DrawImage(icon.Image(), int(DefaultWidth)-icon.W(), 40+30) + sc := 220 / float64(icon.Bounds().Dy()) + canvas.ScaleAbout(sc, sc, DefaultWidth-float64(icon.Bounds().Dx())*sc/2, 40+30+220/2) + canvas.DrawImageAnchored(icon, int(DefaultWidth)-int(float64(icon.Bounds().Dx())*sc/2), 40+30+220/2, 0.5, 0.5) + canvas.Identity() // 加载size为72的字体 - fontsize1 = 72 + t.TextFontOffsetPoint - err = canvas.ParseFontFace(t.TextFontData, fontsize1) + err = canvas.ParseFontFace(t.TextFontData, fontsize2) if err != nil { return } - stringwight, _ = canvas.MeasureString(t.RightTitle) - canvas.DrawStringAnchored(t.RightTitle, DefaultWidth-25-float64(icon.W())-stringwight/2+t.OffsetX, 30+40+(220-fontsize1*72/96*2)*0.33+fontsize1*72/96*0.5+t.OffsetY, 0.5, 0.5) - stringwight, _ = canvas.MeasureString(t.RightSubtitle) - canvas.DrawStringAnchored(t.RightSubtitle, DefaultWidth-25-float64(icon.W())-stringwight/2+t.OffsetX, 30+40+(220-fontsize1*72/96*2)*0.66+fontsize1*72/96*1.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.RightTitle, DefaultWidth-float64(icon.Bounds().Dx())*sc-25+t.OffsetX, 30+40+(220-fontsize2*2)/3+fontsize2/2+t.OffsetY, 1, 0.5) + canvas.DrawStringAnchored(t.RightSubtitle, DefaultWidth-float64(icon.Bounds().Dx())*sc-25+t.OffsetX, 30+40+(220-fontsize2*2)/3*2+fontsize2+fontsize2/2+t.OffsetY, 1, 0.5) imgs = canvas.Image() return @@ -83,15 +80,24 @@ func (t *Title) DrawTitleWithText(info []string) (imgs image.Image, err error) { canvas.Clear() // 加载icon - var icon *imgfactory.Factory - icon, err = imgfactory.LoadFirstFrame(t.ImagePath, 512, 512) + var icon image.Image + icon, err = gg.LoadImage(t.ImagePath) if err != nil { return } - canvas.DrawImage(icon.Image(), DefaultWidth-icon.W(), imgh-icon.H()) + sc := 0.0 + if float64(icon.Bounds().Dy())/float64(icon.Bounds().Dx()) >= 1 { + sc = DefaultWidth / 2 / float64(icon.Bounds().Dy()) + } else { + sc = DefaultWidth / 2 / float64(icon.Bounds().Dx()) + } + canvas.ScaleAbout(sc, sc, float64(canvas.W()), float64(canvas.H())) + canvas.DrawImageAnchored(icon, canvas.W(), canvas.H(), 1, 1) + canvas.Identity() // 加载size为108的字体 fontsize1, fontsize2 := 108.0+t.TitleFontOffsetPoint, 54.0+t.TextFontOffsetPoint + fsp1, fsp2 := fontsize1*72/96, fontsize2*72/96 err = canvas.ParseFontFace(t.TitleFontData, fontsize1) if err != nil { return @@ -100,8 +106,7 @@ func (t *Title) DrawTitleWithText(info []string) (imgs image.Image, err error) { canvas.SetRGBA255(15, 15, 15, 255) // 绘制标题 - stringwight, _ := canvas.MeasureString(t.LeftTitle) - canvas.DrawStringAnchored(t.LeftTitle, 25+stringwight/2+t.OffsetX, 25+fontsize1*72/96*0.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.LeftTitle, 25+t.OffsetX, 25+fsp1/2+t.OffsetY, 0, 0.5) // 加载size为54的字体 err = canvas.ParseFontFace(t.TextFontData, fontsize2) @@ -110,10 +115,9 @@ func (t *Title) DrawTitleWithText(info []string) (imgs image.Image, err error) { } // 绘制一系列标题 - stringwight, _ = canvas.MeasureString(t.LeftSubtitle) - canvas.DrawStringAnchored(t.LeftSubtitle, 25+3+stringwight/2+t.OffsetX, 25+fontsize1*72/96+25+fontsize2*72/96*0.5+t.OffsetY, 0.5, 0.5) - - canvas.DrawRectangle(25+3+t.OffsetX, 25+fontsize1*72/96+25+fontsize2*72/96+7+t.OffsetY, stringwight, 6) + canvas.DrawStringAnchored(t.LeftSubtitle, 25+3+t.OffsetX, 25+fsp1+25+fsp2/2+t.OffsetY, 0, 0.5) + stringwight, _ := canvas.MeasureString(t.LeftSubtitle) + canvas.DrawRectangle(25+3+t.OffsetX, 25+fsp1+25+fsp2+7+t.OffsetY, stringwight, 6) // 绘制插件开启状态 if t.IsEnabled { canvas.SetRGBA255(35, 235, 35, 255) @@ -129,10 +133,8 @@ func (t *Title) DrawTitleWithText(info []string) (imgs image.Image, err error) { return } - stringwight, _ = canvas.MeasureString(t.RightTitle) - canvas.DrawStringAnchored(t.RightTitle, DefaultWidth-40-stringwight/2+t.OffsetX, 40+fontsize2*72/96*0.5+t.OffsetY, 0.5, 0.5) - stringwight, _ = canvas.MeasureString(t.RightSubtitle) - canvas.DrawStringAnchored(t.RightSubtitle, DefaultWidth-40-stringwight/2+t.OffsetX, 40+25+fontsize2*72/96*1.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.RightTitle, DefaultWidth-40+t.OffsetX, 40+fsp2/2+t.OffsetY, 1, 0.5) + canvas.DrawStringAnchored(t.RightSubtitle, DefaultWidth-40+t.OffsetX, 40+fsp2+25+fsp2/2+t.OffsetY, 1, 0.5) // 加载size为38的字体 err = canvas.ParseFontFace(t.TextFontData, 38+t.TextFontOffsetPoint) @@ -140,7 +142,7 @@ func (t *Title) DrawTitleWithText(info []string) (imgs image.Image, err error) { return } - y := 25 + fontsize1*72/96 + 25 + fontsize2*72/96 + y := 25 + fsp1 + 25 + fsp2 for _, text := range info { canvas.DrawString(text, 25.0, y+canvas.FontHeight()*2) y += 20 + canvas.FontHeight() @@ -154,14 +156,21 @@ func (t *Title) DrawCard() (imgs image.Image, err error) { recw, rech := 384.0, 256.0 canvas := gg.NewContext(int(recw), int(rech)) // 绘制图片 - var banner *imgfactory.Factory - banner, err = imgfactory.LoadFirstFrame(t.ImagePath, int(recw)*2, int(rech)*2) + var banner image.Image + banner, err = gg.LoadImage(t.ImagePath) if err == nil { - canvas.DrawImage(imgfactory.Size(banner.Image(), int(recw), int(rech)).Image(), 0, 0) + sc := 0.0 + if float64(banner.Bounds().Dy())/float64(banner.Bounds().Dx()) < rech/recw { + sc = rech / float64(banner.Bounds().Dy()) + } else { + sc = recw / float64(banner.Bounds().Dx()) + } + canvas.ScaleAbout(sc, sc, recw/2, rech/2) + canvas.DrawImageAnchored(banner, int(recw)/2, int(rech)/2, 0.5, 0.5) + canvas.Identity() } else { - canvas.DrawRectangle(0, 0, recw, rech) canvas.SetRGB255(RandJPColor()) - canvas.Fill() + canvas.Clear() } if t.IsEnabled { canvas.DrawRectangle(0, rech*0.54, recw, rech-rech*0.54) @@ -174,17 +183,18 @@ func (t *Title) DrawCard() (imgs image.Image, err error) { // 绘制插件信息 canvas.SetRGBA255(240, 240, 240, 255) fontsize1, fontsize2 := 64.0+t.TitleFontOffsetPoint, 32.0+t.TextFontOffsetPoint + fsp1, fsp2 := fontsize1*72/96, fontsize2*72/96 err = canvas.ParseFontFace(t.TitleFontData, fontsize1) if err != nil { return } - canvas.DrawStringAnchored(t.LeftTitle, recw/2+t.OffsetX, rech*0.54+(rech-rech*0.54-(fontsize1+fontsize2)*72/96)*0.33+fontsize1*72/96*0.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.LeftTitle, recw/2+t.OffsetX, rech*0.54+(rech-rech*0.54-(fsp1+fsp2))/3+fsp1/2+t.OffsetY, 0.5, 0.5) err = canvas.ParseFontFace(t.TextFontData, fontsize2) if err != nil { return } - canvas.DrawStringAnchored(t.LeftSubtitle, recw/2+t.OffsetX, rech*0.54+(rech-rech*0.54-(fontsize1+fontsize2)*72/96)*0.66+fontsize1*72/96+fontsize2*72/96*0.5+t.OffsetY, 0.5, 0.5) + canvas.DrawStringAnchored(t.LeftSubtitle, recw/2+t.OffsetX, rech*0.54+(rech-rech*0.54-(fsp1+fsp2))/3*2+fsp1+fsp2/2+t.OffsetY, 0.5, 0.5) imgs = canvas.Image() return diff --git a/title_test.go b/title_test.go index 489c4e4..ee95e9c 100644 --- a/title_test.go +++ b/title_test.go @@ -42,7 +42,7 @@ func TestDrawTitle(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, "28f9f68f3ef7987a9d189b52b9a8b399", hex.EncodeToString(h.Sum(nil))) + assert.Equal(t, "5450734a22186aa176387ff2a91d9a7e", hex.EncodeToString(h.Sum(nil))) } func TestDrawTitleWithText(t *testing.T) { @@ -77,7 +77,7 @@ func TestDrawTitleWithText(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, "bf5ce310c0a565477fa83904a506c08d", hex.EncodeToString(h.Sum(nil))) + assert.Equal(t, "49c0bb06f1b8e16833e73d2bdcbe01ce", hex.EncodeToString(h.Sum(nil))) } func TestDrawCard(t *testing.T) { @@ -112,5 +112,5 @@ func TestDrawCard(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, "4e1b4c439a78d833b0931655d736b02f", hex.EncodeToString(h.Sum(nil))) + assert.Equal(t, "deba289674306c6d674c0c07f6ae458c", hex.EncodeToString(h.Sum(nil))) } diff --git a/utils.go b/utils.go index c0b8dfc..32824e3 100644 --- a/utils.go +++ b/utils.go @@ -9,24 +9,12 @@ import ( ) // Fillet 将矩形图片裁切为圆角矩形 -func Fillet(dst image.Image, r int) image.Image { - dstr := gg.ImageToNRGBA(dst) - mx, my := dst.Bounds().Max.X, dst.Bounds().Max.Y - var xx, yy, rr float64 - for y := 0; y < my/2; y++ { - for x := 0; x < mx/2; x++ { - if x <= r && y <= r { - xx, yy, rr = float64(r-x), float64(y-r), float64(r) - if xx*xx+yy*yy >= rr*rr { - dstr.Set(x, y, color.NRGBA{}) - dstr.Set(mx-1-x, y, color.NRGBA{}) - dstr.Set(x, my-1-y, color.NRGBA{}) - dstr.Set(mx-1-x, my-1-y, color.NRGBA{}) - } - } - } - } - return dstr +func Fillet(dst image.Image, r float64) image.Image { + canvas := gg.NewContext(dst.Bounds().Dx(), dst.Bounds().Dy()) + canvas.DrawRoundedRectangle(0, 0, float64(dst.Bounds().Dx()), float64(dst.Bounds().Dy()), r) + canvas.Clip() + canvas.DrawImage(dst, 0, 0) + return canvas.Image() } // Transparency 更改透明度 magnification 倍率值