Golang中Jpeg.decode和Jpeg.encode生成不可用数据的问题
Golang中Jpeg.decode和Jpeg.encode生成不可用数据的问题
r := strings.Split(p.UserToEdit.PhotoString64, ",")
if len(r) == 2 {
imageData = r[1]
}
buf := bytes.NewBufferString(imageData)
reader := base64.NewDecoder(base64.StdEncoding, buf)
decodedImage, err := jpeg.Decode(reader)
buff1 := new(bytes.Buffer)
err = jpeg.Encode(buff1, decodedImage, nil)
if buff1 == buf{
fmt.Println("equal")
} else{
fmt.Println("different")
}
我正在学习如何编码/解码图像以用于Web应用程序。在上面的代码中,p.UserToEdit.PhotoString64是一个Base64字符串,它在浏览器中可以通过以下方式正常工作:
displayImage.style.backgroundImage =url({{.UserToEdit.PhotoString64}});
我尝试使用resize.Resize来调整图像大小以生成缩略图,但得到了一个无法使用的字符串。不过,我编写了上面的代码,只是为了先让解码/编码过程正常工作。当我运行这段代码时,两个缓冲区的内容差异很大。如果我能解决这个问题,或许就能成功调整图像大小了。
更多关于Golang中Jpeg.decode和Jpeg.encode生成不可用数据的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你确定你正确进行了Base64编码吗?
更多关于Golang中Jpeg.decode和Jpeg.encode生成不可用数据的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你的字符串表明图像是PNG格式,而不是JPEG格式。
感谢,我之前没有意识到JPEG编码之后还需要进行Base64编码。现在可以正常工作了。
rschluet:
buf1.String()
这些是随机字节,你必须对它们进行 base64 编码。
decodedImage, err := jpeg.Decode(reader)
JPEG 是有损压缩格式,因此重新编码的图像不太可能与原始图像完全相同。默认的编码质量是 75。也许将质量设置为 100 可以得到匹配的结果。
另外,你正在比较的是缓冲区的指针,它们也不会相等。可以尝试比较经过 base-64 编码后的字符串。
抱歉,不小心引入了一个PNG文件。我重新用JPEG格式运行了一下,编码后的图像以以下内容开头:
data:image/jpeg;base64,����\u0000�\u0000\u
我正在编写处理JPEG、PNG和GIF格式的代码,但到目前为止还没有任何一种格式能正常工作。
感谢您的回复。我查看了缓冲区,它们确实不同。解码后的图像在浏览器中无法显示。结果只是一个空图像,并且网络检查器中出现了错误:无效字符。此外,查看网络检查器中的base64字符串,原始图像数据显示所有可打印字符,以以下内容开头:data:image/png;base64,/9j/4AAQSkZJRgABAQEAS。而编码/解码后的字符串大部分是不可打印的字符,以以下内容开头:data:image/png;base64,����\u0000�\u0000\u0008。
好的,我从一个在浏览器中有效的编码字符串开始。我正在整理一个更长的代码片段来展示我所做的所有事情。我很快就会准备好…
以下是用户选择要上传的文件后运行的JavaScript代码,并且它能正确显示。
function processFile(imageInput) {
const reader = new FileReader()
reader.addEventListener("load", () => {
uploaded_image = reader.result;
let displayImage = document.querySelector("#display_image");
displayImage.style.backgroundImage = `url(${uploaded_image})`;
displayImage.value = uploaded_image;
console.log(displayImage);
});
reader.readAsDataURL(imageInput.files[0]);
}
然后我将其保存到数据库中。之后,我检索该字符串并将其发送到浏览器,浏览器能正确显示它。但当我解码它、调整其大小、然后重新编码时,似乎遇到了问题。这个过程产生了一个无法在浏览器中查看的字符串。
以下是我的函数代码:
func processImage(p *generalLedgerPage) {
if len(p.UserToEdit.PhotoString64) == 0 {
return
}
log.Println("processImage: ", p.UserToEdit.PhotoString64)
// 移除头部信息,例如:data:image/jpeg;base64, ...
var imageData string
r := strings.Split(p.UserToEdit.PhotoString64, ",")
if len(r) == 2 {
imageData = r[1]
}
fileType := ""
buf := bytes.NewBufferString(imageData)
reader := base64.NewDecoder(base64.StdEncoding, buf)
decodedImage, err := jpeg.Decode(reader)
if err != nil {
log.Println("jpeg.Decode failed error: ", err)
decodedImage, err = png.Decode(reader)
if err != nil {
log.Println("png.Decode failed error: ", err)
decodedImage, err = gif.Decode(reader)
if err != nil {
log.Println("gif.Decode failed error: ", err)
} else {
fileType = "gif"
}
} else {
fileType = "png"
}
} else {
fileType = "jpg"
}
if err == nil {
log.Println("decodedImage.Bounds(): ", decodedImage.Bounds())
}
//reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(p.UserToEdit.PhotoString64))
// 这将重置位置到起始点
buf = bytes.NewBufferString(imageData)
reader = base64.NewDecoder(base64.StdEncoding, buf)
config, err := jpeg.DecodeConfig(reader)
if err != nil {
log.Println("error jpeg.DecodeConfig: ", err)
config, err = png.DecodeConfig(reader)
if err != nil {
log.Println("error png.DecodeConfig: ", err)
config, err = gif.DecodeConfig(reader)
if err != nil {
log.Println("error gif.DecodeConfig: ", err)
}
}
}
if config.Width > 0 {
log.Println("jpeg.DecodeConfig success config: ", config)
log.Println("Width:", config.Width, "Height:", config.Height)
}
buf1 := new(bytes.Buffer)
var resizedImage image.Image
if err == nil {
resizedImage = resize.Resize(uint(100), 0, decodedImage, resize.Lanczos3)
switch fileType {
case "jpg":
err = jpeg.Encode(buf1, resizedImage, nil)
break
case "png":
err = png.Encode(buf1, resizedImage)
break
case "gif":
err = gif.Encode(buf1, resizedImage, nil)
break
}
if err != nil {
log.Println("Encode error: ", err)
}
}
if err == nil {
p.UserToEdit.ThumbNailString64 = r[0] + "," + buf1.String()
//p.UserToEdit.ThumbNailString64 = buff1.String()
log.Println("p.UserToEdit.ThumbNailString64: ", p.UserToEdit.ThumbNailString64)
}
}
传入的文件以以下内容开头:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD
文件的其余部分都是可打印字符。
生成的文件 p.UserToEdit.ThumbNailString64 以以下内容开头:
data:image/jpeg;base64,ÿØÿÛaaaa
后面跟着许多不可打印字符,这基本上会导致尝试处理它的浏览器窗口崩溃。
在JPEG编解码过程中,即使图像内容看起来相同,编码后的字节数据也可能不同。这是因为JPEG编码器在压缩时可能会使用不同的量化表、霍夫曼表或元数据。你的代码中比较缓冲区内容的方式需要调整。
以下是修正后的代码示例:
package main
import (
"bytes"
"encoding/base64"
"fmt"
"image/jpeg"
"strings"
)
func main() {
// 模拟的Base64图像数据(实际使用时替换为p.UserToEdit.PhotoString64)
photoString64 := "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABADASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k="
r := strings.Split(photoString64, ",")
var imageData string
if len(r) == 2 {
imageData = r[1]
}
// 解码Base64
buf := bytes.NewBufferString(imageData)
reader := base64.NewDecoder(base64.StdEncoding, buf)
// 解码JPEG
decodedImage, err := jpeg.Decode(reader)
if err != nil {
fmt.Printf("解码失败: %v\n", err)
return
}
// 重新编码JPEG
buff1 := new(bytes.Buffer)
err = jpeg.Encode(buff1, decodedImage, nil)
if err != nil {
fmt.Printf("编码失败: %v\n", err)
return
}
// 比较原始Base64数据和新编码的Base64数据
originalBytes, _ := base64.StdEncoding.DecodeString(imageData)
if bytes.Equal(originalBytes, buff1.Bytes()) {
fmt.Println("字节数据完全相同")
} else {
fmt.Printf("字节数据不同 - 原始长度: %d, 新编码长度: %d\n",
len(originalBytes), buff1.Bytes())
// 验证新编码的数据是否有效
_, err := jpeg.Decode(bytes.NewReader(buff1.Bytes()))
if err != nil {
fmt.Printf("新编码的数据无效: %v\n", err)
} else {
fmt.Println("新编码的数据是有效的JPEG图像")
// 生成可用的Base64字符串
newBase64 := base64.StdEncoding.EncodeToString(buff1.Bytes())
fmt.Printf("data:image/jpeg;base64,%s\n", newBase64)
}
}
}
如果你要调整图像大小,这里是一个完整的示例:
package main
import (
"bytes"
"encoding/base64"
"fmt"
"image/jpeg"
"strings"
"github.com/nfnt/resize"
)
func processImage(photoString64 string, width, height uint) (string, error) {
// 分离Base64数据
r := strings.Split(photoString64, ",")
if len(r) != 2 {
return "", fmt.Errorf("无效的Base64字符串格式")
}
imageData := r[1]
// 解码Base64
decodedBytes, err := base64.StdEncoding.DecodeString(imageData)
if err != nil {
return "", fmt.Errorf("Base64解码失败: %v", err)
}
// 解码JPEG图像
img, err := jpeg.Decode(bytes.NewReader(decodedBytes))
if err != nil {
return "", fmt.Errorf("JPEG解码失败: %v", err)
}
// 调整图像大小
resizedImg := resize.Resize(width, height, img, resize.Lanczos3)
// 编码为JPEG
var buf bytes.Buffer
err = jpeg.Encode(&buf, resizedImg, &jpeg.Options{Quality: 85})
if err != nil {
return "", fmt.Errorf("JPEG编码失败: %v", err)
}
// 生成Base64字符串
newBase64 := base64.StdEncoding.EncodeToString(buf.Bytes())
return "data:image/jpeg;base64," + newBase64, nil
}
func main() {
photoString64 := "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABADASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k="
resizedImage, err := processImage(photoString64, 100, 100)
if err != nil {
fmt.Printf("处理失败: %v\n", err)
return
}
fmt.Printf("调整大小后的图像: %s...\n", resizedImage[:100])
}
运行go mod init example && go get github.com/nfnt/resize来安装resize包。

