go image.DecodeConfig 和image.Decode 不能同时使用吗

问题场景:在同时使用go image.DecodeConfig 和image.Decode获取图片信息时,报错提示:

无法读取图像配置 image: unknown format

package main

import (
	"fmt"
	"github.com/golang/freetype"
	"image"
	"image/draw"
	"image/jpeg"
	"os"
	"time"
)

func main() {
	// 打开原始图片
	file, err := os.Open("004.jpeg")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 解码图片
	img, _, err := image.Decode(file)
	if err != nil {
		panic(err)
	}

	// 创建一个画布
	bounds := img.Bounds()
	canvas := image.NewRGBA(bounds)


	// 打开图像文件
	fileInfo, err := os.Stat("004.jpeg")
	if err != nil {
		 fmt.Sprintf("无法获取文件信息:%v", err)
	}
	fmt.Println("文件名:",fileInfo.Name())

	// 读取图像信息
	//image.Config{ Width: image.DecodeConfig()}
	config, _, err := image.DecodeConfig(file)
	if err != nil {
		fmt.Println("无法读取图像配置", err)
	}
	width := config.Width
	height := config.Height
	fmt.Println("图片宽度为:", width)
	fmt.Println("图片高度为:", height)
	//s,err:=file.Stat()
	//fmt.Println(file.Name(),s.Size(),s.Sys(),s.Mode(),s.ModTime())

	// 绘制原始图片到画布上
	draw.Draw(canvas, bounds, img, image.Point{}, draw.Src)

	// 添加文字
	fontBytes, err := os.ReadFile("../ttf/kaiti.TTF") //解析中文
	//fontBytes, err := os.ReadFile("../ttf/luxisr.ttf") //不解析中文
	if err != nil {
		panic(err)
	}
	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		panic(err)
	}

	context := freetype.NewContext()
	context.SetDPI(72)
	context.SetFont(font)
	context.SetFontSize(25)
	context.SetClip(bounds)
	context.SetDst(canvas)
	context.SetSrc(image.Opaque)

	pt := freetype.Pt(0, 5+int(context.PointToFixed(24)>>6))
	context.DrawString("来源公众号:【码农编程进阶笔记】", pt)

	// 保存处理后的图片
	filename := fmt.Sprintf("output_%d.jpg", time.Now().Unix())
	output, err := os.Create(filename)
	if err != nil {
		panic(err)
	}
	defer output.Close()

	// 编码保存到文件
	jpeg.Encode(output, canvas, nil)
}

原因:

试图从同一个io.reader(文件)读取两次。

解决:
	//在image.DecodeConfig 和image.Decode两者之间,添加该行问题解决
	file.Seek(0, io.SeekStart)

 完整代码:

package main

import (
	"fmt"
	"github.com/golang/freetype"
	"image"
	"image/draw"
	"image/jpeg"
	"io"
	"os"
	"time"
)

func main() {
	// 打开原始图片
	file, err := os.Open("004.jpeg")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 解码图片
	img, _, err := image.Decode(file)
	if err != nil {
		panic(err)
	}

	// 创建一个画布
	bounds := img.Bounds()
	canvas := image.NewRGBA(bounds)


	// 打开图像文件
	fileInfo, err := os.Stat("004.jpeg")
	if err != nil {
		 fmt.Sprintf("无法获取文件信息:%v", err)
	}
	fmt.Println("文件名:",fileInfo.Name())

	//添加该行问题解决
	file.Seek(0, io.SeekStart)

	// 读取图像信息
	//image.Config{ Width: image.DecodeConfig()}
	config, _, err := image.DecodeConfig(file)
	if err != nil {
		fmt.Println("无法读取图像配置", err)
	}
	width := config.Width
	height := config.Height
	fmt.Println("图片宽度为:", width)
	fmt.Println("图片高度为:", height)
	//s,err:=file.Stat()
	//fmt.Println(file.Name(),s.Size(),s.Sys(),s.Mode(),s.ModTime())

	// 绘制原始图片到画布上
	draw.Draw(canvas, bounds, img, image.Point{}, draw.Src)

	// 添加文字
	fontBytes, err := os.ReadFile("../ttf/kaiti.TTF") //解析中文
	//fontBytes, err := os.ReadFile("../ttf/luxisr.ttf") //不解析中文
	if err != nil {
		panic(err)
	}
	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		panic(err)
	}

	context := freetype.NewContext()
	context.SetDPI(72)
	context.SetFont(font)
	context.SetFontSize(25)
	context.SetClip(bounds)
	context.SetDst(canvas)
	context.SetSrc(image.Opaque)

	pt := freetype.Pt(0, 5+int(context.PointToFixed(24)>>6))
	context.DrawString("来源公众号:【码农编程进阶笔记】", pt)

	// 保存处理后的图片
	filename := fmt.Sprintf("output_%d.jpg", time.Now().Unix())
	output, err := os.Create(filename)
	if err != nil {
		panic(err)
	}
	defer output.Close()

	// 编码保存到文件
	jpeg.Encode(output, canvas, nil)
}

