golang 通过Go生成文本图像(具有不透明度)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 通过Go生成文本图像(具有不透明度)相关的知识,希望对你有一定的参考价值。

package main

import (
	"github.com/golang/freetype/truetype"
	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"io/ioutil"
	"os"
)

var face font.Face

const textPadding = 10

func init() {
	const (
		fontDPI  = 72
		fontSize = 48
		fontPath = "MSYH.ttf"
	)

	fontBytes, err := ioutil.ReadFile(fontPath)
	if err != nil {
		panic(err)
	}

	myFont, err := truetype.Parse(fontBytes)
	if err != nil {
		panic(err)
	}

	face = truetype.NewFace(myFont, &truetype.Options{
		Size:    fontSize,
		DPI:     fontDPI,
		Hinting: font.HintingVertical,
	})
}

func genImage(text string, opacity float64) image.Image {
	textColor := color.NRGBA{0xFF, 0xFF, 200, 0xFF}

	// 文本的宽度与高度
	textWidth := font.MeasureString(face, text)
	textHeight := face.Metrics().Height

	// 图片的宽度与高度
	imgWidth := textWidth.Ceil() + textPadding*2
	imgHeight := textHeight.Ceil() + textPadding*2

	m := image.NewRGBA(image.Rect(0, 0, imgWidth, imgHeight))

	// 绘制图像
	draw.Draw(m, m.Bounds(), image.NewUniform(color.White), image.ZP, draw.Src)

	// 绘制文字
	d := &font.Drawer{
		Dst:  m,
		Src:  &image.Uniform{textColor},
		Face: face,
	}

	d.Dot = fixed.Point26_6{
		X: (fixed.I(imgWidth) - textWidth) / 2,
		Y: fixed.I(imgHeight) - face.Metrics().Descent,
	}

	d.DrawString(text)

	// 设置透明度
	for x := 0; x < imgWidth; x++ {
		for y := 0; y < imgHeight; y++ {
			rgba := m.RGBAAt(x, y)
			rgba.R = uint8(float64(rgba.R) * opacity)
			rgba.G = uint8(float64(rgba.G) * opacity)
			rgba.B = uint8(float64(rgba.B) * opacity)
			rgba.A = uint8(opacity * 0xFF)
			m.SetRGBA(x, y, rgba)
		}
	}

	return m
}

func main() {
	img := genImage("测试", 0.1)
	outfile, _ := os.Create("t.png")
	png.Encode(outfile, img)
}

具有不透明度和渐变文本笔画/轮廓的 CSS 渐变文本

【中文标题】具有不透明度和渐变文本笔画/轮廓的 CSS 渐变文本【英文标题】:CSS Gradient Text with Opacity and Gradient Text Stroke / Outline 【发布时间】:2020-09-01 15:19:20 【问题描述】:

虽然我找到了similar questions,但没有一个明确符合我的目标。

我正在尝试使用渐变颜色显示文本,不透明度低(因此您可以通过它看到背景),而且还带有(匹配的)实心渐变边框(即文本笔划)。我发现similar questions 的答案通过创建复制(渐变)边框效果的::before 底层状态来开发解决方法,但是更改文本自然状态的不透明度只会显示::before 底层文本的颜色而不是背景颜色(所需的结果)。

我想知道的是,是否有任何解决方法可以有效地使用不透明度低于 1 的(内部)渐变文本创建实心渐变文本笔划?

使用前面提到的其他similar questions,我在几个小时内开发了以下代码,但无法完全弄清楚它是如何完成的。您会在我的代码中注意到我使用了不同的 rgba 值 - 这样做只是为了更轻松地查看结果并查看我是否实现了使(内部)文本具有不透明度(以启用背景)的预期目标要看到),而不是使用相同的颜色。我应用的不透明度越高,您就越能看到 workaround/makeshift 文本笔划的渐变颜色。

body 
  background: #000000;


h1 
  font-size: 60px;
  font-weight: 800;
  font-family: arial;
  color: rgb(255, 255, 255);
  background-image: linear-gradient(to left,
      rgba(255, 0, 0, 0.7),
      rgba(0, 0, 255, 0.7),
      rgba(255, 0, 0, 0.7));
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  margin: 10px;


