我想打开jpeg图像文件,对其进行编码,更改一些像素颜色,然后将其保存回原样。
我想做这样的事情
imgfile, err := os.Open("unchanged.jpeg")
defer imgfile.Close()
if err != nil {
fmt.Println(err.Error())
}
img,err := jpeg.Decode(imgfile)
if err != nil {
fmt.Println(err.Error())
}
img.Set(0, 0, color.RGBA{85, 165, 34, 1})
img.Set(1,0,....)
outFile, _ := os.Create("changed.jpeg")
defer outFile.Close()
jpeg.Encode(outFile, img, nil)
我只是想不出一个可行的解决方案,因为编码图像文件后获得的默认图像类型没有Set方法。
谁能解释该怎么做?非常感谢。
成功解码后image.Decode()
(以及特定的解码功能,如jpeg.Decode()
),返回的值image.Image
。image.Image
是一个接口,用于定义图像的只读视图:它不提供更改/绘制图像的方法。
该image
软件包提供了几种image.Image
实现方式,这些实现方式通常允许您使用一种Set(x, y int, c color.Color)
方法来更改/绘制图像。
image.Decode()
但是,不能保证返回的图像将是image
包中定义的任何图像类型,甚至Set()
不能保证图像的动态类型具有方法(它可以,但不能保证)。注册的自定义图像解码器可能会返回一个image.Image
值,该值是自定义实现(意味着不是image
包中定义的图像类型)。
如果(图像的动态类型)确实具有Set()
方法,则可以使用类型断言并使用其Set()
方法在其上进行绘制。这是可以做到的:
type Changeable interface {
Set(x, y int, c color.Color)
}
imgfile, err := os.Open("unchanged.jpg")
if err != nil {
panic(err.Error())
}
defer imgfile.Close()
img, err := jpeg.Decode(imgfile)
if err != nil {
panic(err.Error())
}
if cimg, ok := img.(Changeable); ok {
// cimg is of type Changeable, you can call its Set() method (draw on it)
cimg.Set(0, 0, color.RGBA{85, 165, 34, 255})
cimg.Set(0, 1, color.RGBA{255, 0, 0, 255})
// when done, save img as usual
} else {
// No luck... see your options below
}
如果图像没有Set()
方法,您可以选择通过实现一个实现的自定义类型来“覆盖其视图” image.Image
,但是在其At(x, y int) color.Color
方法(返回/提供像素的颜色)中,您将返回如果该图像将是可变的,并在不更改图像的情况下返回原始图像的像素。
image.Image
利用 embedding 最容易实现接口,因此您只需要实现所需的更改即可。这是可以做到的:
type MyImg struct {
// Embed image.Image so MyImg will implement image.Image
// because fields and methods of Image will be promoted:
image.Image
}
func (m *MyImg) At(x, y int) color.Color {
// "Changed" part: custom colors for specific coordinates:
switch {
case x == 0 && y == 0:
return color.RGBA{85, 165, 34, 255}
case x == 0 && y == 1:
return color.RGBA{255, 0, 0, 255}
}
// "Unchanged" part: the colors of the original image:
return m.Image.At(x, y)
}
使用它:非常简单。MyImg
照原样加载图像,但是在保存时,请提供我们类型的值,该值将在编码器要求时提供更改后的图像内容(颜色):
jpeg.Encode(outFile, &MyImg{img}, nil)
如果必须更改许多像素,则将所有像素都包含在该At()
方法中是不切实际的。为此,我们可以扩展我们MyImg
的Set()
实现,以存储要更改的像素。示例实现:
type MyImg struct {
image.Image
custom map[image.Point]color.Color
}
func NewMyImg(img image.Image) *MyImg {
return &MyImg{img, map[image.Point]color.Color{}}
}
func (m *MyImg) Set(x, y int, c color.Color) {
m.custom[image.Point{x, y}] = c
}
func (m *MyImg) At(x, y int) color.Color {
// Explicitly changed part: custom colors of the changed pixels:
if c := m.custom[image.Point{x, y}]; c != nil {
return c
}
// Unchanged part: colors of the original image:
return m.Image.At(x, y)
}
使用它:
// Load image as usual, then
my := NewMyImg(img)
my.Set(0, 0, color.RGBA{85, 165, 34, 1})
my.Set(0, 1, color.RGBA{255, 0, 0, 255})
// And when saving, save 'my' instead of the original:
jpeg.Encode(outFile, my, nil)
如果必须更改许多像素,那么仅创建一个支持更改其像素的新图像可能会更有利可图,例如image.RGBA
,在其上绘制原始图像,然后继续更改您想要的像素。
要将图像绘制到另一个图像上,可以使用该image/draw
包装。
cimg := image.NewRGBA(img.Bounds())
draw.Draw(cimg, img.Bounds(), img, image.Point{}, draw.Over)
// Now you have cimg which contains the original image and is changeable
// (it has a Set() method)
cimg.Set(0, 0, color.RGBA{85, 165, 34, 255})
cimg.Set(0, 1, color.RGBA{255, 0, 0, 255})
// And when saving, save 'cimg' of course:
jpeg.Encode(outFile, cimg, nil)
上面的代码仅用于演示。在“现实生活”中,图像Image.Bounds()
可能会返回一个矩形,该矩形并非始于该(0;0)
点,在这种情况下,需要进行一些调整才能使其工作。
问题内容: 给定一个css颜色值,例如: 假设背景为白色,如何将其转换为考虑了alpha分量的RGB十六进制值? 问题答案: 由于alpha值都会减弱背景色和颜色值,因此可以实现以下目的: (以交互方式进行尝试:http : //marcodiiga.github.io/rgba-to-rgb- conversion )
问题内容: 我正在使用aparapi编写Buddhabrot分形生成器。我将其中的OpenCL部分工作了,得到了一个表示每个像素的单维数组。我将最终图像的尺寸作为最终整数,并编写了代码以获取该数组中任意点的索引。我想将其另存为图像,并且尝试将BufferedImage与TYPE_USHORT_GRAY一起使用。这是我到目前为止的内容: 问题是,我不知道将RGB设置为什么。我需要做什么? 问题答案:
问题内容: 我有一个十六进制颜色,例如(或),我想将其转换为 尽可能透明的 rgba颜色(当显示为白色时)。合理?我正在寻找一种算法,或者至少是关于一种算法的构想。 例如: 有想法吗? 基于Guffa答案的FYI解决方案: 问题答案: 取最低的颜色分量,并将其转换为alpha值。然后,通过减去最低值并除以alpha值来缩放颜色分量。 例: 因此,显示为。 我已经在Photoshop中验证颜色实际上
问题内容: 你好,我正在将图像从彩色转换为纯黑白,结果是深色图像。我没有原因。以下是我的代码,它受SO上其他代码的启发。任何指导都会有所帮助。 我没有弄错我在做什么。使用任何其他开放源代码库的任何其他想法都可以。 工作::::: 问题答案: 您实际上并没有将彩色图像转换为黑白图像。您正在创建与空白图片相同大小的新空白图片。您实际上需要做一些处理旧图像的操作。
问题内容: 我有一个3,076,568个二进制值(1s和0s)的NumPy数组。我想将其转换为矩阵,然后在Python中转换为灰度图像。 但是,当我尝试将数组重塑为1,538,284 x 1,538,284矩阵时,出现内存错误。 如何减小矩阵的大小,以便将其变成适合屏幕显示的图像而又不丢失唯一性/数据? 此外,如何将其转换为灰度图像? 任何帮助或建议,将不胜感激。谢谢。 问题答案: 您的“二进制值
我有一个关于将我的PNG图像更改为灰度的问题。我想做一个方法,接受byte[]图像作为参数,并作为byte[]返回新修改的灰度图像。 我发现了一些链接,使图像灰度与JPEG图像使用下面的片段。 我的参考资料在下面:我如何使用ImageJ作为单独的Java应用程序的库?https://www.mkyong.com/java/how-to-convert-byte-to-bufferedimage-i