方法一:(代码简洁,亲测可用

解释:大概意思,

将下一个读取或写入文件的偏移量设置为偏移量,根据以下内容进行解释:0表示相对于文件原点,1表示相对于当前偏移量,2表示相对于终点。它返回新的偏移量和一个错误(如果有的话)。

在使用O_APPEND打开的文件上,未指定Seek的行为。

如果f是一个目录,则Seek的行为因操作而异

系统您可以在类Unix操作系统上查找目录的开头,但不能在Windows上查找。

最终,还是再次读取文件。


// Seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
// The behavior of Seek on a file opened with O_APPEND is not specified.
//
// If f is a directory, the behavior of Seek varies by operating
// system; you can seek to the beginning of the directory on Unix-like
// operating systems, but not on Windows.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
	if err := f.checkValid("seek"); err != nil {
		return 0, err
	}
	r, e := f.seek(offset, whence)
	if e == nil && f.dirinfo != nil && r != 0 {
		e = syscall.EISDIR
	}
	if e != nil {
		return 0, f.wrapErr("seek", e)
	}
	return r, nil
}

方法二:(有点麻烦)

您试图从同一个io.reader(文件)读取两次。

image.DecodeConfig(file)

第二次在

image.Decode(file)

第二次尝试从同一个io.reader读取时,将得到EOF
当Read在成功阅读n〉0字节后遇到错误或文件结束条件时,它返回读取的字节数。它可以返回(non-nil)来自同一调用的错误或返回错误这种一般情况的一个示例是,在输入流的末尾返回非零字节数的Reader可以返回err == 0(并且n == 0)。EOF或err == nil。下一次读取应返回0,EOF。
在这里关于它https://golang.org/pkg/io/#Reader
一些快速和简单的你可以做的是打开文件两次

file, err := os.Open("test2.png")
if err != nil {
    fmt.Println("0 ", err)
    return
}
imageInConfig, _, err := image.DecodeConfig(file)
if err != nil {
    fmt.Println("1 ", err)
    return
}
file2, err := os.Open("test2.png")
if err != nil {
    fmt.Println("3 ", err)
    return
}
imageIn, _, err := image.Decode(file2)
if err != nil {
    fmt.Println("4 ", err)
    return
}

或者,您可以尝试多次阅读同一个文件。How to read multiple times from same io.Reader

 参考:Go语言 image.decode在解码.png文件时返回错误 _大数据知识库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/305372.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件压测工具有哪些功能和特点

目前市场上有许多成熟的压测工具,开发人员可以根据自己的项目特点和需求选择合适的工具进行压力测试。本文将介绍软件压测工具的功能和特点: 一、软件压测工具定义 软件压测工具是一种专门设计用于模拟大量用户并发访问系统的工具。通过模拟真实场景中的…

1876_电感的特性小结

Grey 全部学习内容汇总: GitHub - GreyZhang/g_hardware_basic: You should learn some hardware design knowledge in case hardware engineer would ask you to prove your software is right when their hardware design is wrong! 1876_电感的特性小结 主要是…

服务器运维工具推荐——站长、运维必看!

服务器运维是确保服务器系统稳定运行并保持高效性的重要工作。为了提高运维工作的效率,使用一些优秀的服务器运维工具是非常必要的。使用了解多款运维工具后,总结了几款还不错的工具: 1、Zabbix 📒简介:Zabbix是一款开…

分析一个项目(微信小程序篇)二

目录 首页: 发现: 购物车: 我的: 分析一个项目讲究的是如何进行对项目的解析分解,进一步了解项目的整体结构,熟悉项目的结构,能够知道每个组件所处在哪个位置,发挥什么作用。 接…

U盘、硬盘无法打开,修复RAW磁盘或分区,硬盘变成raw格式如何恢复,数据恢复

本文持续更新,针对遇到的数据丢失问题进行详细记录 磁盘变成RAW的可能原因 突然断电或关机文件系统丢失或损坏病毒或恶意软件感染坏扇区磁盘损坏 以下解决方案针对非病毒损坏 通过Windows自带的工具进行恢复(CHKDSK命令) 1.连接硬盘 2.…

自动化测试框架搭建(流程详解)

说起自动化测试,我想大家都会有个疑问,要不要做自动化测试? 自动化测试给我们带来的收益是否会超出在建设时所投入的成本,这个嘛别说是我,即便是高手也很难回答,自动化测试的初衷是美好的,而测试…

用PreMaint引领先进的预测性维护

