2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。

2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。

答案2023-03-10:

方法一、使用 github.com/moonfdd/ffmpeg-go 库,基于雷霄骅的代码修改。

方法二、使用golang官方库image/jpeg,yuv420p先转换成rgb,再转换成jpeg。代码是用山寨版的chatgpt生成。

go run ./examples/leixiaohua1020/simplest_ffmpeg_picture_encoder/main.go

方法一,参考了雷霄骅的图像编码器,代码用golang编写。代码如下:

// https://github.com/leixiaohua1020/simplest_ffmpeg_picture_encoder/blob/master/simplest_ffmpeg_picture_encoder/simplest_ffmpeg_picture_encoder.cpp
package mainimport ("fmt""os""os/exec""unsafe""github.com/moonfdd/ffmpeg-go/ffcommon""github.com/moonfdd/ffmpeg-go/libavcodec""github.com/moonfdd/ffmpeg-go/libavformat""github.com/moonfdd/ffmpeg-go/libavutil"
)func main0() (ret ffcommon.FInt) {var pFormatCtx *libavformat.AVFormatContextvar fmt0 *libavformat.AVOutputFormatvar video_st *libavformat.AVStreamvar pCodecCtx *libavcodec.AVCodecContextvar pCodec *libavcodec.AVCodecvar picture_buf *ffcommon.FUint8Tvar picture *libavutil.AVFramevar pkt libavcodec.AVPacketvar y_size ffcommon.FIntvar got_picture ffcommon.FInt = 0var size ffcommon.FIntvar in_file *os.File                    //YUV sourcevar in_w, in_h ffcommon.FInt = 640, 360 //YUV's width and heightvar out_file = "./out/pic.jpg"          //Output filein := "./out/pic.yuv"//是否存在yuv文件_, err := os.Stat(in)if err != nil {if os.IsNotExist(err) {fmt.Println("create yuv file")exec.Command("./lib/ffmpeg", "-i", "./resources/big_buck_bunny.mp4", "-pix_fmt", "yuv420p", in, "-y").CombinedOutput()}}in_file, _ = os.Open(in)if in_file == nil {return -1}libavformat.AvRegisterAll()//Method 1pFormatCtx = libavformat.AvformatAllocContext()//Guess formatfmt0 = libavformat.AvGuessFormat("mjpeg", "", "")pFormatCtx.Oformat = fmt0//Output URLif libavformat.AvioOpen(&pFormatCtx.Pb, out_file, libavformat.AVIO_FLAG_READ_WRITE) < 0 {fmt.Printf("Couldn't open output file.")return -1}//Method 2. More simple//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);//fmt = pFormatCtx->oformat;video_st = pFormatCtx.AvformatNewStream(nil)if video_st == nil {return -1}pCodecCtx = video_st.CodecpCodecCtx.CodecId = fmt0.VideoCodecpCodecCtx.CodecType = libavutil.AVMEDIA_TYPE_VIDEOpCodecCtx.PixFmt = libavutil.AV_PIX_FMT_YUVJ420PpCodecCtx.Width = in_wpCodecCtx.Height = in_hpCodecCtx.TimeBase.Num = 1pCodecCtx.TimeBase.Den = 25//Output some informationpFormatCtx.AvDumpFormat(0, out_file, 1)pCodec = libavcodec.AvcodecFindEncoder(pCodecCtx.CodecId)if pCodec == nil {fmt.Printf("Codec not found.")return -1}if pCodecCtx.AvcodecOpen2(pCodec, nil) < 0 {fmt.Printf("Could not open codec.")return -1}picture = libavutil.AvFrameAlloc()picture.Width = pCodecCtx.Widthpicture.Height = pCodecCtx.Heightpicture.Format = pCodecCtx.PixFmtsize = libavcodec.AvpictureGetSize(pCodecCtx.PixFmt, pCodecCtx.Width, pCodecCtx.Height)picture_buf = (*byte)(unsafe.Pointer(libavutil.AvMalloc(uint64(size))))if picture_buf == nil {return -1}((*libavcodec.AVPicture)(unsafe.Pointer(picture))).AvpictureFill(picture_buf, pCodecCtx.PixFmt, pCodecCtx.Width, pCodecCtx.Height)//Write HeaderpFormatCtx.AvformatWriteHeader(nil)y_size = pCodecCtx.Width * pCodecCtx.Heightpkt.AvNewPacket(y_size * 3)//Read YUV_, err = in_file.Read(ffcommon.ByteSliceFromByteP(picture_buf, int(y_size*3/2)))if err != nil {fmt.Printf("Could not read input file.%s", err)return -1}picture.Data[0] = picture_buf                                                                         // Ypicture.Data[1] = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(picture_buf)) + uintptr(y_size)))     // Upicture.Data[2] = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(picture_buf)) + uintptr(y_size*5/4))) // V//Encoderet = pCodecCtx.AvcodecEncodeVideo2(&pkt, picture, &got_picture)if ret < 0 {fmt.Printf("Encode Error.\n")return -1}if got_picture == 1 {pkt.StreamIndex = uint32(video_st.Index)ret = pFormatCtx.AvWriteFrame(&pkt)}pkt.AvFreePacket()//Write TrailerpFormatCtx.AvWriteTrailer()fmt.Printf("Encode Successful.\n")if video_st != nil {video_st.Codec.AvcodecClose()libavutil.AvFree(uintptr(unsafe.Pointer(picture)))libavutil.AvFree(uintptr(unsafe.Pointer(picture_buf)))}pFormatCtx.Pb.AvioClose()pFormatCtx.AvformatFreeContext()in_file.Close()exec.Command("./lib/ffplay.exe", out_file).Output()if err != nil {fmt.Println("play err = ", err)}return 0
}func main() {os.Setenv("Path", os.Getenv("Path")+";./lib")ffcommon.SetAvutilPath("./lib/avutil-56.dll")ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")ffcommon.SetAvfilterPath("./lib/avfilter-56.dll")ffcommon.SetAvformatPath("./lib/avformat-58.dll")ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")ffcommon.SetAvswscalePath("./lib/swscale-5.dll")genDir := "./out"_, err := os.Stat(genDir)if err != nil {if os.IsNotExist(err) {os.Mkdir(genDir, 0777) //  Everyone can read write and execute}}// go func() {// 	time.Sleep(1000)// 	exec.Command("./lib/ffplay.exe", "rtmp://localhost/publishlive/livestream").Output()// 	if err != nil {// 		fmt.Println("play err = ", err)// 	}// }()main0()
}

方法二,用第1个chatgpt生成golang代码:

// https://chat.forchange.cn/
// YUV420P像素数据编码为JPEG图片,请用go语言实现。package mainimport ("bufio""fmt""image""image/color""image/jpeg""os"
)func main() {// 将YUV420P像素数据读入内存yuvFile, err := os.Open("./out/pic.yuv")if err != nil {fmt.Println(err)return}defer yuvFile.Close()width := 640height := 360yuvData := make([]byte, width*height*3/2)yuvReader := bufio.NewReader(yuvFile)_, err = yuvReader.Read(yuvData)if err != nil {fmt.Println(err)return}// 将YUV420P像素数据转换为RGB格式的图像img := image.NewRGBA(image.Rect(0, 0, width, height))for y2 := 0; y2 < height; y2++ {for x := 0; x < width; x++ {// 从YUV420P像素数据中获取Y、U、V值yIndex := y2*width + xuIndex := width*height + (y2/2)*(width/2) + x/2vIndex := width*height*5/4 + (y2/2)*(width/2) + x/2y3 := float64(yuvData[yIndex])u := float64(yuvData[uIndex]) - 128.0v := float64(yuvData[vIndex]) - 128.0// 将YUV值转换为RGB值r := y3 + 1.402*vg := y3 - 0.344*u - 0.714*vb := y3 + 1.772*u// 将RGB值限制在0-255范围内r = limit(r, 0, 255)g = limit(g, 0, 255)b = limit(b, 0, 255)// 将RGB值保存到图像中img.Set(x, y2, color.RGBA{uint8(r), uint8(g), uint8(b), 255})}}// 将图像编码为JPEG图片并保存到文件中jpegFile, err := os.Create("./out/pic2.jpg")if err != nil {fmt.Println(err)return}defer jpegFile.Close()err = jpeg.Encode(jpegFile, img, nil)if err != nil {fmt.Println(err)return}fmt.Println("JPEG image saved to ./out/pic2.jpg")
}// 将value限制在min和max之间
func limit(value, min, max float64) float64 {if value < min {return min}if value > max {return max}return value
}

