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

news2024/11/23 12:22:57
问题场景:在同时使用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文件时返回错误 _大数据知识库

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GPT在地学、GIS、气象、农业、生态、环境等领域应用教程

详情点击链接:GPT在地学、GIS、气象、农业、生态、环境等领域应用教程 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的算法构架与底层逻辑 3)大模型的强大功能与应用场景 4)国内外经典大模型(ChatGPT、LLaMA、Gemini、DALLE、…

【echarts】雷达图参数详细介绍

1. 详细示例 var option {tooltip: {trigger: item},radar: {startAngle: 90,//第一个指示器轴的角度,默认90indicator: [// 指示器{ name: Category A, max: 220 },// name:指示器名称{ name: Category B, max: 200 },// max:指示器的最大值,可选&…

【JAVA】throw 和 throws 的区别?

🍎个人博客:个人主页 🏆个人专栏: JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 throw: throws: 区别: 作用: 使用位置: 个数: 应…

第1章 初识JavaScript

学习目标 了解JavaScript基本概念,能够说出JavaScript的作用、由来、组成和特点 熟悉常见浏览器的特点,能够说出浏览器的组成以及作用 掌握下载和安装Visual Studio Code编辑器,能够独立完成编辑器的下载和安装 掌握JavaScript代码引入方式…

【forwardRef与useImperativeHandle】

1、 2、 3、 4、代码 1、index.tsx代码 import React, {useRef, useEffect} from react import MyInput from "./InputItem";export default function Index() {const ref useRef<any>(null);useEffect(() > {ref.current?.focus();}, [])return (<&…

安达发|APS计划与排程软件之超级BOM功能

在制造业中&#xff0c;物料清单&#xff08;BOM&#xff09;是一个重要的概念&#xff0c;它描述了产品的组成结构和各个部件之间的关系。随着制造业的发展&#xff0c;对于生产计划和排程的要求也越来越高&#xff0c;因此APS&#xff08;高级计划与排程&#xff09;软件应运…

2023年,To B资本航船走向哪了?

国内To B领域在去掉泡沫、结束资本狂欢之后&#xff0c;投资决策愈加理性。但与此同时&#xff0c;下滑的步伐正在放慢&#xff0c;交易数量和金额的降低逐渐放缓&#xff0c;市场逐渐走向稳定。 作者|斗斗 编辑|皮爷 出品|产业家 2023年&#xff0c;在一众业内人士的眼中&…

openai API key 提示你的卡被拒绝怎么办?

openai API key 对于IP的要求非常的严格&#xff0c;以前你开腾讯云、阿里云的服务器都可以绑定、现在就不行了&#xff0c;一定要纯净的IP才可以绑定 一、排除法 1、首先确保自己的账号是没有被封的&#xff0c;可以正常使用的 2、确保银行卡是可以支持openai的银行卡 3、…

IDEA的lombok失效导致工程代码编译build失败的问题处理

今天也是奇了怪了&#xff0c;打包工程&#xff0c;编译始终失败&#xff0c;明明代码符号存在的 解决办法就是&#xff1a;-Djps.track.ap.dependenciesfalse

嵌入式(八)电源低功耗管理 | 五种运行模式 模式转换 睡眠定时器唤醒

文章目录 1 低功耗基本介绍1.1 五种运行模式 2 低功耗控制相关寄存器3 睡眠唤醒实现方式3.1 系统睡眠定时器唤醒 1 低功耗基本介绍 对于嵌入式系统而言&#xff0c;一个非常重要的内容就是低功耗&#xff0c;尽可能减少电量损耗&#xff0c;然后获得更多的续航时间 当然功耗越…

UG装配-布置

UG装配中&#xff0c;当一个产品在不同情况下具有不同的形态的时候&#xff0c;为了快速进行展示&#xff0c;我们可以使用布置命令. 我们可以直接在工具栏布置中&#xff0c;或者在装配导航器中右键单击装配体&#xff0c;选择布置-编辑&#xff0c;添加不同不同的布置页面 使…

模拟算法(模拟算法 == 依葫芦画瓢)万字

模拟算法 基本思想引入算法题替换所有的问号提莫攻击Z字形变换外观数列数青蛙 基本思想 模拟算法 依葫芦画瓢解题思维要么通俗易懂&#xff0c;要么就是找规律&#xff0c;主要难度在于将思路转换为代码。 特点&#xff1a;相对于其他算法思维&#xff0c;思路比较简单&#x…

Docker简介、基本概念和安装

Docker简介、基本概念和安装 1.docker简介 1.1 什么是docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes (opens new window)在法国期间发起的一个公司内部项目&#xff0c;它是基于 dotCloud 公司多年云服务技术的一次革新&#xff0c;并于 2013 年 3 月以 Apache 2…

Power BI - 5分钟学习修改数据类型

每天5分钟&#xff0c;今天介绍Power BI修改数据类型 Power BI加载数据时&#xff0c;会尝试将源列的数据类型转换为更高效的存储、计算和数据可视化的数据类型。 例如&#xff0c;如果从Excel导入的值的列没有小数值&#xff0c;Power BI Desktop会将整个数据列转换为整数数据…

HCIA-Datacom题库(自己整理分类的)_17_简单的命令判断【11道题】

1.华为AR路由器的命令行界面下&#xff0c;save命令的作用是保存当前的系统时间。 解析&#xff1a;Save保存配置 2.VRP界面下&#xff0c;使用命令delete vrpcfg.zp删除文件&#xff0c;必须在回收站中清空&#xff0c;才能彻底删除文件。√ 解析&#xff1a;delete删除到回…

“高端”的位运算

王有志&#xff0c;一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群&#xff1a;共同富裕的Java人 原计划迭代作为预备知识的收尾&#xff0c;不过在解2的幂和4的幂时&#xff0c;想到关于数字2的问题可以通过位运算去解决&#xff0c;因此补充了关于位运算的内容。 …

Spring循环引用和三级缓存

前言 Spring 解决 Bean 之间的循环引用关系用到了三级缓存&#xff0c;那么问题来了。三级缓存是怎么用的&#xff1f;每一层的作用是什么&#xff1f;非得用三级吗&#xff1f;两级缓存行不行&#xff1f; 理解循环引用 所谓的“循环引用”是指 Bean 之间的依赖关系形成了一…

什么事“网络水军”?他们的违法活动主要有四种形式

我国治理网络水军&#xff0c;包括造谣引流、舆情敲诈、刷量控评、有偿删帖等各类“网络水军”等违法犯罪活动已经许久。 日前&#xff0c;官方召开新闻发布会&#xff0c;公布了相关的一些案件进程&#xff0c;今年已累计侦办相关案件339起&#xff0c;超过历年的全年侦办案件…

开启Android学习之旅-6-实战答题App

不经过实战&#xff0c;看再多理论&#xff0c;都是只放在笔记里&#xff0c;活学活用才是硬道理。同时开发应用需要循序渐进&#xff0c;一口气规划300个功能&#xff0c;400张表&#xff0c;会严重打击自己的自信。这里根据所学的&#xff0c;开发一个答题App。 题库需求分析…

Linux 系统之部署 ZFile 在线网盘服务

一、ZFile 介绍 1&#xff09;ZFile 简介 官网&#xff1a;https://www.zfile.vip/ GitHub&#xff1a;https://github.com/zfile-dev/zfile ZFile 是一款基于 Java 的在线网盘程序&#xff0c;支持对接 S3、OneDrive、SharePoint、又拍云、本地存储、FTP 等存储源&#xff0…