PNG元数据读写异常排查:无数据写入/读取问题求助
问题排查与修复方案
你的代码核心问题出在元数据写入的顺序颠倒,还有一些小的语法和资源处理细节问题。咱们一步步拆解解决:
核心错误:TrySave()的调用时机完全搞反了
CreateInPlaceBitmapMetadataWriter的逻辑是:先修改元数据内容,再调用TrySave()把修改同步到文件流里。你原来的代码先调用了TrySave(),这时候写入的还是原始的空元数据,后续的SetQuery操作根本没机会生效,自然看不到任何变化。
其他需要修正的细节
WriteMeta函数里的参数from : b是语法错误,我假设你是想传入第二个整数参数,改成了b : int;- 读取元数据不需要
ReadWrite权限,用FileAccess.Read更合理,也能避免不必要的文件锁定; - 设置元数据时直接传字符串就行,不用转成
char[],BitmapMetadata的SetQuery支持直接接收字符串值; - F#里用
use声明的流会自动释放资源,不用手动调用stm.Close(),多写反而冗余。
修正后的完整代码
open System.IO open System.Windows.Media.Imaging let MetaKey = "/tEXt/Description" // 修正后的元数据写入函数 let WriteMeta (path : string, a : int, b : int) = let data = sprintf "%d %d" a b use stm = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite) let dec = new PngBitmapDecoder(stm, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default) let frm = dec.Frames.[0] let wr = frm.CreateInPlaceBitmapMetadataWriter () // 先设置元数据,再执行保存操作 wr.SetQuery(MetaKey, data) wr.TrySave() // 直接返回保存结果即可 // 修正后的元数据读取函数 let ReadMeta (path : string) = use stm = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read) let dec = new PngBitmapDecoder(stm, BitmapCreateOptions.None, BitmapCacheOption.Default) match dec.Frames.[0].Metadata with | :? BitmapMetadata as met -> match met.GetQuery(MetaKey) with | null -> None | obj -> Some(obj.ToString()) | _ -> None // 处理元数据不存在的边界情况
验证说明
- 运行写入函数后,用TweakPNG查看就能看到
tEXt块下的Description字段已经被正确设置; - 读取用TweakPNG预先添加的
tEXt/Description元数据时,也能正常返回对应的值。
补充一句:PNG的元数据块(比如tEXt、iTXt)不需要像JPEG那样做填充处理,WPF的BitmapMetadata已经帮你处理了这些底层细节,只要调用顺序正确就能正常工作。
内容的提问来源于stack exchange,提问作者RandomB
相关产品推荐
相关产品推荐