方法二,用第2个chatgpt生成golang代码:

// https://chatgpt.zcorky.com/ 第一次失败,第二次成功
// YUV420P像素数据编码为JPEG图片,请用go语言实现。不要用第三方库
package mainimport ("bufio""bytes""fmt""image""image/color""image/jpeg""os"
)func main() {// 将YUV420P像素数据读入内存yuvFile, err := os.Open("./out/pic.yuv")if err != nil {fmt.Println(err)return}defer yuvFile.Close()width := 640height := 360yuvData := make([]byte, width*height*3/2)yuvReader := bufio.NewReader(yuvFile)_, err = yuvReader.Read(yuvData)if err != nil {fmt.Println(err)return}// 假设您已经读取了 YUV420P 格式的像素数据,并将其存储在 data 变量中var yuv []byte = yuvData // YUV420P 数据// 创建一个新的 RGBA 图像rgbaImg := image.NewRGBA(image.Rect(0, 0, width, height))// 将 YUV420P 数据转换为 RGBA 数据for i := 0; i < width*height; i++ {yi := int(yuv[i])ui := int(yuv[width*height+(i/4)])vi := int(yuv[width*height+(width*height/4)+(i/4)])r := float64(yi) + 1.4065*(float64(vi)-128)g := float64(yi) - 0.3455*(float64(ui)-128) - 0.7169*(float64(vi)-128)b := float64(yi) + 1.7790*(float64(ui)-128)if r < 0 {r = 0} else if r > 255 {r = 255}if g < 0 {g = 0} else if g > 255 {g = 255}if b < 0 {b = 0} else if b > 255 {b = 255}rgbaImg.SetRGBA(i%width, i/width, color.RGBA{R: uint8(r),G: uint8(g),B: uint8(b),A: 255,})}// 创建 JPEG 图像文件jpgFile, err := os.Create("./out/pic3.jpg")if err != nil {panic(err)}defer jpgFile.Close()// 使用 image/jpeg 包来编码 JPEG 图像buf := new(bytes.Buffer)if err := jpeg.Encode(buf, rgbaImg, &jpeg.Options{Quality: 80}); err != nil {panic(err)}_, err = jpgFile.Write(buf.Bytes())if err != nil {panic(err)}
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

致敬马克龙访华?法国品牌手机接入鸿蒙!?---转自百度新闻

马克龙的中国之行收获满满&#xff0c;欧洲新领袖呼之欲出。双方签署了很多商业协议&#xff0c;两国的企业赚得盆满钵满。这个世界的规则有时候就很简单&#xff1a;赚钱。与此同时&#xff0c;有一家自称法式浪漫风格的手机品牌WIKO&#xff0c;宣布接入鸿蒙。 星空君煞有介事…

微软谷歌AI大乱斗,谁又将成为中国的“ChatGPT”?

导读&#xff1a;2023年&#xff0c;ChatGPT已经进入内卷时代。 如果科技圈也有热搜排行榜&#xff0c;ChatGPT无疑稳坐“爆”款头条。 ChatGPT已成为史上用户增长最快的消费级应用&#xff08;根据投行瑞银集团研究估算&#xff09;&#xff0c;自2022年11月30日推出以来&…

ChatGPT 最强代码解释器突破“封印”:30 秒出片、5 分钟制作游戏、可视化分析...样样精通!...

整理 | 屠敏 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 20 美元&#xff0c;雇佣一位非常擅长数据分析的个人 AI 助理&#xff0c;到底值不值&#xff1f; 现在&#xff0c;OpenAI 正在让用户这 20 美元花得更值。 今年 3 月&#xff0c;OpenAI 首次宣布为 C…

2023-03-11:给定一个N*M的二维矩阵,只由字符‘O‘、‘X‘、‘S‘、‘E‘组成, ‘O‘表示这个地方是可通行的平地, ‘X‘表示这个地方是不可通行的障碍, ‘S‘表示这个地方有一个士兵,全

2023-03-11&#xff1a;给定一个N*M的二维矩阵&#xff0c;只由字符’O’、‘X’、‘S’、E’组成&#xff0c; O’表示这个地方是可通行的平地&#xff0c; X’表示这个地方是不可通行的障碍&#xff0c; S’表示这个地方有一个士兵&#xff0c;全图保证只有一个士兵&#xff…

我的ChatGPT学习笔记004

大家好啊&#xff0c;我是了不起&#xff01; 前一段时间ChatGPT突然火爆&#xff0c;大佬们纷纷下场。我也跟着努力学习&#xff0c;做了一些笔记。 下面将陆续放出笔记&#xff0c;共享给小伙伴们&#xff01;这是放出的第二篇&#xff0c;和小伙伴们与时俱进哈~~ 笔记四&…

这几天chatGPT为我赚了多少钱

大家好&#xff0c;我是北妈。 一、 这些天chaGPT 有多火你们也看到了。都不用我发文教育你们&#xff0c;给你们传播了&#xff0c;各大媒体&#xff0c;朋友圈都是它的消息了吧。 至于利用它为北妈我赚了多少钱&#xff0c;其实不少了&#xff0c;通过各种渠道和方法。以后可…

[转] ChatGPT热引发年薪千万高管辞职潮

一场技术天花板的创业。 文&#xff5c;《中国企业家》记者 闫俊文 编辑&#xff5c;李薇 图片来源&#xff5c;视觉中国 ChatGPT以及背后的GPT大模型&#xff0c;正在引发一场创业地震。 李开复、王慧文、王小川&#xff0c;不仅这些“退休”的互联网老兵加入了&#xff0c;在…

完蛋!ChatGPT 完全取代了我的 Java 编程工作!

因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享 点击关注#互联网架构师公众号&#xff0c;领取架构师全套资料 都在这里 0、2T架构师学习资料干货分 上一篇&#xff1a;ChatGPT研究框架&#xff08;80页PPT&#xff0c;附下载&#xff09;…

ChatGPT思考:探索智能的极限

作者&#xff1a;符尧 yao.fued.ac.uk University of Edinburgh & Allen Institute for AI 海外独角兽和拾象一直抱着开源研究&#xff0c;开放分享的心态&#xff0c;本文是拾象 Fellow 符尧关于 ChatGPT 的新思考。符尧曾写过一篇非常精彩的拆解GPT3起源的文章&#xf…

ChatGPT 给我们 带来的哲学思考

ChatGPT 给我们 带来的哲学思考 ChatGPT 是一种基于 GPT-3 模型的聊天机器人&#xff0c;它可以与人类进行自然、流畅、有趣的对话。ChatGPT 的出现&#xff0c;不仅是人工智能技术的一次重大突破&#xff0c;也是对人类社会和文化的一次挑战。ChatGPT 给我们带来了一些哲学上…

Netflix 总用户达到 2.325 亿;马斯克打脸创建 X.AI 公司;印度首开苹果门店;谷歌老板对 AI 很担心?特斯拉营收增加,但净利润下降…《经济学人 | 第 17 期 | 速读版》

快速阅读版&#xff0c;完整英文解析版见&#xff1a; https://blog.csdn.net/YopenLang/article/details/130375444 中国第一季度经济增长出乎意料 中国第一季度经济同比增长 4.5%&#xff0c;超出了大多数经济学家的预期。 China’s economy grew by 4.5% in the first quart…

大火的 ChatGPT,让中国式教育面临巨大挑战?

大火的 ChatGPT&#xff0c;让中国式教育面临巨大挑战&#xff0c;ChatGPT是目前最先进的人工智能聊天机器人。它有多牛呢&#xff1f; 特斯拉的老板马斯克赞美它&#xff1a;“好得吓人。 苹果的老板库克赞美它&#xff1a;“不可思议。 微软的老板比尔盖茨赞美它&…

chatgpt赋能python:Python如何进行分步运行

Python如何进行分步运行 Python是一种强大的编程语言&#xff0c;可以用于开发各种应用程序和Web应用程序。在Python中&#xff0c;您可以使用一些简单的技术来分步运行程序&#xff0c;这将使您更容易调试程序并更好地理解程序的工作原理。在本文中&#xff0c;我们将介绍如何…

chatgpt赋能python:利用Python编写模拟器:一种循序渐进的方法

利用Python编写模拟器&#xff1a;一种循序渐进的方法 模拟器是一种用于模拟计算机硬件或软件的程序。它模拟了真实设备的功能&#xff0c;可以帮助开发人员进行测试和调试&#xff0c;以及提供一种环境来设计和验证新的算法和协议。Python是一种广泛使用的编程语言&#xff0…

chatgpt赋能python:Python如何打断点——提高调试效率

Python如何打断点——提高调试效率 Python是一种易于学习、易于编写和易于调试的高级编程语言。调试是编程过程中必不可少的步骤&#xff0c;打断点是其中一个最常用的工具。打断点可以让程序在指定行停止执行&#xff0c;以便程序员可以检查代码和变量值&#xff0c;以及测试…

chatgpt赋能python:Python快捷键设置介绍

Python快捷键设置介绍 Python是一种高级编程语言&#xff0c;也是众多程序员和开发者广泛采用的语言之一。虽然Python作为一种易学易用的语言&#xff0c;但学习Python仍然需要一定的时间和耐心。其中Python快捷键设置可以让编程变得更加快速和高效。 Python快捷键设置能够更…

chatgpt赋能python:Python调试技巧:如何使用断点运行程序

Python调试技巧&#xff1a;如何使用断点运行程序 在Python编程中&#xff0c;程序出现错误或需要调试时&#xff0c;我们需要一些工具来帮助我们定位问题和修复代码。其中之一就是使用断点来运行程序。接下来我们将讨论如何在Python中使用断点进行程序调试的相关技巧。 什么…

chatgpt赋能Python-python_chariot

Python Chariot&#xff1a;一款强大的Python IDE Python Chariot是一款强大的Python IDE&#xff0c;它的特点是简单易用&#xff0c;功能齐全。该IDE适用于各种Python编程任务&#xff0c;无论是编写小型脚本还是大型项目。在本文中&#xff0c;我们将深入介绍Python Chario…

ChatGPT、Java 8 文档、MySQL都说 JDBC 没必要 `Class.forName()`,结果报错了……

文章目录 回顾 Tomcat 部署 WAR 应用报错找不到数据库驱动的问题ChatGPT、Javadoc 和 MySQL 驱动都说没必要 Class.forName()实验创建一个最小复现问题的 Demo不调用 Class.forName("com.mysql.cj.jdbc.Driver")调用 Class.forName("com.mysql.cj.jdbc.Driver&q…

chatgpt赋能Python-pythonctrl快捷键

PythonCtrl快捷键使用指南 作为一名有10年Python编程经验的工程师&#xff0c;我深知PythonCtrl快捷键的重要性。PythonCtrl作为一个Python的开源编辑器&#xff0c;在每一个版本中都加入了更多的功能和快捷键&#xff0c;使得Python编程更加高效和易用。在本篇文章中&#xf…