在设备维护领域,预测性维护成为一项利用先进技术和巧妙工具的数据驱动战略。这一战略通过条件监控和数据分析,以主动维护的方式识别潜在的设备缺陷,避免问题升级。高效使用PreMaint预测性维护工具可不仅节省时间和成本,更显著提升…

信息时代的品牌危机与应对之道:迅腾文化的价值“从心所欲不逾矩”

在瞬息万变的信息时代,企业品牌面临着时代的危机与挑战。在这个时代,自诩能穿透未来迷雾的先知已然无法满足企业的需求,而居安思危、行死而生的“惶者”才是企业所需要的。迅腾文化正是这样的存在,积极倾听企业,融汇未…

Linux第22步_安装CH340驱动和串口终端软件MobaXterm

开发板输出信息通常是采用串口,而计算机通常是USB接口,为了让他们之间能够交换数据,我们通常采用USB转串口的转换器来实现。目前市场上的串口转换器大多是采用CH340芯片来实现的,因此我们需要在计算中安装一个CH340驱动程序&#…

LabVIEW在设备状态监测与故障诊断中的应用

在现代工业自动化领域,LabVIEW的系统设计平台在设备状态监测与故障诊断中扮演着举足轻重的角色。通过提供一个可视化和数据流编程语言,LabVIEW大大提升了设备安全监测的效率,减少了系统维护成本,同时增强了设备的可靠性和可维护性…

时序预测 | Matlab基于灰色隐马尔可夫模型(HMMP-GM11)的时间序列预测

时序预测 | Matlab基于灰色隐马尔可夫模型(HMMP-GM11)的时间序列预测 目录 时序预测 | Matlab基于灰色隐马尔可夫模型(HMMP-GM11)的时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 灰色HMMP-GM11改进模型,通过引入隐马尔可夫模型(HMM)来对原始数据进行状态分…

QT第二天

使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为&…

STM32---WWDG(窗口看门狗)超详细

写在前面:上节我们学习了独立看门狗(IWDG)相关知识,本节我们来学习另外一个看门狗——WWDG窗口看门狗,内容并不难,但是目前这些看门狗的具体内容,还没有得到一个很好的应用,还是先学…

基于apache的http文件服务配置

背景: 公司的产品使用的第三方模组可以OTA,厂家提供的是window开启软件,这样就可以在本机做http下载服务器,然后使用端口映射的方式,公开到外网,这样就可以进行4G网络访问内网服务器了。但这个有个弊端&am…

【前沿技术杂谈:ChatGPT】ChatGPT——热潮背后的反思

【前沿技术杂谈:ChatGPT】ChatGPT——热潮背后的反思 缘起:无中生有,涅槃重生人工智能技术人工智能的发展史无中生有内容自动生成技术的发展代表企业OpenAI-GPT系列技术的发展历程ChatGPT新特点 热潮:万众瞩目,群雄逐鹿…

YOLOv5改进 | 主干篇 | EfficientNetV2均衡缩放网络改进特征提取层

一、本文介绍 这次给大家带来的改进机制是EfficientNetV2,其在其V1版本通过均衡地缩放网络的深度、宽度和分辨率,以提高卷积神经网络的性能的基础上,又提出了一种改进的渐进式学习方法,通过在训练过程中逐步增加图像尺寸并适应性调整正则化来加快训练速度,同时保持准确性…

Apollo基础 - Frenet坐标系

Frenet与笛卡尔坐标系的转换详细推导见&#xff1a;b站老王 自动驾驶决策规划学习记录&#xff08;四&#xff09; Apollo相关代码&#xff1a; modules/common/math/cartesian_frenet_conversion.h #pragma once #include <array> #include "modules/common/mat…

2024年,前端必会的console骚操作

调试。程序员们努力地避免的东西,只为在代码中制造更多的错误。 编写无错误的代码是即使是最好的程序员也会觉得难以实现的。这就是为什么你应该总是调试代码。 而调试JavaScript代码的最好方法之一就是了不起的console.log()。除此之外,还有更好的方法。 这也正是本文的重点…

网络多线程开发小项目--QQ登陆聊天功能(用户登陆功能实现)

9.1.1用户登陆功能实现 1、需求分析 2、代码实现 2.1、Client和Server端共有类 1&#xff09;cn.com.agree.qqcommon.Message package cn.com.agree.qqcommon;import lombok.Data; import lombok.extern.slf4j.Slf4j;import java.io.Serializable; Slf4j Data public class M…

python 基础笔记

基本数据类型 函数 lamda 匿名函数 成员方法 类 类与对象 构造方法 魔术方法 私有成员 私有方法 继承 注解 变量注解 函数注解 Union类型 多态 参考链接&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了_哔哩哔哩_bilib…