h1::before 
  content: attr(data-text);
  background: -webkit-linear-gradient(-180deg, #3399ff, #82ed89, #3399ff);
  -webkit-background-clip: text;
  -webkit-text-stroke: 5px transparent;
  position: absolute;
  z-index: -1;
&lt;h1 data-text="Text"&gt;Text&lt;/h1&gt;

【问题讨论】:

对于您链接的问题,您是否检查过:***.com/a/56234003/8620333?使用 SVG,您可以轻松做到这一点 @TemaniAfif 是的 - 类似于 this question 我想避免使用 SVG(或任何图像),如果可能的话,看看是否有办法完全使用 CSS。 【参考方案1】:

实际上,我能想到的使用 CSS 而不使用 SVG 的唯一方法是依靠 element() 结合 mask,但支持率仍然太低:

这是一个仅适用于 Firefox 的示例。诀窍是创建一个只有描边和透明颜色的文本作为参考,将在相同文本的蒙版中使用,我们有相同的描边,以保持描边可见并获得所需的效果。是的,这个想法有点疯狂,但它确实有效。

body 
  background: #000000;

h1 
  font-size: 80px;
  font-weight: 800;
  font-family: arial;
  color:#fff;

#ref 
  -webkit-text-stroke: 5px red;
  color:transparent;
  display:inline-block;

h1.grad 
  background-image: linear-gradient(to left,
      rgba(255, 0, 0, 0.3),
      rgba(0, 0, 255, 0.4),
      rgba(255, 0, 0, 0.5));
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  margin: 10px;

h1.grad::after 
  content: attr(data-text);


h1.grad::before 
  content: attr(data-text);
  background: -webkit-linear-gradient(-180deg, #3399ff, #82ed89, #3399ff);
  -webkit-background-clip: text;
  -webkit-text-stroke: 5px transparent;
  position: absolute;
  z-index: -1;
  -webkit-mask:element(#ref);
          mask:-moz-element(#ref);
          mask:element(#ref);


body 
  background:url(https://i.picsum.photos/id/107/1000/1000.jpg) center/cover;
<h1 data-text="Some Text" class="grad"></h1>


<div style="height:0;overflow:hidden;">
<h1 id="ref">Some Text</h1>
</div>

如下图所示:

另一个想法是考虑background-attachment:fixed 并使用相同的背景两次。这应该适用于任何地方,但您的背景将被修复:

body 
  background: #000000;

h1 
  font-size: 80px;
  font-weight: 800;
  font-family: arial;
  color:#fff;


h1.grad 
  background: linear-gradient(to left,
      rgba(255, 0, 0, 0.3),
      rgba(0, 0, 255, 0.4),
      rgba(255, 0, 0, 0.5)),
      url(https://i.picsum.photos/id/110/1000/1200.jpg) center/cover fixed;
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
          background-clip: text;
  margin: 10px;

h1.grad::after 
  content: attr(data-text);


h1.grad::before 
  content: attr(data-text);
  background: -webkit-linear-gradient(-180deg, #3399ff, #82ed89, #3399ff);
  -webkit-background-clip: text;
  -webkit-text-stroke: 5px transparent;
  position: absolute;
  z-index: -1;


body 
  background:url(https://i.picsum.photos/id/110/1000/1200.jpg) center/cover fixed;
&lt;h1 data-text="Some Text" class="grad"&gt;&lt;/h1&gt;

【讨论】:

非常棒 - 最终版本很好用(对于不同的浏览器来说是最好的),但我会注意到它只能用于不透明的位图图像。希望他们会用渐变文本笔画功能更新 CSS - 这对于各种项目来说都是一个有用的功能,尤其是那些在用户设备上设置了透明背景或背景的项目。感谢您对此的帮助!

以上是关于golang 通过Go生成文本图像(具有不透明度)的主要内容,如果未能解决你的问题,请参考以下文章

具有变暗不透明度的文本叠加图像 React Native

CALayer - 如何创建具有纯色背景和透明文本的图像?

叠加在图像上时,使文本显示为白色,具有半透明的黑色背景

如何创建具有不透明度的父 div,同时将文本的不透明度保持在 100% [重复]

剪出文字形状的图片

在 React Native iOS 中的图像顶部呈现具有透明背景的文本框